From 08a1ecd5c433df18dd94e836a7927207a5ab9f18 Mon Sep 17 00:00:00 2001
From: Stephen Finucane
Date: Mon, 4 Dec 2023 12:21:23 +0000
Subject: [PATCH 001/180] Fall back to cluster identityRef in absence of
machine
The 'identityRef' attribute is marked as optional but without it we have
no ability to talk to the cloud. In a future API version, we may wish to
make this a required attribute but for now, provide the ability to
retrieve credentials from the cluster in the absence of the machine.
Signed-off-by: Stephen Finucane
---
api/v1alpha7/openstackmachine_types.go | 3 ++-
...infrastructure.cluster.x-k8s.io_openstackclusters.yaml | 3 ++-
...ucture.cluster.x-k8s.io_openstackclustertemplates.yaml | 4 +++-
...infrastructure.cluster.x-k8s.io_openstackmachines.yaml | 3 ++-
...ucture.cluster.x-k8s.io_openstackmachinetemplates.yaml | 3 ++-
controllers/openstackmachine_controller.go | 2 +-
pkg/scope/mock.go | 2 +-
pkg/scope/provider.go | 8 +++++++-
pkg/scope/scope.go | 2 +-
9 files changed, 21 insertions(+), 9 deletions(-)
diff --git a/api/v1alpha7/openstackmachine_types.go b/api/v1alpha7/openstackmachine_types.go
index df5c4a55db..95d8620d3b 100644
--- a/api/v1alpha7/openstackmachine_types.go
+++ b/api/v1alpha7/openstackmachine_types.go
@@ -89,7 +89,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"`
}
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 ac700b690a..46ea6d623d 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -3849,7 +3849,8 @@ spec:
type: string
identityRef:
description: IdentityRef is a reference to a identity to be
- used when reconciling this cluster
+ 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
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 281b48f8df..7afb870b67 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -1695,7 +1695,9 @@ spec:
type: string
identityRef:
description: IdentityRef is a reference to a identity
- to be used when reconciling this cluster
+ 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
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 be2ad0feee..23a287fe20 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
@@ -1228,7 +1228,8 @@ spec:
type: string
identityRef:
description: IdentityRef is a reference to a identity to be used when
- reconciling this cluster
+ 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
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 f0dca99933..5f08d295c4 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
@@ -1032,7 +1032,8 @@ spec:
type: string
identityRef:
description: IdentityRef is a reference to a identity to be
- used when reconciling this cluster
+ 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
diff --git a/controllers/openstackmachine_controller.go b/controllers/openstackmachine_controller.go
index 3609ac2953..232d9bd6ae 100644
--- a/controllers/openstackmachine_controller.go
+++ b/controllers/openstackmachine_controller.go
@@ -140,7 +140,7 @@ func (r *OpenStackMachineReconciler) Reconcile(ctx context.Context, req ctrl.Req
}
}()
- scope, err := r.ScopeFactory.NewClientScopeFromMachine(ctx, r.Client, openStackMachine, r.CaCertificates, log)
+ scope, err := r.ScopeFactory.NewClientScopeFromMachine(ctx, r.Client, openStackMachine, infraCluster, r.CaCertificates, log)
if err != nil {
return reconcile.Result{}, err
}
diff --git a/pkg/scope/mock.go b/pkg/scope/mock.go
index dac09d5ff7..f8b12d8982 100644
--- a/pkg/scope/mock.go
+++ b/pkg/scope/mock.go
@@ -66,7 +66,7 @@ func (f *MockScopeFactory) SetClientScopeCreateError(err error) {
f.clientScopeCreateError = err
}
-func (f *MockScopeFactory) NewClientScopeFromMachine(_ context.Context, _ client.Client, _ *infrav1.OpenStackMachine, _ []byte, _ logr.Logger) (Scope, error) {
+func (f *MockScopeFactory) NewClientScopeFromMachine(_ context.Context, _ client.Client, _ *infrav1.OpenStackMachine, _ *infrav1.OpenStackCluster, _ []byte, _ logr.Logger) (Scope, error) {
if f.clientScopeCreateError != nil {
return nil, f.clientScopeCreateError
}
diff --git a/pkg/scope/provider.go b/pkg/scope/provider.go
index 4b0b5e61c2..dd19efb274 100644
--- a/pkg/scope/provider.go
+++ b/pkg/scope/provider.go
@@ -52,7 +52,7 @@ type providerScopeFactory struct {
clientCache *cache.LRUExpireCache
}
-func (f *providerScopeFactory) NewClientScopeFromMachine(ctx context.Context, ctrlClient client.Client, openStackMachine *infrav1.OpenStackMachine, defaultCACert []byte, logger logr.Logger) (Scope, error) {
+func (f *providerScopeFactory) NewClientScopeFromMachine(ctx context.Context, ctrlClient client.Client, openStackMachine *infrav1.OpenStackMachine, openStackCluster *infrav1.OpenStackCluster, defaultCACert []byte, logger logr.Logger) (Scope, error) {
var cloud clientconfig.Cloud
var caCert []byte
@@ -62,6 +62,12 @@ func (f *providerScopeFactory) NewClientScopeFromMachine(ctx context.Context, ct
if err != nil {
return nil, err
}
+ } else if openStackCluster.Spec.IdentityRef != nil {
+ var err error
+ cloud, caCert, err = getCloudFromSecret(ctx, ctrlClient, openStackCluster.Namespace, openStackCluster.Spec.IdentityRef.Name, openStackCluster.Spec.CloudName)
+ if err != nil {
+ return nil, err
+ }
}
if caCert == nil {
diff --git a/pkg/scope/scope.go b/pkg/scope/scope.go
index 5a2afd4e7a..a248814554 100644
--- a/pkg/scope/scope.go
+++ b/pkg/scope/scope.go
@@ -41,7 +41,7 @@ func NewFactory(maxCacheSize int) Factory {
// Factory instantiates a new Scope using credentials from either a cluster or a machine.
type Factory interface {
- NewClientScopeFromMachine(ctx context.Context, ctrlClient client.Client, openStackMachine *infrav1.OpenStackMachine, defaultCACert []byte, logger logr.Logger) (Scope, error)
+ NewClientScopeFromMachine(ctx context.Context, ctrlClient client.Client, openStackMachine *infrav1.OpenStackMachine, openStackCluster *infrav1.OpenStackCluster, defaultCACert []byte, logger logr.Logger) (Scope, error)
NewClientScopeFromCluster(ctx context.Context, ctrlClient client.Client, openStackCluster *infrav1.OpenStackCluster, defaultCACert []byte, logger logr.Logger) (Scope, error)
}
From 9d9a2e134ec08565674bcd67db62b5b656e688e5 Mon Sep 17 00:00:00 2001
From: Emilien Macchi
Date: Tue, 31 Oct 2023 20:40:56 -0400
Subject: [PATCH 002/180] [vendoring] import CAPI v1.6.0
---
go.mod | 103 ++++++++--------
go.sum | 378 ++++++++++++++++++---------------------------------------
2 files changed, 171 insertions(+), 310 deletions(-)
diff --git a/go.mod b/go.mod
index e51b3ebfc3..b5ac940ec6 100644
--- a/go.mod
+++ b/go.mod
@@ -3,33 +3,33 @@ module sigs.k8s.io/cluster-api-provider-openstack
go 1.20
require (
- github.com/davecgh/go-spew v1.1.1
- github.com/go-logr/logr v1.2.4
+ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc
+ github.com/go-logr/logr v1.3.0
github.com/golang/mock v1.6.0
- github.com/google/go-cmp v0.5.9
+ github.com/google/go-cmp v0.6.0
github.com/google/gofuzz v1.2.0
github.com/gophercloud/gophercloud v1.7.0
github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56
github.com/hashicorp/go-version v1.4.0
- github.com/onsi/ginkgo/v2 v2.11.0
- github.com/onsi/gomega v1.27.8
+ github.com/onsi/ginkgo/v2 v2.13.1
+ github.com/onsi/gomega v1.30.0
github.com/prometheus/client_golang v1.17.0
github.com/spf13/pflag v1.0.5
- golang.org/x/crypto v0.14.0
- golang.org/x/text v0.13.0
+ golang.org/x/crypto v0.15.0
+ golang.org/x/text v0.14.0
gopkg.in/ini.v1 v1.67.0
- k8s.io/api v0.27.7
- k8s.io/apiextensions-apiserver v0.27.2
- k8s.io/apimachinery v0.27.7
- k8s.io/client-go v0.27.7
- k8s.io/component-base v0.27.7
- k8s.io/klog/v2 v2.90.1
- k8s.io/kubernetes v1.27.2
- k8s.io/utils v0.0.0-20230313181309-38a27ef9d749
- sigs.k8s.io/cluster-api v1.5.1
- sigs.k8s.io/cluster-api/test v1.5.1
- sigs.k8s.io/controller-runtime v0.15.1
- sigs.k8s.io/yaml v1.3.0
+ k8s.io/api v0.28.4
+ k8s.io/apiextensions-apiserver v0.28.4
+ k8s.io/apimachinery v0.28.4
+ k8s.io/client-go v0.28.4
+ k8s.io/component-base v0.28.4
+ k8s.io/klog/v2 v2.100.1
+ k8s.io/kubernetes v1.28.3
+ k8s.io/utils v0.0.0-20230406110748-d93618cff8a2
+ sigs.k8s.io/cluster-api v1.6.0
+ sigs.k8s.io/cluster-api/test v1.6.0
+ sigs.k8s.io/controller-runtime v0.16.3
+ sigs.k8s.io/yaml v1.4.0
)
require (
@@ -39,25 +39,25 @@ require (
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.2.0 // indirect
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
- github.com/Microsoft/go-winio v0.5.0 // indirect
+ github.com/Microsoft/go-winio v0.6.0 // indirect
+ github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 // indirect
github.com/adrg/xdg v0.4.0 // indirect
github.com/alessio/shellescape v1.4.1 // indirect
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230321174746-8dcc6526cfb1 // indirect
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/beorn7/perks v1.0.1 // indirect
- github.com/blang/semver v3.5.1+incompatible // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
- github.com/coredns/caddy v1.1.1 // indirect
- github.com/coredns/corefile-migration v1.0.21 // indirect
- github.com/docker/distribution v2.8.2+incompatible // indirect
- github.com/docker/docker v24.0.5+incompatible // indirect
+ github.com/cloudflare/circl v1.3.3 // indirect
+ github.com/distribution/reference v0.5.0 // indirect
+ github.com/docker/distribution v2.8.3+incompatible // indirect
+ github.com/docker/docker v24.0.7+incompatible // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/drone/envsubst/v2 v2.0.0-20210730161058-179042472c46 // indirect
- github.com/emicklei/go-restful/v3 v3.10.2 // indirect
+ github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/evanphx/json-patch v5.6.0+incompatible // indirect
- github.com/evanphx/json-patch/v5 v5.6.0 // indirect
+ github.com/evanphx/json-patch/v5 v5.7.0 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/go-logr/zapr v1.2.4 // indirect
github.com/go-openapi/jsonpointer v0.19.6 // indirect
@@ -68,13 +68,13 @@ require (
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
- github.com/google/cel-go v0.14.0 // indirect
- github.com/google/gnostic v0.6.9 // indirect
- github.com/google/go-github/v48 v48.2.0 // indirect
+ github.com/google/cel-go v0.16.1 // indirect
+ github.com/google/gnostic-models v0.6.8 // indirect
+ github.com/google/go-github/v53 v53.2.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect
github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2 // indirect
- github.com/google/uuid v1.3.0 // indirect
+ github.com/google/uuid v1.3.1 // indirect
github.com/hashicorp/go-uuid v1.0.3 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/huandu/xstrings v1.4.0 // indirect
@@ -84,7 +84,7 @@ require (
github.com/json-iterator/go v1.1.12 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
- github.com/mattn/go-isatty v0.0.17 // indirect
+ github.com/mattn/go-isatty v0.0.20 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
@@ -96,40 +96,45 @@ require (
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.2 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
- github.com/pelletier/go-toml/v2 v2.0.8 // indirect
+ github.com/pelletier/go-toml/v2 v2.1.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect
github.com/prometheus/common v0.44.0 // indirect
github.com/prometheus/procfs v0.11.1 // indirect
+ github.com/sagikazarmark/locafero v0.3.0 // indirect
+ github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/shopspring/decimal v1.3.1 // indirect
- github.com/spf13/afero v1.9.5 // indirect
+ github.com/sourcegraph/conc v0.3.0 // indirect
+ github.com/spf13/afero v1.10.0 // indirect
github.com/spf13/cast v1.5.1 // indirect
- github.com/spf13/cobra v1.7.0 // indirect
- github.com/spf13/jwalterweatherman v1.1.0 // indirect
- github.com/spf13/viper v1.16.0 // indirect
+ github.com/spf13/cobra v1.8.0 // indirect
+ github.com/spf13/viper v1.17.0 // indirect
github.com/stoewer/go-strcase v1.3.0 // indirect
- github.com/subosito/gotenv v1.4.2 // indirect
+ github.com/subosito/gotenv v1.6.0 // indirect
github.com/valyala/fastjson v1.6.4 // indirect
- go.uber.org/atomic v1.10.0 // indirect
+ go.uber.org/goleak v1.3.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
- go.uber.org/zap v1.24.0 // indirect
+ go.uber.org/zap v1.25.0 // indirect
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
- golang.org/x/net v0.17.0 // indirect
- golang.org/x/oauth2 v0.13.0 // indirect
- golang.org/x/sys v0.13.0 // indirect
- golang.org/x/term v0.13.0 // indirect
+ golang.org/x/mod v0.13.0 // indirect
+ golang.org/x/net v0.18.0 // indirect
+ golang.org/x/oauth2 v0.14.0 // indirect
+ golang.org/x/sync v0.4.0 // indirect
+ golang.org/x/sys v0.14.0 // indirect
+ golang.org/x/term v0.14.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.14.0 // indirect
- gomodules.xyz/jsonpatch/v2 v2.3.0 // indirect
+ gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
- google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
+ google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb // indirect
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
- k8s.io/apiserver v0.27.7 // indirect
- k8s.io/cluster-bootstrap v0.27.2 // indirect
- k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f // indirect
+ k8s.io/apiserver v0.28.4 // indirect
+ k8s.io/cluster-bootstrap v0.28.4 // indirect
+ k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/kind v0.20.0 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
diff --git a/go.sum b/go.sum
index 0e2ea38c9d..dc4d419024 100644
--- a/go.sum
+++ b/go.sum
@@ -25,7 +25,6 @@ cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4g
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
-cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
@@ -51,108 +50,82 @@ github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7Y
github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA=
github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM=
-github.com/Microsoft/go-winio v0.5.0 h1:Elr9Wn+sGKPlkaBvwu4mTrxtmOp3F3yV9qhaHbXGjwU=
-github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
-github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
+github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=
+github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE=
+github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 h1:wPbRQzjjwFc0ih8puEVAOFGELsn1zoIIYdxvML7mDxA=
+github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g=
github.com/adrg/xdg v0.4.0 h1:RzRqFcjH4nE5C6oTAxhBtoE2IRyjBSa62SCbyPidvls=
github.com/adrg/xdg v0.4.0/go.mod h1:N6ag73EX4wyxeaoeHctc1mas01KZgsj5tYiAIwqJE/E=
-github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
-github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alessio/shellescape v1.4.1 h1:V7yhSDDn8LP4lc4jS8pFkt0zCnzVJlG5JXy9BVKJUX0=
github.com/alessio/shellescape v1.4.1/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30=
-github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230321174746-8dcc6526cfb1 h1:X8MJ0fnN5FPdcGF5Ij2/OW+HgiJrRg3AfHAx1PJtIzM=
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230321174746-8dcc6526cfb1/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM=
-github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
-github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
-github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
-github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
-github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
-github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
+github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
-github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
-github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
-github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
-github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
-github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
+github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
-github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I=
+github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs=
+github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
-github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
-github.com/coredns/caddy v1.1.0/go.mod h1:A6ntJQlAWuQfFlsd9hvigKbo2WS0VUs2l1e2F+BawD4=
github.com/coredns/caddy v1.1.1 h1:2eYKZT7i6yxIfGP3qLJoJ7HAsDJqYB+X68g4NYjSrE0=
-github.com/coredns/caddy v1.1.1/go.mod h1:A6ntJQlAWuQfFlsd9hvigKbo2WS0VUs2l1e2F+BawD4=
github.com/coredns/corefile-migration v1.0.21 h1:W/DCETrHDiFo0Wj03EyMkaQ9fwsmSgqTCQDHpceaSsE=
-github.com/coredns/corefile-migration v1.0.21/go.mod h1:XnhgULOEouimnzgn0t4WPuFDN2/PJQcTxdWKC5eXNGE=
-github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
-github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
-github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
-github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
-github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
-github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
-github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
+github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
-github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
-github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
-github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
-github.com/docker/docker v24.0.5+incompatible h1:WmgcE4fxyI6EEXxBRxsHnZXrO1pQ3smi0k/jho4HLeY=
-github.com/docker/docker v24.0.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
+github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
+github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0=
+github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
+github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
+github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
+github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM=
+github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
-github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/drone/envsubst/v2 v2.0.0-20210730161058-179042472c46 h1:7QPwrLT79GlD5sizHf27aoY2RTvw62mO6x7mxkScNk0=
github.com/drone/envsubst/v2 v2.0.0-20210730161058-179042472c46/go.mod h1:esf2rsHFNlZlxsqsZDojNBcnNs5REqIvRrWRHqX0vEU=
-github.com/emicklei/go-restful/v3 v3.10.2 h1:hIovbnmBTLjHXkqEBUz3HGpXZdM7ZrE9fJIZIqlJLqE=
-github.com/emicklei/go-restful/v3 v3.10.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
+github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
+github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
-github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U=
github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
-github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww=
github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4=
-github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
-github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0=
-github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
+github.com/evanphx/json-patch/v5 v5.7.0 h1:nJqP7uwL84RJInrohHfW0Fx3awjbm8qZeFv0nW9SYGc=
+github.com/evanphx/json-patch/v5 v5.7.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ=
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
-github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
-github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
-github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
-github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
-github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
-github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=
+github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo=
github.com/go-logr/zapr v1.2.4/go.mod h1:FyHWQIzQORZ0QVE1BtVHv3cKtNLuXsbNLtpuhNapBOA=
github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
@@ -161,17 +134,13 @@ github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2Kv
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g=
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
-github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/gobuffalo/flect v1.0.2 h1:eqjPGSo2WmjgY2XlpGwo2NXgL3RucAKo4k4qQMNA5sA=
github.com/gobuffalo/flect v1.0.2/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs=
-github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
-github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
-github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -201,15 +170,14 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
-github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
-github.com/google/cel-go v0.14.0 h1:LFobwuUDslWUHdQ48SXVXvQgPH2X1XVhsgOGNioAEZ4=
-github.com/google/cel-go v0.14.0/go.mod h1:YzWEoI07MC/a/wj9in8GeVatqfypkldgBlwXh9bCwqY=
-github.com/google/gnostic v0.6.9 h1:ZK/5VhkoX835RikCHpSUJV9a+S3e1zLh59YnyWeBW+0=
-github.com/google/gnostic v0.6.9/go.mod h1:Nm8234We1lq6iB9OmlgNv3nH91XLLVZHCDayfA3xq+E=
+github.com/google/cel-go v0.16.1 h1:3hZfSNiAU3KOiNtxuFXVp5WFy4hf/Ly3Sa4/7F8SXNo=
+github.com/google/cel-go v0.16.1/go.mod h1:HXZKzB0LXqer5lHHgfWAnlYwJaQBDKMjxjulNQzhwhY=
+github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
+github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
@@ -220,10 +188,11 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
-github.com/google/go-github/v48 v48.2.0 h1:68puzySE6WqUY9KWmpOsDEQfDZsso98rT6pZcz9HqcE=
-github.com/google/go-github/v48 v48.2.0/go.mod h1:dDlehKBDo850ZPvCTK0sEqTCVWcrGl2LcDiajkYi89Y=
+github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/go-github/v53 v53.2.0 h1:wvz3FyF53v4BK+AsnvCmeNhf8AkTaeh2SoYu/XUvTtI=
+github.com/google/go-github/v53 v53.2.0/go.mod h1:XhFRObz+m/l+UCm9b7KSIC3lT3NWSXGt7mOsAWEloao=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -249,8 +218,8 @@ github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2 h1:SJ+NtwL6QaZ21U+
github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2/go.mod h1:Tv1PlzqC9t8wNnpPdctvtSUOPUUg4SHeE6vR1Ir2hmg=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
-github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
+github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
@@ -259,37 +228,14 @@ github.com/gophercloud/gophercloud v1.7.0 h1:fyJGKh0LBvIZKLvBWvQdIgkaV5yTM3Jh9EY
github.com/gophercloud/gophercloud v1.7.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM=
github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56 h1:sH7xkTfYzxIEgzq1tDHIMKRh1vThOEOGNsettdEeLbE=
github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56/go.mod h1:VSalo4adEk+3sNkmVJLnhHoOyOYYS8sTWLG4mv5BKto=
-github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
-github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
-github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
-github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
-github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
-github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
-github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
-github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
-github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
-github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
-github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
-github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
-github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
-github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
-github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
-github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
-github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
-github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-version v1.4.0 h1:aAQzgqIrRKRa7w75CKpbBxYsmUoPjzVm1W59ca1L0J4=
github.com/hashicorp/go-version v1.4.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
-github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
-github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
-github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
-github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
-github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU=
github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
@@ -302,57 +248,36 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
-github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
-github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
-github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
-github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
-github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
-github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
-github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
-github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
-github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc=
-github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
-github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
-github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
-github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
-github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
-github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
-github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
-github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
-github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
-github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
-github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
-github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
-github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
-github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
@@ -362,99 +287,67 @@ github.com/moby/term v0.0.0-20221205130635-1aeaba878587 h1:HfkjXDfhgVaN5rmueG8cL
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
-github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
-github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
-github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
-github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU=
-github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM=
-github.com/onsi/gomega v1.27.8 h1:gegWiwZjBsf2DgiSbf5hpokZ98JVDMcWkUiigk6/KXc=
-github.com/onsi/gomega v1.27.8/go.mod h1:2J8vzI/s+2shY9XHRApDkdgPo1TKT7P2u6fXeJKFnNQ=
+github.com/onsi/ginkgo/v2 v2.13.1 h1:LNGfMbR2OVGBfXjvRZIZ2YCTQdGKtPLvuI1rMCCj3OU=
+github.com/onsi/ginkgo/v2 v2.13.1/go.mod h1:XStQ8QcGwLyF4HdfcZB8SFOS/MWCgDuXMSBe6zrvLgM=
+github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8=
+github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
-github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
-github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
-github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
-github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
-github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
+github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
-github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
-github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
-github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
+github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q=
github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY=
-github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
-github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 h1:v7DLqVdK4VrYkVD5diGdl4sxJurKJEMnODWRJlxV9oM=
github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU=
-github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
-github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY=
github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY=
-github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
-github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI=
github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY=
-github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
-github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
-github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
-github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
-github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
-github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
-github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
+github.com/sagikazarmark/locafero v0.3.0 h1:zT7VEGWC2DTflmccN/5T1etyKvxSxpHsjb9cJvm4SvQ=
+github.com/sagikazarmark/locafero v0.3.0/go.mod h1:w+v7UsPNFwzF1cHuOajOOzoq4U7v/ig1mpRjqV+Bu1U=
+github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
+github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
-github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
-github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
-github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
-github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
-github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
-github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
-github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
-github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
-github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM=
-github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ=
-github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
+github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
+github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
+github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY=
+github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ=
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA=
github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48=
-github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g=
-github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
-github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
-github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
-github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
-github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
-github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
+github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
+github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
-github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
-github.com/spf13/viper v1.16.0 h1:rGGH0XDZhdUOryiDWjmIvUSWpbNqisK8Wk0Vyefw8hc=
-github.com/spf13/viper v1.16.0/go.mod h1:yg78JgCJcbrQOvV9YLXgkLaZqUidkY9K+Dd1FofRzQg=
-github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
+github.com/spf13/viper v1.17.0 h1:I5txKw7MJasPL/BrfkbA0Jyo/oELqVmux4pR/UxOMfI=
+github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0+yVI=
github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs=
github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
@@ -466,47 +359,34 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
-github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
-github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
-github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
-github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=
-github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
-github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
+github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
+github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
+github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
-github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
-github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
-github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
-github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
-go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
-go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
-go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
-go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
-go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
-go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
-go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
+go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
+go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
-go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
-go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
-golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
-golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c=
+go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@@ -517,8 +397,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
-golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
-golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
+golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA=
+golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -557,12 +437,9 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
+golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@@ -593,12 +470,11 @@ golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
-golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
-golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
-golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
+golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
+golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -608,8 +484,8 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY=
-golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0=
+golang.org/x/oauth2 v0.14.0 h1:P0Vrf/2538nmC0H+pEQ3MNFRRnVR7RlqyVw+bvm26z0=
+golang.org/x/oauth2 v0.14.0/go.mod h1:lAtNWgaWfL4cm7j2OV8TxGi9Qb7ECORx8DktCY74OwM=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -622,12 +498,9 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
+golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -637,7 +510,6 @@ golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -659,7 +531,6 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -668,44 +539,42 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
-golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
+golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
-golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
-golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
+golang.org/x/term v0.14.0 h1:LGK9IlZ8T9jvdy6cTdfKUCltatMFOehAQo9SRC46UQ8=
+golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
-golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
+golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
@@ -715,7 +584,6 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgw
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@@ -759,8 +627,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-gomodules.xyz/jsonpatch/v2 v2.3.0 h1:8NFhfS6gzxNqjLIYnZxg319wZ5Qjnx4m/CcX+Klzazc=
-gomodules.xyz/jsonpatch/v2 v2.3.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=
+gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw=
+gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
@@ -811,7 +679,6 @@ google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfG
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
@@ -825,9 +692,10 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A=
-google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
+google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb h1:lK0oleSc7IQsUxO3U5TjL9DWlsxpEBemh+zpB7IqhWI=
+google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 h1:N3bU/SQDCDyD6R528GJ/PwW9KjYcJA3dgyH+MovAkIM=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13/go.mod h1:KSqppvjFjtoCI+KGd4PELB0qLNxdJHRGqRI09mB6pQA=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
@@ -841,12 +709,9 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
-google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
-google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
-google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -859,34 +724,24 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
-gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
-gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
-gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
-gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
-gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=
@@ -897,42 +752,43 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
-k8s.io/api v0.27.7 h1:7yG4D3t/q4utJe2ptlRw9aPuxcSmroTsYxsofkQNl/A=
-k8s.io/api v0.27.7/go.mod h1:ZNExI/Lhrs9YrLgVWx6jjHZdoWCTXfBXuFjt1X6olro=
-k8s.io/apiextensions-apiserver v0.27.2 h1:iwhyoeS4xj9Y7v8YExhUwbVuBhMr3Q4bd/laClBV6Bo=
-k8s.io/apiextensions-apiserver v0.27.2/go.mod h1:Oz9UdvGguL3ULgRdY9QMUzL2RZImotgxvGjdWRq6ZXQ=
-k8s.io/apimachinery v0.27.7 h1:Gxgtb7Y/Rsu8ymgmUEaiErkxa6RY4oTd8kNUI6SUR58=
-k8s.io/apimachinery v0.27.7/go.mod h1:jBGQgTjkw99ef6q5hv1YurDd3BqKDk9YRxmX0Ozo0i8=
-k8s.io/apiserver v0.27.7 h1:E8sDHwfUug82YC1++qvE73QxihaXDqT4tr8XYBOEtc4=
-k8s.io/apiserver v0.27.7/go.mod h1:OrLG9RwCOerutAlo8QJW5EHzUG9Dad7k6rgcDUNSO/w=
-k8s.io/client-go v0.27.7 h1:+Xgh9OOKv6A3qdD4Dnl/0VOI5EvAv+0s/OseDxVVTwQ=
-k8s.io/client-go v0.27.7/go.mod h1:dZ2kqcalYp5YZ2EV12XIMc77G6PxHWOJp/kclZr4+5Q=
-k8s.io/cluster-bootstrap v0.27.2 h1:OL3onrOwrUD7NQxBUqQwTl1Uu2GQKCkw9BMHpc4PbiA=
-k8s.io/cluster-bootstrap v0.27.2/go.mod h1:b++PF0mjUOiTKdPQFlDw7p4V2VquANZ8SfhAwzxZJFM=
-k8s.io/component-base v0.27.7 h1:kngM58HR9W9Nqpv7e4rpdRyWnKl/ABpUhLAZ+HoliMs=
-k8s.io/component-base v0.27.7/go.mod h1:YGjlCVL1oeKvG3HSciyPHFh+LCjIEqsxz4BDR3cfHRs=
-k8s.io/klog/v2 v2.90.1 h1:m4bYOKall2MmOiRaR1J+We67Do7vm9KiQVlT96lnHUw=
-k8s.io/klog/v2 v2.90.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
-k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f h1:2kWPakN3i/k81b0gvD5C5FJ2kxm1WrQFanWchyKuqGg=
-k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f/go.mod h1:byini6yhqGC14c3ebc/QwanvYwhuMWF6yz2F8uwW8eg=
-k8s.io/kubernetes v1.27.2 h1:g4v9oY6u7vBUDEuq4FvC50Bbw2K7GZuvM00IIESWVf4=
-k8s.io/kubernetes v1.27.2/go.mod h1:U8ZXeKBAPxeb4J4/HOaxjw1A9K6WfSH+fY2SS7CR6IM=
-k8s.io/utils v0.0.0-20230313181309-38a27ef9d749 h1:xMMXJlJbsU8w3V5N2FLDQ8YgU8s1EoULdbQBcAeNJkY=
-k8s.io/utils v0.0.0-20230313181309-38a27ef9d749/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
+k8s.io/api v0.28.4 h1:8ZBrLjwosLl/NYgv1P7EQLqoO8MGQApnbgH8tu3BMzY=
+k8s.io/api v0.28.4/go.mod h1:axWTGrY88s/5YE+JSt4uUi6NMM+gur1en2REMR7IRj0=
+k8s.io/apiextensions-apiserver v0.28.4 h1:AZpKY/7wQ8n+ZYDtNHbAJBb+N4AXXJvyZx6ww6yAJvU=
+k8s.io/apiextensions-apiserver v0.28.4/go.mod h1:pgQIZ1U8eJSMQcENew/0ShUTlePcSGFq6dxSxf2mwPM=
+k8s.io/apimachinery v0.28.4 h1:zOSJe1mc+GxuMnFzD4Z/U1wst50X28ZNsn5bhgIIao8=
+k8s.io/apimachinery v0.28.4/go.mod h1:wI37ncBvfAoswfq626yPTe6Bz1c22L7uaJ8dho83mgg=
+k8s.io/apiserver v0.28.4 h1:BJXlaQbAU/RXYX2lRz+E1oPe3G3TKlozMMCZWu5GMgg=
+k8s.io/apiserver v0.28.4/go.mod h1:Idq71oXugKZoVGUUL2wgBCTHbUR+FYTWa4rq9j4n23w=
+k8s.io/client-go v0.28.4 h1:Np5ocjlZcTrkyRJ3+T3PkXDpe4UpatQxj85+xjaD2wY=
+k8s.io/client-go v0.28.4/go.mod h1:0VDZFpgoZfelyP5Wqu0/r/TRYcLYuJ2U1KEeoaPa1N4=
+k8s.io/cluster-bootstrap v0.28.4 h1:4MKNy1Qd9QY7pl47rSMGIORF+tm3CUaqC1M8U9bjn4Q=
+k8s.io/cluster-bootstrap v0.28.4/go.mod h1:/c4ro/R4yf4EtJgFgFtvnHkbDOHwubeKJXh5R1c89Bc=
+k8s.io/component-base v0.28.4 h1:c/iQLWPdUgI90O+T9TeECg8o7N3YJTiuz2sKxILYcYo=
+k8s.io/component-base v0.28.4/go.mod h1:m9hR0uvqXDybiGL2nf/3Lf0MerAfQXzkfWhUY58JUbU=
+k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg=
+k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
+k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 h1:LyMgNKD2P8Wn1iAwQU5OhxCKlKJy0sHc+PcDwFB24dQ=
+k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9/go.mod h1:wZK2AVp1uHCp4VamDVgBP2COHZjqD1T68Rf0CM3YjSM=
+k8s.io/kubernetes v1.28.3 h1:XTci6gzk+JR51UZuZQCFJ4CsyUkfivSjLI4O1P9z6LY=
+k8s.io/kubernetes v1.28.3/go.mod h1:NhAysZWvHtNcJFFHic87ofxQN7loylCQwg3ZvXVDbag=
+k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 h1:qY1Ad8PODbnymg2pRbkyMT/ylpTrCM8P2RJ0yroCyIk=
+k8s.io/utils v0.0.0-20230406110748-d93618cff8a2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
-sigs.k8s.io/cluster-api v1.5.1 h1:+oO4EbVQcbBJr5wjqmdjvewPHSTbVLigXZqPk3ZO8t0=
-sigs.k8s.io/cluster-api v1.5.1/go.mod h1:EGJUNpFWi7dF426tO8MG/jE+w7T0UO5KyMnOwQ5riUY=
-sigs.k8s.io/cluster-api/test v1.5.1 h1:kYUfzE6RFsopXek+l/LDnh4gtfjTi2FUghEY8zx0Z9U=
-sigs.k8s.io/cluster-api/test v1.5.1/go.mod h1:mFlsY1y0lApBgQyXbmVprdzCK+9MQNp1C38K+aZdn5A=
-sigs.k8s.io/controller-runtime v0.15.1 h1:9UvgKD4ZJGcj24vefUFgZFP3xej/3igL9BsOUTb/+4c=
-sigs.k8s.io/controller-runtime v0.15.1/go.mod h1:7ngYvp1MLT+9GeZ+6lH3LOlcHkp/+tzA/fmHa4iq9kk=
+sigs.k8s.io/cluster-api v1.6.0 h1:2bhVSnUbtWI8taCjd9lGiHExsRUpKf7Z1fXqi/IwYx4=
+sigs.k8s.io/cluster-api v1.6.0/go.mod h1:LB7u/WxiWj4/bbpHNOa1oQ8nq0MQ5iYlD0pGfRSBGLI=
+sigs.k8s.io/cluster-api/test v1.6.0 h1:hvqUpSYxXCvs4FiEfsDpFZAfZ7i4kkP/59mVdFHlzSI=
+sigs.k8s.io/cluster-api/test v1.6.0/go.mod h1:DJtbkrnrH77cd3PnXeKCQDMtCGVCrHZHPOjMvEsLB2U=
+sigs.k8s.io/controller-runtime v0.16.3 h1:2TuvuokmfXvDUamSx1SuAOO3eTyye+47mJCigwG62c4=
+sigs.k8s.io/controller-runtime v0.16.3/go.mod h1:j7bialYoSn142nv9sCOJmQgDXQXxnroFU4VnX/brVJ0=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
sigs.k8s.io/kind v0.20.0 h1:f0sc3v9mQbGnjBUaqSFST1dwIuiikKVGgoTwpoP33a8=
sigs.k8s.io/kind v0.20.0/go.mod h1:aBlbxg08cauDgZ612shr017/rZwqd7AS563FvpWKPVs=
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE=
sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E=
-sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
+sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
+sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
From 6a792da6c95f793863bf27862481bd4bb9931e73 Mon Sep 17 00:00:00 2001
From: Emilien Macchi
Date: Fri, 20 Oct 2023 09:44:11 -0400
Subject: [PATCH 003/180] Adjustments for new controller-runtime and CAPI
---
Makefile | 7 +-
config/rbac/role.yaml | 12 ++++
go.mod | 26 +++++++-
go.sum | 75 +++++++++++++++++++++-
main.go | 61 ++++++++++++------
test/e2e/data/e2e_conf.yaml | 18 +++---
test/e2e/data/shared/v1beta1/metadata.yaml | 3 +
7 files changed, 170 insertions(+), 32 deletions(-)
diff --git a/Makefile b/Makefile
index 0d6d9a6ee7..de21f50095 100644
--- a/Makefile
+++ b/Makefile
@@ -186,9 +186,9 @@ e2e-image: docker-build
# Pull all the images references in test/e2e/data/e2e_conf.yaml
test-e2e-image-prerequisites:
- docker pull gcr.io/k8s-staging-cluster-api/cluster-api-controller:v1.4.1
- docker pull gcr.io/k8s-staging-cluster-api/kubeadm-bootstrap-controller:v1.4.1
- docker pull gcr.io/k8s-staging-cluster-api/kubeadm-control-plane-controller:v1.4.1
+ docker pull gcr.io/k8s-staging-cluster-api/cluster-api-controller:v1.6.0
+ docker pull gcr.io/k8s-staging-cluster-api/kubeadm-bootstrap-controller:v1.6.0
+ docker pull gcr.io/k8s-staging-cluster-api/kubeadm-control-plane-controller:v1.6.0
docker pull quay.io/jetstack/cert-manager-cainjector:v1.12.1
docker pull quay.io/jetstack/cert-manager-webhook:v1.12.1
docker pull quay.io/jetstack/cert-manager-controller:v1.12.1
@@ -271,6 +271,7 @@ generate-manifests: $(CONTROLLER_GEN) ## Generate manifests e.g. CRD, RBAC etc.
output:webhook:dir=$(WEBHOOK_ROOT) \
webhook
$(CONTROLLER_GEN) \
+ paths=./ \
paths=./controllers/... \
output:rbac:dir=$(RBAC_ROOT) \
rbac:roleName=manager-role
diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml
index 690dbebd30..0eab520098 100644
--- a/config/rbac/role.yaml
+++ b/config/rbac/role.yaml
@@ -23,6 +23,18 @@ rules:
- get
- list
- watch
+- apiGroups:
+ - authentication.k8s.io
+ resources:
+ - tokenreviews
+ verbs:
+ - create
+- apiGroups:
+ - authorization.k8s.io
+ resources:
+ - subjectaccessreviews
+ verbs:
+ - create
- apiGroups:
- cluster.x-k8s.io
resources:
diff --git a/go.mod b/go.mod
index b5ac940ec6..997f835404 100644
--- a/go.mod
+++ b/go.mod
@@ -40,6 +40,7 @@ require (
github.com/Masterminds/semver/v3 v3.2.0 // indirect
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
github.com/Microsoft/go-winio v0.6.0 // indirect
+ github.com/NYTimes/gziphandler v1.1.1 // indirect
github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 // indirect
github.com/adrg/xdg v0.4.0 // indirect
github.com/alessio/shellescape v1.4.1 // indirect
@@ -47,8 +48,11 @@ require (
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
+ github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/cloudflare/circl v1.3.3 // indirect
+ github.com/coreos/go-semver v0.3.1 // indirect
+ github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/distribution/reference v0.5.0 // indirect
github.com/docker/distribution v2.8.3+incompatible // indirect
github.com/docker/docker v24.0.7+incompatible // indirect
@@ -58,7 +62,9 @@ require (
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/evanphx/json-patch v5.6.0+incompatible // indirect
github.com/evanphx/json-patch/v5 v5.7.0 // indirect
+ github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
+ github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-logr/zapr v1.2.4 // indirect
github.com/go-openapi/jsonpointer v0.19.6 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
@@ -75,6 +81,8 @@ require (
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect
github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2 // indirect
github.com/google/uuid v1.3.1 // indirect
+ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect
+ github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect
github.com/hashicorp/go-uuid v1.0.3 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/huandu/xstrings v1.4.0 // indirect
@@ -112,7 +120,18 @@ require (
github.com/stoewer/go-strcase v1.3.0 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/valyala/fastjson v1.6.4 // indirect
- go.uber.org/goleak v1.3.0 // indirect
+ go.etcd.io/etcd/api/v3 v3.5.10 // indirect
+ go.etcd.io/etcd/client/pkg/v3 v3.5.10 // indirect
+ go.etcd.io/etcd/client/v3 v3.5.10 // indirect
+ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.0 // indirect
+ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.0 // indirect
+ go.opentelemetry.io/otel v1.20.0 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.20.0 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.20.0 // indirect
+ go.opentelemetry.io/otel/metric v1.20.0 // indirect
+ go.opentelemetry.io/otel/sdk v1.20.0 // indirect
+ go.opentelemetry.io/otel/trace v1.20.0 // indirect
+ go.opentelemetry.io/proto/otlp v1.0.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.25.0 // indirect
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
@@ -126,15 +145,20 @@ require (
golang.org/x/tools v0.14.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
+ google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 // indirect
+ google.golang.org/grpc v1.59.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
+ gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/apiserver v0.28.4 // indirect
k8s.io/cluster-bootstrap v0.28.4 // indirect
+ k8s.io/kms v0.28.4 // indirect
k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect
+ sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.1.2 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/kind v0.20.0 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
diff --git a/go.sum b/go.sum
index dc4d419024..e3d46fdc89 100644
--- a/go.sum
+++ b/go.sum
@@ -17,12 +17,15 @@ cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHOb
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
+cloud.google.com/go v0.110.7 h1:rJyC7nWRg2jWGZ4wSJ5nY65GTdYJkg0cd/uXb+ACI6o=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
+cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY=
+cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
@@ -52,6 +55,8 @@ github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj
github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM=
github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=
github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE=
+github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
+github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 h1:wPbRQzjjwFc0ih8puEVAOFGELsn1zoIIYdxvML7mDxA=
github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g=
github.com/adrg/xdg v0.4.0 h1:RzRqFcjH4nE5C6oTAxhBtoE2IRyjBSa62SCbyPidvls=
@@ -69,6 +74,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
+github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
+github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -82,8 +89,13 @@ github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUK
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
+github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k=
github.com/coredns/caddy v1.1.1 h1:2eYKZT7i6yxIfGP3qLJoJ7HAsDJqYB+X68g4NYjSrE0=
github.com/coredns/corefile-migration v1.0.21 h1:W/DCETrHDiFo0Wj03EyMkaQ9fwsmSgqTCQDHpceaSsE=
+github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
+github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
+github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
+github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
@@ -103,6 +115,7 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/drone/envsubst/v2 v2.0.0-20210730161058-179042472c46 h1:7QPwrLT79GlD5sizHf27aoY2RTvw62mO6x7mxkScNk0=
github.com/drone/envsubst/v2 v2.0.0-20210730161058-179042472c46/go.mod h1:esf2rsHFNlZlxsqsZDojNBcnNs5REqIvRrWRHqX0vEU=
+github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
@@ -111,11 +124,14 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
+github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA=
github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U=
github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4=
github.com/evanphx/json-patch/v5 v5.7.0 h1:nJqP7uwL84RJInrohHfW0Fx3awjbm8qZeFv0nW9SYGc=
github.com/evanphx/json-patch/v5 v5.7.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ=
+github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
+github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
@@ -123,9 +139,12 @@ github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=
github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
+github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
+github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo=
github.com/go-logr/zapr v1.2.4/go.mod h1:FyHWQIzQORZ0QVE1BtVHv3cKtNLuXsbNLtpuhNapBOA=
github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
@@ -138,9 +157,12 @@ github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEe
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/gobuffalo/flect v1.0.2 h1:eqjPGSo2WmjgY2XlpGwo2NXgL3RucAKo4k4qQMNA5sA=
github.com/gobuffalo/flect v1.0.2/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs=
+github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
+github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -174,6 +196,7 @@ github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
+github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
github.com/google/cel-go v0.16.1 h1:3hZfSNiAU3KOiNtxuFXVp5WFy4hf/Ly3Sa4/7F8SXNo=
github.com/google/cel-go v0.16.1/go.mod h1:HXZKzB0LXqer5lHHgfWAnlYwJaQBDKMjxjulNQzhwhY=
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
@@ -228,6 +251,13 @@ github.com/gophercloud/gophercloud v1.7.0 h1:fyJGKh0LBvIZKLvBWvQdIgkaV5yTM3Jh9EY
github.com/gophercloud/gophercloud v1.7.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM=
github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56 h1:sH7xkTfYzxIEgzq1tDHIMKRh1vThOEOGNsettdEeLbE=
github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56/go.mod h1:VSalo4adEk+3sNkmVJLnhHoOyOYYS8sTWLG4mv5BKto=
+github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
+github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw=
+github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=
+github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
+github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg=
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-version v1.4.0 h1:aAQzgqIrRKRa7w75CKpbBxYsmUoPjzVm1W59ca1L0J4=
@@ -248,6 +278,7 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
+github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
@@ -331,6 +362,8 @@ github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWR
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
+github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
+github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js=
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY=
@@ -363,24 +396,54 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
+github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 h1:6fotK7otjonDflCTK0BCfls4SPy3NcCVb5dqqmbRknE=
github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
+github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
+go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ=
+go.etcd.io/etcd/api/v3 v3.5.10 h1:szRajuUUbLyppkhs9K6BRtjY37l66XQQmw7oZRANE4k=
+go.etcd.io/etcd/api/v3 v3.5.10/go.mod h1:TidfmT4Uycad3NM/o25fG3J07odo4GBB9hoxaodFCtI=
+go.etcd.io/etcd/client/pkg/v3 v3.5.10 h1:kfYIdQftBnbAq8pUWFXfpuuxFSKzlmM5cSn76JByiT0=
+go.etcd.io/etcd/client/pkg/v3 v3.5.10/go.mod h1:DYivfIviIuQ8+/lCq4vcxuseg2P2XbHygkKwFo9fc8U=
+go.etcd.io/etcd/client/v2 v2.305.9 h1:YZ2OLi0OvR0H75AcgSUajjd5uqKDKocQUqROTG11jIo=
+go.etcd.io/etcd/client/v3 v3.5.10 h1:W9TXNZ+oB3MCd/8UjxHTWK5J9Nquw9fQBLJd5ne5/Ao=
+go.etcd.io/etcd/client/v3 v3.5.10/go.mod h1:RVeBnDz2PUEZqTpgqwAtUd8nAPf5kjyFyND7P1VkOKc=
+go.etcd.io/etcd/pkg/v3 v3.5.9 h1:6R2jg/aWd/zB9+9JxmijDKStGJAPFsX3e6BeJkMi6eQ=
+go.etcd.io/etcd/raft/v3 v3.5.9 h1:ZZ1GIHoUlHsn0QVqiRysAm3/81Xx7+i2d7nSdWxlOiI=
+go.etcd.io/etcd/server/v3 v3.5.9 h1:vomEmmxeztLtS5OEH7d0hBAg4cjVIu9wXuNzUZx2ZA0=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
+go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.0 h1:PzIubN4/sjByhDRHLviCjJuweBXWFZWhghjg7cS28+M=
+go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.0/go.mod h1:Ct6zzQEuGK3WpJs2n4dn+wfJYzd/+hNnxMRTWjGn30M=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.0 h1:1eHu3/pUSWaOgltNK3WJFaywKsTIr/PwvHyDmi0lQA0=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.0/go.mod h1:HyABWq60Uy1kjJSa2BVOxUVao8Cdick5AWSKPutqy6U=
+go.opentelemetry.io/otel v1.20.0 h1:vsb/ggIY+hUjD/zCAQHpzTmndPqv/ml2ArbsbfBYTAc=
+go.opentelemetry.io/otel v1.20.0/go.mod h1:oUIGj3D77RwJdM6PPZImDpSZGDvkD9fhesHny69JFrs=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.20.0 h1:DeFD0VgTZ+Cj6hxravYYZE2W4GlneVH81iAOPjZkzk8=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.20.0/go.mod h1:GijYcYmNpX1KazD5JmWGsi4P7dDTTTnfv1UbGn84MnU=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.20.0 h1:gvmNvqrPYovvyRmCSygkUDyL8lC5Tl845MLEwqpxhEU=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.20.0/go.mod h1:vNUq47TGFioo+ffTSnKNdob241vePmtNZnAODKapKd0=
+go.opentelemetry.io/otel/metric v1.20.0 h1:ZlrO8Hu9+GAhnepmRGhSU7/VkpjrNowxRN9GyKR4wzA=
+go.opentelemetry.io/otel/metric v1.20.0/go.mod h1:90DRw3nfK4D7Sm/75yQ00gTJxtkBxX+wu6YaNymbpVM=
+go.opentelemetry.io/otel/sdk v1.20.0 h1:5Jf6imeFZlZtKv9Qbo6qt2ZkmWtdWx/wzcCbNUlAWGM=
+go.opentelemetry.io/otel/sdk v1.20.0/go.mod h1:rmkSx1cZCm/tn16iWDn1GQbLtsW/LvsdEEFzCSRM6V0=
+go.opentelemetry.io/otel/trace v1.20.0 h1:+yxVAPZPbQhbC3OfAkeIVTky6iTFpcr4SiY9om7mXSQ=
+go.opentelemetry.io/otel/trace v1.20.0/go.mod h1:HJSK7F/hA5RlzpZ0zKDCHCDHm556LCDtKaAo6JmBFUU=
+go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
+go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
-go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
@@ -692,6 +755,8 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb h1:XFBgcDwm7irdHTbz4Zk2h7Mh+eis4nfJEFQFYzJzuIA=
+google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4=
google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb h1:lK0oleSc7IQsUxO3U5TjL9DWlsxpEBemh+zpB7IqhWI=
google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 h1:N3bU/SQDCDyD6R528GJ/PwW9KjYcJA3dgyH+MovAkIM=
@@ -712,6 +777,8 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
+google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk=
+google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -736,6 +803,8 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
+gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
+gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@@ -768,6 +837,8 @@ k8s.io/component-base v0.28.4 h1:c/iQLWPdUgI90O+T9TeECg8o7N3YJTiuz2sKxILYcYo=
k8s.io/component-base v0.28.4/go.mod h1:m9hR0uvqXDybiGL2nf/3Lf0MerAfQXzkfWhUY58JUbU=
k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg=
k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
+k8s.io/kms v0.28.4 h1:PMgY/3CQTWP9eIKmNQiTgjLIZ0ns6O+voagzD2/4mSg=
+k8s.io/kms v0.28.4/go.mod h1:HL4/lR/bhjAJPbqycKtfhWiKh1Sp21cpHOL8P4oo87w=
k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 h1:LyMgNKD2P8Wn1iAwQU5OhxCKlKJy0sHc+PcDwFB24dQ=
k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9/go.mod h1:wZK2AVp1uHCp4VamDVgBP2COHZjqD1T68Rf0CM3YjSM=
k8s.io/kubernetes v1.28.3 h1:XTci6gzk+JR51UZuZQCFJ4CsyUkfivSjLI4O1P9z6LY=
@@ -777,6 +848,8 @@ k8s.io/utils v0.0.0-20230406110748-d93618cff8a2/go.mod h1:OLgZIPagt7ERELqWJFomSt
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.1.2 h1:trsWhjU5jZrx6UvFu4WzQDrN7Pga4a7Qg+zcfcj64PA=
+sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.1.2/go.mod h1:+qG7ISXqCDVVcyO8hLn12AKVYYUjM7ftlqsqmrhMZE0=
sigs.k8s.io/cluster-api v1.6.0 h1:2bhVSnUbtWI8taCjd9lGiHExsRUpKf7Z1fXqi/IwYx4=
sigs.k8s.io/cluster-api v1.6.0/go.mod h1:LB7u/WxiWj4/bbpHNOa1oQ8nq0MQ5iYlD0pGfRSBGLI=
sigs.k8s.io/cluster-api/test v1.6.0 h1:hvqUpSYxXCvs4FiEfsDpFZAfZ7i4kkP/59mVdFHlzSI=
diff --git a/main.go b/main.go
index b12b744de0..957a623827 100644
--- a/main.go
+++ b/main.go
@@ -34,10 +34,13 @@ import (
_ "k8s.io/component-base/logs/json/register"
"k8s.io/klog/v2"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
+ "sigs.k8s.io/cluster-api/util/flags"
ctrl "sigs.k8s.io/controller-runtime"
- "sigs.k8s.io/controller-runtime/pkg/client"
+ cache "sigs.k8s.io/controller-runtime/pkg/cache"
+ client "sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/config"
"sigs.k8s.io/controller-runtime/pkg/controller"
+ "sigs.k8s.io/controller-runtime/pkg/webhook"
infrav1alpha5 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha5"
infrav1alpha6 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha6"
@@ -54,7 +57,7 @@ var (
setupLog = ctrl.Log.WithName("setup")
// flags.
- metricsBindAddr string
+ diagnosticsOptions = flags.DiagnosticsOptions{}
enableLeaderElection bool
leaderElectionLeaseDuration time.Duration
leaderElectionRenewDeadline time.Duration
@@ -91,8 +94,7 @@ func InitFlags(fs *pflag.FlagSet) {
logs.AddFlags(fs, logs.SkipLoggingConfigurationFlags())
logsv1.AddFlags(logOptions, fs)
- fs.StringVar(&metricsBindAddr, "metrics-bind-addr", "localhost:8080",
- "The address the metric endpoint binds to.")
+ flags.AddDiagnosticsOptions(fs, &diagnosticsOptions)
fs.BoolVar(&enableLeaderElection, "leader-elect", false,
"Enable leader election for controller manager. Enabling this will ensure there is only one active controller manager.")
@@ -143,6 +145,10 @@ func InitFlags(fs *pflag.FlagSet) {
fs.BoolVar(&showVersion, "version", false, "Show current version and exit.")
}
+// Add RBAC for the authorized diagnostics endpoint.
+// +kubebuilder:rbac:groups=authentication.k8s.io,resources=tokenreviews,verbs=create
+// +kubebuilder:rbac:groups=authorization.k8s.io,resources=subjectaccessreviews,verbs=create
+
func main() {
InitFlags(pflag.CommandLine)
pflag.CommandLine.SetNormalizeFunc(cliflag.WordSepNormalizeFunc)
@@ -183,22 +189,41 @@ func main() {
}
}
+ diagnosticsOpts := flags.GetDiagnosticsOptions(diagnosticsOptions)
+
+ var watchNamespaces map[string]cache.Config
+ if watchNamespace != "" {
+ watchNamespaces = map[string]cache.Config{
+ watchNamespace: {},
+ }
+ }
+
mgr, err := ctrl.NewManager(cfg, ctrl.Options{
- Scheme: scheme,
- MetricsBindAddress: metricsBindAddr,
- LeaderElection: enableLeaderElection,
- LeaderElectionID: "controller-leader-election-capo",
- LeaseDuration: &leaderElectionLeaseDuration,
- RenewDeadline: &leaderElectionRenewDeadline,
- RetryPeriod: &leaderElectionRetryPeriod,
- Namespace: watchNamespace,
- SyncPeriod: &syncPeriod,
- ClientDisableCacheFor: []client.Object{
- &corev1.ConfigMap{},
- &corev1.Secret{},
+ Scheme: scheme,
+ Metrics: diagnosticsOpts,
+ LeaderElection: enableLeaderElection,
+ LeaderElectionID: "controller-leader-election-capo",
+ LeaseDuration: &leaderElectionLeaseDuration,
+ RenewDeadline: &leaderElectionRenewDeadline,
+ RetryPeriod: &leaderElectionRetryPeriod,
+ Cache: cache.Options{
+ DefaultNamespaces: watchNamespaces,
+ SyncPeriod: &syncPeriod,
+ },
+ Client: client.Options{
+ Cache: &client.CacheOptions{
+ DisableFor: []client.Object{
+ &corev1.ConfigMap{},
+ &corev1.Secret{},
+ },
+ },
},
- Port: webhookPort,
- CertDir: webhookCertDir,
+ WebhookServer: webhook.NewServer(
+ webhook.Options{
+ Port: webhookPort,
+ CertDir: webhookCertDir,
+ },
+ ),
HealthProbeBindAddress: healthAddr,
})
if err != nil {
diff --git a/test/e2e/data/e2e_conf.yaml b/test/e2e/data/e2e_conf.yaml
index 7a85fcd1b5..ad70cd733d 100644
--- a/test/e2e/data/e2e_conf.yaml
+++ b/test/e2e/data/e2e_conf.yaml
@@ -12,11 +12,11 @@
managementClusterName: capo-e2e
images:
-- name: gcr.io/k8s-staging-cluster-api/cluster-api-controller:v1.5.1
+- name: gcr.io/k8s-staging-cluster-api/cluster-api-controller:v1.6.0
loadBehavior: tryLoad
-- name: gcr.io/k8s-staging-cluster-api/kubeadm-bootstrap-controller:v1.5.1
+- name: gcr.io/k8s-staging-cluster-api/kubeadm-bootstrap-controller:v1.6.0
loadBehavior: tryLoad
-- name: gcr.io/k8s-staging-cluster-api/kubeadm-control-plane-controller:v1.5.1
+- name: gcr.io/k8s-staging-cluster-api/kubeadm-control-plane-controller:v1.6.0
loadBehavior: tryLoad
# Use local dev images built source tree;
- name: gcr.io/k8s-staging-capi-openstack/capi-openstack-controller:e2e
@@ -32,8 +32,8 @@ providers:
- name: cluster-api
type: CoreProvider
versions:
- - name: v1.5.1
- value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.5.1/core-components.yaml"
+ - name: v1.6.0
+ value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.6.0/core-components.yaml"
type: url
contract: v1beta1
files:
@@ -58,8 +58,8 @@ providers:
- name: kubeadm
type: BootstrapProvider
versions:
- - name: v1.5.1
- value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.5.1/bootstrap-components.yaml"
+ - name: v1.6.0
+ value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.6.0/bootstrap-components.yaml"
type: url
contract: v1beta1
files:
@@ -84,8 +84,8 @@ providers:
- name: kubeadm
type: ControlPlaneProvider
versions:
- - name: v1.5.1
- value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.5.1/control-plane-components.yaml"
+ - name: v1.6.0
+ value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.6.0/control-plane-components.yaml"
type: url
contract: v1beta1
files:
diff --git a/test/e2e/data/shared/v1beta1/metadata.yaml b/test/e2e/data/shared/v1beta1/metadata.yaml
index ce72c124c1..85e75d5e37 100644
--- a/test/e2e/data/shared/v1beta1/metadata.yaml
+++ b/test/e2e/data/shared/v1beta1/metadata.yaml
@@ -13,3 +13,6 @@ releaseSeries:
- major: 1
minor: 5
contract: v1beta1
+ - major: 1
+ minor: 6
+ contract: v1beta1
From f94a1aed20eee9cc60f41ebe3ebd8748b96fd2a6 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Thu, 7 Dec 2023 14:23:41 +0000
Subject: [PATCH 004/180] Revert "Move FloatingIP to Bastion spec"
This reverts commit f19a6cc61bc5698f8292e851dba2d0b491d14ed0.
This change required a version bump. We will re-add this change after
creating the required version bump.
---
api/v1alpha5/conversion.go | 19 -----------
api/v1alpha5/zz_generated.conversion.go | 29 +++++++---------
api/v1alpha6/conversion.go | 23 -------------
api/v1alpha6/zz_generated.conversion.go | 29 +++++++---------
api/v1alpha7/openstackmachine_types.go | 4 +++
api/v1alpha7/types.go | 5 ---
...re.cluster.x-k8s.io_openstackclusters.yaml | 10 +++---
...er.x-k8s.io_openstackclustertemplates.yaml | 10 +++---
...re.cluster.x-k8s.io_openstackmachines.yaml | 5 +++
...er.x-k8s.io_openstackmachinetemplates.yaml | 5 +++
controllers/openstackcluster_controller.go | 2 +-
.../src/clusteropenstack/configuration.md | 2 +-
.../crd-changes/v1alpha6-to-v1alpha7.md | 33 -------------------
13 files changed, 50 insertions(+), 126 deletions(-)
diff --git a/api/v1alpha5/conversion.go b/api/v1alpha5/conversion.go
index 2db68f0402..3f41962b92 100644
--- a/api/v1alpha5/conversion.go
+++ b/api/v1alpha5/conversion.go
@@ -238,16 +238,6 @@ func Convert_v1alpha5_PortOpts_To_v1alpha7_PortOpts(in *PortOpts, out *infrav1.P
return nil
}
-func Convert_v1alpha5_OpenStackMachineSpec_To_v1alpha7_Bastion(in *OpenStackMachineSpec, out *infrav1.Bastion, _ conversion.Scope) error {
- out.FloatingIP = in.FloatingIP
- return nil
-}
-
-func Convert_v1alpha7_Bastion_To_v1alpha5_OpenStackMachineSpec(in *infrav1.Bastion, out *OpenStackMachineSpec, _ conversion.Scope) error {
- out.FloatingIP = in.FloatingIP
- 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
out.ID = in.ID
@@ -447,12 +437,3 @@ func Convert_v1alpha5_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(
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_v1alpha7_Bastion_To_v1alpha5_Bastion(in *infrav1.Bastion, out *Bastion, s conversion.Scope) error {
- err := autoConvert_v1alpha7_Bastion_To_v1alpha5_Bastion(in, out, s)
- if err != nil {
- return err
- }
- in.FloatingIP = out.Instance.FloatingIP
- return nil
-}
diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go
index 1f0f43c79e..52681a9c65 100644
--- a/api/v1alpha5/zz_generated.conversion.go
+++ b/api/v1alpha5/zz_generated.conversion.go
@@ -59,6 +59,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); 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)
+ }); 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)
}); err != nil {
@@ -324,11 +329,6 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddConversionFunc((*OpenStackMachineSpec)(nil), (*v1alpha7.Bastion)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_OpenStackMachineSpec_To_v1alpha7_Bastion(a.(*OpenStackMachineSpec), b.(*v1alpha7.Bastion), 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)
}); err != nil {
@@ -364,16 +364,6 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddConversionFunc((*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)
- }); err != nil {
- return err
- }
- if err := s.AddConversionFunc((*v1alpha7.Bastion)(nil), (*OpenStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_Bastion_To_v1alpha5_OpenStackMachineSpec(a.(*v1alpha7.Bastion), b.(*OpenStackMachineSpec), 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)
}); err != nil {
@@ -484,10 +474,14 @@ func autoConvert_v1alpha7_Bastion_To_v1alpha5_Bastion(in *v1alpha7.Bastion, out
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 {
out.FixedIP = in.FixedIP
if err := Convert_v1alpha5_SubnetParam_To_v1alpha7_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil {
@@ -1083,7 +1077,7 @@ func autoConvert_v1alpha5_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(
out.Ports = nil
}
// WARNING: in.Subnet requires manual conversion: does not exist in peer-type
- // WARNING: in.FloatingIP requires manual conversion: does not exist in peer-type
+ out.FloatingIP = in.FloatingIP
if in.SecurityGroups != nil {
in, out := &in.SecurityGroups, &out.SecurityGroups
*out = make([]v1alpha7.SecurityGroupFilter, len(*in))
@@ -1124,6 +1118,7 @@ func autoConvert_v1alpha7_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(
} else {
out.Ports = nil
}
+ out.FloatingIP = in.FloatingIP
if in.SecurityGroups != nil {
in, out := &in.SecurityGroups, &out.SecurityGroups
*out = make([]SecurityGroupParam, len(*in))
diff --git a/api/v1alpha6/conversion.go b/api/v1alpha6/conversion.go
index b3faa7605d..ae8e343ea8 100644
--- a/api/v1alpha6/conversion.go
+++ b/api/v1alpha6/conversion.go
@@ -40,10 +40,6 @@ func restorev1alpha6MachineSpec(previous *OpenStackMachineSpec, dst *OpenStackMa
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
}
func restorev1alpha6ClusterStatus(previous *OpenStackClusterStatus, dst *OpenStackClusterStatus) {
@@ -476,16 +472,6 @@ func Convert_v1alpha7_PortOpts_To_v1alpha6_PortOpts(in *infrav1.PortOpts, out *P
return nil
}
-func Convert_v1alpha6_OpenStackMachineSpec_To_v1alpha7_Bastion(in *OpenStackMachineSpec, out *infrav1.Bastion, _ apiconversion.Scope) error {
- out.FloatingIP = in.FloatingIP
- return nil
-}
-
-func Convert_v1alpha7_Bastion_To_v1alpha6_OpenStackMachineSpec(in *infrav1.Bastion, out *OpenStackMachineSpec, _ apiconversion.Scope) error {
- out.FloatingIP = in.FloatingIP
- 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
@@ -673,12 +659,3 @@ func Convert_v1alpha6_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(
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)
}
-
-func Convert_v1alpha7_Bastion_To_v1alpha6_Bastion(in *infrav1.Bastion, out *Bastion, s apiconversion.Scope) error {
- err := autoConvert_v1alpha7_Bastion_To_v1alpha6_Bastion(in, out, s)
- if err != nil {
- return err
- }
- in.FloatingIP = out.Instance.FloatingIP
- return nil
-}
diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go
index 09cd655cc1..6bfa0129c3 100644
--- a/api/v1alpha6/zz_generated.conversion.go
+++ b/api/v1alpha6/zz_generated.conversion.go
@@ -64,6 +64,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); 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)
+ }); 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)
}); err != nil {
@@ -344,11 +349,6 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddConversionFunc((*OpenStackMachineSpec)(nil), (*v1alpha7.Bastion)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_OpenStackMachineSpec_To_v1alpha7_Bastion(a.(*OpenStackMachineSpec), b.(*v1alpha7.Bastion), 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)
}); err != nil {
@@ -379,16 +379,6 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddConversionFunc((*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)
- }); err != nil {
- return err
- }
- if err := s.AddConversionFunc((*v1alpha7.Bastion)(nil), (*OpenStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_Bastion_To_v1alpha6_OpenStackMachineSpec(a.(*v1alpha7.Bastion), b.(*OpenStackMachineSpec), 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)
}); err != nil {
@@ -500,10 +490,14 @@ func autoConvert_v1alpha7_Bastion_To_v1alpha6_Bastion(in *v1alpha7.Bastion, out
return err
}
out.AvailabilityZone = in.AvailabilityZone
- // 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 {
out.FixedIP = in.FixedIP
if err := Convert_v1alpha6_SubnetParam_To_v1alpha7_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil {
@@ -1106,7 +1100,7 @@ func autoConvert_v1alpha6_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(
out.Ports = nil
}
// WARNING: in.Subnet requires manual conversion: does not exist in peer-type
- // WARNING: in.FloatingIP requires manual conversion: does not exist in peer-type
+ out.FloatingIP = in.FloatingIP
if in.SecurityGroups != nil {
in, out := &in.SecurityGroups, &out.SecurityGroups
*out = make([]v1alpha7.SecurityGroupFilter, len(*in))
@@ -1147,6 +1141,7 @@ func autoConvert_v1alpha7_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(
} else {
out.Ports = nil
}
+ out.FloatingIP = in.FloatingIP
if in.SecurityGroups != nil {
in, out := &in.SecurityGroups, &out.SecurityGroups
*out = make([]SecurityGroupParam, len(*in))
diff --git a/api/v1alpha7/openstackmachine_types.go b/api/v1alpha7/openstackmachine_types.go
index df5c4a55db..f5f4f698aa 100644
--- a/api/v1alpha7/openstackmachine_types.go
+++ b/api/v1alpha7/openstackmachine_types.go
@@ -60,6 +60,10 @@ 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"`
diff --git a/api/v1alpha7/types.go b/api/v1alpha7/types.go
index d82016bbc7..3ef5305ff2 100644
--- a/api/v1alpha7/types.go
+++ b/api/v1alpha7/types.go
@@ -344,11 +344,6 @@ type Bastion struct {
//+optional
AvailabilityZone string `json:"availabilityZone,omitempty"`
-
- // FloatingIP which will be associated to the bastion machine.
- // The floating IP should already exist and should not be associated with a port.
- //+optional
- FloatingIP string `json:"floatingIP,omitempty"`
}
type APIServerLoadBalancer struct {
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 ac700b690a..a5114ac6a2 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -3767,11 +3767,6 @@ spec:
type: string
enabled:
type: boolean
- floatingIP:
- description: FloatingIP which will be associated to the bastion
- machine. The floating IP should already exist and should not
- be associated with a port.
- type: string
instance:
description: Instance for the bastion itself
properties:
@@ -3847,6 +3842,11 @@ 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.
+ type: string
identityRef:
description: IdentityRef is a reference to a identity to be
used when reconciling this cluster
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 281b48f8df..815a3a83fc 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -1607,11 +1607,6 @@ spec:
type: string
enabled:
type: boolean
- floatingIP:
- description: FloatingIP which will be associated to the
- bastion machine. The floating IP should already exist
- and should not be associated with a port.
- type: string
instance:
description: Instance for the bastion itself
properties:
@@ -1693,6 +1688,11 @@ 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.
+ type: string
identityRef:
description: IdentityRef is a reference to a identity
to be used when reconciling this cluster
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 be2ad0feee..e5171cd868 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
@@ -1226,6 +1226,11 @@ spec:
flavor:
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.
+ type: string
identityRef:
description: IdentityRef is a reference to a identity to be used when
reconciling this cluster
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 f0dca99933..bc88d84fa2 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
@@ -1030,6 +1030,11 @@ 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.
+ type: string
identityRef:
description: IdentityRef is a reference to a identity to be
used when reconciling this cluster
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index e6d3025cba..08177fc9ed 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -359,7 +359,7 @@ func reconcileBastion(scope scope.Scope, cluster *clusterv1.Cluster, openStackCl
return err
}
clusterName := fmt.Sprintf("%s-%s", cluster.Namespace, cluster.Name)
- fp, err := networkingService.GetOrCreateFloatingIP(openStackCluster, openStackCluster, clusterName, openStackCluster.Spec.Bastion.FloatingIP)
+ 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)
diff --git a/docs/book/src/clusteropenstack/configuration.md b/docs/book/src/clusteropenstack/configuration.md
index 3f4e9dc58f..6d9ab32fff 100644
--- a/docs/book/src/clusteropenstack/configuration.md
+++ b/docs/book/src/clusteropenstack/configuration.md
@@ -626,7 +626,7 @@ spec:
...
bastion:
...
- floatingIP:
+ floatingIP:
```
If `managedSecurityGroups: true`, security group rule opening 22/tcp is added to security groups for bastion, controller, and worker nodes respectively. Otherwise, you have to add `securityGroups` to the `bastion` in `OpenStackCluster` spec and `OpenStackMachineTemplate` spec template respectively.
diff --git a/docs/book/src/topics/crd-changes/v1alpha6-to-v1alpha7.md b/docs/book/src/topics/crd-changes/v1alpha6-to-v1alpha7.md
index bed0c4cf5f..25937afa52 100644
--- a/docs/book/src/topics/crd-changes/v1alpha6-to-v1alpha7.md
+++ b/docs/book/src/topics/crd-changes/v1alpha6-to-v1alpha7.md
@@ -8,7 +8,6 @@
- [`OpenStackMachine`](#openstackmachine)
- [⚠️ Removal of networks](#-removal-of-networks)
- [Removal of subnet](#removal-of-subnet)
- - [Change to floatingIP](#change-to-floatingip)
- [Change to securityGroups](#change-to-securitygroups)
- [Changes to ports](#changes-to-ports)
- [Change to securityGroupFilters](#change-to-securitygroupfilters)
@@ -122,38 +121,6 @@ to set the `accessIPv4` field on Nova servers. This feature was not widely
used, difficult to use, and could not be extended to support IPv6. It is
removed without replacement.
-#### Change to floatingIP
-
-The `OpenStackMachineSpec.FloatingIP` field has moved to `OpenStackClusterSpec.Bastion.FloatingIP`.
-For example, if you had the following `OpenStackMachineTemplate`:
-
-```yaml
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha6
-kind: OpenStackMachineTemplate
-metadata:
- name: ${CLUSTER_NAME}-md-0
-spec:
- template:
- spec:
- ..
- floatingIP: "1.2.3.4"
-```
-
-This will safely converted to use `Bastion.FloatingIP` when upgrading to version 0.8.
-
-To use the new `Bastion.FloatingIP` field, here is an example:
-
-```yaml
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
-kind: OpenStackCluster
-metadata:
- name: ${CLUSTER_NAME}
-spec:
- ..
- bastion:
- floatingIP: "1.2.3.4"
-```
-
#### Change to securityGroups
`securityGroups` has been simplified by the removal of a separate filter parameter. It was previously:
From 7e082f1701dc037facb89b6aa5a942175886e06c Mon Sep 17 00:00:00 2001
From: Stephen Finucane
Date: Fri, 8 Dec 2023 11:27:18 +0000
Subject: [PATCH 005/180] Don't apply worker SG to control plane machines
Currently, if a worker machine security group is specified but a control
plane machine security group is not, the worker machine SG will be be
applied to both worker *and* control plane machines. Correct this
mistake.
Signed-off-by: Stephen Finucane
---
controllers/openstackmachine_controller.go | 20 ++++---
.../openstackmachine_controller_test.go | 52 ++++++++++++++++---
2 files changed, 59 insertions(+), 13 deletions(-)
diff --git a/controllers/openstackmachine_controller.go b/controllers/openstackmachine_controller.go
index 3609ac2953..b0345c078c 100644
--- a/controllers/openstackmachine_controller.go
+++ b/controllers/openstackmachine_controller.go
@@ -499,15 +499,21 @@ func machineToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, machine *
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 {
+ managedSecurityGroup = openStackCluster.Status.ControlPlaneSecurityGroup.ID
+ }
+ } else {
+ if openStackCluster.Status.WorkerSecurityGroup != nil {
+ managedSecurityGroup = openStackCluster.Status.WorkerSecurityGroup.ID
+ }
}
- instanceSpec.SecurityGroups = append(instanceSpec.SecurityGroups, infrav1.SecurityGroupFilter{
- ID: managedSecurityGroup,
- })
+ if managedSecurityGroup != "" {
+ instanceSpec.SecurityGroups = append(instanceSpec.SecurityGroups, infrav1.SecurityGroupFilter{
+ ID: managedSecurityGroup,
+ })
+ }
}
instanceSpec.Ports = openStackMachine.Spec.Ports
diff --git a/controllers/openstackmachine_controller_test.go b/controllers/openstackmachine_controller_test.go
index 84151e5dfa..0d9045c221 100644
--- a/controllers/openstackmachine_controller_test.go
+++ b/controllers/openstackmachine_controller_test.go
@@ -89,8 +89,9 @@ func getDefaultOpenStackMachine() *infrav1.OpenStackMachine {
ServerMetadata: map[string]string{
"test-metadata": "test-value",
},
- ConfigDrive: pointer.Bool(true),
- ServerGroupID: serverGroupUUID,
+ ConfigDrive: pointer.Bool(true),
+ SecurityGroups: []infrav1.SecurityGroupFilter{},
+ ServerGroupID: serverGroupUUID,
},
}
}
@@ -105,10 +106,11 @@ func getDefaultInstanceSpec() *compute.InstanceSpec {
Metadata: map[string]string{
"test-metadata": "test-value",
},
- ConfigDrive: *pointer.Bool(true),
- FailureDomain: *pointer.String(failureDomain),
- ServerGroupID: serverGroupUUID,
- Tags: []string{"test-tag"},
+ ConfigDrive: *pointer.Bool(true),
+ FailureDomain: *pointer.String(failureDomain),
+ ServerGroupID: serverGroupUUID,
+ SecurityGroups: []infrav1.SecurityGroupFilter{},
+ Tags: []string{"test-tag"},
}
}
@@ -165,6 +167,44 @@ func Test_machineToInstanceSpec(t *testing.T) {
return i
},
},
+ {
+ name: "Control plane security group not applied to worker",
+ openStackCluster: func() *infrav1.OpenStackCluster {
+ c := getDefaultOpenStackCluster()
+ c.Spec.ManagedSecurityGroups = true
+ c.Status.WorkerSecurityGroup = nil
+ return c
+ },
+ machine: getDefaultMachine,
+ openStackMachine: getDefaultOpenStackMachine,
+ wantInstanceSpec: func() *compute.InstanceSpec {
+ i := getDefaultInstanceSpec()
+ i.SecurityGroups = []infrav1.SecurityGroupFilter{}
+ return i
+ },
+ },
+ {
+ name: "Worker security group not applied to control plane",
+ openStackCluster: func() *infrav1.OpenStackCluster {
+ c := getDefaultOpenStackCluster()
+ c.Spec.ManagedSecurityGroups = true
+ c.Status.ControlPlaneSecurityGroup = nil
+ return c
+ },
+ machine: func() *clusterv1.Machine {
+ m := getDefaultMachine()
+ m.Labels = map[string]string{
+ clusterv1.MachineControlPlaneLabel: "true",
+ }
+ return m
+ },
+ openStackMachine: getDefaultOpenStackMachine,
+ wantInstanceSpec: func() *compute.InstanceSpec {
+ i := getDefaultInstanceSpec()
+ i.SecurityGroups = []infrav1.SecurityGroupFilter{}
+ return i
+ },
+ },
{
name: "Extra security group",
openStackCluster: func() *infrav1.OpenStackCluster {
From f549ede91eb79f5774a9cefa1383f3e0ef6aea8f Mon Sep 17 00:00:00 2001
From: Emilien Macchi
Date: Thu, 7 Dec 2023 11:20:21 -0500
Subject: [PATCH 006/180] Add v1alpha8
---
.golangci.yml | 2 +
Makefile | 6 +-
PROJECT | 12 +
README.md | 9 +-
api/v1alpha5/conversion.go | 128 +-
api/v1alpha5/conversion_test.go | 2 +-
api/v1alpha5/doc.go | 2 +-
api/v1alpha5/zz_generated.conversion.go | 912 ++++-----
api/v1alpha5/zz_generated.deepcopy.go | 2 +-
api/v1alpha6/conversion.go | 164 +-
api/v1alpha6/conversion_test.go | 2 +-
api/v1alpha6/doc.go | 2 +-
api/v1alpha6/zz_generated.conversion.go | 950 +++++-----
api/v1alpha6/zz_generated.deepcopy.go | 2 +-
api/v1alpha7/conversion.go | 225 ++-
api/v1alpha7/conversion_test.go | 212 +++
api/v1alpha7/doc.go | 1 +
api/v1alpha7/groupversion_info.go | 2 +
api/v1alpha7/identity_types.go | 2 -
api/v1alpha7/openstackcluster_types.go | 1 -
.../openstackclustertemplate_types.go | 1 -
api/v1alpha7/openstackmachine_types.go | 1 -
.../openstackmachinetemplate_types.go | 1 -
api/v1alpha7/zz_generated.conversion.go | 1667 +++++++++++++++++
api/v1alpha7/zz_generated.deepcopy.go | 4 +-
api/v1alpha8/conditions_consts.go | 55 +
api/v1alpha8/conversion.go | 41 +
api/v1alpha8/doc.go | 17 +
api/v1alpha8/filter_convert.go | 81 +
api/v1alpha8/groupversion_info.go | 36 +
api/v1alpha8/identity_types.go | 33 +
api/v1alpha8/openstackcluster_types.go | 263 +++
.../openstackcluster_webhook.go | 6 +-
.../openstackcluster_webhook_test.go | 2 +-
.../openstackclusterlist_webhook.go | 2 +-
.../openstackclustertemplate_types.go | 56 +
.../openstackclustertemplate_webhook.go | 6 +-
api/v1alpha8/openstackmachine_types.go | 185 ++
.../openstackmachine_webhook.go | 6 +-
.../openstackmachinelist_webhook.go | 2 +-
.../openstackmachinetemplate_types.go | 51 +
.../openstackmachinetemplate_webhook.go | 4 +-
.../openstackmachinetemplate_webhook_test.go | 2 +-
.../openstackmachinetemplatelist_webhook.go | 2 +-
api/v1alpha8/types.go | 372 ++++
api/{v1alpha7 => v1alpha8}/webhooks.go | 2 +-
api/v1alpha8/zz_generated.deepcopy.go | 1059 +++++++++++
...re.cluster.x-k8s.io_openstackclusters.yaml | 1043 +++++++++++
...er.x-k8s.io_openstackclustertemplates.yaml | 729 +++++++
...re.cluster.x-k8s.io_openstackmachines.yaml | 498 +++++
...er.x-k8s.io_openstackmachinetemplates.yaml | 407 ++++
config/crd/kustomization.yaml | 2 +-
config/webhook/manifests.yaml | 28 +-
controllers/openstackcluster_controller.go | 2 +-
.../openstackcluster_controller_test.go | 2 +-
controllers/openstackmachine_controller.go | 2 +-
.../openstackmachine_controller_test.go | 2 +-
controllers/suite_test.go | 2 +-
.../src/clusteropenstack/configuration.md | 26 +-
hack/boilerplate/boilerplate.generatego.txt | 2 +-
.../v1alpha8/default/cluster-template.yaml | 148 ++
kustomize/v1alpha8/default/kustomization.yaml | 4 +
kustomize/v1alpha8/flatcar/kustomization.yaml | 6 +
kustomize/v1alpha8/flatcar/patch-flatcar.yaml | 109 ++
.../v1alpha8/without-lb/kustomization.yaml | 6 +
.../v1alpha8/without-lb/patch-without-lb.yaml | 15 +
main.go | 4 +-
pkg/clients/mock/compute.go | 2 +-
pkg/clients/mock/image.go | 2 +-
pkg/clients/mock/loadbalancer.go | 2 +-
pkg/clients/mock/network.go | 2 +-
pkg/clients/mock/volume.go | 2 +-
pkg/cloud/services/compute/instance.go | 2 +-
pkg/cloud/services/compute/instance_test.go | 2 +-
pkg/cloud/services/compute/instance_types.go | 2 +-
.../services/loadbalancer/loadbalancer.go | 2 +-
.../loadbalancer/loadbalancer_test.go | 2 +-
pkg/cloud/services/networking/floatingip.go | 2 +-
.../services/networking/floatingip_test.go | 2 +-
pkg/cloud/services/networking/network.go | 2 +-
pkg/cloud/services/networking/network_test.go | 2 +-
pkg/cloud/services/networking/port.go | 2 +-
pkg/cloud/services/networking/port_test.go | 2 +-
pkg/cloud/services/networking/router.go | 2 +-
.../services/networking/securitygroups.go | 2 +-
.../networking/securitygroups_rules.go | 2 +-
pkg/cloud/services/networking/trunk_test.go | 2 +-
pkg/scope/mock.go | 2 +-
pkg/scope/provider.go | 2 +-
pkg/scope/scope.go | 2 +-
templates/cluster-template-flatcar.yaml | 12 +-
templates/cluster-template-without-lb.yaml | 12 +-
templates/cluster-template.yaml | 12 +-
test/e2e/data/e2e_conf.yaml | 14 +
.../data/kustomize/default/kustomization.yaml | 2 +-
.../data/kustomize/flatcar/kustomization.yaml | 2 +-
.../data/kustomize/k8s-upgrade/kcp-patch.yaml | 2 +-
.../data/kustomize/k8s-upgrade/md-patch.yaml | 2 +-
.../k8s-upgrade/upgrade-from-template.yaml | 4 +-
.../k8s-upgrade/upgrade-to-template.yaml | 4 +-
.../kustomize/v1alpha7/kustomization.yaml | 22 +
.../kustomize/without-lb/kustomization.yaml | 2 +-
test/e2e/shared/common.go | 2 +-
test/e2e/shared/defaults.go | 3 +-
test/e2e/shared/openstack.go | 2 +-
.../e2e/suites/e2e/clusterctl_upgrade_test.go | 23 +
test/e2e/suites/e2e/e2e_test.go | 2 +-
107 files changed, 8582 insertions(+), 1218 deletions(-)
create mode 100644 api/v1alpha7/conversion_test.go
create mode 100644 api/v1alpha7/zz_generated.conversion.go
create mode 100644 api/v1alpha8/conditions_consts.go
create mode 100644 api/v1alpha8/conversion.go
create mode 100644 api/v1alpha8/doc.go
create mode 100644 api/v1alpha8/filter_convert.go
create mode 100644 api/v1alpha8/groupversion_info.go
create mode 100644 api/v1alpha8/identity_types.go
create mode 100644 api/v1alpha8/openstackcluster_types.go
rename api/{v1alpha7 => v1alpha8}/openstackcluster_webhook.go (95%)
rename api/{v1alpha7 => v1alpha8}/openstackcluster_webhook_test.go (99%)
rename api/{v1alpha7 => v1alpha8}/openstackclusterlist_webhook.go (98%)
create mode 100644 api/v1alpha8/openstackclustertemplate_types.go
rename api/{v1alpha7 => v1alpha8}/openstackclustertemplate_webhook.go (92%)
create mode 100644 api/v1alpha8/openstackmachine_types.go
rename api/{v1alpha7 => v1alpha8}/openstackmachine_webhook.go (94%)
rename api/{v1alpha7 => v1alpha8}/openstackmachinelist_webhook.go (98%)
create mode 100644 api/v1alpha8/openstackmachinetemplate_types.go
rename api/{v1alpha7 => v1alpha8}/openstackmachinetemplate_webhook.go (96%)
rename api/{v1alpha7 => v1alpha8}/openstackmachinetemplate_webhook_test.go (99%)
rename api/{v1alpha7 => v1alpha8}/openstackmachinetemplatelist_webhook.go (98%)
create mode 100644 api/v1alpha8/types.go
rename api/{v1alpha7 => v1alpha8}/webhooks.go (98%)
create mode 100644 api/v1alpha8/zz_generated.deepcopy.go
create mode 100644 kustomize/v1alpha8/default/cluster-template.yaml
create mode 100644 kustomize/v1alpha8/default/kustomization.yaml
create mode 100644 kustomize/v1alpha8/flatcar/kustomization.yaml
create mode 100644 kustomize/v1alpha8/flatcar/patch-flatcar.yaml
create mode 100644 kustomize/v1alpha8/without-lb/kustomization.yaml
create mode 100644 kustomize/v1alpha8/without-lb/patch-without-lb.yaml
create mode 100644 test/e2e/data/kustomize/v1alpha7/kustomization.yaml
diff --git a/.golangci.yml b/.golangci.yml
index dd62b87cb9..3bc8da3e48 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/v1alpha8
alias: infrav1
- pkg: sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/errors
alias: capoerrors
diff --git a/Makefile b/Makefile
index de21f50095..4ecf6aaccf 100644
--- a/Makefile
+++ b/Makefile
@@ -150,6 +150,7 @@ 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 \
@@ -258,6 +259,7 @@ generate-go: $(MOCKGEN)
--input-dirs=./api/v1alpha5 \
--input-dirs=./api/v1alpha6 \
--input-dirs=./api/v1alpha7 \
+ --input-dirs=./api/v1alpha8 \
--output-file-base=zz_generated.conversion \
--go-header-file=./hack/boilerplate/boilerplate.generatego.txt
go generate ./...
@@ -406,10 +408,10 @@ templates: templates/cluster-template.yaml \
templates/cluster-template-without-lb.yaml \
templates/cluster-template-flatcar.yaml
-templates/cluster-template.yaml: kustomize/v1alpha7/default $(KUSTOMIZE) FORCE
+templates/cluster-template.yaml: kustomize/v1alpha8/default $(KUSTOMIZE) FORCE
$(KUSTOMIZE) build "$<" > "$@"
-templates/cluster-template-%.yaml: kustomize/v1alpha7/% $(KUSTOMIZE) FORCE
+templates/cluster-template-%.yaml: kustomize/v1alpha8/% $(KUSTOMIZE) FORCE
$(KUSTOMIZE) build "$<" > "$@"
.PHONY: release-templates
diff --git a/PROJECT b/PROJECT
index 6544f82880..7874bda38c 100644
--- a/PROJECT
+++ b/PROJECT
@@ -38,3 +38,15 @@ resources:
- group: infrastructure
kind: OpenStackClusterTemplate
version: v1alpha7
+- group: infrastructure
+ version: v1alpha8
+ kind: OpenStackCluster
+- group: infrastructure
+ version: v1alpha8
+ kind: OpenStackMachine
+- group: infrastructure
+ version: v1alpha8
+ kind: OpenStackMachineTemplate
+- group: infrastructure
+ kind: OpenStackClusterTemplate
+ version: v1alpha8
diff --git a/README.md b/README.md
index b683047e91..d2ccc9f6ad 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 v1alpha8 | ✓ |
This provider's versions are able to install and manage the following versions of Kubernetes:
@@ -52,7 +53,8 @@ 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 v1alpha8 | + | ✓ | ✓ | ★ |
This provider's versions are able to install Kubernetes to the following versions of OpenStack:
@@ -60,7 +62,8 @@ This provider's versions are able to install Kubernetes to the following version
|------------------------------------| ------ | ----- | ----- | ----- | ------ | -------- | ------- | ---- | ---- |
| OpenStack Provider v1alpha5 (v0.6) | + | + | + | + | + | ✓ | ✓ | ✓ | ★ |
| OpenStack Provider v1alpha6 (v0.7) | + | + | + | + | + | ✓ | ✓ | ✓ | ★ |
-| OpenStack Provider v1alpha7 | | + | + | + | + | ✓ | ✓ | ✓ | ★ |
+| OpenStack Provider v1alpha7 (v0.9) | | + | + | + | + | ✓ | ✓ | ✓ | ★ |
+| OpenStack Provider v1alpha8 | | + | + | + | + | ✓ | ✓ | ✓ | ★ |
Test status:
diff --git a/api/v1alpha5/conversion.go b/api/v1alpha5/conversion.go
index 3f41962b92..77e39fa2eb 100644
--- a/api/v1alpha5/conversion.go
+++ b/api/v1alpha5/conversion.go
@@ -23,7 +23,7 @@ import (
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/v1alpha8"
)
var _ ctrlconversion.Convertible = &OpenStackCluster{}
@@ -33,7 +33,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_v1alpha8_OpenStackCluster(r, dst, nil); err != nil {
return err
}
@@ -49,7 +49,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_v1alpha8_OpenStackCluster_To_v1alpha5_OpenStackCluster(src, r, nil); err != nil {
return err
}
@@ -62,13 +62,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_v1alpha8_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_v1alpha8_OpenStackClusterList_To_v1alpha5_OpenStackClusterList(src, r, nil)
}
var _ ctrlconversion.Convertible = &OpenStackClusterTemplate{}
@@ -76,7 +76,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_v1alpha8_OpenStackClusterTemplate(r, dst, nil); err != nil {
return err
}
@@ -92,7 +92,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_v1alpha8_OpenStackClusterTemplate_To_v1alpha5_OpenStackClusterTemplate(src, r, nil); err != nil {
return err
}
@@ -105,7 +105,7 @@ 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_v1alpha8_OpenStackMachine(r, dst, nil); err != nil {
return err
}
@@ -121,7 +121,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_v1alpha8_OpenStackMachine_To_v1alpha5_OpenStackMachine(src, r, nil); err != nil {
return err
}
@@ -134,13 +134,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_v1alpha8_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_v1alpha8_OpenStackMachineList_To_v1alpha5_OpenStackMachineList(src, r, nil)
}
var _ ctrlconversion.Convertible = &OpenStackMachineTemplate{}
@@ -148,7 +148,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_v1alpha8_OpenStackMachineTemplate(r, dst, nil); err != nil {
return err
}
@@ -164,7 +164,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_v1alpha8_OpenStackMachineTemplate_To_v1alpha5_OpenStackMachineTemplate(src, r, nil); err != nil {
return err
}
@@ -177,27 +177,27 @@ 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_v1alpha8_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_v1alpha8_OpenStackMachineTemplateList_To_v1alpha5_OpenStackMachineTemplateList(src, r, nil)
}
-func Convert_v1alpha7_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(in *infrav1.OpenStackClusterSpec, out *OpenStackClusterSpec, s conversion.Scope) error {
+func Convert_v1alpha8_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)
+ return autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(in, out, s)
}
-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_v1alpha8_LoadBalancer_To_v1alpha5_LoadBalancer(in *infrav1.LoadBalancer, out *LoadBalancer, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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_v1alpha8_PortOpts_To_v1alpha5_PortOpts(in *infrav1.PortOpts, out *PortOpts, s conversion.Scope) error {
+ // value specs and propagate uplink status have been added in v1alpha8 but have no equivalent in v1alpha5
+ err := autoConvert_v1alpha8_PortOpts_To_v1alpha5_PortOpts(in, out, s)
if err != nil {
return err
}
@@ -212,23 +212,23 @@ func Convert_v1alpha7_PortOpts_To_v1alpha5_PortOpts(in *infrav1.PortOpts, out *P
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_v1alpha8_OpenStackMachineSpec(in *OpenStackMachineSpec, out *infrav1.OpenStackMachineSpec, s conversion.Scope) error {
+ return autoConvert_v1alpha5_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(in, out, s)
}
-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_v1alpha8_APIServerLoadBalancer_To_v1alpha5_APIServerLoadBalancer(in *infrav1.APIServerLoadBalancer, out *APIServerLoadBalancer, s conversion.Scope) error {
+ // Provider was originally added in v1alpha8, but was backported to v1alpha6, but has no equivalent in v1alpha5
+ return autoConvert_v1alpha8_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_v1alpha8_PortOpts(in *PortOpts, out *infrav1.PortOpts, s conversion.Scope) error {
+ // SecurityGroups have been removed in v1alpha8.
+ err := autoConvert_v1alpha5_PortOpts_To_v1alpha8_PortOpts(in, out, s)
if err != nil {
return err
}
- // Profile is now a struct in v1alpha7.
+ // Profile is now a struct in v1alpha8.
if strings.Contains(in.Profile["capabilities"], "switchdev") {
out.Profile.OVSHWOffload = true
}
@@ -238,7 +238,7 @@ func Convert_v1alpha5_PortOpts_To_v1alpha7_PortOpts(in *PortOpts, out *infrav1.P
return nil
}
-func Convert_v1alpha5_Instance_To_v1alpha7_BastionStatus(in *Instance, out *infrav1.BastionStatus, _ conversion.Scope) error {
+func Convert_v1alpha5_Instance_To_v1alpha8_BastionStatus(in *Instance, out *infrav1.BastionStatus, _ conversion.Scope) error {
// BastionStatus is the same as Instance with unused fields removed
out.ID = in.ID
out.Name = in.Name
@@ -249,7 +249,7 @@ func Convert_v1alpha5_Instance_To_v1alpha7_BastionStatus(in *Instance, out *infr
return nil
}
-func Convert_v1alpha7_BastionStatus_To_v1alpha5_Instance(in *infrav1.BastionStatus, out *Instance, _ conversion.Scope) error {
+func Convert_v1alpha8_BastionStatus_To_v1alpha5_Instance(in *infrav1.BastionStatus, out *Instance, _ conversion.Scope) error {
// BastionStatus is the same as Instance with unused fields removed
out.ID = in.ID
out.Name = in.Name
@@ -260,9 +260,9 @@ func Convert_v1alpha7_BastionStatus_To_v1alpha5_Instance(in *infrav1.BastionStat
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_v1alpha8_NetworkStatusWithSubnets(in *Network, out *infrav1.NetworkStatusWithSubnets, s conversion.Scope) error {
+ // PortOpts has been removed in v1alpha8
+ err := Convert_v1alpha5_Network_To_v1alpha8_NetworkStatus(in, &out.NetworkStatus, s)
if err != nil {
return err
}
@@ -273,9 +273,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_v1alpha8_NetworkStatusWithSubnets_To_v1alpha5_Network(in *infrav1.NetworkStatusWithSubnets, out *Network, s conversion.Scope) error {
+ // PortOpts has been removed in v1alpha8
+ err := Convert_v1alpha8_NetworkStatus_To_v1alpha5_Network(&in.NetworkStatus, out, s)
if err != nil {
return err
}
@@ -287,7 +287,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_v1alpha8_NetworkStatus(in *Network, out *infrav1.NetworkStatus, _ conversion.Scope) error {
out.ID = in.ID
out.Name = in.Name
out.Tags = in.Tags
@@ -295,7 +295,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_v1alpha8_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,13 +303,13 @@ 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)
+func Convert_v1alpha5_SecurityGroupFilter_To_v1alpha8_SecurityGroupFilter(in *SecurityGroupFilter, out *infrav1.SecurityGroupFilter, s conversion.Scope) error {
+ err := autoConvert_v1alpha5_SecurityGroupFilter_To_v1alpha8_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.
+ // TenantID has been removed in v1alpha8. Write it to ProjectID if ProjectID is not already set.
if out.ProjectID == "" {
out.ProjectID = in.TenantID
}
@@ -317,9 +317,9 @@ func Convert_v1alpha5_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in *Se
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)
+func Convert_v1alpha5_SecurityGroupParam_To_v1alpha8_SecurityGroupFilter(in *SecurityGroupParam, out *infrav1.SecurityGroupFilter, s conversion.Scope) error {
+ // SecurityGroupParam is replaced by its contained SecurityGroupFilter in v1alpha8
+ err := Convert_v1alpha5_SecurityGroupFilter_To_v1alpha8_SecurityGroupFilter(&in.Filter, out, s)
if err != nil {
return err
}
@@ -333,9 +333,9 @@ func Convert_v1alpha5_SecurityGroupParam_To_v1alpha7_SecurityGroupFilter(in *Sec
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)
+func Convert_v1alpha8_SecurityGroupFilter_To_v1alpha5_SecurityGroupParam(in *infrav1.SecurityGroupFilter, out *SecurityGroupParam, s conversion.Scope) error {
+ // SecurityGroupParam is replaced by its contained SecurityGroupFilter in v1alpha8
+ err := Convert_v1alpha8_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(in, &out.Filter, s)
if err != nil {
return err
}
@@ -349,7 +349,7 @@ func Convert_v1alpha7_SecurityGroupFilter_To_v1alpha5_SecurityGroupParam(in *inf
return nil
}
-func Convert_v1alpha5_SubnetParam_To_v1alpha7_SubnetFilter(in *SubnetParam, out *infrav1.SubnetFilter, _ conversion.Scope) error {
+func Convert_v1alpha5_SubnetParam_To_v1alpha8_SubnetFilter(in *SubnetParam, out *infrav1.SubnetFilter, _ conversion.Scope) error {
*out = infrav1.SubnetFilter(in.Filter)
if in.UUID != "" {
out.ID = in.UUID
@@ -357,14 +357,14 @@ func Convert_v1alpha5_SubnetParam_To_v1alpha7_SubnetFilter(in *SubnetParam, out
return nil
}
-func Convert_v1alpha7_SubnetFilter_To_v1alpha5_SubnetParam(in *infrav1.SubnetFilter, out *SubnetParam, _ conversion.Scope) error {
+func Convert_v1alpha8_SubnetFilter_To_v1alpha5_SubnetParam(in *infrav1.SubnetFilter, out *SubnetParam, _ conversion.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, _ conversion.Scope) error {
+func Convert_Map_string_To_Interface_To_v1alpha8_BindingProfile(in map[string]string, out *infrav1.BindingProfile, _ conversion.Scope) error {
for k, v := range in {
if k == "capabilities" {
if strings.Contains(v, "switchdev") {
@@ -378,7 +378,7 @@ func Convert_Map_string_To_Interface_To_v1alpha7_BindingProfile(in map[string]st
return nil
}
-func Convert_v1alpha7_BindingProfile_To_Map_string_To_Interface(in *infrav1.BindingProfile, out map[string]string, _ conversion.Scope) error {
+func Convert_v1alpha8_BindingProfile_To_Map_string_To_Interface(in *infrav1.BindingProfile, out map[string]string, _ conversion.Scope) error {
if in.OVSHWOffload {
(out)["capabilities"] = "[\"switchdev\"]"
}
@@ -388,13 +388,13 @@ func Convert_v1alpha7_BindingProfile_To_Map_string_To_Interface(in *infrav1.Bind
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_v1alpha8_OpenStackClusterStatus_To_v1alpha5_OpenStackClusterStatus(in *infrav1.OpenStackClusterStatus, out *OpenStackClusterStatus, s conversion.Scope) error {
+ err := autoConvert_v1alpha8_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 v1alpha8
if in.Router != nil || in.APIServerLoadBalancer != nil {
if out.Network == nil {
out.Network = &Network{}
@@ -403,7 +403,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_v1alpha8_LoadBalancer_To_v1alpha5_LoadBalancer(in.APIServerLoadBalancer, out.Network.APIServerLoadBalancer, s)
if err != nil {
return err
}
@@ -413,18 +413,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_v1alpha8_OpenStackClusterStatus(in *OpenStackClusterStatus, out *infrav1.OpenStackClusterStatus, s conversion.Scope) error {
+ err := autoConvert_v1alpha5_OpenStackClusterStatus_To_v1alpha8_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 v1alpha8
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_v1alpha8_LoadBalancer(in.Network.APIServerLoadBalancer, out.APIServerLoadBalancer, s)
if err != nil {
return err
}
@@ -434,6 +434,6 @@ 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_v1alpha8_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(in *infrav1.OpenStackMachineSpec, out *OpenStackMachineSpec, s conversion.Scope) error {
+ return autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(in, out, s)
}
diff --git a/api/v1alpha5/conversion_test.go b/api/v1alpha5/conversion_test.go
index a7bfef2841..95f83052dd 100644
--- a/api/v1alpha5/conversion_test.go
+++ b/api/v1alpha5/conversion_test.go
@@ -24,7 +24,7 @@ import (
runtime "k8s.io/apimachinery/pkg/runtime"
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/v1alpha8"
)
func TestConvertFrom(t *testing.T) {
diff --git a/api/v1alpha5/doc.go b/api/v1alpha5/doc.go
index 3793105e75..ad0e9949b2 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/v1alpha8
package v1alpha5
diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go
index 52681a9c65..5ef62e512e 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.
@@ -27,7 +27,7 @@ import (
v1 "k8s.io/api/core/v1"
conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime"
- v1alpha7 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
+ v1alpha8 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
v1beta1 "sigs.k8s.io/cluster-api/api/v1beta1"
errors "sigs.k8s.io/cluster-api/errors"
)
@@ -39,392 +39,392 @@ 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), (*v1alpha8.APIServerLoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalancer(a.(*APIServerLoadBalancer), b.(*v1alpha8.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), (*v1alpha8.AddressPair)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_AddressPair_To_v1alpha8_AddressPair(a.(*AddressPair), b.(*v1alpha8.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((*v1alpha8.AddressPair)(nil), (*AddressPair)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_AddressPair_To_v1alpha5_AddressPair(a.(*v1alpha8.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((*Bastion)(nil), (*v1alpha8.Bastion)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_Bastion_To_v1alpha8_Bastion(a.(*Bastion), b.(*v1alpha8.Bastion), 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((*v1alpha8.Bastion)(nil), (*Bastion)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_Bastion_To_v1alpha5_Bastion(a.(*v1alpha8.Bastion), b.(*Bastion), 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((*ExternalRouterIPParam)(nil), (*v1alpha8.ExternalRouterIPParam)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_ExternalRouterIPParam_To_v1alpha8_ExternalRouterIPParam(a.(*ExternalRouterIPParam), b.(*v1alpha8.ExternalRouterIPParam), 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((*v1alpha8.ExternalRouterIPParam)(nil), (*ExternalRouterIPParam)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_ExternalRouterIPParam_To_v1alpha5_ExternalRouterIPParam(a.(*v1alpha8.ExternalRouterIPParam), b.(*ExternalRouterIPParam), 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((*FixedIP)(nil), (*v1alpha8.FixedIP)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_FixedIP_To_v1alpha8_FixedIP(a.(*FixedIP), b.(*v1alpha8.FixedIP), 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((*v1alpha8.FixedIP)(nil), (*FixedIP)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_FixedIP_To_v1alpha5_FixedIP(a.(*v1alpha8.FixedIP), b.(*FixedIP), 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((*LoadBalancer)(nil), (*v1alpha8.LoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_LoadBalancer_To_v1alpha8_LoadBalancer(a.(*LoadBalancer), b.(*v1alpha8.LoadBalancer), 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((*NetworkFilter)(nil), (*v1alpha8.NetworkFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_NetworkFilter_To_v1alpha8_NetworkFilter(a.(*NetworkFilter), b.(*v1alpha8.NetworkFilter), 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((*v1alpha8.NetworkFilter)(nil), (*NetworkFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_NetworkFilter_To_v1alpha5_NetworkFilter(a.(*v1alpha8.NetworkFilter), b.(*NetworkFilter), 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((*OpenStackCluster)(nil), (*v1alpha8.OpenStackCluster)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_OpenStackCluster_To_v1alpha8_OpenStackCluster(a.(*OpenStackCluster), b.(*v1alpha8.OpenStackCluster), 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((*v1alpha8.OpenStackCluster)(nil), (*OpenStackCluster)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackCluster_To_v1alpha5_OpenStackCluster(a.(*v1alpha8.OpenStackCluster), b.(*OpenStackCluster), 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((*OpenStackClusterList)(nil), (*v1alpha8.OpenStackClusterList)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_OpenStackClusterList_To_v1alpha8_OpenStackClusterList(a.(*OpenStackClusterList), b.(*v1alpha8.OpenStackClusterList), 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((*v1alpha8.OpenStackClusterList)(nil), (*OpenStackClusterList)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackClusterList_To_v1alpha5_OpenStackClusterList(a.(*v1alpha8.OpenStackClusterList), b.(*OpenStackClusterList), 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((*OpenStackClusterSpec)(nil), (*v1alpha8.OpenStackClusterSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(a.(*OpenStackClusterSpec), b.(*v1alpha8.OpenStackClusterSpec), 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((*OpenStackClusterTemplate)(nil), (*v1alpha8.OpenStackClusterTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate(a.(*OpenStackClusterTemplate), b.(*v1alpha8.OpenStackClusterTemplate), 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((*v1alpha8.OpenStackClusterTemplate)(nil), (*OpenStackClusterTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackClusterTemplate_To_v1alpha5_OpenStackClusterTemplate(a.(*v1alpha8.OpenStackClusterTemplate), b.(*OpenStackClusterTemplate), 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((*OpenStackClusterTemplateList)(nil), (*v1alpha8.OpenStackClusterTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_OpenStackClusterTemplateList_To_v1alpha8_OpenStackClusterTemplateList(a.(*OpenStackClusterTemplateList), b.(*v1alpha8.OpenStackClusterTemplateList), 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((*v1alpha8.OpenStackClusterTemplateList)(nil), (*OpenStackClusterTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackClusterTemplateList_To_v1alpha5_OpenStackClusterTemplateList(a.(*v1alpha8.OpenStackClusterTemplateList), b.(*OpenStackClusterTemplateList), 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((*OpenStackClusterTemplateResource)(nil), (*v1alpha8.OpenStackClusterTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_OpenStackClusterTemplateResource_To_v1alpha8_OpenStackClusterTemplateResource(a.(*OpenStackClusterTemplateResource), b.(*v1alpha8.OpenStackClusterTemplateResource), 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((*v1alpha8.OpenStackClusterTemplateResource)(nil), (*OpenStackClusterTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackClusterTemplateResource_To_v1alpha5_OpenStackClusterTemplateResource(a.(*v1alpha8.OpenStackClusterTemplateResource), b.(*OpenStackClusterTemplateResource), 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((*OpenStackClusterTemplateSpec)(nil), (*v1alpha8.OpenStackClusterTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_OpenStackClusterTemplateSpec_To_v1alpha8_OpenStackClusterTemplateSpec(a.(*OpenStackClusterTemplateSpec), b.(*v1alpha8.OpenStackClusterTemplateSpec), 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((*v1alpha8.OpenStackClusterTemplateSpec)(nil), (*OpenStackClusterTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackClusterTemplateSpec_To_v1alpha5_OpenStackClusterTemplateSpec(a.(*v1alpha8.OpenStackClusterTemplateSpec), b.(*OpenStackClusterTemplateSpec), 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((*OpenStackIdentityReference)(nil), (*v1alpha8.OpenStackIdentityReference)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(a.(*OpenStackIdentityReference), b.(*v1alpha8.OpenStackIdentityReference), 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((*v1alpha8.OpenStackIdentityReference)(nil), (*OpenStackIdentityReference)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackIdentityReference_To_v1alpha5_OpenStackIdentityReference(a.(*v1alpha8.OpenStackIdentityReference), b.(*OpenStackIdentityReference), 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((*OpenStackMachine)(nil), (*v1alpha8.OpenStackMachine)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_OpenStackMachine_To_v1alpha8_OpenStackMachine(a.(*OpenStackMachine), b.(*v1alpha8.OpenStackMachine), 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((*v1alpha8.OpenStackMachine)(nil), (*OpenStackMachine)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackMachine_To_v1alpha5_OpenStackMachine(a.(*v1alpha8.OpenStackMachine), b.(*OpenStackMachine), 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((*OpenStackMachineList)(nil), (*v1alpha8.OpenStackMachineList)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_OpenStackMachineList_To_v1alpha8_OpenStackMachineList(a.(*OpenStackMachineList), b.(*v1alpha8.OpenStackMachineList), 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((*v1alpha8.OpenStackMachineList)(nil), (*OpenStackMachineList)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackMachineList_To_v1alpha5_OpenStackMachineList(a.(*v1alpha8.OpenStackMachineList), b.(*OpenStackMachineList), 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((*OpenStackMachineStatus)(nil), (*v1alpha8.OpenStackMachineStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_OpenStackMachineStatus_To_v1alpha8_OpenStackMachineStatus(a.(*OpenStackMachineStatus), b.(*v1alpha8.OpenStackMachineStatus), 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((*v1alpha8.OpenStackMachineStatus)(nil), (*OpenStackMachineStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineStatus(a.(*v1alpha8.OpenStackMachineStatus), b.(*OpenStackMachineStatus), 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((*OpenStackMachineTemplate)(nil), (*v1alpha8.OpenStackMachineTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate(a.(*OpenStackMachineTemplate), b.(*v1alpha8.OpenStackMachineTemplate), 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((*v1alpha8.OpenStackMachineTemplate)(nil), (*OpenStackMachineTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackMachineTemplate_To_v1alpha5_OpenStackMachineTemplate(a.(*v1alpha8.OpenStackMachineTemplate), b.(*OpenStackMachineTemplate), 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((*OpenStackMachineTemplateList)(nil), (*v1alpha8.OpenStackMachineTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_OpenStackMachineTemplateList_To_v1alpha8_OpenStackMachineTemplateList(a.(*OpenStackMachineTemplateList), b.(*v1alpha8.OpenStackMachineTemplateList), 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((*v1alpha8.OpenStackMachineTemplateList)(nil), (*OpenStackMachineTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackMachineTemplateList_To_v1alpha5_OpenStackMachineTemplateList(a.(*v1alpha8.OpenStackMachineTemplateList), b.(*OpenStackMachineTemplateList), 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.AddGeneratedConversionFunc((*OpenStackMachineTemplateResource)(nil), (*v1alpha8.OpenStackMachineTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_OpenStackMachineTemplateResource_To_v1alpha8_OpenStackMachineTemplateResource(a.(*OpenStackMachineTemplateResource), b.(*v1alpha8.OpenStackMachineTemplateResource), 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.AddGeneratedConversionFunc((*v1alpha8.OpenStackMachineTemplateResource)(nil), (*OpenStackMachineTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackMachineTemplateResource_To_v1alpha5_OpenStackMachineTemplateResource(a.(*v1alpha8.OpenStackMachineTemplateResource), b.(*OpenStackMachineTemplateResource), 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.AddGeneratedConversionFunc((*OpenStackMachineTemplateSpec)(nil), (*v1alpha8.OpenStackMachineTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_OpenStackMachineTemplateSpec_To_v1alpha8_OpenStackMachineTemplateSpec(a.(*OpenStackMachineTemplateSpec), b.(*v1alpha8.OpenStackMachineTemplateSpec), 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.AddGeneratedConversionFunc((*v1alpha8.OpenStackMachineTemplateSpec)(nil), (*OpenStackMachineTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackMachineTemplateSpec_To_v1alpha5_OpenStackMachineTemplateSpec(a.(*v1alpha8.OpenStackMachineTemplateSpec), b.(*OpenStackMachineTemplateSpec), 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.AddGeneratedConversionFunc((*RootVolume)(nil), (*v1alpha8.RootVolume)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_RootVolume_To_v1alpha8_RootVolume(a.(*RootVolume), b.(*v1alpha8.RootVolume), 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.AddGeneratedConversionFunc((*v1alpha8.RootVolume)(nil), (*RootVolume)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_RootVolume_To_v1alpha5_RootVolume(a.(*v1alpha8.RootVolume), b.(*RootVolume), 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.AddGeneratedConversionFunc((*Router)(nil), (*v1alpha8.Router)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_Router_To_v1alpha8_Router(a.(*Router), b.(*v1alpha8.Router), 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.AddGeneratedConversionFunc((*v1alpha8.Router)(nil), (*Router)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_Router_To_v1alpha5_Router(a.(*v1alpha8.Router), b.(*Router), 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.AddGeneratedConversionFunc((*SecurityGroup)(nil), (*v1alpha8.SecurityGroup)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_SecurityGroup_To_v1alpha8_SecurityGroup(a.(*SecurityGroup), b.(*v1alpha8.SecurityGroup), 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.AddGeneratedConversionFunc((*v1alpha8.SecurityGroup)(nil), (*SecurityGroup)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_SecurityGroup_To_v1alpha5_SecurityGroup(a.(*v1alpha8.SecurityGroup), b.(*SecurityGroup), 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.AddGeneratedConversionFunc((*v1alpha8.SecurityGroupFilter)(nil), (*SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(a.(*v1alpha8.SecurityGroupFilter), b.(*SecurityGroupFilter), 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.AddGeneratedConversionFunc((*SecurityGroupRule)(nil), (*v1alpha8.SecurityGroupRule)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_SecurityGroupRule_To_v1alpha8_SecurityGroupRule(a.(*SecurityGroupRule), b.(*v1alpha8.SecurityGroupRule), 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.AddGeneratedConversionFunc((*v1alpha8.SecurityGroupRule)(nil), (*SecurityGroupRule)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_SecurityGroupRule_To_v1alpha5_SecurityGroupRule(a.(*v1alpha8.SecurityGroupRule), b.(*SecurityGroupRule), 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.AddGeneratedConversionFunc((*Subnet)(nil), (*v1alpha8.Subnet)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_Subnet_To_v1alpha8_Subnet(a.(*Subnet), b.(*v1alpha8.Subnet), 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.AddGeneratedConversionFunc((*v1alpha8.Subnet)(nil), (*Subnet)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_Subnet_To_v1alpha5_Subnet(a.(*v1alpha8.Subnet), b.(*Subnet), 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.AddGeneratedConversionFunc((*SubnetFilter)(nil), (*v1alpha8.SubnetFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_SubnetFilter_To_v1alpha8_SubnetFilter(a.(*SubnetFilter), b.(*v1alpha8.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_v1alpha5_SubnetFilter(a.(*v1alpha7.SubnetFilter), b.(*SubnetFilter), scope)
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.SubnetFilter)(nil), (*SubnetFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_SubnetFilter_To_v1alpha5_SubnetFilter(a.(*v1alpha8.SubnetFilter), b.(*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((*Instance)(nil), (*v1alpha8.BastionStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_Instance_To_v1alpha8_BastionStatus(a.(*Instance), b.(*v1alpha8.BastionStatus), 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((*Network)(nil), (*v1alpha8.NetworkStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_Network_To_v1alpha8_NetworkStatus(a.(*Network), b.(*v1alpha8.NetworkStatus), 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((*Network)(nil), (*v1alpha8.NetworkStatusWithSubnets)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_Network_To_v1alpha8_NetworkStatusWithSubnets(a.(*Network), b.(*v1alpha8.NetworkStatusWithSubnets), 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((*OpenStackClusterStatus)(nil), (*v1alpha8.OpenStackClusterStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterStatus(a.(*OpenStackClusterStatus), b.(*v1alpha8.OpenStackClusterStatus), 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((*OpenStackMachineSpec)(nil), (*v1alpha8.OpenStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(a.(*OpenStackMachineSpec), b.(*v1alpha8.OpenStackMachineSpec), 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((*PortOpts)(nil), (*v1alpha8.PortOpts)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_PortOpts_To_v1alpha8_PortOpts(a.(*PortOpts), b.(*v1alpha8.PortOpts), 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((*SecurityGroupFilter)(nil), (*v1alpha8.SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_SecurityGroupFilter_To_v1alpha8_SecurityGroupFilter(a.(*SecurityGroupFilter), b.(*v1alpha8.SecurityGroupFilter), 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((*SecurityGroupParam)(nil), (*v1alpha8.SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_SecurityGroupParam_To_v1alpha8_SecurityGroupFilter(a.(*SecurityGroupParam), b.(*v1alpha8.SecurityGroupFilter), 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((*SubnetParam)(nil), (*v1alpha8.SubnetFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_SubnetParam_To_v1alpha8_SubnetFilter(a.(*SubnetParam), b.(*v1alpha8.SubnetFilter), 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((*v1alpha8.APIServerLoadBalancer)(nil), (*APIServerLoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_APIServerLoadBalancer_To_v1alpha5_APIServerLoadBalancer(a.(*v1alpha8.APIServerLoadBalancer), b.(*APIServerLoadBalancer), 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((*v1alpha8.BastionStatus)(nil), (*Instance)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_BastionStatus_To_v1alpha5_Instance(a.(*v1alpha8.BastionStatus), b.(*Instance), 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((*v1alpha8.LoadBalancer)(nil), (*LoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_LoadBalancer_To_v1alpha5_LoadBalancer(a.(*v1alpha8.LoadBalancer), b.(*LoadBalancer), 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((*v1alpha8.NetworkStatusWithSubnets)(nil), (*Network)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_NetworkStatusWithSubnets_To_v1alpha5_Network(a.(*v1alpha8.NetworkStatusWithSubnets), b.(*Network), 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((*v1alpha8.NetworkStatus)(nil), (*Network)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_NetworkStatus_To_v1alpha5_Network(a.(*v1alpha8.NetworkStatus), b.(*Network), 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((*v1alpha8.OpenStackClusterSpec)(nil), (*OpenStackClusterSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(a.(*v1alpha8.OpenStackClusterSpec), b.(*OpenStackClusterSpec), 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((*v1alpha8.OpenStackClusterStatus)(nil), (*OpenStackClusterStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackClusterStatus_To_v1alpha5_OpenStackClusterStatus(a.(*v1alpha8.OpenStackClusterStatus), b.(*OpenStackClusterStatus), 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((*v1alpha8.OpenStackMachineSpec)(nil), (*OpenStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(a.(*v1alpha8.OpenStackMachineSpec), b.(*OpenStackMachineSpec), 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((*v1alpha8.PortOpts)(nil), (*PortOpts)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_PortOpts_To_v1alpha5_PortOpts(a.(*v1alpha8.PortOpts), b.(*PortOpts), 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((*v1alpha8.SecurityGroupFilter)(nil), (*SecurityGroupParam)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_SecurityGroupFilter_To_v1alpha5_SecurityGroupParam(a.(*v1alpha8.SecurityGroupFilter), b.(*SecurityGroupParam), 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((*v1alpha8.SubnetFilter)(nil), (*SubnetParam)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_SubnetFilter_To_v1alpha5_SubnetParam(a.(*v1alpha8.SubnetFilter), 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 {
+func autoConvert_v1alpha5_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalancer(in *APIServerLoadBalancer, out *v1alpha8.APIServerLoadBalancer, s conversion.Scope) error {
out.Enabled = in.Enabled
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_v1alpha8_APIServerLoadBalancer is an autogenerated conversion function.
+func Convert_v1alpha5_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalancer(in *APIServerLoadBalancer, out *v1alpha8.APIServerLoadBalancer, s conversion.Scope) error {
+ return autoConvert_v1alpha5_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalancer(in, out, s)
}
-func autoConvert_v1alpha7_APIServerLoadBalancer_To_v1alpha5_APIServerLoadBalancer(in *v1alpha7.APIServerLoadBalancer, out *APIServerLoadBalancer, s conversion.Scope) error {
+func autoConvert_v1alpha8_APIServerLoadBalancer_To_v1alpha5_APIServerLoadBalancer(in *v1alpha8.APIServerLoadBalancer, out *APIServerLoadBalancer, s conversion.Scope) error {
out.Enabled = in.Enabled
out.AdditionalPorts = *(*[]int)(unsafe.Pointer(&in.AdditionalPorts))
out.AllowedCIDRs = *(*[]string)(unsafe.Pointer(&in.AllowedCIDRs))
@@ -432,105 +432,105 @@ func autoConvert_v1alpha7_APIServerLoadBalancer_To_v1alpha5_APIServerLoadBalance
return nil
}
-func autoConvert_v1alpha5_AddressPair_To_v1alpha7_AddressPair(in *AddressPair, out *v1alpha7.AddressPair, s conversion.Scope) error {
+func autoConvert_v1alpha5_AddressPair_To_v1alpha8_AddressPair(in *AddressPair, out *v1alpha8.AddressPair, s conversion.Scope) error {
out.IPAddress = in.IPAddress
out.MACAddress = in.MACAddress
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_v1alpha8_AddressPair is an autogenerated conversion function.
+func Convert_v1alpha5_AddressPair_To_v1alpha8_AddressPair(in *AddressPair, out *v1alpha8.AddressPair, s conversion.Scope) error {
+ return autoConvert_v1alpha5_AddressPair_To_v1alpha8_AddressPair(in, out, s)
}
-func autoConvert_v1alpha7_AddressPair_To_v1alpha5_AddressPair(in *v1alpha7.AddressPair, out *AddressPair, s conversion.Scope) error {
+func autoConvert_v1alpha8_AddressPair_To_v1alpha5_AddressPair(in *v1alpha8.AddressPair, out *AddressPair, s conversion.Scope) error {
out.IPAddress = in.IPAddress
out.MACAddress = in.MACAddress
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_v1alpha8_AddressPair_To_v1alpha5_AddressPair is an autogenerated conversion function.
+func Convert_v1alpha8_AddressPair_To_v1alpha5_AddressPair(in *v1alpha8.AddressPair, out *AddressPair, s conversion.Scope) error {
+ return autoConvert_v1alpha8_AddressPair_To_v1alpha5_AddressPair(in, out, s)
}
-func autoConvert_v1alpha5_Bastion_To_v1alpha7_Bastion(in *Bastion, out *v1alpha7.Bastion, s conversion.Scope) error {
+func autoConvert_v1alpha5_Bastion_To_v1alpha8_Bastion(in *Bastion, out *v1alpha8.Bastion, s conversion.Scope) error {
out.Enabled = in.Enabled
- if err := Convert_v1alpha5_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(&in.Instance, &out.Instance, s); err != nil {
+ if err := Convert_v1alpha5_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(&in.Instance, &out.Instance, 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)
+// Convert_v1alpha5_Bastion_To_v1alpha8_Bastion is an autogenerated conversion function.
+func Convert_v1alpha5_Bastion_To_v1alpha8_Bastion(in *Bastion, out *v1alpha8.Bastion, s conversion.Scope) error {
+ return autoConvert_v1alpha5_Bastion_To_v1alpha8_Bastion(in, out, s)
}
-func autoConvert_v1alpha7_Bastion_To_v1alpha5_Bastion(in *v1alpha7.Bastion, out *Bastion, s conversion.Scope) error {
+func autoConvert_v1alpha8_Bastion_To_v1alpha5_Bastion(in *v1alpha8.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 {
+ if err := Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(&in.Instance, &out.Instance, s); err != nil {
return err
}
out.AvailabilityZone = in.AvailabilityZone
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)
+// Convert_v1alpha8_Bastion_To_v1alpha5_Bastion is an autogenerated conversion function.
+func Convert_v1alpha8_Bastion_To_v1alpha5_Bastion(in *v1alpha8.Bastion, out *Bastion, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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_v1alpha8_ExternalRouterIPParam(in *ExternalRouterIPParam, out *v1alpha8.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_v1alpha8_SubnetFilter(&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_v1alpha8_ExternalRouterIPParam is an autogenerated conversion function.
+func Convert_v1alpha5_ExternalRouterIPParam_To_v1alpha8_ExternalRouterIPParam(in *ExternalRouterIPParam, out *v1alpha8.ExternalRouterIPParam, s conversion.Scope) error {
+ return autoConvert_v1alpha5_ExternalRouterIPParam_To_v1alpha8_ExternalRouterIPParam(in, out, s)
}
-func autoConvert_v1alpha7_ExternalRouterIPParam_To_v1alpha5_ExternalRouterIPParam(in *v1alpha7.ExternalRouterIPParam, out *ExternalRouterIPParam, s conversion.Scope) error {
+func autoConvert_v1alpha8_ExternalRouterIPParam_To_v1alpha5_ExternalRouterIPParam(in *v1alpha8.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_v1alpha8_SubnetFilter_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_v1alpha8_ExternalRouterIPParam_To_v1alpha5_ExternalRouterIPParam is an autogenerated conversion function.
+func Convert_v1alpha8_ExternalRouterIPParam_To_v1alpha5_ExternalRouterIPParam(in *v1alpha8.ExternalRouterIPParam, out *ExternalRouterIPParam, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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))
+func autoConvert_v1alpha5_FixedIP_To_v1alpha8_FixedIP(in *FixedIP, out *v1alpha8.FixedIP, s conversion.Scope) error {
+ out.Subnet = (*v1alpha8.SubnetFilter)(unsafe.Pointer(in.Subnet))
out.IPAddress = in.IPAddress
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_v1alpha8_FixedIP is an autogenerated conversion function.
+func Convert_v1alpha5_FixedIP_To_v1alpha8_FixedIP(in *FixedIP, out *v1alpha8.FixedIP, s conversion.Scope) error {
+ return autoConvert_v1alpha5_FixedIP_To_v1alpha8_FixedIP(in, out, s)
}
-func autoConvert_v1alpha7_FixedIP_To_v1alpha5_FixedIP(in *v1alpha7.FixedIP, out *FixedIP, s conversion.Scope) error {
+func autoConvert_v1alpha8_FixedIP_To_v1alpha5_FixedIP(in *v1alpha8.FixedIP, out *FixedIP, s conversion.Scope) error {
out.Subnet = (*SubnetFilter)(unsafe.Pointer(in.Subnet))
out.IPAddress = in.IPAddress
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_v1alpha8_FixedIP_To_v1alpha5_FixedIP is an autogenerated conversion function.
+func Convert_v1alpha8_FixedIP_To_v1alpha5_FixedIP(in *v1alpha8.FixedIP, out *FixedIP, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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_v1alpha8_LoadBalancer(in *LoadBalancer, out *v1alpha8.LoadBalancer, s conversion.Scope) error {
out.Name = in.Name
out.ID = in.ID
out.IP = in.IP
@@ -539,12 +539,12 @@ 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_v1alpha8_LoadBalancer is an autogenerated conversion function.
+func Convert_v1alpha5_LoadBalancer_To_v1alpha8_LoadBalancer(in *LoadBalancer, out *v1alpha8.LoadBalancer, s conversion.Scope) error {
+ return autoConvert_v1alpha5_LoadBalancer_To_v1alpha8_LoadBalancer(in, out, s)
}
-func autoConvert_v1alpha7_LoadBalancer_To_v1alpha5_LoadBalancer(in *v1alpha7.LoadBalancer, out *LoadBalancer, s conversion.Scope) error {
+func autoConvert_v1alpha8_LoadBalancer_To_v1alpha5_LoadBalancer(in *v1alpha8.LoadBalancer, out *LoadBalancer, s conversion.Scope) error {
out.Name = in.Name
out.ID = in.ID
out.IP = in.IP
@@ -554,7 +554,7 @@ func autoConvert_v1alpha7_LoadBalancer_To_v1alpha5_LoadBalancer(in *v1alpha7.Loa
return nil
}
-func autoConvert_v1alpha5_NetworkFilter_To_v1alpha7_NetworkFilter(in *NetworkFilter, out *v1alpha7.NetworkFilter, s conversion.Scope) error {
+func autoConvert_v1alpha5_NetworkFilter_To_v1alpha8_NetworkFilter(in *NetworkFilter, out *v1alpha8.NetworkFilter, s conversion.Scope) error {
out.Name = in.Name
out.Description = in.Description
out.ProjectID = in.ProjectID
@@ -566,12 +566,12 @@ func autoConvert_v1alpha5_NetworkFilter_To_v1alpha7_NetworkFilter(in *NetworkFil
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)
+// Convert_v1alpha5_NetworkFilter_To_v1alpha8_NetworkFilter is an autogenerated conversion function.
+func Convert_v1alpha5_NetworkFilter_To_v1alpha8_NetworkFilter(in *NetworkFilter, out *v1alpha8.NetworkFilter, s conversion.Scope) error {
+ return autoConvert_v1alpha5_NetworkFilter_To_v1alpha8_NetworkFilter(in, out, s)
}
-func autoConvert_v1alpha7_NetworkFilter_To_v1alpha5_NetworkFilter(in *v1alpha7.NetworkFilter, out *NetworkFilter, s conversion.Scope) error {
+func autoConvert_v1alpha8_NetworkFilter_To_v1alpha5_NetworkFilter(in *v1alpha8.NetworkFilter, out *NetworkFilter, s conversion.Scope) error {
out.Name = in.Name
out.Description = in.Description
out.ProjectID = in.ProjectID
@@ -583,50 +583,50 @@ func autoConvert_v1alpha7_NetworkFilter_To_v1alpha5_NetworkFilter(in *v1alpha7.N
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)
+// Convert_v1alpha8_NetworkFilter_To_v1alpha5_NetworkFilter is an autogenerated conversion function.
+func Convert_v1alpha8_NetworkFilter_To_v1alpha5_NetworkFilter(in *v1alpha8.NetworkFilter, out *NetworkFilter, s conversion.Scope) error {
+ return autoConvert_v1alpha8_NetworkFilter_To_v1alpha5_NetworkFilter(in, out, s)
}
-func autoConvert_v1alpha5_OpenStackCluster_To_v1alpha7_OpenStackCluster(in *OpenStackCluster, out *v1alpha7.OpenStackCluster, s conversion.Scope) error {
+func autoConvert_v1alpha5_OpenStackCluster_To_v1alpha8_OpenStackCluster(in *OpenStackCluster, out *v1alpha8.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_v1alpha8_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_v1alpha8_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_v1alpha8_OpenStackCluster is an autogenerated conversion function.
+func Convert_v1alpha5_OpenStackCluster_To_v1alpha8_OpenStackCluster(in *OpenStackCluster, out *v1alpha8.OpenStackCluster, s conversion.Scope) error {
+ return autoConvert_v1alpha5_OpenStackCluster_To_v1alpha8_OpenStackCluster(in, out, s)
}
-func autoConvert_v1alpha7_OpenStackCluster_To_v1alpha5_OpenStackCluster(in *v1alpha7.OpenStackCluster, out *OpenStackCluster, s conversion.Scope) error {
+func autoConvert_v1alpha8_OpenStackCluster_To_v1alpha5_OpenStackCluster(in *v1alpha8.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_v1alpha8_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_v1alpha8_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_v1alpha8_OpenStackCluster_To_v1alpha5_OpenStackCluster is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackCluster_To_v1alpha5_OpenStackCluster(in *v1alpha8.OpenStackCluster, out *OpenStackCluster, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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_v1alpha8_OpenStackClusterList(in *OpenStackClusterList, out *v1alpha8.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([]v1alpha8.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_v1alpha8_OpenStackCluster(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -636,18 +636,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_v1alpha8_OpenStackClusterList is an autogenerated conversion function.
+func Convert_v1alpha5_OpenStackClusterList_To_v1alpha8_OpenStackClusterList(in *OpenStackClusterList, out *v1alpha8.OpenStackClusterList, s conversion.Scope) error {
+ return autoConvert_v1alpha5_OpenStackClusterList_To_v1alpha8_OpenStackClusterList(in, out, s)
}
-func autoConvert_v1alpha7_OpenStackClusterList_To_v1alpha5_OpenStackClusterList(in *v1alpha7.OpenStackClusterList, out *OpenStackClusterList, s conversion.Scope) error {
+func autoConvert_v1alpha8_OpenStackClusterList_To_v1alpha5_OpenStackClusterList(in *v1alpha8.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_v1alpha8_OpenStackCluster_To_v1alpha5_OpenStackCluster(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -657,26 +657,26 @@ 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_v1alpha8_OpenStackClusterList_To_v1alpha5_OpenStackClusterList is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackClusterList_To_v1alpha5_OpenStackClusterList(in *v1alpha8.OpenStackClusterList, out *OpenStackClusterList, s conversion.Scope) error {
+ return autoConvert_v1alpha8_OpenStackClusterList_To_v1alpha5_OpenStackClusterList(in, out, s)
}
-func autoConvert_v1alpha5_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in *OpenStackClusterSpec, out *v1alpha7.OpenStackClusterSpec, s conversion.Scope) error {
+func autoConvert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *OpenStackClusterSpec, out *v1alpha8.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 {
+ if err := Convert_v1alpha5_NetworkFilter_To_v1alpha8_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 {
+ if err := Convert_v1alpha5_SubnetFilter_To_v1alpha8_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil {
return err
}
out.DNSNameservers = *(*[]string)(unsafe.Pointer(&in.DNSNameservers))
if in.ExternalRouterIPs != nil {
in, out := &in.ExternalRouterIPs, &out.ExternalRouterIPs
- *out = make([]v1alpha7.ExternalRouterIPParam, len(*in))
+ *out = make([]v1alpha8.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_v1alpha8_ExternalRouterIPParam(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -684,7 +684,7 @@ func autoConvert_v1alpha5_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(
out.ExternalRouterIPs = nil
}
out.ExternalNetworkID = in.ExternalNetworkID
- if err := Convert_v1alpha5_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil {
+ if err := Convert_v1alpha5_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil {
return err
}
out.DisableAPIServerFloatingIP = in.DisableAPIServerFloatingIP
@@ -699,30 +699,30 @@ func autoConvert_v1alpha5_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(
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(v1alpha8.Bastion)
+ if err := Convert_v1alpha5_Bastion_To_v1alpha8_Bastion(*in, *out, s); err != nil {
return err
}
} else {
out.Bastion = nil
}
- out.IdentityRef = (*v1alpha7.OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef))
+ out.IdentityRef = (*v1alpha8.OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef))
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)
+// Convert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec is an autogenerated conversion function.
+func Convert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *OpenStackClusterSpec, out *v1alpha8.OpenStackClusterSpec, s conversion.Scope) error {
+ return autoConvert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in, out, s)
}
-func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(in *v1alpha7.OpenStackClusterSpec, out *OpenStackClusterSpec, s conversion.Scope) error {
+func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(in *v1alpha8.OpenStackClusterSpec, out *OpenStackClusterSpec, s conversion.Scope) error {
out.CloudName = in.CloudName
out.NodeCIDR = in.NodeCIDR
// 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 {
+ if err := Convert_v1alpha8_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 {
+ if err := Convert_v1alpha8_SubnetFilter_To_v1alpha5_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil {
return err
}
// WARNING: in.NetworkMTU requires manual conversion: does not exist in peer-type
@@ -731,7 +731,7 @@ func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(
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_v1alpha8_ExternalRouterIPParam_To_v1alpha5_ExternalRouterIPParam(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -739,7 +739,7 @@ func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(
out.ExternalRouterIPs = nil
}
out.ExternalNetworkID = in.ExternalNetworkID
- if err := Convert_v1alpha7_APIServerLoadBalancer_To_v1alpha5_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil {
+ if err := Convert_v1alpha8_APIServerLoadBalancer_To_v1alpha5_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil {
return err
}
out.DisableAPIServerFloatingIP = in.DisableAPIServerFloatingIP
@@ -756,7 +756,7 @@ func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(
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_v1alpha8_Bastion_To_v1alpha5_Bastion(*in, *out, s); err != nil {
return err
}
} else {
@@ -766,12 +766,12 @@ func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(
return nil
}
-func autoConvert_v1alpha5_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(in *OpenStackClusterStatus, out *v1alpha7.OpenStackClusterStatus, s conversion.Scope) error {
+func autoConvert_v1alpha5_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterStatus(in *OpenStackClusterStatus, out *v1alpha8.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(v1alpha8.NetworkStatusWithSubnets)
+ if err := Convert_v1alpha5_Network_To_v1alpha8_NetworkStatusWithSubnets(*in, *out, s); err != nil {
return err
}
} else {
@@ -779,21 +779,21 @@ 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(v1alpha8.NetworkStatus)
+ if err := Convert_v1alpha5_Network_To_v1alpha8_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.ControlPlaneSecurityGroup = (*v1alpha8.SecurityGroup)(unsafe.Pointer(in.ControlPlaneSecurityGroup))
+ out.WorkerSecurityGroup = (*v1alpha8.SecurityGroup)(unsafe.Pointer(in.WorkerSecurityGroup))
+ out.BastionSecurityGroup = (*v1alpha8.SecurityGroup)(unsafe.Pointer(in.BastionSecurityGroup))
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(v1alpha8.BastionStatus)
+ if err := Convert_v1alpha5_Instance_To_v1alpha8_BastionStatus(*in, *out, s); err != nil {
return err
}
} else {
@@ -804,12 +804,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_v1alpha8_OpenStackClusterStatus_To_v1alpha5_OpenStackClusterStatus(in *v1alpha8.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_v1alpha8_NetworkStatusWithSubnets_To_v1alpha5_Network(*in, *out, s); err != nil {
return err
}
} else {
@@ -818,7 +818,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_v1alpha8_NetworkStatus_To_v1alpha5_Network(*in, *out, s); err != nil {
return err
}
} else {
@@ -833,7 +833,7 @@ func autoConvert_v1alpha7_OpenStackClusterStatus_To_v1alpha5_OpenStackClusterSta
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_v1alpha8_BastionStatus_To_v1alpha5_Instance(*in, *out, s); err != nil {
return err
}
} else {
@@ -844,39 +844,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_v1alpha8_OpenStackClusterTemplate(in *OpenStackClusterTemplate, out *v1alpha8.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_v1alpha8_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_v1alpha8_OpenStackClusterTemplate is an autogenerated conversion function.
+func Convert_v1alpha5_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate(in *OpenStackClusterTemplate, out *v1alpha8.OpenStackClusterTemplate, s conversion.Scope) error {
+ return autoConvert_v1alpha5_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate(in, out, s)
}
-func autoConvert_v1alpha7_OpenStackClusterTemplate_To_v1alpha5_OpenStackClusterTemplate(in *v1alpha7.OpenStackClusterTemplate, out *OpenStackClusterTemplate, s conversion.Scope) error {
+func autoConvert_v1alpha8_OpenStackClusterTemplate_To_v1alpha5_OpenStackClusterTemplate(in *v1alpha8.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_v1alpha8_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_v1alpha8_OpenStackClusterTemplate_To_v1alpha5_OpenStackClusterTemplate is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackClusterTemplate_To_v1alpha5_OpenStackClusterTemplate(in *v1alpha8.OpenStackClusterTemplate, out *OpenStackClusterTemplate, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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_v1alpha8_OpenStackClusterTemplateList(in *OpenStackClusterTemplateList, out *v1alpha8.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([]v1alpha8.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_v1alpha8_OpenStackClusterTemplate(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -886,18 +886,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_v1alpha8_OpenStackClusterTemplateList is an autogenerated conversion function.
+func Convert_v1alpha5_OpenStackClusterTemplateList_To_v1alpha8_OpenStackClusterTemplateList(in *OpenStackClusterTemplateList, out *v1alpha8.OpenStackClusterTemplateList, s conversion.Scope) error {
+ return autoConvert_v1alpha5_OpenStackClusterTemplateList_To_v1alpha8_OpenStackClusterTemplateList(in, out, s)
}
-func autoConvert_v1alpha7_OpenStackClusterTemplateList_To_v1alpha5_OpenStackClusterTemplateList(in *v1alpha7.OpenStackClusterTemplateList, out *OpenStackClusterTemplateList, s conversion.Scope) error {
+func autoConvert_v1alpha8_OpenStackClusterTemplateList_To_v1alpha5_OpenStackClusterTemplateList(in *v1alpha8.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_v1alpha8_OpenStackClusterTemplate_To_v1alpha5_OpenStackClusterTemplate(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -907,120 +907,120 @@ 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_v1alpha8_OpenStackClusterTemplateList_To_v1alpha5_OpenStackClusterTemplateList is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackClusterTemplateList_To_v1alpha5_OpenStackClusterTemplateList(in *v1alpha8.OpenStackClusterTemplateList, out *OpenStackClusterTemplateList, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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_v1alpha8_OpenStackClusterTemplateResource(in *OpenStackClusterTemplateResource, out *v1alpha8.OpenStackClusterTemplateResource, s conversion.Scope) error {
+ if err := Convert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_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_v1alpha8_OpenStackClusterTemplateResource is an autogenerated conversion function.
+func Convert_v1alpha5_OpenStackClusterTemplateResource_To_v1alpha8_OpenStackClusterTemplateResource(in *OpenStackClusterTemplateResource, out *v1alpha8.OpenStackClusterTemplateResource, s conversion.Scope) error {
+ return autoConvert_v1alpha5_OpenStackClusterTemplateResource_To_v1alpha8_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_v1alpha8_OpenStackClusterTemplateResource_To_v1alpha5_OpenStackClusterTemplateResource(in *v1alpha8.OpenStackClusterTemplateResource, out *OpenStackClusterTemplateResource, s conversion.Scope) error {
+ if err := Convert_v1alpha8_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_v1alpha8_OpenStackClusterTemplateResource_To_v1alpha5_OpenStackClusterTemplateResource is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackClusterTemplateResource_To_v1alpha5_OpenStackClusterTemplateResource(in *v1alpha8.OpenStackClusterTemplateResource, out *OpenStackClusterTemplateResource, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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_v1alpha8_OpenStackClusterTemplateSpec(in *OpenStackClusterTemplateSpec, out *v1alpha8.OpenStackClusterTemplateSpec, s conversion.Scope) error {
+ if err := Convert_v1alpha5_OpenStackClusterTemplateResource_To_v1alpha8_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_v1alpha8_OpenStackClusterTemplateSpec is an autogenerated conversion function.
+func Convert_v1alpha5_OpenStackClusterTemplateSpec_To_v1alpha8_OpenStackClusterTemplateSpec(in *OpenStackClusterTemplateSpec, out *v1alpha8.OpenStackClusterTemplateSpec, s conversion.Scope) error {
+ return autoConvert_v1alpha5_OpenStackClusterTemplateSpec_To_v1alpha8_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_v1alpha8_OpenStackClusterTemplateSpec_To_v1alpha5_OpenStackClusterTemplateSpec(in *v1alpha8.OpenStackClusterTemplateSpec, out *OpenStackClusterTemplateSpec, s conversion.Scope) error {
+ if err := Convert_v1alpha8_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_v1alpha8_OpenStackClusterTemplateSpec_To_v1alpha5_OpenStackClusterTemplateSpec is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackClusterTemplateSpec_To_v1alpha5_OpenStackClusterTemplateSpec(in *v1alpha8.OpenStackClusterTemplateSpec, out *OpenStackClusterTemplateSpec, s conversion.Scope) error {
+ return autoConvert_v1alpha8_OpenStackClusterTemplateSpec_To_v1alpha5_OpenStackClusterTemplateSpec(in, out, s)
}
-func autoConvert_v1alpha5_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference(in *OpenStackIdentityReference, out *v1alpha7.OpenStackIdentityReference, s conversion.Scope) error {
+func autoConvert_v1alpha5_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(in *OpenStackIdentityReference, out *v1alpha8.OpenStackIdentityReference, s conversion.Scope) error {
out.Kind = in.Kind
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)
+// Convert_v1alpha5_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference is an autogenerated conversion function.
+func Convert_v1alpha5_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(in *OpenStackIdentityReference, out *v1alpha8.OpenStackIdentityReference, s conversion.Scope) error {
+ return autoConvert_v1alpha5_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(in, out, s)
}
-func autoConvert_v1alpha7_OpenStackIdentityReference_To_v1alpha5_OpenStackIdentityReference(in *v1alpha7.OpenStackIdentityReference, out *OpenStackIdentityReference, s conversion.Scope) error {
+func autoConvert_v1alpha8_OpenStackIdentityReference_To_v1alpha5_OpenStackIdentityReference(in *v1alpha8.OpenStackIdentityReference, out *OpenStackIdentityReference, s conversion.Scope) error {
out.Kind = in.Kind
out.Name = in.Name
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)
+// Convert_v1alpha8_OpenStackIdentityReference_To_v1alpha5_OpenStackIdentityReference is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackIdentityReference_To_v1alpha5_OpenStackIdentityReference(in *v1alpha8.OpenStackIdentityReference, out *OpenStackIdentityReference, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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_v1alpha8_OpenStackMachine(in *OpenStackMachine, out *v1alpha8.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_v1alpha8_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_v1alpha8_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_v1alpha8_OpenStackMachine is an autogenerated conversion function.
+func Convert_v1alpha5_OpenStackMachine_To_v1alpha8_OpenStackMachine(in *OpenStackMachine, out *v1alpha8.OpenStackMachine, s conversion.Scope) error {
+ return autoConvert_v1alpha5_OpenStackMachine_To_v1alpha8_OpenStackMachine(in, out, s)
}
-func autoConvert_v1alpha7_OpenStackMachine_To_v1alpha5_OpenStackMachine(in *v1alpha7.OpenStackMachine, out *OpenStackMachine, s conversion.Scope) error {
+func autoConvert_v1alpha8_OpenStackMachine_To_v1alpha5_OpenStackMachine(in *v1alpha8.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_v1alpha8_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_v1alpha8_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_v1alpha8_OpenStackMachine_To_v1alpha5_OpenStackMachine is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackMachine_To_v1alpha5_OpenStackMachine(in *v1alpha8.OpenStackMachine, out *OpenStackMachine, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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_v1alpha8_OpenStackMachineList(in *OpenStackMachineList, out *v1alpha8.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([]v1alpha8.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_v1alpha8_OpenStackMachine(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -1030,18 +1030,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_v1alpha8_OpenStackMachineList is an autogenerated conversion function.
+func Convert_v1alpha5_OpenStackMachineList_To_v1alpha8_OpenStackMachineList(in *OpenStackMachineList, out *v1alpha8.OpenStackMachineList, s conversion.Scope) error {
+ return autoConvert_v1alpha5_OpenStackMachineList_To_v1alpha8_OpenStackMachineList(in, out, s)
}
-func autoConvert_v1alpha7_OpenStackMachineList_To_v1alpha5_OpenStackMachineList(in *v1alpha7.OpenStackMachineList, out *OpenStackMachineList, s conversion.Scope) error {
+func autoConvert_v1alpha8_OpenStackMachineList_To_v1alpha5_OpenStackMachineList(in *v1alpha8.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_v1alpha8_OpenStackMachine_To_v1alpha5_OpenStackMachine(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -1051,12 +1051,12 @@ 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_v1alpha8_OpenStackMachineList_To_v1alpha5_OpenStackMachineList is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackMachineList_To_v1alpha5_OpenStackMachineList(in *v1alpha8.OpenStackMachineList, out *OpenStackMachineList, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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_v1alpha8_OpenStackMachineSpec(in *OpenStackMachineSpec, out *v1alpha8.OpenStackMachineSpec, s conversion.Scope) error {
out.ProviderID = (*string)(unsafe.Pointer(in.ProviderID))
out.InstanceID = (*string)(unsafe.Pointer(in.InstanceID))
out.CloudName = in.CloudName
@@ -1067,9 +1067,9 @@ func autoConvert_v1alpha5_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(
// 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([]v1alpha8.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_v1alpha8_PortOpts(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -1080,9 +1080,9 @@ func autoConvert_v1alpha5_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(
out.FloatingIP = in.FloatingIP
if in.SecurityGroups != nil {
in, out := &in.SecurityGroups, &out.SecurityGroups
- *out = make([]v1alpha7.SecurityGroupFilter, len(*in))
+ *out = make([]v1alpha8.SecurityGroupFilter, 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_v1alpha8_SecurityGroupFilter(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -1093,13 +1093,13 @@ func autoConvert_v1alpha5_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
out.ServerMetadata = *(*map[string]string)(unsafe.Pointer(&in.ServerMetadata))
out.ConfigDrive = (*bool)(unsafe.Pointer(in.ConfigDrive))
- out.RootVolume = (*v1alpha7.RootVolume)(unsafe.Pointer(in.RootVolume))
+ out.RootVolume = (*v1alpha8.RootVolume)(unsafe.Pointer(in.RootVolume))
out.ServerGroupID = in.ServerGroupID
- out.IdentityRef = (*v1alpha7.OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef))
+ out.IdentityRef = (*v1alpha8.OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef))
return nil
}
-func autoConvert_v1alpha7_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(in *v1alpha7.OpenStackMachineSpec, out *OpenStackMachineSpec, s conversion.Scope) error {
+func autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(in *v1alpha8.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
@@ -1111,7 +1111,7 @@ func autoConvert_v1alpha7_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(
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_v1alpha8_PortOpts_To_v1alpha5_PortOpts(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -1123,7 +1123,7 @@ func autoConvert_v1alpha7_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(
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_v1alpha8_SecurityGroupFilter_To_v1alpha5_SecurityGroupParam(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -1141,22 +1141,22 @@ func autoConvert_v1alpha7_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(
return nil
}
-func autoConvert_v1alpha5_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus(in *OpenStackMachineStatus, out *v1alpha7.OpenStackMachineStatus, s conversion.Scope) error {
+func autoConvert_v1alpha5_OpenStackMachineStatus_To_v1alpha8_OpenStackMachineStatus(in *OpenStackMachineStatus, out *v1alpha8.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.InstanceState = (*v1alpha8.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))
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_v1alpha8_OpenStackMachineStatus is an autogenerated conversion function.
+func Convert_v1alpha5_OpenStackMachineStatus_To_v1alpha8_OpenStackMachineStatus(in *OpenStackMachineStatus, out *v1alpha8.OpenStackMachineStatus, s conversion.Scope) error {
+ return autoConvert_v1alpha5_OpenStackMachineStatus_To_v1alpha8_OpenStackMachineStatus(in, out, s)
}
-func autoConvert_v1alpha7_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineStatus(in *v1alpha7.OpenStackMachineStatus, out *OpenStackMachineStatus, s conversion.Scope) error {
+func autoConvert_v1alpha8_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineStatus(in *v1alpha8.OpenStackMachineStatus, out *OpenStackMachineStatus, s conversion.Scope) error {
out.Ready = in.Ready
out.Addresses = *(*[]v1.NodeAddress)(unsafe.Pointer(&in.Addresses))
out.InstanceState = (*InstanceState)(unsafe.Pointer(in.InstanceState))
@@ -1166,44 +1166,44 @@ func autoConvert_v1alpha7_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineSta
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)
+// Convert_v1alpha8_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineStatus is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineStatus(in *v1alpha8.OpenStackMachineStatus, out *OpenStackMachineStatus, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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_v1alpha8_OpenStackMachineTemplate(in *OpenStackMachineTemplate, out *v1alpha8.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_v1alpha8_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_v1alpha8_OpenStackMachineTemplate is an autogenerated conversion function.
+func Convert_v1alpha5_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate(in *OpenStackMachineTemplate, out *v1alpha8.OpenStackMachineTemplate, s conversion.Scope) error {
+ return autoConvert_v1alpha5_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate(in, out, s)
}
-func autoConvert_v1alpha7_OpenStackMachineTemplate_To_v1alpha5_OpenStackMachineTemplate(in *v1alpha7.OpenStackMachineTemplate, out *OpenStackMachineTemplate, s conversion.Scope) error {
+func autoConvert_v1alpha8_OpenStackMachineTemplate_To_v1alpha5_OpenStackMachineTemplate(in *v1alpha8.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_v1alpha8_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_v1alpha8_OpenStackMachineTemplate_To_v1alpha5_OpenStackMachineTemplate is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackMachineTemplate_To_v1alpha5_OpenStackMachineTemplate(in *v1alpha8.OpenStackMachineTemplate, out *OpenStackMachineTemplate, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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_v1alpha8_OpenStackMachineTemplateList(in *OpenStackMachineTemplateList, out *v1alpha8.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([]v1alpha8.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_v1alpha8_OpenStackMachineTemplate(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -1213,18 +1213,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_v1alpha8_OpenStackMachineTemplateList is an autogenerated conversion function.
+func Convert_v1alpha5_OpenStackMachineTemplateList_To_v1alpha8_OpenStackMachineTemplateList(in *OpenStackMachineTemplateList, out *v1alpha8.OpenStackMachineTemplateList, s conversion.Scope) error {
+ return autoConvert_v1alpha5_OpenStackMachineTemplateList_To_v1alpha8_OpenStackMachineTemplateList(in, out, s)
}
-func autoConvert_v1alpha7_OpenStackMachineTemplateList_To_v1alpha5_OpenStackMachineTemplateList(in *v1alpha7.OpenStackMachineTemplateList, out *OpenStackMachineTemplateList, s conversion.Scope) error {
+func autoConvert_v1alpha8_OpenStackMachineTemplateList_To_v1alpha5_OpenStackMachineTemplateList(in *v1alpha8.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_v1alpha8_OpenStackMachineTemplate_To_v1alpha5_OpenStackMachineTemplate(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -1234,91 +1234,91 @@ 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_v1alpha8_OpenStackMachineTemplateList_To_v1alpha5_OpenStackMachineTemplateList is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackMachineTemplateList_To_v1alpha5_OpenStackMachineTemplateList(in *v1alpha8.OpenStackMachineTemplateList, out *OpenStackMachineTemplateList, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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_v1alpha8_OpenStackMachineTemplateResource(in *OpenStackMachineTemplateResource, out *v1alpha8.OpenStackMachineTemplateResource, s conversion.Scope) error {
+ if err := Convert_v1alpha5_OpenStackMachineSpec_To_v1alpha8_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_v1alpha8_OpenStackMachineTemplateResource is an autogenerated conversion function.
+func Convert_v1alpha5_OpenStackMachineTemplateResource_To_v1alpha8_OpenStackMachineTemplateResource(in *OpenStackMachineTemplateResource, out *v1alpha8.OpenStackMachineTemplateResource, s conversion.Scope) error {
+ return autoConvert_v1alpha5_OpenStackMachineTemplateResource_To_v1alpha8_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_v1alpha8_OpenStackMachineTemplateResource_To_v1alpha5_OpenStackMachineTemplateResource(in *v1alpha8.OpenStackMachineTemplateResource, out *OpenStackMachineTemplateResource, s conversion.Scope) error {
+ if err := Convert_v1alpha8_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_v1alpha8_OpenStackMachineTemplateResource_To_v1alpha5_OpenStackMachineTemplateResource is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackMachineTemplateResource_To_v1alpha5_OpenStackMachineTemplateResource(in *v1alpha8.OpenStackMachineTemplateResource, out *OpenStackMachineTemplateResource, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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_v1alpha8_OpenStackMachineTemplateSpec(in *OpenStackMachineTemplateSpec, out *v1alpha8.OpenStackMachineTemplateSpec, s conversion.Scope) error {
+ if err := Convert_v1alpha5_OpenStackMachineTemplateResource_To_v1alpha8_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_v1alpha8_OpenStackMachineTemplateSpec is an autogenerated conversion function.
+func Convert_v1alpha5_OpenStackMachineTemplateSpec_To_v1alpha8_OpenStackMachineTemplateSpec(in *OpenStackMachineTemplateSpec, out *v1alpha8.OpenStackMachineTemplateSpec, s conversion.Scope) error {
+ return autoConvert_v1alpha5_OpenStackMachineTemplateSpec_To_v1alpha8_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_v1alpha8_OpenStackMachineTemplateSpec_To_v1alpha5_OpenStackMachineTemplateSpec(in *v1alpha8.OpenStackMachineTemplateSpec, out *OpenStackMachineTemplateSpec, s conversion.Scope) error {
+ if err := Convert_v1alpha8_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_v1alpha8_OpenStackMachineTemplateSpec_To_v1alpha5_OpenStackMachineTemplateSpec is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackMachineTemplateSpec_To_v1alpha5_OpenStackMachineTemplateSpec(in *v1alpha8.OpenStackMachineTemplateSpec, out *OpenStackMachineTemplateSpec, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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))
+func autoConvert_v1alpha5_PortOpts_To_v1alpha8_PortOpts(in *PortOpts, out *v1alpha8.PortOpts, s conversion.Scope) error {
+ out.Network = (*v1alpha8.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))
+ out.FixedIPs = *(*[]v1alpha8.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))
+ *out = make([]v1alpha8.SecurityGroupFilter, 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_v1alpha8_SecurityGroupFilter(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.SecurityGroupFilters = nil
}
- out.AllowedAddressPairs = *(*[]v1alpha7.AddressPair)(unsafe.Pointer(&in.AllowedAddressPairs))
+ out.AllowedAddressPairs = *(*[]v1alpha8.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 (map[string]string vs sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7.BindingProfile)
+ // WARNING: in.Profile requires manual conversion: inconvertible types (map[string]string vs sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8.BindingProfile)
out.DisablePortSecurity = (*bool)(unsafe.Pointer(in.DisablePortSecurity))
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 {
+func autoConvert_v1alpha8_PortOpts_To_v1alpha5_PortOpts(in *v1alpha8.PortOpts, out *PortOpts, s conversion.Scope) error {
out.Network = (*NetworkFilter)(unsafe.Pointer(in.Network))
out.NameSuffix = in.NameSuffix
out.Description = in.Description
@@ -1329,7 +1329,7 @@ func autoConvert_v1alpha7_PortOpts_To_v1alpha5_PortOpts(in *v1alpha7.PortOpts, o
in, out := &in.SecurityGroupFilters, &out.SecurityGroupFilters
*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_v1alpha8_SecurityGroupFilter_To_v1alpha5_SecurityGroupParam(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -1340,7 +1340,7 @@ func autoConvert_v1alpha7_PortOpts_To_v1alpha5_PortOpts(in *v1alpha7.PortOpts, o
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)
+ // WARNING: in.Profile requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8.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))
@@ -1348,31 +1348,31 @@ func autoConvert_v1alpha7_PortOpts_To_v1alpha5_PortOpts(in *v1alpha7.PortOpts, o
return nil
}
-func autoConvert_v1alpha5_RootVolume_To_v1alpha7_RootVolume(in *RootVolume, out *v1alpha7.RootVolume, s conversion.Scope) error {
+func autoConvert_v1alpha5_RootVolume_To_v1alpha8_RootVolume(in *RootVolume, out *v1alpha8.RootVolume, s conversion.Scope) error {
out.Size = in.Size
out.VolumeType = in.VolumeType
out.AvailabilityZone = in.AvailabilityZone
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)
+// Convert_v1alpha5_RootVolume_To_v1alpha8_RootVolume is an autogenerated conversion function.
+func Convert_v1alpha5_RootVolume_To_v1alpha8_RootVolume(in *RootVolume, out *v1alpha8.RootVolume, s conversion.Scope) error {
+ return autoConvert_v1alpha5_RootVolume_To_v1alpha8_RootVolume(in, out, s)
}
-func autoConvert_v1alpha7_RootVolume_To_v1alpha5_RootVolume(in *v1alpha7.RootVolume, out *RootVolume, s conversion.Scope) error {
+func autoConvert_v1alpha8_RootVolume_To_v1alpha5_RootVolume(in *v1alpha8.RootVolume, out *RootVolume, s conversion.Scope) error {
out.Size = in.Size
out.VolumeType = in.VolumeType
out.AvailabilityZone = in.AvailabilityZone
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)
+// Convert_v1alpha8_RootVolume_To_v1alpha5_RootVolume is an autogenerated conversion function.
+func Convert_v1alpha8_RootVolume_To_v1alpha5_RootVolume(in *v1alpha8.RootVolume, out *RootVolume, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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_v1alpha8_Router(in *Router, out *v1alpha8.Router, s conversion.Scope) error {
out.Name = in.Name
out.ID = in.ID
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
@@ -1380,12 +1380,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_v1alpha8_Router is an autogenerated conversion function.
+func Convert_v1alpha5_Router_To_v1alpha8_Router(in *Router, out *v1alpha8.Router, s conversion.Scope) error {
+ return autoConvert_v1alpha5_Router_To_v1alpha8_Router(in, out, s)
}
-func autoConvert_v1alpha7_Router_To_v1alpha5_Router(in *v1alpha7.Router, out *Router, s conversion.Scope) error {
+func autoConvert_v1alpha8_Router_To_v1alpha5_Router(in *v1alpha8.Router, out *Router, s conversion.Scope) error {
out.Name = in.Name
out.ID = in.ID
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
@@ -1393,36 +1393,36 @@ 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_v1alpha8_Router_To_v1alpha5_Router is an autogenerated conversion function.
+func Convert_v1alpha8_Router_To_v1alpha5_Router(in *v1alpha8.Router, out *Router, s conversion.Scope) error {
+ return autoConvert_v1alpha8_Router_To_v1alpha5_Router(in, out, s)
}
-func autoConvert_v1alpha5_SecurityGroup_To_v1alpha7_SecurityGroup(in *SecurityGroup, out *v1alpha7.SecurityGroup, s conversion.Scope) error {
+func autoConvert_v1alpha5_SecurityGroup_To_v1alpha8_SecurityGroup(in *SecurityGroup, out *v1alpha8.SecurityGroup, s conversion.Scope) error {
out.Name = in.Name
out.ID = in.ID
- out.Rules = *(*[]v1alpha7.SecurityGroupRule)(unsafe.Pointer(&in.Rules))
+ out.Rules = *(*[]v1alpha8.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)
+// Convert_v1alpha5_SecurityGroup_To_v1alpha8_SecurityGroup is an autogenerated conversion function.
+func Convert_v1alpha5_SecurityGroup_To_v1alpha8_SecurityGroup(in *SecurityGroup, out *v1alpha8.SecurityGroup, s conversion.Scope) error {
+ return autoConvert_v1alpha5_SecurityGroup_To_v1alpha8_SecurityGroup(in, out, s)
}
-func autoConvert_v1alpha7_SecurityGroup_To_v1alpha5_SecurityGroup(in *v1alpha7.SecurityGroup, out *SecurityGroup, s conversion.Scope) error {
+func autoConvert_v1alpha8_SecurityGroup_To_v1alpha5_SecurityGroup(in *v1alpha8.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)
+// Convert_v1alpha8_SecurityGroup_To_v1alpha5_SecurityGroup is an autogenerated conversion function.
+func Convert_v1alpha8_SecurityGroup_To_v1alpha5_SecurityGroup(in *v1alpha8.SecurityGroup, out *SecurityGroup, s conversion.Scope) error {
+ return autoConvert_v1alpha8_SecurityGroup_To_v1alpha5_SecurityGroup(in, out, s)
}
-func autoConvert_v1alpha5_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in *SecurityGroupFilter, out *v1alpha7.SecurityGroupFilter, s conversion.Scope) error {
+func autoConvert_v1alpha5_SecurityGroupFilter_To_v1alpha8_SecurityGroupFilter(in *SecurityGroupFilter, out *v1alpha8.SecurityGroupFilter, s conversion.Scope) error {
out.ID = in.ID
out.Name = in.Name
out.Description = in.Description
@@ -1439,7 +1439,7 @@ func autoConvert_v1alpha5_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in
return nil
}
-func autoConvert_v1alpha7_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(in *v1alpha7.SecurityGroupFilter, out *SecurityGroupFilter, s conversion.Scope) error {
+func autoConvert_v1alpha8_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(in *v1alpha8.SecurityGroupFilter, out *SecurityGroupFilter, s conversion.Scope) error {
out.ID = in.ID
out.Name = in.Name
out.Description = in.Description
@@ -1451,12 +1451,12 @@ func autoConvert_v1alpha7_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(in
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)
+// Convert_v1alpha8_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter is an autogenerated conversion function.
+func Convert_v1alpha8_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(in *v1alpha8.SecurityGroupFilter, out *SecurityGroupFilter, s conversion.Scope) error {
+ return autoConvert_v1alpha8_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(in, out, s)
}
-func autoConvert_v1alpha5_SecurityGroupRule_To_v1alpha7_SecurityGroupRule(in *SecurityGroupRule, out *v1alpha7.SecurityGroupRule, s conversion.Scope) error {
+func autoConvert_v1alpha5_SecurityGroupRule_To_v1alpha8_SecurityGroupRule(in *SecurityGroupRule, out *v1alpha8.SecurityGroupRule, s conversion.Scope) error {
out.Description = in.Description
out.ID = in.ID
out.Direction = in.Direction
@@ -1470,12 +1470,12 @@ func autoConvert_v1alpha5_SecurityGroupRule_To_v1alpha7_SecurityGroupRule(in *Se
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)
+// Convert_v1alpha5_SecurityGroupRule_To_v1alpha8_SecurityGroupRule is an autogenerated conversion function.
+func Convert_v1alpha5_SecurityGroupRule_To_v1alpha8_SecurityGroupRule(in *SecurityGroupRule, out *v1alpha8.SecurityGroupRule, s conversion.Scope) error {
+ return autoConvert_v1alpha5_SecurityGroupRule_To_v1alpha8_SecurityGroupRule(in, out, s)
}
-func autoConvert_v1alpha7_SecurityGroupRule_To_v1alpha5_SecurityGroupRule(in *v1alpha7.SecurityGroupRule, out *SecurityGroupRule, s conversion.Scope) error {
+func autoConvert_v1alpha8_SecurityGroupRule_To_v1alpha5_SecurityGroupRule(in *v1alpha8.SecurityGroupRule, out *SecurityGroupRule, s conversion.Scope) error {
out.Description = in.Description
out.ID = in.ID
out.Direction = in.Direction
@@ -1489,12 +1489,12 @@ func autoConvert_v1alpha7_SecurityGroupRule_To_v1alpha5_SecurityGroupRule(in *v1
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)
+// Convert_v1alpha8_SecurityGroupRule_To_v1alpha5_SecurityGroupRule is an autogenerated conversion function.
+func Convert_v1alpha8_SecurityGroupRule_To_v1alpha5_SecurityGroupRule(in *v1alpha8.SecurityGroupRule, out *SecurityGroupRule, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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_v1alpha8_Subnet(in *Subnet, out *v1alpha8.Subnet, s conversion.Scope) error {
out.Name = in.Name
out.ID = in.ID
out.CIDR = in.CIDR
@@ -1502,12 +1502,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_v1alpha8_Subnet is an autogenerated conversion function.
+func Convert_v1alpha5_Subnet_To_v1alpha8_Subnet(in *Subnet, out *v1alpha8.Subnet, s conversion.Scope) error {
+ return autoConvert_v1alpha5_Subnet_To_v1alpha8_Subnet(in, out, s)
}
-func autoConvert_v1alpha7_Subnet_To_v1alpha5_Subnet(in *v1alpha7.Subnet, out *Subnet, s conversion.Scope) error {
+func autoConvert_v1alpha8_Subnet_To_v1alpha5_Subnet(in *v1alpha8.Subnet, out *Subnet, s conversion.Scope) error {
out.Name = in.Name
out.ID = in.ID
out.CIDR = in.CIDR
@@ -1515,12 +1515,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_v1alpha8_Subnet_To_v1alpha5_Subnet is an autogenerated conversion function.
+func Convert_v1alpha8_Subnet_To_v1alpha5_Subnet(in *v1alpha8.Subnet, out *Subnet, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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_v1alpha8_SubnetFilter(in *SubnetFilter, out *v1alpha8.SubnetFilter, s conversion.Scope) error {
out.Name = in.Name
out.Description = in.Description
out.ProjectID = in.ProjectID
@@ -1537,12 +1537,12 @@ func autoConvert_v1alpha5_SubnetFilter_To_v1alpha7_SubnetFilter(in *SubnetFilter
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)
+// Convert_v1alpha5_SubnetFilter_To_v1alpha8_SubnetFilter is an autogenerated conversion function.
+func Convert_v1alpha5_SubnetFilter_To_v1alpha8_SubnetFilter(in *SubnetFilter, out *v1alpha8.SubnetFilter, s conversion.Scope) error {
+ return autoConvert_v1alpha5_SubnetFilter_To_v1alpha8_SubnetFilter(in, out, s)
}
-func autoConvert_v1alpha7_SubnetFilter_To_v1alpha5_SubnetFilter(in *v1alpha7.SubnetFilter, out *SubnetFilter, s conversion.Scope) error {
+func autoConvert_v1alpha8_SubnetFilter_To_v1alpha5_SubnetFilter(in *v1alpha8.SubnetFilter, out *SubnetFilter, s conversion.Scope) error {
out.Name = in.Name
out.Description = in.Description
out.ProjectID = in.ProjectID
@@ -1559,7 +1559,7 @@ func autoConvert_v1alpha7_SubnetFilter_To_v1alpha5_SubnetFilter(in *v1alpha7.Sub
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)
+// Convert_v1alpha8_SubnetFilter_To_v1alpha5_SubnetFilter is an autogenerated conversion function.
+func Convert_v1alpha8_SubnetFilter_To_v1alpha5_SubnetFilter(in *v1alpha8.SubnetFilter, out *SubnetFilter, s conversion.Scope) error {
+ return autoConvert_v1alpha8_SubnetFilter_To_v1alpha5_SubnetFilter(in, out, s)
}
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
index ae8e343ea8..66f77e3076 100644
--- a/api/v1alpha6/conversion.go
+++ b/api/v1alpha6/conversion.go
@@ -23,14 +23,14 @@ import (
apiconversion "k8s.io/apimachinery/pkg/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/v1alpha8"
"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
+ // Subnet is removed from v1alpha8 with no replacement, so can't be
// losslessly converted. Restore the previously stored value on down-conversion.
dst.Subnet = previous.Subnet
@@ -43,7 +43,7 @@ func restorev1alpha6MachineSpec(previous *OpenStackMachineSpec, dst *OpenStackMa
}
func restorev1alpha6ClusterStatus(previous *OpenStackClusterStatus, dst *OpenStackClusterStatus) {
- // PortOpts.SecurityGroups have been removed in v1alpha7
+ // PortOpts.SecurityGroups have been removed in v1alpha8
// We restore the whole PortOpts/Networks since they are anyway immutable.
if previous.ExternalNetwork != nil {
dst.ExternalNetwork.PortOpts = previous.ExternalNetwork.PortOpts
@@ -56,21 +56,21 @@ func restorev1alpha6ClusterStatus(previous *OpenStackClusterStatus, dst *OpenSta
}
}
-func restorev1alpha7MachineSpec(previous *infrav1.OpenStackMachineSpec, dst *infrav1.OpenStackMachineSpec) {
- // PropagateUplinkStatus has been added in v1alpha7.
+func restorev1alpha8MachineSpec(previous *infrav1.OpenStackMachineSpec, dst *infrav1.OpenStackMachineSpec) {
+ // PropagateUplinkStatus has been added in v1alpha8.
// 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) {
+func restorev1alpha8Bastion(previous **infrav1.Bastion, dst **infrav1.Bastion) {
if *previous != nil && *dst != nil {
- restorev1alpha7MachineSpec(&(*previous).Instance, &(*dst).Instance)
+ restorev1alpha8MachineSpec(&(*previous).Instance, &(*dst).Instance)
}
}
-func restorev1alpha7ClusterStatus(previous *infrav1.OpenStackClusterStatus, dst *infrav1.OpenStackClusterStatus) {
- // It's (theoretically) possible in v1alpha7 to have Network nil but
+func restorev1alpha8ClusterStatus(previous *infrav1.OpenStackClusterStatus, dst *infrav1.OpenStackClusterStatus) {
+ // It's (theoretically) possible in v1alpha8 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() {
@@ -117,7 +117,7 @@ var v1alpha6OpenStackClusterRestorer = conversion.RestorerFor[*OpenStackCluster]
},
}
-var v1alpha7OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStackCluster]{
+var v1alpha8OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStackCluster]{
"router": conversion.UnconditionalFieldRestorer[*infrav1.OpenStackCluster, *infrav1.RouterFilter]{
GetField: func(c *infrav1.OpenStackCluster) **infrav1.RouterFilter {
return &c.Spec.Router
@@ -132,13 +132,13 @@ var v1alpha7OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStack
GetField: func(c *infrav1.OpenStackCluster) **infrav1.Bastion {
return &c.Spec.Bastion
},
- RestoreField: restorev1alpha7Bastion,
+ RestoreField: restorev1alpha8Bastion,
},
"status": conversion.HashedFieldRestorer[*infrav1.OpenStackCluster, infrav1.OpenStackClusterStatus]{
GetField: func(c *infrav1.OpenStackCluster) *infrav1.OpenStackClusterStatus {
return &c.Status
},
- RestoreField: restorev1alpha7ClusterStatus,
+ RestoreField: restorev1alpha8ClusterStatus,
},
}
@@ -148,8 +148,8 @@ func (r *OpenStackCluster) ConvertTo(dstRaw ctrlconversion.Hub) error {
compare := &OpenStackCluster{}
return conversion.ConvertAndRestore(
r, dst, compare,
- Convert_v1alpha6_OpenStackCluster_To_v1alpha7_OpenStackCluster, Convert_v1alpha7_OpenStackCluster_To_v1alpha6_OpenStackCluster,
- v1alpha6OpenStackClusterRestorer, v1alpha7OpenStackClusterRestorer,
+ Convert_v1alpha6_OpenStackCluster_To_v1alpha8_OpenStackCluster, Convert_v1alpha8_OpenStackCluster_To_v1alpha6_OpenStackCluster,
+ v1alpha6OpenStackClusterRestorer, v1alpha8OpenStackClusterRestorer,
)
}
@@ -159,8 +159,8 @@ func (r *OpenStackCluster) ConvertFrom(srcRaw ctrlconversion.Hub) error {
compare := &infrav1.OpenStackCluster{}
return conversion.ConvertAndRestore(
src, r, compare,
- Convert_v1alpha7_OpenStackCluster_To_v1alpha6_OpenStackCluster, Convert_v1alpha6_OpenStackCluster_To_v1alpha7_OpenStackCluster,
- v1alpha7OpenStackClusterRestorer, v1alpha6OpenStackClusterRestorer,
+ Convert_v1alpha8_OpenStackCluster_To_v1alpha6_OpenStackCluster, Convert_v1alpha6_OpenStackCluster_To_v1alpha8_OpenStackCluster,
+ v1alpha8OpenStackClusterRestorer, v1alpha6OpenStackClusterRestorer,
)
}
@@ -169,13 +169,13 @@ 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)
+ return Convert_v1alpha6_OpenStackClusterList_To_v1alpha8_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)
+ return Convert_v1alpha8_OpenStackClusterList_To_v1alpha6_OpenStackClusterList(src, r, nil)
}
var _ ctrlconversion.Convertible = &OpenStackClusterTemplate{}
@@ -189,7 +189,7 @@ var v1alpha6OpenStackClusterTemplateRestorer = conversion.RestorerFor[*OpenStack
},
}
-var v1alpha7OpenStackClusterTemplateRestorer = conversion.RestorerFor[*infrav1.OpenStackClusterTemplate]{
+var v1alpha8OpenStackClusterTemplateRestorer = conversion.RestorerFor[*infrav1.OpenStackClusterTemplate]{
"router": conversion.UnconditionalFieldRestorer[*infrav1.OpenStackClusterTemplate, *infrav1.RouterFilter]{
GetField: func(c *infrav1.OpenStackClusterTemplate) **infrav1.RouterFilter {
return &c.Spec.Template.Spec.Router
@@ -204,7 +204,7 @@ var v1alpha7OpenStackClusterTemplateRestorer = conversion.RestorerFor[*infrav1.O
GetField: func(c *infrav1.OpenStackClusterTemplate) **infrav1.Bastion {
return &c.Spec.Template.Spec.Bastion
},
- RestoreField: restorev1alpha7Bastion,
+ RestoreField: restorev1alpha8Bastion,
},
}
@@ -214,8 +214,8 @@ func (r *OpenStackClusterTemplate) ConvertTo(dstRaw ctrlconversion.Hub) error {
compare := &OpenStackClusterTemplate{}
return conversion.ConvertAndRestore(
r, dst, compare,
- Convert_v1alpha6_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate, Convert_v1alpha7_OpenStackClusterTemplate_To_v1alpha6_OpenStackClusterTemplate,
- v1alpha6OpenStackClusterTemplateRestorer, v1alpha7OpenStackClusterTemplateRestorer,
+ Convert_v1alpha6_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate, Convert_v1alpha8_OpenStackClusterTemplate_To_v1alpha6_OpenStackClusterTemplate,
+ v1alpha6OpenStackClusterTemplateRestorer, v1alpha8OpenStackClusterTemplateRestorer,
)
}
@@ -225,8 +225,8 @@ func (r *OpenStackClusterTemplate) ConvertFrom(srcRaw ctrlconversion.Hub) error
compare := &infrav1.OpenStackClusterTemplate{}
return conversion.ConvertAndRestore(
src, r, compare,
- Convert_v1alpha7_OpenStackClusterTemplate_To_v1alpha6_OpenStackClusterTemplate, Convert_v1alpha6_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate,
- v1alpha7OpenStackClusterTemplateRestorer, v1alpha6OpenStackClusterTemplateRestorer,
+ Convert_v1alpha8_OpenStackClusterTemplate_To_v1alpha6_OpenStackClusterTemplate, Convert_v1alpha6_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate,
+ v1alpha8OpenStackClusterTemplateRestorer, v1alpha6OpenStackClusterTemplateRestorer,
)
}
@@ -254,12 +254,12 @@ var v1alpha6OpenStackMachineRestorer = conversion.RestorerFor[*OpenStackMachine]
},
}
-var v1alpha7OpenStackMachineRestorer = conversion.RestorerFor[*infrav1.OpenStackMachine]{
+var v1alpha8OpenStackMachineRestorer = conversion.RestorerFor[*infrav1.OpenStackMachine]{
"spec": conversion.HashedFieldRestorer[*infrav1.OpenStackMachine, infrav1.OpenStackMachineSpec]{
GetField: func(c *infrav1.OpenStackMachine) *infrav1.OpenStackMachineSpec {
return &c.Spec
},
- RestoreField: restorev1alpha7MachineSpec,
+ RestoreField: restorev1alpha8MachineSpec,
},
}
@@ -269,8 +269,8 @@ func (r *OpenStackMachine) ConvertTo(dstRaw ctrlconversion.Hub) error {
compare := &OpenStackMachine{}
return conversion.ConvertAndRestore(
r, dst, compare,
- Convert_v1alpha6_OpenStackMachine_To_v1alpha7_OpenStackMachine, Convert_v1alpha7_OpenStackMachine_To_v1alpha6_OpenStackMachine,
- v1alpha6OpenStackMachineRestorer, v1alpha7OpenStackMachineRestorer,
+ Convert_v1alpha6_OpenStackMachine_To_v1alpha8_OpenStackMachine, Convert_v1alpha8_OpenStackMachine_To_v1alpha6_OpenStackMachine,
+ v1alpha6OpenStackMachineRestorer, v1alpha8OpenStackMachineRestorer,
)
}
@@ -280,8 +280,8 @@ func (r *OpenStackMachine) ConvertFrom(srcRaw ctrlconversion.Hub) error {
compare := &infrav1.OpenStackMachine{}
return conversion.ConvertAndRestore(
src, r, compare,
- Convert_v1alpha7_OpenStackMachine_To_v1alpha6_OpenStackMachine, Convert_v1alpha6_OpenStackMachine_To_v1alpha7_OpenStackMachine,
- v1alpha7OpenStackMachineRestorer, v1alpha6OpenStackMachineRestorer,
+ Convert_v1alpha8_OpenStackMachine_To_v1alpha6_OpenStackMachine, Convert_v1alpha6_OpenStackMachine_To_v1alpha8_OpenStackMachine,
+ v1alpha8OpenStackMachineRestorer, v1alpha6OpenStackMachineRestorer,
)
}
@@ -289,12 +289,12 @@ 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)
+ return Convert_v1alpha6_OpenStackMachineList_To_v1alpha8_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)
+ return Convert_v1alpha8_OpenStackMachineList_To_v1alpha6_OpenStackMachineList(src, r, nil)
}
var _ ctrlconversion.Convertible = &OpenStackMachineTemplate{}
@@ -308,12 +308,12 @@ var v1alpha6OpenStackMachineTemplateRestorer = conversion.RestorerFor[*OpenStack
},
}
-var v1alpha7OpenStackMachineTemplateRestorer = conversion.RestorerFor[*infrav1.OpenStackMachineTemplate]{
+var v1alpha8OpenStackMachineTemplateRestorer = 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,
+ RestoreField: restorev1alpha8MachineSpec,
},
}
@@ -323,8 +323,8 @@ func (r *OpenStackMachineTemplate) ConvertTo(dstRaw ctrlconversion.Hub) error {
compare := &OpenStackMachineTemplate{}
return conversion.ConvertAndRestore(
r, dst, compare,
- Convert_v1alpha6_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate, Convert_v1alpha7_OpenStackMachineTemplate_To_v1alpha6_OpenStackMachineTemplate,
- v1alpha6OpenStackMachineTemplateRestorer, v1alpha7OpenStackMachineTemplateRestorer,
+ Convert_v1alpha6_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate, Convert_v1alpha8_OpenStackMachineTemplate_To_v1alpha6_OpenStackMachineTemplate,
+ v1alpha6OpenStackMachineTemplateRestorer, v1alpha8OpenStackMachineTemplateRestorer,
)
}
@@ -334,8 +334,8 @@ func (r *OpenStackMachineTemplate) ConvertFrom(srcRaw ctrlconversion.Hub) error
compare := &infrav1.OpenStackMachineTemplate{}
return conversion.ConvertAndRestore(
src, r, compare,
- Convert_v1alpha7_OpenStackMachineTemplate_To_v1alpha6_OpenStackMachineTemplate, Convert_v1alpha6_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate,
- v1alpha7OpenStackMachineTemplateRestorer, v1alpha6OpenStackMachineTemplateRestorer,
+ Convert_v1alpha8_OpenStackMachineTemplate_To_v1alpha6_OpenStackMachineTemplate, Convert_v1alpha6_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate,
+ v1alpha8OpenStackMachineTemplateRestorer, v1alpha6OpenStackMachineTemplateRestorer,
)
}
@@ -343,16 +343,16 @@ 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)
+ return Convert_v1alpha6_OpenStackMachineTemplateList_To_v1alpha8_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)
+ return Convert_v1alpha8_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)
+func Convert_v1alpha6_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(in *OpenStackMachineSpec, out *infrav1.OpenStackMachineSpec, s apiconversion.Scope) error {
+ err := autoConvert_v1alpha6_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(in, out, s)
if err != nil {
return err
}
@@ -431,21 +431,21 @@ func convertNetworksToPorts(networks []NetworkParam) []infrav1.PortOpts {
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_v1alpha8_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(in *infrav1.OpenStackClusterSpec, out *OpenStackClusterSpec, s apiconversion.Scope) error {
+ return autoConvert_v1alpha8_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)
+func Convert_v1alpha6_PortOpts_To_v1alpha8_PortOpts(in *PortOpts, out *infrav1.PortOpts, s apiconversion.Scope) error {
+ err := autoConvert_v1alpha6_PortOpts_To_v1alpha8_PortOpts(in, out, s)
if err != nil {
return err
}
- // SecurityGroups are removed in v1alpha7 without replacement. SecurityGroupFilters can be used instead.
+ // SecurityGroups are removed in v1alpha8 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.
+ // Profile is now a struct in v1alpha8.
if strings.Contains(in.Profile["capabilities"], "switchdev") {
out.Profile.OVSHWOffload = true
}
@@ -455,9 +455,9 @@ func Convert_v1alpha6_PortOpts_To_v1alpha7_PortOpts(in *PortOpts, out *infrav1.P
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)
+func Convert_v1alpha8_PortOpts_To_v1alpha6_PortOpts(in *infrav1.PortOpts, out *PortOpts, s apiconversion.Scope) error {
+ // value specs and propagate uplink status have been added in v1alpha8 but have no equivalent in v1alpha5
+ err := autoConvert_v1alpha8_PortOpts_To_v1alpha6_PortOpts(in, out, s)
if err != nil {
return err
}
@@ -472,7 +472,7 @@ func Convert_v1alpha7_PortOpts_To_v1alpha6_PortOpts(in *infrav1.PortOpts, out *P
return nil
}
-func Convert_v1alpha6_Instance_To_v1alpha7_BastionStatus(in *Instance, out *infrav1.BastionStatus, _ apiconversion.Scope) error {
+func Convert_v1alpha6_Instance_To_v1alpha8_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
@@ -483,7 +483,7 @@ func Convert_v1alpha6_Instance_To_v1alpha7_BastionStatus(in *Instance, out *infr
return nil
}
-func Convert_v1alpha7_BastionStatus_To_v1alpha6_Instance(in *infrav1.BastionStatus, out *Instance, _ apiconversion.Scope) error {
+func Convert_v1alpha8_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
@@ -494,9 +494,9 @@ func Convert_v1alpha7_BastionStatus_To_v1alpha6_Instance(in *infrav1.BastionStat
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)
+func Convert_v1alpha6_Network_To_v1alpha8_NetworkStatusWithSubnets(in *Network, out *infrav1.NetworkStatusWithSubnets, s apiconversion.Scope) error {
+ // PortOpts has been removed in v1alpha8
+ err := Convert_v1alpha6_Network_To_v1alpha8_NetworkStatus(in, &out.NetworkStatus, s)
if err != nil {
return err
}
@@ -507,9 +507,9 @@ func Convert_v1alpha6_Network_To_v1alpha7_NetworkStatusWithSubnets(in *Network,
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)
+func Convert_v1alpha8_NetworkStatusWithSubnets_To_v1alpha6_Network(in *infrav1.NetworkStatusWithSubnets, out *Network, s apiconversion.Scope) error {
+ // PortOpts has been removed in v1alpha8
+ err := Convert_v1alpha8_NetworkStatus_To_v1alpha6_Network(&in.NetworkStatus, out, s)
if err != nil {
return err
}
@@ -521,7 +521,7 @@ func Convert_v1alpha7_NetworkStatusWithSubnets_To_v1alpha6_Network(in *infrav1.N
return nil
}
-func Convert_v1alpha6_Network_To_v1alpha7_NetworkStatus(in *Network, out *infrav1.NetworkStatus, _ apiconversion.Scope) error {
+func Convert_v1alpha6_Network_To_v1alpha8_NetworkStatus(in *Network, out *infrav1.NetworkStatus, _ apiconversion.Scope) error {
out.ID = in.ID
out.Name = in.Name
out.Tags = in.Tags
@@ -529,7 +529,7 @@ func Convert_v1alpha6_Network_To_v1alpha7_NetworkStatus(in *Network, out *infrav
return nil
}
-func Convert_v1alpha7_NetworkStatus_To_v1alpha6_Network(in *infrav1.NetworkStatus, out *Network, _ apiconversion.Scope) error {
+func Convert_v1alpha8_NetworkStatus_To_v1alpha6_Network(in *infrav1.NetworkStatus, out *Network, _ apiconversion.Scope) error {
out.ID = in.ID
out.Name = in.Name
out.Tags = in.Tags
@@ -537,13 +537,13 @@ func Convert_v1alpha7_NetworkStatus_To_v1alpha6_Network(in *infrav1.NetworkStatu
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)
+func Convert_v1alpha6_SecurityGroupFilter_To_v1alpha8_SecurityGroupFilter(in *SecurityGroupFilter, out *infrav1.SecurityGroupFilter, s apiconversion.Scope) error {
+ err := autoConvert_v1alpha6_SecurityGroupFilter_To_v1alpha8_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.
+ // TenantID has been removed in v1alpha8. Write it to ProjectID if ProjectID is not already set.
if out.ProjectID == "" {
out.ProjectID = in.TenantID
}
@@ -551,9 +551,9 @@ func Convert_v1alpha6_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in *Se
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)
+func Convert_v1alpha6_SecurityGroupParam_To_v1alpha8_SecurityGroupFilter(in *SecurityGroupParam, out *infrav1.SecurityGroupFilter, s apiconversion.Scope) error {
+ // SecurityGroupParam is replaced by its contained SecurityGroupFilter in v1alpha8
+ err := Convert_v1alpha6_SecurityGroupFilter_To_v1alpha8_SecurityGroupFilter(&in.Filter, out, s)
if err != nil {
return err
}
@@ -567,9 +567,9 @@ func Convert_v1alpha6_SecurityGroupParam_To_v1alpha7_SecurityGroupFilter(in *Sec
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)
+func Convert_v1alpha8_SecurityGroupFilter_To_v1alpha6_SecurityGroupParam(in *infrav1.SecurityGroupFilter, out *SecurityGroupParam, s apiconversion.Scope) error {
+ // SecurityGroupParam is replaced by its contained SecurityGroupFilter in v1alpha8
+ err := Convert_v1alpha8_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(in, &out.Filter, s)
if err != nil {
return err
}
@@ -583,7 +583,7 @@ func Convert_v1alpha7_SecurityGroupFilter_To_v1alpha6_SecurityGroupParam(in *inf
return nil
}
-func Convert_v1alpha6_SubnetParam_To_v1alpha7_SubnetFilter(in *SubnetParam, out *infrav1.SubnetFilter, _ apiconversion.Scope) error {
+func Convert_v1alpha6_SubnetParam_To_v1alpha8_SubnetFilter(in *SubnetParam, out *infrav1.SubnetFilter, _ apiconversion.Scope) error {
*out = infrav1.SubnetFilter(in.Filter)
if in.UUID != "" {
out.ID = in.UUID
@@ -591,14 +591,14 @@ func Convert_v1alpha6_SubnetParam_To_v1alpha7_SubnetFilter(in *SubnetParam, out
return nil
}
-func Convert_v1alpha7_SubnetFilter_To_v1alpha6_SubnetParam(in *infrav1.SubnetFilter, out *SubnetParam, _ apiconversion.Scope) error {
+func Convert_v1alpha8_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 {
+func Convert_Map_string_To_Interface_To_v1alpha8_BindingProfile(in map[string]string, out *infrav1.BindingProfile, _ apiconversion.Scope) error {
for k, v := range in {
if k == "capabilities" {
if strings.Contains(v, "switchdev") {
@@ -612,7 +612,7 @@ func Convert_Map_string_To_Interface_To_v1alpha7_BindingProfile(in map[string]st
return nil
}
-func Convert_v1alpha7_BindingProfile_To_Map_string_To_Interface(in *infrav1.BindingProfile, out map[string]string, _ apiconversion.Scope) error {
+func Convert_v1alpha8_BindingProfile_To_Map_string_To_Interface(in *infrav1.BindingProfile, out map[string]string, _ apiconversion.Scope) error {
if in.OVSHWOffload {
(out)["capabilities"] = "[\"switchdev\"]"
}
@@ -622,13 +622,13 @@ func Convert_v1alpha7_BindingProfile_To_Map_string_To_Interface(in *infrav1.Bind
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)
+func Convert_v1alpha8_OpenStackClusterStatus_To_v1alpha6_OpenStackClusterStatus(in *infrav1.OpenStackClusterStatus, out *OpenStackClusterStatus, s apiconversion.Scope) error {
+ err := autoConvert_v1alpha8_OpenStackClusterStatus_To_v1alpha6_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 v1alpha8
if in.Router != nil || in.APIServerLoadBalancer != nil {
if out.Network == nil {
out.Network = &Network{}
@@ -641,13 +641,13 @@ func Convert_v1alpha7_OpenStackClusterStatus_To_v1alpha6_OpenStackClusterStatus(
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)
+func Convert_v1alpha6_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterStatus(in *OpenStackClusterStatus, out *infrav1.OpenStackClusterStatus, s apiconversion.Scope) error {
+ err := autoConvert_v1alpha6_OpenStackClusterStatus_To_v1alpha8_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 v1alpha8
if in.Network != nil {
out.Router = (*infrav1.Router)(in.Network.Router)
out.APIServerLoadBalancer = (*infrav1.LoadBalancer)(in.Network.APIServerLoadBalancer)
@@ -656,6 +656,6 @@ func Convert_v1alpha6_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(
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)
+func Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(in *infrav1.OpenStackMachineSpec, out *OpenStackMachineSpec, s apiconversion.Scope) error {
+ return autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(in, out, s)
}
diff --git a/api/v1alpha6/conversion_test.go b/api/v1alpha6/conversion_test.go
index a89815b285..7f67ad9ef9 100644
--- a/api/v1alpha6/conversion_test.go
+++ b/api/v1alpha6/conversion_test.go
@@ -29,7 +29,7 @@ import (
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/v1alpha8"
testhelpers "sigs.k8s.io/cluster-api-provider-openstack/test/helpers"
)
diff --git a/api/v1alpha6/doc.go b/api/v1alpha6/doc.go
index 721815c0fe..e0fde58a62 100644
--- a/api/v1alpha6/doc.go
+++ b/api/v1alpha6/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/v1alpha8
package v1alpha6
diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go
index 6bfa0129c3..ec1a8020f7 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.
@@ -27,7 +27,7 @@ import (
v1 "k8s.io/api/core/v1"
conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime"
- v1alpha7 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
+ v1alpha8 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
v1beta1 "sigs.k8s.io/cluster-api/api/v1beta1"
errors "sigs.k8s.io/cluster-api/errors"
)
@@ -39,390 +39,390 @@ 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((*APIServerLoadBalancer)(nil), (*v1alpha8.APIServerLoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalancer(a.(*APIServerLoadBalancer), b.(*v1alpha8.APIServerLoadBalancer), 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((*v1alpha8.APIServerLoadBalancer)(nil), (*APIServerLoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalancer(a.(*v1alpha8.APIServerLoadBalancer), b.(*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_v1alpha6_AddressPair_To_v1alpha7_AddressPair(a.(*AddressPair), b.(*v1alpha7.AddressPair), scope)
+ if err := s.AddGeneratedConversionFunc((*AddressPair)(nil), (*v1alpha8.AddressPair)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_AddressPair_To_v1alpha8_AddressPair(a.(*AddressPair), b.(*v1alpha8.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_v1alpha6_AddressPair(a.(*v1alpha7.AddressPair), b.(*AddressPair), scope)
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.AddressPair)(nil), (*AddressPair)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_AddressPair_To_v1alpha6_AddressPair(a.(*v1alpha8.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_v1alpha6_Bastion_To_v1alpha7_Bastion(a.(*Bastion), b.(*v1alpha7.Bastion), scope)
+ if err := s.AddGeneratedConversionFunc((*Bastion)(nil), (*v1alpha8.Bastion)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_Bastion_To_v1alpha8_Bastion(a.(*Bastion), b.(*v1alpha8.Bastion), 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((*v1alpha8.Bastion)(nil), (*Bastion)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_Bastion_To_v1alpha6_Bastion(a.(*v1alpha8.Bastion), b.(*Bastion), 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((*ExternalRouterIPParam)(nil), (*v1alpha8.ExternalRouterIPParam)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_ExternalRouterIPParam_To_v1alpha8_ExternalRouterIPParam(a.(*ExternalRouterIPParam), b.(*v1alpha8.ExternalRouterIPParam), 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((*v1alpha8.ExternalRouterIPParam)(nil), (*ExternalRouterIPParam)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_ExternalRouterIPParam_To_v1alpha6_ExternalRouterIPParam(a.(*v1alpha8.ExternalRouterIPParam), b.(*ExternalRouterIPParam), 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((*FixedIP)(nil), (*v1alpha8.FixedIP)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_FixedIP_To_v1alpha8_FixedIP(a.(*FixedIP), b.(*v1alpha8.FixedIP), 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((*v1alpha8.FixedIP)(nil), (*FixedIP)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_FixedIP_To_v1alpha6_FixedIP(a.(*v1alpha8.FixedIP), b.(*FixedIP), 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((*LoadBalancer)(nil), (*v1alpha8.LoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_LoadBalancer_To_v1alpha8_LoadBalancer(a.(*LoadBalancer), b.(*v1alpha8.LoadBalancer), 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((*v1alpha8.LoadBalancer)(nil), (*LoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_LoadBalancer_To_v1alpha6_LoadBalancer(a.(*v1alpha8.LoadBalancer), b.(*LoadBalancer), 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((*NetworkFilter)(nil), (*v1alpha8.NetworkFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_NetworkFilter_To_v1alpha8_NetworkFilter(a.(*NetworkFilter), b.(*v1alpha8.NetworkFilter), 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((*v1alpha8.NetworkFilter)(nil), (*NetworkFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_NetworkFilter_To_v1alpha6_NetworkFilter(a.(*v1alpha8.NetworkFilter), b.(*NetworkFilter), 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((*OpenStackCluster)(nil), (*v1alpha8.OpenStackCluster)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_OpenStackCluster_To_v1alpha8_OpenStackCluster(a.(*OpenStackCluster), b.(*v1alpha8.OpenStackCluster), 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((*v1alpha8.OpenStackCluster)(nil), (*OpenStackCluster)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackCluster_To_v1alpha6_OpenStackCluster(a.(*v1alpha8.OpenStackCluster), b.(*OpenStackCluster), 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((*OpenStackClusterList)(nil), (*v1alpha8.OpenStackClusterList)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_OpenStackClusterList_To_v1alpha8_OpenStackClusterList(a.(*OpenStackClusterList), b.(*v1alpha8.OpenStackClusterList), 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((*v1alpha8.OpenStackClusterList)(nil), (*OpenStackClusterList)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackClusterList_To_v1alpha6_OpenStackClusterList(a.(*v1alpha8.OpenStackClusterList), b.(*OpenStackClusterList), 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((*OpenStackClusterSpec)(nil), (*v1alpha8.OpenStackClusterSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(a.(*OpenStackClusterSpec), b.(*v1alpha8.OpenStackClusterSpec), 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((*OpenStackClusterTemplate)(nil), (*v1alpha8.OpenStackClusterTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate(a.(*OpenStackClusterTemplate), b.(*v1alpha8.OpenStackClusterTemplate), 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((*v1alpha8.OpenStackClusterTemplate)(nil), (*OpenStackClusterTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackClusterTemplate_To_v1alpha6_OpenStackClusterTemplate(a.(*v1alpha8.OpenStackClusterTemplate), b.(*OpenStackClusterTemplate), 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((*OpenStackClusterTemplateList)(nil), (*v1alpha8.OpenStackClusterTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_OpenStackClusterTemplateList_To_v1alpha8_OpenStackClusterTemplateList(a.(*OpenStackClusterTemplateList), b.(*v1alpha8.OpenStackClusterTemplateList), 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((*v1alpha8.OpenStackClusterTemplateList)(nil), (*OpenStackClusterTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackClusterTemplateList_To_v1alpha6_OpenStackClusterTemplateList(a.(*v1alpha8.OpenStackClusterTemplateList), b.(*OpenStackClusterTemplateList), 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((*OpenStackClusterTemplateResource)(nil), (*v1alpha8.OpenStackClusterTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_OpenStackClusterTemplateResource_To_v1alpha8_OpenStackClusterTemplateResource(a.(*OpenStackClusterTemplateResource), b.(*v1alpha8.OpenStackClusterTemplateResource), 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((*v1alpha8.OpenStackClusterTemplateResource)(nil), (*OpenStackClusterTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackClusterTemplateResource_To_v1alpha6_OpenStackClusterTemplateResource(a.(*v1alpha8.OpenStackClusterTemplateResource), b.(*OpenStackClusterTemplateResource), 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((*OpenStackClusterTemplateSpec)(nil), (*v1alpha8.OpenStackClusterTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_OpenStackClusterTemplateSpec_To_v1alpha8_OpenStackClusterTemplateSpec(a.(*OpenStackClusterTemplateSpec), b.(*v1alpha8.OpenStackClusterTemplateSpec), 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((*v1alpha8.OpenStackClusterTemplateSpec)(nil), (*OpenStackClusterTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackClusterTemplateSpec_To_v1alpha6_OpenStackClusterTemplateSpec(a.(*v1alpha8.OpenStackClusterTemplateSpec), b.(*OpenStackClusterTemplateSpec), 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((*OpenStackIdentityReference)(nil), (*v1alpha8.OpenStackIdentityReference)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(a.(*OpenStackIdentityReference), b.(*v1alpha8.OpenStackIdentityReference), 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((*v1alpha8.OpenStackIdentityReference)(nil), (*OpenStackIdentityReference)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackIdentityReference_To_v1alpha6_OpenStackIdentityReference(a.(*v1alpha8.OpenStackIdentityReference), b.(*OpenStackIdentityReference), 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((*OpenStackMachine)(nil), (*v1alpha8.OpenStackMachine)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_OpenStackMachine_To_v1alpha8_OpenStackMachine(a.(*OpenStackMachine), b.(*v1alpha8.OpenStackMachine), 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((*v1alpha8.OpenStackMachine)(nil), (*OpenStackMachine)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackMachine_To_v1alpha6_OpenStackMachine(a.(*v1alpha8.OpenStackMachine), b.(*OpenStackMachine), 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((*OpenStackMachineList)(nil), (*v1alpha8.OpenStackMachineList)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_OpenStackMachineList_To_v1alpha8_OpenStackMachineList(a.(*OpenStackMachineList), b.(*v1alpha8.OpenStackMachineList), 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((*v1alpha8.OpenStackMachineList)(nil), (*OpenStackMachineList)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackMachineList_To_v1alpha6_OpenStackMachineList(a.(*v1alpha8.OpenStackMachineList), b.(*OpenStackMachineList), 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((*OpenStackMachineStatus)(nil), (*v1alpha8.OpenStackMachineStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_OpenStackMachineStatus_To_v1alpha8_OpenStackMachineStatus(a.(*OpenStackMachineStatus), b.(*v1alpha8.OpenStackMachineStatus), 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((*v1alpha8.OpenStackMachineStatus)(nil), (*OpenStackMachineStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackMachineStatus_To_v1alpha6_OpenStackMachineStatus(a.(*v1alpha8.OpenStackMachineStatus), b.(*OpenStackMachineStatus), 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((*OpenStackMachineTemplate)(nil), (*v1alpha8.OpenStackMachineTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate(a.(*OpenStackMachineTemplate), b.(*v1alpha8.OpenStackMachineTemplate), 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.AddGeneratedConversionFunc((*v1alpha8.OpenStackMachineTemplate)(nil), (*OpenStackMachineTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackMachineTemplate_To_v1alpha6_OpenStackMachineTemplate(a.(*v1alpha8.OpenStackMachineTemplate), b.(*OpenStackMachineTemplate), 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.AddGeneratedConversionFunc((*OpenStackMachineTemplateList)(nil), (*v1alpha8.OpenStackMachineTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_OpenStackMachineTemplateList_To_v1alpha8_OpenStackMachineTemplateList(a.(*OpenStackMachineTemplateList), b.(*v1alpha8.OpenStackMachineTemplateList), 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.AddGeneratedConversionFunc((*v1alpha8.OpenStackMachineTemplateList)(nil), (*OpenStackMachineTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackMachineTemplateList_To_v1alpha6_OpenStackMachineTemplateList(a.(*v1alpha8.OpenStackMachineTemplateList), b.(*OpenStackMachineTemplateList), 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.AddGeneratedConversionFunc((*OpenStackMachineTemplateResource)(nil), (*v1alpha8.OpenStackMachineTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_OpenStackMachineTemplateResource_To_v1alpha8_OpenStackMachineTemplateResource(a.(*OpenStackMachineTemplateResource), b.(*v1alpha8.OpenStackMachineTemplateResource), 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.AddGeneratedConversionFunc((*v1alpha8.OpenStackMachineTemplateResource)(nil), (*OpenStackMachineTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackMachineTemplateResource_To_v1alpha6_OpenStackMachineTemplateResource(a.(*v1alpha8.OpenStackMachineTemplateResource), b.(*OpenStackMachineTemplateResource), 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.AddGeneratedConversionFunc((*OpenStackMachineTemplateSpec)(nil), (*v1alpha8.OpenStackMachineTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_OpenStackMachineTemplateSpec_To_v1alpha8_OpenStackMachineTemplateSpec(a.(*OpenStackMachineTemplateSpec), b.(*v1alpha8.OpenStackMachineTemplateSpec), 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.AddGeneratedConversionFunc((*v1alpha8.OpenStackMachineTemplateSpec)(nil), (*OpenStackMachineTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackMachineTemplateSpec_To_v1alpha6_OpenStackMachineTemplateSpec(a.(*v1alpha8.OpenStackMachineTemplateSpec), b.(*OpenStackMachineTemplateSpec), 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.AddGeneratedConversionFunc((*RootVolume)(nil), (*v1alpha8.RootVolume)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_RootVolume_To_v1alpha8_RootVolume(a.(*RootVolume), b.(*v1alpha8.RootVolume), 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.AddGeneratedConversionFunc((*v1alpha8.RootVolume)(nil), (*RootVolume)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_RootVolume_To_v1alpha6_RootVolume(a.(*v1alpha8.RootVolume), b.(*RootVolume), 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.AddGeneratedConversionFunc((*Router)(nil), (*v1alpha8.Router)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_Router_To_v1alpha8_Router(a.(*Router), b.(*v1alpha8.Router), 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.AddGeneratedConversionFunc((*v1alpha8.Router)(nil), (*Router)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_Router_To_v1alpha6_Router(a.(*v1alpha8.Router), b.(*Router), 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.AddGeneratedConversionFunc((*SecurityGroup)(nil), (*v1alpha8.SecurityGroup)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_SecurityGroup_To_v1alpha8_SecurityGroup(a.(*SecurityGroup), b.(*v1alpha8.SecurityGroup), 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.AddGeneratedConversionFunc((*v1alpha8.SecurityGroup)(nil), (*SecurityGroup)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_SecurityGroup_To_v1alpha6_SecurityGroup(a.(*v1alpha8.SecurityGroup), b.(*SecurityGroup), 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.AddGeneratedConversionFunc((*v1alpha8.SecurityGroupFilter)(nil), (*SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(a.(*v1alpha8.SecurityGroupFilter), b.(*SecurityGroupFilter), 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.AddGeneratedConversionFunc((*SecurityGroupRule)(nil), (*v1alpha8.SecurityGroupRule)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_SecurityGroupRule_To_v1alpha8_SecurityGroupRule(a.(*SecurityGroupRule), b.(*v1alpha8.SecurityGroupRule), 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.AddGeneratedConversionFunc((*v1alpha8.SecurityGroupRule)(nil), (*SecurityGroupRule)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_SecurityGroupRule_To_v1alpha6_SecurityGroupRule(a.(*v1alpha8.SecurityGroupRule), b.(*SecurityGroupRule), 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.AddGeneratedConversionFunc((*Subnet)(nil), (*v1alpha8.Subnet)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_Subnet_To_v1alpha8_Subnet(a.(*Subnet), b.(*v1alpha8.Subnet), 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.AddGeneratedConversionFunc((*v1alpha8.Subnet)(nil), (*Subnet)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_Subnet_To_v1alpha6_Subnet(a.(*v1alpha8.Subnet), b.(*Subnet), 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.AddGeneratedConversionFunc((*SubnetFilter)(nil), (*v1alpha8.SubnetFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_SubnetFilter_To_v1alpha8_SubnetFilter(a.(*SubnetFilter), b.(*v1alpha8.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.AddGeneratedConversionFunc((*v1alpha8.SubnetFilter)(nil), (*SubnetFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_SubnetFilter_To_v1alpha6_SubnetFilter(a.(*v1alpha8.SubnetFilter), b.(*SubnetFilter), 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.AddGeneratedConversionFunc((*ValueSpec)(nil), (*v1alpha8.ValueSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_ValueSpec_To_v1alpha8_ValueSpec(a.(*ValueSpec), b.(*v1alpha8.ValueSpec), 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.AddGeneratedConversionFunc((*v1alpha8.ValueSpec)(nil), (*ValueSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_ValueSpec_To_v1alpha6_ValueSpec(a.(*v1alpha8.ValueSpec), b.(*ValueSpec), 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((*Instance)(nil), (*v1alpha8.BastionStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_Instance_To_v1alpha8_BastionStatus(a.(*Instance), b.(*v1alpha8.BastionStatus), 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((*Network)(nil), (*v1alpha8.NetworkStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_Network_To_v1alpha8_NetworkStatus(a.(*Network), b.(*v1alpha8.NetworkStatus), 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((*Network)(nil), (*v1alpha8.NetworkStatusWithSubnets)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_Network_To_v1alpha8_NetworkStatusWithSubnets(a.(*Network), b.(*v1alpha8.NetworkStatusWithSubnets), 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((*OpenStackClusterStatus)(nil), (*v1alpha8.OpenStackClusterStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterStatus(a.(*OpenStackClusterStatus), b.(*v1alpha8.OpenStackClusterStatus), 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((*OpenStackMachineSpec)(nil), (*v1alpha8.OpenStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(a.(*OpenStackMachineSpec), b.(*v1alpha8.OpenStackMachineSpec), 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((*PortOpts)(nil), (*v1alpha8.PortOpts)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_PortOpts_To_v1alpha8_PortOpts(a.(*PortOpts), b.(*v1alpha8.PortOpts), 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((*SecurityGroupFilter)(nil), (*v1alpha8.SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_SecurityGroupFilter_To_v1alpha8_SecurityGroupFilter(a.(*SecurityGroupFilter), b.(*v1alpha8.SecurityGroupFilter), 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((*SecurityGroupParam)(nil), (*v1alpha8.SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_SecurityGroupParam_To_v1alpha8_SecurityGroupFilter(a.(*SecurityGroupParam), b.(*v1alpha8.SecurityGroupFilter), 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((*SubnetParam)(nil), (*v1alpha8.SubnetFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_SubnetParam_To_v1alpha8_SubnetFilter(a.(*SubnetParam), b.(*v1alpha8.SubnetFilter), 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((*v1alpha8.BastionStatus)(nil), (*Instance)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_BastionStatus_To_v1alpha6_Instance(a.(*v1alpha8.BastionStatus), b.(*Instance), 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((*v1alpha8.NetworkStatusWithSubnets)(nil), (*Network)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_NetworkStatusWithSubnets_To_v1alpha6_Network(a.(*v1alpha8.NetworkStatusWithSubnets), b.(*Network), 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((*v1alpha8.NetworkStatus)(nil), (*Network)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_NetworkStatus_To_v1alpha6_Network(a.(*v1alpha8.NetworkStatus), b.(*Network), 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((*v1alpha8.OpenStackClusterSpec)(nil), (*OpenStackClusterSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(a.(*v1alpha8.OpenStackClusterSpec), b.(*OpenStackClusterSpec), 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((*v1alpha8.OpenStackClusterStatus)(nil), (*OpenStackClusterStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackClusterStatus_To_v1alpha6_OpenStackClusterStatus(a.(*v1alpha8.OpenStackClusterStatus), b.(*OpenStackClusterStatus), 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((*v1alpha8.OpenStackMachineSpec)(nil), (*OpenStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(a.(*v1alpha8.OpenStackMachineSpec), b.(*OpenStackMachineSpec), 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((*v1alpha8.PortOpts)(nil), (*PortOpts)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_PortOpts_To_v1alpha6_PortOpts(a.(*v1alpha8.PortOpts), b.(*PortOpts), 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((*v1alpha8.SecurityGroupFilter)(nil), (*SecurityGroupParam)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_SecurityGroupFilter_To_v1alpha6_SecurityGroupParam(a.(*v1alpha8.SecurityGroupFilter), b.(*SecurityGroupParam), 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((*v1alpha8.SubnetFilter)(nil), (*SubnetParam)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_SubnetFilter_To_v1alpha6_SubnetParam(a.(*v1alpha8.SubnetFilter), 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 {
+func autoConvert_v1alpha6_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalancer(in *APIServerLoadBalancer, out *v1alpha8.APIServerLoadBalancer, s conversion.Scope) error {
out.Enabled = in.Enabled
out.AdditionalPorts = *(*[]int)(unsafe.Pointer(&in.AdditionalPorts))
out.AllowedCIDRs = *(*[]string)(unsafe.Pointer(&in.AllowedCIDRs))
@@ -430,12 +430,12 @@ func autoConvert_v1alpha6_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalance
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)
+// Convert_v1alpha6_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalancer is an autogenerated conversion function.
+func Convert_v1alpha6_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalancer(in *APIServerLoadBalancer, out *v1alpha8.APIServerLoadBalancer, s conversion.Scope) error {
+ return autoConvert_v1alpha6_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalancer(in, out, s)
}
-func autoConvert_v1alpha7_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalancer(in *v1alpha7.APIServerLoadBalancer, out *APIServerLoadBalancer, s conversion.Scope) error {
+func autoConvert_v1alpha8_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalancer(in *v1alpha8.APIServerLoadBalancer, out *APIServerLoadBalancer, s conversion.Scope) error {
out.Enabled = in.Enabled
out.AdditionalPorts = *(*[]int)(unsafe.Pointer(&in.AdditionalPorts))
out.AllowedCIDRs = *(*[]string)(unsafe.Pointer(&in.AllowedCIDRs))
@@ -443,110 +443,110 @@ func autoConvert_v1alpha7_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalance
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)
+// Convert_v1alpha8_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalancer is an autogenerated conversion function.
+func Convert_v1alpha8_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalancer(in *v1alpha8.APIServerLoadBalancer, out *APIServerLoadBalancer, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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_v1alpha8_AddressPair(in *AddressPair, out *v1alpha8.AddressPair, s conversion.Scope) error {
out.IPAddress = in.IPAddress
out.MACAddress = in.MACAddress
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_v1alpha8_AddressPair is an autogenerated conversion function.
+func Convert_v1alpha6_AddressPair_To_v1alpha8_AddressPair(in *AddressPair, out *v1alpha8.AddressPair, s conversion.Scope) error {
+ return autoConvert_v1alpha6_AddressPair_To_v1alpha8_AddressPair(in, out, s)
}
-func autoConvert_v1alpha7_AddressPair_To_v1alpha6_AddressPair(in *v1alpha7.AddressPair, out *AddressPair, s conversion.Scope) error {
+func autoConvert_v1alpha8_AddressPair_To_v1alpha6_AddressPair(in *v1alpha8.AddressPair, out *AddressPair, s conversion.Scope) error {
out.IPAddress = in.IPAddress
out.MACAddress = in.MACAddress
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_v1alpha8_AddressPair_To_v1alpha6_AddressPair is an autogenerated conversion function.
+func Convert_v1alpha8_AddressPair_To_v1alpha6_AddressPair(in *v1alpha8.AddressPair, out *AddressPair, s conversion.Scope) error {
+ return autoConvert_v1alpha8_AddressPair_To_v1alpha6_AddressPair(in, out, s)
}
-func autoConvert_v1alpha6_Bastion_To_v1alpha7_Bastion(in *Bastion, out *v1alpha7.Bastion, s conversion.Scope) error {
+func autoConvert_v1alpha6_Bastion_To_v1alpha8_Bastion(in *Bastion, out *v1alpha8.Bastion, s conversion.Scope) error {
out.Enabled = in.Enabled
- if err := Convert_v1alpha6_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(&in.Instance, &out.Instance, s); err != nil {
+ if err := Convert_v1alpha6_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(&in.Instance, &out.Instance, 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)
+// Convert_v1alpha6_Bastion_To_v1alpha8_Bastion is an autogenerated conversion function.
+func Convert_v1alpha6_Bastion_To_v1alpha8_Bastion(in *Bastion, out *v1alpha8.Bastion, s conversion.Scope) error {
+ return autoConvert_v1alpha6_Bastion_To_v1alpha8_Bastion(in, out, s)
}
-func autoConvert_v1alpha7_Bastion_To_v1alpha6_Bastion(in *v1alpha7.Bastion, out *Bastion, s conversion.Scope) error {
+func autoConvert_v1alpha8_Bastion_To_v1alpha6_Bastion(in *v1alpha8.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 {
+ if err := Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(&in.Instance, &out.Instance, s); err != nil {
return err
}
out.AvailabilityZone = in.AvailabilityZone
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)
+// Convert_v1alpha8_Bastion_To_v1alpha6_Bastion is an autogenerated conversion function.
+func Convert_v1alpha8_Bastion_To_v1alpha6_Bastion(in *v1alpha8.Bastion, out *Bastion, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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_v1alpha8_ExternalRouterIPParam(in *ExternalRouterIPParam, out *v1alpha8.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_v1alpha8_SubnetFilter(&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_v1alpha8_ExternalRouterIPParam is an autogenerated conversion function.
+func Convert_v1alpha6_ExternalRouterIPParam_To_v1alpha8_ExternalRouterIPParam(in *ExternalRouterIPParam, out *v1alpha8.ExternalRouterIPParam, s conversion.Scope) error {
+ return autoConvert_v1alpha6_ExternalRouterIPParam_To_v1alpha8_ExternalRouterIPParam(in, out, s)
}
-func autoConvert_v1alpha7_ExternalRouterIPParam_To_v1alpha6_ExternalRouterIPParam(in *v1alpha7.ExternalRouterIPParam, out *ExternalRouterIPParam, s conversion.Scope) error {
+func autoConvert_v1alpha8_ExternalRouterIPParam_To_v1alpha6_ExternalRouterIPParam(in *v1alpha8.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_v1alpha8_SubnetFilter_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_v1alpha8_ExternalRouterIPParam_To_v1alpha6_ExternalRouterIPParam is an autogenerated conversion function.
+func Convert_v1alpha8_ExternalRouterIPParam_To_v1alpha6_ExternalRouterIPParam(in *v1alpha8.ExternalRouterIPParam, out *ExternalRouterIPParam, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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))
+func autoConvert_v1alpha6_FixedIP_To_v1alpha8_FixedIP(in *FixedIP, out *v1alpha8.FixedIP, s conversion.Scope) error {
+ out.Subnet = (*v1alpha8.SubnetFilter)(unsafe.Pointer(in.Subnet))
out.IPAddress = in.IPAddress
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_v1alpha8_FixedIP is an autogenerated conversion function.
+func Convert_v1alpha6_FixedIP_To_v1alpha8_FixedIP(in *FixedIP, out *v1alpha8.FixedIP, s conversion.Scope) error {
+ return autoConvert_v1alpha6_FixedIP_To_v1alpha8_FixedIP(in, out, s)
}
-func autoConvert_v1alpha7_FixedIP_To_v1alpha6_FixedIP(in *v1alpha7.FixedIP, out *FixedIP, s conversion.Scope) error {
+func autoConvert_v1alpha8_FixedIP_To_v1alpha6_FixedIP(in *v1alpha8.FixedIP, out *FixedIP, s conversion.Scope) error {
out.Subnet = (*SubnetFilter)(unsafe.Pointer(in.Subnet))
out.IPAddress = in.IPAddress
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_v1alpha8_FixedIP_To_v1alpha6_FixedIP is an autogenerated conversion function.
+func Convert_v1alpha8_FixedIP_To_v1alpha6_FixedIP(in *v1alpha8.FixedIP, out *FixedIP, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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_v1alpha8_LoadBalancer(in *LoadBalancer, out *v1alpha8.LoadBalancer, s conversion.Scope) error {
out.Name = in.Name
out.ID = in.ID
out.IP = in.IP
@@ -556,12 +556,12 @@ 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_v1alpha8_LoadBalancer is an autogenerated conversion function.
+func Convert_v1alpha6_LoadBalancer_To_v1alpha8_LoadBalancer(in *LoadBalancer, out *v1alpha8.LoadBalancer, s conversion.Scope) error {
+ return autoConvert_v1alpha6_LoadBalancer_To_v1alpha8_LoadBalancer(in, out, s)
}
-func autoConvert_v1alpha7_LoadBalancer_To_v1alpha6_LoadBalancer(in *v1alpha7.LoadBalancer, out *LoadBalancer, s conversion.Scope) error {
+func autoConvert_v1alpha8_LoadBalancer_To_v1alpha6_LoadBalancer(in *v1alpha8.LoadBalancer, out *LoadBalancer, s conversion.Scope) error {
out.Name = in.Name
out.ID = in.ID
out.IP = in.IP
@@ -571,12 +571,12 @@ func autoConvert_v1alpha7_LoadBalancer_To_v1alpha6_LoadBalancer(in *v1alpha7.Loa
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)
+// Convert_v1alpha8_LoadBalancer_To_v1alpha6_LoadBalancer is an autogenerated conversion function.
+func Convert_v1alpha8_LoadBalancer_To_v1alpha6_LoadBalancer(in *v1alpha8.LoadBalancer, out *LoadBalancer, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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_v1alpha8_NetworkFilter(in *NetworkFilter, out *v1alpha8.NetworkFilter, s conversion.Scope) error {
out.Name = in.Name
out.Description = in.Description
out.ProjectID = in.ProjectID
@@ -588,12 +588,12 @@ func autoConvert_v1alpha6_NetworkFilter_To_v1alpha7_NetworkFilter(in *NetworkFil
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)
+// Convert_v1alpha6_NetworkFilter_To_v1alpha8_NetworkFilter is an autogenerated conversion function.
+func Convert_v1alpha6_NetworkFilter_To_v1alpha8_NetworkFilter(in *NetworkFilter, out *v1alpha8.NetworkFilter, s conversion.Scope) error {
+ return autoConvert_v1alpha6_NetworkFilter_To_v1alpha8_NetworkFilter(in, out, s)
}
-func autoConvert_v1alpha7_NetworkFilter_To_v1alpha6_NetworkFilter(in *v1alpha7.NetworkFilter, out *NetworkFilter, s conversion.Scope) error {
+func autoConvert_v1alpha8_NetworkFilter_To_v1alpha6_NetworkFilter(in *v1alpha8.NetworkFilter, out *NetworkFilter, s conversion.Scope) error {
out.Name = in.Name
out.Description = in.Description
out.ProjectID = in.ProjectID
@@ -605,50 +605,50 @@ func autoConvert_v1alpha7_NetworkFilter_To_v1alpha6_NetworkFilter(in *v1alpha7.N
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)
+// Convert_v1alpha8_NetworkFilter_To_v1alpha6_NetworkFilter is an autogenerated conversion function.
+func Convert_v1alpha8_NetworkFilter_To_v1alpha6_NetworkFilter(in *v1alpha8.NetworkFilter, out *NetworkFilter, s conversion.Scope) error {
+ return autoConvert_v1alpha8_NetworkFilter_To_v1alpha6_NetworkFilter(in, out, s)
}
-func autoConvert_v1alpha6_OpenStackCluster_To_v1alpha7_OpenStackCluster(in *OpenStackCluster, out *v1alpha7.OpenStackCluster, s conversion.Scope) error {
+func autoConvert_v1alpha6_OpenStackCluster_To_v1alpha8_OpenStackCluster(in *OpenStackCluster, out *v1alpha8.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_v1alpha8_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_v1alpha8_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_v1alpha8_OpenStackCluster is an autogenerated conversion function.
+func Convert_v1alpha6_OpenStackCluster_To_v1alpha8_OpenStackCluster(in *OpenStackCluster, out *v1alpha8.OpenStackCluster, s conversion.Scope) error {
+ return autoConvert_v1alpha6_OpenStackCluster_To_v1alpha8_OpenStackCluster(in, out, s)
}
-func autoConvert_v1alpha7_OpenStackCluster_To_v1alpha6_OpenStackCluster(in *v1alpha7.OpenStackCluster, out *OpenStackCluster, s conversion.Scope) error {
+func autoConvert_v1alpha8_OpenStackCluster_To_v1alpha6_OpenStackCluster(in *v1alpha8.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_v1alpha8_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_v1alpha8_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_v1alpha8_OpenStackCluster_To_v1alpha6_OpenStackCluster is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackCluster_To_v1alpha6_OpenStackCluster(in *v1alpha8.OpenStackCluster, out *OpenStackCluster, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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_v1alpha8_OpenStackClusterList(in *OpenStackClusterList, out *v1alpha8.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([]v1alpha8.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_v1alpha8_OpenStackCluster(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -658,18 +658,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_v1alpha8_OpenStackClusterList is an autogenerated conversion function.
+func Convert_v1alpha6_OpenStackClusterList_To_v1alpha8_OpenStackClusterList(in *OpenStackClusterList, out *v1alpha8.OpenStackClusterList, s conversion.Scope) error {
+ return autoConvert_v1alpha6_OpenStackClusterList_To_v1alpha8_OpenStackClusterList(in, out, s)
}
-func autoConvert_v1alpha7_OpenStackClusterList_To_v1alpha6_OpenStackClusterList(in *v1alpha7.OpenStackClusterList, out *OpenStackClusterList, s conversion.Scope) error {
+func autoConvert_v1alpha8_OpenStackClusterList_To_v1alpha6_OpenStackClusterList(in *v1alpha8.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_v1alpha8_OpenStackCluster_To_v1alpha6_OpenStackCluster(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -679,26 +679,26 @@ 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_v1alpha8_OpenStackClusterList_To_v1alpha6_OpenStackClusterList is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackClusterList_To_v1alpha6_OpenStackClusterList(in *v1alpha8.OpenStackClusterList, out *OpenStackClusterList, s conversion.Scope) error {
+ return autoConvert_v1alpha8_OpenStackClusterList_To_v1alpha6_OpenStackClusterList(in, out, s)
}
-func autoConvert_v1alpha6_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in *OpenStackClusterSpec, out *v1alpha7.OpenStackClusterSpec, s conversion.Scope) error {
+func autoConvert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *OpenStackClusterSpec, out *v1alpha8.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 {
+ if err := Convert_v1alpha6_NetworkFilter_To_v1alpha8_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 {
+ if err := Convert_v1alpha6_SubnetFilter_To_v1alpha8_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil {
return err
}
out.DNSNameservers = *(*[]string)(unsafe.Pointer(&in.DNSNameservers))
if in.ExternalRouterIPs != nil {
in, out := &in.ExternalRouterIPs, &out.ExternalRouterIPs
- *out = make([]v1alpha7.ExternalRouterIPParam, len(*in))
+ *out = make([]v1alpha8.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_v1alpha8_ExternalRouterIPParam(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -706,7 +706,7 @@ func autoConvert_v1alpha6_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(
out.ExternalRouterIPs = nil
}
out.ExternalNetworkID = in.ExternalNetworkID
- if err := Convert_v1alpha6_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil {
+ if err := Convert_v1alpha6_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil {
return err
}
out.DisableAPIServerFloatingIP = in.DisableAPIServerFloatingIP
@@ -722,30 +722,30 @@ func autoConvert_v1alpha6_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(
out.ControlPlaneOmitAvailabilityZone = in.ControlPlaneOmitAvailabilityZone
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(v1alpha8.Bastion)
+ if err := Convert_v1alpha6_Bastion_To_v1alpha8_Bastion(*in, *out, s); err != nil {
return err
}
} else {
out.Bastion = nil
}
- out.IdentityRef = (*v1alpha7.OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef))
+ out.IdentityRef = (*v1alpha8.OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef))
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)
+// Convert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec is an autogenerated conversion function.
+func Convert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *OpenStackClusterSpec, out *v1alpha8.OpenStackClusterSpec, s conversion.Scope) error {
+ return autoConvert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in, out, s)
}
-func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(in *v1alpha7.OpenStackClusterSpec, out *OpenStackClusterSpec, s conversion.Scope) error {
+func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(in *v1alpha8.OpenStackClusterSpec, out *OpenStackClusterSpec, s conversion.Scope) error {
out.CloudName = in.CloudName
out.NodeCIDR = in.NodeCIDR
// 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 {
+ if err := Convert_v1alpha8_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 {
+ if err := Convert_v1alpha8_SubnetFilter_To_v1alpha6_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil {
return err
}
// WARNING: in.NetworkMTU requires manual conversion: does not exist in peer-type
@@ -754,7 +754,7 @@ func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(
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_v1alpha8_ExternalRouterIPParam_To_v1alpha6_ExternalRouterIPParam(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -762,7 +762,7 @@ func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(
out.ExternalRouterIPs = nil
}
out.ExternalNetworkID = in.ExternalNetworkID
- if err := Convert_v1alpha7_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil {
+ if err := Convert_v1alpha8_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil {
return err
}
out.DisableAPIServerFloatingIP = in.DisableAPIServerFloatingIP
@@ -779,7 +779,7 @@ func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(
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_v1alpha8_Bastion_To_v1alpha6_Bastion(*in, *out, s); err != nil {
return err
}
} else {
@@ -789,12 +789,12 @@ func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(
return nil
}
-func autoConvert_v1alpha6_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(in *OpenStackClusterStatus, out *v1alpha7.OpenStackClusterStatus, s conversion.Scope) error {
+func autoConvert_v1alpha6_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterStatus(in *OpenStackClusterStatus, out *v1alpha8.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(v1alpha8.NetworkStatusWithSubnets)
+ if err := Convert_v1alpha6_Network_To_v1alpha8_NetworkStatusWithSubnets(*in, *out, s); err != nil {
return err
}
} else {
@@ -802,21 +802,21 @@ 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(v1alpha8.NetworkStatus)
+ if err := Convert_v1alpha6_Network_To_v1alpha8_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.ControlPlaneSecurityGroup = (*v1alpha8.SecurityGroup)(unsafe.Pointer(in.ControlPlaneSecurityGroup))
+ out.WorkerSecurityGroup = (*v1alpha8.SecurityGroup)(unsafe.Pointer(in.WorkerSecurityGroup))
+ out.BastionSecurityGroup = (*v1alpha8.SecurityGroup)(unsafe.Pointer(in.BastionSecurityGroup))
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(v1alpha8.BastionStatus)
+ if err := Convert_v1alpha6_Instance_To_v1alpha8_BastionStatus(*in, *out, s); err != nil {
return err
}
} else {
@@ -827,12 +827,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_v1alpha8_OpenStackClusterStatus_To_v1alpha6_OpenStackClusterStatus(in *v1alpha8.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_v1alpha8_NetworkStatusWithSubnets_To_v1alpha6_Network(*in, *out, s); err != nil {
return err
}
} else {
@@ -841,7 +841,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_v1alpha8_NetworkStatus_To_v1alpha6_Network(*in, *out, s); err != nil {
return err
}
} else {
@@ -856,7 +856,7 @@ func autoConvert_v1alpha7_OpenStackClusterStatus_To_v1alpha6_OpenStackClusterSta
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_v1alpha8_BastionStatus_To_v1alpha6_Instance(*in, *out, s); err != nil {
return err
}
} else {
@@ -867,39 +867,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_v1alpha8_OpenStackClusterTemplate(in *OpenStackClusterTemplate, out *v1alpha8.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_v1alpha8_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_v1alpha8_OpenStackClusterTemplate is an autogenerated conversion function.
+func Convert_v1alpha6_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate(in *OpenStackClusterTemplate, out *v1alpha8.OpenStackClusterTemplate, s conversion.Scope) error {
+ return autoConvert_v1alpha6_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate(in, out, s)
}
-func autoConvert_v1alpha7_OpenStackClusterTemplate_To_v1alpha6_OpenStackClusterTemplate(in *v1alpha7.OpenStackClusterTemplate, out *OpenStackClusterTemplate, s conversion.Scope) error {
+func autoConvert_v1alpha8_OpenStackClusterTemplate_To_v1alpha6_OpenStackClusterTemplate(in *v1alpha8.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_v1alpha8_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_v1alpha8_OpenStackClusterTemplate_To_v1alpha6_OpenStackClusterTemplate is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackClusterTemplate_To_v1alpha6_OpenStackClusterTemplate(in *v1alpha8.OpenStackClusterTemplate, out *OpenStackClusterTemplate, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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_v1alpha8_OpenStackClusterTemplateList(in *OpenStackClusterTemplateList, out *v1alpha8.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([]v1alpha8.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_v1alpha8_OpenStackClusterTemplate(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -909,18 +909,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_v1alpha8_OpenStackClusterTemplateList is an autogenerated conversion function.
+func Convert_v1alpha6_OpenStackClusterTemplateList_To_v1alpha8_OpenStackClusterTemplateList(in *OpenStackClusterTemplateList, out *v1alpha8.OpenStackClusterTemplateList, s conversion.Scope) error {
+ return autoConvert_v1alpha6_OpenStackClusterTemplateList_To_v1alpha8_OpenStackClusterTemplateList(in, out, s)
}
-func autoConvert_v1alpha7_OpenStackClusterTemplateList_To_v1alpha6_OpenStackClusterTemplateList(in *v1alpha7.OpenStackClusterTemplateList, out *OpenStackClusterTemplateList, s conversion.Scope) error {
+func autoConvert_v1alpha8_OpenStackClusterTemplateList_To_v1alpha6_OpenStackClusterTemplateList(in *v1alpha8.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_v1alpha8_OpenStackClusterTemplate_To_v1alpha6_OpenStackClusterTemplate(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -930,120 +930,120 @@ 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_v1alpha8_OpenStackClusterTemplateList_To_v1alpha6_OpenStackClusterTemplateList is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackClusterTemplateList_To_v1alpha6_OpenStackClusterTemplateList(in *v1alpha8.OpenStackClusterTemplateList, out *OpenStackClusterTemplateList, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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_v1alpha8_OpenStackClusterTemplateResource(in *OpenStackClusterTemplateResource, out *v1alpha8.OpenStackClusterTemplateResource, s conversion.Scope) error {
+ if err := Convert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_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_v1alpha8_OpenStackClusterTemplateResource is an autogenerated conversion function.
+func Convert_v1alpha6_OpenStackClusterTemplateResource_To_v1alpha8_OpenStackClusterTemplateResource(in *OpenStackClusterTemplateResource, out *v1alpha8.OpenStackClusterTemplateResource, s conversion.Scope) error {
+ return autoConvert_v1alpha6_OpenStackClusterTemplateResource_To_v1alpha8_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_v1alpha8_OpenStackClusterTemplateResource_To_v1alpha6_OpenStackClusterTemplateResource(in *v1alpha8.OpenStackClusterTemplateResource, out *OpenStackClusterTemplateResource, s conversion.Scope) error {
+ if err := Convert_v1alpha8_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_v1alpha8_OpenStackClusterTemplateResource_To_v1alpha6_OpenStackClusterTemplateResource is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackClusterTemplateResource_To_v1alpha6_OpenStackClusterTemplateResource(in *v1alpha8.OpenStackClusterTemplateResource, out *OpenStackClusterTemplateResource, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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_v1alpha8_OpenStackClusterTemplateSpec(in *OpenStackClusterTemplateSpec, out *v1alpha8.OpenStackClusterTemplateSpec, s conversion.Scope) error {
+ if err := Convert_v1alpha6_OpenStackClusterTemplateResource_To_v1alpha8_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_v1alpha8_OpenStackClusterTemplateSpec is an autogenerated conversion function.
+func Convert_v1alpha6_OpenStackClusterTemplateSpec_To_v1alpha8_OpenStackClusterTemplateSpec(in *OpenStackClusterTemplateSpec, out *v1alpha8.OpenStackClusterTemplateSpec, s conversion.Scope) error {
+ return autoConvert_v1alpha6_OpenStackClusterTemplateSpec_To_v1alpha8_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_v1alpha8_OpenStackClusterTemplateSpec_To_v1alpha6_OpenStackClusterTemplateSpec(in *v1alpha8.OpenStackClusterTemplateSpec, out *OpenStackClusterTemplateSpec, s conversion.Scope) error {
+ if err := Convert_v1alpha8_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_v1alpha8_OpenStackClusterTemplateSpec_To_v1alpha6_OpenStackClusterTemplateSpec is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackClusterTemplateSpec_To_v1alpha6_OpenStackClusterTemplateSpec(in *v1alpha8.OpenStackClusterTemplateSpec, out *OpenStackClusterTemplateSpec, s conversion.Scope) error {
+ return autoConvert_v1alpha8_OpenStackClusterTemplateSpec_To_v1alpha6_OpenStackClusterTemplateSpec(in, out, s)
}
-func autoConvert_v1alpha6_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference(in *OpenStackIdentityReference, out *v1alpha7.OpenStackIdentityReference, s conversion.Scope) error {
+func autoConvert_v1alpha6_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(in *OpenStackIdentityReference, out *v1alpha8.OpenStackIdentityReference, s conversion.Scope) error {
out.Kind = in.Kind
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)
+// Convert_v1alpha6_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference is an autogenerated conversion function.
+func Convert_v1alpha6_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(in *OpenStackIdentityReference, out *v1alpha8.OpenStackIdentityReference, s conversion.Scope) error {
+ return autoConvert_v1alpha6_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(in, out, s)
}
-func autoConvert_v1alpha7_OpenStackIdentityReference_To_v1alpha6_OpenStackIdentityReference(in *v1alpha7.OpenStackIdentityReference, out *OpenStackIdentityReference, s conversion.Scope) error {
+func autoConvert_v1alpha8_OpenStackIdentityReference_To_v1alpha6_OpenStackIdentityReference(in *v1alpha8.OpenStackIdentityReference, out *OpenStackIdentityReference, s conversion.Scope) error {
out.Kind = in.Kind
out.Name = in.Name
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)
+// Convert_v1alpha8_OpenStackIdentityReference_To_v1alpha6_OpenStackIdentityReference is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackIdentityReference_To_v1alpha6_OpenStackIdentityReference(in *v1alpha8.OpenStackIdentityReference, out *OpenStackIdentityReference, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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_v1alpha8_OpenStackMachine(in *OpenStackMachine, out *v1alpha8.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_v1alpha8_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_v1alpha8_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)
+// Convert_v1alpha6_OpenStackMachine_To_v1alpha8_OpenStackMachine is an autogenerated conversion function.
+func Convert_v1alpha6_OpenStackMachine_To_v1alpha8_OpenStackMachine(in *OpenStackMachine, out *v1alpha8.OpenStackMachine, s conversion.Scope) error {
+ return autoConvert_v1alpha6_OpenStackMachine_To_v1alpha8_OpenStackMachine(in, out, s)
}
-func autoConvert_v1alpha7_OpenStackMachine_To_v1alpha6_OpenStackMachine(in *v1alpha7.OpenStackMachine, out *OpenStackMachine, s conversion.Scope) error {
+func autoConvert_v1alpha8_OpenStackMachine_To_v1alpha6_OpenStackMachine(in *v1alpha8.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_v1alpha8_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_v1alpha8_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)
+// Convert_v1alpha8_OpenStackMachine_To_v1alpha6_OpenStackMachine is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackMachine_To_v1alpha6_OpenStackMachine(in *v1alpha8.OpenStackMachine, out *OpenStackMachine, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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_v1alpha8_OpenStackMachineList(in *OpenStackMachineList, out *v1alpha8.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([]v1alpha8.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_v1alpha8_OpenStackMachine(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -1053,18 +1053,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_v1alpha8_OpenStackMachineList is an autogenerated conversion function.
+func Convert_v1alpha6_OpenStackMachineList_To_v1alpha8_OpenStackMachineList(in *OpenStackMachineList, out *v1alpha8.OpenStackMachineList, s conversion.Scope) error {
+ return autoConvert_v1alpha6_OpenStackMachineList_To_v1alpha8_OpenStackMachineList(in, out, s)
}
-func autoConvert_v1alpha7_OpenStackMachineList_To_v1alpha6_OpenStackMachineList(in *v1alpha7.OpenStackMachineList, out *OpenStackMachineList, s conversion.Scope) error {
+func autoConvert_v1alpha8_OpenStackMachineList_To_v1alpha6_OpenStackMachineList(in *v1alpha8.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_v1alpha8_OpenStackMachine_To_v1alpha6_OpenStackMachine(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -1074,12 +1074,12 @@ 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_v1alpha8_OpenStackMachineList_To_v1alpha6_OpenStackMachineList is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackMachineList_To_v1alpha6_OpenStackMachineList(in *v1alpha8.OpenStackMachineList, out *OpenStackMachineList, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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_v1alpha8_OpenStackMachineSpec(in *OpenStackMachineSpec, out *v1alpha8.OpenStackMachineSpec, s conversion.Scope) error {
out.ProviderID = (*string)(unsafe.Pointer(in.ProviderID))
out.InstanceID = (*string)(unsafe.Pointer(in.InstanceID))
out.CloudName = in.CloudName
@@ -1090,9 +1090,9 @@ func autoConvert_v1alpha6_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(
// 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([]v1alpha8.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_v1alpha8_PortOpts(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -1103,9 +1103,9 @@ func autoConvert_v1alpha6_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(
out.FloatingIP = in.FloatingIP
if in.SecurityGroups != nil {
in, out := &in.SecurityGroups, &out.SecurityGroups
- *out = make([]v1alpha7.SecurityGroupFilter, len(*in))
+ *out = make([]v1alpha8.SecurityGroupFilter, 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_v1alpha8_SecurityGroupFilter(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -1116,13 +1116,13 @@ func autoConvert_v1alpha6_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
out.ServerMetadata = *(*map[string]string)(unsafe.Pointer(&in.ServerMetadata))
out.ConfigDrive = (*bool)(unsafe.Pointer(in.ConfigDrive))
- out.RootVolume = (*v1alpha7.RootVolume)(unsafe.Pointer(in.RootVolume))
+ out.RootVolume = (*v1alpha8.RootVolume)(unsafe.Pointer(in.RootVolume))
out.ServerGroupID = in.ServerGroupID
- out.IdentityRef = (*v1alpha7.OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef))
+ out.IdentityRef = (*v1alpha8.OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef))
return nil
}
-func autoConvert_v1alpha7_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(in *v1alpha7.OpenStackMachineSpec, out *OpenStackMachineSpec, s conversion.Scope) error {
+func autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(in *v1alpha8.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
@@ -1134,7 +1134,7 @@ func autoConvert_v1alpha7_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(
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_v1alpha8_PortOpts_To_v1alpha6_PortOpts(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -1146,7 +1146,7 @@ func autoConvert_v1alpha7_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(
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_v1alpha8_SecurityGroupFilter_To_v1alpha6_SecurityGroupParam(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -1164,22 +1164,22 @@ func autoConvert_v1alpha7_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(
return nil
}
-func autoConvert_v1alpha6_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus(in *OpenStackMachineStatus, out *v1alpha7.OpenStackMachineStatus, s conversion.Scope) error {
+func autoConvert_v1alpha6_OpenStackMachineStatus_To_v1alpha8_OpenStackMachineStatus(in *OpenStackMachineStatus, out *v1alpha8.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.InstanceState = (*v1alpha8.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))
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_v1alpha8_OpenStackMachineStatus is an autogenerated conversion function.
+func Convert_v1alpha6_OpenStackMachineStatus_To_v1alpha8_OpenStackMachineStatus(in *OpenStackMachineStatus, out *v1alpha8.OpenStackMachineStatus, s conversion.Scope) error {
+ return autoConvert_v1alpha6_OpenStackMachineStatus_To_v1alpha8_OpenStackMachineStatus(in, out, s)
}
-func autoConvert_v1alpha7_OpenStackMachineStatus_To_v1alpha6_OpenStackMachineStatus(in *v1alpha7.OpenStackMachineStatus, out *OpenStackMachineStatus, s conversion.Scope) error {
+func autoConvert_v1alpha8_OpenStackMachineStatus_To_v1alpha6_OpenStackMachineStatus(in *v1alpha8.OpenStackMachineStatus, out *OpenStackMachineStatus, s conversion.Scope) error {
out.Ready = in.Ready
out.Addresses = *(*[]v1.NodeAddress)(unsafe.Pointer(&in.Addresses))
out.InstanceState = (*InstanceState)(unsafe.Pointer(in.InstanceState))
@@ -1189,44 +1189,44 @@ func autoConvert_v1alpha7_OpenStackMachineStatus_To_v1alpha6_OpenStackMachineSta
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)
+// Convert_v1alpha8_OpenStackMachineStatus_To_v1alpha6_OpenStackMachineStatus is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackMachineStatus_To_v1alpha6_OpenStackMachineStatus(in *v1alpha8.OpenStackMachineStatus, out *OpenStackMachineStatus, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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_v1alpha8_OpenStackMachineTemplate(in *OpenStackMachineTemplate, out *v1alpha8.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_v1alpha8_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_v1alpha8_OpenStackMachineTemplate is an autogenerated conversion function.
+func Convert_v1alpha6_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate(in *OpenStackMachineTemplate, out *v1alpha8.OpenStackMachineTemplate, s conversion.Scope) error {
+ return autoConvert_v1alpha6_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate(in, out, s)
}
-func autoConvert_v1alpha7_OpenStackMachineTemplate_To_v1alpha6_OpenStackMachineTemplate(in *v1alpha7.OpenStackMachineTemplate, out *OpenStackMachineTemplate, s conversion.Scope) error {
+func autoConvert_v1alpha8_OpenStackMachineTemplate_To_v1alpha6_OpenStackMachineTemplate(in *v1alpha8.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_v1alpha8_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_v1alpha8_OpenStackMachineTemplate_To_v1alpha6_OpenStackMachineTemplate is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackMachineTemplate_To_v1alpha6_OpenStackMachineTemplate(in *v1alpha8.OpenStackMachineTemplate, out *OpenStackMachineTemplate, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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_v1alpha8_OpenStackMachineTemplateList(in *OpenStackMachineTemplateList, out *v1alpha8.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([]v1alpha8.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_v1alpha8_OpenStackMachineTemplate(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -1236,18 +1236,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_v1alpha8_OpenStackMachineTemplateList is an autogenerated conversion function.
+func Convert_v1alpha6_OpenStackMachineTemplateList_To_v1alpha8_OpenStackMachineTemplateList(in *OpenStackMachineTemplateList, out *v1alpha8.OpenStackMachineTemplateList, s conversion.Scope) error {
+ return autoConvert_v1alpha6_OpenStackMachineTemplateList_To_v1alpha8_OpenStackMachineTemplateList(in, out, s)
}
-func autoConvert_v1alpha7_OpenStackMachineTemplateList_To_v1alpha6_OpenStackMachineTemplateList(in *v1alpha7.OpenStackMachineTemplateList, out *OpenStackMachineTemplateList, s conversion.Scope) error {
+func autoConvert_v1alpha8_OpenStackMachineTemplateList_To_v1alpha6_OpenStackMachineTemplateList(in *v1alpha8.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_v1alpha8_OpenStackMachineTemplate_To_v1alpha6_OpenStackMachineTemplate(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -1257,92 +1257,92 @@ 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_v1alpha8_OpenStackMachineTemplateList_To_v1alpha6_OpenStackMachineTemplateList is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackMachineTemplateList_To_v1alpha6_OpenStackMachineTemplateList(in *v1alpha8.OpenStackMachineTemplateList, out *OpenStackMachineTemplateList, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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_v1alpha8_OpenStackMachineTemplateResource(in *OpenStackMachineTemplateResource, out *v1alpha8.OpenStackMachineTemplateResource, s conversion.Scope) error {
+ if err := Convert_v1alpha6_OpenStackMachineSpec_To_v1alpha8_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_v1alpha8_OpenStackMachineTemplateResource is an autogenerated conversion function.
+func Convert_v1alpha6_OpenStackMachineTemplateResource_To_v1alpha8_OpenStackMachineTemplateResource(in *OpenStackMachineTemplateResource, out *v1alpha8.OpenStackMachineTemplateResource, s conversion.Scope) error {
+ return autoConvert_v1alpha6_OpenStackMachineTemplateResource_To_v1alpha8_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_v1alpha8_OpenStackMachineTemplateResource_To_v1alpha6_OpenStackMachineTemplateResource(in *v1alpha8.OpenStackMachineTemplateResource, out *OpenStackMachineTemplateResource, s conversion.Scope) error {
+ if err := Convert_v1alpha8_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_v1alpha8_OpenStackMachineTemplateResource_To_v1alpha6_OpenStackMachineTemplateResource is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackMachineTemplateResource_To_v1alpha6_OpenStackMachineTemplateResource(in *v1alpha8.OpenStackMachineTemplateResource, out *OpenStackMachineTemplateResource, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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_v1alpha8_OpenStackMachineTemplateSpec(in *OpenStackMachineTemplateSpec, out *v1alpha8.OpenStackMachineTemplateSpec, s conversion.Scope) error {
+ if err := Convert_v1alpha6_OpenStackMachineTemplateResource_To_v1alpha8_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_v1alpha8_OpenStackMachineTemplateSpec is an autogenerated conversion function.
+func Convert_v1alpha6_OpenStackMachineTemplateSpec_To_v1alpha8_OpenStackMachineTemplateSpec(in *OpenStackMachineTemplateSpec, out *v1alpha8.OpenStackMachineTemplateSpec, s conversion.Scope) error {
+ return autoConvert_v1alpha6_OpenStackMachineTemplateSpec_To_v1alpha8_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_v1alpha8_OpenStackMachineTemplateSpec_To_v1alpha6_OpenStackMachineTemplateSpec(in *v1alpha8.OpenStackMachineTemplateSpec, out *OpenStackMachineTemplateSpec, s conversion.Scope) error {
+ if err := Convert_v1alpha8_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_v1alpha8_OpenStackMachineTemplateSpec_To_v1alpha6_OpenStackMachineTemplateSpec is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackMachineTemplateSpec_To_v1alpha6_OpenStackMachineTemplateSpec(in *v1alpha8.OpenStackMachineTemplateSpec, out *OpenStackMachineTemplateSpec, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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))
+func autoConvert_v1alpha6_PortOpts_To_v1alpha8_PortOpts(in *PortOpts, out *v1alpha8.PortOpts, s conversion.Scope) error {
+ out.Network = (*v1alpha8.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))
+ out.FixedIPs = *(*[]v1alpha8.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))
+ *out = make([]v1alpha8.SecurityGroupFilter, 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_v1alpha8_SecurityGroupFilter(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.SecurityGroupFilters = nil
}
- out.AllowedAddressPairs = *(*[]v1alpha7.AddressPair)(unsafe.Pointer(&in.AllowedAddressPairs))
+ out.AllowedAddressPairs = *(*[]v1alpha8.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 (map[string]string vs sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7.BindingProfile)
+ // WARNING: in.Profile requires manual conversion: inconvertible types (map[string]string vs sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8.BindingProfile)
out.DisablePortSecurity = (*bool)(unsafe.Pointer(in.DisablePortSecurity))
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
- out.ValueSpecs = *(*[]v1alpha7.ValueSpec)(unsafe.Pointer(&in.ValueSpecs))
+ out.ValueSpecs = *(*[]v1alpha8.ValueSpec)(unsafe.Pointer(&in.ValueSpecs))
return nil
}
-func autoConvert_v1alpha7_PortOpts_To_v1alpha6_PortOpts(in *v1alpha7.PortOpts, out *PortOpts, s conversion.Scope) error {
+func autoConvert_v1alpha8_PortOpts_To_v1alpha6_PortOpts(in *v1alpha8.PortOpts, out *PortOpts, s conversion.Scope) error {
out.Network = (*NetworkFilter)(unsafe.Pointer(in.Network))
out.NameSuffix = in.NameSuffix
out.Description = in.Description
@@ -1353,7 +1353,7 @@ func autoConvert_v1alpha7_PortOpts_To_v1alpha6_PortOpts(in *v1alpha7.PortOpts, o
in, out := &in.SecurityGroupFilters, &out.SecurityGroupFilters
*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_v1alpha8_SecurityGroupFilter_To_v1alpha6_SecurityGroupParam(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -1364,7 +1364,7 @@ func autoConvert_v1alpha7_PortOpts_To_v1alpha6_PortOpts(in *v1alpha7.PortOpts, o
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)
+ // WARNING: in.Profile requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8.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))
@@ -1372,31 +1372,31 @@ func autoConvert_v1alpha7_PortOpts_To_v1alpha6_PortOpts(in *v1alpha7.PortOpts, o
return nil
}
-func autoConvert_v1alpha6_RootVolume_To_v1alpha7_RootVolume(in *RootVolume, out *v1alpha7.RootVolume, s conversion.Scope) error {
+func autoConvert_v1alpha6_RootVolume_To_v1alpha8_RootVolume(in *RootVolume, out *v1alpha8.RootVolume, s conversion.Scope) error {
out.Size = in.Size
out.VolumeType = in.VolumeType
out.AvailabilityZone = in.AvailabilityZone
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)
+// Convert_v1alpha6_RootVolume_To_v1alpha8_RootVolume is an autogenerated conversion function.
+func Convert_v1alpha6_RootVolume_To_v1alpha8_RootVolume(in *RootVolume, out *v1alpha8.RootVolume, s conversion.Scope) error {
+ return autoConvert_v1alpha6_RootVolume_To_v1alpha8_RootVolume(in, out, s)
}
-func autoConvert_v1alpha7_RootVolume_To_v1alpha6_RootVolume(in *v1alpha7.RootVolume, out *RootVolume, s conversion.Scope) error {
+func autoConvert_v1alpha8_RootVolume_To_v1alpha6_RootVolume(in *v1alpha8.RootVolume, out *RootVolume, s conversion.Scope) error {
out.Size = in.Size
out.VolumeType = in.VolumeType
out.AvailabilityZone = in.AvailabilityZone
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)
+// Convert_v1alpha8_RootVolume_To_v1alpha6_RootVolume is an autogenerated conversion function.
+func Convert_v1alpha8_RootVolume_To_v1alpha6_RootVolume(in *v1alpha8.RootVolume, out *RootVolume, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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_v1alpha8_Router(in *Router, out *v1alpha8.Router, s conversion.Scope) error {
out.Name = in.Name
out.ID = in.ID
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
@@ -1404,12 +1404,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_v1alpha8_Router is an autogenerated conversion function.
+func Convert_v1alpha6_Router_To_v1alpha8_Router(in *Router, out *v1alpha8.Router, s conversion.Scope) error {
+ return autoConvert_v1alpha6_Router_To_v1alpha8_Router(in, out, s)
}
-func autoConvert_v1alpha7_Router_To_v1alpha6_Router(in *v1alpha7.Router, out *Router, s conversion.Scope) error {
+func autoConvert_v1alpha8_Router_To_v1alpha6_Router(in *v1alpha8.Router, out *Router, s conversion.Scope) error {
out.Name = in.Name
out.ID = in.ID
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
@@ -1417,36 +1417,36 @@ 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)
+// Convert_v1alpha8_Router_To_v1alpha6_Router is an autogenerated conversion function.
+func Convert_v1alpha8_Router_To_v1alpha6_Router(in *v1alpha8.Router, out *Router, s conversion.Scope) error {
+ return autoConvert_v1alpha8_Router_To_v1alpha6_Router(in, out, s)
}
-func autoConvert_v1alpha6_SecurityGroup_To_v1alpha7_SecurityGroup(in *SecurityGroup, out *v1alpha7.SecurityGroup, s conversion.Scope) error {
+func autoConvert_v1alpha6_SecurityGroup_To_v1alpha8_SecurityGroup(in *SecurityGroup, out *v1alpha8.SecurityGroup, s conversion.Scope) error {
out.Name = in.Name
out.ID = in.ID
- out.Rules = *(*[]v1alpha7.SecurityGroupRule)(unsafe.Pointer(&in.Rules))
+ out.Rules = *(*[]v1alpha8.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_v1alpha6_SecurityGroup_To_v1alpha8_SecurityGroup is an autogenerated conversion function.
+func Convert_v1alpha6_SecurityGroup_To_v1alpha8_SecurityGroup(in *SecurityGroup, out *v1alpha8.SecurityGroup, s conversion.Scope) error {
+ return autoConvert_v1alpha6_SecurityGroup_To_v1alpha8_SecurityGroup(in, out, s)
}
-func autoConvert_v1alpha7_SecurityGroup_To_v1alpha6_SecurityGroup(in *v1alpha7.SecurityGroup, out *SecurityGroup, s conversion.Scope) error {
+func autoConvert_v1alpha8_SecurityGroup_To_v1alpha6_SecurityGroup(in *v1alpha8.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)
+// Convert_v1alpha8_SecurityGroup_To_v1alpha6_SecurityGroup is an autogenerated conversion function.
+func Convert_v1alpha8_SecurityGroup_To_v1alpha6_SecurityGroup(in *v1alpha8.SecurityGroup, out *SecurityGroup, s conversion.Scope) error {
+ return autoConvert_v1alpha8_SecurityGroup_To_v1alpha6_SecurityGroup(in, out, s)
}
-func autoConvert_v1alpha6_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in *SecurityGroupFilter, out *v1alpha7.SecurityGroupFilter, s conversion.Scope) error {
+func autoConvert_v1alpha6_SecurityGroupFilter_To_v1alpha8_SecurityGroupFilter(in *SecurityGroupFilter, out *v1alpha8.SecurityGroupFilter, s conversion.Scope) error {
out.ID = in.ID
out.Name = in.Name
out.Description = in.Description
@@ -1463,7 +1463,7 @@ func autoConvert_v1alpha6_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in
return nil
}
-func autoConvert_v1alpha7_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(in *v1alpha7.SecurityGroupFilter, out *SecurityGroupFilter, s conversion.Scope) error {
+func autoConvert_v1alpha8_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(in *v1alpha8.SecurityGroupFilter, out *SecurityGroupFilter, s conversion.Scope) error {
out.ID = in.ID
out.Name = in.Name
out.Description = in.Description
@@ -1475,12 +1475,12 @@ func autoConvert_v1alpha7_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(in
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)
+// Convert_v1alpha8_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter is an autogenerated conversion function.
+func Convert_v1alpha8_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(in *v1alpha8.SecurityGroupFilter, out *SecurityGroupFilter, s conversion.Scope) error {
+ return autoConvert_v1alpha8_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(in, out, s)
}
-func autoConvert_v1alpha6_SecurityGroupRule_To_v1alpha7_SecurityGroupRule(in *SecurityGroupRule, out *v1alpha7.SecurityGroupRule, s conversion.Scope) error {
+func autoConvert_v1alpha6_SecurityGroupRule_To_v1alpha8_SecurityGroupRule(in *SecurityGroupRule, out *v1alpha8.SecurityGroupRule, s conversion.Scope) error {
out.Description = in.Description
out.ID = in.ID
out.Direction = in.Direction
@@ -1494,12 +1494,12 @@ func autoConvert_v1alpha6_SecurityGroupRule_To_v1alpha7_SecurityGroupRule(in *Se
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)
+// Convert_v1alpha6_SecurityGroupRule_To_v1alpha8_SecurityGroupRule is an autogenerated conversion function.
+func Convert_v1alpha6_SecurityGroupRule_To_v1alpha8_SecurityGroupRule(in *SecurityGroupRule, out *v1alpha8.SecurityGroupRule, s conversion.Scope) error {
+ return autoConvert_v1alpha6_SecurityGroupRule_To_v1alpha8_SecurityGroupRule(in, out, s)
}
-func autoConvert_v1alpha7_SecurityGroupRule_To_v1alpha6_SecurityGroupRule(in *v1alpha7.SecurityGroupRule, out *SecurityGroupRule, s conversion.Scope) error {
+func autoConvert_v1alpha8_SecurityGroupRule_To_v1alpha6_SecurityGroupRule(in *v1alpha8.SecurityGroupRule, out *SecurityGroupRule, s conversion.Scope) error {
out.Description = in.Description
out.ID = in.ID
out.Direction = in.Direction
@@ -1513,12 +1513,12 @@ func autoConvert_v1alpha7_SecurityGroupRule_To_v1alpha6_SecurityGroupRule(in *v1
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)
+// Convert_v1alpha8_SecurityGroupRule_To_v1alpha6_SecurityGroupRule is an autogenerated conversion function.
+func Convert_v1alpha8_SecurityGroupRule_To_v1alpha6_SecurityGroupRule(in *v1alpha8.SecurityGroupRule, out *SecurityGroupRule, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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_v1alpha8_Subnet(in *Subnet, out *v1alpha8.Subnet, s conversion.Scope) error {
out.Name = in.Name
out.ID = in.ID
out.CIDR = in.CIDR
@@ -1526,12 +1526,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_v1alpha8_Subnet is an autogenerated conversion function.
+func Convert_v1alpha6_Subnet_To_v1alpha8_Subnet(in *Subnet, out *v1alpha8.Subnet, s conversion.Scope) error {
+ return autoConvert_v1alpha6_Subnet_To_v1alpha8_Subnet(in, out, s)
}
-func autoConvert_v1alpha7_Subnet_To_v1alpha6_Subnet(in *v1alpha7.Subnet, out *Subnet, s conversion.Scope) error {
+func autoConvert_v1alpha8_Subnet_To_v1alpha6_Subnet(in *v1alpha8.Subnet, out *Subnet, s conversion.Scope) error {
out.Name = in.Name
out.ID = in.ID
out.CIDR = in.CIDR
@@ -1539,12 +1539,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_v1alpha8_Subnet_To_v1alpha6_Subnet is an autogenerated conversion function.
+func Convert_v1alpha8_Subnet_To_v1alpha6_Subnet(in *v1alpha8.Subnet, out *Subnet, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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_v1alpha8_SubnetFilter(in *SubnetFilter, out *v1alpha8.SubnetFilter, s conversion.Scope) error {
out.Name = in.Name
out.Description = in.Description
out.ProjectID = in.ProjectID
@@ -1561,12 +1561,12 @@ func autoConvert_v1alpha6_SubnetFilter_To_v1alpha7_SubnetFilter(in *SubnetFilter
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)
+// Convert_v1alpha6_SubnetFilter_To_v1alpha8_SubnetFilter is an autogenerated conversion function.
+func Convert_v1alpha6_SubnetFilter_To_v1alpha8_SubnetFilter(in *SubnetFilter, out *v1alpha8.SubnetFilter, s conversion.Scope) error {
+ return autoConvert_v1alpha6_SubnetFilter_To_v1alpha8_SubnetFilter(in, out, s)
}
-func autoConvert_v1alpha7_SubnetFilter_To_v1alpha6_SubnetFilter(in *v1alpha7.SubnetFilter, out *SubnetFilter, s conversion.Scope) error {
+func autoConvert_v1alpha8_SubnetFilter_To_v1alpha6_SubnetFilter(in *v1alpha8.SubnetFilter, out *SubnetFilter, s conversion.Scope) error {
out.Name = in.Name
out.Description = in.Description
out.ProjectID = in.ProjectID
@@ -1583,31 +1583,31 @@ func autoConvert_v1alpha7_SubnetFilter_To_v1alpha6_SubnetFilter(in *v1alpha7.Sub
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)
+// Convert_v1alpha8_SubnetFilter_To_v1alpha6_SubnetFilter is an autogenerated conversion function.
+func Convert_v1alpha8_SubnetFilter_To_v1alpha6_SubnetFilter(in *v1alpha8.SubnetFilter, out *SubnetFilter, s conversion.Scope) error {
+ return autoConvert_v1alpha8_SubnetFilter_To_v1alpha6_SubnetFilter(in, out, s)
}
-func autoConvert_v1alpha6_ValueSpec_To_v1alpha7_ValueSpec(in *ValueSpec, out *v1alpha7.ValueSpec, s conversion.Scope) error {
+func autoConvert_v1alpha6_ValueSpec_To_v1alpha8_ValueSpec(in *ValueSpec, out *v1alpha8.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_v1alpha8_ValueSpec is an autogenerated conversion function.
+func Convert_v1alpha6_ValueSpec_To_v1alpha8_ValueSpec(in *ValueSpec, out *v1alpha8.ValueSpec, s conversion.Scope) error {
+ return autoConvert_v1alpha6_ValueSpec_To_v1alpha8_ValueSpec(in, out, s)
}
-func autoConvert_v1alpha7_ValueSpec_To_v1alpha6_ValueSpec(in *v1alpha7.ValueSpec, out *ValueSpec, s conversion.Scope) error {
+func autoConvert_v1alpha8_ValueSpec_To_v1alpha6_ValueSpec(in *v1alpha8.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_v1alpha8_ValueSpec_To_v1alpha6_ValueSpec is an autogenerated conversion function.
+func Convert_v1alpha8_ValueSpec_To_v1alpha6_ValueSpec(in *v1alpha8.ValueSpec, out *ValueSpec, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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
index 4bbb9d0e7a..6b17160fdf 100644
--- a/api/v1alpha7/conversion.go
+++ b/api/v1alpha7/conversion.go
@@ -16,26 +16,219 @@ limitations under the License.
package v1alpha7
-// Hub marks OpenStackCluster as a conversion hub.
-func (*OpenStackCluster) Hub() {}
+import (
+ ctrlconversion "sigs.k8s.io/controller-runtime/pkg/conversion"
-// Hub marks OpenStackClusterList as a conversion hub.
-func (*OpenStackClusterList) Hub() {}
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/conversion"
+)
-// Hub marks OpenStackClusterTemplate as a conversion hub.
-func (*OpenStackClusterTemplate) Hub() {}
+var _ ctrlconversion.Convertible = &OpenStackCluster{}
-// Hub marks OpenStackClusterTemplateList as a conversion hub.
-func (*OpenStackClusterTemplateList) Hub() {}
+var v1alpha7OpenStackClusterRestorer = conversion.RestorerFor[*OpenStackCluster]{
+ "spec": conversion.HashedFieldRestorer[*OpenStackCluster, OpenStackClusterSpec]{
+ GetField: func(c *OpenStackCluster) *OpenStackClusterSpec {
+ return &c.Spec
+ },
+ },
+ "status": conversion.HashedFieldRestorer[*OpenStackCluster, OpenStackClusterStatus]{
+ GetField: func(c *OpenStackCluster) *OpenStackClusterStatus {
+ return &c.Status
+ },
+ },
+}
-// Hub marks OpenStackMachine as a conversion hub.
-func (*OpenStackMachine) Hub() {}
+var v1alpha8OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStackCluster]{
+ "status": conversion.HashedFieldRestorer[*infrav1.OpenStackCluster, infrav1.OpenStackClusterStatus]{
+ GetField: func(c *infrav1.OpenStackCluster) *infrav1.OpenStackClusterStatus {
+ return &c.Status
+ },
+ },
+}
-// Hub marks OpenStackMachineList as a conversion hub.
-func (*OpenStackMachineList) Hub() {}
+func (r *OpenStackCluster) ConvertTo(dstRaw ctrlconversion.Hub) error {
+ dst := dstRaw.(*infrav1.OpenStackCluster)
-// Hub marks OpenStackMachineTemplate as a conversion hub.
-func (*OpenStackMachineTemplate) Hub() {}
+ compare := &OpenStackCluster{}
+ return conversion.ConvertAndRestore(
+ r, dst, compare,
+ Convert_v1alpha7_OpenStackCluster_To_v1alpha8_OpenStackCluster, Convert_v1alpha8_OpenStackCluster_To_v1alpha7_OpenStackCluster,
+ v1alpha7OpenStackClusterRestorer, v1alpha8OpenStackClusterRestorer,
+ )
+}
-// Hub marks OpenStackMachineTemplateList as a conversion hub.
-func (*OpenStackMachineTemplateList) Hub() {}
+func (r *OpenStackCluster) ConvertFrom(srcRaw ctrlconversion.Hub) error {
+ src := srcRaw.(*infrav1.OpenStackCluster)
+
+ compare := &infrav1.OpenStackCluster{}
+ return conversion.ConvertAndRestore(
+ src, r, compare,
+ Convert_v1alpha8_OpenStackCluster_To_v1alpha7_OpenStackCluster, Convert_v1alpha7_OpenStackCluster_To_v1alpha8_OpenStackCluster,
+ v1alpha8OpenStackClusterRestorer, v1alpha7OpenStackClusterRestorer,
+ )
+}
+
+var _ ctrlconversion.Convertible = &OpenStackClusterList{}
+
+func (r *OpenStackClusterList) ConvertTo(dstRaw ctrlconversion.Hub) error {
+ dst := dstRaw.(*infrav1.OpenStackClusterList)
+
+ return Convert_v1alpha7_OpenStackClusterList_To_v1alpha8_OpenStackClusterList(r, dst, nil)
+}
+
+func (r *OpenStackClusterList) ConvertFrom(srcRaw ctrlconversion.Hub) error {
+ src := srcRaw.(*infrav1.OpenStackClusterList)
+
+ return Convert_v1alpha8_OpenStackClusterList_To_v1alpha7_OpenStackClusterList(src, r, nil)
+}
+
+var _ ctrlconversion.Convertible = &OpenStackClusterTemplate{}
+
+var v1alpha7OpenStackClusterTemplateRestorer = conversion.RestorerFor[*OpenStackClusterTemplate]{
+ "spec": conversion.HashedFieldRestorer[*OpenStackClusterTemplate, OpenStackClusterSpec]{
+ GetField: func(c *OpenStackClusterTemplate) *OpenStackClusterSpec {
+ return &c.Spec.Template.Spec
+ },
+ },
+}
+
+var v1alpha8OpenStackClusterTemplateRestorer = conversion.RestorerFor[*infrav1.OpenStackClusterTemplate]{}
+
+func (r *OpenStackClusterTemplate) ConvertTo(dstRaw ctrlconversion.Hub) error {
+ dst := dstRaw.(*infrav1.OpenStackClusterTemplate)
+
+ compare := &OpenStackClusterTemplate{}
+ return conversion.ConvertAndRestore(
+ r, dst, compare,
+ Convert_v1alpha7_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate, Convert_v1alpha8_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate,
+ v1alpha7OpenStackClusterTemplateRestorer, v1alpha8OpenStackClusterTemplateRestorer,
+ )
+}
+
+func (r *OpenStackClusterTemplate) ConvertFrom(srcRaw ctrlconversion.Hub) error {
+ src := srcRaw.(*infrav1.OpenStackClusterTemplate)
+
+ compare := &infrav1.OpenStackClusterTemplate{}
+ return conversion.ConvertAndRestore(
+ src, r, compare,
+ Convert_v1alpha8_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate, Convert_v1alpha7_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate,
+ v1alpha8OpenStackClusterTemplateRestorer, v1alpha7OpenStackClusterTemplateRestorer,
+ )
+}
+
+var _ ctrlconversion.Convertible = &OpenStackMachine{}
+
+var v1alpha7OpenStackMachineRestorer = 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
+ },
+ },
+}
+
+var v1alpha8OpenStackMachineRestorer = conversion.RestorerFor[*infrav1.OpenStackMachine]{
+ "spec": conversion.HashedFieldRestorer[*infrav1.OpenStackMachine, infrav1.OpenStackMachineSpec]{
+ GetField: func(c *infrav1.OpenStackMachine) *infrav1.OpenStackMachineSpec {
+ return &c.Spec
+ },
+ },
+}
+
+func (r *OpenStackMachine) ConvertTo(dstRaw ctrlconversion.Hub) error {
+ dst := dstRaw.(*infrav1.OpenStackMachine)
+
+ compare := &OpenStackMachine{}
+ return conversion.ConvertAndRestore(
+ r, dst, compare,
+ Convert_v1alpha7_OpenStackMachine_To_v1alpha8_OpenStackMachine, Convert_v1alpha8_OpenStackMachine_To_v1alpha7_OpenStackMachine,
+ v1alpha7OpenStackMachineRestorer, v1alpha8OpenStackMachineRestorer,
+ )
+}
+
+func (r *OpenStackMachine) ConvertFrom(srcRaw ctrlconversion.Hub) error {
+ src := srcRaw.(*infrav1.OpenStackMachine)
+
+ compare := &infrav1.OpenStackMachine{}
+ return conversion.ConvertAndRestore(
+ src, r, compare,
+ Convert_v1alpha8_OpenStackMachine_To_v1alpha7_OpenStackMachine, Convert_v1alpha7_OpenStackMachine_To_v1alpha8_OpenStackMachine,
+ v1alpha8OpenStackMachineRestorer, v1alpha7OpenStackMachineRestorer,
+ )
+}
+
+var _ ctrlconversion.Convertible = &OpenStackMachineList{}
+
+func (r *OpenStackMachineList) ConvertTo(dstRaw ctrlconversion.Hub) error {
+ dst := dstRaw.(*infrav1.OpenStackMachineList)
+ return Convert_v1alpha7_OpenStackMachineList_To_v1alpha8_OpenStackMachineList(r, dst, nil)
+}
+
+func (r *OpenStackMachineList) ConvertFrom(srcRaw ctrlconversion.Hub) error {
+ src := srcRaw.(*infrav1.OpenStackMachineList)
+ return Convert_v1alpha8_OpenStackMachineList_To_v1alpha7_OpenStackMachineList(src, r, nil)
+}
+
+var _ ctrlconversion.Convertible = &OpenStackMachineTemplate{}
+
+var v1alpha7OpenStackMachineTemplateRestorer = conversion.RestorerFor[*OpenStackMachineTemplate]{
+ "spec": conversion.HashedFieldRestorer[*OpenStackMachineTemplate, OpenStackMachineSpec]{
+ GetField: func(c *OpenStackMachineTemplate) *OpenStackMachineSpec {
+ return &c.Spec.Template.Spec
+ },
+ },
+}
+
+var v1alpha8OpenStackMachineTemplateRestorer = conversion.RestorerFor[*infrav1.OpenStackMachineTemplate]{
+ "spec": conversion.HashedFieldRestorer[*infrav1.OpenStackMachineTemplate, infrav1.OpenStackMachineSpec]{
+ GetField: func(c *infrav1.OpenStackMachineTemplate) *infrav1.OpenStackMachineSpec {
+ return &c.Spec.Template.Spec
+ },
+ },
+}
+
+func (r *OpenStackMachineTemplate) ConvertTo(dstRaw ctrlconversion.Hub) error {
+ dst := dstRaw.(*infrav1.OpenStackMachineTemplate)
+
+ compare := &OpenStackMachineTemplate{}
+ return conversion.ConvertAndRestore(
+ r, dst, compare,
+ Convert_v1alpha7_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate, Convert_v1alpha8_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate,
+ v1alpha7OpenStackMachineTemplateRestorer, v1alpha8OpenStackMachineTemplateRestorer,
+ )
+}
+
+func (r *OpenStackMachineTemplate) ConvertFrom(srcRaw ctrlconversion.Hub) error {
+ src := srcRaw.(*infrav1.OpenStackMachineTemplate)
+
+ compare := &infrav1.OpenStackMachineTemplate{}
+ return conversion.ConvertAndRestore(
+ src, r, compare,
+ Convert_v1alpha8_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate, Convert_v1alpha7_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate,
+ v1alpha8OpenStackMachineTemplateRestorer, v1alpha7OpenStackMachineTemplateRestorer,
+ )
+}
+
+var _ ctrlconversion.Convertible = &OpenStackMachineTemplateList{}
+
+func (r *OpenStackMachineTemplateList) ConvertTo(dstRaw ctrlconversion.Hub) error {
+ dst := dstRaw.(*infrav1.OpenStackMachineTemplateList)
+ return Convert_v1alpha7_OpenStackMachineTemplateList_To_v1alpha8_OpenStackMachineTemplateList(r, dst, nil)
+}
+
+func (r *OpenStackMachineTemplateList) ConvertFrom(srcRaw ctrlconversion.Hub) error {
+ src := srcRaw.(*infrav1.OpenStackMachineTemplateList)
+ return Convert_v1alpha8_OpenStackMachineTemplateList_To_v1alpha7_OpenStackMachineTemplateList(src, r, nil)
+}
diff --git a/api/v1alpha7/conversion_test.go b/api/v1alpha7/conversion_test.go
new file mode 100644
index 0000000000..ab032f20ff
--- /dev/null
+++ b/api/v1alpha7/conversion_test.go
@@ -0,0 +1,212 @@
+/*
+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"
+
+ 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"
+ utilconversion "sigs.k8s.io/cluster-api/util/conversion"
+ "sigs.k8s.io/controller-runtime/pkg/conversion"
+
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ 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{} {
+ return []interface{}{
+ func(status *OpenStackClusterStatus, c fuzz.Continue) {
+ c.FuzzNoCustom(status)
+ },
+ }
+ }
+
+ 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,
+ })))
+
+ t.Run("for OpenStackClusterTemplate with mutate", runParallel(testhelpers.FuzzMutateTestFunc(testhelpers.FuzzMutateTestFuncInput{
+ FuzzTestFuncInput: utilconversion.FuzzTestFuncInput{
+ Hub: &infrav1.OpenStackClusterTemplate{},
+ Spoke: &OpenStackClusterTemplate{},
+ HubAfterMutation: ignoreDataAnnotation,
+ },
+ })))
+
+ t.Run("for OpenStackMachine", runParallel(utilconversion.FuzzTestFunc(utilconversion.FuzzTestFuncInput{
+ Hub: &infrav1.OpenStackMachine{},
+ Spoke: &OpenStackMachine{},
+ HubAfterMutation: ignoreDataAnnotation,
+ })))
+
+ t.Run("for OpenStackMachine with mutate", runParallel(testhelpers.FuzzMutateTestFunc(testhelpers.FuzzMutateTestFuncInput{
+ FuzzTestFuncInput: utilconversion.FuzzTestFuncInput{
+ Hub: &infrav1.OpenStackMachine{},
+ Spoke: &OpenStackMachine{},
+ HubAfterMutation: ignoreDataAnnotation,
+ },
+ })))
+
+ t.Run("for OpenStackMachineTemplate", runParallel(utilconversion.FuzzTestFunc(utilconversion.FuzzTestFuncInput{
+ Hub: &infrav1.OpenStackMachineTemplate{},
+ Spoke: &OpenStackMachineTemplate{},
+ HubAfterMutation: ignoreDataAnnotation,
+ })))
+
+ t.Run("for OpenStackMachineTemplate with mutate", runParallel(testhelpers.FuzzMutateTestFunc(testhelpers.FuzzMutateTestFuncInput{
+ FuzzTestFuncInput: utilconversion.FuzzTestFuncInput{
+ Hub: &infrav1.OpenStackMachineTemplate{},
+ Spoke: &OpenStackMachineTemplate{},
+ HubAfterMutation: ignoreDataAnnotation,
+ },
+ })))
+}
+
+func TestMachineConversionControllerSpecFields(t *testing.T) {
+ // This tests that we still do field restoration when the controller modifies ProviderID and InstanceID in the spec
+
+ g := gomega.NewWithT(t)
+ scheme := runtime.NewScheme()
+ g.Expect(AddToScheme(scheme)).To(gomega.Succeed())
+ g.Expect(infrav1.AddToScheme(scheme)).To(gomega.Succeed())
+
+ testMachine := func() *OpenStackMachine {
+ return &OpenStackMachine{
+ Spec: OpenStackMachineSpec{},
+ }
+ }
+
+ tests := []struct {
+ name string
+ modifyUp func(*infrav1.OpenStackMachine)
+ testAfter func(*OpenStackMachine)
+ expectNetworkDiff bool
+ }{
+ {
+ name: "No change",
+ },
+ {
+ name: "Non-ignored change",
+ modifyUp: func(up *infrav1.OpenStackMachine) {
+ up.Spec.Flavor = "new-flavor"
+ },
+ testAfter: func(after *OpenStackMachine) {
+ g.Expect(after.Spec.Flavor).To(gomega.Equal("new-flavor"))
+ },
+ expectNetworkDiff: true,
+ },
+ {
+ name: "Set ProviderID",
+ modifyUp: func(up *infrav1.OpenStackMachine) {
+ up.Spec.ProviderID = pointer.String("new-provider-id")
+ },
+ testAfter: func(after *OpenStackMachine) {
+ g.Expect(after.Spec.ProviderID).To(gomega.Equal(pointer.String("new-provider-id")))
+ },
+ expectNetworkDiff: false,
+ },
+ {
+ name: "Set InstanceID",
+ modifyUp: func(up *infrav1.OpenStackMachine) {
+ up.Spec.InstanceID = pointer.String("new-instance-id")
+ },
+ testAfter: func(after *OpenStackMachine) {
+ g.Expect(after.Spec.InstanceID).To(gomega.Equal(pointer.String("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.Flavor = "new-flavor"
+ },
+ testAfter: func(after *OpenStackMachine) {
+ g.Expect(after.Spec.ProviderID).To(gomega.Equal(pointer.String("new-provider-id")))
+ g.Expect(after.Spec.Flavor).To(gomega.Equal("new-flavor"))
+ },
+ expectNetworkDiff: true,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ 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(&after)
+ }
+ })
+ }
+}
diff --git a/api/v1alpha7/doc.go b/api/v1alpha7/doc.go
index 817c2b4119..91f912911d 100644
--- a/api/v1alpha7/doc.go
+++ b/api/v1alpha7/doc.go
@@ -14,4 +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/v1alpha8
package v1alpha7
diff --git a/api/v1alpha7/groupversion_info.go b/api/v1alpha7/groupversion_info.go
index 019caf4f0f..bc23eee49e 100644
--- a/api/v1alpha7/groupversion_info.go
+++ b/api/v1alpha7/groupversion_info.go
@@ -33,4 +33,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_types.go b/api/v1alpha7/openstackcluster_types.go
index b4826685b0..e822e02872 100644
--- a/api/v1alpha7/openstackcluster_types.go
+++ b/api/v1alpha7/openstackcluster_types.go
@@ -231,7 +231,6 @@ type OpenStackClusterStatus struct {
// +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/openstackclustertemplate_types.go b/api/v1alpha7/openstackclustertemplate_types.go
index c255284a77..0c02a154b3 100644
--- a/api/v1alpha7/openstackclustertemplate_types.go
+++ b/api/v1alpha7/openstackclustertemplate_types.go
@@ -31,7 +31,6 @@ type OpenStackClusterTemplateSpec struct {
}
//+kubebuilder:object:root=true
-// +kubebuilder:storageversion
//+kubebuilder:resource:path=openstackclustertemplates,scope=Namespaced,categories=cluster-api,shortName=osct
// OpenStackClusterTemplate is the Schema for the openstackclustertemplates API.
diff --git a/api/v1alpha7/openstackmachine_types.go b/api/v1alpha7/openstackmachine_types.go
index f5f4f698aa..d7bdbf2438 100644
--- a/api/v1alpha7/openstackmachine_types.go
+++ b/api/v1alpha7/openstackmachine_types.go
@@ -136,7 +136,6 @@ type OpenStackMachineStatus struct {
}
// +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"
diff --git a/api/v1alpha7/openstackmachinetemplate_types.go b/api/v1alpha7/openstackmachinetemplate_types.go
index 5202234ba2..3eeda6ad7a 100644
--- a/api/v1alpha7/openstackmachinetemplate_types.go
+++ b/api/v1alpha7/openstackmachinetemplate_types.go
@@ -26,7 +26,6 @@ type OpenStackMachineTemplateSpec struct {
}
// +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/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go
new file mode 100644
index 0000000000..2d4a574a69
--- /dev/null
+++ b/api/v1alpha7/zz_generated.conversion.go
@@ -0,0 +1,1667 @@
+//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"
+
+ v1 "k8s.io/api/core/v1"
+ conversion "k8s.io/apimachinery/pkg/conversion"
+ runtime "k8s.io/apimachinery/pkg/runtime"
+ v1alpha8 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ v1beta1 "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((*APIServerLoadBalancer)(nil), (*v1alpha8.APIServerLoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalancer(a.(*APIServerLoadBalancer), b.(*v1alpha8.APIServerLoadBalancer), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.APIServerLoadBalancer)(nil), (*APIServerLoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer(a.(*v1alpha8.APIServerLoadBalancer), b.(*APIServerLoadBalancer), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*AdditionalBlockDevice)(nil), (*v1alpha8.AdditionalBlockDevice)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_AdditionalBlockDevice_To_v1alpha8_AdditionalBlockDevice(a.(*AdditionalBlockDevice), b.(*v1alpha8.AdditionalBlockDevice), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.AdditionalBlockDevice)(nil), (*AdditionalBlockDevice)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_AdditionalBlockDevice_To_v1alpha7_AdditionalBlockDevice(a.(*v1alpha8.AdditionalBlockDevice), b.(*AdditionalBlockDevice), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*AddressPair)(nil), (*v1alpha8.AddressPair)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_AddressPair_To_v1alpha8_AddressPair(a.(*AddressPair), b.(*v1alpha8.AddressPair), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.AddressPair)(nil), (*AddressPair)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_AddressPair_To_v1alpha7_AddressPair(a.(*v1alpha8.AddressPair), b.(*AddressPair), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*Bastion)(nil), (*v1alpha8.Bastion)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_Bastion_To_v1alpha8_Bastion(a.(*Bastion), b.(*v1alpha8.Bastion), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.Bastion)(nil), (*Bastion)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_Bastion_To_v1alpha7_Bastion(a.(*v1alpha8.Bastion), b.(*Bastion), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*BastionStatus)(nil), (*v1alpha8.BastionStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_BastionStatus_To_v1alpha8_BastionStatus(a.(*BastionStatus), b.(*v1alpha8.BastionStatus), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.BastionStatus)(nil), (*BastionStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_BastionStatus_To_v1alpha7_BastionStatus(a.(*v1alpha8.BastionStatus), b.(*BastionStatus), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*BindingProfile)(nil), (*v1alpha8.BindingProfile)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_BindingProfile_To_v1alpha8_BindingProfile(a.(*BindingProfile), b.(*v1alpha8.BindingProfile), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.BindingProfile)(nil), (*BindingProfile)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_BindingProfile_To_v1alpha7_BindingProfile(a.(*v1alpha8.BindingProfile), b.(*BindingProfile), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*BlockDeviceStorage)(nil), (*v1alpha8.BlockDeviceStorage)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_BlockDeviceStorage_To_v1alpha8_BlockDeviceStorage(a.(*BlockDeviceStorage), b.(*v1alpha8.BlockDeviceStorage), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.BlockDeviceStorage)(nil), (*BlockDeviceStorage)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_BlockDeviceStorage_To_v1alpha7_BlockDeviceStorage(a.(*v1alpha8.BlockDeviceStorage), b.(*BlockDeviceStorage), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*BlockDeviceVolume)(nil), (*v1alpha8.BlockDeviceVolume)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_BlockDeviceVolume_To_v1alpha8_BlockDeviceVolume(a.(*BlockDeviceVolume), b.(*v1alpha8.BlockDeviceVolume), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.BlockDeviceVolume)(nil), (*BlockDeviceVolume)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_BlockDeviceVolume_To_v1alpha7_BlockDeviceVolume(a.(*v1alpha8.BlockDeviceVolume), b.(*BlockDeviceVolume), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*ExternalRouterIPParam)(nil), (*v1alpha8.ExternalRouterIPParam)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_ExternalRouterIPParam_To_v1alpha8_ExternalRouterIPParam(a.(*ExternalRouterIPParam), b.(*v1alpha8.ExternalRouterIPParam), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.ExternalRouterIPParam)(nil), (*ExternalRouterIPParam)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_ExternalRouterIPParam_To_v1alpha7_ExternalRouterIPParam(a.(*v1alpha8.ExternalRouterIPParam), b.(*ExternalRouterIPParam), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*FixedIP)(nil), (*v1alpha8.FixedIP)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_FixedIP_To_v1alpha8_FixedIP(a.(*FixedIP), b.(*v1alpha8.FixedIP), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.FixedIP)(nil), (*FixedIP)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_FixedIP_To_v1alpha7_FixedIP(a.(*v1alpha8.FixedIP), b.(*FixedIP), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*LoadBalancer)(nil), (*v1alpha8.LoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_LoadBalancer_To_v1alpha8_LoadBalancer(a.(*LoadBalancer), b.(*v1alpha8.LoadBalancer), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.LoadBalancer)(nil), (*LoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_LoadBalancer_To_v1alpha7_LoadBalancer(a.(*v1alpha8.LoadBalancer), b.(*LoadBalancer), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*NetworkFilter)(nil), (*v1alpha8.NetworkFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_NetworkFilter_To_v1alpha8_NetworkFilter(a.(*NetworkFilter), b.(*v1alpha8.NetworkFilter), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.NetworkFilter)(nil), (*NetworkFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_NetworkFilter_To_v1alpha7_NetworkFilter(a.(*v1alpha8.NetworkFilter), b.(*NetworkFilter), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*NetworkStatus)(nil), (*v1alpha8.NetworkStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_NetworkStatus_To_v1alpha8_NetworkStatus(a.(*NetworkStatus), b.(*v1alpha8.NetworkStatus), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.NetworkStatus)(nil), (*NetworkStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_NetworkStatus_To_v1alpha7_NetworkStatus(a.(*v1alpha8.NetworkStatus), b.(*NetworkStatus), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*NetworkStatusWithSubnets)(nil), (*v1alpha8.NetworkStatusWithSubnets)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_NetworkStatusWithSubnets_To_v1alpha8_NetworkStatusWithSubnets(a.(*NetworkStatusWithSubnets), b.(*v1alpha8.NetworkStatusWithSubnets), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.NetworkStatusWithSubnets)(nil), (*NetworkStatusWithSubnets)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_NetworkStatusWithSubnets_To_v1alpha7_NetworkStatusWithSubnets(a.(*v1alpha8.NetworkStatusWithSubnets), b.(*NetworkStatusWithSubnets), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*OpenStackCluster)(nil), (*v1alpha8.OpenStackCluster)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_OpenStackCluster_To_v1alpha8_OpenStackCluster(a.(*OpenStackCluster), b.(*v1alpha8.OpenStackCluster), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.OpenStackCluster)(nil), (*OpenStackCluster)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackCluster_To_v1alpha7_OpenStackCluster(a.(*v1alpha8.OpenStackCluster), b.(*OpenStackCluster), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*OpenStackClusterList)(nil), (*v1alpha8.OpenStackClusterList)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_OpenStackClusterList_To_v1alpha8_OpenStackClusterList(a.(*OpenStackClusterList), b.(*v1alpha8.OpenStackClusterList), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.OpenStackClusterList)(nil), (*OpenStackClusterList)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackClusterList_To_v1alpha7_OpenStackClusterList(a.(*v1alpha8.OpenStackClusterList), b.(*OpenStackClusterList), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*OpenStackClusterSpec)(nil), (*v1alpha8.OpenStackClusterSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(a.(*OpenStackClusterSpec), b.(*v1alpha8.OpenStackClusterSpec), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.OpenStackClusterSpec)(nil), (*OpenStackClusterSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(a.(*v1alpha8.OpenStackClusterSpec), b.(*OpenStackClusterSpec), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*OpenStackClusterStatus)(nil), (*v1alpha8.OpenStackClusterStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterStatus(a.(*OpenStackClusterStatus), b.(*v1alpha8.OpenStackClusterStatus), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.OpenStackClusterStatus)(nil), (*OpenStackClusterStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(a.(*v1alpha8.OpenStackClusterStatus), b.(*OpenStackClusterStatus), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*OpenStackClusterTemplate)(nil), (*v1alpha8.OpenStackClusterTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate(a.(*OpenStackClusterTemplate), b.(*v1alpha8.OpenStackClusterTemplate), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.OpenStackClusterTemplate)(nil), (*OpenStackClusterTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate(a.(*v1alpha8.OpenStackClusterTemplate), b.(*OpenStackClusterTemplate), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*OpenStackClusterTemplateList)(nil), (*v1alpha8.OpenStackClusterTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_OpenStackClusterTemplateList_To_v1alpha8_OpenStackClusterTemplateList(a.(*OpenStackClusterTemplateList), b.(*v1alpha8.OpenStackClusterTemplateList), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.OpenStackClusterTemplateList)(nil), (*OpenStackClusterTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackClusterTemplateList_To_v1alpha7_OpenStackClusterTemplateList(a.(*v1alpha8.OpenStackClusterTemplateList), b.(*OpenStackClusterTemplateList), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*OpenStackClusterTemplateResource)(nil), (*v1alpha8.OpenStackClusterTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_OpenStackClusterTemplateResource_To_v1alpha8_OpenStackClusterTemplateResource(a.(*OpenStackClusterTemplateResource), b.(*v1alpha8.OpenStackClusterTemplateResource), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.OpenStackClusterTemplateResource)(nil), (*OpenStackClusterTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackClusterTemplateResource_To_v1alpha7_OpenStackClusterTemplateResource(a.(*v1alpha8.OpenStackClusterTemplateResource), b.(*OpenStackClusterTemplateResource), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*OpenStackClusterTemplateSpec)(nil), (*v1alpha8.OpenStackClusterTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_OpenStackClusterTemplateSpec_To_v1alpha8_OpenStackClusterTemplateSpec(a.(*OpenStackClusterTemplateSpec), b.(*v1alpha8.OpenStackClusterTemplateSpec), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.OpenStackClusterTemplateSpec)(nil), (*OpenStackClusterTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackClusterTemplateSpec_To_v1alpha7_OpenStackClusterTemplateSpec(a.(*v1alpha8.OpenStackClusterTemplateSpec), b.(*OpenStackClusterTemplateSpec), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*OpenStackIdentityReference)(nil), (*v1alpha8.OpenStackIdentityReference)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(a.(*OpenStackIdentityReference), b.(*v1alpha8.OpenStackIdentityReference), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.OpenStackIdentityReference)(nil), (*OpenStackIdentityReference)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference(a.(*v1alpha8.OpenStackIdentityReference), b.(*OpenStackIdentityReference), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*OpenStackMachine)(nil), (*v1alpha8.OpenStackMachine)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_OpenStackMachine_To_v1alpha8_OpenStackMachine(a.(*OpenStackMachine), b.(*v1alpha8.OpenStackMachine), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.OpenStackMachine)(nil), (*OpenStackMachine)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackMachine_To_v1alpha7_OpenStackMachine(a.(*v1alpha8.OpenStackMachine), b.(*OpenStackMachine), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*OpenStackMachineList)(nil), (*v1alpha8.OpenStackMachineList)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_OpenStackMachineList_To_v1alpha8_OpenStackMachineList(a.(*OpenStackMachineList), b.(*v1alpha8.OpenStackMachineList), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.OpenStackMachineList)(nil), (*OpenStackMachineList)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackMachineList_To_v1alpha7_OpenStackMachineList(a.(*v1alpha8.OpenStackMachineList), b.(*OpenStackMachineList), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*OpenStackMachineSpec)(nil), (*v1alpha8.OpenStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(a.(*OpenStackMachineSpec), b.(*v1alpha8.OpenStackMachineSpec), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.OpenStackMachineSpec)(nil), (*OpenStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(a.(*v1alpha8.OpenStackMachineSpec), b.(*OpenStackMachineSpec), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*OpenStackMachineStatus)(nil), (*v1alpha8.OpenStackMachineStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_OpenStackMachineStatus_To_v1alpha8_OpenStackMachineStatus(a.(*OpenStackMachineStatus), b.(*v1alpha8.OpenStackMachineStatus), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.OpenStackMachineStatus)(nil), (*OpenStackMachineStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus(a.(*v1alpha8.OpenStackMachineStatus), b.(*OpenStackMachineStatus), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*OpenStackMachineTemplate)(nil), (*v1alpha8.OpenStackMachineTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate(a.(*OpenStackMachineTemplate), b.(*v1alpha8.OpenStackMachineTemplate), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.OpenStackMachineTemplate)(nil), (*OpenStackMachineTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate(a.(*v1alpha8.OpenStackMachineTemplate), b.(*OpenStackMachineTemplate), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*OpenStackMachineTemplateList)(nil), (*v1alpha8.OpenStackMachineTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_OpenStackMachineTemplateList_To_v1alpha8_OpenStackMachineTemplateList(a.(*OpenStackMachineTemplateList), b.(*v1alpha8.OpenStackMachineTemplateList), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.OpenStackMachineTemplateList)(nil), (*OpenStackMachineTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackMachineTemplateList_To_v1alpha7_OpenStackMachineTemplateList(a.(*v1alpha8.OpenStackMachineTemplateList), b.(*OpenStackMachineTemplateList), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*OpenStackMachineTemplateResource)(nil), (*v1alpha8.OpenStackMachineTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_OpenStackMachineTemplateResource_To_v1alpha8_OpenStackMachineTemplateResource(a.(*OpenStackMachineTemplateResource), b.(*v1alpha8.OpenStackMachineTemplateResource), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.OpenStackMachineTemplateResource)(nil), (*OpenStackMachineTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackMachineTemplateResource_To_v1alpha7_OpenStackMachineTemplateResource(a.(*v1alpha8.OpenStackMachineTemplateResource), b.(*OpenStackMachineTemplateResource), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*OpenStackMachineTemplateSpec)(nil), (*v1alpha8.OpenStackMachineTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_OpenStackMachineTemplateSpec_To_v1alpha8_OpenStackMachineTemplateSpec(a.(*OpenStackMachineTemplateSpec), b.(*v1alpha8.OpenStackMachineTemplateSpec), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.OpenStackMachineTemplateSpec)(nil), (*OpenStackMachineTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackMachineTemplateSpec_To_v1alpha7_OpenStackMachineTemplateSpec(a.(*v1alpha8.OpenStackMachineTemplateSpec), b.(*OpenStackMachineTemplateSpec), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*PortOpts)(nil), (*v1alpha8.PortOpts)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_PortOpts_To_v1alpha8_PortOpts(a.(*PortOpts), b.(*v1alpha8.PortOpts), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.PortOpts)(nil), (*PortOpts)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_PortOpts_To_v1alpha7_PortOpts(a.(*v1alpha8.PortOpts), b.(*PortOpts), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*RootVolume)(nil), (*v1alpha8.RootVolume)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_RootVolume_To_v1alpha8_RootVolume(a.(*RootVolume), b.(*v1alpha8.RootVolume), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.RootVolume)(nil), (*RootVolume)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_RootVolume_To_v1alpha7_RootVolume(a.(*v1alpha8.RootVolume), b.(*RootVolume), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*Router)(nil), (*v1alpha8.Router)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_Router_To_v1alpha8_Router(a.(*Router), b.(*v1alpha8.Router), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.Router)(nil), (*Router)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_Router_To_v1alpha7_Router(a.(*v1alpha8.Router), b.(*Router), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*RouterFilter)(nil), (*v1alpha8.RouterFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_RouterFilter_To_v1alpha8_RouterFilter(a.(*RouterFilter), b.(*v1alpha8.RouterFilter), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.RouterFilter)(nil), (*RouterFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_RouterFilter_To_v1alpha7_RouterFilter(a.(*v1alpha8.RouterFilter), b.(*RouterFilter), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*SecurityGroup)(nil), (*v1alpha8.SecurityGroup)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_SecurityGroup_To_v1alpha8_SecurityGroup(a.(*SecurityGroup), b.(*v1alpha8.SecurityGroup), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.SecurityGroup)(nil), (*SecurityGroup)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_SecurityGroup_To_v1alpha7_SecurityGroup(a.(*v1alpha8.SecurityGroup), b.(*SecurityGroup), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*SecurityGroupFilter)(nil), (*v1alpha8.SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_SecurityGroupFilter_To_v1alpha8_SecurityGroupFilter(a.(*SecurityGroupFilter), b.(*v1alpha8.SecurityGroupFilter), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.SecurityGroupFilter)(nil), (*SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(a.(*v1alpha8.SecurityGroupFilter), b.(*SecurityGroupFilter), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*SecurityGroupRule)(nil), (*v1alpha8.SecurityGroupRule)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_SecurityGroupRule_To_v1alpha8_SecurityGroupRule(a.(*SecurityGroupRule), b.(*v1alpha8.SecurityGroupRule), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.SecurityGroupRule)(nil), (*SecurityGroupRule)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_SecurityGroupRule_To_v1alpha7_SecurityGroupRule(a.(*v1alpha8.SecurityGroupRule), b.(*SecurityGroupRule), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*Subnet)(nil), (*v1alpha8.Subnet)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_Subnet_To_v1alpha8_Subnet(a.(*Subnet), b.(*v1alpha8.Subnet), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.Subnet)(nil), (*Subnet)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_Subnet_To_v1alpha7_Subnet(a.(*v1alpha8.Subnet), b.(*Subnet), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*SubnetFilter)(nil), (*v1alpha8.SubnetFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_SubnetFilter_To_v1alpha8_SubnetFilter(a.(*SubnetFilter), b.(*v1alpha8.SubnetFilter), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.SubnetFilter)(nil), (*SubnetFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_SubnetFilter_To_v1alpha7_SubnetFilter(a.(*v1alpha8.SubnetFilter), b.(*SubnetFilter), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*ValueSpec)(nil), (*v1alpha8.ValueSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_ValueSpec_To_v1alpha8_ValueSpec(a.(*ValueSpec), b.(*v1alpha8.ValueSpec), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*v1alpha8.ValueSpec)(nil), (*ValueSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_ValueSpec_To_v1alpha7_ValueSpec(a.(*v1alpha8.ValueSpec), b.(*ValueSpec), scope)
+ }); err != nil {
+ return err
+ }
+ return nil
+}
+
+func autoConvert_v1alpha7_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalancer(in *APIServerLoadBalancer, out *v1alpha8.APIServerLoadBalancer, s conversion.Scope) error {
+ out.Enabled = in.Enabled
+ out.AdditionalPorts = *(*[]int)(unsafe.Pointer(&in.AdditionalPorts))
+ out.AllowedCIDRs = *(*[]string)(unsafe.Pointer(&in.AllowedCIDRs))
+ out.Provider = in.Provider
+ return nil
+}
+
+// Convert_v1alpha7_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalancer is an autogenerated conversion function.
+func Convert_v1alpha7_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalancer(in *APIServerLoadBalancer, out *v1alpha8.APIServerLoadBalancer, s conversion.Scope) error {
+ return autoConvert_v1alpha7_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalancer(in, out, s)
+}
+
+func autoConvert_v1alpha8_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer(in *v1alpha8.APIServerLoadBalancer, out *APIServerLoadBalancer, s conversion.Scope) error {
+ out.Enabled = in.Enabled
+ out.AdditionalPorts = *(*[]int)(unsafe.Pointer(&in.AdditionalPorts))
+ out.AllowedCIDRs = *(*[]string)(unsafe.Pointer(&in.AllowedCIDRs))
+ out.Provider = in.Provider
+ return nil
+}
+
+// Convert_v1alpha8_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer is an autogenerated conversion function.
+func Convert_v1alpha8_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer(in *v1alpha8.APIServerLoadBalancer, out *APIServerLoadBalancer, s conversion.Scope) error {
+ return autoConvert_v1alpha8_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer(in, out, s)
+}
+
+func autoConvert_v1alpha7_AdditionalBlockDevice_To_v1alpha8_AdditionalBlockDevice(in *AdditionalBlockDevice, out *v1alpha8.AdditionalBlockDevice, s conversion.Scope) error {
+ out.Name = in.Name
+ out.SizeGiB = in.SizeGiB
+ if err := Convert_v1alpha7_BlockDeviceStorage_To_v1alpha8_BlockDeviceStorage(&in.Storage, &out.Storage, s); err != nil {
+ return err
+ }
+ return nil
+}
+
+// Convert_v1alpha7_AdditionalBlockDevice_To_v1alpha8_AdditionalBlockDevice is an autogenerated conversion function.
+func Convert_v1alpha7_AdditionalBlockDevice_To_v1alpha8_AdditionalBlockDevice(in *AdditionalBlockDevice, out *v1alpha8.AdditionalBlockDevice, s conversion.Scope) error {
+ return autoConvert_v1alpha7_AdditionalBlockDevice_To_v1alpha8_AdditionalBlockDevice(in, out, s)
+}
+
+func autoConvert_v1alpha8_AdditionalBlockDevice_To_v1alpha7_AdditionalBlockDevice(in *v1alpha8.AdditionalBlockDevice, out *AdditionalBlockDevice, s conversion.Scope) error {
+ out.Name = in.Name
+ out.SizeGiB = in.SizeGiB
+ if err := Convert_v1alpha8_BlockDeviceStorage_To_v1alpha7_BlockDeviceStorage(&in.Storage, &out.Storage, s); err != nil {
+ return err
+ }
+ return nil
+}
+
+// Convert_v1alpha8_AdditionalBlockDevice_To_v1alpha7_AdditionalBlockDevice is an autogenerated conversion function.
+func Convert_v1alpha8_AdditionalBlockDevice_To_v1alpha7_AdditionalBlockDevice(in *v1alpha8.AdditionalBlockDevice, out *AdditionalBlockDevice, s conversion.Scope) error {
+ return autoConvert_v1alpha8_AdditionalBlockDevice_To_v1alpha7_AdditionalBlockDevice(in, out, s)
+}
+
+func autoConvert_v1alpha7_AddressPair_To_v1alpha8_AddressPair(in *AddressPair, out *v1alpha8.AddressPair, s conversion.Scope) error {
+ out.IPAddress = in.IPAddress
+ out.MACAddress = in.MACAddress
+ return nil
+}
+
+// Convert_v1alpha7_AddressPair_To_v1alpha8_AddressPair is an autogenerated conversion function.
+func Convert_v1alpha7_AddressPair_To_v1alpha8_AddressPair(in *AddressPair, out *v1alpha8.AddressPair, s conversion.Scope) error {
+ return autoConvert_v1alpha7_AddressPair_To_v1alpha8_AddressPair(in, out, s)
+}
+
+func autoConvert_v1alpha8_AddressPair_To_v1alpha7_AddressPair(in *v1alpha8.AddressPair, out *AddressPair, s conversion.Scope) error {
+ out.IPAddress = in.IPAddress
+ out.MACAddress = in.MACAddress
+ return nil
+}
+
+// Convert_v1alpha8_AddressPair_To_v1alpha7_AddressPair is an autogenerated conversion function.
+func Convert_v1alpha8_AddressPair_To_v1alpha7_AddressPair(in *v1alpha8.AddressPair, out *AddressPair, s conversion.Scope) error {
+ return autoConvert_v1alpha8_AddressPair_To_v1alpha7_AddressPair(in, out, s)
+}
+
+func autoConvert_v1alpha7_Bastion_To_v1alpha8_Bastion(in *Bastion, out *v1alpha8.Bastion, s conversion.Scope) error {
+ out.Enabled = in.Enabled
+ if err := Convert_v1alpha7_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(&in.Instance, &out.Instance, s); err != nil {
+ return err
+ }
+ out.AvailabilityZone = in.AvailabilityZone
+ return nil
+}
+
+// Convert_v1alpha7_Bastion_To_v1alpha8_Bastion is an autogenerated conversion function.
+func Convert_v1alpha7_Bastion_To_v1alpha8_Bastion(in *Bastion, out *v1alpha8.Bastion, s conversion.Scope) error {
+ return autoConvert_v1alpha7_Bastion_To_v1alpha8_Bastion(in, out, s)
+}
+
+func autoConvert_v1alpha8_Bastion_To_v1alpha7_Bastion(in *v1alpha8.Bastion, out *Bastion, s conversion.Scope) error {
+ out.Enabled = in.Enabled
+ if err := Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(&in.Instance, &out.Instance, s); err != nil {
+ return err
+ }
+ out.AvailabilityZone = in.AvailabilityZone
+ return nil
+}
+
+// Convert_v1alpha8_Bastion_To_v1alpha7_Bastion is an autogenerated conversion function.
+func Convert_v1alpha8_Bastion_To_v1alpha7_Bastion(in *v1alpha8.Bastion, out *Bastion, s conversion.Scope) error {
+ return autoConvert_v1alpha8_Bastion_To_v1alpha7_Bastion(in, out, s)
+}
+
+func autoConvert_v1alpha7_BastionStatus_To_v1alpha8_BastionStatus(in *BastionStatus, out *v1alpha8.BastionStatus, s conversion.Scope) error {
+ out.ID = in.ID
+ out.Name = in.Name
+ out.SSHKeyName = in.SSHKeyName
+ out.State = v1alpha8.InstanceState(in.State)
+ out.IP = in.IP
+ out.FloatingIP = in.FloatingIP
+ return nil
+}
+
+// Convert_v1alpha7_BastionStatus_To_v1alpha8_BastionStatus is an autogenerated conversion function.
+func Convert_v1alpha7_BastionStatus_To_v1alpha8_BastionStatus(in *BastionStatus, out *v1alpha8.BastionStatus, s conversion.Scope) error {
+ return autoConvert_v1alpha7_BastionStatus_To_v1alpha8_BastionStatus(in, out, s)
+}
+
+func autoConvert_v1alpha8_BastionStatus_To_v1alpha7_BastionStatus(in *v1alpha8.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
+ return nil
+}
+
+// Convert_v1alpha8_BastionStatus_To_v1alpha7_BastionStatus is an autogenerated conversion function.
+func Convert_v1alpha8_BastionStatus_To_v1alpha7_BastionStatus(in *v1alpha8.BastionStatus, out *BastionStatus, s conversion.Scope) error {
+ return autoConvert_v1alpha8_BastionStatus_To_v1alpha7_BastionStatus(in, out, s)
+}
+
+func autoConvert_v1alpha7_BindingProfile_To_v1alpha8_BindingProfile(in *BindingProfile, out *v1alpha8.BindingProfile, s conversion.Scope) error {
+ out.OVSHWOffload = in.OVSHWOffload
+ out.TrustedVF = in.TrustedVF
+ return nil
+}
+
+// Convert_v1alpha7_BindingProfile_To_v1alpha8_BindingProfile is an autogenerated conversion function.
+func Convert_v1alpha7_BindingProfile_To_v1alpha8_BindingProfile(in *BindingProfile, out *v1alpha8.BindingProfile, s conversion.Scope) error {
+ return autoConvert_v1alpha7_BindingProfile_To_v1alpha8_BindingProfile(in, out, s)
+}
+
+func autoConvert_v1alpha8_BindingProfile_To_v1alpha7_BindingProfile(in *v1alpha8.BindingProfile, out *BindingProfile, s conversion.Scope) error {
+ out.OVSHWOffload = in.OVSHWOffload
+ out.TrustedVF = in.TrustedVF
+ return nil
+}
+
+// Convert_v1alpha8_BindingProfile_To_v1alpha7_BindingProfile is an autogenerated conversion function.
+func Convert_v1alpha8_BindingProfile_To_v1alpha7_BindingProfile(in *v1alpha8.BindingProfile, out *BindingProfile, s conversion.Scope) error {
+ return autoConvert_v1alpha8_BindingProfile_To_v1alpha7_BindingProfile(in, out, s)
+}
+
+func autoConvert_v1alpha7_BlockDeviceStorage_To_v1alpha8_BlockDeviceStorage(in *BlockDeviceStorage, out *v1alpha8.BlockDeviceStorage, s conversion.Scope) error {
+ out.Type = v1alpha8.BlockDeviceType(in.Type)
+ out.Volume = (*v1alpha8.BlockDeviceVolume)(unsafe.Pointer(in.Volume))
+ return nil
+}
+
+// Convert_v1alpha7_BlockDeviceStorage_To_v1alpha8_BlockDeviceStorage is an autogenerated conversion function.
+func Convert_v1alpha7_BlockDeviceStorage_To_v1alpha8_BlockDeviceStorage(in *BlockDeviceStorage, out *v1alpha8.BlockDeviceStorage, s conversion.Scope) error {
+ return autoConvert_v1alpha7_BlockDeviceStorage_To_v1alpha8_BlockDeviceStorage(in, out, s)
+}
+
+func autoConvert_v1alpha8_BlockDeviceStorage_To_v1alpha7_BlockDeviceStorage(in *v1alpha8.BlockDeviceStorage, out *BlockDeviceStorage, s conversion.Scope) error {
+ out.Type = BlockDeviceType(in.Type)
+ out.Volume = (*BlockDeviceVolume)(unsafe.Pointer(in.Volume))
+ return nil
+}
+
+// Convert_v1alpha8_BlockDeviceStorage_To_v1alpha7_BlockDeviceStorage is an autogenerated conversion function.
+func Convert_v1alpha8_BlockDeviceStorage_To_v1alpha7_BlockDeviceStorage(in *v1alpha8.BlockDeviceStorage, out *BlockDeviceStorage, s conversion.Scope) error {
+ return autoConvert_v1alpha8_BlockDeviceStorage_To_v1alpha7_BlockDeviceStorage(in, out, s)
+}
+
+func autoConvert_v1alpha7_BlockDeviceVolume_To_v1alpha8_BlockDeviceVolume(in *BlockDeviceVolume, out *v1alpha8.BlockDeviceVolume, s conversion.Scope) error {
+ out.Type = in.Type
+ out.AvailabilityZone = in.AvailabilityZone
+ return nil
+}
+
+// Convert_v1alpha7_BlockDeviceVolume_To_v1alpha8_BlockDeviceVolume is an autogenerated conversion function.
+func Convert_v1alpha7_BlockDeviceVolume_To_v1alpha8_BlockDeviceVolume(in *BlockDeviceVolume, out *v1alpha8.BlockDeviceVolume, s conversion.Scope) error {
+ return autoConvert_v1alpha7_BlockDeviceVolume_To_v1alpha8_BlockDeviceVolume(in, out, s)
+}
+
+func autoConvert_v1alpha8_BlockDeviceVolume_To_v1alpha7_BlockDeviceVolume(in *v1alpha8.BlockDeviceVolume, out *BlockDeviceVolume, s conversion.Scope) error {
+ out.Type = in.Type
+ out.AvailabilityZone = in.AvailabilityZone
+ return nil
+}
+
+// Convert_v1alpha8_BlockDeviceVolume_To_v1alpha7_BlockDeviceVolume is an autogenerated conversion function.
+func Convert_v1alpha8_BlockDeviceVolume_To_v1alpha7_BlockDeviceVolume(in *v1alpha8.BlockDeviceVolume, out *BlockDeviceVolume, s conversion.Scope) error {
+ return autoConvert_v1alpha8_BlockDeviceVolume_To_v1alpha7_BlockDeviceVolume(in, out, s)
+}
+
+func autoConvert_v1alpha7_ExternalRouterIPParam_To_v1alpha8_ExternalRouterIPParam(in *ExternalRouterIPParam, out *v1alpha8.ExternalRouterIPParam, s conversion.Scope) error {
+ out.FixedIP = in.FixedIP
+ if err := Convert_v1alpha7_SubnetFilter_To_v1alpha8_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil {
+ return err
+ }
+ return nil
+}
+
+// Convert_v1alpha7_ExternalRouterIPParam_To_v1alpha8_ExternalRouterIPParam is an autogenerated conversion function.
+func Convert_v1alpha7_ExternalRouterIPParam_To_v1alpha8_ExternalRouterIPParam(in *ExternalRouterIPParam, out *v1alpha8.ExternalRouterIPParam, s conversion.Scope) error {
+ return autoConvert_v1alpha7_ExternalRouterIPParam_To_v1alpha8_ExternalRouterIPParam(in, out, s)
+}
+
+func autoConvert_v1alpha8_ExternalRouterIPParam_To_v1alpha7_ExternalRouterIPParam(in *v1alpha8.ExternalRouterIPParam, out *ExternalRouterIPParam, s conversion.Scope) error {
+ out.FixedIP = in.FixedIP
+ if err := Convert_v1alpha8_SubnetFilter_To_v1alpha7_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil {
+ return err
+ }
+ return nil
+}
+
+// Convert_v1alpha8_ExternalRouterIPParam_To_v1alpha7_ExternalRouterIPParam is an autogenerated conversion function.
+func Convert_v1alpha8_ExternalRouterIPParam_To_v1alpha7_ExternalRouterIPParam(in *v1alpha8.ExternalRouterIPParam, out *ExternalRouterIPParam, s conversion.Scope) error {
+ return autoConvert_v1alpha8_ExternalRouterIPParam_To_v1alpha7_ExternalRouterIPParam(in, out, s)
+}
+
+func autoConvert_v1alpha7_FixedIP_To_v1alpha8_FixedIP(in *FixedIP, out *v1alpha8.FixedIP, s conversion.Scope) error {
+ out.Subnet = (*v1alpha8.SubnetFilter)(unsafe.Pointer(in.Subnet))
+ out.IPAddress = in.IPAddress
+ return nil
+}
+
+// Convert_v1alpha7_FixedIP_To_v1alpha8_FixedIP is an autogenerated conversion function.
+func Convert_v1alpha7_FixedIP_To_v1alpha8_FixedIP(in *FixedIP, out *v1alpha8.FixedIP, s conversion.Scope) error {
+ return autoConvert_v1alpha7_FixedIP_To_v1alpha8_FixedIP(in, out, s)
+}
+
+func autoConvert_v1alpha8_FixedIP_To_v1alpha7_FixedIP(in *v1alpha8.FixedIP, out *FixedIP, s conversion.Scope) error {
+ out.Subnet = (*SubnetFilter)(unsafe.Pointer(in.Subnet))
+ out.IPAddress = in.IPAddress
+ return nil
+}
+
+// Convert_v1alpha8_FixedIP_To_v1alpha7_FixedIP is an autogenerated conversion function.
+func Convert_v1alpha8_FixedIP_To_v1alpha7_FixedIP(in *v1alpha8.FixedIP, out *FixedIP, s conversion.Scope) error {
+ return autoConvert_v1alpha8_FixedIP_To_v1alpha7_FixedIP(in, out, s)
+}
+
+func autoConvert_v1alpha7_LoadBalancer_To_v1alpha8_LoadBalancer(in *LoadBalancer, out *v1alpha8.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_v1alpha8_LoadBalancer is an autogenerated conversion function.
+func Convert_v1alpha7_LoadBalancer_To_v1alpha8_LoadBalancer(in *LoadBalancer, out *v1alpha8.LoadBalancer, s conversion.Scope) error {
+ return autoConvert_v1alpha7_LoadBalancer_To_v1alpha8_LoadBalancer(in, out, s)
+}
+
+func autoConvert_v1alpha8_LoadBalancer_To_v1alpha7_LoadBalancer(in *v1alpha8.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))
+ return nil
+}
+
+// Convert_v1alpha8_LoadBalancer_To_v1alpha7_LoadBalancer is an autogenerated conversion function.
+func Convert_v1alpha8_LoadBalancer_To_v1alpha7_LoadBalancer(in *v1alpha8.LoadBalancer, out *LoadBalancer, s conversion.Scope) error {
+ return autoConvert_v1alpha8_LoadBalancer_To_v1alpha7_LoadBalancer(in, out, s)
+}
+
+func autoConvert_v1alpha7_NetworkFilter_To_v1alpha8_NetworkFilter(in *NetworkFilter, out *v1alpha8.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
+ return nil
+}
+
+// Convert_v1alpha7_NetworkFilter_To_v1alpha8_NetworkFilter is an autogenerated conversion function.
+func Convert_v1alpha7_NetworkFilter_To_v1alpha8_NetworkFilter(in *NetworkFilter, out *v1alpha8.NetworkFilter, s conversion.Scope) error {
+ return autoConvert_v1alpha7_NetworkFilter_To_v1alpha8_NetworkFilter(in, out, s)
+}
+
+func autoConvert_v1alpha8_NetworkFilter_To_v1alpha7_NetworkFilter(in *v1alpha8.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
+ return nil
+}
+
+// Convert_v1alpha8_NetworkFilter_To_v1alpha7_NetworkFilter is an autogenerated conversion function.
+func Convert_v1alpha8_NetworkFilter_To_v1alpha7_NetworkFilter(in *v1alpha8.NetworkFilter, out *NetworkFilter, s conversion.Scope) error {
+ return autoConvert_v1alpha8_NetworkFilter_To_v1alpha7_NetworkFilter(in, out, s)
+}
+
+func autoConvert_v1alpha7_NetworkStatus_To_v1alpha8_NetworkStatus(in *NetworkStatus, out *v1alpha8.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_v1alpha8_NetworkStatus is an autogenerated conversion function.
+func Convert_v1alpha7_NetworkStatus_To_v1alpha8_NetworkStatus(in *NetworkStatus, out *v1alpha8.NetworkStatus, s conversion.Scope) error {
+ return autoConvert_v1alpha7_NetworkStatus_To_v1alpha8_NetworkStatus(in, out, s)
+}
+
+func autoConvert_v1alpha8_NetworkStatus_To_v1alpha7_NetworkStatus(in *v1alpha8.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_v1alpha8_NetworkStatus_To_v1alpha7_NetworkStatus is an autogenerated conversion function.
+func Convert_v1alpha8_NetworkStatus_To_v1alpha7_NetworkStatus(in *v1alpha8.NetworkStatus, out *NetworkStatus, s conversion.Scope) error {
+ return autoConvert_v1alpha8_NetworkStatus_To_v1alpha7_NetworkStatus(in, out, s)
+}
+
+func autoConvert_v1alpha7_NetworkStatusWithSubnets_To_v1alpha8_NetworkStatusWithSubnets(in *NetworkStatusWithSubnets, out *v1alpha8.NetworkStatusWithSubnets, s conversion.Scope) error {
+ if err := Convert_v1alpha7_NetworkStatus_To_v1alpha8_NetworkStatus(&in.NetworkStatus, &out.NetworkStatus, s); err != nil {
+ return err
+ }
+ out.Subnets = *(*[]v1alpha8.Subnet)(unsafe.Pointer(&in.Subnets))
+ return nil
+}
+
+// Convert_v1alpha7_NetworkStatusWithSubnets_To_v1alpha8_NetworkStatusWithSubnets is an autogenerated conversion function.
+func Convert_v1alpha7_NetworkStatusWithSubnets_To_v1alpha8_NetworkStatusWithSubnets(in *NetworkStatusWithSubnets, out *v1alpha8.NetworkStatusWithSubnets, s conversion.Scope) error {
+ return autoConvert_v1alpha7_NetworkStatusWithSubnets_To_v1alpha8_NetworkStatusWithSubnets(in, out, s)
+}
+
+func autoConvert_v1alpha8_NetworkStatusWithSubnets_To_v1alpha7_NetworkStatusWithSubnets(in *v1alpha8.NetworkStatusWithSubnets, out *NetworkStatusWithSubnets, s conversion.Scope) error {
+ if err := Convert_v1alpha8_NetworkStatus_To_v1alpha7_NetworkStatus(&in.NetworkStatus, &out.NetworkStatus, s); err != nil {
+ return err
+ }
+ out.Subnets = *(*[]Subnet)(unsafe.Pointer(&in.Subnets))
+ return nil
+}
+
+// Convert_v1alpha8_NetworkStatusWithSubnets_To_v1alpha7_NetworkStatusWithSubnets is an autogenerated conversion function.
+func Convert_v1alpha8_NetworkStatusWithSubnets_To_v1alpha7_NetworkStatusWithSubnets(in *v1alpha8.NetworkStatusWithSubnets, out *NetworkStatusWithSubnets, s conversion.Scope) error {
+ return autoConvert_v1alpha8_NetworkStatusWithSubnets_To_v1alpha7_NetworkStatusWithSubnets(in, out, s)
+}
+
+func autoConvert_v1alpha7_OpenStackCluster_To_v1alpha8_OpenStackCluster(in *OpenStackCluster, out *v1alpha8.OpenStackCluster, s conversion.Scope) error {
+ out.ObjectMeta = in.ObjectMeta
+ if err := Convert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(&in.Spec, &out.Spec, s); err != nil {
+ return err
+ }
+ if err := Convert_v1alpha7_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterStatus(&in.Status, &out.Status, s); err != nil {
+ return err
+ }
+ return nil
+}
+
+// Convert_v1alpha7_OpenStackCluster_To_v1alpha8_OpenStackCluster is an autogenerated conversion function.
+func Convert_v1alpha7_OpenStackCluster_To_v1alpha8_OpenStackCluster(in *OpenStackCluster, out *v1alpha8.OpenStackCluster, s conversion.Scope) error {
+ return autoConvert_v1alpha7_OpenStackCluster_To_v1alpha8_OpenStackCluster(in, out, s)
+}
+
+func autoConvert_v1alpha8_OpenStackCluster_To_v1alpha7_OpenStackCluster(in *v1alpha8.OpenStackCluster, out *OpenStackCluster, s conversion.Scope) error {
+ out.ObjectMeta = in.ObjectMeta
+ if err := Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(&in.Spec, &out.Spec, s); err != nil {
+ return err
+ }
+ if err := Convert_v1alpha8_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(&in.Status, &out.Status, s); err != nil {
+ return err
+ }
+ return nil
+}
+
+// Convert_v1alpha8_OpenStackCluster_To_v1alpha7_OpenStackCluster is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackCluster_To_v1alpha7_OpenStackCluster(in *v1alpha8.OpenStackCluster, out *OpenStackCluster, s conversion.Scope) error {
+ return autoConvert_v1alpha8_OpenStackCluster_To_v1alpha7_OpenStackCluster(in, out, s)
+}
+
+func autoConvert_v1alpha7_OpenStackClusterList_To_v1alpha8_OpenStackClusterList(in *OpenStackClusterList, out *v1alpha8.OpenStackClusterList, s conversion.Scope) error {
+ out.ListMeta = in.ListMeta
+ out.Items = *(*[]v1alpha8.OpenStackCluster)(unsafe.Pointer(&in.Items))
+ return nil
+}
+
+// Convert_v1alpha7_OpenStackClusterList_To_v1alpha8_OpenStackClusterList is an autogenerated conversion function.
+func Convert_v1alpha7_OpenStackClusterList_To_v1alpha8_OpenStackClusterList(in *OpenStackClusterList, out *v1alpha8.OpenStackClusterList, s conversion.Scope) error {
+ return autoConvert_v1alpha7_OpenStackClusterList_To_v1alpha8_OpenStackClusterList(in, out, s)
+}
+
+func autoConvert_v1alpha8_OpenStackClusterList_To_v1alpha7_OpenStackClusterList(in *v1alpha8.OpenStackClusterList, out *OpenStackClusterList, s conversion.Scope) error {
+ out.ListMeta = in.ListMeta
+ out.Items = *(*[]OpenStackCluster)(unsafe.Pointer(&in.Items))
+ return nil
+}
+
+// Convert_v1alpha8_OpenStackClusterList_To_v1alpha7_OpenStackClusterList is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackClusterList_To_v1alpha7_OpenStackClusterList(in *v1alpha8.OpenStackClusterList, out *OpenStackClusterList, s conversion.Scope) error {
+ return autoConvert_v1alpha8_OpenStackClusterList_To_v1alpha7_OpenStackClusterList(in, out, s)
+}
+
+func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *OpenStackClusterSpec, out *v1alpha8.OpenStackClusterSpec, s conversion.Scope) error {
+ out.CloudName = in.CloudName
+ out.NodeCIDR = in.NodeCIDR
+ out.Router = (*v1alpha8.RouterFilter)(unsafe.Pointer(in.Router))
+ if err := Convert_v1alpha7_NetworkFilter_To_v1alpha8_NetworkFilter(&in.Network, &out.Network, s); err != nil {
+ return err
+ }
+ if err := Convert_v1alpha7_SubnetFilter_To_v1alpha8_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil {
+ return err
+ }
+ out.NetworkMTU = in.NetworkMTU
+ out.DNSNameservers = *(*[]string)(unsafe.Pointer(&in.DNSNameservers))
+ out.ExternalRouterIPs = *(*[]v1alpha8.ExternalRouterIPParam)(unsafe.Pointer(&in.ExternalRouterIPs))
+ out.ExternalNetworkID = in.ExternalNetworkID
+ if err := Convert_v1alpha7_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, 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
+ out.ControlPlaneAvailabilityZones = *(*[]string)(unsafe.Pointer(&in.ControlPlaneAvailabilityZones))
+ out.ControlPlaneOmitAvailabilityZone = in.ControlPlaneOmitAvailabilityZone
+ out.Bastion = (*v1alpha8.Bastion)(unsafe.Pointer(in.Bastion))
+ out.IdentityRef = (*v1alpha8.OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef))
+ return nil
+}
+
+// Convert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec is an autogenerated conversion function.
+func Convert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *OpenStackClusterSpec, out *v1alpha8.OpenStackClusterSpec, s conversion.Scope) error {
+ return autoConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in, out, s)
+}
+
+func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in *v1alpha8.OpenStackClusterSpec, out *OpenStackClusterSpec, s conversion.Scope) error {
+ out.CloudName = in.CloudName
+ out.NodeCIDR = in.NodeCIDR
+ out.Router = (*RouterFilter)(unsafe.Pointer(in.Router))
+ if err := Convert_v1alpha8_NetworkFilter_To_v1alpha7_NetworkFilter(&in.Network, &out.Network, s); err != nil {
+ return err
+ }
+ if err := Convert_v1alpha8_SubnetFilter_To_v1alpha7_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil {
+ return err
+ }
+ out.NetworkMTU = in.NetworkMTU
+ out.DNSNameservers = *(*[]string)(unsafe.Pointer(&in.DNSNameservers))
+ out.ExternalRouterIPs = *(*[]ExternalRouterIPParam)(unsafe.Pointer(&in.ExternalRouterIPs))
+ out.ExternalNetworkID = in.ExternalNetworkID
+ if err := Convert_v1alpha8_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, 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
+ out.ControlPlaneAvailabilityZones = *(*[]string)(unsafe.Pointer(&in.ControlPlaneAvailabilityZones))
+ out.ControlPlaneOmitAvailabilityZone = in.ControlPlaneOmitAvailabilityZone
+ out.Bastion = (*Bastion)(unsafe.Pointer(in.Bastion))
+ out.IdentityRef = (*OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef))
+ return nil
+}
+
+// Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in *v1alpha8.OpenStackClusterSpec, out *OpenStackClusterSpec, s conversion.Scope) error {
+ return autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in, out, s)
+}
+
+func autoConvert_v1alpha7_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterStatus(in *OpenStackClusterStatus, out *v1alpha8.OpenStackClusterStatus, s conversion.Scope) error {
+ out.Ready = in.Ready
+ out.Network = (*v1alpha8.NetworkStatusWithSubnets)(unsafe.Pointer(in.Network))
+ out.ExternalNetwork = (*v1alpha8.NetworkStatus)(unsafe.Pointer(in.ExternalNetwork))
+ out.Router = (*v1alpha8.Router)(unsafe.Pointer(in.Router))
+ out.APIServerLoadBalancer = (*v1alpha8.LoadBalancer)(unsafe.Pointer(in.APIServerLoadBalancer))
+ out.FailureDomains = *(*v1beta1.FailureDomains)(unsafe.Pointer(&in.FailureDomains))
+ out.ControlPlaneSecurityGroup = (*v1alpha8.SecurityGroup)(unsafe.Pointer(in.ControlPlaneSecurityGroup))
+ out.WorkerSecurityGroup = (*v1alpha8.SecurityGroup)(unsafe.Pointer(in.WorkerSecurityGroup))
+ out.BastionSecurityGroup = (*v1alpha8.SecurityGroup)(unsafe.Pointer(in.BastionSecurityGroup))
+ out.Bastion = (*v1alpha8.BastionStatus)(unsafe.Pointer(in.Bastion))
+ out.FailureReason = (*errors.ClusterStatusError)(unsafe.Pointer(in.FailureReason))
+ out.FailureMessage = (*string)(unsafe.Pointer(in.FailureMessage))
+ return nil
+}
+
+// Convert_v1alpha7_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterStatus is an autogenerated conversion function.
+func Convert_v1alpha7_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterStatus(in *OpenStackClusterStatus, out *v1alpha8.OpenStackClusterStatus, s conversion.Scope) error {
+ return autoConvert_v1alpha7_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterStatus(in, out, s)
+}
+
+func autoConvert_v1alpha8_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(in *v1alpha8.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))
+ out.APIServerLoadBalancer = (*LoadBalancer)(unsafe.Pointer(in.APIServerLoadBalancer))
+ 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.Bastion = (*BastionStatus)(unsafe.Pointer(in.Bastion))
+ out.FailureReason = (*errors.ClusterStatusError)(unsafe.Pointer(in.FailureReason))
+ out.FailureMessage = (*string)(unsafe.Pointer(in.FailureMessage))
+ return nil
+}
+
+// Convert_v1alpha8_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(in *v1alpha8.OpenStackClusterStatus, out *OpenStackClusterStatus, s conversion.Scope) error {
+ return autoConvert_v1alpha8_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(in, out, s)
+}
+
+func autoConvert_v1alpha7_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate(in *OpenStackClusterTemplate, out *v1alpha8.OpenStackClusterTemplate, s conversion.Scope) error {
+ out.ObjectMeta = in.ObjectMeta
+ if err := Convert_v1alpha7_OpenStackClusterTemplateSpec_To_v1alpha8_OpenStackClusterTemplateSpec(&in.Spec, &out.Spec, s); err != nil {
+ return err
+ }
+ return nil
+}
+
+// Convert_v1alpha7_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate is an autogenerated conversion function.
+func Convert_v1alpha7_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate(in *OpenStackClusterTemplate, out *v1alpha8.OpenStackClusterTemplate, s conversion.Scope) error {
+ return autoConvert_v1alpha7_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate(in, out, s)
+}
+
+func autoConvert_v1alpha8_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate(in *v1alpha8.OpenStackClusterTemplate, out *OpenStackClusterTemplate, s conversion.Scope) error {
+ out.ObjectMeta = in.ObjectMeta
+ if err := Convert_v1alpha8_OpenStackClusterTemplateSpec_To_v1alpha7_OpenStackClusterTemplateSpec(&in.Spec, &out.Spec, s); err != nil {
+ return err
+ }
+ return nil
+}
+
+// Convert_v1alpha8_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate(in *v1alpha8.OpenStackClusterTemplate, out *OpenStackClusterTemplate, s conversion.Scope) error {
+ return autoConvert_v1alpha8_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate(in, out, s)
+}
+
+func autoConvert_v1alpha7_OpenStackClusterTemplateList_To_v1alpha8_OpenStackClusterTemplateList(in *OpenStackClusterTemplateList, out *v1alpha8.OpenStackClusterTemplateList, s conversion.Scope) error {
+ out.ListMeta = in.ListMeta
+ out.Items = *(*[]v1alpha8.OpenStackClusterTemplate)(unsafe.Pointer(&in.Items))
+ return nil
+}
+
+// Convert_v1alpha7_OpenStackClusterTemplateList_To_v1alpha8_OpenStackClusterTemplateList is an autogenerated conversion function.
+func Convert_v1alpha7_OpenStackClusterTemplateList_To_v1alpha8_OpenStackClusterTemplateList(in *OpenStackClusterTemplateList, out *v1alpha8.OpenStackClusterTemplateList, s conversion.Scope) error {
+ return autoConvert_v1alpha7_OpenStackClusterTemplateList_To_v1alpha8_OpenStackClusterTemplateList(in, out, s)
+}
+
+func autoConvert_v1alpha8_OpenStackClusterTemplateList_To_v1alpha7_OpenStackClusterTemplateList(in *v1alpha8.OpenStackClusterTemplateList, out *OpenStackClusterTemplateList, s conversion.Scope) error {
+ out.ListMeta = in.ListMeta
+ out.Items = *(*[]OpenStackClusterTemplate)(unsafe.Pointer(&in.Items))
+ return nil
+}
+
+// Convert_v1alpha8_OpenStackClusterTemplateList_To_v1alpha7_OpenStackClusterTemplateList is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackClusterTemplateList_To_v1alpha7_OpenStackClusterTemplateList(in *v1alpha8.OpenStackClusterTemplateList, out *OpenStackClusterTemplateList, s conversion.Scope) error {
+ return autoConvert_v1alpha8_OpenStackClusterTemplateList_To_v1alpha7_OpenStackClusterTemplateList(in, out, s)
+}
+
+func autoConvert_v1alpha7_OpenStackClusterTemplateResource_To_v1alpha8_OpenStackClusterTemplateResource(in *OpenStackClusterTemplateResource, out *v1alpha8.OpenStackClusterTemplateResource, s conversion.Scope) error {
+ if err := Convert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(&in.Spec, &out.Spec, s); err != nil {
+ return err
+ }
+ return nil
+}
+
+// Convert_v1alpha7_OpenStackClusterTemplateResource_To_v1alpha8_OpenStackClusterTemplateResource is an autogenerated conversion function.
+func Convert_v1alpha7_OpenStackClusterTemplateResource_To_v1alpha8_OpenStackClusterTemplateResource(in *OpenStackClusterTemplateResource, out *v1alpha8.OpenStackClusterTemplateResource, s conversion.Scope) error {
+ return autoConvert_v1alpha7_OpenStackClusterTemplateResource_To_v1alpha8_OpenStackClusterTemplateResource(in, out, s)
+}
+
+func autoConvert_v1alpha8_OpenStackClusterTemplateResource_To_v1alpha7_OpenStackClusterTemplateResource(in *v1alpha8.OpenStackClusterTemplateResource, out *OpenStackClusterTemplateResource, s conversion.Scope) error {
+ if err := Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(&in.Spec, &out.Spec, s); err != nil {
+ return err
+ }
+ return nil
+}
+
+// Convert_v1alpha8_OpenStackClusterTemplateResource_To_v1alpha7_OpenStackClusterTemplateResource is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackClusterTemplateResource_To_v1alpha7_OpenStackClusterTemplateResource(in *v1alpha8.OpenStackClusterTemplateResource, out *OpenStackClusterTemplateResource, s conversion.Scope) error {
+ return autoConvert_v1alpha8_OpenStackClusterTemplateResource_To_v1alpha7_OpenStackClusterTemplateResource(in, out, s)
+}
+
+func autoConvert_v1alpha7_OpenStackClusterTemplateSpec_To_v1alpha8_OpenStackClusterTemplateSpec(in *OpenStackClusterTemplateSpec, out *v1alpha8.OpenStackClusterTemplateSpec, s conversion.Scope) error {
+ if err := Convert_v1alpha7_OpenStackClusterTemplateResource_To_v1alpha8_OpenStackClusterTemplateResource(&in.Template, &out.Template, s); err != nil {
+ return err
+ }
+ return nil
+}
+
+// Convert_v1alpha7_OpenStackClusterTemplateSpec_To_v1alpha8_OpenStackClusterTemplateSpec is an autogenerated conversion function.
+func Convert_v1alpha7_OpenStackClusterTemplateSpec_To_v1alpha8_OpenStackClusterTemplateSpec(in *OpenStackClusterTemplateSpec, out *v1alpha8.OpenStackClusterTemplateSpec, s conversion.Scope) error {
+ return autoConvert_v1alpha7_OpenStackClusterTemplateSpec_To_v1alpha8_OpenStackClusterTemplateSpec(in, out, s)
+}
+
+func autoConvert_v1alpha8_OpenStackClusterTemplateSpec_To_v1alpha7_OpenStackClusterTemplateSpec(in *v1alpha8.OpenStackClusterTemplateSpec, out *OpenStackClusterTemplateSpec, s conversion.Scope) error {
+ if err := Convert_v1alpha8_OpenStackClusterTemplateResource_To_v1alpha7_OpenStackClusterTemplateResource(&in.Template, &out.Template, s); err != nil {
+ return err
+ }
+ return nil
+}
+
+// Convert_v1alpha8_OpenStackClusterTemplateSpec_To_v1alpha7_OpenStackClusterTemplateSpec is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackClusterTemplateSpec_To_v1alpha7_OpenStackClusterTemplateSpec(in *v1alpha8.OpenStackClusterTemplateSpec, out *OpenStackClusterTemplateSpec, s conversion.Scope) error {
+ return autoConvert_v1alpha8_OpenStackClusterTemplateSpec_To_v1alpha7_OpenStackClusterTemplateSpec(in, out, s)
+}
+
+func autoConvert_v1alpha7_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(in *OpenStackIdentityReference, out *v1alpha8.OpenStackIdentityReference, s conversion.Scope) error {
+ out.Kind = in.Kind
+ out.Name = in.Name
+ return nil
+}
+
+// Convert_v1alpha7_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference is an autogenerated conversion function.
+func Convert_v1alpha7_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(in *OpenStackIdentityReference, out *v1alpha8.OpenStackIdentityReference, s conversion.Scope) error {
+ return autoConvert_v1alpha7_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(in, out, s)
+}
+
+func autoConvert_v1alpha8_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference(in *v1alpha8.OpenStackIdentityReference, out *OpenStackIdentityReference, s conversion.Scope) error {
+ out.Kind = in.Kind
+ out.Name = in.Name
+ return nil
+}
+
+// Convert_v1alpha8_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference(in *v1alpha8.OpenStackIdentityReference, out *OpenStackIdentityReference, s conversion.Scope) error {
+ return autoConvert_v1alpha8_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference(in, out, s)
+}
+
+func autoConvert_v1alpha7_OpenStackMachine_To_v1alpha8_OpenStackMachine(in *OpenStackMachine, out *v1alpha8.OpenStackMachine, s conversion.Scope) error {
+ out.ObjectMeta = in.ObjectMeta
+ if err := Convert_v1alpha7_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(&in.Spec, &out.Spec, s); err != nil {
+ return err
+ }
+ if err := Convert_v1alpha7_OpenStackMachineStatus_To_v1alpha8_OpenStackMachineStatus(&in.Status, &out.Status, s); err != nil {
+ return err
+ }
+ return nil
+}
+
+// Convert_v1alpha7_OpenStackMachine_To_v1alpha8_OpenStackMachine is an autogenerated conversion function.
+func Convert_v1alpha7_OpenStackMachine_To_v1alpha8_OpenStackMachine(in *OpenStackMachine, out *v1alpha8.OpenStackMachine, s conversion.Scope) error {
+ return autoConvert_v1alpha7_OpenStackMachine_To_v1alpha8_OpenStackMachine(in, out, s)
+}
+
+func autoConvert_v1alpha8_OpenStackMachine_To_v1alpha7_OpenStackMachine(in *v1alpha8.OpenStackMachine, out *OpenStackMachine, s conversion.Scope) error {
+ out.ObjectMeta = in.ObjectMeta
+ if err := Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(&in.Spec, &out.Spec, s); err != nil {
+ return err
+ }
+ if err := Convert_v1alpha8_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus(&in.Status, &out.Status, s); err != nil {
+ return err
+ }
+ return nil
+}
+
+// Convert_v1alpha8_OpenStackMachine_To_v1alpha7_OpenStackMachine is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackMachine_To_v1alpha7_OpenStackMachine(in *v1alpha8.OpenStackMachine, out *OpenStackMachine, s conversion.Scope) error {
+ return autoConvert_v1alpha8_OpenStackMachine_To_v1alpha7_OpenStackMachine(in, out, s)
+}
+
+func autoConvert_v1alpha7_OpenStackMachineList_To_v1alpha8_OpenStackMachineList(in *OpenStackMachineList, out *v1alpha8.OpenStackMachineList, s conversion.Scope) error {
+ out.ListMeta = in.ListMeta
+ out.Items = *(*[]v1alpha8.OpenStackMachine)(unsafe.Pointer(&in.Items))
+ return nil
+}
+
+// Convert_v1alpha7_OpenStackMachineList_To_v1alpha8_OpenStackMachineList is an autogenerated conversion function.
+func Convert_v1alpha7_OpenStackMachineList_To_v1alpha8_OpenStackMachineList(in *OpenStackMachineList, out *v1alpha8.OpenStackMachineList, s conversion.Scope) error {
+ return autoConvert_v1alpha7_OpenStackMachineList_To_v1alpha8_OpenStackMachineList(in, out, s)
+}
+
+func autoConvert_v1alpha8_OpenStackMachineList_To_v1alpha7_OpenStackMachineList(in *v1alpha8.OpenStackMachineList, out *OpenStackMachineList, s conversion.Scope) error {
+ out.ListMeta = in.ListMeta
+ out.Items = *(*[]OpenStackMachine)(unsafe.Pointer(&in.Items))
+ return nil
+}
+
+// Convert_v1alpha8_OpenStackMachineList_To_v1alpha7_OpenStackMachineList is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackMachineList_To_v1alpha7_OpenStackMachineList(in *v1alpha8.OpenStackMachineList, out *OpenStackMachineList, s conversion.Scope) error {
+ return autoConvert_v1alpha8_OpenStackMachineList_To_v1alpha7_OpenStackMachineList(in, out, s)
+}
+
+func autoConvert_v1alpha7_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(in *OpenStackMachineSpec, out *v1alpha8.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
+ out.SSHKeyName = in.SSHKeyName
+ out.Ports = *(*[]v1alpha8.PortOpts)(unsafe.Pointer(&in.Ports))
+ out.FloatingIP = in.FloatingIP
+ out.SecurityGroups = *(*[]v1alpha8.SecurityGroupFilter)(unsafe.Pointer(&in.SecurityGroups))
+ out.Trunk = in.Trunk
+ out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
+ out.ServerMetadata = *(*map[string]string)(unsafe.Pointer(&in.ServerMetadata))
+ out.ConfigDrive = (*bool)(unsafe.Pointer(in.ConfigDrive))
+ out.RootVolume = (*v1alpha8.RootVolume)(unsafe.Pointer(in.RootVolume))
+ out.AdditionalBlockDevices = *(*[]v1alpha8.AdditionalBlockDevice)(unsafe.Pointer(&in.AdditionalBlockDevices))
+ out.ServerGroupID = in.ServerGroupID
+ out.IdentityRef = (*v1alpha8.OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef))
+ return nil
+}
+
+// Convert_v1alpha7_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec is an autogenerated conversion function.
+func Convert_v1alpha7_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(in *OpenStackMachineSpec, out *v1alpha8.OpenStackMachineSpec, s conversion.Scope) error {
+ return autoConvert_v1alpha7_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(in, out, s)
+}
+
+func autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(in *v1alpha8.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
+ out.SSHKeyName = in.SSHKeyName
+ out.Ports = *(*[]PortOpts)(unsafe.Pointer(&in.Ports))
+ out.FloatingIP = in.FloatingIP
+ out.SecurityGroups = *(*[]SecurityGroupFilter)(unsafe.Pointer(&in.SecurityGroups))
+ out.Trunk = in.Trunk
+ out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
+ out.ServerMetadata = *(*map[string]string)(unsafe.Pointer(&in.ServerMetadata))
+ out.ConfigDrive = (*bool)(unsafe.Pointer(in.ConfigDrive))
+ out.RootVolume = (*RootVolume)(unsafe.Pointer(in.RootVolume))
+ out.AdditionalBlockDevices = *(*[]AdditionalBlockDevice)(unsafe.Pointer(&in.AdditionalBlockDevices))
+ out.ServerGroupID = in.ServerGroupID
+ out.IdentityRef = (*OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef))
+ return nil
+}
+
+// Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(in *v1alpha8.OpenStackMachineSpec, out *OpenStackMachineSpec, s conversion.Scope) error {
+ return autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(in, out, s)
+}
+
+func autoConvert_v1alpha7_OpenStackMachineStatus_To_v1alpha8_OpenStackMachineStatus(in *OpenStackMachineStatus, out *v1alpha8.OpenStackMachineStatus, s conversion.Scope) error {
+ out.Ready = in.Ready
+ out.Addresses = *(*[]v1.NodeAddress)(unsafe.Pointer(&in.Addresses))
+ out.InstanceState = (*v1alpha8.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))
+ return nil
+}
+
+// Convert_v1alpha7_OpenStackMachineStatus_To_v1alpha8_OpenStackMachineStatus is an autogenerated conversion function.
+func Convert_v1alpha7_OpenStackMachineStatus_To_v1alpha8_OpenStackMachineStatus(in *OpenStackMachineStatus, out *v1alpha8.OpenStackMachineStatus, s conversion.Scope) error {
+ return autoConvert_v1alpha7_OpenStackMachineStatus_To_v1alpha8_OpenStackMachineStatus(in, out, s)
+}
+
+func autoConvert_v1alpha8_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus(in *v1alpha8.OpenStackMachineStatus, out *OpenStackMachineStatus, s conversion.Scope) error {
+ out.Ready = in.Ready
+ out.Addresses = *(*[]v1.NodeAddress)(unsafe.Pointer(&in.Addresses))
+ out.InstanceState = (*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))
+ return nil
+}
+
+// Convert_v1alpha8_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus(in *v1alpha8.OpenStackMachineStatus, out *OpenStackMachineStatus, s conversion.Scope) error {
+ return autoConvert_v1alpha8_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus(in, out, s)
+}
+
+func autoConvert_v1alpha7_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate(in *OpenStackMachineTemplate, out *v1alpha8.OpenStackMachineTemplate, s conversion.Scope) error {
+ out.ObjectMeta = in.ObjectMeta
+ if err := Convert_v1alpha7_OpenStackMachineTemplateSpec_To_v1alpha8_OpenStackMachineTemplateSpec(&in.Spec, &out.Spec, s); err != nil {
+ return err
+ }
+ return nil
+}
+
+// Convert_v1alpha7_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate is an autogenerated conversion function.
+func Convert_v1alpha7_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate(in *OpenStackMachineTemplate, out *v1alpha8.OpenStackMachineTemplate, s conversion.Scope) error {
+ return autoConvert_v1alpha7_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate(in, out, s)
+}
+
+func autoConvert_v1alpha8_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate(in *v1alpha8.OpenStackMachineTemplate, out *OpenStackMachineTemplate, s conversion.Scope) error {
+ out.ObjectMeta = in.ObjectMeta
+ if err := Convert_v1alpha8_OpenStackMachineTemplateSpec_To_v1alpha7_OpenStackMachineTemplateSpec(&in.Spec, &out.Spec, s); err != nil {
+ return err
+ }
+ return nil
+}
+
+// Convert_v1alpha8_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate(in *v1alpha8.OpenStackMachineTemplate, out *OpenStackMachineTemplate, s conversion.Scope) error {
+ return autoConvert_v1alpha8_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate(in, out, s)
+}
+
+func autoConvert_v1alpha7_OpenStackMachineTemplateList_To_v1alpha8_OpenStackMachineTemplateList(in *OpenStackMachineTemplateList, out *v1alpha8.OpenStackMachineTemplateList, s conversion.Scope) error {
+ out.ListMeta = in.ListMeta
+ out.Items = *(*[]v1alpha8.OpenStackMachineTemplate)(unsafe.Pointer(&in.Items))
+ return nil
+}
+
+// Convert_v1alpha7_OpenStackMachineTemplateList_To_v1alpha8_OpenStackMachineTemplateList is an autogenerated conversion function.
+func Convert_v1alpha7_OpenStackMachineTemplateList_To_v1alpha8_OpenStackMachineTemplateList(in *OpenStackMachineTemplateList, out *v1alpha8.OpenStackMachineTemplateList, s conversion.Scope) error {
+ return autoConvert_v1alpha7_OpenStackMachineTemplateList_To_v1alpha8_OpenStackMachineTemplateList(in, out, s)
+}
+
+func autoConvert_v1alpha8_OpenStackMachineTemplateList_To_v1alpha7_OpenStackMachineTemplateList(in *v1alpha8.OpenStackMachineTemplateList, out *OpenStackMachineTemplateList, s conversion.Scope) error {
+ out.ListMeta = in.ListMeta
+ out.Items = *(*[]OpenStackMachineTemplate)(unsafe.Pointer(&in.Items))
+ return nil
+}
+
+// Convert_v1alpha8_OpenStackMachineTemplateList_To_v1alpha7_OpenStackMachineTemplateList is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackMachineTemplateList_To_v1alpha7_OpenStackMachineTemplateList(in *v1alpha8.OpenStackMachineTemplateList, out *OpenStackMachineTemplateList, s conversion.Scope) error {
+ return autoConvert_v1alpha8_OpenStackMachineTemplateList_To_v1alpha7_OpenStackMachineTemplateList(in, out, s)
+}
+
+func autoConvert_v1alpha7_OpenStackMachineTemplateResource_To_v1alpha8_OpenStackMachineTemplateResource(in *OpenStackMachineTemplateResource, out *v1alpha8.OpenStackMachineTemplateResource, s conversion.Scope) error {
+ if err := Convert_v1alpha7_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(&in.Spec, &out.Spec, s); err != nil {
+ return err
+ }
+ return nil
+}
+
+// Convert_v1alpha7_OpenStackMachineTemplateResource_To_v1alpha8_OpenStackMachineTemplateResource is an autogenerated conversion function.
+func Convert_v1alpha7_OpenStackMachineTemplateResource_To_v1alpha8_OpenStackMachineTemplateResource(in *OpenStackMachineTemplateResource, out *v1alpha8.OpenStackMachineTemplateResource, s conversion.Scope) error {
+ return autoConvert_v1alpha7_OpenStackMachineTemplateResource_To_v1alpha8_OpenStackMachineTemplateResource(in, out, s)
+}
+
+func autoConvert_v1alpha8_OpenStackMachineTemplateResource_To_v1alpha7_OpenStackMachineTemplateResource(in *v1alpha8.OpenStackMachineTemplateResource, out *OpenStackMachineTemplateResource, s conversion.Scope) error {
+ if err := Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(&in.Spec, &out.Spec, s); err != nil {
+ return err
+ }
+ return nil
+}
+
+// Convert_v1alpha8_OpenStackMachineTemplateResource_To_v1alpha7_OpenStackMachineTemplateResource is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackMachineTemplateResource_To_v1alpha7_OpenStackMachineTemplateResource(in *v1alpha8.OpenStackMachineTemplateResource, out *OpenStackMachineTemplateResource, s conversion.Scope) error {
+ return autoConvert_v1alpha8_OpenStackMachineTemplateResource_To_v1alpha7_OpenStackMachineTemplateResource(in, out, s)
+}
+
+func autoConvert_v1alpha7_OpenStackMachineTemplateSpec_To_v1alpha8_OpenStackMachineTemplateSpec(in *OpenStackMachineTemplateSpec, out *v1alpha8.OpenStackMachineTemplateSpec, s conversion.Scope) error {
+ if err := Convert_v1alpha7_OpenStackMachineTemplateResource_To_v1alpha8_OpenStackMachineTemplateResource(&in.Template, &out.Template, s); err != nil {
+ return err
+ }
+ return nil
+}
+
+// Convert_v1alpha7_OpenStackMachineTemplateSpec_To_v1alpha8_OpenStackMachineTemplateSpec is an autogenerated conversion function.
+func Convert_v1alpha7_OpenStackMachineTemplateSpec_To_v1alpha8_OpenStackMachineTemplateSpec(in *OpenStackMachineTemplateSpec, out *v1alpha8.OpenStackMachineTemplateSpec, s conversion.Scope) error {
+ return autoConvert_v1alpha7_OpenStackMachineTemplateSpec_To_v1alpha8_OpenStackMachineTemplateSpec(in, out, s)
+}
+
+func autoConvert_v1alpha8_OpenStackMachineTemplateSpec_To_v1alpha7_OpenStackMachineTemplateSpec(in *v1alpha8.OpenStackMachineTemplateSpec, out *OpenStackMachineTemplateSpec, s conversion.Scope) error {
+ if err := Convert_v1alpha8_OpenStackMachineTemplateResource_To_v1alpha7_OpenStackMachineTemplateResource(&in.Template, &out.Template, s); err != nil {
+ return err
+ }
+ return nil
+}
+
+// Convert_v1alpha8_OpenStackMachineTemplateSpec_To_v1alpha7_OpenStackMachineTemplateSpec is an autogenerated conversion function.
+func Convert_v1alpha8_OpenStackMachineTemplateSpec_To_v1alpha7_OpenStackMachineTemplateSpec(in *v1alpha8.OpenStackMachineTemplateSpec, out *OpenStackMachineTemplateSpec, s conversion.Scope) error {
+ return autoConvert_v1alpha8_OpenStackMachineTemplateSpec_To_v1alpha7_OpenStackMachineTemplateSpec(in, out, s)
+}
+
+func autoConvert_v1alpha7_PortOpts_To_v1alpha8_PortOpts(in *PortOpts, out *v1alpha8.PortOpts, s conversion.Scope) error {
+ out.Network = (*v1alpha8.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 = *(*[]v1alpha8.FixedIP)(unsafe.Pointer(&in.FixedIPs))
+ out.SecurityGroupFilters = *(*[]v1alpha8.SecurityGroupFilter)(unsafe.Pointer(&in.SecurityGroupFilters))
+ out.AllowedAddressPairs = *(*[]v1alpha8.AddressPair)(unsafe.Pointer(&in.AllowedAddressPairs))
+ out.Trunk = (*bool)(unsafe.Pointer(in.Trunk))
+ out.HostID = in.HostID
+ out.VNICType = in.VNICType
+ if err := Convert_v1alpha7_BindingProfile_To_v1alpha8_BindingProfile(&in.Profile, &out.Profile, s); err != nil {
+ return err
+ }
+ out.DisablePortSecurity = (*bool)(unsafe.Pointer(in.DisablePortSecurity))
+ out.PropagateUplinkStatus = (*bool)(unsafe.Pointer(in.PropagateUplinkStatus))
+ out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
+ out.ValueSpecs = *(*[]v1alpha8.ValueSpec)(unsafe.Pointer(&in.ValueSpecs))
+ return nil
+}
+
+// Convert_v1alpha7_PortOpts_To_v1alpha8_PortOpts is an autogenerated conversion function.
+func Convert_v1alpha7_PortOpts_To_v1alpha8_PortOpts(in *PortOpts, out *v1alpha8.PortOpts, s conversion.Scope) error {
+ return autoConvert_v1alpha7_PortOpts_To_v1alpha8_PortOpts(in, out, s)
+}
+
+func autoConvert_v1alpha8_PortOpts_To_v1alpha7_PortOpts(in *v1alpha8.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))
+ out.SecurityGroupFilters = *(*[]SecurityGroupFilter)(unsafe.Pointer(&in.SecurityGroupFilters))
+ out.AllowedAddressPairs = *(*[]AddressPair)(unsafe.Pointer(&in.AllowedAddressPairs))
+ out.Trunk = (*bool)(unsafe.Pointer(in.Trunk))
+ out.HostID = in.HostID
+ out.VNICType = in.VNICType
+ if err := Convert_v1alpha8_BindingProfile_To_v1alpha7_BindingProfile(&in.Profile, &out.Profile, s); err != nil {
+ return err
+ }
+ out.DisablePortSecurity = (*bool)(unsafe.Pointer(in.DisablePortSecurity))
+ out.PropagateUplinkStatus = (*bool)(unsafe.Pointer(in.PropagateUplinkStatus))
+ out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
+ out.ValueSpecs = *(*[]ValueSpec)(unsafe.Pointer(&in.ValueSpecs))
+ return nil
+}
+
+// Convert_v1alpha8_PortOpts_To_v1alpha7_PortOpts is an autogenerated conversion function.
+func Convert_v1alpha8_PortOpts_To_v1alpha7_PortOpts(in *v1alpha8.PortOpts, out *PortOpts, s conversion.Scope) error {
+ return autoConvert_v1alpha8_PortOpts_To_v1alpha7_PortOpts(in, out, s)
+}
+
+func autoConvert_v1alpha7_RootVolume_To_v1alpha8_RootVolume(in *RootVolume, out *v1alpha8.RootVolume, s conversion.Scope) error {
+ out.Size = in.Size
+ out.VolumeType = in.VolumeType
+ out.AvailabilityZone = in.AvailabilityZone
+ return nil
+}
+
+// Convert_v1alpha7_RootVolume_To_v1alpha8_RootVolume is an autogenerated conversion function.
+func Convert_v1alpha7_RootVolume_To_v1alpha8_RootVolume(in *RootVolume, out *v1alpha8.RootVolume, s conversion.Scope) error {
+ return autoConvert_v1alpha7_RootVolume_To_v1alpha8_RootVolume(in, out, s)
+}
+
+func autoConvert_v1alpha8_RootVolume_To_v1alpha7_RootVolume(in *v1alpha8.RootVolume, out *RootVolume, s conversion.Scope) error {
+ out.Size = in.Size
+ out.VolumeType = in.VolumeType
+ out.AvailabilityZone = in.AvailabilityZone
+ return nil
+}
+
+// Convert_v1alpha8_RootVolume_To_v1alpha7_RootVolume is an autogenerated conversion function.
+func Convert_v1alpha8_RootVolume_To_v1alpha7_RootVolume(in *v1alpha8.RootVolume, out *RootVolume, s conversion.Scope) error {
+ return autoConvert_v1alpha8_RootVolume_To_v1alpha7_RootVolume(in, out, s)
+}
+
+func autoConvert_v1alpha7_Router_To_v1alpha8_Router(in *Router, out *v1alpha8.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_v1alpha8_Router is an autogenerated conversion function.
+func Convert_v1alpha7_Router_To_v1alpha8_Router(in *Router, out *v1alpha8.Router, s conversion.Scope) error {
+ return autoConvert_v1alpha7_Router_To_v1alpha8_Router(in, out, s)
+}
+
+func autoConvert_v1alpha8_Router_To_v1alpha7_Router(in *v1alpha8.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_v1alpha8_Router_To_v1alpha7_Router is an autogenerated conversion function.
+func Convert_v1alpha8_Router_To_v1alpha7_Router(in *v1alpha8.Router, out *Router, s conversion.Scope) error {
+ return autoConvert_v1alpha8_Router_To_v1alpha7_Router(in, out, s)
+}
+
+func autoConvert_v1alpha7_RouterFilter_To_v1alpha8_RouterFilter(in *RouterFilter, out *v1alpha8.RouterFilter, s conversion.Scope) error {
+ out.ID = in.ID
+ 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
+ return nil
+}
+
+// Convert_v1alpha7_RouterFilter_To_v1alpha8_RouterFilter is an autogenerated conversion function.
+func Convert_v1alpha7_RouterFilter_To_v1alpha8_RouterFilter(in *RouterFilter, out *v1alpha8.RouterFilter, s conversion.Scope) error {
+ return autoConvert_v1alpha7_RouterFilter_To_v1alpha8_RouterFilter(in, out, s)
+}
+
+func autoConvert_v1alpha8_RouterFilter_To_v1alpha7_RouterFilter(in *v1alpha8.RouterFilter, out *RouterFilter, s conversion.Scope) error {
+ out.ID = in.ID
+ 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
+ return nil
+}
+
+// Convert_v1alpha8_RouterFilter_To_v1alpha7_RouterFilter is an autogenerated conversion function.
+func Convert_v1alpha8_RouterFilter_To_v1alpha7_RouterFilter(in *v1alpha8.RouterFilter, out *RouterFilter, s conversion.Scope) error {
+ return autoConvert_v1alpha8_RouterFilter_To_v1alpha7_RouterFilter(in, out, s)
+}
+
+func autoConvert_v1alpha7_SecurityGroup_To_v1alpha8_SecurityGroup(in *SecurityGroup, out *v1alpha8.SecurityGroup, s conversion.Scope) error {
+ out.Name = in.Name
+ out.ID = in.ID
+ out.Rules = *(*[]v1alpha8.SecurityGroupRule)(unsafe.Pointer(&in.Rules))
+ return nil
+}
+
+// Convert_v1alpha7_SecurityGroup_To_v1alpha8_SecurityGroup is an autogenerated conversion function.
+func Convert_v1alpha7_SecurityGroup_To_v1alpha8_SecurityGroup(in *SecurityGroup, out *v1alpha8.SecurityGroup, s conversion.Scope) error {
+ return autoConvert_v1alpha7_SecurityGroup_To_v1alpha8_SecurityGroup(in, out, s)
+}
+
+func autoConvert_v1alpha8_SecurityGroup_To_v1alpha7_SecurityGroup(in *v1alpha8.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_v1alpha8_SecurityGroup_To_v1alpha7_SecurityGroup is an autogenerated conversion function.
+func Convert_v1alpha8_SecurityGroup_To_v1alpha7_SecurityGroup(in *v1alpha8.SecurityGroup, out *SecurityGroup, s conversion.Scope) error {
+ return autoConvert_v1alpha8_SecurityGroup_To_v1alpha7_SecurityGroup(in, out, s)
+}
+
+func autoConvert_v1alpha7_SecurityGroupFilter_To_v1alpha8_SecurityGroupFilter(in *SecurityGroupFilter, out *v1alpha8.SecurityGroupFilter, s conversion.Scope) error {
+ out.ID = in.ID
+ 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
+ return nil
+}
+
+// Convert_v1alpha7_SecurityGroupFilter_To_v1alpha8_SecurityGroupFilter is an autogenerated conversion function.
+func Convert_v1alpha7_SecurityGroupFilter_To_v1alpha8_SecurityGroupFilter(in *SecurityGroupFilter, out *v1alpha8.SecurityGroupFilter, s conversion.Scope) error {
+ return autoConvert_v1alpha7_SecurityGroupFilter_To_v1alpha8_SecurityGroupFilter(in, out, s)
+}
+
+func autoConvert_v1alpha8_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in *v1alpha8.SecurityGroupFilter, out *SecurityGroupFilter, s conversion.Scope) error {
+ out.ID = in.ID
+ 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
+ return nil
+}
+
+// Convert_v1alpha8_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter is an autogenerated conversion function.
+func Convert_v1alpha8_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in *v1alpha8.SecurityGroupFilter, out *SecurityGroupFilter, s conversion.Scope) error {
+ return autoConvert_v1alpha8_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in, out, s)
+}
+
+func autoConvert_v1alpha7_SecurityGroupRule_To_v1alpha8_SecurityGroupRule(in *SecurityGroupRule, out *v1alpha8.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
+ return nil
+}
+
+// Convert_v1alpha7_SecurityGroupRule_To_v1alpha8_SecurityGroupRule is an autogenerated conversion function.
+func Convert_v1alpha7_SecurityGroupRule_To_v1alpha8_SecurityGroupRule(in *SecurityGroupRule, out *v1alpha8.SecurityGroupRule, s conversion.Scope) error {
+ return autoConvert_v1alpha7_SecurityGroupRule_To_v1alpha8_SecurityGroupRule(in, out, s)
+}
+
+func autoConvert_v1alpha8_SecurityGroupRule_To_v1alpha7_SecurityGroupRule(in *v1alpha8.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
+ return nil
+}
+
+// Convert_v1alpha8_SecurityGroupRule_To_v1alpha7_SecurityGroupRule is an autogenerated conversion function.
+func Convert_v1alpha8_SecurityGroupRule_To_v1alpha7_SecurityGroupRule(in *v1alpha8.SecurityGroupRule, out *SecurityGroupRule, s conversion.Scope) error {
+ return autoConvert_v1alpha8_SecurityGroupRule_To_v1alpha7_SecurityGroupRule(in, out, s)
+}
+
+func autoConvert_v1alpha7_Subnet_To_v1alpha8_Subnet(in *Subnet, out *v1alpha8.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_v1alpha8_Subnet is an autogenerated conversion function.
+func Convert_v1alpha7_Subnet_To_v1alpha8_Subnet(in *Subnet, out *v1alpha8.Subnet, s conversion.Scope) error {
+ return autoConvert_v1alpha7_Subnet_To_v1alpha8_Subnet(in, out, s)
+}
+
+func autoConvert_v1alpha8_Subnet_To_v1alpha7_Subnet(in *v1alpha8.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_v1alpha8_Subnet_To_v1alpha7_Subnet is an autogenerated conversion function.
+func Convert_v1alpha8_Subnet_To_v1alpha7_Subnet(in *v1alpha8.Subnet, out *Subnet, s conversion.Scope) error {
+ return autoConvert_v1alpha8_Subnet_To_v1alpha7_Subnet(in, out, s)
+}
+
+func autoConvert_v1alpha7_SubnetFilter_To_v1alpha8_SubnetFilter(in *SubnetFilter, out *v1alpha8.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
+ out.ID = in.ID
+ out.Tags = in.Tags
+ out.TagsAny = in.TagsAny
+ out.NotTags = in.NotTags
+ out.NotTagsAny = in.NotTagsAny
+ return nil
+}
+
+// Convert_v1alpha7_SubnetFilter_To_v1alpha8_SubnetFilter is an autogenerated conversion function.
+func Convert_v1alpha7_SubnetFilter_To_v1alpha8_SubnetFilter(in *SubnetFilter, out *v1alpha8.SubnetFilter, s conversion.Scope) error {
+ return autoConvert_v1alpha7_SubnetFilter_To_v1alpha8_SubnetFilter(in, out, s)
+}
+
+func autoConvert_v1alpha8_SubnetFilter_To_v1alpha7_SubnetFilter(in *v1alpha8.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
+ out.ID = in.ID
+ out.Tags = in.Tags
+ out.TagsAny = in.TagsAny
+ out.NotTags = in.NotTags
+ out.NotTagsAny = in.NotTagsAny
+ return nil
+}
+
+// Convert_v1alpha8_SubnetFilter_To_v1alpha7_SubnetFilter is an autogenerated conversion function.
+func Convert_v1alpha8_SubnetFilter_To_v1alpha7_SubnetFilter(in *v1alpha8.SubnetFilter, out *SubnetFilter, s conversion.Scope) error {
+ return autoConvert_v1alpha8_SubnetFilter_To_v1alpha7_SubnetFilter(in, out, s)
+}
+
+func autoConvert_v1alpha7_ValueSpec_To_v1alpha8_ValueSpec(in *ValueSpec, out *v1alpha8.ValueSpec, s conversion.Scope) error {
+ out.Name = in.Name
+ out.Key = in.Key
+ out.Value = in.Value
+ return nil
+}
+
+// Convert_v1alpha7_ValueSpec_To_v1alpha8_ValueSpec is an autogenerated conversion function.
+func Convert_v1alpha7_ValueSpec_To_v1alpha8_ValueSpec(in *ValueSpec, out *v1alpha8.ValueSpec, s conversion.Scope) error {
+ return autoConvert_v1alpha7_ValueSpec_To_v1alpha8_ValueSpec(in, out, s)
+}
+
+func autoConvert_v1alpha8_ValueSpec_To_v1alpha7_ValueSpec(in *v1alpha8.ValueSpec, out *ValueSpec, s conversion.Scope) error {
+ out.Name = in.Name
+ out.Key = in.Key
+ out.Value = in.Value
+ return nil
+}
+
+// Convert_v1alpha8_ValueSpec_To_v1alpha7_ValueSpec is an autogenerated conversion function.
+func Convert_v1alpha8_ValueSpec_To_v1alpha7_ValueSpec(in *v1alpha8.ValueSpec, out *ValueSpec, s conversion.Scope) error {
+ return autoConvert_v1alpha8_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/api/v1alpha8/conditions_consts.go b/api/v1alpha8/conditions_consts.go
new file mode 100644
index 0000000000..de16adeb08
--- /dev/null
+++ b/api/v1alpha8/conditions_consts.go
@@ -0,0 +1,55 @@
+/*
+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 v1alpha8
+
+import clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
+
+const (
+ // InstanceReadyCondition reports on current status of the OpenStack instance. Ready indicates the instance is in a Running state.
+ InstanceReadyCondition clusterv1.ConditionType = "InstanceReady"
+
+ // WaitingForClusterInfrastructureReason used when machine is waiting for cluster infrastructure to be ready before proceeding.
+ WaitingForClusterInfrastructureReason = "WaitingForClusterInfrastructure"
+ // WaitingForBootstrapDataReason used when machine is waiting for bootstrap data to be ready before proceeding.
+ WaitingForBootstrapDataReason = "WaitingForBootstrapData"
+ // InvalidMachineSpecReason used when the machine spec is invalid.
+ InvalidMachineSpecReason = "InvalidMachineSpec"
+ // InstanceCreateFailedReason used when creating the instance failed.
+ InstanceCreateFailedReason = "InstanceCreateFailed"
+ // InstanceNotFoundReason used when the instance couldn't be retrieved.
+ InstanceNotFoundReason = "InstanceNotFound"
+ // InstanceStateErrorReason used when the instance is in error state.
+ InstanceStateErrorReason = "InstanceStateError"
+ // InstanceDeletedReason used when the instance is in a deleted state.
+ InstanceDeletedReason = "InstanceDeleted"
+ // InstanceNotReadyReason used when the instance is in a pending state.
+ InstanceNotReadyReason = "InstanceNotReady"
+ // InstanceDeleteFailedReason used when deleting the instance failed.
+ InstanceDeleteFailedReason = "InstanceDeleteFailed"
+ // OpenstackErrorReason used when there is an error communicating with OpenStack.
+ OpenStackErrorReason = "OpenStackError"
+)
+
+const (
+ // APIServerIngressReadyCondition reports on the current status of the network ingress (Loadbalancer, Floating IP) for Control Plane machines. Ready indicates that the instance can receive requests.
+ APIServerIngressReadyCondition clusterv1.ConditionType = "APIServerIngressReadyCondition"
+
+ // LoadBalancerMemberErrorReason used when the instance could not be added as a loadbalancer member.
+ LoadBalancerMemberErrorReason = "LoadBalancerMemberError"
+ // FloatingIPErrorReason used when the floating ip could not be created or attached.
+ FloatingIPErrorReason = "FloatingIPError"
+)
diff --git a/api/v1alpha8/conversion.go b/api/v1alpha8/conversion.go
new file mode 100644
index 0000000000..49a817623d
--- /dev/null
+++ b/api/v1alpha8/conversion.go
@@ -0,0 +1,41 @@
+/*
+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 v1alpha8
+
+// 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/v1alpha8/doc.go b/api/v1alpha8/doc.go
new file mode 100644
index 0000000000..6e9bd36d84
--- /dev/null
+++ b/api/v1alpha8/doc.go
@@ -0,0 +1,17 @@
+/*
+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 v1alpha8
diff --git a/api/v1alpha8/filter_convert.go b/api/v1alpha8/filter_convert.go
new file mode 100644
index 0000000000..23e5330588
--- /dev/null
+++ b/api/v1alpha8/filter_convert.go
@@ -0,0 +1,81 @@
+/*
+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 v1alpha8
+
+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/v1alpha8/groupversion_info.go b/api/v1alpha8/groupversion_info.go
new file mode 100644
index 0000000000..28fb759111
--- /dev/null
+++ b/api/v1alpha8/groupversion_info.go
@@ -0,0 +1,36 @@
+/*
+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 v1alpha8 contains API Schema definitions for the infrastructure v1alpha8 API group
+// +kubebuilder:object:generate=true
+// +groupName=infrastructure.cluster.x-k8s.io
+package v1alpha8
+
+import (
+ "k8s.io/apimachinery/pkg/runtime/schema"
+ "sigs.k8s.io/controller-runtime/pkg/scheme"
+)
+
+var (
+ // GroupVersion is group version used to register these objects.
+ GroupVersion = schema.GroupVersion{Group: "infrastructure.cluster.x-k8s.io", Version: "v1alpha8"}
+
+ // SchemeBuilder is used to add go types to the GroupVersionKind scheme.
+ SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}
+
+ // AddToScheme adds the types in this group-version to the given scheme.
+ AddToScheme = SchemeBuilder.AddToScheme
+)
diff --git a/api/v1alpha8/identity_types.go b/api/v1alpha8/identity_types.go
new file mode 100644
index 0000000000..b77700c2df
--- /dev/null
+++ b/api/v1alpha8/identity_types.go
@@ -0,0 +1,33 @@
+/*
+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 v1alpha8
+
+const defaultIdentityRefKind = "Secret"
+
+// 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 string `json:"name"`
+}
diff --git a/api/v1alpha8/openstackcluster_types.go b/api/v1alpha8/openstackcluster_types.go
new file mode 100644
index 0000000000..902e9c7c03
--- /dev/null
+++ b/api/v1alpha8/openstackcluster_types.go
@@ -0,0 +1,263 @@
+/*
+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 v1alpha8
+
+import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
+ capierrors "sigs.k8s.io/cluster-api/errors"
+)
+
+const (
+ // ClusterFinalizer allows ReconcileOpenStackCluster to clean up OpenStack resources associated with OpenStackCluster before
+ // removing it from the apiserver.
+ ClusterFinalizer = "openstackcluster.infrastructure.cluster.x-k8s.io"
+)
+
+// OpenStackClusterSpec defines the desired state of OpenStackCluster.
+type OpenStackClusterSpec struct {
+ // The name of the cloud to use from the clouds secret
+ // +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"`
+
+ // If NodeCIDR is set this option can be used to detect an existing router.
+ // 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"`
+
+ // If NodeCIDR cannot be set this can be used to detect an existing subnet.
+ Subnet SubnetFilter `json:"subnet,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.
+ // To use this field, the Openstack installation requires the net-mtu neutron API extension.
+ // +optional
+ NetworkMTU 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.
+ ExternalRouterIPs []ExternalRouterIPParam `json:"externalRouterIPs,omitempty"`
+ // ExternalNetworkID is the ID of an external OpenStack Network. This is necessary
+ // to get public internet to the VMs.
+ // +optional
+ ExternalNetworkID string `json:"externalNetworkId,omitempty"`
+
+ // APIServerLoadBalancer configures the optional LoadBalancer for the APIServer.
+ // It must be activated by setting `enabled: true`.
+ // +optional
+ 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
+ // 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.
+ // +optional
+ DisableAPIServerFloatingIP bool `json:"disableAPIServerFloatingIP"`
+
+ // 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"`
+
+ // 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.
+ APIServerFixedIP string `json:"apiServerFixedIP,omitempty"`
+
+ // APIServerPort is the port on which the listener on the APIServer
+ // will be created
+ APIServerPort 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.
+ // +optional
+ AllowAllInClusterTraffic bool `json:"allowAllInClusterTraffic"`
+
+ // DisablePortSecurity disables the port security of the network created for the
+ // Kubernetes cluster, which also disables SecurityGroups
+ DisablePortSecurity bool `json:"disablePortSecurity,omitempty"`
+
+ // Tags for all resources in cluster
+ // +listType=set
+ Tags []string `json:"tags,omitempty"`
+
+ // ControlPlaneEndpoint represents the endpoint used to communicate with the control plane.
+ // +optional
+ ControlPlaneEndpoint clusterv1.APIEndpoint `json:"controlPlaneEndpoint"`
+
+ // ControlPlaneAvailabilityZones is the az to deploy control plane to
+ // +listType=set
+ 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"`
+
+ // 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.
+ //+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"`
+}
+
+// OpenStackClusterStatus defines the observed state of OpenStackCluster.
+type OpenStackClusterStatus struct {
+ Ready bool `json:"ready"`
+
+ // Network contains information about the created OpenStack Network.
+ Network *NetworkStatusWithSubnets `json:"network,omitempty"`
+
+ // externalNetwork contains information about the external network used for default ingress and egress traffic.
+ ExternalNetwork *NetworkStatus `json:"externalNetwork,omitempty"`
+
+ // Router describes the default cluster router
+ Router *Router `json:"router,omitempty"`
+
+ // APIServerLoadBalancer describes the api server load balancer if one exists
+ 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"`
+
+ // WorkerSecurityGroup contains all the information about the OpenStack Security
+ // Group that needs to be applied to worker nodes.
+ WorkerSecurityGroup *SecurityGroup `json:"workerSecurityGroup,omitempty"`
+
+ BastionSecurityGroup *SecurityGroup `json:"bastionSecurityGroup,omitempty"`
+
+ Bastion *BastionStatus `json:"bastion,omitempty"`
+
+ // 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.
+ // +optional
+ FailureReason *capierrors.ClusterStatusError `json:"failureReason,omitempty"`
+
+ // 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.
+ // +optional
+ FailureMessage *string `json:"failureMessage,omitempty"`
+}
+
+// +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"
+// +kubebuilder:printcolumn:name="Network",type="string",JSONPath=".status.network.id",description="Network the cluster is using"
+// +kubebuilder:printcolumn:name="Endpoint",type="string",JSONPath=".spec.controlPlaneEndpoint.host",description="API Endpoint",priority=1
+// +kubebuilder:printcolumn:name="Bastion IP",type="string",JSONPath=".status.bastion.floatingIP",description="Bastion address for breakglass access"
+// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Time duration since creation of OpenStackCluster"
+
+// OpenStackCluster is the Schema for the openstackclusters API.
+type OpenStackCluster struct {
+ metav1.TypeMeta `json:",inline"`
+ metav1.ObjectMeta `json:"metadata,omitempty"`
+
+ Spec OpenStackClusterSpec `json:"spec,omitempty"`
+ Status OpenStackClusterStatus `json:"status,omitempty"`
+}
+
+// +kubebuilder:object:root=true
+
+// OpenStackClusterList contains a list of OpenStackCluster.
+type OpenStackClusterList struct {
+ metav1.TypeMeta `json:",inline"`
+ metav1.ListMeta `json:"metadata,omitempty"`
+ Items []OpenStackCluster `json:"items"`
+}
+
+func init() {
+ SchemeBuilder.Register(&OpenStackCluster{}, &OpenStackClusterList{})
+}
diff --git a/api/v1alpha7/openstackcluster_webhook.go b/api/v1alpha8/openstackcluster_webhook.go
similarity index 95%
rename from api/v1alpha7/openstackcluster_webhook.go
rename to api/v1alpha8/openstackcluster_webhook.go
index 706d10a8c6..6821b6c1df 100644
--- a/api/v1alpha7/openstackcluster_webhook.go
+++ b/api/v1alpha8/openstackcluster_webhook.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package v1alpha7
+package v1alpha8
import (
"fmt"
@@ -40,8 +40,8 @@ func (r *OpenStackCluster) SetupWebhookWithManager(mgr manager.Manager) error {
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
+// +kubebuilder:webhook:verbs=create;update,path=/validate-infrastructure-cluster-x-k8s-io-v1alpha8-openstackcluster,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=openstackclusters,versions=v1alpha8,name=validation.openstackcluster.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1
+// +kubebuilder:webhook:verbs=create;update,path=/mutate-infrastructure-cluster-x-k8s-io-v1alpha8-openstackcluster,mutating=true,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=openstackclusters,versions=v1alpha8,name=default.openstackcluster.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1
var (
_ webhook.Defaulter = &OpenStackCluster{}
diff --git a/api/v1alpha7/openstackcluster_webhook_test.go b/api/v1alpha8/openstackcluster_webhook_test.go
similarity index 99%
rename from api/v1alpha7/openstackcluster_webhook_test.go
rename to api/v1alpha8/openstackcluster_webhook_test.go
index 24e1407f2c..256988c81a 100644
--- a/api/v1alpha7/openstackcluster_webhook_test.go
+++ b/api/v1alpha8/openstackcluster_webhook_test.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package v1alpha7
+package v1alpha8
import (
"testing"
diff --git a/api/v1alpha7/openstackclusterlist_webhook.go b/api/v1alpha8/openstackclusterlist_webhook.go
similarity index 98%
rename from api/v1alpha7/openstackclusterlist_webhook.go
rename to api/v1alpha8/openstackclusterlist_webhook.go
index f7749b7ade..e6c3d9d47a 100644
--- a/api/v1alpha7/openstackclusterlist_webhook.go
+++ b/api/v1alpha8/openstackclusterlist_webhook.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package v1alpha7
+package v1alpha8
import (
"sigs.k8s.io/controller-runtime/pkg/builder"
diff --git a/api/v1alpha8/openstackclustertemplate_types.go b/api/v1alpha8/openstackclustertemplate_types.go
new file mode 100644
index 0000000000..60fc00956a
--- /dev/null
+++ b/api/v1alpha8/openstackclustertemplate_types.go
@@ -0,0 +1,56 @@
+/*
+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 v1alpha8
+
+import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+// OpenStackClusterTemplateResource describes the data needed to create a OpenStackCluster from a template.
+type OpenStackClusterTemplateResource struct {
+ Spec OpenStackClusterSpec `json:"spec"`
+}
+
+// OpenStackClusterTemplateSpec defines the desired state of OpenStackClusterTemplate.
+type OpenStackClusterTemplateSpec struct {
+ Template OpenStackClusterTemplateResource `json:"template"`
+}
+
+//+kubebuilder:object:root=true
+// +kubebuilder:storageversion
+//+kubebuilder:resource:path=openstackclustertemplates,scope=Namespaced,categories=cluster-api,shortName=osct
+
+// OpenStackClusterTemplate is the Schema for the openstackclustertemplates API.
+type OpenStackClusterTemplate struct {
+ metav1.TypeMeta `json:",inline"`
+ metav1.ObjectMeta `json:"metadata,omitempty"`
+
+ Spec OpenStackClusterTemplateSpec `json:"spec,omitempty"`
+}
+
+//+kubebuilder:object:root=true
+
+// OpenStackClusterTemplateList contains a list of OpenStackClusterTemplate.
+type OpenStackClusterTemplateList struct {
+ metav1.TypeMeta `json:",inline"`
+ metav1.ListMeta `json:"metadata,omitempty"`
+ Items []OpenStackClusterTemplate `json:"items"`
+}
+
+func init() {
+ SchemeBuilder.Register(&OpenStackClusterTemplate{}, &OpenStackClusterTemplateList{})
+}
diff --git a/api/v1alpha7/openstackclustertemplate_webhook.go b/api/v1alpha8/openstackclustertemplate_webhook.go
similarity index 92%
rename from api/v1alpha7/openstackclustertemplate_webhook.go
rename to api/v1alpha8/openstackclustertemplate_webhook.go
index 337928a3f1..5cfbc6b92d 100644
--- a/api/v1alpha7/openstackclustertemplate_webhook.go
+++ b/api/v1alpha8/openstackclustertemplate_webhook.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package v1alpha7
+package v1alpha8
import (
"fmt"
@@ -36,8 +36,8 @@ func (r *OpenStackClusterTemplate) SetupWebhookWithManager(mgr ctrl.Manager) err
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
+// +kubebuilder:webhook:verbs=create;update,path=/mutate-infrastructure-cluster-x-k8s-io-v1alpha8-openstackclustertemplate,mutating=true,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=openstackclustertemplates,versions=v1alpha8,name=default.openstackclustertemplate.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1
+// +kubebuilder:webhook:verbs=create;update,path=/validate-infrastructure-cluster-x-k8s-io-v1alpha8-openstackclustertemplate,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=openstackclustertemplates,versions=v1alpha8,name=validation.openstackclustertemplate.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1
var (
_ webhook.Defaulter = &OpenStackClusterTemplate{}
diff --git a/api/v1alpha8/openstackmachine_types.go b/api/v1alpha8/openstackmachine_types.go
new file mode 100644
index 0000000000..8a7c97d406
--- /dev/null
+++ b/api/v1alpha8/openstackmachine_types.go
@@ -0,0 +1,185 @@
+/*
+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 v1alpha8
+
+import (
+ corev1 "k8s.io/api/core/v1"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/utils/pointer"
+ clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
+ "sigs.k8s.io/cluster-api/errors"
+)
+
+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"
+)
+
+// OpenStackMachineSpec defines the desired state of OpenStackMachine.
+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 ssh key to inject in the instance
+ SSHKeyName string `json:"sshKeyName,omitempty"`
+
+ // 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.
+ 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"`
+
+ // Whether the server instance is created on a trunk port or not.
+ Trunk bool `json:"trunk,omitempty"`
+
+ // Machine tags
+ // 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"`
+
+ // Config Drive support
+ ConfigDrive *bool `json:"configDrive,omitempty"`
+
+ // The volume metadata to boot from
+ RootVolume *RootVolume `json:"rootVolume,omitempty"`
+
+ // AdditionalBlockDevices is a list of specifications for additional block devices to attach to the server instance
+ // +listType=map
+ // +listMapKey=name
+ // +optional
+ AdditionalBlockDevices []AdditionalBlockDevice `json:"additionalBlockDevices,omitempty"`
+
+ // 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
+ // +optional
+ IdentityRef *OpenStackIdentityReference `json:"identityRef,omitempty"`
+}
+
+// OpenStackMachineStatus defines the observed state of OpenStackMachine.
+type OpenStackMachineStatus struct {
+ // Ready is true when the provider resource is ready.
+ // +optional
+ Ready bool `json:"ready"`
+
+ // Addresses contains the OpenStack instance associated addresses.
+ Addresses []corev1.NodeAddress `json:"addresses,omitempty"`
+
+ // InstanceState is the state of the OpenStack instance for this machine.
+ // +optional
+ InstanceState *InstanceState `json:"instanceState,omitempty"`
+
+ FailureReason *errors.MachineStatusError `json:"failureReason,omitempty"`
+
+ // 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.
+ // +optional
+ FailureMessage *string `json:"failureMessage,omitempty"`
+
+ Conditions clusterv1.Conditions `json:"conditions,omitempty"`
+}
+
+// +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"
+// +kubebuilder:printcolumn:name="InstanceState",type="string",JSONPath=".status.instanceState",description="OpenStack instance state"
+// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.ready",description="Machine ready status"
+// +kubebuilder:printcolumn:name="ProviderID",type="string",JSONPath=".spec.providerID",description="OpenStack instance ID"
+// +kubebuilder:printcolumn:name="Machine",type="string",JSONPath=".metadata.ownerReferences[?(@.kind==\"Machine\")].name",description="Machine object which owns with this OpenStackMachine"
+// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Time duration since creation of OpenStackMachine"
+
+// OpenStackMachine is the Schema for the openstackmachines API.
+type OpenStackMachine struct {
+ metav1.TypeMeta `json:",inline"`
+ metav1.ObjectMeta `json:"metadata,omitempty"`
+
+ Spec OpenStackMachineSpec `json:"spec,omitempty"`
+ Status OpenStackMachineStatus `json:"status,omitempty"`
+}
+
+// +kubebuilder:object:root=true
+
+// OpenStackMachineList contains a list of OpenStackMachine.
+type OpenStackMachineList struct {
+ metav1.TypeMeta `json:",inline"`
+ metav1.ListMeta `json:"metadata,omitempty"`
+ Items []OpenStackMachine `json:"items"`
+}
+
+// GetConditions returns the observations of the operational state of the OpenStackMachine resource.
+func (r *OpenStackMachine) GetConditions() clusterv1.Conditions {
+ return r.Status.Conditions
+}
+
+// SetConditions sets the underlying service state of the OpenStackMachine to the predescribed clusterv1.Conditions.
+func (r *OpenStackMachine) SetConditions(conditions clusterv1.Conditions) {
+ r.Status.Conditions = 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())
+}
+
+func init() {
+ SchemeBuilder.Register(&OpenStackMachine{}, &OpenStackMachineList{})
+}
diff --git a/api/v1alpha7/openstackmachine_webhook.go b/api/v1alpha8/openstackmachine_webhook.go
similarity index 94%
rename from api/v1alpha7/openstackmachine_webhook.go
rename to api/v1alpha8/openstackmachine_webhook.go
index 6470589a76..b5ddbaf0e3 100644
--- a/api/v1alpha7/openstackmachine_webhook.go
+++ b/api/v1alpha8/openstackmachine_webhook.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package v1alpha7
+package v1alpha8
import (
"fmt"
@@ -39,8 +39,8 @@ func (r *OpenStackMachine) SetupWebhookWithManager(mgr manager.Manager) error {
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
+// +kubebuilder:webhook:verbs=create;update,path=/validate-infrastructure-cluster-x-k8s-io-v1alpha8-openstackmachine,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=openstackmachines,versions=v1alpha8,name=validation.openstackmachine.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1
+// +kubebuilder:webhook:verbs=create;update,path=/mutate-infrastructure-cluster-x-k8s-io-v1alpha8-openstackmachine,mutating=true,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=openstackmachines,versions=v1alpha8,name=default.openstackmachine.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1
var (
_ webhook.Defaulter = &OpenStackMachine{}
diff --git a/api/v1alpha7/openstackmachinelist_webhook.go b/api/v1alpha8/openstackmachinelist_webhook.go
similarity index 98%
rename from api/v1alpha7/openstackmachinelist_webhook.go
rename to api/v1alpha8/openstackmachinelist_webhook.go
index 0122e1b52c..e858ba072d 100644
--- a/api/v1alpha7/openstackmachinelist_webhook.go
+++ b/api/v1alpha8/openstackmachinelist_webhook.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package v1alpha7
+package v1alpha8
import (
"sigs.k8s.io/controller-runtime/pkg/builder"
diff --git a/api/v1alpha8/openstackmachinetemplate_types.go b/api/v1alpha8/openstackmachinetemplate_types.go
new file mode 100644
index 0000000000..f66cc2b1f1
--- /dev/null
+++ b/api/v1alpha8/openstackmachinetemplate_types.go
@@ -0,0 +1,51 @@
+/*
+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 v1alpha8
+
+import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+// OpenStackMachineTemplateSpec defines the desired state of OpenStackMachineTemplate.
+type OpenStackMachineTemplateSpec struct {
+ Template OpenStackMachineTemplateResource `json:"template"`
+}
+
+// +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.
+type OpenStackMachineTemplate struct {
+ metav1.TypeMeta `json:",inline"`
+ metav1.ObjectMeta `json:"metadata,omitempty"`
+
+ Spec OpenStackMachineTemplateSpec `json:"spec,omitempty"`
+}
+
+// +kubebuilder:object:root=true
+
+// OpenStackMachineTemplateList contains a list of OpenStackMachineTemplate.
+type OpenStackMachineTemplateList struct {
+ metav1.TypeMeta `json:",inline"`
+ metav1.ListMeta `json:"metadata,omitempty"`
+ Items []OpenStackMachineTemplate `json:"items"`
+}
+
+func init() {
+ SchemeBuilder.Register(&OpenStackMachineTemplate{}, &OpenStackMachineTemplateList{})
+}
diff --git a/api/v1alpha7/openstackmachinetemplate_webhook.go b/api/v1alpha8/openstackmachinetemplate_webhook.go
similarity index 96%
rename from api/v1alpha7/openstackmachinetemplate_webhook.go
rename to api/v1alpha8/openstackmachinetemplate_webhook.go
index b74d056ba2..cbb91ebb17 100644
--- a/api/v1alpha7/openstackmachinetemplate_webhook.go
+++ b/api/v1alpha8/openstackmachinetemplate_webhook.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package v1alpha7
+package v1alpha8
import (
"context"
@@ -44,7 +44,7 @@ func (r *OpenStackMachineTemplateWebhook) SetupWebhookWithManager(mgr manager.Ma
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
+// +kubebuilder:webhook:verbs=create;update,path=/validate-infrastructure-cluster-x-k8s-io-v1alpha8-openstackmachinetemplate,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=openstackmachinetemplates,versions=v1alpha8,name=validation.openstackmachinetemplate.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1
var _ webhook.CustomValidator = &OpenStackMachineTemplateWebhook{}
diff --git a/api/v1alpha7/openstackmachinetemplate_webhook_test.go b/api/v1alpha8/openstackmachinetemplate_webhook_test.go
similarity index 99%
rename from api/v1alpha7/openstackmachinetemplate_webhook_test.go
rename to api/v1alpha8/openstackmachinetemplate_webhook_test.go
index d9a53adc17..6728f9d5fe 100644
--- a/api/v1alpha7/openstackmachinetemplate_webhook_test.go
+++ b/api/v1alpha8/openstackmachinetemplate_webhook_test.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package v1alpha7
+package v1alpha8
import (
"context"
diff --git a/api/v1alpha7/openstackmachinetemplatelist_webhook.go b/api/v1alpha8/openstackmachinetemplatelist_webhook.go
similarity index 98%
rename from api/v1alpha7/openstackmachinetemplatelist_webhook.go
rename to api/v1alpha8/openstackmachinetemplatelist_webhook.go
index c1ff00c3dd..01d976b51e 100644
--- a/api/v1alpha7/openstackmachinetemplatelist_webhook.go
+++ b/api/v1alpha8/openstackmachinetemplatelist_webhook.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package v1alpha7
+package v1alpha8
import (
"sigs.k8s.io/controller-runtime/pkg/builder"
diff --git a/api/v1alpha8/types.go b/api/v1alpha8/types.go
new file mode 100644
index 0000000000..a6d949cb0a
--- /dev/null
+++ b/api/v1alpha8/types.go
@@ -0,0 +1,372 @@
+/*
+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 v1alpha8
+
+// 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"`
+}
+
+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 SubnetFilter `json:"subnet"`
+}
+
+type SecurityGroupFilter struct {
+ ID string `json:"id,omitempty"`
+ Name string `json:"name,omitempty"`
+ Description string `json:"description,omitempty"`
+ ProjectID string `json:"projectId,omitempty"`
+ Tags string `json:"tags,omitempty"`
+ TagsAny string `json:"tagsAny,omitempty"`
+ NotTags string `json:"notTags,omitempty"`
+ NotTagsAny string `json:"notTagsAny,omitempty"`
+}
+
+type NetworkFilter struct {
+ Name string `json:"name,omitempty"`
+ Description string `json:"description,omitempty"`
+ ProjectID string `json:"projectId,omitempty"`
+ ID string `json:"id,omitempty"`
+ Tags string `json:"tags,omitempty"`
+ TagsAny string `json:"tagsAny,omitempty"`
+ NotTags string `json:"notTags,omitempty"`
+ NotTagsAny string `json:"notTagsAny,omitempty"`
+}
+
+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:"gateway_ip,omitempty"`
+ CIDR string `json:"cidr,omitempty"`
+ IPv6AddressMode string `json:"ipv6AddressMode,omitempty"`
+ IPv6RAMode string `json:"ipv6RaMode,omitempty"`
+ ID string `json:"id,omitempty"`
+ Tags string `json:"tags,omitempty"`
+ TagsAny string `json:"tagsAny,omitempty"`
+ NotTags string `json:"notTags,omitempty"`
+ NotTagsAny string `json:"notTagsAny,omitempty"`
+}
+
+type RouterFilter struct {
+ ID string `json:"id,omitempty"`
+ Name string `json:"name,omitempty"`
+ Description string `json:"description,omitempty"`
+ ProjectID string `json:"projectId,omitempty"`
+ Tags string `json:"tags,omitempty"`
+ TagsAny string `json:"tagsAny,omitempty"`
+ NotTags string `json:"notTags,omitempty"`
+ NotTagsAny string `json:"notTagsAny,omitempty"`
+}
+
+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.
+ Network *NetworkFilter `json:"network,omitempty"`
+ // Used to make the name of the port unique. If unspecified, instead the 0-based index of the port in the list is used.
+ NameSuffix string `json:"nameSuffix,omitempty"`
+ Description string `json:"description,omitempty"`
+ AdminStateUp *bool `json:"adminStateUp,omitempty"`
+ MACAddress string `json:"macAddress,omitempty"`
+ // Specify pairs of subnet and/or IP address. These should be subnets of the network with the given NetworkID.
+ FixedIPs []FixedIP `json:"fixedIPs,omitempty"`
+ // The names, uuids, filters or any combination these of the security groups to assign to the instance
+ SecurityGroupFilters []SecurityGroupFilter `json:"securityGroupFilters,omitempty"`
+ AllowedAddressPairs []AddressPair `json:"allowedAddressPairs,omitempty"`
+ // Enables and disables trunk at port level. If not provided, openStackMachine.Spec.Trunk is inherited.
+ Trunk *bool `json:"trunk,omitempty"`
+
+ // The ID of the host where the port is allocated
+ HostID string `json:"hostId,omitempty"`
+
+ // The virtual network interface card (vNIC) type that is bound to the neutron port.
+ VNICType 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
+ 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.
+ DisablePortSecurity *bool `json:"disablePortSecurity,omitempty"`
+
+ // PropageteUplinkStatus enables or disables the propagate uplink status on the port.
+ PropagateUplinkStatus *bool `json:"propagateUplinkStatus,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
+ Tags []string `json:"tags,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"`
+}
+
+type BindingProfile struct {
+ // OVSHWOffload enables or disables the OVS hardware offload feature.
+ OVSHWOffload bool `json:"ovsHWOffload,omitempty"`
+
+ // TrustedVF enables or disables the “trusted mode” for the VF.
+ 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.
+ Subnet *SubnetFilter `json:"subnet"`
+ IPAddress string `json:"ipAddress,omitempty"`
+}
+
+type AddressPair struct {
+ IPAddress string `json:"ipAddress,omitempty"`
+ MACAddress 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"`
+}
+
+type RootVolume struct {
+ Size int `json:"diskSize,omitempty"`
+ VolumeType string `json:"volumeType,omitempty"`
+ AvailabilityZone string `json:"availabilityZone,omitempty"`
+}
+
+// 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 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.
+ // +optional
+ AvailabilityZone string `json:"availabilityZone,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 string `json:"name"`
+
+ // SizeGiB is the size of the block device in gibibytes (GiB).
+ SizeGiB int `json:"sizeGiB"`
+
+ // Storage specifies the storage type of the block device and
+ // additional storage options.
+ Storage BlockDeviceStorage `json:"storage"`
+}
+
+// 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"`
+}
+
+// SecurityGroup represents the basic information of the associated
+// OpenStack Neutron Security Group.
+type SecurityGroup struct {
+ Name string `json:"name"`
+ ID string `json:"id"`
+ Rules []SecurityGroupRule `json:"rules"`
+}
+
+// SecurityGroupRule represent the basic information of the associated OpenStack
+// Security Group Role.
+type SecurityGroupRule struct {
+ Description string `json:"description"`
+ ID string `json:"name"`
+ Direction string `json:"direction"`
+ EtherType string `json:"etherType"`
+ SecurityGroupID string `json:"securityGroupID"`
+ PortRangeMin int `json:"portRangeMin"`
+ PortRangeMax int `json:"portRangeMax"`
+ Protocol string `json:"protocol"`
+ RemoteGroupID string `json:"remoteGroupID"`
+ RemoteIPPrefix string `json:"remoteIPPrefix"`
+}
+
+// Equal checks if two SecurityGroupRules are the same.
+func (r SecurityGroupRule) Equal(x SecurityGroupRule) bool {
+ return (r.Direction == x.Direction &&
+ r.Description == x.Description &&
+ r.EtherType == x.EtherType &&
+ r.PortRangeMin == x.PortRangeMin &&
+ r.PortRangeMax == x.PortRangeMax &&
+ r.Protocol == x.Protocol &&
+ r.RemoteGroupID == x.RemoteGroupID &&
+ r.RemoteIPPrefix == x.RemoteIPPrefix)
+}
+
+// InstanceState describes the state of an OpenStack instance.
+type InstanceState string
+
+var (
+ // InstanceStateBuilding is the string representing an instance in a building state.
+ InstanceStateBuilding = InstanceState("BUILDING")
+
+ // 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")
+)
+
+// Bastion represents basic information about the bastion node.
+type Bastion struct {
+ //+optional
+ Enabled bool `json:"enabled"`
+
+ // Instance for the bastion itself
+ Instance OpenStackMachineSpec `json:"instance,omitempty"`
+
+ //+optional
+ AvailabilityZone string `json:"availabilityZone,omitempty"`
+}
+
+type APIServerLoadBalancer struct {
+ // Enabled defines whether a load balancer should be created.
+ Enabled bool `json:"enabled,omitempty"`
+ // AdditionalPorts adds additional tcp ports to the load balancer.
+ AdditionalPorts []int `json:"additionalPorts,omitempty"`
+ // AllowedCIDRs restrict access to all API-Server listeners to the given address CIDRs.
+ AllowedCIDRs []string `json:"allowedCidrs,omitempty"`
+ // Octavia Provider Used to create load balancer
+ Provider string `json:"provider,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/api/v1alpha7/webhooks.go b/api/v1alpha8/webhooks.go
similarity index 98%
rename from api/v1alpha7/webhooks.go
rename to api/v1alpha8/webhooks.go
index d58fdbb155..87a4a374a0 100644
--- a/api/v1alpha7/webhooks.go
+++ b/api/v1alpha8/webhooks.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package v1alpha7
+package v1alpha8
import (
apierrors "k8s.io/apimachinery/pkg/api/errors"
diff --git a/api/v1alpha8/zz_generated.deepcopy.go b/api/v1alpha8/zz_generated.deepcopy.go
new file mode 100644
index 0000000000..3ded212691
--- /dev/null
+++ b/api/v1alpha8/zz_generated.deepcopy.go
@@ -0,0 +1,1059 @@
+//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 v1alpha8
+
+import (
+ "k8s.io/api/core/v1"
+ "k8s.io/apimachinery/pkg/runtime"
+ "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.AdditionalPorts != nil {
+ in, out := &in.AdditionalPorts, &out.AdditionalPorts
+ *out = make([]int, len(*in))
+ copy(*out, *in)
+ }
+ if in.AllowedCIDRs != nil {
+ in, out := &in.AllowedCIDRs, &out.AllowedCIDRs
+ *out = make([]string, len(*in))
+ copy(*out, *in)
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIServerLoadBalancer.
+func (in *APIServerLoadBalancer) DeepCopy() *APIServerLoadBalancer {
+ if in == nil {
+ return nil
+ }
+ out := new(APIServerLoadBalancer)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *AdditionalBlockDevice) DeepCopyInto(out *AdditionalBlockDevice) {
+ *out = *in
+ in.Storage.DeepCopyInto(&out.Storage)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AdditionalBlockDevice.
+func (in *AdditionalBlockDevice) DeepCopy() *AdditionalBlockDevice {
+ if in == nil {
+ return nil
+ }
+ out := new(AdditionalBlockDevice)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// 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
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddressPair.
+func (in *AddressPair) DeepCopy() *AddressPair {
+ if in == nil {
+ return nil
+ }
+ out := new(AddressPair)
+ 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)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Bastion.
+func (in *Bastion) DeepCopy() *Bastion {
+ if in == nil {
+ return nil
+ }
+ out := new(Bastion)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// 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
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BastionStatus.
+func (in *BastionStatus) DeepCopy() *BastionStatus {
+ if in == nil {
+ return nil
+ }
+ out := new(BastionStatus)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// 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
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BindingProfile.
+func (in *BindingProfile) DeepCopy() *BindingProfile {
+ if in == nil {
+ return nil
+ }
+ out := new(BindingProfile)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *BlockDeviceStorage) DeepCopyInto(out *BlockDeviceStorage) {
+ *out = *in
+ if in.Volume != nil {
+ in, out := &in.Volume, &out.Volume
+ *out = new(BlockDeviceVolume)
+ **out = **in
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BlockDeviceStorage.
+func (in *BlockDeviceStorage) DeepCopy() *BlockDeviceStorage {
+ if in == nil {
+ return nil
+ }
+ out := new(BlockDeviceStorage)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// 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
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BlockDeviceVolume.
+func (in *BlockDeviceVolume) DeepCopy() *BlockDeviceVolume {
+ if in == nil {
+ return nil
+ }
+ out := new(BlockDeviceVolume)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// 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
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalRouterIPParam.
+func (in *ExternalRouterIPParam) DeepCopy() *ExternalRouterIPParam {
+ if in == nil {
+ return nil
+ }
+ out := new(ExternalRouterIPParam)
+ 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 = **in
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FixedIP.
+func (in *FixedIP) DeepCopy() *FixedIP {
+ if in == nil {
+ return nil
+ }
+ out := new(FixedIP)
+ 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
+ if in.AllowedCIDRs != nil {
+ in, out := &in.AllowedCIDRs, &out.AllowedCIDRs
+ *out = make([]string, len(*in))
+ copy(*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 LoadBalancer.
+func (in *LoadBalancer) DeepCopy() *LoadBalancer {
+ if in == nil {
+ return nil
+ }
+ out := new(LoadBalancer)
+ 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
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkFilter.
+func (in *NetworkFilter) DeepCopy() *NetworkFilter {
+ if in == nil {
+ return nil
+ }
+ out := new(NetworkFilter)
+ 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
+ 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 NetworkStatus.
+func (in *NetworkStatus) DeepCopy() *NetworkStatus {
+ if in == nil {
+ return nil
+ }
+ out := new(NetworkStatus)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *NetworkStatusWithSubnets) DeepCopyInto(out *NetworkStatusWithSubnets) {
+ *out = *in
+ in.NetworkStatus.DeepCopyInto(&out.NetworkStatus)
+ if in.Subnets != nil {
+ in, out := &in.Subnets, &out.Subnets
+ *out = make([]Subnet, len(*in))
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkStatusWithSubnets.
+func (in *NetworkStatusWithSubnets) DeepCopy() *NetworkStatusWithSubnets {
+ if in == nil {
+ return nil
+ }
+ out := new(NetworkStatusWithSubnets)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *OpenStackCluster) DeepCopyInto(out *OpenStackCluster) {
+ *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 OpenStackCluster.
+func (in *OpenStackCluster) DeepCopy() *OpenStackCluster {
+ if in == nil {
+ return nil
+ }
+ out := new(OpenStackCluster)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *OpenStackCluster) 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 *OpenStackClusterList) DeepCopyInto(out *OpenStackClusterList) {
+ *out = *in
+ out.TypeMeta = in.TypeMeta
+ in.ListMeta.DeepCopyInto(&out.ListMeta)
+ if in.Items != nil {
+ in, out := &in.Items, &out.Items
+ *out = make([]OpenStackCluster, len(*in))
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenStackClusterList.
+func (in *OpenStackClusterList) DeepCopy() *OpenStackClusterList {
+ if in == nil {
+ return nil
+ }
+ out := new(OpenStackClusterList)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *OpenStackClusterList) 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 *OpenStackClusterSpec) DeepCopyInto(out *OpenStackClusterSpec) {
+ *out = *in
+ if in.Router != nil {
+ in, out := &in.Router, &out.Router
+ *out = new(RouterFilter)
+ **out = **in
+ }
+ 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.ExternalRouterIPs != nil {
+ in, out := &in.ExternalRouterIPs, &out.ExternalRouterIPs
+ *out = make([]ExternalRouterIPParam, len(*in))
+ copy(*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.ControlPlaneAvailabilityZones != nil {
+ in, out := &in.ControlPlaneAvailabilityZones, &out.ControlPlaneAvailabilityZones
+ *out = make([]string, len(*in))
+ copy(*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
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenStackClusterSpec.
+func (in *OpenStackClusterSpec) DeepCopy() *OpenStackClusterSpec {
+ if in == nil {
+ return nil
+ }
+ out := new(OpenStackClusterSpec)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *OpenStackClusterStatus) DeepCopyInto(out *OpenStackClusterStatus) {
+ *out = *in
+ if in.Network != nil {
+ in, out := &in.Network, &out.Network
+ *out = new(NetworkStatusWithSubnets)
+ (*in).DeepCopyInto(*out)
+ }
+ if in.ExternalNetwork != nil {
+ in, out := &in.ExternalNetwork, &out.ExternalNetwork
+ *out = new(NetworkStatus)
+ (*in).DeepCopyInto(*out)
+ }
+ if in.Router != nil {
+ in, out := &in.Router, &out.Router
+ *out = new(Router)
+ (*in).DeepCopyInto(*out)
+ }
+ if in.APIServerLoadBalancer != nil {
+ in, out := &in.APIServerLoadBalancer, &out.APIServerLoadBalancer
+ *out = new(LoadBalancer)
+ (*in).DeepCopyInto(*out)
+ }
+ if in.FailureDomains != nil {
+ in, out := &in.FailureDomains, &out.FailureDomains
+ *out = make(v1beta1.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)
+ }
+ if in.WorkerSecurityGroup != nil {
+ in, out := &in.WorkerSecurityGroup, &out.WorkerSecurityGroup
+ *out = new(SecurityGroup)
+ (*in).DeepCopyInto(*out)
+ }
+ if in.BastionSecurityGroup != nil {
+ in, out := &in.BastionSecurityGroup, &out.BastionSecurityGroup
+ *out = new(SecurityGroup)
+ (*in).DeepCopyInto(*out)
+ }
+ if in.Bastion != nil {
+ in, out := &in.Bastion, &out.Bastion
+ *out = new(BastionStatus)
+ **out = **in
+ }
+ if in.FailureReason != nil {
+ in, out := &in.FailureReason, &out.FailureReason
+ *out = new(errors.ClusterStatusError)
+ **out = **in
+ }
+ if in.FailureMessage != nil {
+ in, out := &in.FailureMessage, &out.FailureMessage
+ *out = new(string)
+ **out = **in
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenStackClusterStatus.
+func (in *OpenStackClusterStatus) DeepCopy() *OpenStackClusterStatus {
+ if in == nil {
+ return nil
+ }
+ out := new(OpenStackClusterStatus)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *OpenStackClusterTemplate) DeepCopyInto(out *OpenStackClusterTemplate) {
+ *out = *in
+ out.TypeMeta = in.TypeMeta
+ in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+ in.Spec.DeepCopyInto(&out.Spec)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenStackClusterTemplate.
+func (in *OpenStackClusterTemplate) DeepCopy() *OpenStackClusterTemplate {
+ if in == nil {
+ return nil
+ }
+ out := new(OpenStackClusterTemplate)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *OpenStackClusterTemplate) 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 *OpenStackClusterTemplateList) DeepCopyInto(out *OpenStackClusterTemplateList) {
+ *out = *in
+ out.TypeMeta = in.TypeMeta
+ in.ListMeta.DeepCopyInto(&out.ListMeta)
+ if in.Items != nil {
+ in, out := &in.Items, &out.Items
+ *out = make([]OpenStackClusterTemplate, len(*in))
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenStackClusterTemplateList.
+func (in *OpenStackClusterTemplateList) DeepCopy() *OpenStackClusterTemplateList {
+ if in == nil {
+ return nil
+ }
+ out := new(OpenStackClusterTemplateList)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *OpenStackClusterTemplateList) 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 *OpenStackClusterTemplateResource) DeepCopyInto(out *OpenStackClusterTemplateResource) {
+ *out = *in
+ in.Spec.DeepCopyInto(&out.Spec)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenStackClusterTemplateResource.
+func (in *OpenStackClusterTemplateResource) DeepCopy() *OpenStackClusterTemplateResource {
+ if in == nil {
+ return nil
+ }
+ out := new(OpenStackClusterTemplateResource)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *OpenStackClusterTemplateSpec) DeepCopyInto(out *OpenStackClusterTemplateSpec) {
+ *out = *in
+ in.Template.DeepCopyInto(&out.Template)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenStackClusterTemplateSpec.
+func (in *OpenStackClusterTemplateSpec) DeepCopy() *OpenStackClusterTemplateSpec {
+ if in == nil {
+ return nil
+ }
+ out := new(OpenStackClusterTemplateSpec)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *OpenStackIdentityReference) DeepCopyInto(out *OpenStackIdentityReference) {
+ *out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenStackIdentityReference.
+func (in *OpenStackIdentityReference) DeepCopy() *OpenStackIdentityReference {
+ if in == nil {
+ return nil
+ }
+ out := new(OpenStackIdentityReference)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *OpenStackMachine) DeepCopyInto(out *OpenStackMachine) {
+ *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 OpenStackMachine.
+func (in *OpenStackMachine) DeepCopy() *OpenStackMachine {
+ if in == nil {
+ return nil
+ }
+ out := new(OpenStackMachine)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *OpenStackMachine) 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 *OpenStackMachineList) DeepCopyInto(out *OpenStackMachineList) {
+ *out = *in
+ out.TypeMeta = in.TypeMeta
+ in.ListMeta.DeepCopyInto(&out.ListMeta)
+ if in.Items != nil {
+ in, out := &in.Items, &out.Items
+ *out = make([]OpenStackMachine, len(*in))
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenStackMachineList.
+func (in *OpenStackMachineList) DeepCopy() *OpenStackMachineList {
+ if in == nil {
+ return nil
+ }
+ out := new(OpenStackMachineList)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *OpenStackMachineList) 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 *OpenStackMachineSpec) DeepCopyInto(out *OpenStackMachineSpec) {
+ *out = *in
+ if in.ProviderID != nil {
+ in, out := &in.ProviderID, &out.ProviderID
+ *out = new(string)
+ **out = **in
+ }
+ if in.InstanceID != nil {
+ in, out := &in.InstanceID, &out.InstanceID
+ *out = new(string)
+ **out = **in
+ }
+ if in.Ports != nil {
+ in, out := &in.Ports, &out.Ports
+ *out = make([]PortOpts, len(*in))
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
+ }
+ if in.SecurityGroups != nil {
+ in, out := &in.SecurityGroups, &out.SecurityGroups
+ *out = make([]SecurityGroupFilter, len(*in))
+ copy(*out, *in)
+ }
+ if in.Tags != nil {
+ in, out := &in.Tags, &out.Tags
+ *out = make([]string, len(*in))
+ copy(*out, *in)
+ }
+ 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
+ }
+ }
+ if in.ConfigDrive != nil {
+ in, out := &in.ConfigDrive, &out.ConfigDrive
+ *out = new(bool)
+ **out = **in
+ }
+ if in.RootVolume != nil {
+ in, out := &in.RootVolume, &out.RootVolume
+ *out = new(RootVolume)
+ **out = **in
+ }
+ if in.AdditionalBlockDevices != nil {
+ in, out := &in.AdditionalBlockDevices, &out.AdditionalBlockDevices
+ *out = make([]AdditionalBlockDevice, len(*in))
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
+ }
+ if in.IdentityRef != nil {
+ in, out := &in.IdentityRef, &out.IdentityRef
+ *out = new(OpenStackIdentityReference)
+ **out = **in
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenStackMachineSpec.
+func (in *OpenStackMachineSpec) DeepCopy() *OpenStackMachineSpec {
+ if in == nil {
+ return nil
+ }
+ out := new(OpenStackMachineSpec)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// 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.Addresses != nil {
+ in, out := &in.Addresses, &out.Addresses
+ *out = make([]v1.NodeAddress, len(*in))
+ copy(*out, *in)
+ }
+ if in.InstanceState != nil {
+ in, out := &in.InstanceState, &out.InstanceState
+ *out = new(InstanceState)
+ **out = **in
+ }
+ if in.FailureReason != nil {
+ in, out := &in.FailureReason, &out.FailureReason
+ *out = new(errors.MachineStatusError)
+ **out = **in
+ }
+ if in.FailureMessage != nil {
+ in, out := &in.FailureMessage, &out.FailureMessage
+ *out = new(string)
+ **out = **in
+ }
+ if in.Conditions != nil {
+ in, out := &in.Conditions, &out.Conditions
+ *out = make(v1beta1.Conditions, len(*in))
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenStackMachineStatus.
+func (in *OpenStackMachineStatus) DeepCopy() *OpenStackMachineStatus {
+ if in == nil {
+ return nil
+ }
+ out := new(OpenStackMachineStatus)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *OpenStackMachineTemplate) DeepCopyInto(out *OpenStackMachineTemplate) {
+ *out = *in
+ out.TypeMeta = in.TypeMeta
+ in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+ in.Spec.DeepCopyInto(&out.Spec)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenStackMachineTemplate.
+func (in *OpenStackMachineTemplate) DeepCopy() *OpenStackMachineTemplate {
+ if in == nil {
+ return nil
+ }
+ out := new(OpenStackMachineTemplate)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *OpenStackMachineTemplate) 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 *OpenStackMachineTemplateList) DeepCopyInto(out *OpenStackMachineTemplateList) {
+ *out = *in
+ out.TypeMeta = in.TypeMeta
+ in.ListMeta.DeepCopyInto(&out.ListMeta)
+ if in.Items != nil {
+ in, out := &in.Items, &out.Items
+ *out = make([]OpenStackMachineTemplate, len(*in))
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenStackMachineTemplateList.
+func (in *OpenStackMachineTemplateList) DeepCopy() *OpenStackMachineTemplateList {
+ if in == nil {
+ return nil
+ }
+ out := new(OpenStackMachineTemplateList)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *OpenStackMachineTemplateList) 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 *OpenStackMachineTemplateResource) DeepCopyInto(out *OpenStackMachineTemplateResource) {
+ *out = *in
+ in.Spec.DeepCopyInto(&out.Spec)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenStackMachineTemplateResource.
+func (in *OpenStackMachineTemplateResource) DeepCopy() *OpenStackMachineTemplateResource {
+ if in == nil {
+ return nil
+ }
+ out := new(OpenStackMachineTemplateResource)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *OpenStackMachineTemplateSpec) DeepCopyInto(out *OpenStackMachineTemplateSpec) {
+ *out = *in
+ in.Template.DeepCopyInto(&out.Template)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenStackMachineTemplateSpec.
+func (in *OpenStackMachineTemplateSpec) DeepCopy() *OpenStackMachineTemplateSpec {
+ if in == nil {
+ return nil
+ }
+ out := new(OpenStackMachineTemplateSpec)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *PortOpts) DeepCopyInto(out *PortOpts) {
+ *out = *in
+ if in.Network != nil {
+ in, out := &in.Network, &out.Network
+ *out = new(NetworkFilter)
+ **out = **in
+ }
+ if in.AdminStateUp != nil {
+ in, out := &in.AdminStateUp, &out.AdminStateUp
+ *out = new(bool)
+ **out = **in
+ }
+ if in.FixedIPs != nil {
+ in, out := &in.FixedIPs, &out.FixedIPs
+ *out = make([]FixedIP, len(*in))
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
+ }
+ if in.SecurityGroupFilters != nil {
+ in, out := &in.SecurityGroupFilters, &out.SecurityGroupFilters
+ *out = make([]SecurityGroupFilter, len(*in))
+ copy(*out, *in)
+ }
+ if in.AllowedAddressPairs != nil {
+ in, out := &in.AllowedAddressPairs, &out.AllowedAddressPairs
+ *out = make([]AddressPair, len(*in))
+ copy(*out, *in)
+ }
+ if in.Trunk != nil {
+ in, out := &in.Trunk, &out.Trunk
+ *out = new(bool)
+ **out = **in
+ }
+ out.Profile = in.Profile
+ if in.DisablePortSecurity != nil {
+ in, out := &in.DisablePortSecurity, &out.DisablePortSecurity
+ *out = new(bool)
+ **out = **in
+ }
+ if in.PropagateUplinkStatus != nil {
+ in, out := &in.PropagateUplinkStatus, &out.PropagateUplinkStatus
+ *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))
+ copy(*out, *in)
+ }
+}
+
+// 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 *RootVolume) DeepCopyInto(out *RootVolume) {
+ *out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RootVolume.
+func (in *RootVolume) DeepCopy() *RootVolume {
+ if in == nil {
+ return nil
+ }
+ out := new(RootVolume)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *Router) DeepCopyInto(out *Router) {
+ *out = *in
+ if in.Tags != nil {
+ in, out := &in.Tags, &out.Tags
+ *out = make([]string, len(*in))
+ copy(*out, *in)
+ }
+ if in.IPs != nil {
+ in, out := &in.IPs, &out.IPs
+ *out = make([]string, len(*in))
+ copy(*out, *in)
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Router.
+func (in *Router) DeepCopy() *Router {
+ if in == nil {
+ return nil
+ }
+ out := new(Router)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// 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
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouterFilter.
+func (in *RouterFilter) DeepCopy() *RouterFilter {
+ if in == nil {
+ return nil
+ }
+ out := new(RouterFilter)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *SecurityGroup) DeepCopyInto(out *SecurityGroup) {
+ *out = *in
+ if in.Rules != nil {
+ in, out := &in.Rules, &out.Rules
+ *out = make([]SecurityGroupRule, len(*in))
+ copy(*out, *in)
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecurityGroup.
+func (in *SecurityGroup) DeepCopy() *SecurityGroup {
+ if in == nil {
+ return nil
+ }
+ out := new(SecurityGroup)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// 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
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecurityGroupFilter.
+func (in *SecurityGroupFilter) DeepCopy() *SecurityGroupFilter {
+ if in == nil {
+ return nil
+ }
+ out := new(SecurityGroupFilter)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *SecurityGroupRule) DeepCopyInto(out *SecurityGroupRule) {
+ *out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecurityGroupRule.
+func (in *SecurityGroupRule) DeepCopy() *SecurityGroupRule {
+ if in == nil {
+ return nil
+ }
+ out := new(SecurityGroupRule)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *Subnet) DeepCopyInto(out *Subnet) {
+ *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 Subnet.
+func (in *Subnet) DeepCopy() *Subnet {
+ if in == nil {
+ return nil
+ }
+ out := new(Subnet)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// 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
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubnetFilter.
+func (in *SubnetFilter) DeepCopy() *SubnetFilter {
+ if in == nil {
+ return nil
+ }
+ out := new(SubnetFilter)
+ 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
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ValueSpec.
+func (in *ValueSpec) DeepCopy() *ValueSpec {
+ if in == nil {
+ return nil
+ }
+ out := new(ValueSpec)
+ 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..532490a5ea 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -4700,6 +4700,1049 @@ spec:
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: v1alpha8
+ 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:
+ 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.
+ 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.
+ 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. It must be activated by setting `enabled: true`.'
+ properties:
+ additionalPorts:
+ description: AdditionalPorts adds additional tcp ports to the
+ load balancer.
+ items:
+ type: integer
+ type: array
+ allowedCidrs:
+ description: AllowedCIDRs restrict access to all API-Server listeners
+ to the given address CIDRs.
+ items:
+ type: string
+ type: array
+ enabled:
+ description: Enabled defines whether a load balancer should be
+ created.
+ type: boolean
+ provider:
+ description: Octavia Provider Used to create load balancer
+ type: string
+ 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
+ \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."
+ properties:
+ availabilityZone:
+ type: string
+ enabled:
+ type: boolean
+ instance:
+ description: Instance 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.
+ 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.
+ 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 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.
+ 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
+ cloudName:
+ description: The name of the cloud to use from the clouds
+ secret
+ type: string
+ configDrive:
+ description: Config Drive support
+ type: boolean
+ flavor:
+ 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.
+ 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.
+ 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.
+ 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.
+ type: string
+ imageUUID:
+ 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.
+ items:
+ properties:
+ adminStateUp:
+ type: boolean
+ allowedAddressPairs:
+ items:
+ properties:
+ ipAddress:
+ type: string
+ macAddress:
+ type: string
+ type: object
+ type: array
+ 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.
+ type: boolean
+ fixedIPs:
+ description: Specify pairs of subnet and/or IP address.
+ These should be subnets of the network with the given
+ NetworkID.
+ items:
+ properties:
+ 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.
+ properties:
+ cidr:
+ type: string
+ description:
+ type: string
+ gateway_ip:
+ type: string
+ id:
+ type: string
+ ipVersion:
+ type: integer
+ ipv6AddressMode:
+ type: string
+ ipv6RaMode:
+ type: string
+ name:
+ type: string
+ notTags:
+ type: string
+ notTagsAny:
+ type: string
+ projectId:
+ type: string
+ tags:
+ type: string
+ tagsAny:
+ type: string
+ type: object
+ required:
+ - subnet
+ type: object
+ type: array
+ hostId:
+ description: The ID of the host where the port is allocated
+ type: string
+ macAddress:
+ type: string
+ nameSuffix:
+ description: Used to make the name of the port unique.
+ 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.
+ properties:
+ description:
+ type: string
+ id:
+ type: string
+ name:
+ type: string
+ notTags:
+ type: string
+ notTagsAny:
+ type: string
+ projectId:
+ type: string
+ tags:
+ type: string
+ tagsAny:
+ 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
+ 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
+ securityGroupFilters:
+ description: The names, uuids, filters or any combination
+ these of the security groups to assign to the instance
+ items:
+ properties:
+ description:
+ type: string
+ id:
+ type: string
+ name:
+ type: string
+ notTags:
+ type: string
+ notTagsAny:
+ type: string
+ projectId:
+ type: string
+ tags:
+ type: string
+ tagsAny:
+ type: string
+ 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.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: set
+ trunk:
+ description: Enables and disables trunk at port level.
+ 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.
+ 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: The virtual network interface card (vNIC)
+ type that is bound to the neutron port.
+ 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:
+ type: string
+ diskSize:
+ type: integer
+ volumeType:
+ type: string
+ type: object
+ securityGroups:
+ description: The names of the security groups to assign to
+ the instance
+ items:
+ properties:
+ description:
+ type: string
+ id:
+ type: string
+ name:
+ type: string
+ notTags:
+ type: string
+ notTagsAny:
+ type: string
+ projectId:
+ type: string
+ tags:
+ type: string
+ tagsAny:
+ type: string
+ type: object
+ type: array
+ serverGroupID:
+ description: The server group to assign the machine to
+ type: string
+ serverMetadata:
+ additionalProperties:
+ type: string
+ description: Metadata mapping. Allows you to create a map
+ of key value pairs to add to the server instance.
+ type: object
+ sshKeyName:
+ description: The ssh key to inject in the instance
+ type: string
+ tags:
+ 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
+ type: object
+ cloudName:
+ description: The name of the cloud to use from the clouds secret
+ type: string
+ controlPlaneAvailabilityZones:
+ description: ControlPlaneAvailabilityZones is the az to deploy control
+ plane to
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: set
+ controlPlaneEndpoint:
+ description: ControlPlaneEndpoint represents the endpoint used to
+ communicate with the control plane.
+ 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: 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.
+ type: boolean
+ disablePortSecurity:
+ 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.
+ 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.
+ 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.
+ 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
+ properties:
+ cidr:
+ type: string
+ description:
+ type: string
+ gateway_ip:
+ type: string
+ id:
+ type: string
+ ipVersion:
+ type: integer
+ ipv6AddressMode:
+ type: string
+ ipv6RaMode:
+ type: string
+ name:
+ type: string
+ notTags:
+ type: string
+ notTagsAny:
+ type: string
+ projectId:
+ type: string
+ tags:
+ type: string
+ tagsAny:
+ type: string
+ type: object
+ required:
+ - subnet
+ type: object
+ type: array
+ 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.
+ 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.
+ 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.
+ type: boolean
+ network:
+ description: If NodeCIDR cannot be set this can be used to detect
+ an existing network.
+ properties:
+ description:
+ type: string
+ id:
+ type: string
+ name:
+ type: string
+ notTags:
+ type: string
+ notTagsAny:
+ type: string
+ projectId:
+ type: string
+ tags:
+ type: string
+ tagsAny:
+ 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.
+ 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.
+ 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.
+ properties:
+ description:
+ type: string
+ id:
+ type: string
+ name:
+ type: string
+ notTags:
+ type: string
+ notTagsAny:
+ type: string
+ projectId:
+ type: string
+ tags:
+ type: string
+ tagsAny:
+ type: string
+ type: object
+ subnet:
+ description: If NodeCIDR cannot be set this can be used to detect
+ an existing subnet.
+ properties:
+ cidr:
+ type: string
+ description:
+ type: string
+ gateway_ip:
+ type: string
+ id:
+ type: string
+ ipVersion:
+ type: integer
+ ipv6AddressMode:
+ type: string
+ ipv6RaMode:
+ type: string
+ name:
+ type: string
+ notTags:
+ type: string
+ notTagsAny:
+ type: string
+ projectId:
+ type: string
+ tags:
+ type: string
+ tagsAny:
+ type: string
+ type: object
+ tags:
+ description: Tags for all resources in cluster
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: set
+ 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
+ name:
+ type: string
+ tags:
+ items:
+ type: string
+ type: array
+ required:
+ - id
+ - internalIP
+ - ip
+ - name
+ type: object
+ bastion:
+ properties:
+ floatingIP:
+ type: string
+ id:
+ type: string
+ ip:
+ type: string
+ name:
+ type: string
+ sshKeyName:
+ type: string
+ state:
+ description: InstanceState describes the state of an OpenStack
+ instance.
+ type: string
+ type: object
+ bastionSecurityGroup:
+ description: SecurityGroup represents the basic information of the
+ associated OpenStack Neutron Security Group.
+ properties:
+ id:
+ type: string
+ name:
+ type: string
+ rules:
+ items:
+ description: SecurityGroupRule represent the basic information
+ of the associated OpenStack Security Group Role.
+ properties:
+ description:
+ type: string
+ direction:
+ type: string
+ etherType:
+ type: string
+ name:
+ type: string
+ portRangeMax:
+ type: integer
+ portRangeMin:
+ type: integer
+ protocol:
+ type: string
+ remoteGroupID:
+ type: string
+ remoteIPPrefix:
+ type: string
+ securityGroupID:
+ type: string
+ required:
+ - description
+ - direction
+ - etherType
+ - name
+ - portRangeMax
+ - portRangeMin
+ - protocol
+ - remoteGroupID
+ - remoteIPPrefix
+ - securityGroupID
+ type: object
+ type: array
+ 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?'
+ properties:
+ id:
+ type: string
+ name:
+ type: string
+ rules:
+ items:
+ description: SecurityGroupRule represent the basic information
+ of the associated OpenStack Security Group Role.
+ properties:
+ description:
+ type: string
+ direction:
+ type: string
+ etherType:
+ type: string
+ name:
+ type: string
+ portRangeMax:
+ type: integer
+ portRangeMin:
+ type: integer
+ protocol:
+ type: string
+ remoteGroupID:
+ type: string
+ remoteIPPrefix:
+ type: string
+ securityGroupID:
+ type: string
+ required:
+ - description
+ - direction
+ - etherType
+ - name
+ - portRangeMax
+ - portRangeMin
+ - protocol
+ - remoteGroupID
+ - remoteIPPrefix
+ - securityGroupID
+ type: object
+ type: array
+ required:
+ - id
+ - name
+ - rules
+ 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.
+ \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."
+ 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."
+ 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:
+ 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 all the information about
+ the OpenStack Security Group that needs to be applied to worker
+ nodes.
+ properties:
+ id:
+ type: string
+ name:
+ type: string
+ rules:
+ items:
+ description: SecurityGroupRule represent the basic information
+ of the associated OpenStack Security Group Role.
+ properties:
+ description:
+ type: string
+ direction:
+ type: string
+ etherType:
+ type: string
+ name:
+ type: string
+ portRangeMax:
+ type: integer
+ portRangeMin:
+ type: integer
+ protocol:
+ type: string
+ remoteGroupID:
+ type: string
+ remoteIPPrefix:
+ type: string
+ securityGroupID:
+ type: string
+ required:
+ - description
+ - direction
+ - etherType
+ - name
+ - portRangeMax
+ - portRangeMin
+ - protocol
+ - remoteGroupID
+ - remoteIPPrefix
+ - securityGroupID
+ type: object
+ type: array
+ required:
+ - id
+ - name
+ - rules
+ type: object
+ required:
+ - ready
+ type: object
+ type: object
+ served: true
storage: true
subresources:
status: {}
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..73f10af04d 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -2240,4 +2240,733 @@ spec:
type: object
type: object
served: true
+ storage: false
+ - name: v1alpha8
+ 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:
+ 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.
+ 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.
+ 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. It must be activated by
+ setting `enabled: true`.'
+ properties:
+ additionalPorts:
+ description: AdditionalPorts adds additional tcp ports
+ to the load balancer.
+ items:
+ type: integer
+ type: array
+ allowedCidrs:
+ description: AllowedCIDRs restrict access to all API-Server
+ listeners to the given address CIDRs.
+ items:
+ type: string
+ type: array
+ enabled:
+ description: Enabled defines whether a load balancer should
+ be created.
+ type: boolean
+ provider:
+ description: Octavia Provider Used to create load balancer
+ type: string
+ 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 \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."
+ properties:
+ availabilityZone:
+ type: string
+ enabled:
+ type: boolean
+ instance:
+ description: Instance 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.
+ 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.
+ 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 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.
+ 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
+ cloudName:
+ description: The name of the cloud to use from the
+ clouds secret
+ type: string
+ configDrive:
+ description: Config Drive support
+ type: boolean
+ flavor:
+ 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.
+ 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.
+ 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.
+ 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.
+ type: string
+ imageUUID:
+ 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.
+ items:
+ properties:
+ adminStateUp:
+ type: boolean
+ allowedAddressPairs:
+ items:
+ properties:
+ ipAddress:
+ type: string
+ macAddress:
+ type: string
+ type: object
+ type: array
+ 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.
+ type: boolean
+ fixedIPs:
+ description: Specify pairs of subnet and/or
+ IP address. These should be subnets of the
+ network with the given NetworkID.
+ items:
+ properties:
+ 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.
+ properties:
+ cidr:
+ type: string
+ description:
+ type: string
+ gateway_ip:
+ type: string
+ id:
+ type: string
+ ipVersion:
+ type: integer
+ ipv6AddressMode:
+ type: string
+ ipv6RaMode:
+ type: string
+ name:
+ type: string
+ notTags:
+ type: string
+ notTagsAny:
+ type: string
+ projectId:
+ type: string
+ tags:
+ type: string
+ tagsAny:
+ type: string
+ type: object
+ required:
+ - subnet
+ type: object
+ type: array
+ hostId:
+ description: The ID of the host where the port
+ is allocated
+ type: string
+ macAddress:
+ type: string
+ nameSuffix:
+ description: Used to make the name of the port
+ unique. 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.
+ properties:
+ description:
+ type: string
+ id:
+ type: string
+ name:
+ type: string
+ notTags:
+ type: string
+ notTagsAny:
+ type: string
+ projectId:
+ type: string
+ tags:
+ type: string
+ tagsAny:
+ 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
+ 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
+ securityGroupFilters:
+ description: The names, uuids, filters or any
+ combination these of the security groups to
+ assign to the instance
+ items:
+ properties:
+ description:
+ type: string
+ id:
+ type: string
+ name:
+ type: string
+ notTags:
+ type: string
+ notTagsAny:
+ type: string
+ projectId:
+ type: string
+ tags:
+ type: string
+ tagsAny:
+ type: string
+ 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.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: set
+ trunk:
+ description: Enables and disables trunk at port
+ level. 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.
+ 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: The virtual network interface card
+ (vNIC) type that is bound to the neutron port.
+ 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:
+ type: string
+ diskSize:
+ type: integer
+ volumeType:
+ type: string
+ type: object
+ securityGroups:
+ description: The names of the security groups to assign
+ to the instance
+ items:
+ properties:
+ description:
+ type: string
+ id:
+ type: string
+ name:
+ type: string
+ notTags:
+ type: string
+ notTagsAny:
+ type: string
+ projectId:
+ type: string
+ tags:
+ type: string
+ tagsAny:
+ type: string
+ type: object
+ type: array
+ serverGroupID:
+ description: The server group to assign the machine
+ to
+ type: string
+ serverMetadata:
+ additionalProperties:
+ type: string
+ description: Metadata mapping. Allows you to create
+ a map of key value pairs to add to the server instance.
+ type: object
+ sshKeyName:
+ description: The ssh key to inject in the instance
+ type: string
+ tags:
+ 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
+ type: object
+ cloudName:
+ description: The name of the cloud to use from the clouds
+ secret
+ type: string
+ controlPlaneAvailabilityZones:
+ description: ControlPlaneAvailabilityZones is the az to deploy
+ control plane to
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: set
+ controlPlaneEndpoint:
+ description: ControlPlaneEndpoint represents the endpoint
+ used to communicate with the control plane.
+ 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: 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.
+ type: boolean
+ disablePortSecurity:
+ 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.
+ 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.
+ 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.
+ 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
+ properties:
+ cidr:
+ type: string
+ description:
+ type: string
+ gateway_ip:
+ type: string
+ id:
+ type: string
+ ipVersion:
+ type: integer
+ ipv6AddressMode:
+ type: string
+ ipv6RaMode:
+ type: string
+ name:
+ type: string
+ notTags:
+ type: string
+ notTagsAny:
+ type: string
+ projectId:
+ type: string
+ tags:
+ type: string
+ tagsAny:
+ type: string
+ type: object
+ required:
+ - subnet
+ type: object
+ type: array
+ 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.
+ 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.
+ 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.
+ type: boolean
+ network:
+ description: If NodeCIDR cannot be set this can be used to
+ detect an existing network.
+ properties:
+ description:
+ type: string
+ id:
+ type: string
+ name:
+ type: string
+ notTags:
+ type: string
+ notTagsAny:
+ type: string
+ projectId:
+ type: string
+ tags:
+ type: string
+ tagsAny:
+ 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.
+ 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.
+ 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.
+ properties:
+ description:
+ type: string
+ id:
+ type: string
+ name:
+ type: string
+ notTags:
+ type: string
+ notTagsAny:
+ type: string
+ projectId:
+ type: string
+ tags:
+ type: string
+ tagsAny:
+ type: string
+ type: object
+ subnet:
+ description: If NodeCIDR cannot be set this can be used to
+ detect an existing subnet.
+ properties:
+ cidr:
+ type: string
+ description:
+ type: string
+ gateway_ip:
+ type: string
+ id:
+ type: string
+ ipVersion:
+ type: integer
+ ipv6AddressMode:
+ type: string
+ ipv6RaMode:
+ type: string
+ name:
+ type: string
+ notTags:
+ type: string
+ notTagsAny:
+ type: string
+ projectId:
+ type: string
+ tags:
+ type: string
+ tagsAny:
+ type: string
+ type: object
+ tags:
+ description: Tags for all resources in cluster
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: set
+ 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_openstackmachines.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
index e5171cd868..a9b90ba429 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
@@ -1609,6 +1609,504 @@ spec:
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: v1alpha8
+ 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.
+ 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.
+ 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 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.
+ 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
+ cloudName:
+ description: The name of the cloud to use from the clouds secret
+ type: string
+ configDrive:
+ description: Config Drive support
+ type: boolean
+ flavor:
+ 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.
+ 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.
+ 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.
+ 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.
+ type: string
+ imageUUID:
+ 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.
+ items:
+ properties:
+ adminStateUp:
+ type: boolean
+ allowedAddressPairs:
+ items:
+ properties:
+ ipAddress:
+ type: string
+ macAddress:
+ type: string
+ type: object
+ type: array
+ 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.
+ type: boolean
+ fixedIPs:
+ description: Specify pairs of subnet and/or IP address. These
+ should be subnets of the network with the given NetworkID.
+ items:
+ properties:
+ 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.
+ properties:
+ cidr:
+ type: string
+ description:
+ type: string
+ gateway_ip:
+ type: string
+ id:
+ type: string
+ ipVersion:
+ type: integer
+ ipv6AddressMode:
+ type: string
+ ipv6RaMode:
+ type: string
+ name:
+ type: string
+ notTags:
+ type: string
+ notTagsAny:
+ type: string
+ projectId:
+ type: string
+ tags:
+ type: string
+ tagsAny:
+ type: string
+ type: object
+ required:
+ - subnet
+ type: object
+ type: array
+ hostId:
+ description: The ID of the host where the port is allocated
+ type: string
+ macAddress:
+ type: string
+ nameSuffix:
+ description: Used to make the name of the port unique. 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.
+ properties:
+ description:
+ type: string
+ id:
+ type: string
+ name:
+ type: string
+ notTags:
+ type: string
+ notTagsAny:
+ type: string
+ projectId:
+ type: string
+ tags:
+ type: string
+ tagsAny:
+ 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
+ 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
+ securityGroupFilters:
+ description: The names, uuids, filters or any combination these
+ of the security groups to assign to the instance
+ items:
+ properties:
+ description:
+ type: string
+ id:
+ type: string
+ name:
+ type: string
+ notTags:
+ type: string
+ notTagsAny:
+ type: string
+ projectId:
+ type: string
+ tags:
+ type: string
+ tagsAny:
+ type: string
+ 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.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: set
+ trunk:
+ description: Enables and disables trunk at port level. 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.
+ 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: The virtual network interface card (vNIC) type
+ that is bound to the neutron port.
+ 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:
+ type: string
+ diskSize:
+ type: integer
+ volumeType:
+ type: string
+ type: object
+ securityGroups:
+ description: The names of the security groups to assign to the instance
+ items:
+ properties:
+ description:
+ type: string
+ id:
+ type: string
+ name:
+ type: string
+ notTags:
+ type: string
+ notTagsAny:
+ type: string
+ projectId:
+ type: string
+ tags:
+ type: string
+ tagsAny:
+ type: string
+ type: object
+ type: array
+ serverGroupID:
+ description: The server group to assign the machine to
+ type: string
+ serverMetadata:
+ additionalProperties:
+ type: string
+ description: Metadata mapping. Allows you to create a map of key value
+ pairs to add to the server instance.
+ type: object
+ sshKeyName:
+ description: The ssh key to inject in the instance
+ type: string
+ tags:
+ 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. \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."
+ 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: true
subresources:
status: {}
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..f60aff2895 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
@@ -1334,4 +1334,411 @@ spec:
type: object
type: object
served: true
+ storage: false
+ - name: v1alpha8
+ 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.
+ 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.
+ 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 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.
+ 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
+ cloudName:
+ description: The name of the cloud to use from the clouds
+ secret
+ type: string
+ configDrive:
+ description: Config Drive support
+ type: boolean
+ flavor:
+ 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.
+ 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.
+ 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.
+ 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.
+ type: string
+ imageUUID:
+ 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.
+ items:
+ properties:
+ adminStateUp:
+ type: boolean
+ allowedAddressPairs:
+ items:
+ properties:
+ ipAddress:
+ type: string
+ macAddress:
+ type: string
+ type: object
+ type: array
+ 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.
+ type: boolean
+ fixedIPs:
+ description: Specify pairs of subnet and/or IP address.
+ These should be subnets of the network with the given
+ NetworkID.
+ items:
+ properties:
+ 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.
+ properties:
+ cidr:
+ type: string
+ description:
+ type: string
+ gateway_ip:
+ type: string
+ id:
+ type: string
+ ipVersion:
+ type: integer
+ ipv6AddressMode:
+ type: string
+ ipv6RaMode:
+ type: string
+ name:
+ type: string
+ notTags:
+ type: string
+ notTagsAny:
+ type: string
+ projectId:
+ type: string
+ tags:
+ type: string
+ tagsAny:
+ type: string
+ type: object
+ required:
+ - subnet
+ type: object
+ type: array
+ hostId:
+ description: The ID of the host where the port is allocated
+ type: string
+ macAddress:
+ type: string
+ nameSuffix:
+ description: Used to make the name of the port unique.
+ 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.
+ properties:
+ description:
+ type: string
+ id:
+ type: string
+ name:
+ type: string
+ notTags:
+ type: string
+ notTagsAny:
+ type: string
+ projectId:
+ type: string
+ tags:
+ type: string
+ tagsAny:
+ 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
+ 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
+ securityGroupFilters:
+ description: The names, uuids, filters or any combination
+ these of the security groups to assign to the instance
+ items:
+ properties:
+ description:
+ type: string
+ id:
+ type: string
+ name:
+ type: string
+ notTags:
+ type: string
+ notTagsAny:
+ type: string
+ projectId:
+ type: string
+ tags:
+ type: string
+ tagsAny:
+ type: string
+ 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.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: set
+ trunk:
+ description: Enables and disables trunk at port level.
+ 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.
+ 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: The virtual network interface card (vNIC)
+ type that is bound to the neutron port.
+ 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:
+ type: string
+ diskSize:
+ type: integer
+ volumeType:
+ type: string
+ type: object
+ securityGroups:
+ description: The names of the security groups to assign to
+ the instance
+ items:
+ properties:
+ description:
+ type: string
+ id:
+ type: string
+ name:
+ type: string
+ notTags:
+ type: string
+ notTagsAny:
+ type: string
+ projectId:
+ type: string
+ tags:
+ type: string
+ tagsAny:
+ type: string
+ type: object
+ type: array
+ serverGroupID:
+ description: The server group to assign the machine to
+ type: string
+ serverMetadata:
+ additionalProperties:
+ type: string
+ description: Metadata mapping. Allows you to create a map
+ of key value pairs to add to the server instance.
+ type: object
+ sshKeyName:
+ description: The ssh key to inject in the instance
+ type: string
+ tags:
+ 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: true
diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml
index f26fa8c3b8..283048b008 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_v1alpha8
# 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.
diff --git a/config/webhook/manifests.yaml b/config/webhook/manifests.yaml
index b2e5ad4c2b..d65e84a9f2 100644
--- a/config/webhook/manifests.yaml
+++ b/config/webhook/manifests.yaml
@@ -10,7 +10,7 @@ webhooks:
service:
name: webhook-service
namespace: system
- path: /mutate-infrastructure-cluster-x-k8s-io-v1alpha7-openstackcluster
+ path: /mutate-infrastructure-cluster-x-k8s-io-v1alpha8-openstackcluster
failurePolicy: Fail
matchPolicy: Equivalent
name: default.openstackcluster.infrastructure.cluster.x-k8s.io
@@ -18,7 +18,7 @@ webhooks:
- apiGroups:
- infrastructure.cluster.x-k8s.io
apiVersions:
- - v1alpha7
+ - v1alpha8
operations:
- CREATE
- UPDATE
@@ -31,7 +31,7 @@ webhooks:
service:
name: webhook-service
namespace: system
- path: /mutate-infrastructure-cluster-x-k8s-io-v1alpha7-openstackclustertemplate
+ path: /mutate-infrastructure-cluster-x-k8s-io-v1alpha8-openstackclustertemplate
failurePolicy: Fail
matchPolicy: Equivalent
name: default.openstackclustertemplate.infrastructure.cluster.x-k8s.io
@@ -39,7 +39,7 @@ webhooks:
- apiGroups:
- infrastructure.cluster.x-k8s.io
apiVersions:
- - v1alpha7
+ - v1alpha8
operations:
- CREATE
- UPDATE
@@ -52,7 +52,7 @@ webhooks:
service:
name: webhook-service
namespace: system
- path: /mutate-infrastructure-cluster-x-k8s-io-v1alpha7-openstackmachine
+ path: /mutate-infrastructure-cluster-x-k8s-io-v1alpha8-openstackmachine
failurePolicy: Fail
matchPolicy: Equivalent
name: default.openstackmachine.infrastructure.cluster.x-k8s.io
@@ -60,7 +60,7 @@ webhooks:
- apiGroups:
- infrastructure.cluster.x-k8s.io
apiVersions:
- - v1alpha7
+ - v1alpha8
operations:
- CREATE
- UPDATE
@@ -79,7 +79,7 @@ webhooks:
service:
name: webhook-service
namespace: system
- path: /validate-infrastructure-cluster-x-k8s-io-v1alpha7-openstackcluster
+ path: /validate-infrastructure-cluster-x-k8s-io-v1alpha8-openstackcluster
failurePolicy: Fail
matchPolicy: Equivalent
name: validation.openstackcluster.infrastructure.cluster.x-k8s.io
@@ -87,7 +87,7 @@ webhooks:
- apiGroups:
- infrastructure.cluster.x-k8s.io
apiVersions:
- - v1alpha7
+ - v1alpha8
operations:
- CREATE
- UPDATE
@@ -100,7 +100,7 @@ webhooks:
service:
name: webhook-service
namespace: system
- path: /validate-infrastructure-cluster-x-k8s-io-v1alpha7-openstackclustertemplate
+ path: /validate-infrastructure-cluster-x-k8s-io-v1alpha8-openstackclustertemplate
failurePolicy: Fail
matchPolicy: Equivalent
name: validation.openstackclustertemplate.infrastructure.cluster.x-k8s.io
@@ -108,7 +108,7 @@ webhooks:
- apiGroups:
- infrastructure.cluster.x-k8s.io
apiVersions:
- - v1alpha7
+ - v1alpha8
operations:
- CREATE
- UPDATE
@@ -121,7 +121,7 @@ webhooks:
service:
name: webhook-service
namespace: system
- path: /validate-infrastructure-cluster-x-k8s-io-v1alpha7-openstackmachine
+ path: /validate-infrastructure-cluster-x-k8s-io-v1alpha8-openstackmachine
failurePolicy: Fail
matchPolicy: Equivalent
name: validation.openstackmachine.infrastructure.cluster.x-k8s.io
@@ -129,7 +129,7 @@ webhooks:
- apiGroups:
- infrastructure.cluster.x-k8s.io
apiVersions:
- - v1alpha7
+ - v1alpha8
operations:
- CREATE
- UPDATE
@@ -142,7 +142,7 @@ webhooks:
service:
name: webhook-service
namespace: system
- path: /validate-infrastructure-cluster-x-k8s-io-v1alpha7-openstackmachinetemplate
+ path: /validate-infrastructure-cluster-x-k8s-io-v1alpha8-openstackmachinetemplate
failurePolicy: Fail
matchPolicy: Equivalent
name: validation.openstackmachinetemplate.infrastructure.cluster.x-k8s.io
@@ -150,7 +150,7 @@ webhooks:
- apiGroups:
- infrastructure.cluster.x-k8s.io
apiVersions:
- - v1alpha7
+ - v1alpha8
operations:
- CREATE
- UPDATE
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index 08177fc9ed..f83b8b75a9 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -44,7 +44,7 @@ import (
"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/v1alpha8"
"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"
diff --git a/controllers/openstackcluster_controller_test.go b/controllers/openstackcluster_controller_test.go
index a4f0cfb442..400710ee42 100644
--- a/controllers/openstackcluster_controller_test.go
+++ b/controllers/openstackcluster_controller_test.go
@@ -37,7 +37,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/v1alpha8"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
)
diff --git a/controllers/openstackmachine_controller.go b/controllers/openstackmachine_controller.go
index b0345c078c..d5acde67cb 100644
--- a/controllers/openstackmachine_controller.go
+++ b/controllers/openstackmachine_controller.go
@@ -48,7 +48,7 @@ import (
"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/v1alpha8"
"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"
diff --git a/controllers/openstackmachine_controller_test.go b/controllers/openstackmachine_controller_test.go
index 0d9045c221..c78ab8643c 100644
--- a/controllers/openstackmachine_controller_test.go
+++ b/controllers/openstackmachine_controller_test.go
@@ -24,7 +24,7 @@ import (
"k8s.io/utils/pointer"
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/v1alpha8"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/cloud/services/compute"
)
diff --git a/controllers/suite_test.go b/controllers/suite_test.go
index b0edc98d5f..3a63e41d9a 100644
--- a/controllers/suite_test.go
+++ b/controllers/suite_test.go
@@ -37,7 +37,7 @@ import (
"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/v1alpha8"
"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"
diff --git a/docs/book/src/clusteropenstack/configuration.md b/docs/book/src/clusteropenstack/configuration.md
index 6d9ab32fff..a767139134 100644
--- a/docs/book/src/clusteropenstack/configuration.md
+++ b/docs/book/src/clusteropenstack/configuration.md
@@ -178,7 +178,7 @@ Note: If your openstack cluster does not already have a public network, you shou
You can use a pre-existing router instead of creating a new one. When deleting a cluster a pre-existing router will not be deleted.
```yaml
- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+ apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackCluster
metadata:
name:
@@ -245,7 +245,7 @@ It is possible to restrict access to the Kubernetes API server on a network leve
the allowed CIDRs by `spec.APIServerLoadBalancer.AllowedCIDRs` of `OpenStackCluster`.
```yaml
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackCluster
metadata:
name:
@@ -264,7 +264,7 @@ All known IPs of the target cluster will be discovered dynamically (e.g. you don
All applied CIDRs (user defined + dynamically discovered) are written back into `status.network.apiServerLoadBalancer.allowedCIDRs`
```yaml
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackCluster
metadata:
name:
@@ -297,7 +297,7 @@ If you have a complex query that you want to use to lookup a network, then you c
By using filters to look up a network, please note that it is possible to get multiple networks as a result. This should not be a problem, however please test your filters with `openstack network list` to be certain that it returns the networks you want. Please refer to the following usage example:
```yaml
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
metadata:
name: -controlplane
@@ -315,7 +315,7 @@ spec:
You can specify multiple networks (or subnets) to connect your server to. To do this, simply add another entry in the networks array. The following example connects the server to 3 different networks:
```yaml
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
metadata:
name: -controlplane
@@ -339,7 +339,7 @@ spec:
Rather than just using a network, you have the option of specifying a specific subnet to connect your server to. The following is an example of how to specify a specific subnet of a network to use for your server.
```yaml
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
metadata:
name: -controlplane
@@ -360,7 +360,7 @@ spec:
A server can also be connected to networks by describing what ports to create. Describing a server's connection with `ports` allows for finer and more advanced configuration. For example, you can specify per-port security groups, fixed IPs, VNIC type or profile.
```yaml
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
metadata:
name: -controlplane
@@ -458,7 +458,7 @@ ports:
`port security` can be applied to specific port to enable/disable the `port security` on that port; When not set, it takes the value of the corresponding field at the network level.
```yaml
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
metadata:
name: -controlplane
@@ -504,7 +504,7 @@ If this is not flexible enough, pre-existing security groups can be added to the
spec of an `OpenStackMachineTemplate`, e.g.:
```yaml
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
metadata:
name: ${CLUSTER_NAME}-control-plane
@@ -520,7 +520,7 @@ spec:
You have the ability to tag all resources created by the cluster in the `OpenStackCluster` spec. Here is an example how to configure tagging:
```yaml
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackCluster
metadata:
name:
@@ -533,7 +533,7 @@ spec:
To tag resources specific to a machine, add a value to the tags field in the `OpenStackMachineTemplate` spec like this:
```yaml
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
metadata:
name: -controlplane
@@ -550,7 +550,7 @@ spec:
You also have the option to add metadata to instances. Here is a usage example:
```yaml
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
metadata:
name: -controlplane
@@ -568,7 +568,7 @@ spec:
For example in `OpenStackMachineTemplate` set `spec.rootVolume.diskSize` to something greater than `0` means boot from volume.
```yaml
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
metadata:
name: -controlplane
diff --git a/hack/boilerplate/boilerplate.generatego.txt b/hack/boilerplate/boilerplate.generatego.txt
index 1653d588d3..9e6642b40b 100644
--- a/hack/boilerplate/boilerplate.generatego.txt
+++ b/hack/boilerplate/boilerplate.generatego.txt
@@ -1,5 +1,5 @@
/*
-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/kustomize/v1alpha8/default/cluster-template.yaml b/kustomize/v1alpha8/default/cluster-template.yaml
new file mode 100644
index 0000000000..4bf130b0a9
--- /dev/null
+++ b/kustomize/v1alpha8/default/cluster-template.yaml
@@ -0,0 +1,148 @@
+---
+apiVersion: cluster.x-k8s.io/v1beta1
+kind: Cluster
+metadata:
+ name: ${CLUSTER_NAME}
+spec:
+ clusterNetwork:
+ pods:
+ cidrBlocks: ["192.168.0.0/16"] # CIDR block used by Calico.
+ serviceDomain: "cluster.local"
+ infrastructureRef:
+ apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+ kind: OpenStackCluster
+ name: ${CLUSTER_NAME}
+ controlPlaneRef:
+ kind: KubeadmControlPlane
+ apiVersion: controlplane.cluster.x-k8s.io/v1beta1
+ name: ${CLUSTER_NAME}-control-plane
+---
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+kind: OpenStackCluster
+metadata:
+ name: ${CLUSTER_NAME}
+spec:
+ cloudName: ${OPENSTACK_CLOUD}
+ identityRef:
+ name: ${CLUSTER_NAME}-cloud-config
+ kind: Secret
+ apiServerLoadBalancer:
+ enabled: true
+ managedSecurityGroups: true
+ nodeCidr: 10.6.0.0/24
+ dnsNameservers:
+ - ${OPENSTACK_DNS_NAMESERVERS}
+ externalNetworkId: ${OPENSTACK_EXTERNAL_NETWORK_ID}
+---
+kind: KubeadmControlPlane
+apiVersion: controlplane.cluster.x-k8s.io/v1beta1
+metadata:
+ name: "${CLUSTER_NAME}-control-plane"
+spec:
+ replicas: ${CONTROL_PLANE_MACHINE_COUNT}
+ machineTemplate:
+ infrastructureRef:
+ kind: OpenStackMachineTemplate
+ apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+ name: "${CLUSTER_NAME}-control-plane"
+ kubeadmConfigSpec:
+ initConfiguration:
+ nodeRegistration:
+ name: '{{ local_hostname }}'
+ kubeletExtraArgs:
+ cloud-provider: external
+ provider-id: "openstack:///'{{ instance_id }}'"
+ clusterConfiguration:
+ apiServer:
+ extraArgs:
+ cloud-provider: external
+ controllerManager:
+ extraArgs:
+ cloud-provider: external
+ joinConfiguration:
+ nodeRegistration:
+ name: '{{ local_hostname }}'
+ kubeletExtraArgs:
+ cloud-provider: external
+ provider-id: "openstack:///'{{ instance_id }}'"
+ files: []
+ version: "${KUBERNETES_VERSION}"
+---
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+kind: OpenStackMachineTemplate
+metadata:
+ name: ${CLUSTER_NAME}-control-plane
+spec:
+ template:
+ spec:
+ flavor: ${OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR}
+ image: ${OPENSTACK_IMAGE_NAME}
+ sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
+ cloudName: ${OPENSTACK_CLOUD}
+ identityRef:
+ name: ${CLUSTER_NAME}-cloud-config
+ kind: Secret
+---
+apiVersion: cluster.x-k8s.io/v1beta1
+kind: MachineDeployment
+metadata:
+ name: "${CLUSTER_NAME}-md-0"
+spec:
+ clusterName: "${CLUSTER_NAME}"
+ replicas: ${WORKER_MACHINE_COUNT}
+ selector:
+ matchLabels:
+ template:
+ spec:
+ clusterName: "${CLUSTER_NAME}"
+ version: "${KUBERNETES_VERSION}"
+ failureDomain: ${OPENSTACK_FAILURE_DOMAIN}
+ bootstrap:
+ configRef:
+ name: "${CLUSTER_NAME}-md-0"
+ apiVersion: bootstrap.cluster.x-k8s.io/v1beta1
+ kind: KubeadmConfigTemplate
+ infrastructureRef:
+ name: "${CLUSTER_NAME}-md-0"
+ apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+ kind: OpenStackMachineTemplate
+---
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+kind: OpenStackMachineTemplate
+metadata:
+ name: ${CLUSTER_NAME}-md-0
+spec:
+ template:
+ spec:
+ cloudName: ${OPENSTACK_CLOUD}
+ identityRef:
+ name: ${CLUSTER_NAME}-cloud-config
+ kind: Secret
+ flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR}
+ image: ${OPENSTACK_IMAGE_NAME}
+ sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
+---
+apiVersion: bootstrap.cluster.x-k8s.io/v1beta1
+kind: KubeadmConfigTemplate
+metadata:
+ name: ${CLUSTER_NAME}-md-0
+spec:
+ template:
+ spec:
+ files: []
+ joinConfiguration:
+ nodeRegistration:
+ name: '{{ local_hostname }}'
+ kubeletExtraArgs:
+ cloud-provider: external
+ provider-id: "openstack:///'{{ instance_id }}'"
+---
+apiVersion: v1
+kind: Secret
+metadata:
+ name: ${CLUSTER_NAME}-cloud-config
+ labels:
+ clusterctl.cluster.x-k8s.io/move: "true"
+data:
+ clouds.yaml: ${OPENSTACK_CLOUD_YAML_B64}
+ cacert: ${OPENSTACK_CLOUD_CACERT_B64}
diff --git a/kustomize/v1alpha8/default/kustomization.yaml b/kustomize/v1alpha8/default/kustomization.yaml
new file mode 100644
index 0000000000..bc7ab04c05
--- /dev/null
+++ b/kustomize/v1alpha8/default/kustomization.yaml
@@ -0,0 +1,4 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+resources:
+- cluster-template.yaml
diff --git a/kustomize/v1alpha8/flatcar/kustomization.yaml b/kustomize/v1alpha8/flatcar/kustomization.yaml
new file mode 100644
index 0000000000..7332b6b51f
--- /dev/null
+++ b/kustomize/v1alpha8/flatcar/kustomization.yaml
@@ -0,0 +1,6 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+resources:
+- ../default
+patches:
+- path: patch-flatcar.yaml
diff --git a/kustomize/v1alpha8/flatcar/patch-flatcar.yaml b/kustomize/v1alpha8/flatcar/patch-flatcar.yaml
new file mode 100644
index 0000000000..d3750014fb
--- /dev/null
+++ b/kustomize/v1alpha8/flatcar/patch-flatcar.yaml
@@ -0,0 +1,109 @@
+---
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+kind: OpenStackCluster
+metadata:
+ name: ${CLUSTER_NAME}
+spec:
+ apiServerLoadBalancer:
+ $patch: delete
+---
+apiVersion: controlplane.cluster.x-k8s.io/v1beta1
+kind: KubeadmControlPlane
+metadata:
+ name: "${CLUSTER_NAME}-control-plane"
+spec:
+ replicas: ${CONTROL_PLANE_MACHINE_COUNT}
+ kubeadmConfigSpec:
+ joinConfiguration:
+ nodeRegistration:
+ name: $${COREOS_OPENSTACK_HOSTNAME}
+ kubeletExtraArgs:
+ provider-id: null
+ initConfiguration:
+ nodeRegistration:
+ name: $${COREOS_OPENSTACK_HOSTNAME}
+ kubeletExtraArgs:
+ # Fixme(lentzi90): This is here just to override the value set in the default
+ # kustomization. It will be replaced with a value that works for flatcar in
+ # https://github.com/kubernetes-sigs/cluster-api-provider-openstack/pull/1564
+ provider-id: null
+ format: ignition
+ ignition:
+ containerLinuxConfig:
+ additionalConfig: |
+ systemd:
+ units:
+ - name: coreos-metadata-sshkeys@.service
+ enabled: true
+ - name: kubeadm.service
+ enabled: true
+ dropins:
+ - name: 10-flatcar.conf
+ contents: |
+ [Unit]
+ Requires=containerd.service coreos-metadata.service
+ After=containerd.service coreos-metadata.service
+
+ [Service]
+ EnvironmentFile=/run/metadata/flatcar
+ preKubeadmCommands:
+ - export COREOS_OPENSTACK_HOSTNAME=$${COREOS_OPENSTACK_HOSTNAME%.*}
+ - envsubst < /etc/kubeadm.yml > /etc/kubeadm.yml.tmp
+ - mv /etc/kubeadm.yml.tmp /etc/kubeadm.yml
+---
+apiVersion: bootstrap.cluster.x-k8s.io/v1beta1
+kind: KubeadmConfigTemplate
+metadata:
+ name: ${CLUSTER_NAME}-md-0
+spec:
+ template:
+ spec:
+ joinConfiguration:
+ nodeRegistration:
+ name: $${COREOS_OPENSTACK_HOSTNAME}
+ kubeletExtraArgs:
+ # Fixme(lentzi90): This is here just to override the value set in the default
+ # kustomization. It will be replaced with a value that works for flatcar in
+ # https://github.com/kubernetes-sigs/cluster-api-provider-openstack/pull/1564
+ provider-id: null
+ preKubeadmCommands:
+ - export COREOS_OPENSTACK_HOSTNAME=$${COREOS_OPENSTACK_HOSTNAME%.*}
+ - envsubst < /etc/kubeadm.yml > /etc/kubeadm.yml.tmp
+ - mv /etc/kubeadm.yml.tmp /etc/kubeadm.yml
+ format: ignition
+ ignition:
+ containerLinuxConfig:
+ additionalConfig: |
+ systemd:
+ units:
+ - name: coreos-metadata-sshkeys@.service
+ enabled: true
+ - name: kubeadm.service
+ enabled: true
+ dropins:
+ - name: 10-flatcar.conf
+ contents: |
+ [Unit]
+ Requires=containerd.service coreos-metadata.service
+ After=containerd.service coreos-metadata.service
+
+ [Service]
+ EnvironmentFile=/run/metadata/flatcar
+---
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+kind: OpenStackMachineTemplate
+metadata:
+ name: ${CLUSTER_NAME}-md-0
+spec:
+ template:
+ spec:
+ image: ${OPENSTACK_FLATCAR_IMAGE_NAME}
+---
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+kind: OpenStackMachineTemplate
+metadata:
+ name: ${CLUSTER_NAME}-control-plane
+spec:
+ template:
+ spec:
+ image: ${OPENSTACK_FLATCAR_IMAGE_NAME}
diff --git a/kustomize/v1alpha8/without-lb/kustomization.yaml b/kustomize/v1alpha8/without-lb/kustomization.yaml
new file mode 100644
index 0000000000..b12f7e5db4
--- /dev/null
+++ b/kustomize/v1alpha8/without-lb/kustomization.yaml
@@ -0,0 +1,6 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+resources:
+- ../default
+patches:
+- path: patch-without-lb.yaml
diff --git a/kustomize/v1alpha8/without-lb/patch-without-lb.yaml b/kustomize/v1alpha8/without-lb/patch-without-lb.yaml
new file mode 100644
index 0000000000..57166c05e2
--- /dev/null
+++ b/kustomize/v1alpha8/without-lb/patch-without-lb.yaml
@@ -0,0 +1,15 @@
+---
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+kind: OpenStackCluster
+metadata:
+ name: ${CLUSTER_NAME}
+spec:
+ apiServerLoadBalancer:
+ $patch: delete
+---
+apiVersion: controlplane.cluster.x-k8s.io/v1beta1
+kind: KubeadmControlPlane
+metadata:
+ name: "${CLUSTER_NAME}-control-plane"
+spec:
+ replicas: 1
diff --git a/main.go b/main.go
index 957a623827..62ad0a04b4 100644
--- a/main.go
+++ b/main.go
@@ -44,7 +44,8 @@ import (
infrav1alpha5 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha5"
infrav1alpha6 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha6"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
+ infrav1alpha7 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
"sigs.k8s.io/cluster-api-provider-openstack/controllers"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/metrics"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/record"
@@ -84,6 +85,7 @@ func init() {
_ = infrav1.AddToScheme(scheme)
_ = infrav1alpha5.AddToScheme(scheme)
_ = infrav1alpha6.AddToScheme(scheme)
+ _ = infrav1alpha7.AddToScheme(scheme)
// +kubebuilder:scaffold:scheme
metrics.RegisterAPIPrometheusMetrics()
diff --git a/pkg/clients/mock/compute.go b/pkg/clients/mock/compute.go
index 7204858e69..93573cd5b2 100644
--- a/pkg/clients/mock/compute.go
+++ b/pkg/clients/mock/compute.go
@@ -1,5 +1,5 @@
/*
-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/pkg/clients/mock/image.go b/pkg/clients/mock/image.go
index c0dab59cc9..890e2f01a7 100644
--- a/pkg/clients/mock/image.go
+++ b/pkg/clients/mock/image.go
@@ -1,5 +1,5 @@
/*
-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/pkg/clients/mock/loadbalancer.go b/pkg/clients/mock/loadbalancer.go
index 2588cbeaea..8958def90f 100644
--- a/pkg/clients/mock/loadbalancer.go
+++ b/pkg/clients/mock/loadbalancer.go
@@ -1,5 +1,5 @@
/*
-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/pkg/clients/mock/network.go b/pkg/clients/mock/network.go
index 091a89f3b7..1493055a01 100644
--- a/pkg/clients/mock/network.go
+++ b/pkg/clients/mock/network.go
@@ -1,5 +1,5 @@
/*
-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/pkg/clients/mock/volume.go b/pkg/clients/mock/volume.go
index 511ed06cd1..91237deb21 100644
--- a/pkg/clients/mock/volume.go
+++ b/pkg/clients/mock/volume.go
@@ -1,5 +1,5 @@
/*
-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/pkg/cloud/services/compute/instance.go b/pkg/cloud/services/compute/instance.go
index c6b70af87e..3c3710ee76 100644
--- a/pkg/cloud/services/compute/instance.go
+++ b/pkg/cloud/services/compute/instance.go
@@ -35,7 +35,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/wait"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/cloud/services/networking"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/record"
diff --git a/pkg/cloud/services/compute/instance_test.go b/pkg/cloud/services/compute/instance_test.go
index cafc9e3edc..814fd807a9 100644
--- a/pkg/cloud/services/compute/instance_test.go
+++ b/pkg/cloud/services/compute/instance_test.go
@@ -45,7 +45,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/utils/pointer"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
"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/networking"
diff --git a/pkg/cloud/services/compute/instance_types.go b/pkg/cloud/services/compute/instance_types.go
index 0524e79774..d7b5634605 100644
--- a/pkg/cloud/services/compute/instance_types.go
+++ b/pkg/cloud/services/compute/instance_types.go
@@ -24,7 +24,7 @@ import (
"github.com/go-logr/logr"
corev1 "k8s.io/api/core/v1"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients"
)
diff --git a/pkg/cloud/services/loadbalancer/loadbalancer.go b/pkg/cloud/services/loadbalancer/loadbalancer.go
index 780f7c5426..e395373c66 100644
--- a/pkg/cloud/services/loadbalancer/loadbalancer.go
+++ b/pkg/cloud/services/loadbalancer/loadbalancer.go
@@ -31,7 +31,7 @@ import (
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
"sigs.k8s.io/cluster-api/util"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/record"
capoerrors "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/errors"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/names"
diff --git a/pkg/cloud/services/loadbalancer/loadbalancer_test.go b/pkg/cloud/services/loadbalancer/loadbalancer_test.go
index 6b78f1c1bc..4eb4737712 100644
--- a/pkg/cloud/services/loadbalancer/loadbalancer_test.go
+++ b/pkg/cloud/services/loadbalancer/loadbalancer_test.go
@@ -29,7 +29,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/providers"
. "github.com/onsi/gomega"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/mock"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
)
diff --git a/pkg/cloud/services/networking/floatingip.go b/pkg/cloud/services/networking/floatingip.go
index 9cc0b971b7..61b7e77d94 100644
--- a/pkg/cloud/services/networking/floatingip.go
+++ b/pkg/cloud/services/networking/floatingip.go
@@ -24,7 +24,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/wait"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/metrics"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/record"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/names"
diff --git a/pkg/cloud/services/networking/floatingip_test.go b/pkg/cloud/services/networking/floatingip_test.go
index a47c26d8b0..06c1fdc005 100644
--- a/pkg/cloud/services/networking/floatingip_test.go
+++ b/pkg/cloud/services/networking/floatingip_test.go
@@ -23,7 +23,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips"
. "github.com/onsi/gomega"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/mock"
)
diff --git a/pkg/cloud/services/networking/network.go b/pkg/cloud/services/networking/network.go
index 53516a2ab6..031d0b053c 100644
--- a/pkg/cloud/services/networking/network.go
+++ b/pkg/cloud/services/networking/network.go
@@ -25,7 +25,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
"github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/metrics"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/record"
capoerrors "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/errors"
diff --git a/pkg/cloud/services/networking/network_test.go b/pkg/cloud/services/networking/network_test.go
index 9191e5f48c..f01bf859da 100644
--- a/pkg/cloud/services/networking/network_test.go
+++ b/pkg/cloud/services/networking/network_test.go
@@ -26,7 +26,7 @@ import (
. "github.com/onsi/gomega"
"k8s.io/utils/pointer"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/mock"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
)
diff --git a/pkg/cloud/services/networking/port.go b/pkg/cloud/services/networking/port.go
index e3e9b0d8dd..4c213851f8 100644
--- a/pkg/cloud/services/networking/port.go
+++ b/pkg/cloud/services/networking/port.go
@@ -28,7 +28,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/wait"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/record"
capoerrors "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/errors"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/names"
diff --git a/pkg/cloud/services/networking/port_test.go b/pkg/cloud/services/networking/port_test.go
index d0e2f9ec91..962ac2256d 100644
--- a/pkg/cloud/services/networking/port_test.go
+++ b/pkg/cloud/services/networking/port_test.go
@@ -28,7 +28,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
. "github.com/onsi/gomega"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/mock"
)
diff --git a/pkg/cloud/services/networking/router.go b/pkg/cloud/services/networking/router.go
index 49eb9abc95..021617c060 100644
--- a/pkg/cloud/services/networking/router.go
+++ b/pkg/cloud/services/networking/router.go
@@ -24,7 +24,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
"github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/record"
capoerrors "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/errors"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/names"
diff --git a/pkg/cloud/services/networking/securitygroups.go b/pkg/cloud/services/networking/securitygroups.go
index ddea470128..e2a5617de6 100644
--- a/pkg/cloud/services/networking/securitygroups.go
+++ b/pkg/cloud/services/networking/securitygroups.go
@@ -23,7 +23,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/record"
)
diff --git a/pkg/cloud/services/networking/securitygroups_rules.go b/pkg/cloud/services/networking/securitygroups_rules.go
index 8fe3966323..5889867127 100644
--- a/pkg/cloud/services/networking/securitygroups_rules.go
+++ b/pkg/cloud/services/networking/securitygroups_rules.go
@@ -17,7 +17,7 @@ limitations under the License.
package networking
import (
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
)
var defaultRules = []infrav1.SecurityGroupRule{
diff --git a/pkg/cloud/services/networking/trunk_test.go b/pkg/cloud/services/networking/trunk_test.go
index 1b9d74e64e..24c6bfb719 100644
--- a/pkg/cloud/services/networking/trunk_test.go
+++ b/pkg/cloud/services/networking/trunk_test.go
@@ -23,7 +23,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/trunks"
. "github.com/onsi/gomega"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/mock"
)
diff --git a/pkg/scope/mock.go b/pkg/scope/mock.go
index dac09d5ff7..c6b68248e5 100644
--- a/pkg/scope/mock.go
+++ b/pkg/scope/mock.go
@@ -25,7 +25,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/identity/v3/tokens"
"sigs.k8s.io/controller-runtime/pkg/client"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/mock"
)
diff --git a/pkg/scope/provider.go b/pkg/scope/provider.go
index 433c10faaa..972d2ac75c 100644
--- a/pkg/scope/provider.go
+++ b/pkg/scope/provider.go
@@ -37,7 +37,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/yaml"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/hash"
"sigs.k8s.io/cluster-api-provider-openstack/version"
diff --git a/pkg/scope/scope.go b/pkg/scope/scope.go
index 5a2afd4e7a..4b0340be01 100644
--- a/pkg/scope/scope.go
+++ b/pkg/scope/scope.go
@@ -24,7 +24,7 @@ import (
"k8s.io/apimachinery/pkg/util/cache"
"sigs.k8s.io/controller-runtime/pkg/client"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients"
)
diff --git a/templates/cluster-template-flatcar.yaml b/templates/cluster-template-flatcar.yaml
index c73cbd996c..cb3cf1b0eb 100644
--- a/templates/cluster-template-flatcar.yaml
+++ b/templates/cluster-template-flatcar.yaml
@@ -60,7 +60,7 @@ spec:
kind: KubeadmControlPlane
name: ${CLUSTER_NAME}-control-plane
infrastructureRef:
- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+ apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackCluster
name: ${CLUSTER_NAME}
---
@@ -83,7 +83,7 @@ spec:
clusterName: ${CLUSTER_NAME}
failureDomain: ${OPENSTACK_FAILURE_DOMAIN}
infrastructureRef:
- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+ apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
name: ${CLUSTER_NAME}-md-0
version: ${KUBERNETES_VERSION}
@@ -137,13 +137,13 @@ spec:
- mv /etc/kubeadm.yml.tmp /etc/kubeadm.yml
machineTemplate:
infrastructureRef:
- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+ apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
name: ${CLUSTER_NAME}-control-plane
replicas: ${CONTROL_PLANE_MACHINE_COUNT}
version: ${KUBERNETES_VERSION}
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackCluster
metadata:
name: ${CLUSTER_NAME}
@@ -158,7 +158,7 @@ spec:
managedSecurityGroups: true
nodeCidr: 10.6.0.0/24
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
metadata:
name: ${CLUSTER_NAME}-control-plane
@@ -173,7 +173,7 @@ spec:
image: ${OPENSTACK_FLATCAR_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
metadata:
name: ${CLUSTER_NAME}-md-0
diff --git a/templates/cluster-template-without-lb.yaml b/templates/cluster-template-without-lb.yaml
index 48dfefe23f..4081e804ff 100644
--- a/templates/cluster-template-without-lb.yaml
+++ b/templates/cluster-template-without-lb.yaml
@@ -38,7 +38,7 @@ spec:
kind: KubeadmControlPlane
name: ${CLUSTER_NAME}-control-plane
infrastructureRef:
- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+ apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackCluster
name: ${CLUSTER_NAME}
---
@@ -61,7 +61,7 @@ spec:
clusterName: ${CLUSTER_NAME}
failureDomain: ${OPENSTACK_FAILURE_DOMAIN}
infrastructureRef:
- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+ apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
name: ${CLUSTER_NAME}-md-0
version: ${KUBERNETES_VERSION}
@@ -94,13 +94,13 @@ spec:
name: '{{ local_hostname }}'
machineTemplate:
infrastructureRef:
- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+ apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
name: ${CLUSTER_NAME}-control-plane
replicas: 1
version: ${KUBERNETES_VERSION}
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackCluster
metadata:
name: ${CLUSTER_NAME}
@@ -115,7 +115,7 @@ spec:
managedSecurityGroups: true
nodeCidr: 10.6.0.0/24
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
metadata:
name: ${CLUSTER_NAME}-control-plane
@@ -130,7 +130,7 @@ spec:
image: ${OPENSTACK_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
metadata:
name: ${CLUSTER_NAME}-md-0
diff --git a/templates/cluster-template.yaml b/templates/cluster-template.yaml
index 8a971a591a..71f9f5695c 100644
--- a/templates/cluster-template.yaml
+++ b/templates/cluster-template.yaml
@@ -38,7 +38,7 @@ spec:
kind: KubeadmControlPlane
name: ${CLUSTER_NAME}-control-plane
infrastructureRef:
- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+ apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackCluster
name: ${CLUSTER_NAME}
---
@@ -61,7 +61,7 @@ spec:
clusterName: ${CLUSTER_NAME}
failureDomain: ${OPENSTACK_FAILURE_DOMAIN}
infrastructureRef:
- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+ apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
name: ${CLUSTER_NAME}-md-0
version: ${KUBERNETES_VERSION}
@@ -94,13 +94,13 @@ spec:
name: '{{ local_hostname }}'
machineTemplate:
infrastructureRef:
- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+ apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
name: ${CLUSTER_NAME}-control-plane
replicas: ${CONTROL_PLANE_MACHINE_COUNT}
version: ${KUBERNETES_VERSION}
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackCluster
metadata:
name: ${CLUSTER_NAME}
@@ -117,7 +117,7 @@ spec:
managedSecurityGroups: true
nodeCidr: 10.6.0.0/24
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
metadata:
name: ${CLUSTER_NAME}-control-plane
@@ -132,7 +132,7 @@ spec:
image: ${OPENSTACK_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
metadata:
name: ${CLUSTER_NAME}-md-0
diff --git a/test/e2e/data/e2e_conf.yaml b/test/e2e/data/e2e_conf.yaml
index b1e30eb1ad..f17655b66f 100644
--- a/test/e2e/data/e2e_conf.yaml
+++ b/test/e2e/data/e2e_conf.yaml
@@ -139,6 +139,20 @@ providers:
new: "--v=4"
- old: "--leader-elect"
new: "--leader-elect=false\n - --sync-period=1m"
+ - name: v0.8.0
+ value: "https://github.com/kubernetes-sigs/cluster-api-provider-openstack/releases/download/v0.8.0/infrastructure-components.yaml"
+ type: url
+ contract: v1beta1
+ files:
+ - sourcePath: "../data/shared/v1beta1_provider/metadata.yaml"
+ - sourcePath: "./infrastructure-openstack-no-artifact/cluster-template.yaml"
+ replacements:
+ - old: "imagePullPolicy: Always"
+ new: "imagePullPolicy: IfNotPresent"
+ - old: "--v=2"
+ new: "--v=4"
+ - old: "--leader-elect"
+ new: "--leader-elect=false\n - --sync-period=1m"
- name: v0.9.99
value: ../../../config/default
# This is the upcoming version.
diff --git a/test/e2e/data/kustomize/default/kustomization.yaml b/test/e2e/data/kustomize/default/kustomization.yaml
index 9401c28fd2..b648538489 100644
--- a/test/e2e/data/kustomize/default/kustomization.yaml
+++ b/test/e2e/data/kustomize/default/kustomization.yaml
@@ -1,7 +1,7 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
-- ../../../../../kustomize/v1alpha7/default
+- ../../../../../kustomize/v1alpha8/default
components:
- ../common-patches/cni
- ../upgrade-patches
diff --git a/test/e2e/data/kustomize/flatcar/kustomization.yaml b/test/e2e/data/kustomize/flatcar/kustomization.yaml
index 2f3f5d1359..2d7874e6ac 100644
--- a/test/e2e/data/kustomize/flatcar/kustomization.yaml
+++ b/test/e2e/data/kustomize/flatcar/kustomization.yaml
@@ -1,7 +1,7 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
-- ../../../../../kustomize/v1alpha7/flatcar
+- ../../../../../kustomize/v1alpha8/flatcar
components:
- ../common-patches/cni
diff --git a/test/e2e/data/kustomize/k8s-upgrade/kcp-patch.yaml b/test/e2e/data/kustomize/k8s-upgrade/kcp-patch.yaml
index b3561dc8e1..0eb4b5f713 100644
--- a/test/e2e/data/kustomize/k8s-upgrade/kcp-patch.yaml
+++ b/test/e2e/data/kustomize/k8s-upgrade/kcp-patch.yaml
@@ -5,6 +5,6 @@ metadata:
spec:
machineTemplate:
infrastructureRef:
- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+ apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
name: ${CLUSTER_NAME}-upgrade-from-control-plane
diff --git a/test/e2e/data/kustomize/k8s-upgrade/md-patch.yaml b/test/e2e/data/kustomize/k8s-upgrade/md-patch.yaml
index bde877415b..fb59a3df2f 100644
--- a/test/e2e/data/kustomize/k8s-upgrade/md-patch.yaml
+++ b/test/e2e/data/kustomize/k8s-upgrade/md-patch.yaml
@@ -6,6 +6,6 @@ spec:
template:
spec:
infrastructureRef:
- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+ apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
name: ${CLUSTER_NAME}-upgrade-from-md-0
diff --git a/test/e2e/data/kustomize/k8s-upgrade/upgrade-from-template.yaml b/test/e2e/data/kustomize/k8s-upgrade/upgrade-from-template.yaml
index fe20fcc5f2..4bba2d5165 100644
--- a/test/e2e/data/kustomize/k8s-upgrade/upgrade-from-template.yaml
+++ b/test/e2e/data/kustomize/k8s-upgrade/upgrade-from-template.yaml
@@ -1,5 +1,5 @@
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
metadata:
name: ${CLUSTER_NAME}-upgrade-from-control-plane
@@ -16,7 +16,7 @@ spec:
tags:
- control-plane
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
metadata:
name: ${CLUSTER_NAME}-upgrade-from-md-0
diff --git a/test/e2e/data/kustomize/k8s-upgrade/upgrade-to-template.yaml b/test/e2e/data/kustomize/k8s-upgrade/upgrade-to-template.yaml
index 734946741d..035aad375a 100644
--- a/test/e2e/data/kustomize/k8s-upgrade/upgrade-to-template.yaml
+++ b/test/e2e/data/kustomize/k8s-upgrade/upgrade-to-template.yaml
@@ -4,7 +4,7 @@
# See CONTROL_PLANE_MACHINE_TEMPLATE_UPGRADE_TO and WORKERS_MACHINE_TEMPLATE_UPGRADE_TO
# in the e2e config.
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
metadata:
name: upgrade-to-control-plane
@@ -23,7 +23,7 @@ spec:
tags:
- control-plane
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
metadata:
name: upgrade-to-md-0
diff --git a/test/e2e/data/kustomize/v1alpha7/kustomization.yaml b/test/e2e/data/kustomize/v1alpha7/kustomization.yaml
new file mode 100644
index 0000000000..3ad33a43b0
--- /dev/null
+++ b/test/e2e/data/kustomize/v1alpha7/kustomization.yaml
@@ -0,0 +1,22 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+resources:
+- ../../../../../kustomize/v1alpha6/external-cloud-provider
+
+components:
+- ../common-patches/cni
+- ../common-patches/ccm
+
+patches:
+- patch: |-
+ apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+ kind: OpenStackMachineTemplate
+ metadata:
+ name: ignored
+ spec:
+ template:
+ spec:
+ networks:
+ - {}
+ target:
+ kind: OpenStackMachineTemplate
diff --git a/test/e2e/data/kustomize/without-lb/kustomization.yaml b/test/e2e/data/kustomize/without-lb/kustomization.yaml
index 76ea83bb0f..dd2efc8c50 100644
--- a/test/e2e/data/kustomize/without-lb/kustomization.yaml
+++ b/test/e2e/data/kustomize/without-lb/kustomization.yaml
@@ -1,7 +1,7 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
-- ../../../../../kustomize/v1alpha7/without-lb
+- ../../../../../kustomize/v1alpha8/without-lb
components:
- ../common-patches/cni
diff --git a/test/e2e/shared/common.go b/test/e2e/shared/common.go
index 06faa87a43..8f1465e23c 100644
--- a/test/e2e/shared/common.go
+++ b/test/e2e/shared/common.go
@@ -40,7 +40,7 @@ import (
"sigs.k8s.io/cluster-api/util"
"sigs.k8s.io/controller-runtime/pkg/client"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
)
func SetupSpecNamespace(ctx context.Context, specName string, e2eCtx *E2EContext) *corev1.Namespace {
diff --git a/test/e2e/shared/defaults.go b/test/e2e/shared/defaults.go
index 857bd134fa..9c82de4f04 100644
--- a/test/e2e/shared/defaults.go
+++ b/test/e2e/shared/defaults.go
@@ -26,7 +26,7 @@ import (
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
"sigs.k8s.io/cluster-api/test/framework"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
)
const (
@@ -50,6 +50,7 @@ const (
FlavorMultiAZ = "multi-az"
FlavorV1alpha5 = "v1alpha5"
FlavorV1alpha6 = "v1alpha6"
+ FlavorV1alpha7 = "v1alpha7"
FlavorMDRemediation = "md-remediation"
FlavorKCPRemediation = "kcp-remediation"
FlavorFlatcar = "flatcar"
diff --git a/test/e2e/shared/openstack.go b/test/e2e/shared/openstack.go
index 056dd37e70..4d46837775 100644
--- a/test/e2e/shared/openstack.go
+++ b/test/e2e/shared/openstack.go
@@ -51,7 +51,7 @@ import (
"k8s.io/apimachinery/pkg/util/sets"
"sigs.k8s.io/yaml"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
"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"
diff --git a/test/e2e/suites/e2e/clusterctl_upgrade_test.go b/test/e2e/suites/e2e/clusterctl_upgrade_test.go
index 460f19a58b..e31c1c6256 100644
--- a/test/e2e/suites/e2e/clusterctl_upgrade_test.go
+++ b/test/e2e/suites/e2e/clusterctl_upgrade_test.go
@@ -75,3 +75,26 @@ var _ = Describe("When testing clusterctl upgrades (v0.7=>current) [clusterctl-u
}
})
})
+
+var _ = Describe("When testing clusterctl upgrades (v0.8=>current) [clusterctl-upgrade]", func() {
+ ctx := context.TODO()
+ shared.SetEnvVar("DOWNLOAD_E2E_IMAGE", "true", false)
+
+ capi_e2e.ClusterctlUpgradeSpec(ctx, func() capi_e2e.ClusterctlUpgradeSpecInput {
+ return capi_e2e.ClusterctlUpgradeSpecInput{
+ E2EConfig: e2eCtx.E2EConfig,
+ ClusterctlConfigPath: e2eCtx.Environment.ClusterctlConfigPath,
+ BootstrapClusterProxy: e2eCtx.Environment.BootstrapClusterProxy,
+ ArtifactFolder: e2eCtx.Settings.ArtifactFolder,
+ SkipCleanup: false,
+ InitWithBinary: "https://github.com/kubernetes-sigs/cluster-api/releases/download/" + OldCAPIVersion + "/clusterctl-{OS}-{ARCH}",
+ InitWithProvidersContract: "v1beta1",
+ InitWithInfrastructureProviders: []string{"openstack:v0.8.0"},
+ InitWithCoreProvider: "cluster-api:" + OldCAPIVersion,
+ InitWithBootstrapProviders: []string{"kubeadm:" + OldCAPIVersion},
+ InitWithControlPlaneProviders: []string{"kubeadm:" + OldCAPIVersion},
+ MgmtFlavor: shared.FlavorDefault,
+ WorkloadFlavor: shared.FlavorV1alpha7,
+ }
+ })
+})
diff --git a/test/e2e/suites/e2e/e2e_test.go b/test/e2e/suites/e2e/e2e_test.go
index c851054749..90930a9fd3 100644
--- a/test/e2e/suites/e2e/e2e_test.go
+++ b/test/e2e/suites/e2e/e2e_test.go
@@ -56,7 +56,7 @@ import (
"sigs.k8s.io/cluster-api/test/framework/clusterctl"
crclient "sigs.k8s.io/controller-runtime/pkg/client"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
capoerrors "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/errors"
"sigs.k8s.io/cluster-api-provider-openstack/test/e2e/shared"
)
From 9af5f88f36988ca793c4f9bf45be0f3137d323e8 Mon Sep 17 00:00:00 2001
From: Tobias Giese
Date: Mon, 18 Dec 2023 10:59:26 +0100
Subject: [PATCH 007/180] Remove tobiasgiese from maintainers
Signed-off-by: Tobias Giese
---
OWNERS | 1 +
OWNERS_ALIASES | 1 -
2 files changed, 1 insertion(+), 1 deletion(-)
diff --git a/OWNERS b/OWNERS
index 8b5bf82409..d136d4a439 100644
--- a/OWNERS
+++ b/OWNERS
@@ -19,3 +19,4 @@ emeritus_approvers:
- sbueringer
- hidekazuna
- chrischdi
+ - tobiasgiese
diff --git a/OWNERS_ALIASES b/OWNERS_ALIASES
index c9a9af82e8..f45247d92b 100644
--- a/OWNERS_ALIASES
+++ b/OWNERS_ALIASES
@@ -23,6 +23,5 @@ aliases:
- lentzi90
- mdbooth
- seanschneeweiss
- - tobiasgiese
cluster-api-openstack-reviewers:
- dulek
From a1b9e4eaf0d524ba601cbbfec1177f3ad22db7f5 Mon Sep 17 00:00:00 2001
From: Tobias Giese
Date: Mon, 18 Dec 2023 11:07:00 +0100
Subject: [PATCH 008/180] Remove seanschneeweiss from maintainers
Signed-off-by: Tobias Giese
---
OWNERS | 1 +
OWNERS_ALIASES | 1 -
2 files changed, 1 insertion(+), 1 deletion(-)
diff --git a/OWNERS b/OWNERS
index d136d4a439..ea64e2e7b8 100644
--- a/OWNERS
+++ b/OWNERS
@@ -20,3 +20,4 @@ emeritus_approvers:
- hidekazuna
- chrischdi
- tobiasgiese
+ - seanschneeweiss
diff --git a/OWNERS_ALIASES b/OWNERS_ALIASES
index f45247d92b..146f103863 100644
--- a/OWNERS_ALIASES
+++ b/OWNERS_ALIASES
@@ -22,6 +22,5 @@ aliases:
- jichenjc
- lentzi90
- mdbooth
- - seanschneeweiss
cluster-api-openstack-reviewers:
- dulek
From b979d9b40c04342185f1bd5dddffe9b636eb98ec Mon Sep 17 00:00:00 2001
From: Mathieu Tortuyaux
Date: Wed, 11 Oct 2023 11:30:24 +0200
Subject: [PATCH 009/180] templates: add flatcar-sysext template
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This template allows to use a plain Flatcar image from the Flatcar
release server without building with the image-builder.
This template will consume Kubernetes systemd-sysext image from the
flatcar/sysext-bakery release artifacts.
This template will emit a /run/reboot-required file flag when a new
Kubernetes release has been downloaded and that we need to coordinate
the reboot of the node using Kured for example.
Signed-off-by: Mathieu Tortuyaux
Co-authored-by: Kai Lüke
---
Makefile | 6 +-
.../flatcar-sysext/kustomization.yaml | 7 +
.../flatcar-sysext/patch-flatcar.yaml | 185 ++++++++++++
.../cluster-template-flatcar-sysext.yaml | 265 ++++++++++++++++++
4 files changed, 461 insertions(+), 2 deletions(-)
create mode 100644 kustomize/v1alpha7/flatcar-sysext/kustomization.yaml
create mode 100644 kustomize/v1alpha7/flatcar-sysext/patch-flatcar.yaml
create mode 100644 templates/cluster-template-flatcar-sysext.yaml
diff --git a/Makefile b/Makefile
index 4ecf6aaccf..c1968fe83a 100644
--- a/Makefile
+++ b/Makefile
@@ -158,7 +158,8 @@ 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)
# Currently no templates that require CI artifacts
# $(addprefix $(E2E_TEMPLATES_DIR)/, add-templates-here.yaml) \
@@ -406,7 +407,8 @@ 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/v1alpha8/default $(KUSTOMIZE) FORCE
$(KUSTOMIZE) build "$<" > "$@"
diff --git a/kustomize/v1alpha7/flatcar-sysext/kustomization.yaml b/kustomize/v1alpha7/flatcar-sysext/kustomization.yaml
new file mode 100644
index 0000000000..b5cb7540a4
--- /dev/null
+++ b/kustomize/v1alpha7/flatcar-sysext/kustomization.yaml
@@ -0,0 +1,7 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+resources:
+- ../default
+
+patches:
+- path: patch-flatcar.yaml
diff --git a/kustomize/v1alpha7/flatcar-sysext/patch-flatcar.yaml b/kustomize/v1alpha7/flatcar-sysext/patch-flatcar.yaml
new file mode 100644
index 0000000000..9f8b858c08
--- /dev/null
+++ b/kustomize/v1alpha7/flatcar-sysext/patch-flatcar.yaml
@@ -0,0 +1,185 @@
+---
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+kind: OpenStackCluster
+metadata:
+ name: ${CLUSTER_NAME}
+spec:
+ apiServerLoadBalancer:
+ $patch: delete
+---
+apiVersion: controlplane.cluster.x-k8s.io/v1beta1
+kind: KubeadmControlPlane
+metadata:
+ name: "${CLUSTER_NAME}-control-plane"
+spec:
+ replicas: ${CONTROL_PLANE_MACHINE_COUNT}
+ kubeadmConfigSpec:
+ joinConfiguration:
+ nodeRegistration:
+ name: $${COREOS_OPENSTACK_HOSTNAME}
+ kubeletExtraArgs:
+ provider-id: null
+ initConfiguration:
+ nodeRegistration:
+ name: $${COREOS_OPENSTACK_HOSTNAME}
+ kubeletExtraArgs:
+ # Fixme(lentzi90): This is here just to override the value set in the default
+ # kustomization. It will be replaced with a value that works for flatcar in
+ # https://github.com/kubernetes-sigs/cluster-api-provider-openstack/pull/1564
+ provider-id: null
+ format: ignition
+ ignition:
+ containerLinuxConfig:
+ additionalConfig: |
+ storage:
+ links:
+ - path: /etc/extensions/kubernetes.raw
+ hard: false
+ target: /opt/extensions/kubernetes/kubernetes-${KUBERNETES_VERSION}-x86-64.raw
+ files:
+ - path: /etc/sysupdate.kubernetes.d/kubernetes-${KUBERNETES_VERSION%.*}.conf
+ mode: 0644
+ contents:
+ remote:
+ url: https://github.com/flatcar/sysext-bakery/releases/download/latest/kubernetes-${KUBERNETES_VERSION%.*}.conf
+ - path: /etc/sysupdate.d/noop.conf
+ mode: 0644
+ contents:
+ remote:
+ url: https://github.com/flatcar/sysext-bakery/releases/download/latest/noop.conf
+ - path: /opt/extensions/kubernetes/kubernetes-${KUBERNETES_VERSION}-x86-64.raw
+ contents:
+ remote:
+ url: https://github.com/flatcar/sysext-bakery/releases/download/latest/kubernetes-${KUBERNETES_VERSION}-x86-64.raw
+ systemd:
+ units:
+ - name: systemd-sysupdate.service
+ dropins:
+ - name: kubernetes.conf
+ contents: |
+ [Service]
+ ExecStartPre=/usr/bin/sh -c "readlink --canonicalize /etc/extensions/kubernetes.raw > /tmp/kubernetes"
+ ExecStartPre=/usr/lib/systemd/systemd-sysupdate -C kubernetes update
+ ExecStartPost=/usr/bin/sh -c "readlink --canonicalize /etc/extensions/kubernetes.raw > /tmp/kubernetes-new"
+ ExecStartPost=/usr/bin/sh -c "if ! cmp --silent /tmp/kubernetes /tmp/kubernetes-new; then touch /run/reboot-required; fi"
+ - name: update-engine.service
+ # Set this to 'false' if you want to enable Flatcar auto-update
+ mask: ${FLATCAR_DISABLE_AUTO_UPDATE:=true}
+ - name: locksmithd.service
+ # NOTE: To coordinate the node reboot in this context, we recommend to use Kured.
+ mask: true
+ - name: systemd-sysupdate.timer
+ # Set this to 'true' if you want to enable the Kubernetes auto-update.
+ # NOTE: Only patches version will be pulled.
+ enabled: false
+ - name: coreos-metadata-sshkeys@.service
+ enabled: true
+ - name: kubeadm.service
+ enabled: true
+ dropins:
+ - name: 10-flatcar.conf
+ contents: |
+ [Unit]
+ Requires=containerd.service coreos-metadata.service
+ After=containerd.service coreos-metadata.service
+ [Service]
+ EnvironmentFile=/run/metadata/flatcar
+ preKubeadmCommands:
+ - export COREOS_OPENSTACK_HOSTNAME=$${COREOS_OPENSTACK_HOSTNAME%.*}
+ - envsubst < /etc/kubeadm.yml > /etc/kubeadm.yml.tmp
+ - mv /etc/kubeadm.yml.tmp /etc/kubeadm.yml
+---
+apiVersion: bootstrap.cluster.x-k8s.io/v1beta1
+kind: KubeadmConfigTemplate
+metadata:
+ name: ${CLUSTER_NAME}-md-0
+spec:
+ template:
+ spec:
+ joinConfiguration:
+ nodeRegistration:
+ name: $${COREOS_OPENSTACK_HOSTNAME}
+ kubeletExtraArgs:
+ # Fixme(lentzi90): This is here just to override the value set in the default
+ # kustomization. It will be replaced with a value that works for flatcar in
+ # https://github.com/kubernetes-sigs/cluster-api-provider-openstack/pull/1564
+ provider-id: null
+ preKubeadmCommands:
+ - export COREOS_OPENSTACK_HOSTNAME=$${COREOS_OPENSTACK_HOSTNAME%.*}
+ - envsubst < /etc/kubeadm.yml > /etc/kubeadm.yml.tmp
+ - mv /etc/kubeadm.yml.tmp /etc/kubeadm.yml
+ format: ignition
+ ignition:
+ containerLinuxConfig:
+ additionalConfig: |
+ storage:
+ links:
+ - path: /etc/extensions/kubernetes.raw
+ hard: false
+ target: /opt/extensions/kubernetes/kubernetes-${KUBERNETES_VERSION}-x86-64.raw
+ files:
+ - path: /etc/sysupdate.kubernetes.d/kubernetes-${KUBERNETES_VERSION%.*}.conf
+ mode: 0644
+ contents:
+ remote:
+ url: https://github.com/flatcar/sysext-bakery/releases/download/latest/kubernetes-${KUBERNETES_VERSION%.*}.conf
+ - path: /etc/sysupdate.d/noop.conf
+ mode: 0644
+ contents:
+ remote:
+ url: https://github.com/flatcar/sysext-bakery/releases/download/latest/noop.conf
+ - path: /opt/extensions/kubernetes/kubernetes-${KUBERNETES_VERSION}-x86-64.raw
+ contents:
+ remote:
+ url: https://github.com/flatcar/sysext-bakery/releases/download/latest/kubernetes-${KUBERNETES_VERSION}-x86-64.raw
+ systemd:
+ units:
+ - name: systemd-sysupdate.service
+ dropins:
+ - name: kubernetes.conf
+ contents: |
+ [Service]
+ ExecStartPre=/usr/bin/sh -c "readlink --canonicalize /etc/extensions/kubernetes.raw > /tmp/kubernetes"
+ ExecStartPre=/usr/lib/systemd/systemd-sysupdate -C kubernetes update
+ ExecStartPost=/usr/bin/sh -c "readlink --canonicalize /etc/extensions/kubernetes.raw > /tmp/kubernetes-new"
+ ExecStartPost=/usr/bin/sh -c "if ! cmp --silent /tmp/kubernetes /tmp/kubernetes-new; then touch /run/reboot-required; fi"
+ - name: update-engine.service
+ # Set this to 'false' if you want to enable Flatcar auto-update
+ mask: ${FLATCAR_DISABLE_AUTO_UPDATE:=true}
+ - name: locksmithd.service
+ # NOTE: To coordinate the node reboot in this context, we recommend to use Kured.
+ mask: true
+ - name: systemd-sysupdate.timer
+ # Set this to 'true' if you want to enable the Kubernetes auto-update.
+ # NOTE: Only patches version will be pulled.
+ enabled: false
+ - name: coreos-metadata-sshkeys@.service
+ enabled: true
+ - name: kubeadm.service
+ enabled: true
+ dropins:
+ - name: 10-flatcar.conf
+ contents: |
+ [Unit]
+ Requires=containerd.service coreos-metadata.service
+ After=containerd.service coreos-metadata.service
+ [Service]
+ EnvironmentFile=/run/metadata/flatcar
+---
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+kind: OpenStackMachineTemplate
+metadata:
+ name: ${CLUSTER_NAME}-md-0
+spec:
+ template:
+ spec:
+ image: ${FLATCAR_IMAGE_NAME}
+---
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+kind: OpenStackMachineTemplate
+metadata:
+ name: ${CLUSTER_NAME}-control-plane
+spec:
+ template:
+ spec:
+ image: ${FLATCAR_IMAGE_NAME}
diff --git a/templates/cluster-template-flatcar-sysext.yaml b/templates/cluster-template-flatcar-sysext.yaml
new file mode 100644
index 0000000000..fa0ef1bf02
--- /dev/null
+++ b/templates/cluster-template-flatcar-sysext.yaml
@@ -0,0 +1,265 @@
+apiVersion: v1
+data:
+ cacert: ${OPENSTACK_CLOUD_CACERT_B64}
+ clouds.yaml: ${OPENSTACK_CLOUD_YAML_B64}
+kind: Secret
+metadata:
+ labels:
+ clusterctl.cluster.x-k8s.io/move: "true"
+ name: ${CLUSTER_NAME}-cloud-config
+---
+apiVersion: bootstrap.cluster.x-k8s.io/v1beta1
+kind: KubeadmConfigTemplate
+metadata:
+ name: ${CLUSTER_NAME}-md-0
+spec:
+ template:
+ spec:
+ files: []
+ format: ignition
+ ignition:
+ containerLinuxConfig:
+ additionalConfig: |
+ storage:
+ links:
+ - path: /etc/extensions/kubernetes.raw
+ hard: false
+ target: /opt/extensions/kubernetes/kubernetes-${KUBERNETES_VERSION}-x86-64.raw
+ files:
+ - path: /etc/sysupdate.kubernetes.d/kubernetes-${KUBERNETES_VERSION%.*}.conf
+ mode: 0644
+ contents:
+ remote:
+ url: https://github.com/flatcar/sysext-bakery/releases/download/latest/kubernetes-${KUBERNETES_VERSION%.*}.conf
+ - path: /etc/sysupdate.d/noop.conf
+ mode: 0644
+ contents:
+ remote:
+ url: https://github.com/flatcar/sysext-bakery/releases/download/latest/noop.conf
+ - path: /opt/extensions/kubernetes/kubernetes-${KUBERNETES_VERSION}-x86-64.raw
+ contents:
+ remote:
+ url: https://github.com/flatcar/sysext-bakery/releases/download/latest/kubernetes-${KUBERNETES_VERSION}-x86-64.raw
+ systemd:
+ units:
+ - name: systemd-sysupdate.service
+ dropins:
+ - name: kubernetes.conf
+ contents: |
+ [Service]
+ ExecStartPre=/usr/bin/sh -c "readlink --canonicalize /etc/extensions/kubernetes.raw > /tmp/kubernetes"
+ ExecStartPre=/usr/lib/systemd/systemd-sysupdate -C kubernetes update
+ ExecStartPost=/usr/bin/sh -c "readlink --canonicalize /etc/extensions/kubernetes.raw > /tmp/kubernetes-new"
+ ExecStartPost=/usr/bin/sh -c "if ! cmp --silent /tmp/kubernetes /tmp/kubernetes-new; then touch /run/reboot-required; fi"
+ - name: update-engine.service
+ # Set this to 'false' if you want to enable Flatcar auto-update
+ mask: ${FLATCAR_DISABLE_AUTO_UPDATE:=true}
+ - name: locksmithd.service
+ # NOTE: To coordinate the node reboot in this context, we recommend to use Kured.
+ mask: true
+ - name: systemd-sysupdate.timer
+ # Set this to 'true' if you want to enable the Kubernetes auto-update.
+ # NOTE: Only patches version will be pulled.
+ enabled: false
+ - name: coreos-metadata-sshkeys@.service
+ enabled: true
+ - name: kubeadm.service
+ enabled: true
+ dropins:
+ - name: 10-flatcar.conf
+ contents: |
+ [Unit]
+ Requires=containerd.service coreos-metadata.service
+ After=containerd.service coreos-metadata.service
+ [Service]
+ EnvironmentFile=/run/metadata/flatcar
+ joinConfiguration:
+ nodeRegistration:
+ kubeletExtraArgs:
+ cloud-provider: external
+ name: $${COREOS_OPENSTACK_HOSTNAME}
+ preKubeadmCommands:
+ - export COREOS_OPENSTACK_HOSTNAME=$${COREOS_OPENSTACK_HOSTNAME%.*}
+ - envsubst < /etc/kubeadm.yml > /etc/kubeadm.yml.tmp
+ - mv /etc/kubeadm.yml.tmp /etc/kubeadm.yml
+---
+apiVersion: cluster.x-k8s.io/v1beta1
+kind: Cluster
+metadata:
+ name: ${CLUSTER_NAME}
+spec:
+ clusterNetwork:
+ pods:
+ cidrBlocks:
+ - 192.168.0.0/16
+ serviceDomain: cluster.local
+ controlPlaneRef:
+ apiVersion: controlplane.cluster.x-k8s.io/v1beta1
+ kind: KubeadmControlPlane
+ name: ${CLUSTER_NAME}-control-plane
+ infrastructureRef:
+ apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+ kind: OpenStackCluster
+ name: ${CLUSTER_NAME}
+---
+apiVersion: cluster.x-k8s.io/v1beta1
+kind: MachineDeployment
+metadata:
+ name: ${CLUSTER_NAME}-md-0
+spec:
+ clusterName: ${CLUSTER_NAME}
+ replicas: ${WORKER_MACHINE_COUNT}
+ selector:
+ matchLabels: null
+ template:
+ spec:
+ bootstrap:
+ configRef:
+ apiVersion: bootstrap.cluster.x-k8s.io/v1beta1
+ kind: KubeadmConfigTemplate
+ name: ${CLUSTER_NAME}-md-0
+ clusterName: ${CLUSTER_NAME}
+ failureDomain: ${OPENSTACK_FAILURE_DOMAIN}
+ infrastructureRef:
+ apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+ kind: OpenStackMachineTemplate
+ name: ${CLUSTER_NAME}-md-0
+ version: ${KUBERNETES_VERSION}
+---
+apiVersion: controlplane.cluster.x-k8s.io/v1beta1
+kind: KubeadmControlPlane
+metadata:
+ name: ${CLUSTER_NAME}-control-plane
+spec:
+ kubeadmConfigSpec:
+ clusterConfiguration:
+ apiServer:
+ extraArgs:
+ cloud-provider: external
+ controllerManager:
+ extraArgs:
+ cloud-provider: external
+ files: []
+ format: ignition
+ ignition:
+ containerLinuxConfig:
+ additionalConfig: |
+ storage:
+ links:
+ - path: /etc/extensions/kubernetes.raw
+ hard: false
+ target: /opt/extensions/kubernetes/kubernetes-${KUBERNETES_VERSION}-x86-64.raw
+ files:
+ - path: /etc/sysupdate.kubernetes.d/kubernetes-${KUBERNETES_VERSION%.*}.conf
+ mode: 0644
+ contents:
+ remote:
+ url: https://github.com/flatcar/sysext-bakery/releases/download/latest/kubernetes-${KUBERNETES_VERSION%.*}.conf
+ - path: /etc/sysupdate.d/noop.conf
+ mode: 0644
+ contents:
+ remote:
+ url: https://github.com/flatcar/sysext-bakery/releases/download/latest/noop.conf
+ - path: /opt/extensions/kubernetes/kubernetes-${KUBERNETES_VERSION}-x86-64.raw
+ contents:
+ remote:
+ url: https://github.com/flatcar/sysext-bakery/releases/download/latest/kubernetes-${KUBERNETES_VERSION}-x86-64.raw
+ systemd:
+ units:
+ - name: systemd-sysupdate.service
+ dropins:
+ - name: kubernetes.conf
+ contents: |
+ [Service]
+ ExecStartPre=/usr/bin/sh -c "readlink --canonicalize /etc/extensions/kubernetes.raw > /tmp/kubernetes"
+ ExecStartPre=/usr/lib/systemd/systemd-sysupdate -C kubernetes update
+ ExecStartPost=/usr/bin/sh -c "readlink --canonicalize /etc/extensions/kubernetes.raw > /tmp/kubernetes-new"
+ ExecStartPost=/usr/bin/sh -c "if ! cmp --silent /tmp/kubernetes /tmp/kubernetes-new; then touch /run/reboot-required; fi"
+ - name: update-engine.service
+ # Set this to 'false' if you want to enable Flatcar auto-update
+ mask: ${FLATCAR_DISABLE_AUTO_UPDATE:=true}
+ - name: locksmithd.service
+ # NOTE: To coordinate the node reboot in this context, we recommend to use Kured.
+ mask: true
+ - name: systemd-sysupdate.timer
+ # Set this to 'true' if you want to enable the Kubernetes auto-update.
+ # NOTE: Only patches version will be pulled.
+ enabled: false
+ - name: coreos-metadata-sshkeys@.service
+ enabled: true
+ - name: kubeadm.service
+ enabled: true
+ dropins:
+ - name: 10-flatcar.conf
+ contents: |
+ [Unit]
+ Requires=containerd.service coreos-metadata.service
+ After=containerd.service coreos-metadata.service
+ [Service]
+ EnvironmentFile=/run/metadata/flatcar
+ initConfiguration:
+ nodeRegistration:
+ kubeletExtraArgs:
+ cloud-provider: external
+ name: $${COREOS_OPENSTACK_HOSTNAME}
+ joinConfiguration:
+ nodeRegistration:
+ kubeletExtraArgs:
+ cloud-provider: external
+ name: $${COREOS_OPENSTACK_HOSTNAME}
+ preKubeadmCommands:
+ - export COREOS_OPENSTACK_HOSTNAME=$${COREOS_OPENSTACK_HOSTNAME%.*}
+ - envsubst < /etc/kubeadm.yml > /etc/kubeadm.yml.tmp
+ - mv /etc/kubeadm.yml.tmp /etc/kubeadm.yml
+ machineTemplate:
+ infrastructureRef:
+ apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+ kind: OpenStackMachineTemplate
+ name: ${CLUSTER_NAME}-control-plane
+ replicas: ${CONTROL_PLANE_MACHINE_COUNT}
+ version: ${KUBERNETES_VERSION}
+---
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+kind: OpenStackCluster
+metadata:
+ name: ${CLUSTER_NAME}
+spec:
+ cloudName: ${OPENSTACK_CLOUD}
+ dnsNameservers:
+ - ${OPENSTACK_DNS_NAMESERVERS}
+ externalNetworkId: ${OPENSTACK_EXTERNAL_NETWORK_ID}
+ identityRef:
+ kind: Secret
+ name: ${CLUSTER_NAME}-cloud-config
+ managedSecurityGroups: true
+ nodeCidr: 10.6.0.0/24
+---
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+kind: OpenStackMachineTemplate
+metadata:
+ name: ${CLUSTER_NAME}-control-plane
+spec:
+ template:
+ spec:
+ cloudName: ${OPENSTACK_CLOUD}
+ flavor: ${OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR}
+ identityRef:
+ kind: Secret
+ name: ${CLUSTER_NAME}-cloud-config
+ image: ${FLATCAR_IMAGE_NAME}
+ sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
+---
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+kind: OpenStackMachineTemplate
+metadata:
+ name: ${CLUSTER_NAME}-md-0
+spec:
+ template:
+ spec:
+ cloudName: ${OPENSTACK_CLOUD}
+ flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR}
+ identityRef:
+ kind: Secret
+ name: ${CLUSTER_NAME}-cloud-config
+ image: ${FLATCAR_IMAGE_NAME}
+ sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
From d85b5fc973ac089e05573135b07dc7cf4bf82a0e Mon Sep 17 00:00:00 2001
From: Mathieu Tortuyaux
Date: Wed, 11 Oct 2023 11:37:02 +0200
Subject: [PATCH 010/180] test: add flatcar-sysext test
This test consumes the flatcar-sysext template to deploy a workload
cluster.
It uses a plain Flatcar OpenStack image from the release servers as it
does not need to rely on the image-builder built image.
Signed-off-by: Mathieu Tortuyaux
---
hack/ci/cloud-init/controller.yaml.tpl | 3 +-
test/e2e/data/e2e_conf.yaml | 3 ++
.../flatcar-sysext/kustomization.yaml | 7 +++
test/e2e/shared/defaults.go | 1 +
test/e2e/suites/e2e/e2e_test.go | 45 +++++++++++++++++++
5 files changed, 58 insertions(+), 1 deletion(-)
create mode 100644 test/e2e/data/kustomize/flatcar-sysext/kustomization.yaml
diff --git a/hack/ci/cloud-init/controller.yaml.tpl b/hack/ci/cloud-init/controller.yaml.tpl
index f83ddda1b6..4b872d512b 100644
--- a/hack/ci/cloud-init/controller.yaml.tpl
+++ b/hack/ci/cloud-init/controller.yaml.tpl
@@ -64,7 +64,8 @@
IMAGE_URLS+="https://storage.googleapis.com/artifacts.k8s-staging-capi-openstack.appspot.com/test/cirros/2022-12-05/cirros-0.6.1-x86_64-disk.img,"
IMAGE_URLS+="https://storage.googleapis.com/artifacts.k8s-staging-capi-openstack.appspot.com/test/ubuntu/2023-09-29/ubuntu-2204-kube-v1.27.2.img,"
IMAGE_URLS+="https://storage.googleapis.com/artifacts.k8s-staging-capi-openstack.appspot.com/test/ubuntu/2023-09-29/ubuntu-2204-kube-v1.28.2.img,"
- IMAGE_URLS+="https://storage.googleapis.com/artifacts.k8s-staging-capi-openstack.appspot.com/test/flatcar/flatcar-stable-3602.2.0-kube-v1.28.2.img"
+ IMAGE_URLS+="https://storage.googleapis.com/artifacts.k8s-staging-capi-openstack.appspot.com/test/flatcar/flatcar-stable-3602.2.0-kube-v1.28.2.img,"
+ IMAGE_URLS+="https://stable.release.flatcar-linux.net/amd64-usr/current/flatcar_production_openstack_image.img"
[[post-config|$NOVA_CONF]]
[DEFAULT]
diff --git a/test/e2e/data/e2e_conf.yaml b/test/e2e/data/e2e_conf.yaml
index f17655b66f..c4c54f9956 100644
--- a/test/e2e/data/e2e_conf.yaml
+++ b/test/e2e/data/e2e_conf.yaml
@@ -211,7 +211,10 @@ variables:
# The default user for SSH connections from bastion to machines
SSH_USER_MACHINE: "ubuntu"
EXP_KUBEADM_BOOTSTRAP_FORMAT_IGNITION: "true"
+ # The Flatcar image produced by the image-builder
OPENSTACK_FLATCAR_IMAGE_NAME: "flatcar-stable-3602.2.0-kube-v1.28.2"
+ # A plain Flatcar from the Flatcar releases server
+ FLATCAR_IMAGE_NAME: "flatcar_production_openstack_image"
intervals:
conformance/wait-control-plane: ["30m", "10s"]
diff --git a/test/e2e/data/kustomize/flatcar-sysext/kustomization.yaml b/test/e2e/data/kustomize/flatcar-sysext/kustomization.yaml
new file mode 100644
index 0000000000..f8d0816c32
--- /dev/null
+++ b/test/e2e/data/kustomize/flatcar-sysext/kustomization.yaml
@@ -0,0 +1,7 @@
+---
+resources:
+- ../../../../../kustomize/v1alpha7/flatcar-sysext
+
+components:
+- ../common-patches/cni
+- ../common-patches/ccm
diff --git a/test/e2e/shared/defaults.go b/test/e2e/shared/defaults.go
index 9c82de4f04..4ab3e9a7db 100644
--- a/test/e2e/shared/defaults.go
+++ b/test/e2e/shared/defaults.go
@@ -55,6 +55,7 @@ const (
FlavorKCPRemediation = "kcp-remediation"
FlavorFlatcar = "flatcar"
FlavorKubernetesUpgrade = "k8s-upgrade"
+ FlavorFlatcarSysext = "flatcar-sysext"
)
// DefaultScheme returns the default scheme to use for testing.
diff --git a/test/e2e/suites/e2e/e2e_test.go b/test/e2e/suites/e2e/e2e_test.go
index 90930a9fd3..fa27ec588c 100644
--- a/test/e2e/suites/e2e/e2e_test.go
+++ b/test/e2e/suites/e2e/e2e_test.go
@@ -205,6 +205,51 @@ var _ = Describe("e2e tests [PR-Blocking]", func() {
})
})
+ Describe("Workload cluster (flatcar-sysext)", func() {
+ It("should be creatable and deletable", func() {
+ // Flatcar default user is "core"
+ shared.SetEnvVar(shared.SSHUserMachine, "core", false)
+
+ shared.Logf("Creating a cluster")
+ clusterName := fmt.Sprintf("cluster-%s", namespace.Name)
+ configCluster := defaultConfigCluster(clusterName, namespace.Name)
+ configCluster.ControlPlaneMachineCount = pointer.Int64(3)
+ configCluster.WorkerMachineCount = pointer.Int64(1)
+ configCluster.Flavor = shared.FlavorFlatcarSysext
+ createCluster(ctx, configCluster, clusterResources)
+ md := clusterResources.MachineDeployments
+
+ workerMachines := framework.GetMachinesByMachineDeployments(ctx, framework.GetMachinesByMachineDeploymentsInput{
+ Lister: e2eCtx.Environment.BootstrapClusterProxy.GetClient(),
+ ClusterName: clusterName,
+ Namespace: namespace.Name,
+ MachineDeployment: *md[0],
+ })
+ controlPlaneMachines := framework.GetControlPlaneMachinesByCluster(ctx, framework.GetControlPlaneMachinesByClusterInput{
+ Lister: e2eCtx.Environment.BootstrapClusterProxy.GetClient(),
+ ClusterName: clusterName,
+ Namespace: namespace.Name,
+ })
+ Expect(workerMachines).To(HaveLen(1))
+ Expect(controlPlaneMachines).To(HaveLen(3))
+
+ shared.Logf("Waiting for worker nodes to be in Running phase")
+ statusChecks := []framework.MachineStatusCheck{framework.MachinePhaseCheck(string(clusterv1.MachinePhaseRunning))}
+ machineStatusInput := framework.WaitForMachineStatusCheckInput{
+ Getter: e2eCtx.Environment.BootstrapClusterProxy.GetClient(),
+ Machine: &workerMachines[0],
+ StatusChecks: statusChecks,
+ }
+ framework.WaitForMachineStatusCheck(ctx, machineStatusInput, e2eCtx.E2EConfig.GetIntervals(specName, "wait-machine-status")...)
+
+ workloadCluster := e2eCtx.Environment.BootstrapClusterProxy.GetWorkloadCluster(ctx, namespace.Name, clusterName)
+
+ waitForDaemonSetRunning(ctx, workloadCluster.GetClient(), "kube-system", "openstack-cloud-controller-manager")
+
+ waitForNodesReadyWithoutCCMTaint(ctx, workloadCluster.GetClient(), 4)
+ })
+ })
+
Describe("Workload cluster (without lb)", func() {
It("Should create port(s) with custom options", func() {
shared.Logf("Creating a cluster")
From 5a39a20eb377425cb238eb63ded29f9e5847c25b Mon Sep 17 00:00:00 2001
From: Mathieu Tortuyaux
Date: Thu, 12 Oct 2023 09:21:53 +0200
Subject: [PATCH 011/180] doc: mention Flatcar sysext template
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Mathieu Tortuyaux
Co-authored-by: Kai Lüke
---
.../src/clusteropenstack/configuration.md | 38 +++++++++++++++++--
1 file changed, 34 insertions(+), 4 deletions(-)
diff --git a/docs/book/src/clusteropenstack/configuration.md b/docs/book/src/clusteropenstack/configuration.md
index a767139134..7802107f02 100644
--- a/docs/book/src/clusteropenstack/configuration.md
+++ b/docs/book/src/clusteropenstack/configuration.md
@@ -74,10 +74,33 @@ The image can be referenced by exposing it as an environment variable `OPENSTACK
Some OS like [Fedora CoreOS](https://getfedora.org/en/coreos) or [Flatcar](https://www.flatcar.org/) do not use cloud-init but [Ignition](https://coreos.github.io/ignition/) to provision the instance. You need to enable the [Ignition experimental feature](https://cluster-api.sigs.k8s.io/tasks/experimental-features/ignition.html): `export EXP_KUBEADM_BOOTSTRAP_FORMAT_IGNITION=true`
-To use Flatcar image:
-* Build the image with the [image-builder](https://image-builder.sigs.k8s.io/capi/providers/openstack.html): `make OEM_ID=openstack build-qemu-flatcar`
-* Export the name of the uploaded image: `export OPENSTACK_FLATCAR_IMAGE_NAME=flatcar-stable-3374.2.5-kube-v1.25.6`
-* When generating the cluster configuration, use the following Cluster API [flavor](https://cluster-api.sigs.k8s.io/clusterctl/commands/generate-cluster.html?#flavors): `--flavor flatcar` (_NOTE_: Don't forget to refer to the [external-cloud-provider](https://cluster-api-openstack.sigs.k8s.io/topics/external-cloud-provider.html) section)
+Flatcar comes in two [flavor][flavor] variants:
+* `flatcar`
+
+ This variant relies on a Flatcar image built using the image-builder project: the Kubernetes version is bound to the Flatcar version and a rebuild of the image is required for each Kubernetes or Flatcar upgrade.
+
+ To build and use Flatcar image:
+ * Build the image with the [image-builder][image-builder]: `make OEM_ID=openstack build-qemu-flatcar`
+ * Upload the image
+ * Export the name of the uploaded image: `export OPENSTACK_FLATCAR_IMAGE_NAME=flatcar-stable-3374.2.5-kube-v1.25.6`
+ * When generating the cluster configuration, use the following Cluster API [flavor][flavor]: `--flavor flatcar` (_NOTE_: Don't forget to refer to the [external-cloud-provider][external-cloud-provider] section)
+
+* `flatcar-sysext`
+
+ This variant relies on a plain Flatcar image and it leverages [systemd-sysext][systemd-sysext] feature to install and update Kubernetes components: the Kubernetes version is not bound to the Flatcar version (i.e Flatcar can be independently upgraded from Kubernetes and vice versa).
+
+ The template comes with a [systemd-sysupdate][systemd-sysupdate] configuration file that will download each new patch version of Kubernetes (i.e if you start with Kubernetes 1.x.y, systemd-sysupdate will automatically pull 1.x.y+1 but not 1.x+1.y), please note that this behavior is disabled by default. To enable the Kubernetes auto-update you can:
+ * Update the template to enable the `systemd-sysupdate.timer`
+ * Or run the following command on the nodes: `sudo systemctl enable --now systemd-sysupdate.timer`
+
+ When the Kubernetes release reaches end-of-life it will not receive updates anymore. To switch to a new major version, do a `sudo rm /etc/sysupdate.kubernetes.d/kubernetes-*.conf` and download the new update config into the folder with `cd /etc/sysupdate.kubernetes.d && sudo wget https://github.com/flatcar/sysext-bakery/releases/download/latest/kubernetes-${KUBERNETES_VERSION%.*}.conf`.
+
+ To coordinate the node reboot, we recommend to use [Kured][kured]. Note that running `kubeadm upgrade apply` on the first controller and `kubeadm upgrade node` on all other nodes is not automated (yet), see the [docs](https://kubernetes.io/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade/).
+
+ To use Flatcar image:
+ * Upload an image on OpenStack from the Flatcar release servers (e.g for Stable, you might use this image: https://stable.release.flatcar-linux.net/amd64-usr/current/flatcar_production_openstack_image.img)
+ * Export the name of the uploaded image: `export FLATCAR_IMAGE_NAME=flatcar_production_openstack_image`
+ * When generating the cluster configuration, use the following Cluster API [flavor][flavor]: `--flavor flatcar-sysext` (_NOTE_: Don't forget to refer to the [external-cloud-provider][external-cloud-provider] section)
## SSH key pair
@@ -640,3 +663,10 @@ $ kubectl get openstackcluster
NAME CLUSTER READY NETWORK SUBNET BASTION
nonha nonha true 2e2a2fad-28c0-4159-8898-c0a2241a86a7 53cb77ab-86a6-4f2c-8d87-24f8411f15de 10.0.0.213
```
+
+[external-cloud-provider]: https://cluster-api-openstack.sigs.k8s.io/topics/external-cloud-provider.html
+[flavor]: https://cluster-api.sigs.k8s.io/clusterctl/commands/generate-cluster.html?#flavors
+[image-builder]: https://image-builder.sigs.k8s.io/capi/providers/openstack.html
+[kured]: https://github.com/kubereboot/kured
+[systemd-sysext]: https://www.flatcar.org/docs/latest/provisioning/sysext/
+[systemd-sysupdate]: https://www.freedesktop.org/software/systemd/man/latest/sysupdate.d.html
From fc305d11dd40adc73926e5b1913d807ffe63300f Mon Sep 17 00:00:00 2001
From: Anurag <81210977+kranurag7@users.noreply.github.com>
Date: Tue, 19 Dec 2023 18:39:12 +0530
Subject: [PATCH 012/180] change how we register scheme as per capi 1.6
Signed-off-by: Anurag <81210977+kranurag7@users.noreply.github.com>
---
api/v1alpha8/groupversion_info.go | 17 +++++++++++++----
api/v1alpha8/openstackcluster_types.go | 2 +-
api/v1alpha8/openstackclustertemplate_types.go | 2 +-
api/v1alpha8/openstackmachine_types.go | 2 +-
api/v1alpha8/openstackmachinetemplate_types.go | 2 +-
5 files changed, 17 insertions(+), 8 deletions(-)
diff --git a/api/v1alpha8/groupversion_info.go b/api/v1alpha8/groupversion_info.go
index 28fb759111..b0ab35273c 100644
--- a/api/v1alpha8/groupversion_info.go
+++ b/api/v1alpha8/groupversion_info.go
@@ -20,17 +20,26 @@ limitations under the License.
package v1alpha8
import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
- "sigs.k8s.io/controller-runtime/pkg/scheme"
)
var (
// GroupVersion is group version used to register these objects.
GroupVersion = schema.GroupVersion{Group: "infrastructure.cluster.x-k8s.io", Version: "v1alpha8"}
- // SchemeBuilder is used to add go types to the GroupVersionKind scheme.
- SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}
+ // 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
+ 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/api/v1alpha8/openstackcluster_types.go b/api/v1alpha8/openstackcluster_types.go
index 902e9c7c03..36b86a9df3 100644
--- a/api/v1alpha8/openstackcluster_types.go
+++ b/api/v1alpha8/openstackcluster_types.go
@@ -259,5 +259,5 @@ type OpenStackClusterList struct {
}
func init() {
- SchemeBuilder.Register(&OpenStackCluster{}, &OpenStackClusterList{})
+ objectTypes = append(objectTypes, &OpenStackCluster{}, &OpenStackClusterList{})
}
diff --git a/api/v1alpha8/openstackclustertemplate_types.go b/api/v1alpha8/openstackclustertemplate_types.go
index 60fc00956a..65ea6aeff6 100644
--- a/api/v1alpha8/openstackclustertemplate_types.go
+++ b/api/v1alpha8/openstackclustertemplate_types.go
@@ -52,5 +52,5 @@ type OpenStackClusterTemplateList struct {
}
func init() {
- SchemeBuilder.Register(&OpenStackClusterTemplate{}, &OpenStackClusterTemplateList{})
+ objectTypes = append(objectTypes, &OpenStackClusterTemplate{}, &OpenStackClusterTemplateList{})
}
diff --git a/api/v1alpha8/openstackmachine_types.go b/api/v1alpha8/openstackmachine_types.go
index 8a7c97d406..751051ff3e 100644
--- a/api/v1alpha8/openstackmachine_types.go
+++ b/api/v1alpha8/openstackmachine_types.go
@@ -181,5 +181,5 @@ func (r *OpenStackMachine) SetFailure(failureReason errors.MachineStatusError, f
}
func init() {
- SchemeBuilder.Register(&OpenStackMachine{}, &OpenStackMachineList{})
+ objectTypes = append(objectTypes, &OpenStackMachine{}, &OpenStackMachineList{})
}
diff --git a/api/v1alpha8/openstackmachinetemplate_types.go b/api/v1alpha8/openstackmachinetemplate_types.go
index f66cc2b1f1..fa80dc371d 100644
--- a/api/v1alpha8/openstackmachinetemplate_types.go
+++ b/api/v1alpha8/openstackmachinetemplate_types.go
@@ -47,5 +47,5 @@ type OpenStackMachineTemplateList struct {
}
func init() {
- SchemeBuilder.Register(&OpenStackMachineTemplate{}, &OpenStackMachineTemplateList{})
+ objectTypes = append(objectTypes, &OpenStackMachineTemplate{}, &OpenStackMachineTemplateList{})
}
From a45a6a987f97d5963d3098f8a0e7b983d31d5ef7 Mon Sep 17 00:00:00 2001
From: Max Rantil
Date: Fri, 1 Dec 2023 18:26:09 +0000
Subject: [PATCH 013/180] Make it possible to use a pre-created volume type in
e2e tests
Signed-off-by: Max Rantil
---
hack/ci/cloud-init/controller.yaml.tpl | 8 ++++++++
test/e2e/suites/e2e/e2e_suite_test.go | 1 -
test/e2e/suites/e2e/e2e_test.go | 25 -------------------------
3 files changed, 8 insertions(+), 26 deletions(-)
diff --git a/hack/ci/cloud-init/controller.yaml.tpl b/hack/ci/cloud-init/controller.yaml.tpl
index f83ddda1b6..6ab3d880ed 100644
--- a/hack/ci/cloud-init/controller.yaml.tpl
+++ b/hack/ci/cloud-init/controller.yaml.tpl
@@ -150,6 +150,14 @@
openstack aggregate add host "$aggregateid" "$host"
done
+ # Create the volume type
+ VOLUME_TYPE_NAME="test-volume-type"
+ if openstack volume type create --description "Test volume type" --public "${VOLUME_TYPE_NAME}" &> /dev/null; then
+ echo "Volume type '${VOLUME_TYPE_NAME}' created successfully."
+ else
+ echo "Error: Failed to create volume type '${VOLUME_TYPE_NAME}'."
+ fi
+
# the flavors are created in a way that we can execute at least 2 e2e tests in parallel (overall we have 32 vCPUs)
openstack flavor delete m1.tiny
openstack flavor create --ram 512 --disk 1 --ephemeral 1 --vcpus 1 --public --id 1 m1.tiny --property hw_rng:allowed='True'
diff --git a/test/e2e/suites/e2e/e2e_suite_test.go b/test/e2e/suites/e2e/e2e_suite_test.go
index df406adc1c..177c5ee2cc 100644
--- a/test/e2e/suites/e2e/e2e_suite_test.go
+++ b/test/e2e/suites/e2e/e2e_suite_test.go
@@ -52,7 +52,6 @@ func TestE2E(t *testing.T) {
var _ = SynchronizedBeforeSuite(func() []byte {
data := shared.Node1BeforeSuite(e2eCtx)
- createTestVolumeType(e2eCtx)
return data
}, func(data []byte) {
shared.AllNodesBeforeSuite(e2eCtx, data)
diff --git a/test/e2e/suites/e2e/e2e_test.go b/test/e2e/suites/e2e/e2e_test.go
index 90930a9fd3..e732033019 100644
--- a/test/e2e/suites/e2e/e2e_test.go
+++ b/test/e2e/suites/e2e/e2e_test.go
@@ -28,10 +28,7 @@ import (
"strings"
"time"
- "github.com/gophercloud/gophercloud"
- "github.com/gophercloud/gophercloud/openstack"
"github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes"
- "github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumetypes"
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups"
@@ -57,7 +54,6 @@ import (
crclient "sigs.k8s.io/controller-runtime/pkg/client"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
- capoerrors "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/errors"
"sigs.k8s.io/cluster-api-provider-openstack/test/e2e/shared"
)
@@ -890,24 +886,3 @@ func isCloudProviderInitialized(taints []corev1.Taint) bool {
}
return true
}
-
-func createTestVolumeType(e2eCtx *shared.E2EContext) {
- providerClient, clientOpts, _, err := shared.GetAdminProviderClient(e2eCtx)
- Expect(err).NotTo(HaveOccurred())
-
- volumeClient, err := openstack.NewBlockStorageV3(providerClient, gophercloud.EndpointOpts{Region: clientOpts.RegionName})
- Expect(err).NotTo(HaveOccurred())
-
- shared.Logf("Creating test volume type")
- _, err = volumetypes.Create(volumeClient, &volumetypes.CreateOpts{
- Name: e2eCtx.E2EConfig.GetVariable(shared.OpenStackVolumeTypeAlt),
- Description: "Test volume type",
- IsPublic: pointer.Bool(true),
- ExtraSpecs: map[string]string{},
- }).Extract()
- if capoerrors.IsConflict(err) {
- shared.Logf("Volume type already exists. This may happen in development environments, but it is not expected in CI.")
- return
- }
- Expect(err).NotTo(HaveOccurred())
-}
From 5f031ec271e2a92471fb8af78d9353ebc7bc2a0c Mon Sep 17 00:00:00 2001
From: Lennart Jern
Date: Wed, 20 Dec 2023 15:56:39 +0200
Subject: [PATCH 014/180] Update links in release docs
Some of the links were still pointing to the old k8s.gcr.io related
config, instead of registry.k8s.io.
---
RELEASE.md | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
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)
From f3f295948f01f200974fa7febe77a116d7312bdf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Andr=C3=A9?=
Date: Thu, 21 Dec 2023 13:52:03 +0100
Subject: [PATCH 015/180] Fix potential panic during instance create
The `FailedCreateServer` event was mistakenly calling the `Name()`
method on the createdInstance instance, that could very well be
unitialized since creation failed. Instead, log the event using the
named passed in the instance spec.
---
pkg/cloud/services/compute/instance.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pkg/cloud/services/compute/instance.go b/pkg/cloud/services/compute/instance.go
index 3c3710ee76..15e9756895 100644
--- a/pkg/cloud/services/compute/instance.go
+++ b/pkg/cloud/services/compute/instance.go
@@ -348,7 +348,7 @@ func (s *Service) createInstanceImpl(eventObject runtime.Object, openStackCluste
return createdInstance.State() == infrav1.InstanceStateActive, nil
})
if err != nil {
- record.Warnf(eventObject, "FailedCreateServer", "Failed to create server %s: %v", createdInstance.Name(), err)
+ record.Warnf(eventObject, "FailedCreateServer", "Failed to create server %s: %v", instanceSpec.Name, err)
return nil, err
}
From 173f41b71d2feaca17f477f91b33c1eda2f60f2a Mon Sep 17 00:00:00 2001
From: Emilien Macchi
Date: Thu, 4 Jan 2024 09:04:11 -0500
Subject: [PATCH 016/180] Move flatcar-sysext to v1alpha8
This was added via v1alpha7 but the latest api is v1alpha8 and to keep
our CI consistent we will move the manifests to v1alpha8.
---
.../flatcar-sysext/kustomization.yaml | 7 +
.../flatcar-sysext/patch-flatcar.yaml | 185 ++++++++++++++++++
.../cluster-template-flatcar-sysext.yaml | 12 +-
.../flatcar-sysext/kustomization.yaml | 2 +-
4 files changed, 199 insertions(+), 7 deletions(-)
create mode 100644 kustomize/v1alpha8/flatcar-sysext/kustomization.yaml
create mode 100644 kustomize/v1alpha8/flatcar-sysext/patch-flatcar.yaml
diff --git a/kustomize/v1alpha8/flatcar-sysext/kustomization.yaml b/kustomize/v1alpha8/flatcar-sysext/kustomization.yaml
new file mode 100644
index 0000000000..b5cb7540a4
--- /dev/null
+++ b/kustomize/v1alpha8/flatcar-sysext/kustomization.yaml
@@ -0,0 +1,7 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+resources:
+- ../default
+
+patches:
+- path: patch-flatcar.yaml
diff --git a/kustomize/v1alpha8/flatcar-sysext/patch-flatcar.yaml b/kustomize/v1alpha8/flatcar-sysext/patch-flatcar.yaml
new file mode 100644
index 0000000000..f1616ac759
--- /dev/null
+++ b/kustomize/v1alpha8/flatcar-sysext/patch-flatcar.yaml
@@ -0,0 +1,185 @@
+---
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+kind: OpenStackCluster
+metadata:
+ name: ${CLUSTER_NAME}
+spec:
+ apiServerLoadBalancer:
+ $patch: delete
+---
+apiVersion: controlplane.cluster.x-k8s.io/v1beta1
+kind: KubeadmControlPlane
+metadata:
+ name: "${CLUSTER_NAME}-control-plane"
+spec:
+ replicas: ${CONTROL_PLANE_MACHINE_COUNT}
+ kubeadmConfigSpec:
+ joinConfiguration:
+ nodeRegistration:
+ name: $${COREOS_OPENSTACK_HOSTNAME}
+ kubeletExtraArgs:
+ provider-id: null
+ initConfiguration:
+ nodeRegistration:
+ name: $${COREOS_OPENSTACK_HOSTNAME}
+ kubeletExtraArgs:
+ # Fixme(lentzi90): This is here just to override the value set in the default
+ # kustomization. It will be replaced with a value that works for flatcar in
+ # https://github.com/kubernetes-sigs/cluster-api-provider-openstack/pull/1564
+ provider-id: null
+ format: ignition
+ ignition:
+ containerLinuxConfig:
+ additionalConfig: |
+ storage:
+ links:
+ - path: /etc/extensions/kubernetes.raw
+ hard: false
+ target: /opt/extensions/kubernetes/kubernetes-${KUBERNETES_VERSION}-x86-64.raw
+ files:
+ - path: /etc/sysupdate.kubernetes.d/kubernetes-${KUBERNETES_VERSION%.*}.conf
+ mode: 0644
+ contents:
+ remote:
+ url: https://github.com/flatcar/sysext-bakery/releases/download/latest/kubernetes-${KUBERNETES_VERSION%.*}.conf
+ - path: /etc/sysupdate.d/noop.conf
+ mode: 0644
+ contents:
+ remote:
+ url: https://github.com/flatcar/sysext-bakery/releases/download/latest/noop.conf
+ - path: /opt/extensions/kubernetes/kubernetes-${KUBERNETES_VERSION}-x86-64.raw
+ contents:
+ remote:
+ url: https://github.com/flatcar/sysext-bakery/releases/download/latest/kubernetes-${KUBERNETES_VERSION}-x86-64.raw
+ systemd:
+ units:
+ - name: systemd-sysupdate.service
+ dropins:
+ - name: kubernetes.conf
+ contents: |
+ [Service]
+ ExecStartPre=/usr/bin/sh -c "readlink --canonicalize /etc/extensions/kubernetes.raw > /tmp/kubernetes"
+ ExecStartPre=/usr/lib/systemd/systemd-sysupdate -C kubernetes update
+ ExecStartPost=/usr/bin/sh -c "readlink --canonicalize /etc/extensions/kubernetes.raw > /tmp/kubernetes-new"
+ ExecStartPost=/usr/bin/sh -c "if ! cmp --silent /tmp/kubernetes /tmp/kubernetes-new; then touch /run/reboot-required; fi"
+ - name: update-engine.service
+ # Set this to 'false' if you want to enable Flatcar auto-update
+ mask: ${FLATCAR_DISABLE_AUTO_UPDATE:=true}
+ - name: locksmithd.service
+ # NOTE: To coordinate the node reboot in this context, we recommend to use Kured.
+ mask: true
+ - name: systemd-sysupdate.timer
+ # Set this to 'true' if you want to enable the Kubernetes auto-update.
+ # NOTE: Only patches version will be pulled.
+ enabled: false
+ - name: coreos-metadata-sshkeys@.service
+ enabled: true
+ - name: kubeadm.service
+ enabled: true
+ dropins:
+ - name: 10-flatcar.conf
+ contents: |
+ [Unit]
+ Requires=containerd.service coreos-metadata.service
+ After=containerd.service coreos-metadata.service
+ [Service]
+ EnvironmentFile=/run/metadata/flatcar
+ preKubeadmCommands:
+ - export COREOS_OPENSTACK_HOSTNAME=$${COREOS_OPENSTACK_HOSTNAME%.*}
+ - envsubst < /etc/kubeadm.yml > /etc/kubeadm.yml.tmp
+ - mv /etc/kubeadm.yml.tmp /etc/kubeadm.yml
+---
+apiVersion: bootstrap.cluster.x-k8s.io/v1beta1
+kind: KubeadmConfigTemplate
+metadata:
+ name: ${CLUSTER_NAME}-md-0
+spec:
+ template:
+ spec:
+ joinConfiguration:
+ nodeRegistration:
+ name: $${COREOS_OPENSTACK_HOSTNAME}
+ kubeletExtraArgs:
+ # Fixme(lentzi90): This is here just to override the value set in the default
+ # kustomization. It will be replaced with a value that works for flatcar in
+ # https://github.com/kubernetes-sigs/cluster-api-provider-openstack/pull/1564
+ provider-id: null
+ preKubeadmCommands:
+ - export COREOS_OPENSTACK_HOSTNAME=$${COREOS_OPENSTACK_HOSTNAME%.*}
+ - envsubst < /etc/kubeadm.yml > /etc/kubeadm.yml.tmp
+ - mv /etc/kubeadm.yml.tmp /etc/kubeadm.yml
+ format: ignition
+ ignition:
+ containerLinuxConfig:
+ additionalConfig: |
+ storage:
+ links:
+ - path: /etc/extensions/kubernetes.raw
+ hard: false
+ target: /opt/extensions/kubernetes/kubernetes-${KUBERNETES_VERSION}-x86-64.raw
+ files:
+ - path: /etc/sysupdate.kubernetes.d/kubernetes-${KUBERNETES_VERSION%.*}.conf
+ mode: 0644
+ contents:
+ remote:
+ url: https://github.com/flatcar/sysext-bakery/releases/download/latest/kubernetes-${KUBERNETES_VERSION%.*}.conf
+ - path: /etc/sysupdate.d/noop.conf
+ mode: 0644
+ contents:
+ remote:
+ url: https://github.com/flatcar/sysext-bakery/releases/download/latest/noop.conf
+ - path: /opt/extensions/kubernetes/kubernetes-${KUBERNETES_VERSION}-x86-64.raw
+ contents:
+ remote:
+ url: https://github.com/flatcar/sysext-bakery/releases/download/latest/kubernetes-${KUBERNETES_VERSION}-x86-64.raw
+ systemd:
+ units:
+ - name: systemd-sysupdate.service
+ dropins:
+ - name: kubernetes.conf
+ contents: |
+ [Service]
+ ExecStartPre=/usr/bin/sh -c "readlink --canonicalize /etc/extensions/kubernetes.raw > /tmp/kubernetes"
+ ExecStartPre=/usr/lib/systemd/systemd-sysupdate -C kubernetes update
+ ExecStartPost=/usr/bin/sh -c "readlink --canonicalize /etc/extensions/kubernetes.raw > /tmp/kubernetes-new"
+ ExecStartPost=/usr/bin/sh -c "if ! cmp --silent /tmp/kubernetes /tmp/kubernetes-new; then touch /run/reboot-required; fi"
+ - name: update-engine.service
+ # Set this to 'false' if you want to enable Flatcar auto-update
+ mask: ${FLATCAR_DISABLE_AUTO_UPDATE:=true}
+ - name: locksmithd.service
+ # NOTE: To coordinate the node reboot in this context, we recommend to use Kured.
+ mask: true
+ - name: systemd-sysupdate.timer
+ # Set this to 'true' if you want to enable the Kubernetes auto-update.
+ # NOTE: Only patches version will be pulled.
+ enabled: false
+ - name: coreos-metadata-sshkeys@.service
+ enabled: true
+ - name: kubeadm.service
+ enabled: true
+ dropins:
+ - name: 10-flatcar.conf
+ contents: |
+ [Unit]
+ Requires=containerd.service coreos-metadata.service
+ After=containerd.service coreos-metadata.service
+ [Service]
+ EnvironmentFile=/run/metadata/flatcar
+---
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+kind: OpenStackMachineTemplate
+metadata:
+ name: ${CLUSTER_NAME}-md-0
+spec:
+ template:
+ spec:
+ image: ${FLATCAR_IMAGE_NAME}
+---
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+kind: OpenStackMachineTemplate
+metadata:
+ name: ${CLUSTER_NAME}-control-plane
+spec:
+ template:
+ spec:
+ image: ${FLATCAR_IMAGE_NAME}
diff --git a/templates/cluster-template-flatcar-sysext.yaml b/templates/cluster-template-flatcar-sysext.yaml
index fa0ef1bf02..3de5d4fb07 100644
--- a/templates/cluster-template-flatcar-sysext.yaml
+++ b/templates/cluster-template-flatcar-sysext.yaml
@@ -98,7 +98,7 @@ spec:
kind: KubeadmControlPlane
name: ${CLUSTER_NAME}-control-plane
infrastructureRef:
- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+ apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackCluster
name: ${CLUSTER_NAME}
---
@@ -121,7 +121,7 @@ spec:
clusterName: ${CLUSTER_NAME}
failureDomain: ${OPENSTACK_FAILURE_DOMAIN}
infrastructureRef:
- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+ apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
name: ${CLUSTER_NAME}-md-0
version: ${KUBERNETES_VERSION}
@@ -213,13 +213,13 @@ spec:
- mv /etc/kubeadm.yml.tmp /etc/kubeadm.yml
machineTemplate:
infrastructureRef:
- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+ apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
name: ${CLUSTER_NAME}-control-plane
replicas: ${CONTROL_PLANE_MACHINE_COUNT}
version: ${KUBERNETES_VERSION}
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackCluster
metadata:
name: ${CLUSTER_NAME}
@@ -234,7 +234,7 @@ spec:
managedSecurityGroups: true
nodeCidr: 10.6.0.0/24
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
metadata:
name: ${CLUSTER_NAME}-control-plane
@@ -249,7 +249,7 @@ spec:
image: ${FLATCAR_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
metadata:
name: ${CLUSTER_NAME}-md-0
diff --git a/test/e2e/data/kustomize/flatcar-sysext/kustomization.yaml b/test/e2e/data/kustomize/flatcar-sysext/kustomization.yaml
index f8d0816c32..c3d83b26c3 100644
--- a/test/e2e/data/kustomize/flatcar-sysext/kustomization.yaml
+++ b/test/e2e/data/kustomize/flatcar-sysext/kustomization.yaml
@@ -1,6 +1,6 @@
---
resources:
-- ../../../../../kustomize/v1alpha7/flatcar-sysext
+- ../../../../../kustomize/v1alpha8/flatcar-sysext
components:
- ../common-patches/cni
From b77e0caa3caff0eeb94833b0c99459a948bd9af8 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Thu, 4 Jan 2024 18:06:50 +0000
Subject: [PATCH 017/180] v1alpha8: Make all restorers no-ops
v1alpha8 does not yet have any lossy conversions, so doesn't require any
restorer functions.
---
api/v1alpha7/conversion.go | 74 ++++----------------------------------
1 file changed, 7 insertions(+), 67 deletions(-)
diff --git a/api/v1alpha7/conversion.go b/api/v1alpha7/conversion.go
index 6b17160fdf..db22f57e64 100644
--- a/api/v1alpha7/conversion.go
+++ b/api/v1alpha7/conversion.go
@@ -25,26 +25,9 @@ import (
var _ ctrlconversion.Convertible = &OpenStackCluster{}
-var v1alpha7OpenStackClusterRestorer = conversion.RestorerFor[*OpenStackCluster]{
- "spec": conversion.HashedFieldRestorer[*OpenStackCluster, OpenStackClusterSpec]{
- GetField: func(c *OpenStackCluster) *OpenStackClusterSpec {
- return &c.Spec
- },
- },
- "status": conversion.HashedFieldRestorer[*OpenStackCluster, OpenStackClusterStatus]{
- GetField: func(c *OpenStackCluster) *OpenStackClusterStatus {
- return &c.Status
- },
- },
-}
+var v1alpha7OpenStackClusterRestorer = conversion.RestorerFor[*OpenStackCluster]{}
-var v1alpha8OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStackCluster]{
- "status": conversion.HashedFieldRestorer[*infrav1.OpenStackCluster, infrav1.OpenStackClusterStatus]{
- GetField: func(c *infrav1.OpenStackCluster) *infrav1.OpenStackClusterStatus {
- return &c.Status
- },
- },
-}
+var v1alpha8OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStackCluster]{}
func (r *OpenStackCluster) ConvertTo(dstRaw ctrlconversion.Hub) error {
dst := dstRaw.(*infrav1.OpenStackCluster)
@@ -84,13 +67,7 @@ func (r *OpenStackClusterList) ConvertFrom(srcRaw ctrlconversion.Hub) error {
var _ ctrlconversion.Convertible = &OpenStackClusterTemplate{}
-var v1alpha7OpenStackClusterTemplateRestorer = conversion.RestorerFor[*OpenStackClusterTemplate]{
- "spec": conversion.HashedFieldRestorer[*OpenStackClusterTemplate, OpenStackClusterSpec]{
- GetField: func(c *OpenStackClusterTemplate) *OpenStackClusterSpec {
- return &c.Spec.Template.Spec
- },
- },
-}
+var v1alpha7OpenStackClusterTemplateRestorer = conversion.RestorerFor[*OpenStackClusterTemplate]{}
var v1alpha8OpenStackClusterTemplateRestorer = conversion.RestorerFor[*infrav1.OpenStackClusterTemplate]{}
@@ -118,34 +95,9 @@ func (r *OpenStackClusterTemplate) ConvertFrom(srcRaw ctrlconversion.Hub) error
var _ ctrlconversion.Convertible = &OpenStackMachine{}
-var v1alpha7OpenStackMachineRestorer = 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
- },
- },
-}
+var v1alpha7OpenStackMachineRestorer = conversion.RestorerFor[*OpenStackMachine]{}
-var v1alpha8OpenStackMachineRestorer = conversion.RestorerFor[*infrav1.OpenStackMachine]{
- "spec": conversion.HashedFieldRestorer[*infrav1.OpenStackMachine, infrav1.OpenStackMachineSpec]{
- GetField: func(c *infrav1.OpenStackMachine) *infrav1.OpenStackMachineSpec {
- return &c.Spec
- },
- },
-}
+var v1alpha8OpenStackMachineRestorer = conversion.RestorerFor[*infrav1.OpenStackMachine]{}
func (r *OpenStackMachine) ConvertTo(dstRaw ctrlconversion.Hub) error {
dst := dstRaw.(*infrav1.OpenStackMachine)
@@ -183,21 +135,9 @@ func (r *OpenStackMachineList) ConvertFrom(srcRaw ctrlconversion.Hub) error {
var _ ctrlconversion.Convertible = &OpenStackMachineTemplate{}
-var v1alpha7OpenStackMachineTemplateRestorer = conversion.RestorerFor[*OpenStackMachineTemplate]{
- "spec": conversion.HashedFieldRestorer[*OpenStackMachineTemplate, OpenStackMachineSpec]{
- GetField: func(c *OpenStackMachineTemplate) *OpenStackMachineSpec {
- return &c.Spec.Template.Spec
- },
- },
-}
+var v1alpha7OpenStackMachineTemplateRestorer = conversion.RestorerFor[*OpenStackMachineTemplate]{}
-var v1alpha8OpenStackMachineTemplateRestorer = conversion.RestorerFor[*infrav1.OpenStackMachineTemplate]{
- "spec": conversion.HashedFieldRestorer[*infrav1.OpenStackMachineTemplate, infrav1.OpenStackMachineSpec]{
- GetField: func(c *infrav1.OpenStackMachineTemplate) *infrav1.OpenStackMachineSpec {
- return &c.Spec.Template.Spec
- },
- },
-}
+var v1alpha8OpenStackMachineTemplateRestorer = conversion.RestorerFor[*infrav1.OpenStackMachineTemplate]{}
func (r *OpenStackMachineTemplate) ConvertTo(dstRaw ctrlconversion.Hub) error {
dst := dstRaw.(*infrav1.OpenStackMachineTemplate)
From 4519da9de3ece725646d96ba441b3630ae042ef5 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Thu, 4 Jan 2024 17:53:39 +0000
Subject: [PATCH 018/180] Improve method signatures of conversion functions
It was possible to create a HashedFieldRestorer without a RestoreField,
which resulted in a crash in the conversion function. Additionally, it
was not easy to understand from the existing documentation that the
function was required and what its behaviour needed to be.
This change updates the method signatures of the conversion functions to
ensure initialisation of required fields, which turns this error into a
compile error. It additionally improves the documentation.
---
api/v1alpha6/conversion.go | 132 +++++++++++++++-----------------
api/v1alpha7/conversion.go | 24 ++----
pkg/utils/conversion/restore.go | 125 ++++++++++++++++++++++--------
3 files changed, 163 insertions(+), 118 deletions(-)
diff --git a/api/v1alpha6/conversion.go b/api/v1alpha6/conversion.go
index 66f77e3076..9fa55afb1a 100644
--- a/api/v1alpha6/conversion.go
+++ b/api/v1alpha6/conversion.go
@@ -103,51 +103,50 @@ func restorev1alpha6ClusterSpec(previous *OpenStackClusterSpec, dst *OpenStackCl
var _ ctrlconversion.Convertible = &OpenStackCluster{}
var v1alpha6OpenStackClusterRestorer = conversion.RestorerFor[*OpenStackCluster]{
- "spec": conversion.HashedFieldRestorer[*OpenStackCluster, OpenStackClusterSpec]{
- GetField: func(c *OpenStackCluster) *OpenStackClusterSpec {
+ "spec": conversion.HashedFieldRestorer(
+ func(c *OpenStackCluster) *OpenStackClusterSpec {
return &c.Spec
},
- RestoreField: restorev1alpha6ClusterSpec,
- },
- "status": conversion.HashedFieldRestorer[*OpenStackCluster, OpenStackClusterStatus]{
- GetField: func(c *OpenStackCluster) *OpenStackClusterStatus {
+ restorev1alpha6ClusterSpec,
+ ),
+ "status": conversion.HashedFieldRestorer(
+ func(c *OpenStackCluster) *OpenStackClusterStatus {
return &c.Status
},
- RestoreField: restorev1alpha6ClusterStatus,
- },
+ restorev1alpha6ClusterStatus,
+ ),
}
var v1alpha8OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStackCluster]{
- "router": conversion.UnconditionalFieldRestorer[*infrav1.OpenStackCluster, *infrav1.RouterFilter]{
- GetField: func(c *infrav1.OpenStackCluster) **infrav1.RouterFilter {
+ "router": conversion.UnconditionalFieldRestorer(
+ func(c *infrav1.OpenStackCluster) **infrav1.RouterFilter {
return &c.Spec.Router
},
- },
- "networkMtu": conversion.UnconditionalFieldRestorer[*infrav1.OpenStackCluster, int]{
- GetField: func(c *infrav1.OpenStackCluster) *int {
+ ),
+ "networkMtu": conversion.UnconditionalFieldRestorer(
+ func(c *infrav1.OpenStackCluster) *int {
return &c.Spec.NetworkMTU
},
- },
- "bastion": conversion.HashedFieldRestorer[*infrav1.OpenStackCluster, *infrav1.Bastion]{
- GetField: func(c *infrav1.OpenStackCluster) **infrav1.Bastion {
+ ),
+ "bastion": conversion.HashedFieldRestorer(
+ func(c *infrav1.OpenStackCluster) **infrav1.Bastion {
return &c.Spec.Bastion
},
- RestoreField: restorev1alpha8Bastion,
- },
- "status": conversion.HashedFieldRestorer[*infrav1.OpenStackCluster, infrav1.OpenStackClusterStatus]{
- GetField: func(c *infrav1.OpenStackCluster) *infrav1.OpenStackClusterStatus {
+ restorev1alpha8Bastion,
+ ),
+ "status": conversion.HashedFieldRestorer(
+ func(c *infrav1.OpenStackCluster) *infrav1.OpenStackClusterStatus {
return &c.Status
},
- RestoreField: restorev1alpha8ClusterStatus,
- },
+ restorev1alpha8ClusterStatus,
+ ),
}
func (r *OpenStackCluster) ConvertTo(dstRaw ctrlconversion.Hub) error {
dst := dstRaw.(*infrav1.OpenStackCluster)
- compare := &OpenStackCluster{}
return conversion.ConvertAndRestore(
- r, dst, compare,
+ r, dst,
Convert_v1alpha6_OpenStackCluster_To_v1alpha8_OpenStackCluster, Convert_v1alpha8_OpenStackCluster_To_v1alpha6_OpenStackCluster,
v1alpha6OpenStackClusterRestorer, v1alpha8OpenStackClusterRestorer,
)
@@ -156,9 +155,8 @@ func (r *OpenStackCluster) ConvertTo(dstRaw ctrlconversion.Hub) error {
func (r *OpenStackCluster) ConvertFrom(srcRaw ctrlconversion.Hub) error {
src := srcRaw.(*infrav1.OpenStackCluster)
- compare := &infrav1.OpenStackCluster{}
return conversion.ConvertAndRestore(
- src, r, compare,
+ src, r,
Convert_v1alpha8_OpenStackCluster_To_v1alpha6_OpenStackCluster, Convert_v1alpha6_OpenStackCluster_To_v1alpha8_OpenStackCluster,
v1alpha8OpenStackClusterRestorer, v1alpha6OpenStackClusterRestorer,
)
@@ -181,39 +179,38 @@ func (r *OpenStackClusterList) ConvertFrom(srcRaw ctrlconversion.Hub) error {
var _ ctrlconversion.Convertible = &OpenStackClusterTemplate{}
var v1alpha6OpenStackClusterTemplateRestorer = conversion.RestorerFor[*OpenStackClusterTemplate]{
- "spec": conversion.HashedFieldRestorer[*OpenStackClusterTemplate, OpenStackClusterSpec]{
- GetField: func(c *OpenStackClusterTemplate) *OpenStackClusterSpec {
+ "spec": conversion.HashedFieldRestorer(
+ func(c *OpenStackClusterTemplate) *OpenStackClusterSpec {
return &c.Spec.Template.Spec
},
- RestoreField: restorev1alpha6ClusterSpec,
- },
+ restorev1alpha6ClusterSpec,
+ ),
}
var v1alpha8OpenStackClusterTemplateRestorer = conversion.RestorerFor[*infrav1.OpenStackClusterTemplate]{
- "router": conversion.UnconditionalFieldRestorer[*infrav1.OpenStackClusterTemplate, *infrav1.RouterFilter]{
- GetField: func(c *infrav1.OpenStackClusterTemplate) **infrav1.RouterFilter {
+ "router": conversion.UnconditionalFieldRestorer(
+ func(c *infrav1.OpenStackClusterTemplate) **infrav1.RouterFilter {
return &c.Spec.Template.Spec.Router
},
- },
- "networkMtu": conversion.UnconditionalFieldRestorer[*infrav1.OpenStackClusterTemplate, int]{
- GetField: func(c *infrav1.OpenStackClusterTemplate) *int {
+ ),
+ "networkMtu": conversion.UnconditionalFieldRestorer(
+ 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 {
+ ),
+ "bastion": conversion.HashedFieldRestorer(
+ func(c *infrav1.OpenStackClusterTemplate) **infrav1.Bastion {
return &c.Spec.Template.Spec.Bastion
},
- RestoreField: restorev1alpha8Bastion,
- },
+ restorev1alpha8Bastion,
+ ),
}
func (r *OpenStackClusterTemplate) ConvertTo(dstRaw ctrlconversion.Hub) error {
dst := dstRaw.(*infrav1.OpenStackClusterTemplate)
- compare := &OpenStackClusterTemplate{}
return conversion.ConvertAndRestore(
- r, dst, compare,
+ r, dst,
Convert_v1alpha6_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate, Convert_v1alpha8_OpenStackClusterTemplate_To_v1alpha6_OpenStackClusterTemplate,
v1alpha6OpenStackClusterTemplateRestorer, v1alpha8OpenStackClusterTemplateRestorer,
)
@@ -222,9 +219,8 @@ func (r *OpenStackClusterTemplate) ConvertTo(dstRaw ctrlconversion.Hub) error {
func (r *OpenStackClusterTemplate) ConvertFrom(srcRaw ctrlconversion.Hub) error {
src := srcRaw.(*infrav1.OpenStackClusterTemplate)
- compare := &infrav1.OpenStackClusterTemplate{}
return conversion.ConvertAndRestore(
- src, r, compare,
+ src, r,
Convert_v1alpha8_OpenStackClusterTemplate_To_v1alpha6_OpenStackClusterTemplate, Convert_v1alpha6_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate,
v1alpha8OpenStackClusterTemplateRestorer, v1alpha6OpenStackClusterTemplateRestorer,
)
@@ -233,11 +229,12 @@ func (r *OpenStackClusterTemplate) ConvertFrom(srcRaw ctrlconversion.Hub) error
var _ ctrlconversion.Convertible = &OpenStackMachine{}
var v1alpha6OpenStackMachineRestorer = conversion.RestorerFor[*OpenStackMachine]{
- "spec": conversion.HashedFieldRestorer[*OpenStackMachine, OpenStackMachineSpec]{
- GetField: func(c *OpenStackMachine) *OpenStackMachineSpec {
+ "spec": conversion.HashedFieldRestorer(
+ func(c *OpenStackMachine) *OpenStackMachineSpec {
return &c.Spec
},
- FilterField: func(s *OpenStackMachineSpec) *OpenStackMachineSpec {
+ 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
@@ -249,26 +246,24 @@ var v1alpha6OpenStackMachineRestorer = conversion.RestorerFor[*OpenStackMachine]
return &f
}
return s
- },
- RestoreField: restorev1alpha6MachineSpec,
- },
+ }),
+ ),
}
var v1alpha8OpenStackMachineRestorer = conversion.RestorerFor[*infrav1.OpenStackMachine]{
- "spec": conversion.HashedFieldRestorer[*infrav1.OpenStackMachine, infrav1.OpenStackMachineSpec]{
- GetField: func(c *infrav1.OpenStackMachine) *infrav1.OpenStackMachineSpec {
+ "spec": conversion.HashedFieldRestorer(
+ func(c *infrav1.OpenStackMachine) *infrav1.OpenStackMachineSpec {
return &c.Spec
},
- RestoreField: restorev1alpha8MachineSpec,
- },
+ restorev1alpha8MachineSpec,
+ ),
}
func (r *OpenStackMachine) ConvertTo(dstRaw ctrlconversion.Hub) error {
dst := dstRaw.(*infrav1.OpenStackMachine)
- compare := &OpenStackMachine{}
return conversion.ConvertAndRestore(
- r, dst, compare,
+ r, dst,
Convert_v1alpha6_OpenStackMachine_To_v1alpha8_OpenStackMachine, Convert_v1alpha8_OpenStackMachine_To_v1alpha6_OpenStackMachine,
v1alpha6OpenStackMachineRestorer, v1alpha8OpenStackMachineRestorer,
)
@@ -277,9 +272,8 @@ func (r *OpenStackMachine) ConvertTo(dstRaw ctrlconversion.Hub) error {
func (r *OpenStackMachine) ConvertFrom(srcRaw ctrlconversion.Hub) error {
src := srcRaw.(*infrav1.OpenStackMachine)
- compare := &infrav1.OpenStackMachine{}
return conversion.ConvertAndRestore(
- src, r, compare,
+ src, r,
Convert_v1alpha8_OpenStackMachine_To_v1alpha6_OpenStackMachine, Convert_v1alpha6_OpenStackMachine_To_v1alpha8_OpenStackMachine,
v1alpha8OpenStackMachineRestorer, v1alpha6OpenStackMachineRestorer,
)
@@ -300,29 +294,28 @@ func (r *OpenStackMachineList) ConvertFrom(srcRaw ctrlconversion.Hub) error {
var _ ctrlconversion.Convertible = &OpenStackMachineTemplate{}
var v1alpha6OpenStackMachineTemplateRestorer = conversion.RestorerFor[*OpenStackMachineTemplate]{
- "spec": conversion.HashedFieldRestorer[*OpenStackMachineTemplate, OpenStackMachineSpec]{
- GetField: func(c *OpenStackMachineTemplate) *OpenStackMachineSpec {
+ "spec": conversion.HashedFieldRestorer(
+ func(c *OpenStackMachineTemplate) *OpenStackMachineSpec {
return &c.Spec.Template.Spec
},
- RestoreField: restorev1alpha6MachineSpec,
- },
+ restorev1alpha6MachineSpec,
+ ),
}
var v1alpha8OpenStackMachineTemplateRestorer = conversion.RestorerFor[*infrav1.OpenStackMachineTemplate]{
- "spec": conversion.HashedFieldRestorer[*infrav1.OpenStackMachineTemplate, infrav1.OpenStackMachineSpec]{
- GetField: func(c *infrav1.OpenStackMachineTemplate) *infrav1.OpenStackMachineSpec {
+ "spec": conversion.HashedFieldRestorer(
+ func(c *infrav1.OpenStackMachineTemplate) *infrav1.OpenStackMachineSpec {
return &c.Spec.Template.Spec
},
- RestoreField: restorev1alpha8MachineSpec,
- },
+ restorev1alpha8MachineSpec,
+ ),
}
func (r *OpenStackMachineTemplate) ConvertTo(dstRaw ctrlconversion.Hub) error {
dst := dstRaw.(*infrav1.OpenStackMachineTemplate)
- compare := &OpenStackMachineTemplate{}
return conversion.ConvertAndRestore(
- r, dst, compare,
+ r, dst,
Convert_v1alpha6_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate, Convert_v1alpha8_OpenStackMachineTemplate_To_v1alpha6_OpenStackMachineTemplate,
v1alpha6OpenStackMachineTemplateRestorer, v1alpha8OpenStackMachineTemplateRestorer,
)
@@ -331,9 +324,8 @@ func (r *OpenStackMachineTemplate) ConvertTo(dstRaw ctrlconversion.Hub) error {
func (r *OpenStackMachineTemplate) ConvertFrom(srcRaw ctrlconversion.Hub) error {
src := srcRaw.(*infrav1.OpenStackMachineTemplate)
- compare := &infrav1.OpenStackMachineTemplate{}
return conversion.ConvertAndRestore(
- src, r, compare,
+ src, r,
Convert_v1alpha8_OpenStackMachineTemplate_To_v1alpha6_OpenStackMachineTemplate, Convert_v1alpha6_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate,
v1alpha8OpenStackMachineTemplateRestorer, v1alpha6OpenStackMachineTemplateRestorer,
)
diff --git a/api/v1alpha7/conversion.go b/api/v1alpha7/conversion.go
index db22f57e64..6677d7186a 100644
--- a/api/v1alpha7/conversion.go
+++ b/api/v1alpha7/conversion.go
@@ -32,9 +32,8 @@ var v1alpha8OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStack
func (r *OpenStackCluster) ConvertTo(dstRaw ctrlconversion.Hub) error {
dst := dstRaw.(*infrav1.OpenStackCluster)
- compare := &OpenStackCluster{}
return conversion.ConvertAndRestore(
- r, dst, compare,
+ r, dst,
Convert_v1alpha7_OpenStackCluster_To_v1alpha8_OpenStackCluster, Convert_v1alpha8_OpenStackCluster_To_v1alpha7_OpenStackCluster,
v1alpha7OpenStackClusterRestorer, v1alpha8OpenStackClusterRestorer,
)
@@ -43,9 +42,8 @@ func (r *OpenStackCluster) ConvertTo(dstRaw ctrlconversion.Hub) error {
func (r *OpenStackCluster) ConvertFrom(srcRaw ctrlconversion.Hub) error {
src := srcRaw.(*infrav1.OpenStackCluster)
- compare := &infrav1.OpenStackCluster{}
return conversion.ConvertAndRestore(
- src, r, compare,
+ src, r,
Convert_v1alpha8_OpenStackCluster_To_v1alpha7_OpenStackCluster, Convert_v1alpha7_OpenStackCluster_To_v1alpha8_OpenStackCluster,
v1alpha8OpenStackClusterRestorer, v1alpha7OpenStackClusterRestorer,
)
@@ -74,9 +72,8 @@ var v1alpha8OpenStackClusterTemplateRestorer = conversion.RestorerFor[*infrav1.O
func (r *OpenStackClusterTemplate) ConvertTo(dstRaw ctrlconversion.Hub) error {
dst := dstRaw.(*infrav1.OpenStackClusterTemplate)
- compare := &OpenStackClusterTemplate{}
return conversion.ConvertAndRestore(
- r, dst, compare,
+ r, dst,
Convert_v1alpha7_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate, Convert_v1alpha8_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate,
v1alpha7OpenStackClusterTemplateRestorer, v1alpha8OpenStackClusterTemplateRestorer,
)
@@ -85,9 +82,8 @@ func (r *OpenStackClusterTemplate) ConvertTo(dstRaw ctrlconversion.Hub) error {
func (r *OpenStackClusterTemplate) ConvertFrom(srcRaw ctrlconversion.Hub) error {
src := srcRaw.(*infrav1.OpenStackClusterTemplate)
- compare := &infrav1.OpenStackClusterTemplate{}
return conversion.ConvertAndRestore(
- src, r, compare,
+ src, r,
Convert_v1alpha8_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate, Convert_v1alpha7_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate,
v1alpha8OpenStackClusterTemplateRestorer, v1alpha7OpenStackClusterTemplateRestorer,
)
@@ -102,9 +98,8 @@ var v1alpha8OpenStackMachineRestorer = conversion.RestorerFor[*infrav1.OpenStack
func (r *OpenStackMachine) ConvertTo(dstRaw ctrlconversion.Hub) error {
dst := dstRaw.(*infrav1.OpenStackMachine)
- compare := &OpenStackMachine{}
return conversion.ConvertAndRestore(
- r, dst, compare,
+ r, dst,
Convert_v1alpha7_OpenStackMachine_To_v1alpha8_OpenStackMachine, Convert_v1alpha8_OpenStackMachine_To_v1alpha7_OpenStackMachine,
v1alpha7OpenStackMachineRestorer, v1alpha8OpenStackMachineRestorer,
)
@@ -113,9 +108,8 @@ func (r *OpenStackMachine) ConvertTo(dstRaw ctrlconversion.Hub) error {
func (r *OpenStackMachine) ConvertFrom(srcRaw ctrlconversion.Hub) error {
src := srcRaw.(*infrav1.OpenStackMachine)
- compare := &infrav1.OpenStackMachine{}
return conversion.ConvertAndRestore(
- src, r, compare,
+ src, r,
Convert_v1alpha8_OpenStackMachine_To_v1alpha7_OpenStackMachine, Convert_v1alpha7_OpenStackMachine_To_v1alpha8_OpenStackMachine,
v1alpha8OpenStackMachineRestorer, v1alpha7OpenStackMachineRestorer,
)
@@ -142,9 +136,8 @@ var v1alpha8OpenStackMachineTemplateRestorer = conversion.RestorerFor[*infrav1.O
func (r *OpenStackMachineTemplate) ConvertTo(dstRaw ctrlconversion.Hub) error {
dst := dstRaw.(*infrav1.OpenStackMachineTemplate)
- compare := &OpenStackMachineTemplate{}
return conversion.ConvertAndRestore(
- r, dst, compare,
+ r, dst,
Convert_v1alpha7_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate, Convert_v1alpha8_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate,
v1alpha7OpenStackMachineTemplateRestorer, v1alpha8OpenStackMachineTemplateRestorer,
)
@@ -153,9 +146,8 @@ func (r *OpenStackMachineTemplate) ConvertTo(dstRaw ctrlconversion.Hub) error {
func (r *OpenStackMachineTemplate) ConvertFrom(srcRaw ctrlconversion.Hub) error {
src := srcRaw.(*infrav1.OpenStackMachineTemplate)
- compare := &infrav1.OpenStackMachineTemplate{}
return conversion.ConvertAndRestore(
- src, r, compare,
+ src, r,
Convert_v1alpha8_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate, Convert_v1alpha7_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate,
v1alpha8OpenStackMachineTemplateRestorer, v1alpha7OpenStackMachineTemplateRestorer,
)
diff --git a/pkg/utils/conversion/restore.go b/pkg/utils/conversion/restore.go
index 65cc8b515d..3d515074ba 100644
--- a/pkg/utils/conversion/restore.go
+++ b/pkg/utils/conversion/restore.go
@@ -29,29 +29,84 @@ import (
)
// RestorerFor holds all field restorers for a given type T.
-type RestorerFor[T metav1.Object] map[string]fieldRestorerFor[T]
+type RestorerFor[T metav1.Object] map[string]FieldRestorerFor[T]
-type fieldRestorerFor[T any] interface {
+type FieldRestorerFor[T any] interface {
marshalState(T, T) (json.RawMessage, error)
restore(json.RawMessage, T) error
}
+// HashedFieldRestorerOpt is a modifier which adds optional behaviour to a
+// HashedFieldRestorer. It can be passed as an argument to
+// HashedFieldRestorer().
+type HashedFieldRestorerOpt[T, F any] func(*hashedFieldRestorer[T, F])
+
// HashedFieldRestorer restores a field to its original pre-conversion state
// only if it was not modified while converted. It does this by doing a full
// round-trip conversion before saving its state, and storing the hash of an
// unmodified round-trip converted object.
-type HashedFieldRestorer[T any, F any] struct {
- // GetField returns the field to be restored
- GetField func(T) *F
+//
+// HashedFieldRestorer takes 2 type arguments:
+//
+// T: The type of the object being converted. This is a pointer type.
+// F: The type of the field in T which is being restored. This is not a
+// pointer type.
+//
+// The type arguments can usually be omitted, as they can be inferred from the
+// arguments.
+//
+// HashedFieldRestorer takes 2 arguments:
+//
+// getField: A function which takes the object being converted (of type T) and returns a pointer to the field being restored (of type *F).
+// restoreField: Described below.
+//
+// restoreField is used to restore parts of the field to their original
+// pre-conversion state which were not restored by the normal conversion
+// functions. This is to preserve idempotency when the normal conversion
+// functions are lossy, so it is only called if the field was not modified
+// during conversion.
+//
+// restoreField takes 2 arguments:
+//
+// previous: A pointer to the saved original state of the field before conversion.
+// dst: A pointer to the field which needs to be updated.
+//
+// The normal conversion functions should do as much work as possible, so
+// restoreField should only be used to restore state which cannot be restored
+// any other way.
+func HashedFieldRestorer[T, F any](getField func(T) *F, restoreField func(*F, *F), opts ...HashedFieldRestorerOpt[T, F]) FieldRestorerFor[T] {
+ restorer := hashedFieldRestorer[T, F]{
+ getField: getField,
+ restoreField: restoreField,
+ }
+ for _, opt := range opts {
+ opt(&restorer)
+ }
- // FilterField returns a modified copy of the field to be used for comparison. i.e. filtered fields will be ignored in comparison.
- FilterField func(*F) *F
+ return restorer
+}
+
+// HashedFilterField adds a field filter to a HashedFieldRestorer. The field
+// filter returns a modified copy of the field to be used for comparison. This
+// can be used to ignore certain changes during comparison.
+func HashedFilterField[T, F any](f func(*F) *F) func(*hashedFieldRestorer[T, F]) {
+ return func(r *hashedFieldRestorer[T, F]) {
+ r.filterField = f
+ }
+}
+
+type hashedFieldRestorer[T any, F any] struct {
+ // getField returns the field to be restored
+ getField func(T) *F
+
+ // restoreField restores the field to its original pre-conversion state
+ restoreField func(*F, *F)
- // RestoreField restores the field to its original pre-conversion state
- RestoreField func(*F, *F)
+ // filterField returns a modified copy of the field to be used for comparison. i.e. filtered fields will be ignored in comparison.
+ filterField func(*F) *F
}
-var _ fieldRestorerFor[any] = HashedFieldRestorer[any, any]{}
+var _ FieldRestorerFor[any] = hashedFieldRestorer[any, any]{}
//nolint:unused
type hashedFieldRestoreState struct {
@@ -60,10 +115,10 @@ type hashedFieldRestoreState struct {
}
//nolint:unused
-func (r HashedFieldRestorer[T, F]) getHash(obj T) []byte {
- f := r.GetField(obj)
- if r.FilterField != nil {
- f = r.FilterField(f)
+func (r hashedFieldRestorer[T, F]) getHash(obj T) []byte {
+ f := r.getField(obj)
+ if r.filterField != nil {
+ f = r.filterField(f)
}
table := crc64.MakeTable(crc64.ECMA)
@@ -73,8 +128,8 @@ func (r HashedFieldRestorer[T, F]) getHash(obj T) []byte {
}
//nolint:unused
-func (r HashedFieldRestorer[T, F]) marshalState(src, compare T) (json.RawMessage, error) {
- b, err := json.Marshal(r.GetField(src))
+func (r hashedFieldRestorer[T, F]) marshalState(src, compare T) (json.RawMessage, error) {
+ b, err := json.Marshal(r.getField(src))
if err != nil {
return nil, err
}
@@ -93,7 +148,7 @@ func (r HashedFieldRestorer[T, F]) marshalState(src, compare T) (json.RawMessage
}
//nolint:unused
-func (r HashedFieldRestorer[T, F]) restore(b json.RawMessage, dst T) error {
+func (r hashedFieldRestorer[T, F]) restore(b json.RawMessage, dst T) error {
var restoreState hashedFieldRestoreState
if err := json.Unmarshal(b, &restoreState); err != nil {
return err
@@ -104,50 +159,55 @@ func (r HashedFieldRestorer[T, F]) restore(b json.RawMessage, dst T) error {
if err := json.Unmarshal(restoreState.Data, &previous); err != nil {
return err
}
- r.RestoreField(&previous, r.GetField(dst))
+ r.restoreField(&previous, r.getField(dst))
}
return nil
}
// UnconditionalFieldRestorer restores a field to its previous value without checking to see if it was modified during conversion.
-//
+func UnconditionalFieldRestorer[T, F any](getField func(T) *F) FieldRestorerFor[T] {
+ return unconditionalFieldRestorer[T, F]{
+ getField: getField,
+ }
+}
-type UnconditionalFieldRestorer[T any, F any] struct {
- GetField func(T) *F
+type unconditionalFieldRestorer[T any, F any] struct {
+ getField func(T) *F
}
-var _ fieldRestorerFor[any] = UnconditionalFieldRestorer[any, any]{}
+var _ FieldRestorerFor[any] = unconditionalFieldRestorer[any, any]{}
//nolint:unused
type unconditionalFieldRestoreState json.RawMessage
//nolint:unused
-func (r UnconditionalFieldRestorer[T, F]) marshalState(src, _ T) (json.RawMessage, error) {
- f := r.GetField(src)
+func (r unconditionalFieldRestorer[T, F]) marshalState(src, _ T) (json.RawMessage, error) {
+ f := r.getField(src)
// We could do this with a comparable constraint on F, but that's too restrictive for an arbitrary struct.
if reflect.ValueOf(f).Elem().IsZero() {
return nil, nil
}
- return json.Marshal(r.GetField(src))
+ return json.Marshal(r.getField(src))
}
//nolint:unused
-func (r UnconditionalFieldRestorer[T, F]) restore(b json.RawMessage, dst T) error {
- return json.Unmarshal(b, r.GetField(dst))
+func (r unconditionalFieldRestorer[T, F]) restore(b json.RawMessage, dst T) error {
+ return json.Unmarshal(b, r.getField(dst))
}
// restoreData serialises state for a set of restorers.
type restoreData map[string]json.RawMessage
-// ConvertAndRestore converts src to dst. During conversion is reads and uses any restore data in the src annotation, and writes new restore data to the dst annotation.
-func ConvertAndRestore[S, D metav1.Object](src S, dst D, compare S, convert func(S, D, conversion.Scope) error, unconvert func(D, S, conversion.Scope) error, srcRestorer RestorerFor[S], dstRestorer RestorerFor[D]) error {
- // NOTE(mdbooth): passing compare in here is a wart. If there's any way
- // to redefine the signature of this function such that we can create a
- // compare object ourselves we should do it.
+type pointerToObject[T any] interface {
+ *T
+ metav1.Object
+}
+// ConvertAndRestore converts src to dst. During conversion is reads and uses any restore data in the src annotation, and writes new restore data to the dst annotation.
+func ConvertAndRestore[S pointerToObject[SO], SO any, D metav1.Object](src S, dst D, convert func(S, D, conversion.Scope) error, unconvert func(D, S, conversion.Scope) error, srcRestorer RestorerFor[S], dstRestorer RestorerFor[D]) error {
var dstRestoreData restoreData
srcAnnotations := src.GetAnnotations()
if srcData, ok := srcAnnotations[utilconversion.DataAnnotation]; ok {
@@ -161,6 +221,7 @@ func ConvertAndRestore[S, D metav1.Object](src S, dst D, compare S, convert func
return err
}
+ compare := new(SO)
if err := unconvert(dst, compare, nil); err != nil {
return err
}
From 7bd42abe3c8c12fcc6634ccb5ddd7305111efa83 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Mon, 8 Jan 2024 11:23:48 +0000
Subject: [PATCH 019/180] conversion: Allow getField to return nil in
UnconditionalFieldRestorer
---
pkg/utils/conversion/restore.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pkg/utils/conversion/restore.go b/pkg/utils/conversion/restore.go
index 3d515074ba..04701a19e8 100644
--- a/pkg/utils/conversion/restore.go
+++ b/pkg/utils/conversion/restore.go
@@ -186,7 +186,7 @@ func (r unconditionalFieldRestorer[T, F]) marshalState(src, _ T) (json.RawMessag
f := r.getField(src)
// We could do this with a comparable constraint on F, but that's too restrictive for an arbitrary struct.
- if reflect.ValueOf(f).Elem().IsZero() {
+ if f == nil || reflect.ValueOf(f).Elem().IsZero() {
return nil, nil
}
From 32369b648c349710a86e7226b7bce0b662b312a1 Mon Sep 17 00:00:00 2001
From: Stephen Finucane
Date: Thu, 7 Dec 2023 15:01:52 +0000
Subject: [PATCH 020/180] api: Add ServerGroupFilter
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Allow users to request Server Groups by either name or ID. This aligns
us with the pattern of filters used for other resources such as Security
Groups and Ports.
Additionally `ReferencedResources` field is added to `BastionStatus` and
`OpenStackMachineStatus` as a container to hold all the IDs of resources
computed by the controllers. `ServerGroupID` is the first field added
there.
Co-Authored-By: Emilien Macchi
Co-Authored-By: Michał Dulko
Co-Authored-By: Stephen Finucane
---
api/v1alpha5/conversion.go | 31 ++-
api/v1alpha5/conversion_test.go | 2 +-
api/v1alpha5/zz_generated.conversion.go | 20 +-
api/v1alpha6/conversion.go | 63 ++++-
api/v1alpha6/zz_generated.conversion.go | 50 ++--
api/v1alpha7/conversion.go | 144 ++++++++++-
api/v1alpha7/conversion_test.go | 14 --
api/v1alpha7/zz_generated.conversion.go | 232 ++++++++++++------
api/v1alpha8/openstackmachine_types.go | 8 +-
api/v1alpha8/types.go | 25 +-
api/v1alpha8/zz_generated.deepcopy.go | 37 +++
...re.cluster.x-k8s.io_openstackclusters.yaml | 20 +-
...er.x-k8s.io_openstackclustertemplates.yaml | 11 +-
...re.cluster.x-k8s.io_openstackmachines.yaml | 20 +-
...er.x-k8s.io_openstackmachinetemplates.yaml | 11 +-
controllers/openstackmachine_controller.go | 8 +-
.../openstackmachine_controller_test.go | 7 +-
docs/book/src/development/development.md | 10 +
.../crd-changes/v1alpha7-to-v1alpha8.md | 51 ++++
pkg/clients/compute.go | 17 ++
pkg/clients/mock/compute.go | 16 ++
.../services/compute/referenced_resources.go | 42 ++++
.../compute/referenced_resources_test.go | 99 ++++++++
pkg/cloud/services/compute/servergroup.go | 71 ++++++
.../services/compute/servergroup_test.go | 128 ++++++++++
25 files changed, 975 insertions(+), 162 deletions(-)
create mode 100644 docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md
create mode 100644 pkg/cloud/services/compute/referenced_resources.go
create mode 100644 pkg/cloud/services/compute/referenced_resources_test.go
create mode 100644 pkg/cloud/services/compute/servergroup.go
create mode 100644 pkg/cloud/services/compute/servergroup_test.go
diff --git a/api/v1alpha5/conversion.go b/api/v1alpha5/conversion.go
index 77e39fa2eb..0d7ed69f41 100644
--- a/api/v1alpha5/conversion.go
+++ b/api/v1alpha5/conversion.go
@@ -213,7 +213,18 @@ func Convert_v1alpha8_PortOpts_To_v1alpha5_PortOpts(in *infrav1.PortOpts, out *P
}
func Convert_v1alpha5_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(in *OpenStackMachineSpec, out *infrav1.OpenStackMachineSpec, s conversion.Scope) error {
- return autoConvert_v1alpha5_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(in, out, s)
+ err := autoConvert_v1alpha5_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(in, out, s)
+ if err != nil {
+ return err
+ }
+
+ if in.ServerGroupID != "" {
+ out.ServerGroup = &infrav1.ServerGroupFilter{ID: in.ServerGroupID}
+ } else {
+ out.ServerGroup = &infrav1.ServerGroupFilter{}
+ }
+
+ return nil
}
func Convert_v1alpha8_APIServerLoadBalancer_To_v1alpha5_APIServerLoadBalancer(in *infrav1.APIServerLoadBalancer, out *APIServerLoadBalancer, s conversion.Scope) error {
@@ -246,6 +257,7 @@ func Convert_v1alpha5_Instance_To_v1alpha8_BastionStatus(in *Instance, out *infr
out.State = infrav1.InstanceState(in.State)
out.IP = in.IP
out.FloatingIP = in.FloatingIP
+ out.ReferencedResources.ServerGroupID = in.ServerGroupID
return nil
}
@@ -257,6 +269,7 @@ func Convert_v1alpha8_BastionStatus_To_v1alpha5_Instance(in *infrav1.BastionStat
out.State = InstanceState(in.State)
out.IP = in.IP
out.FloatingIP = in.FloatingIP
+ out.ServerGroupID = in.ReferencedResources.ServerGroupID
return nil
}
@@ -435,5 +448,19 @@ func Convert_v1alpha5_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterStatus(
}
func Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(in *infrav1.OpenStackMachineSpec, out *OpenStackMachineSpec, s conversion.Scope) error {
- return autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(in, out, s)
+ err := autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(in, out, s)
+ if err != nil {
+ return err
+ }
+
+ if in.ServerGroup != nil {
+ out.ServerGroupID = in.ServerGroup.ID
+ }
+
+ return nil
+}
+
+func Convert_v1alpha8_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineStatus(in *infrav1.OpenStackMachineStatus, out *OpenStackMachineStatus, s conversion.Scope) error {
+ // ReferencedResources have no equivalent in v1alpha5
+ return autoConvert_v1alpha8_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineStatus(in, out, s)
}
diff --git a/api/v1alpha5/conversion_test.go b/api/v1alpha5/conversion_test.go
index 95f83052dd..895af62b0d 100644
--- a/api/v1alpha5/conversion_test.go
+++ b/api/v1alpha5/conversion_test.go
@@ -79,7 +79,7 @@ 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\":{\"cloudName\":\"\",\"flavor\":\"\"},\"status\":{\"ready\":false,\"referencedResources\":{}}}",
},
},
},
diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go
index 5ef62e512e..7939a3ad41 100644
--- a/api/v1alpha5/zz_generated.conversion.go
+++ b/api/v1alpha5/zz_generated.conversion.go
@@ -199,11 +199,6 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*v1alpha8.OpenStackMachineStatus)(nil), (*OpenStackMachineStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineStatus(a.(*v1alpha8.OpenStackMachineStatus), b.(*OpenStackMachineStatus), scope)
- }); err != nil {
- return err
- }
if err := s.AddGeneratedConversionFunc((*OpenStackMachineTemplate)(nil), (*v1alpha8.OpenStackMachineTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha5_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate(a.(*OpenStackMachineTemplate), b.(*v1alpha8.OpenStackMachineTemplate), scope)
}); err != nil {
@@ -394,6 +389,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
+ if err := s.AddConversionFunc((*v1alpha8.OpenStackMachineStatus)(nil), (*OpenStackMachineStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineStatus(a.(*v1alpha8.OpenStackMachineStatus), b.(*OpenStackMachineStatus), scope)
+ }); err != nil {
+ return err
+ }
if err := s.AddConversionFunc((*v1alpha8.PortOpts)(nil), (*PortOpts)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha8_PortOpts_To_v1alpha5_PortOpts(a.(*v1alpha8.PortOpts), b.(*PortOpts), scope)
}); err != nil {
@@ -1094,7 +1094,7 @@ func autoConvert_v1alpha5_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(
out.ServerMetadata = *(*map[string]string)(unsafe.Pointer(&in.ServerMetadata))
out.ConfigDrive = (*bool)(unsafe.Pointer(in.ConfigDrive))
out.RootVolume = (*v1alpha8.RootVolume)(unsafe.Pointer(in.RootVolume))
- out.ServerGroupID = in.ServerGroupID
+ // WARNING: in.ServerGroupID requires manual conversion: does not exist in peer-type
out.IdentityRef = (*v1alpha8.OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef))
return nil
}
@@ -1136,7 +1136,7 @@ func autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(
out.ConfigDrive = (*bool)(unsafe.Pointer(in.ConfigDrive))
out.RootVolume = (*RootVolume)(unsafe.Pointer(in.RootVolume))
// WARNING: in.AdditionalBlockDevices requires manual conversion: does not exist in peer-type
- out.ServerGroupID = in.ServerGroupID
+ // WARNING: in.ServerGroup requires manual conversion: does not exist in peer-type
out.IdentityRef = (*OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef))
return nil
}
@@ -1160,17 +1160,13 @@ func autoConvert_v1alpha8_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineSta
out.Ready = in.Ready
out.Addresses = *(*[]v1.NodeAddress)(unsafe.Pointer(&in.Addresses))
out.InstanceState = (*InstanceState)(unsafe.Pointer(in.InstanceState))
+ // WARNING: in.ReferencedResources 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))
return nil
}
-// Convert_v1alpha8_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineStatus is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineStatus(in *v1alpha8.OpenStackMachineStatus, out *OpenStackMachineStatus, s conversion.Scope) error {
- return autoConvert_v1alpha8_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineStatus(in, out, s)
-}
-
func autoConvert_v1alpha5_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate(in *OpenStackMachineTemplate, out *v1alpha8.OpenStackMachineTemplate, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
if err := Convert_v1alpha5_OpenStackMachineTemplateSpec_To_v1alpha8_OpenStackMachineTemplateSpec(&in.Spec, &out.Spec, s); err != nil {
diff --git a/api/v1alpha6/conversion.go b/api/v1alpha6/conversion.go
index 9fa55afb1a..f981a8a692 100644
--- a/api/v1alpha6/conversion.go
+++ b/api/v1alpha6/conversion.go
@@ -61,6 +61,7 @@ func restorev1alpha8MachineSpec(previous *infrav1.OpenStackMachineSpec, dst *inf
// We restore the whole Ports since they are anyway immutable.
dst.Ports = previous.Ports
dst.AdditionalBlockDevices = previous.AdditionalBlockDevices
+ dst.ServerGroup = previous.ServerGroup
}
func restorev1alpha8Bastion(previous **infrav1.Bastion, dst **infrav1.Bastion) {
@@ -76,6 +77,10 @@ func restorev1alpha8ClusterStatus(previous *infrav1.OpenStackClusterStatus, dst
if previous.Network == nil && dst.Network != nil && reflect.ValueOf(*dst.Network).IsZero() {
dst.Network = nil
}
+
+ if previous.Bastion != nil {
+ dst.Bastion.ReferencedResources = previous.Bastion.ReferencedResources
+ }
}
func restorev1alpha6ClusterSpec(previous *OpenStackClusterSpec, dst *OpenStackClusterSpec) {
@@ -257,6 +262,13 @@ var v1alpha8OpenStackMachineRestorer = conversion.RestorerFor[*infrav1.OpenStack
},
restorev1alpha8MachineSpec,
),
+
+ // No equivalent in v1alpha6
+ "refresources": conversion.UnconditionalFieldRestorer(
+ func(c *infrav1.OpenStackMachine) *infrav1.ReferencedMachineResources {
+ return &c.Status.ReferencedResources
+ },
+ ),
}
func (r *OpenStackMachine) ConvertTo(dstRaw ctrlconversion.Hub) error {
@@ -354,6 +366,13 @@ func Convert_v1alpha6_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(in *
// Networks were previously created first, so need to come before ports
out.Ports = append(ports, out.Ports...)
}
+
+ if in.ServerGroupID != "" {
+ out.ServerGroup = &infrav1.ServerGroupFilter{ID: in.ServerGroupID}
+ } else {
+ out.ServerGroup = nil
+ }
+
return nil
}
@@ -649,5 +668,47 @@ func Convert_v1alpha6_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterStatus(
}
func Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(in *infrav1.OpenStackMachineSpec, out *OpenStackMachineSpec, s apiconversion.Scope) error {
- return autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(in, out, s)
+ err := autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(in, out, s)
+ if err != nil {
+ return err
+ }
+
+ if in.ServerGroup != nil {
+ out.ServerGroupID = in.ServerGroup.ID
+ }
+
+ return nil
+}
+
+func Convert_v1alpha8_OpenStackMachineStatus_To_v1alpha6_OpenStackMachineStatus(in *infrav1.OpenStackMachineStatus, out *OpenStackMachineStatus, s apiconversion.Scope) error {
+ // ReferencedResources have no equivalent in v1alpha6
+ return autoConvert_v1alpha8_OpenStackMachineStatus_To_v1alpha6_OpenStackMachineStatus(in, out, s)
+}
+
+func Convert_v1alpha6_Bastion_To_v1alpha8_Bastion(in *Bastion, out *infrav1.Bastion, s apiconversion.Scope) error {
+ err := autoConvert_v1alpha6_Bastion_To_v1alpha8_Bastion(in, out, s)
+ if err != nil {
+ return err
+ }
+
+ if in.Instance.ServerGroupID != "" {
+ out.Instance.ServerGroup = &infrav1.ServerGroupFilter{ID: in.Instance.ServerGroupID}
+ } else {
+ out.Instance.ServerGroup = nil
+ }
+
+ return nil
+}
+
+func Convert_v1alpha8_Bastion_To_v1alpha6_Bastion(in *infrav1.Bastion, out *Bastion, s apiconversion.Scope) error {
+ err := autoConvert_v1alpha8_Bastion_To_v1alpha6_Bastion(in, out, s)
+ if err != nil {
+ return err
+ }
+
+ if in.Instance.ServerGroup != nil && in.Instance.ServerGroup.ID != "" {
+ out.Instance.ServerGroupID = in.Instance.ServerGroup.ID
+ }
+
+ return nil
}
diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go
index ec1a8020f7..5382f4071c 100644
--- a/api/v1alpha6/zz_generated.conversion.go
+++ b/api/v1alpha6/zz_generated.conversion.go
@@ -59,16 +59,6 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*Bastion)(nil), (*v1alpha8.Bastion)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_Bastion_To_v1alpha8_Bastion(a.(*Bastion), b.(*v1alpha8.Bastion), scope)
- }); err != nil {
- return err
- }
- if err := s.AddGeneratedConversionFunc((*v1alpha8.Bastion)(nil), (*Bastion)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_Bastion_To_v1alpha6_Bastion(a.(*v1alpha8.Bastion), b.(*Bastion), scope)
- }); err != nil {
- return err
- }
if err := s.AddGeneratedConversionFunc((*ExternalRouterIPParam)(nil), (*v1alpha8.ExternalRouterIPParam)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha6_ExternalRouterIPParam_To_v1alpha8_ExternalRouterIPParam(a.(*ExternalRouterIPParam), b.(*v1alpha8.ExternalRouterIPParam), scope)
}); err != nil {
@@ -209,11 +199,6 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*v1alpha8.OpenStackMachineStatus)(nil), (*OpenStackMachineStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackMachineStatus_To_v1alpha6_OpenStackMachineStatus(a.(*v1alpha8.OpenStackMachineStatus), b.(*OpenStackMachineStatus), scope)
- }); err != nil {
- return err
- }
if err := s.AddGeneratedConversionFunc((*OpenStackMachineTemplate)(nil), (*v1alpha8.OpenStackMachineTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha6_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate(a.(*OpenStackMachineTemplate), b.(*v1alpha8.OpenStackMachineTemplate), scope)
}); err != nil {
@@ -329,6 +314,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
+ if err := s.AddConversionFunc((*Bastion)(nil), (*v1alpha8.Bastion)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_Bastion_To_v1alpha8_Bastion(a.(*Bastion), b.(*v1alpha8.Bastion), scope)
+ }); err != nil {
+ return err
+ }
if err := s.AddConversionFunc((*Instance)(nil), (*v1alpha8.BastionStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha6_Instance_To_v1alpha8_BastionStatus(a.(*Instance), b.(*v1alpha8.BastionStatus), scope)
}); err != nil {
@@ -379,6 +369,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
+ if err := s.AddConversionFunc((*v1alpha8.Bastion)(nil), (*Bastion)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_Bastion_To_v1alpha6_Bastion(a.(*v1alpha8.Bastion), b.(*Bastion), scope)
+ }); err != nil {
+ return err
+ }
if err := s.AddConversionFunc((*v1alpha8.NetworkStatusWithSubnets)(nil), (*Network)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha8_NetworkStatusWithSubnets_To_v1alpha6_Network(a.(*v1alpha8.NetworkStatusWithSubnets), b.(*Network), scope)
}); err != nil {
@@ -404,6 +399,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
+ if err := s.AddConversionFunc((*v1alpha8.OpenStackMachineStatus)(nil), (*OpenStackMachineStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackMachineStatus_To_v1alpha6_OpenStackMachineStatus(a.(*v1alpha8.OpenStackMachineStatus), b.(*OpenStackMachineStatus), scope)
+ }); err != nil {
+ return err
+ }
if err := s.AddConversionFunc((*v1alpha8.PortOpts)(nil), (*PortOpts)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha8_PortOpts_To_v1alpha6_PortOpts(a.(*v1alpha8.PortOpts), b.(*PortOpts), scope)
}); err != nil {
@@ -479,11 +479,6 @@ func autoConvert_v1alpha6_Bastion_To_v1alpha8_Bastion(in *Bastion, out *v1alpha8
return nil
}
-// Convert_v1alpha6_Bastion_To_v1alpha8_Bastion is an autogenerated conversion function.
-func Convert_v1alpha6_Bastion_To_v1alpha8_Bastion(in *Bastion, out *v1alpha8.Bastion, s conversion.Scope) error {
- return autoConvert_v1alpha6_Bastion_To_v1alpha8_Bastion(in, out, s)
-}
-
func autoConvert_v1alpha8_Bastion_To_v1alpha6_Bastion(in *v1alpha8.Bastion, out *Bastion, s conversion.Scope) error {
out.Enabled = in.Enabled
if err := Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(&in.Instance, &out.Instance, s); err != nil {
@@ -493,11 +488,6 @@ func autoConvert_v1alpha8_Bastion_To_v1alpha6_Bastion(in *v1alpha8.Bastion, out
return nil
}
-// Convert_v1alpha8_Bastion_To_v1alpha6_Bastion is an autogenerated conversion function.
-func Convert_v1alpha8_Bastion_To_v1alpha6_Bastion(in *v1alpha8.Bastion, out *Bastion, s conversion.Scope) error {
- return autoConvert_v1alpha8_Bastion_To_v1alpha6_Bastion(in, out, s)
-}
-
func autoConvert_v1alpha6_ExternalRouterIPParam_To_v1alpha8_ExternalRouterIPParam(in *ExternalRouterIPParam, out *v1alpha8.ExternalRouterIPParam, s conversion.Scope) error {
out.FixedIP = in.FixedIP
if err := Convert_v1alpha6_SubnetParam_To_v1alpha8_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil {
@@ -1117,7 +1107,7 @@ func autoConvert_v1alpha6_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(
out.ServerMetadata = *(*map[string]string)(unsafe.Pointer(&in.ServerMetadata))
out.ConfigDrive = (*bool)(unsafe.Pointer(in.ConfigDrive))
out.RootVolume = (*v1alpha8.RootVolume)(unsafe.Pointer(in.RootVolume))
- out.ServerGroupID = in.ServerGroupID
+ // WARNING: in.ServerGroupID requires manual conversion: does not exist in peer-type
out.IdentityRef = (*v1alpha8.OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef))
return nil
}
@@ -1159,7 +1149,7 @@ func autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(
out.ConfigDrive = (*bool)(unsafe.Pointer(in.ConfigDrive))
out.RootVolume = (*RootVolume)(unsafe.Pointer(in.RootVolume))
// WARNING: in.AdditionalBlockDevices requires manual conversion: does not exist in peer-type
- out.ServerGroupID = in.ServerGroupID
+ // WARNING: in.ServerGroup requires manual conversion: does not exist in peer-type
out.IdentityRef = (*OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef))
return nil
}
@@ -1183,17 +1173,13 @@ func autoConvert_v1alpha8_OpenStackMachineStatus_To_v1alpha6_OpenStackMachineSta
out.Ready = in.Ready
out.Addresses = *(*[]v1.NodeAddress)(unsafe.Pointer(&in.Addresses))
out.InstanceState = (*InstanceState)(unsafe.Pointer(in.InstanceState))
+ // WARNING: in.ReferencedResources 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))
return nil
}
-// Convert_v1alpha8_OpenStackMachineStatus_To_v1alpha6_OpenStackMachineStatus is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackMachineStatus_To_v1alpha6_OpenStackMachineStatus(in *v1alpha8.OpenStackMachineStatus, out *OpenStackMachineStatus, s conversion.Scope) error {
- return autoConvert_v1alpha8_OpenStackMachineStatus_To_v1alpha6_OpenStackMachineStatus(in, out, s)
-}
-
func autoConvert_v1alpha6_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate(in *OpenStackMachineTemplate, out *v1alpha8.OpenStackMachineTemplate, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
if err := Convert_v1alpha6_OpenStackMachineTemplateSpec_To_v1alpha8_OpenStackMachineTemplateSpec(&in.Spec, &out.Spec, s); err != nil {
diff --git a/api/v1alpha7/conversion.go b/api/v1alpha7/conversion.go
index 6677d7186a..1ad771bb02 100644
--- a/api/v1alpha7/conversion.go
+++ b/api/v1alpha7/conversion.go
@@ -17,6 +17,7 @@ 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/v1alpha8"
@@ -27,7 +28,48 @@ var _ ctrlconversion.Convertible = &OpenStackCluster{}
var v1alpha7OpenStackClusterRestorer = conversion.RestorerFor[*OpenStackCluster]{}
-var v1alpha8OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStackCluster]{}
+var v1alpha8OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStackCluster]{
+ "bastion": conversion.HashedFieldRestorer(
+ func(c *infrav1.OpenStackCluster) **infrav1.Bastion {
+ return &c.Spec.Bastion
+ },
+ restorev1alpha8Bastion,
+ ),
+ "spec": conversion.HashedFieldRestorer(
+ func(c *infrav1.OpenStackCluster) *infrav1.OpenStackClusterSpec {
+ return &c.Spec
+ },
+ restorev1alpha8ClusterSpec,
+ ),
+
+ // No equivalent in v1alpha7
+ "bastionrefresources": conversion.UnconditionalFieldRestorer(
+ func(c *infrav1.OpenStackCluster) *infrav1.ReferencedMachineResources {
+ if c.Status.Bastion == nil {
+ return nil
+ }
+ return &c.Status.Bastion.ReferencedResources
+ },
+ ),
+}
+
+func restorev1alpha8MachineSpec(previous *infrav1.OpenStackMachineSpec, dst *infrav1.OpenStackMachineSpec) {
+ dst.ServerGroup = previous.ServerGroup
+}
+
+func restorev1alpha8Bastion(previous **infrav1.Bastion, dst **infrav1.Bastion) {
+ if *previous != nil && *dst != nil {
+ restorev1alpha8MachineSpec(&(*previous).Instance, &(*dst).Instance)
+ }
+}
+
+func restorev1alpha8ClusterSpec(previous *infrav1.OpenStackClusterSpec, dst *infrav1.OpenStackClusterSpec) {
+ prevBastion := previous.Bastion
+ dstBastion := dst.Bastion
+ if prevBastion != nil && dstBastion != nil {
+ restorev1alpha8MachineSpec(&prevBastion.Instance, &dstBastion.Instance)
+ }
+}
func (r *OpenStackCluster) ConvertTo(dstRaw ctrlconversion.Hub) error {
dst := dstRaw.(*infrav1.OpenStackCluster)
@@ -67,7 +109,14 @@ var _ ctrlconversion.Convertible = &OpenStackClusterTemplate{}
var v1alpha7OpenStackClusterTemplateRestorer = conversion.RestorerFor[*OpenStackClusterTemplate]{}
-var v1alpha8OpenStackClusterTemplateRestorer = conversion.RestorerFor[*infrav1.OpenStackClusterTemplate]{}
+var v1alpha8OpenStackClusterTemplateRestorer = conversion.RestorerFor[*infrav1.OpenStackClusterTemplate]{
+ "bastion": conversion.HashedFieldRestorer(
+ func(c *infrav1.OpenStackClusterTemplate) **infrav1.Bastion {
+ return &c.Spec.Template.Spec.Bastion
+ },
+ restorev1alpha8Bastion,
+ ),
+}
func (r *OpenStackClusterTemplate) ConvertTo(dstRaw ctrlconversion.Hub) error {
dst := dstRaw.(*infrav1.OpenStackClusterTemplate)
@@ -93,7 +142,21 @@ var _ ctrlconversion.Convertible = &OpenStackMachine{}
var v1alpha7OpenStackMachineRestorer = conversion.RestorerFor[*OpenStackMachine]{}
-var v1alpha8OpenStackMachineRestorer = conversion.RestorerFor[*infrav1.OpenStackMachine]{}
+var v1alpha8OpenStackMachineRestorer = conversion.RestorerFor[*infrav1.OpenStackMachine]{
+ "spec": conversion.HashedFieldRestorer(
+ func(c *infrav1.OpenStackMachine) *infrav1.OpenStackMachineSpec {
+ return &c.Spec
+ },
+ restorev1alpha8MachineSpec,
+ ),
+
+ // No equivalent in v1alpha7
+ "refresources": conversion.UnconditionalFieldRestorer(
+ func(c *infrav1.OpenStackMachine) *infrav1.ReferencedMachineResources {
+ return &c.Status.ReferencedResources
+ },
+ ),
+}
func (r *OpenStackMachine) ConvertTo(dstRaw ctrlconversion.Hub) error {
dst := dstRaw.(*infrav1.OpenStackMachine)
@@ -131,7 +194,14 @@ var _ ctrlconversion.Convertible = &OpenStackMachineTemplate{}
var v1alpha7OpenStackMachineTemplateRestorer = conversion.RestorerFor[*OpenStackMachineTemplate]{}
-var v1alpha8OpenStackMachineTemplateRestorer = conversion.RestorerFor[*infrav1.OpenStackMachineTemplate]{}
+var v1alpha8OpenStackMachineTemplateRestorer = conversion.RestorerFor[*infrav1.OpenStackMachineTemplate]{
+ "spec": conversion.HashedFieldRestorer(
+ func(c *infrav1.OpenStackMachineTemplate) *infrav1.OpenStackMachineSpec {
+ return &c.Spec.Template.Spec
+ },
+ restorev1alpha8MachineSpec,
+ ),
+}
func (r *OpenStackMachineTemplate) ConvertTo(dstRaw ctrlconversion.Hub) error {
dst := dstRaw.(*infrav1.OpenStackMachineTemplate)
@@ -164,3 +234,69 @@ func (r *OpenStackMachineTemplateList) ConvertFrom(srcRaw ctrlconversion.Hub) er
src := srcRaw.(*infrav1.OpenStackMachineTemplateList)
return Convert_v1alpha8_OpenStackMachineTemplateList_To_v1alpha7_OpenStackMachineTemplateList(src, r, nil)
}
+
+func Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(in *infrav1.OpenStackMachineSpec, out *OpenStackMachineSpec, s apiconversion.Scope) error {
+ err := autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(in, out, s)
+ if err != nil {
+ return err
+ }
+
+ if in.ServerGroup != nil {
+ out.ServerGroupID = in.ServerGroup.ID
+ }
+
+ return nil
+}
+
+func Convert_v1alpha7_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(in *OpenStackMachineSpec, out *infrav1.OpenStackMachineSpec, s apiconversion.Scope) error {
+ err := autoConvert_v1alpha7_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(in, out, s)
+ if err != nil {
+ return err
+ }
+
+ if in.ServerGroupID != "" {
+ out.ServerGroup = &infrav1.ServerGroupFilter{ID: in.ServerGroupID}
+ } else {
+ out.ServerGroup = nil
+ }
+
+ return nil
+}
+
+func Convert_v1alpha8_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus(in *infrav1.OpenStackMachineStatus, out *OpenStackMachineStatus, s apiconversion.Scope) error {
+ // ReferencedResources have no equivalent in v1alpha7
+ return autoConvert_v1alpha8_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus(in, out, s)
+}
+
+func Convert_v1alpha8_BastionStatus_To_v1alpha7_BastionStatus(in *infrav1.BastionStatus, out *BastionStatus, s apiconversion.Scope) error {
+ // ReferencedResources have no equivalent in v1alpha7
+ return autoConvert_v1alpha8_BastionStatus_To_v1alpha7_BastionStatus(in, out, s)
+}
+
+func Convert_v1alpha7_Bastion_To_v1alpha8_Bastion(in *Bastion, out *infrav1.Bastion, s apiconversion.Scope) error {
+ err := autoConvert_v1alpha7_Bastion_To_v1alpha8_Bastion(in, out, s)
+ if err != nil {
+ return err
+ }
+
+ if in.Instance.ServerGroupID != "" {
+ out.Instance.ServerGroup = &infrav1.ServerGroupFilter{ID: in.Instance.ServerGroupID}
+ } else {
+ out.Instance.ServerGroup = nil
+ }
+
+ return nil
+}
+
+func Convert_v1alpha8_Bastion_To_v1alpha7_Bastion(in *infrav1.Bastion, out *Bastion, s apiconversion.Scope) error {
+ err := autoConvert_v1alpha8_Bastion_To_v1alpha7_Bastion(in, out, s)
+ if err != nil {
+ return err
+ }
+
+ if in.Instance.ServerGroup != nil && in.Instance.ServerGroup.ID != "" {
+ out.Instance.ServerGroupID = in.Instance.ServerGroup.ID
+ }
+
+ return nil
+}
diff --git a/api/v1alpha7/conversion_test.go b/api/v1alpha7/conversion_test.go
index ab032f20ff..8613db762b 100644
--- a/api/v1alpha7/conversion_test.go
+++ b/api/v1alpha7/conversion_test.go
@@ -19,12 +19,9 @@ package v1alpha7
import (
"testing"
- 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"
utilconversion "sigs.k8s.io/cluster-api/util/conversion"
"sigs.k8s.io/controller-runtime/pkg/conversion"
@@ -55,19 +52,10 @@ func TestFuzzyConversion(t *testing.T) {
delete(obj.GetAnnotations(), utilconversion.DataAnnotation)
}
- fuzzerFuncs := func(_ runtimeserializer.CodecFactory) []interface{} {
- return []interface{}{
- func(status *OpenStackClusterStatus, c fuzz.Continue) {
- c.FuzzNoCustom(status)
- },
- }
- }
-
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{
@@ -75,9 +63,7 @@ func TestFuzzyConversion(t *testing.T) {
Hub: &infrav1.OpenStackCluster{},
Spoke: &OpenStackCluster{},
HubAfterMutation: ignoreDataAnnotation,
- FuzzerFuncs: []fuzzer.FuzzerFuncs{fuzzerFuncs},
},
- MutateFuzzerFuncs: []fuzzer.FuzzerFuncs{fuzzerFuncs},
})))
t.Run("for OpenStackClusterTemplate", runParallel(utilconversion.FuzzTestFunc(utilconversion.FuzzTestFuncInput{
diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go
index 2d4a574a69..3739ade074 100644
--- a/api/v1alpha7/zz_generated.conversion.go
+++ b/api/v1alpha7/zz_generated.conversion.go
@@ -69,26 +69,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*Bastion)(nil), (*v1alpha8.Bastion)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_Bastion_To_v1alpha8_Bastion(a.(*Bastion), b.(*v1alpha8.Bastion), scope)
- }); err != nil {
- return err
- }
- if err := s.AddGeneratedConversionFunc((*v1alpha8.Bastion)(nil), (*Bastion)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_Bastion_To_v1alpha7_Bastion(a.(*v1alpha8.Bastion), b.(*Bastion), scope)
- }); err != nil {
- return err
- }
if err := s.AddGeneratedConversionFunc((*BastionStatus)(nil), (*v1alpha8.BastionStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha7_BastionStatus_To_v1alpha8_BastionStatus(a.(*BastionStatus), b.(*v1alpha8.BastionStatus), scope)
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*v1alpha8.BastionStatus)(nil), (*BastionStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_BastionStatus_To_v1alpha7_BastionStatus(a.(*v1alpha8.BastionStatus), b.(*BastionStatus), scope)
- }); err != nil {
- return err
- }
if err := s.AddGeneratedConversionFunc((*BindingProfile)(nil), (*v1alpha8.BindingProfile)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha7_BindingProfile_To_v1alpha8_BindingProfile(a.(*BindingProfile), b.(*v1alpha8.BindingProfile), scope)
}); err != nil {
@@ -289,26 +274,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*OpenStackMachineSpec)(nil), (*v1alpha8.OpenStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(a.(*OpenStackMachineSpec), b.(*v1alpha8.OpenStackMachineSpec), scope)
- }); err != nil {
- return err
- }
- if err := s.AddGeneratedConversionFunc((*v1alpha8.OpenStackMachineSpec)(nil), (*OpenStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(a.(*v1alpha8.OpenStackMachineSpec), b.(*OpenStackMachineSpec), scope)
- }); err != nil {
- return err
- }
if err := s.AddGeneratedConversionFunc((*OpenStackMachineStatus)(nil), (*v1alpha8.OpenStackMachineStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha7_OpenStackMachineStatus_To_v1alpha8_OpenStackMachineStatus(a.(*OpenStackMachineStatus), b.(*v1alpha8.OpenStackMachineStatus), scope)
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*v1alpha8.OpenStackMachineStatus)(nil), (*OpenStackMachineStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus(a.(*v1alpha8.OpenStackMachineStatus), b.(*OpenStackMachineStatus), scope)
- }); err != nil {
- return err
- }
if err := s.AddGeneratedConversionFunc((*OpenStackMachineTemplate)(nil), (*v1alpha8.OpenStackMachineTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha7_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate(a.(*OpenStackMachineTemplate), b.(*v1alpha8.OpenStackMachineTemplate), scope)
}); err != nil {
@@ -449,6 +419,36 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
+ if err := s.AddConversionFunc((*Bastion)(nil), (*v1alpha8.Bastion)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_Bastion_To_v1alpha8_Bastion(a.(*Bastion), b.(*v1alpha8.Bastion), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddConversionFunc((*OpenStackMachineSpec)(nil), (*v1alpha8.OpenStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(a.(*OpenStackMachineSpec), b.(*v1alpha8.OpenStackMachineSpec), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddConversionFunc((*v1alpha8.BastionStatus)(nil), (*BastionStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_BastionStatus_To_v1alpha7_BastionStatus(a.(*v1alpha8.BastionStatus), b.(*BastionStatus), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddConversionFunc((*v1alpha8.Bastion)(nil), (*Bastion)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_Bastion_To_v1alpha7_Bastion(a.(*v1alpha8.Bastion), b.(*Bastion), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddConversionFunc((*v1alpha8.OpenStackMachineSpec)(nil), (*OpenStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(a.(*v1alpha8.OpenStackMachineSpec), b.(*OpenStackMachineSpec), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddConversionFunc((*v1alpha8.OpenStackMachineStatus)(nil), (*OpenStackMachineStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus(a.(*v1alpha8.OpenStackMachineStatus), b.(*OpenStackMachineStatus), scope)
+ }); err != nil {
+ return err
+ }
return nil
}
@@ -537,11 +537,6 @@ func autoConvert_v1alpha7_Bastion_To_v1alpha8_Bastion(in *Bastion, out *v1alpha8
return nil
}
-// Convert_v1alpha7_Bastion_To_v1alpha8_Bastion is an autogenerated conversion function.
-func Convert_v1alpha7_Bastion_To_v1alpha8_Bastion(in *Bastion, out *v1alpha8.Bastion, s conversion.Scope) error {
- return autoConvert_v1alpha7_Bastion_To_v1alpha8_Bastion(in, out, s)
-}
-
func autoConvert_v1alpha8_Bastion_To_v1alpha7_Bastion(in *v1alpha8.Bastion, out *Bastion, s conversion.Scope) error {
out.Enabled = in.Enabled
if err := Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(&in.Instance, &out.Instance, s); err != nil {
@@ -551,11 +546,6 @@ func autoConvert_v1alpha8_Bastion_To_v1alpha7_Bastion(in *v1alpha8.Bastion, out
return nil
}
-// Convert_v1alpha8_Bastion_To_v1alpha7_Bastion is an autogenerated conversion function.
-func Convert_v1alpha8_Bastion_To_v1alpha7_Bastion(in *v1alpha8.Bastion, out *Bastion, s conversion.Scope) error {
- return autoConvert_v1alpha8_Bastion_To_v1alpha7_Bastion(in, out, s)
-}
-
func autoConvert_v1alpha7_BastionStatus_To_v1alpha8_BastionStatus(in *BastionStatus, out *v1alpha8.BastionStatus, s conversion.Scope) error {
out.ID = in.ID
out.Name = in.Name
@@ -578,14 +568,10 @@ func autoConvert_v1alpha8_BastionStatus_To_v1alpha7_BastionStatus(in *v1alpha8.B
out.State = InstanceState(in.State)
out.IP = in.IP
out.FloatingIP = in.FloatingIP
+ // WARNING: in.ReferencedResources requires manual conversion: does not exist in peer-type
return nil
}
-// Convert_v1alpha8_BastionStatus_To_v1alpha7_BastionStatus is an autogenerated conversion function.
-func Convert_v1alpha8_BastionStatus_To_v1alpha7_BastionStatus(in *v1alpha8.BastionStatus, out *BastionStatus, s conversion.Scope) error {
- return autoConvert_v1alpha8_BastionStatus_To_v1alpha7_BastionStatus(in, out, s)
-}
-
func autoConvert_v1alpha7_BindingProfile_To_v1alpha8_BindingProfile(in *BindingProfile, out *v1alpha8.BindingProfile, s conversion.Scope) error {
out.OVSHWOffload = in.OVSHWOffload
out.TrustedVF = in.TrustedVF
@@ -848,7 +834,17 @@ func Convert_v1alpha8_OpenStackCluster_To_v1alpha7_OpenStackCluster(in *v1alpha8
func autoConvert_v1alpha7_OpenStackClusterList_To_v1alpha8_OpenStackClusterList(in *OpenStackClusterList, out *v1alpha8.OpenStackClusterList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
- out.Items = *(*[]v1alpha8.OpenStackCluster)(unsafe.Pointer(&in.Items))
+ if in.Items != nil {
+ in, out := &in.Items, &out.Items
+ *out = make([]v1alpha8.OpenStackCluster, len(*in))
+ for i := range *in {
+ if err := Convert_v1alpha7_OpenStackCluster_To_v1alpha8_OpenStackCluster(&(*in)[i], &(*out)[i], s); err != nil {
+ return err
+ }
+ }
+ } else {
+ out.Items = nil
+ }
return nil
}
@@ -859,7 +855,17 @@ func Convert_v1alpha7_OpenStackClusterList_To_v1alpha8_OpenStackClusterList(in *
func autoConvert_v1alpha8_OpenStackClusterList_To_v1alpha7_OpenStackClusterList(in *v1alpha8.OpenStackClusterList, out *OpenStackClusterList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
- out.Items = *(*[]OpenStackCluster)(unsafe.Pointer(&in.Items))
+ if in.Items != nil {
+ in, out := &in.Items, &out.Items
+ *out = make([]OpenStackCluster, len(*in))
+ for i := range *in {
+ if err := Convert_v1alpha8_OpenStackCluster_To_v1alpha7_OpenStackCluster(&(*in)[i], &(*out)[i], s); err != nil {
+ return err
+ }
+ }
+ } else {
+ out.Items = nil
+ }
return nil
}
@@ -896,7 +902,15 @@ func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(
out.ControlPlaneEndpoint = in.ControlPlaneEndpoint
out.ControlPlaneAvailabilityZones = *(*[]string)(unsafe.Pointer(&in.ControlPlaneAvailabilityZones))
out.ControlPlaneOmitAvailabilityZone = in.ControlPlaneOmitAvailabilityZone
- out.Bastion = (*v1alpha8.Bastion)(unsafe.Pointer(in.Bastion))
+ if in.Bastion != nil {
+ in, out := &in.Bastion, &out.Bastion
+ *out = new(v1alpha8.Bastion)
+ if err := Convert_v1alpha7_Bastion_To_v1alpha8_Bastion(*in, *out, s); err != nil {
+ return err
+ }
+ } else {
+ out.Bastion = nil
+ }
out.IdentityRef = (*v1alpha8.OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef))
return nil
}
@@ -934,7 +948,15 @@ func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(
out.ControlPlaneEndpoint = in.ControlPlaneEndpoint
out.ControlPlaneAvailabilityZones = *(*[]string)(unsafe.Pointer(&in.ControlPlaneAvailabilityZones))
out.ControlPlaneOmitAvailabilityZone = in.ControlPlaneOmitAvailabilityZone
- out.Bastion = (*Bastion)(unsafe.Pointer(in.Bastion))
+ if in.Bastion != nil {
+ in, out := &in.Bastion, &out.Bastion
+ *out = new(Bastion)
+ if err := Convert_v1alpha8_Bastion_To_v1alpha7_Bastion(*in, *out, s); err != nil {
+ return err
+ }
+ } else {
+ out.Bastion = nil
+ }
out.IdentityRef = (*OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef))
return nil
}
@@ -954,7 +976,15 @@ func autoConvert_v1alpha7_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterSta
out.ControlPlaneSecurityGroup = (*v1alpha8.SecurityGroup)(unsafe.Pointer(in.ControlPlaneSecurityGroup))
out.WorkerSecurityGroup = (*v1alpha8.SecurityGroup)(unsafe.Pointer(in.WorkerSecurityGroup))
out.BastionSecurityGroup = (*v1alpha8.SecurityGroup)(unsafe.Pointer(in.BastionSecurityGroup))
- out.Bastion = (*v1alpha8.BastionStatus)(unsafe.Pointer(in.Bastion))
+ if in.Bastion != nil {
+ in, out := &in.Bastion, &out.Bastion
+ *out = new(v1alpha8.BastionStatus)
+ if err := Convert_v1alpha7_BastionStatus_To_v1alpha8_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
@@ -975,7 +1005,15 @@ func autoConvert_v1alpha8_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterSta
out.ControlPlaneSecurityGroup = (*SecurityGroup)(unsafe.Pointer(in.ControlPlaneSecurityGroup))
out.WorkerSecurityGroup = (*SecurityGroup)(unsafe.Pointer(in.WorkerSecurityGroup))
out.BastionSecurityGroup = (*SecurityGroup)(unsafe.Pointer(in.BastionSecurityGroup))
- out.Bastion = (*BastionStatus)(unsafe.Pointer(in.Bastion))
+ if in.Bastion != nil {
+ in, out := &in.Bastion, &out.Bastion
+ *out = new(BastionStatus)
+ if err := Convert_v1alpha8_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
@@ -1014,7 +1052,17 @@ func Convert_v1alpha8_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTempl
func autoConvert_v1alpha7_OpenStackClusterTemplateList_To_v1alpha8_OpenStackClusterTemplateList(in *OpenStackClusterTemplateList, out *v1alpha8.OpenStackClusterTemplateList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
- out.Items = *(*[]v1alpha8.OpenStackClusterTemplate)(unsafe.Pointer(&in.Items))
+ if in.Items != nil {
+ in, out := &in.Items, &out.Items
+ *out = make([]v1alpha8.OpenStackClusterTemplate, len(*in))
+ for i := range *in {
+ if err := Convert_v1alpha7_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate(&(*in)[i], &(*out)[i], s); err != nil {
+ return err
+ }
+ }
+ } else {
+ out.Items = nil
+ }
return nil
}
@@ -1025,7 +1073,17 @@ func Convert_v1alpha7_OpenStackClusterTemplateList_To_v1alpha8_OpenStackClusterT
func autoConvert_v1alpha8_OpenStackClusterTemplateList_To_v1alpha7_OpenStackClusterTemplateList(in *v1alpha8.OpenStackClusterTemplateList, out *OpenStackClusterTemplateList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
- out.Items = *(*[]OpenStackClusterTemplate)(unsafe.Pointer(&in.Items))
+ if in.Items != nil {
+ in, out := &in.Items, &out.Items
+ *out = make([]OpenStackClusterTemplate, len(*in))
+ for i := range *in {
+ if err := Convert_v1alpha8_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate(&(*in)[i], &(*out)[i], s); err != nil {
+ return err
+ }
+ }
+ } else {
+ out.Items = nil
+ }
return nil
}
@@ -1138,7 +1196,17 @@ func Convert_v1alpha8_OpenStackMachine_To_v1alpha7_OpenStackMachine(in *v1alpha8
func autoConvert_v1alpha7_OpenStackMachineList_To_v1alpha8_OpenStackMachineList(in *OpenStackMachineList, out *v1alpha8.OpenStackMachineList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
- out.Items = *(*[]v1alpha8.OpenStackMachine)(unsafe.Pointer(&in.Items))
+ if in.Items != nil {
+ in, out := &in.Items, &out.Items
+ *out = make([]v1alpha8.OpenStackMachine, len(*in))
+ for i := range *in {
+ if err := Convert_v1alpha7_OpenStackMachine_To_v1alpha8_OpenStackMachine(&(*in)[i], &(*out)[i], s); err != nil {
+ return err
+ }
+ }
+ } else {
+ out.Items = nil
+ }
return nil
}
@@ -1149,7 +1217,17 @@ func Convert_v1alpha7_OpenStackMachineList_To_v1alpha8_OpenStackMachineList(in *
func autoConvert_v1alpha8_OpenStackMachineList_To_v1alpha7_OpenStackMachineList(in *v1alpha8.OpenStackMachineList, out *OpenStackMachineList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
- out.Items = *(*[]OpenStackMachine)(unsafe.Pointer(&in.Items))
+ if in.Items != nil {
+ in, out := &in.Items, &out.Items
+ *out = make([]OpenStackMachine, len(*in))
+ for i := range *in {
+ if err := Convert_v1alpha8_OpenStackMachine_To_v1alpha7_OpenStackMachine(&(*in)[i], &(*out)[i], s); err != nil {
+ return err
+ }
+ }
+ } else {
+ out.Items = nil
+ }
return nil
}
@@ -1175,16 +1253,11 @@ func autoConvert_v1alpha7_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(
out.ConfigDrive = (*bool)(unsafe.Pointer(in.ConfigDrive))
out.RootVolume = (*v1alpha8.RootVolume)(unsafe.Pointer(in.RootVolume))
out.AdditionalBlockDevices = *(*[]v1alpha8.AdditionalBlockDevice)(unsafe.Pointer(&in.AdditionalBlockDevices))
- out.ServerGroupID = in.ServerGroupID
+ // WARNING: in.ServerGroupID requires manual conversion: does not exist in peer-type
out.IdentityRef = (*v1alpha8.OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef))
return nil
}
-// Convert_v1alpha7_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec is an autogenerated conversion function.
-func Convert_v1alpha7_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(in *OpenStackMachineSpec, out *v1alpha8.OpenStackMachineSpec, s conversion.Scope) error {
- return autoConvert_v1alpha7_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(in, out, s)
-}
-
func autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(in *v1alpha8.OpenStackMachineSpec, out *OpenStackMachineSpec, s conversion.Scope) error {
out.ProviderID = (*string)(unsafe.Pointer(in.ProviderID))
out.InstanceID = (*string)(unsafe.Pointer(in.InstanceID))
@@ -1202,16 +1275,11 @@ func autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(
out.ConfigDrive = (*bool)(unsafe.Pointer(in.ConfigDrive))
out.RootVolume = (*RootVolume)(unsafe.Pointer(in.RootVolume))
out.AdditionalBlockDevices = *(*[]AdditionalBlockDevice)(unsafe.Pointer(&in.AdditionalBlockDevices))
- out.ServerGroupID = in.ServerGroupID
+ // WARNING: in.ServerGroup requires manual conversion: does not exist in peer-type
out.IdentityRef = (*OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef))
return nil
}
-// Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(in *v1alpha8.OpenStackMachineSpec, out *OpenStackMachineSpec, s conversion.Scope) error {
- return autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(in, out, s)
-}
-
func autoConvert_v1alpha7_OpenStackMachineStatus_To_v1alpha8_OpenStackMachineStatus(in *OpenStackMachineStatus, out *v1alpha8.OpenStackMachineStatus, s conversion.Scope) error {
out.Ready = in.Ready
out.Addresses = *(*[]v1.NodeAddress)(unsafe.Pointer(&in.Addresses))
@@ -1231,17 +1299,13 @@ func autoConvert_v1alpha8_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineSta
out.Ready = in.Ready
out.Addresses = *(*[]v1.NodeAddress)(unsafe.Pointer(&in.Addresses))
out.InstanceState = (*InstanceState)(unsafe.Pointer(in.InstanceState))
+ // WARNING: in.ReferencedResources 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))
return nil
}
-// Convert_v1alpha8_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus(in *v1alpha8.OpenStackMachineStatus, out *OpenStackMachineStatus, s conversion.Scope) error {
- return autoConvert_v1alpha8_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus(in, out, s)
-}
-
func autoConvert_v1alpha7_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate(in *OpenStackMachineTemplate, out *v1alpha8.OpenStackMachineTemplate, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
if err := Convert_v1alpha7_OpenStackMachineTemplateSpec_To_v1alpha8_OpenStackMachineTemplateSpec(&in.Spec, &out.Spec, s); err != nil {
@@ -1270,7 +1334,17 @@ func Convert_v1alpha8_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTempl
func autoConvert_v1alpha7_OpenStackMachineTemplateList_To_v1alpha8_OpenStackMachineTemplateList(in *OpenStackMachineTemplateList, out *v1alpha8.OpenStackMachineTemplateList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
- out.Items = *(*[]v1alpha8.OpenStackMachineTemplate)(unsafe.Pointer(&in.Items))
+ if in.Items != nil {
+ in, out := &in.Items, &out.Items
+ *out = make([]v1alpha8.OpenStackMachineTemplate, len(*in))
+ for i := range *in {
+ if err := Convert_v1alpha7_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate(&(*in)[i], &(*out)[i], s); err != nil {
+ return err
+ }
+ }
+ } else {
+ out.Items = nil
+ }
return nil
}
@@ -1281,7 +1355,17 @@ func Convert_v1alpha7_OpenStackMachineTemplateList_To_v1alpha8_OpenStackMachineT
func autoConvert_v1alpha8_OpenStackMachineTemplateList_To_v1alpha7_OpenStackMachineTemplateList(in *v1alpha8.OpenStackMachineTemplateList, out *OpenStackMachineTemplateList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
- out.Items = *(*[]OpenStackMachineTemplate)(unsafe.Pointer(&in.Items))
+ if in.Items != nil {
+ in, out := &in.Items, &out.Items
+ *out = make([]OpenStackMachineTemplate, len(*in))
+ for i := range *in {
+ if err := Convert_v1alpha8_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate(&(*in)[i], &(*out)[i], s); err != nil {
+ return err
+ }
+ }
+ } else {
+ out.Items = nil
+ }
return nil
}
diff --git a/api/v1alpha8/openstackmachine_types.go b/api/v1alpha8/openstackmachine_types.go
index 8a7c97d406..317a2d9782 100644
--- a/api/v1alpha8/openstackmachine_types.go
+++ b/api/v1alpha8/openstackmachine_types.go
@@ -90,8 +90,9 @@ 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 *ServerGroupFilter `json:"serverGroup,omitempty"`
// IdentityRef is a reference to a identity to be used when reconciling this cluster
// +optional
@@ -111,6 +112,9 @@ type OpenStackMachineStatus struct {
// +optional
InstanceState *InstanceState `json:"instanceState,omitempty"`
+ // ReferencedResources contains resolved references to resources that the machine depends on.
+ ReferencedResources ReferencedMachineResources `json:"referencedResources,omitempty"`
+
FailureReason *errors.MachineStatusError `json:"failureReason,omitempty"`
// FailureMessage will be set in the event that there is a terminal problem
diff --git a/api/v1alpha8/types.go b/api/v1alpha8/types.go
index a6d949cb0a..cccf992e70 100644
--- a/api/v1alpha8/types.go
+++ b/api/v1alpha8/types.go
@@ -149,12 +149,13 @@ type AddressPair struct {
}
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"`
+ 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"`
+ ReferencedResources ReferencedMachineResources `json:"referencedResources,omitempty"`
}
type RootVolume struct {
@@ -215,6 +216,11 @@ type AdditionalBlockDevice struct {
Storage BlockDeviceStorage `json:"storage"`
}
+type ServerGroupFilter struct {
+ ID string `json:"id,omitempty"`
+ Name string `json:"name,omitempty"`
+}
+
// BlockDeviceType defines the type of block device to create.
type BlockDeviceType string
@@ -357,6 +363,13 @@ type APIServerLoadBalancer struct {
Provider string `json:"provider,omitempty"`
}
+// ReferencedMachineResources contains resolved references to resources required by the machine.
+type ReferencedMachineResources 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"`
+}
+
// ValueSpec represents a single value_spec key-value pair.
type ValueSpec struct {
// Name is the name of the key-value pair.
diff --git a/api/v1alpha8/zz_generated.deepcopy.go b/api/v1alpha8/zz_generated.deepcopy.go
index 3ded212691..a25da87fd4 100644
--- a/api/v1alpha8/zz_generated.deepcopy.go
+++ b/api/v1alpha8/zz_generated.deepcopy.go
@@ -102,6 +102,7 @@ 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
+ out.ReferencedResources = in.ReferencedResources
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BastionStatus.
@@ -686,6 +687,11 @@ func (in *OpenStackMachineSpec) DeepCopyInto(out *OpenStackMachineSpec) {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
+ if in.ServerGroup != nil {
+ in, out := &in.ServerGroup, &out.ServerGroup
+ *out = new(ServerGroupFilter)
+ **out = **in
+ }
if in.IdentityRef != nil {
in, out := &in.IdentityRef, &out.IdentityRef
*out = new(OpenStackIdentityReference)
@@ -716,6 +722,7 @@ func (in *OpenStackMachineStatus) DeepCopyInto(out *OpenStackMachineStatus) {
*out = new(InstanceState)
**out = **in
}
+ out.ReferencedResources = in.ReferencedResources
if in.FailureReason != nil {
in, out := &in.FailureReason, &out.FailureReason
*out = new(errors.MachineStatusError)
@@ -903,6 +910,21 @@ func (in *PortOpts) DeepCopy() *PortOpts {
return out
}
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ReferencedMachineResources) DeepCopyInto(out *ReferencedMachineResources) {
+ *out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReferencedMachineResources.
+func (in *ReferencedMachineResources) DeepCopy() *ReferencedMachineResources {
+ if in == nil {
+ return nil
+ }
+ out := new(ReferencedMachineResources)
+ in.DeepCopyInto(out)
+ return out
+}
+
// 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
@@ -1008,6 +1030,21 @@ func (in *SecurityGroupRule) DeepCopy() *SecurityGroupRule {
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
+}
+
+// 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 *Subnet) DeepCopyInto(out *Subnet) {
*out = *in
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 532490a5ea..9ce8a7259d 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -5156,9 +5156,14 @@ spec:
type: string
type: object
type: array
- serverGroupID:
- description: The server group to assign the machine to
- type: string
+ serverGroup:
+ description: The server group to assign the machine to.
+ properties:
+ id:
+ type: string
+ name:
+ type: string
+ type: object
serverMetadata:
additionalProperties:
type: string
@@ -5447,6 +5452,15 @@ spec:
type: string
name:
type: string
+ referencedResources:
+ description: ReferencedMachineResources contains resolved references
+ to resources required by the machine.
+ properties:
+ 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
sshKeyName:
type: string
state:
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 73f10af04d..f37bc32494 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -2698,10 +2698,15 @@ spec:
type: string
type: object
type: array
- serverGroupID:
+ serverGroup:
description: The server group to assign the machine
- to
- type: string
+ to.
+ properties:
+ id:
+ type: string
+ name:
+ type: string
+ type: object
serverMetadata:
additionalProperties:
type: string
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 a9b90ba429..2529ebc65e 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
@@ -1986,9 +1986,14 @@ spec:
type: string
type: object
type: array
- serverGroupID:
- description: The server group to assign the machine to
- type: string
+ serverGroup:
+ description: The server group to assign the machine to.
+ properties:
+ id:
+ type: string
+ name:
+ type: string
+ type: object
serverMetadata:
additionalProperties:
type: string
@@ -2104,6 +2109,15 @@ spec:
ready:
description: Ready is true when the provider resource is ready.
type: boolean
+ referencedResources:
+ description: ReferencedResources contains resolved references to resources
+ that the machine depends on.
+ properties:
+ 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
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 f60aff2895..cc2baec78b 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
@@ -1708,9 +1708,14 @@ spec:
type: string
type: object
type: array
- serverGroupID:
- description: The server group to assign the machine to
- type: string
+ serverGroup:
+ description: The server group to assign the machine to.
+ properties:
+ id:
+ type: string
+ name:
+ type: string
+ type: object
serverMetadata:
additionalProperties:
type: string
diff --git a/controllers/openstackmachine_controller.go b/controllers/openstackmachine_controller.go
index d5acde67cb..69cd7c8429 100644
--- a/controllers/openstackmachine_controller.go
+++ b/controllers/openstackmachine_controller.go
@@ -145,6 +145,12 @@ func (r *OpenStackMachineReconciler) Reconcile(ctx context.Context, req ctrl.Req
return reconcile.Result{}, err
}
+ // Resolve and store referenced resources
+ err = compute.ResolveReferencedMachineResources(scope, &openStackMachine.Spec, &openStackMachine.Status.ReferencedResources)
+ if err != nil {
+ return reconcile.Result{}, err
+ }
+
// Handle deleted machines
if !openStackMachine.DeletionTimestamp.IsZero() {
return r.reconcileDelete(scope, cluster, infraCluster, machine, openStackMachine)
@@ -463,7 +469,7 @@ func machineToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, machine *
ConfigDrive: openStackMachine.Spec.ConfigDrive != nil && *openStackMachine.Spec.ConfigDrive,
RootVolume: openStackMachine.Spec.RootVolume,
AdditionalBlockDevices: openStackMachine.Spec.AdditionalBlockDevices,
- ServerGroupID: openStackMachine.Spec.ServerGroupID,
+ ServerGroupID: openStackMachine.Status.ReferencedResources.ServerGroupID,
Trunk: openStackMachine.Spec.Trunk,
}
diff --git a/controllers/openstackmachine_controller_test.go b/controllers/openstackmachine_controller_test.go
index c78ab8643c..cfdeed7bcf 100644
--- a/controllers/openstackmachine_controller_test.go
+++ b/controllers/openstackmachine_controller_test.go
@@ -91,7 +91,12 @@ func getDefaultOpenStackMachine() *infrav1.OpenStackMachine {
},
ConfigDrive: pointer.Bool(true),
SecurityGroups: []infrav1.SecurityGroupFilter{},
- ServerGroupID: serverGroupUUID,
+ ServerGroup: &infrav1.ServerGroupFilter{ID: serverGroupUUID},
+ },
+ Status: infrav1.OpenStackMachineStatus{
+ ReferencedResources: infrav1.ReferencedMachineResources{
+ ServerGroupID: serverGroupUUID,
+ },
},
}
}
diff --git a/docs/book/src/development/development.md b/docs/book/src/development/development.md
index 61497b9ee9..f8719c9178 100644
--- a/docs/book/src/development/development.md
+++ b/docs/book/src/development/development.md
@@ -341,3 +341,13 @@ $ sudo ln -s /run/user/$(id -u)/podman/podman.sock /var/run/docker.sock
[hack-ci-create-devstack]: https://github.com/kubernetes-sigs/cluster-api-provider-openstack/blob/main/hack/ci/create_devstack.sh
[hack-ci-gce-project]: https://github.com/kubernetes-sigs/cluster-api-provider-openstack/blob/main/hack/ci/gce-project.sh
[hack-ci-openstack]: https://github.com/kubernetes-sigs/cluster-api-provider-openstack/blob/main/hack/ci/openstack.sh
+
+## API concepts
+
+This sections goal is to gather various insights into the API design that can serve as a reference to explain various choices made without need to analyze discussions in individual PRs.
+
+### `referencedResources`
+
+Starting from v1alpha8 both `OpenStackMachineStatus` and `BastionsStatus` feature a field named `referencedResources` which aims to include fields that list individual IDs of the resources associated with the machine or bastion. These IDs are calculated on machine or bastion creation and are not intended to be changed during the object lifecycle.
+
+Having all the IDs of related resources saved in the statuses allows CAPO to make easy decisions about deleting the related resources when deleting the VM corresponding to the machine or bastion.
\ No newline at end of file
diff --git a/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md b/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md
new file mode 100644
index 0000000000..e52885b5f4
--- /dev/null
+++ b/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md
@@ -0,0 +1,51 @@
+
+
+**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
+
+- [v1alpha7 compared to v1alpha8](#v1alpha7-compared-to-v1alpha8)
+ - [Migration](#migration)
+ - [API Changes](#api-changes)
+ - [`OpenStackMachine`](#openstackmachine)
+ - [Change to `serverGroupID`](#change-to-servergroupid)
+
+
+
+# v1alpha7 compared to v1alpha8
+
+> ⚠️ v1alpha8 has not been released yet.
+## Migration
+
+All users are encouraged to migrate their usage of the CAPO CRDs from older versions to `v1alpha8`. This includes yaml files and source code. As CAPO implements automatic conversions between the CRD versions, this migration can happen after installing the new CAPO release.
+
+## API Changes
+
+This only documents backwards incompatible changes. Fields that were added to v1alpha8 are not listed here.
+
+### `OpenStackMachine`
+
+#### ⚠️ Change to `serverGroupID`
+
+The field `serverGroupID` has been renamed to `serverGroup` and is now a `ServerGroupFilter` object rather than a string ID.
+
+The `ServerGroupFilter` object allows selection of a server group by name or by ID.
+
+```yaml
+serverGroupID: "e60f19e7-cb37-49f9-a2ee-0a1281f6e03e"
+```
+
+becomes
+
+```yaml
+serverGroup:
+ id: "e60f19e7-cb37-49f9-a2ee-0a1281f6e03e"
+```
+
+To select a server group by name instead of ID:
+
+```yaml
+serverGroup:
+ name: "workers"
+```
+
+If a server group is provided and found, it'll be added to `OpenStackMachine.Status.ReferencedResources.ServerGroupID`. If the server group can't be found or filter matches multiple server groups, an error will be returned.
+If empty object or null is provided, Machine will not be added to any server group and `OpenStackMachine.Status.ReferencedResources.ServerGroupID` will be empty.
\ No newline at end of file
diff --git a/pkg/clients/compute.go b/pkg/clients/compute.go
index 0fbd20de31..64ae059fc7 100644
--- a/pkg/clients/compute.go
+++ b/pkg/clients/compute.go
@@ -23,6 +23,7 @@ import (
"github.com/gophercloud/gophercloud/openstack"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/attachinterfaces"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/availabilityzones"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/servergroups"
"github.com/gophercloud/gophercloud/openstack/compute/v2/flavors"
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
"github.com/gophercloud/utils/openstack/clientconfig"
@@ -60,6 +61,8 @@ type ComputeClient interface {
ListAttachedInterfaces(serverID string) ([]attachinterfaces.Interface, error)
DeleteAttachedInterface(serverID, portID string) error
+
+ ListServerGroups() ([]servergroups.ServerGroup, error)
}
type computeClient struct{ client *gophercloud.ServiceClient }
@@ -149,6 +152,16 @@ func (c computeClient) DeleteAttachedInterface(serverID, portID string) error {
return mc.ObserveRequestIgnoreNotFoundorConflict(err)
}
+func (c computeClient) ListServerGroups() ([]servergroups.ServerGroup, error) {
+ mc := metrics.NewMetricPrometheusContext("server_group", "list")
+ opts := servergroups.ListOpts{}
+ allPages, err := servergroups.List(c.client, opts).AllPages()
+ if mc.ObserveRequest(err) != nil {
+ return nil, err
+ }
+ return servergroups.ExtractServerGroups(allPages)
+}
+
type computeErrorClient struct{ error }
// NewComputeErrorClient returns a ComputeClient in which every method returns the given error.
@@ -187,3 +200,7 @@ func (e computeErrorClient) ListAttachedInterfaces(_ string) ([]attachinterfaces
func (e computeErrorClient) DeleteAttachedInterface(_, _ string) error {
return e.error
}
+
+func (e computeErrorClient) ListServerGroups() ([]servergroups.ServerGroup, error) {
+ return nil, e.error
+}
diff --git a/pkg/clients/mock/compute.go b/pkg/clients/mock/compute.go
index 93573cd5b2..77e7b7a8b2 100644
--- a/pkg/clients/mock/compute.go
+++ b/pkg/clients/mock/compute.go
@@ -26,6 +26,7 @@ import (
gomock "github.com/golang/mock/gomock"
attachinterfaces "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/attachinterfaces"
availabilityzones "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/availabilityzones"
+ servergroups "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/servergroups"
flavors "github.com/gophercloud/gophercloud/openstack/compute/v2/flavors"
servers "github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
clients "sigs.k8s.io/cluster-api-provider-openstack/pkg/clients"
@@ -157,6 +158,21 @@ func (mr *MockComputeClientMockRecorder) ListAvailabilityZones() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListAvailabilityZones", reflect.TypeOf((*MockComputeClient)(nil).ListAvailabilityZones))
}
+// ListServerGroups mocks base method.
+func (m *MockComputeClient) ListServerGroups() ([]servergroups.ServerGroup, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "ListServerGroups")
+ ret0, _ := ret[0].([]servergroups.ServerGroup)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// ListServerGroups indicates an expected call of ListServerGroups.
+func (mr *MockComputeClientMockRecorder) ListServerGroups() *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListServerGroups", reflect.TypeOf((*MockComputeClient)(nil).ListServerGroups))
+}
+
// ListServers mocks base method.
func (m *MockComputeClient) ListServers(arg0 servers.ListOptsBuilder) ([]clients.ServerExt, error) {
m.ctrl.T.Helper()
diff --git a/pkg/cloud/services/compute/referenced_resources.go b/pkg/cloud/services/compute/referenced_resources.go
new file mode 100644
index 0000000000..7b80947480
--- /dev/null
+++ b/pkg/cloud/services/compute/referenced_resources.go
@@ -0,0 +1,42 @@
+/*
+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 compute
+
+import (
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ "sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
+)
+
+// ResolveReferencedMachineResources is responsible for populating ReferencedMachineResources with IDs of
+// the resources referenced in the OpenStackMachineSpec by querying the OpenStack APIs. It'll return error
+// if resources cannot be found or their filters are ambiguous.
+func ResolveReferencedMachineResources(scope scope.Scope, spec *infrav1.OpenStackMachineSpec, resources *infrav1.ReferencedMachineResources) error {
+ compute, err := NewService(scope)
+ if err != nil {
+ return err
+ }
+
+ if spec.ServerGroup != nil && resources.ServerGroupID == "" {
+ serverGroupID, err := compute.GetServerGroupID(spec.ServerGroup)
+ if err != nil {
+ return err
+ }
+ resources.ServerGroupID = serverGroupID
+ }
+
+ return nil
+}
diff --git a/pkg/cloud/services/compute/referenced_resources_test.go b/pkg/cloud/services/compute/referenced_resources_test.go
new file mode 100644
index 0000000000..97e606ee71
--- /dev/null
+++ b/pkg/cloud/services/compute/referenced_resources_test.go
@@ -0,0 +1,99 @@
+/*
+Copyright 2024 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 compute
+
+import (
+ "testing"
+
+ "github.com/go-logr/logr"
+ "github.com/golang/mock/gomock"
+ "github.com/google/go-cmp/cmp"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/servergroups"
+ . "github.com/onsi/gomega"
+
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ "sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/mock"
+ "sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
+)
+
+func Test_ResolveReferencedMachineResources(t *testing.T) {
+ const serverGroupID1 = "ce96e584-7ebc-46d6-9e55-987d72e3806c"
+
+ tests := []struct {
+ testName string
+ serverGroupFilter *infrav1.ServerGroupFilter
+ expect func(m *mock.MockComputeClientMockRecorder)
+ want *infrav1.ReferencedMachineResources
+ wantErr bool
+ }{
+ {
+ testName: "Server group ID passed",
+ serverGroupFilter: &infrav1.ServerGroupFilter{ID: serverGroupID1},
+ expect: func(m *mock.MockComputeClientMockRecorder) {},
+ want: &infrav1.ReferencedMachineResources{ServerGroupID: serverGroupID1},
+ wantErr: false,
+ },
+ {
+ testName: "Server group filter nil",
+ serverGroupFilter: nil,
+ expect: func(m *mock.MockComputeClientMockRecorder) {},
+ want: &infrav1.ReferencedMachineResources{},
+ wantErr: false,
+ },
+ {
+ testName: "Server group ID empty",
+ serverGroupFilter: &infrav1.ServerGroupFilter{},
+ expect: func(m *mock.MockComputeClientMockRecorder) {},
+ want: &infrav1.ReferencedMachineResources{},
+ wantErr: false,
+ },
+ {
+ testName: "Server group by Name not found",
+ serverGroupFilter: &infrav1.ServerGroupFilter{Name: "test-server-group"},
+ expect: func(m *mock.MockComputeClientMockRecorder) {
+ m.ListServerGroups().Return(
+ []servergroups.ServerGroup{},
+ nil)
+ },
+ want: &infrav1.ReferencedMachineResources{},
+ wantErr: true,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.testName, func(t *testing.T) {
+ g := NewWithT(t)
+ mockCtrl := gomock.NewController(t)
+ mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "", logr.Discard())
+
+ tt.expect(mockScopeFactory.ComputeClient.EXPECT())
+
+ machineSpec := &infrav1.OpenStackMachineSpec{
+ ServerGroup: tt.serverGroupFilter,
+ }
+
+ resources := &infrav1.ReferencedMachineResources{}
+
+ err := ResolveReferencedMachineResources(mockScopeFactory, machineSpec, resources)
+ if tt.wantErr {
+ g.Expect(err).Error()
+ return
+ }
+
+ g.Expect(resources).To(Equal(tt.want), cmp.Diff(resources, tt.want))
+ })
+ }
+}
diff --git a/pkg/cloud/services/compute/servergroup.go b/pkg/cloud/services/compute/servergroup.go
new file mode 100644
index 0000000000..b084a99634
--- /dev/null
+++ b/pkg/cloud/services/compute/servergroup.go
@@ -0,0 +1,71 @@
+/*
+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 compute
+
+import (
+ "fmt"
+
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/servergroups"
+
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+)
+
+// GetServerGroupID looks up a server group using the passed filter and returns
+// its ID. It'll return an error when server group is not found or there are multiple.
+func (s *Service) GetServerGroupID(serverGroupFilter *infrav1.ServerGroupFilter) (string, error) {
+ if serverGroupFilter.ID != "" {
+ return serverGroupFilter.ID, nil
+ }
+
+ if serverGroupFilter.Name == "" {
+ // empty filter produced no server group, but also no error
+ return "", nil
+ }
+
+ // otherwise fallback to looking up by name, which is slower
+ serverGroup, err := s.getServerGroupByName(serverGroupFilter.Name)
+ if err != nil {
+ return "", err
+ }
+
+ return serverGroup.ID, nil
+}
+
+func (s *Service) getServerGroupByName(serverGroupName string) (*servergroups.ServerGroup, error) {
+ allServerGroups, err := s.getComputeClient().ListServerGroups()
+ if err != nil {
+ return nil, err
+ }
+
+ serverGroups := []servergroups.ServerGroup{}
+
+ for _, serverGroup := range allServerGroups {
+ if serverGroupName == serverGroup.Name {
+ serverGroups = append(serverGroups, serverGroup)
+ }
+ }
+
+ switch len(serverGroups) {
+ case 0:
+ return nil, fmt.Errorf("no server group with name %s could be found", serverGroupName)
+ case 1:
+ return &serverGroups[0], nil
+ default:
+ // this will never happen due to duplicate IDs, only duplicate names, so our error message is worded accordingly
+ return nil, fmt.Errorf("too many server groups with name %s were found", serverGroupName)
+ }
+}
diff --git a/pkg/cloud/services/compute/servergroup_test.go b/pkg/cloud/services/compute/servergroup_test.go
new file mode 100644
index 0000000000..572e3d78c6
--- /dev/null
+++ b/pkg/cloud/services/compute/servergroup_test.go
@@ -0,0 +1,128 @@
+/*
+Copyright 2024 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 compute
+
+import (
+ "fmt"
+ "testing"
+
+ "github.com/go-logr/logr"
+ "github.com/golang/mock/gomock"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/servergroups"
+
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ "sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/mock"
+ "sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
+)
+
+func TestService_GetServerGroupID(t *testing.T) {
+ const serverGroupID1 = "ce96e584-7ebc-46d6-9e55-987d72e3806c"
+ const serverGroupID2 = "8f536889-5198-42d7-8314-cb78f4f4755c"
+
+ tests := []struct {
+ testName string
+ serverGroupFilter *infrav1.ServerGroupFilter
+ expect func(m *mock.MockComputeClientMockRecorder)
+ want string
+ wantErr bool
+ }{
+ {
+ testName: "Return server group ID from filter if only filter (with ID) given",
+ serverGroupFilter: &infrav1.ServerGroupFilter{ID: serverGroupID1},
+ expect: func(m *mock.MockComputeClientMockRecorder) {
+ },
+ want: serverGroupID1,
+ wantErr: false,
+ },
+ {
+ testName: "Return no server group if empty filter is given",
+ serverGroupFilter: &infrav1.ServerGroupFilter{},
+ expect: func(m *mock.MockComputeClientMockRecorder) {
+ },
+ want: "",
+ wantErr: false,
+ },
+ {
+ testName: "Return server group ID from filter if only filter (with name) given",
+ serverGroupFilter: &infrav1.ServerGroupFilter{Name: "test-server-group"},
+ expect: func(m *mock.MockComputeClientMockRecorder) {
+ m.ListServerGroups().Return(
+ []servergroups.ServerGroup{{ID: serverGroupID1, Name: "test-server-group"}},
+ nil)
+ },
+ want: serverGroupID1,
+ wantErr: false,
+ },
+ {
+ testName: "Return no results",
+ serverGroupFilter: &infrav1.ServerGroupFilter{Name: "test-server-group"},
+ expect: func(m *mock.MockComputeClientMockRecorder) {
+ m.ListServerGroups().Return(
+ []servergroups.ServerGroup{},
+ nil)
+ },
+ want: "",
+ wantErr: true,
+ },
+ {
+ testName: "Return multiple results",
+ serverGroupFilter: &infrav1.ServerGroupFilter{Name: "test-server-group"},
+ expect: func(m *mock.MockComputeClientMockRecorder) {
+ m.ListServerGroups().Return(
+ []servergroups.ServerGroup{
+ {ID: serverGroupID1, Name: "test-server-group"},
+ {ID: serverGroupID2, Name: "test-server-group"},
+ },
+ nil)
+ },
+ want: "",
+ wantErr: true,
+ },
+ {
+ testName: "OpenStack returns error",
+ serverGroupFilter: &infrav1.ServerGroupFilter{Name: "test-server-group"},
+ expect: func(m *mock.MockComputeClientMockRecorder) {
+ m.ListServerGroups().Return(
+ nil,
+ fmt.Errorf("test error"))
+ },
+ want: "",
+ wantErr: true,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.testName, func(t *testing.T) {
+ mockCtrl := gomock.NewController(t)
+ mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "", logr.Discard())
+
+ s, err := NewService(mockScopeFactory)
+ if err != nil {
+ t.Fatalf("Failed to create service: %v", err)
+ }
+ tt.expect(mockScopeFactory.ComputeClient.EXPECT())
+
+ got, err := s.GetServerGroupID(tt.serverGroupFilter)
+ if (err != nil) != tt.wantErr {
+ t.Errorf("Service.getServerGroupID() error = %v, wantErr %v", err, tt.wantErr)
+ return
+ }
+ if got != tt.want {
+ t.Errorf("Service.getServerGroupID() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
From 87cb35665cc8c71ad6b5bd94f38e3e54ba4e2342 Mon Sep 17 00:00:00 2001
From: Emilien Macchi
Date: Fri, 15 Dec 2023 11:30:38 -0500
Subject: [PATCH 021/180] New API for External Network
---
api/v1alpha5/conversion.go | 27 ++-
api/v1alpha5/conversion_test.go | 4 +-
api/v1alpha5/zz_generated.conversion.go | 20 +-
api/v1alpha6/conversion.go | 46 +++-
api/v1alpha6/zz_generated.conversion.go | 20 +-
api/v1alpha7/conversion.go | 64 ++++-
api/v1alpha7/zz_generated.conversion.go | 35 +--
api/v1alpha8/openstackcluster_types.go | 12 +-
api/v1alpha8/zz_generated.deepcopy.go | 1 +
...re.cluster.x-k8s.io_openstackclusters.yaml | 31 ++-
...er.x-k8s.io_openstackclustertemplates.yaml | 33 ++-
.../openstackcluster_controller_test.go | 11 +-
docs/book/src/SUMMARY.md | 1 +
.../crd-changes/v1alpha7-to-v1alpha8.md | 41 +++-
.../v1alpha8/default/cluster-template.yaml | 3 +-
pkg/cloud/services/networking/network.go | 73 +++---
pkg/cloud/services/networking/network_test.go | 226 ++++++++++++++++++
pkg/utils/conversion/restore.go | 7 +-
.../cluster-template-flatcar-sysext.yaml | 3 +-
templates/cluster-template-flatcar.yaml | 3 +-
templates/cluster-template-without-lb.yaml | 3 +-
templates/cluster-template.yaml | 3 +-
22 files changed, 548 insertions(+), 119 deletions(-)
diff --git a/api/v1alpha5/conversion.go b/api/v1alpha5/conversion.go
index 0d7ed69f41..dc675d0c6a 100644
--- a/api/v1alpha5/conversion.go
+++ b/api/v1alpha5/conversion.go
@@ -187,8 +187,31 @@ func (r *OpenStackMachineTemplateList) ConvertFrom(srcRaw ctrlconversion.Hub) er
}
func Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(in *infrav1.OpenStackClusterSpec, out *OpenStackClusterSpec, s conversion.Scope) error {
- // Our new flag has no equivalent in v1alpha5
- return autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(in, out, s)
+ err := autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(in, out, s)
+ if err != nil {
+ return err
+ }
+
+ if in.ExternalNetwork.ID != "" {
+ out.ExternalNetworkID = in.ExternalNetwork.ID
+ }
+
+ return nil
+}
+
+func Convert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *OpenStackClusterSpec, out *infrav1.OpenStackClusterSpec, s conversion.Scope) error {
+ err := autoConvert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in, out, s)
+ if err != nil {
+ return err
+ }
+
+ if in.ExternalNetworkID != "" {
+ out.ExternalNetwork = infrav1.NetworkFilter{
+ ID: in.ExternalNetworkID,
+ }
+ }
+
+ return nil
}
func Convert_v1alpha8_LoadBalancer_To_v1alpha5_LoadBalancer(in *infrav1.LoadBalancer, out *LoadBalancer, s conversion.Scope) error {
diff --git a/api/v1alpha5/conversion_test.go b/api/v1alpha5/conversion_test.go
index 895af62b0d..839e9bd4a4 100644
--- a/api/v1alpha5/conversion_test.go
+++ b/api/v1alpha5/conversion_test.go
@@ -49,7 +49,7 @@ func TestConvertFrom(t *testing.T) {
Spec: OpenStackClusterSpec{},
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\":{\"allowAllInClusterTraffic\":false,\"apiServerLoadBalancer\":{},\"cloudName\":\"\",\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"disableExternalNetwork\":false,\"externalNetwork\":{},\"managedSecurityGroups\":false,\"network\":{},\"subnet\":{}},\"status\":{\"ready\":false}}",
},
},
},
@@ -64,7 +64,7 @@ func TestConvertFrom(t *testing.T) {
Spec: OpenStackClusterTemplateSpec{},
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\":{\"allowAllInClusterTraffic\":false,\"apiServerLoadBalancer\":{},\"cloudName\":\"\",\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"disableExternalNetwork\":false,\"externalNetwork\":{},\"managedSecurityGroups\":false,\"network\":{},\"subnet\":{}}}}}",
},
},
},
diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go
index 7939a3ad41..b1deb78263 100644
--- a/api/v1alpha5/zz_generated.conversion.go
+++ b/api/v1alpha5/zz_generated.conversion.go
@@ -119,11 +119,6 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*OpenStackClusterSpec)(nil), (*v1alpha8.OpenStackClusterSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(a.(*OpenStackClusterSpec), b.(*v1alpha8.OpenStackClusterSpec), scope)
- }); err != nil {
- return err
- }
if err := s.AddGeneratedConversionFunc((*OpenStackClusterTemplate)(nil), (*v1alpha8.OpenStackClusterTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha5_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate(a.(*OpenStackClusterTemplate), b.(*v1alpha8.OpenStackClusterTemplate), scope)
}); err != nil {
@@ -319,6 +314,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
+ if err := s.AddConversionFunc((*OpenStackClusterSpec)(nil), (*v1alpha8.OpenStackClusterSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(a.(*OpenStackClusterSpec), b.(*v1alpha8.OpenStackClusterSpec), scope)
+ }); err != nil {
+ return err
+ }
if err := s.AddConversionFunc((*OpenStackClusterStatus)(nil), (*v1alpha8.OpenStackClusterStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha5_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterStatus(a.(*OpenStackClusterStatus), b.(*v1alpha8.OpenStackClusterStatus), scope)
}); err != nil {
@@ -683,7 +683,7 @@ func autoConvert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(
} else {
out.ExternalRouterIPs = nil
}
- out.ExternalNetworkID = in.ExternalNetworkID
+ // WARNING: in.ExternalNetworkID requires manual conversion: does not exist in peer-type
if err := Convert_v1alpha5_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil {
return err
}
@@ -710,11 +710,6 @@ func autoConvert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(
return nil
}
-// Convert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec is an autogenerated conversion function.
-func Convert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *OpenStackClusterSpec, out *v1alpha8.OpenStackClusterSpec, s conversion.Scope) error {
- return autoConvert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in, out, s)
-}
-
func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(in *v1alpha8.OpenStackClusterSpec, out *OpenStackClusterSpec, s conversion.Scope) error {
out.CloudName = in.CloudName
out.NodeCIDR = in.NodeCIDR
@@ -738,7 +733,8 @@ func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(
} else {
out.ExternalRouterIPs = nil
}
- out.ExternalNetworkID = in.ExternalNetworkID
+ // WARNING: in.ExternalNetwork requires manual conversion: does not exist in peer-type
+ // WARNING: in.DisableExternalNetwork requires manual conversion: does not exist in peer-type
if err := Convert_v1alpha8_APIServerLoadBalancer_To_v1alpha5_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil {
return err
}
diff --git a/api/v1alpha6/conversion.go b/api/v1alpha6/conversion.go
index f981a8a692..56aab5fbf7 100644
--- a/api/v1alpha6/conversion.go
+++ b/api/v1alpha6/conversion.go
@@ -123,6 +123,16 @@ var v1alpha6OpenStackClusterRestorer = conversion.RestorerFor[*OpenStackCluster]
}
var v1alpha8OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStackCluster]{
+ "externalNetwork": conversion.UnconditionalFieldRestorer(
+ func(c *infrav1.OpenStackCluster) *infrav1.NetworkFilter {
+ return &c.Spec.ExternalNetwork
+ },
+ ),
+ "disableExternalNetwork": conversion.UnconditionalFieldRestorer(
+ func(c *infrav1.OpenStackCluster) *bool {
+ return &c.Spec.DisableExternalNetwork
+ },
+ ),
"router": conversion.UnconditionalFieldRestorer(
func(c *infrav1.OpenStackCluster) **infrav1.RouterFilter {
return &c.Spec.Router
@@ -193,6 +203,16 @@ var v1alpha6OpenStackClusterTemplateRestorer = conversion.RestorerFor[*OpenStack
}
var v1alpha8OpenStackClusterTemplateRestorer = conversion.RestorerFor[*infrav1.OpenStackClusterTemplate]{
+ "externalNetwork": conversion.UnconditionalFieldRestorer(
+ func(c *infrav1.OpenStackClusterTemplate) *infrav1.NetworkFilter {
+ return &c.Spec.Template.Spec.ExternalNetwork
+ },
+ ),
+ "disableExternalNetwork": conversion.UnconditionalFieldRestorer(
+ func(c *infrav1.OpenStackClusterTemplate) *bool {
+ return &c.Spec.Template.Spec.DisableExternalNetwork
+ },
+ ),
"router": conversion.UnconditionalFieldRestorer(
func(c *infrav1.OpenStackClusterTemplate) **infrav1.RouterFilter {
return &c.Spec.Template.Spec.Router
@@ -443,7 +463,31 @@ func convertNetworksToPorts(networks []NetworkParam) []infrav1.PortOpts {
}
func Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(in *infrav1.OpenStackClusterSpec, out *OpenStackClusterSpec, s apiconversion.Scope) error {
- return autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(in, out, s)
+ err := autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(in, out, s)
+ if err != nil {
+ return err
+ }
+
+ if in.ExternalNetwork.ID != "" {
+ out.ExternalNetworkID = in.ExternalNetwork.ID
+ }
+
+ return nil
+}
+
+func Convert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *OpenStackClusterSpec, out *infrav1.OpenStackClusterSpec, s apiconversion.Scope) error {
+ err := autoConvert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in, out, s)
+ if err != nil {
+ return err
+ }
+
+ if in.ExternalNetworkID != "" {
+ out.ExternalNetwork = infrav1.NetworkFilter{
+ ID: in.ExternalNetworkID,
+ }
+ }
+
+ return nil
}
func Convert_v1alpha6_PortOpts_To_v1alpha8_PortOpts(in *PortOpts, out *infrav1.PortOpts, s apiconversion.Scope) error {
diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go
index 5382f4071c..1501975342 100644
--- a/api/v1alpha6/zz_generated.conversion.go
+++ b/api/v1alpha6/zz_generated.conversion.go
@@ -119,11 +119,6 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*OpenStackClusterSpec)(nil), (*v1alpha8.OpenStackClusterSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(a.(*OpenStackClusterSpec), b.(*v1alpha8.OpenStackClusterSpec), scope)
- }); err != nil {
- return err
- }
if err := s.AddGeneratedConversionFunc((*OpenStackClusterTemplate)(nil), (*v1alpha8.OpenStackClusterTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha6_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate(a.(*OpenStackClusterTemplate), b.(*v1alpha8.OpenStackClusterTemplate), scope)
}); err != nil {
@@ -334,6 +329,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
+ if err := s.AddConversionFunc((*OpenStackClusterSpec)(nil), (*v1alpha8.OpenStackClusterSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(a.(*OpenStackClusterSpec), b.(*v1alpha8.OpenStackClusterSpec), scope)
+ }); err != nil {
+ return err
+ }
if err := s.AddConversionFunc((*OpenStackClusterStatus)(nil), (*v1alpha8.OpenStackClusterStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha6_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterStatus(a.(*OpenStackClusterStatus), b.(*v1alpha8.OpenStackClusterStatus), scope)
}); err != nil {
@@ -695,7 +695,7 @@ func autoConvert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(
} else {
out.ExternalRouterIPs = nil
}
- out.ExternalNetworkID = in.ExternalNetworkID
+ // WARNING: in.ExternalNetworkID requires manual conversion: does not exist in peer-type
if err := Convert_v1alpha6_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil {
return err
}
@@ -723,11 +723,6 @@ func autoConvert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(
return nil
}
-// Convert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec is an autogenerated conversion function.
-func Convert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *OpenStackClusterSpec, out *v1alpha8.OpenStackClusterSpec, s conversion.Scope) error {
- return autoConvert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in, out, s)
-}
-
func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(in *v1alpha8.OpenStackClusterSpec, out *OpenStackClusterSpec, s conversion.Scope) error {
out.CloudName = in.CloudName
out.NodeCIDR = in.NodeCIDR
@@ -751,7 +746,8 @@ func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(
} else {
out.ExternalRouterIPs = nil
}
- out.ExternalNetworkID = in.ExternalNetworkID
+ // WARNING: in.ExternalNetwork requires manual conversion: does not exist in peer-type
+ // WARNING: in.DisableExternalNetwork requires manual conversion: does not exist in peer-type
if err := Convert_v1alpha8_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil {
return err
}
diff --git a/api/v1alpha7/conversion.go b/api/v1alpha7/conversion.go
index 1ad771bb02..89fa5563b5 100644
--- a/api/v1alpha7/conversion.go
+++ b/api/v1alpha7/conversion.go
@@ -40,6 +40,18 @@ var v1alpha8OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStack
return &c.Spec
},
restorev1alpha8ClusterSpec,
+
+ // 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
+ },
+ ),
),
// No equivalent in v1alpha7
@@ -69,6 +81,17 @@ func restorev1alpha8ClusterSpec(previous *infrav1.OpenStackClusterSpec, dst *inf
if prevBastion != nil && dstBastion != nil {
restorev1alpha8MachineSpec(&prevBastion.Instance, &dstBastion.Instance)
}
+
+ // Restore all fields except ID, which should have been copied over in conversion
+ dst.ExternalNetwork.Name = previous.ExternalNetwork.Name
+ dst.ExternalNetwork.Description = previous.ExternalNetwork.Description
+ dst.ExternalNetwork.ProjectID = previous.ExternalNetwork.ProjectID
+ dst.ExternalNetwork.Tags = previous.ExternalNetwork.Tags
+ dst.ExternalNetwork.TagsAny = previous.ExternalNetwork.TagsAny
+ dst.ExternalNetwork.NotTags = previous.ExternalNetwork.NotTags
+ dst.ExternalNetwork.NotTagsAny = previous.ExternalNetwork.NotTagsAny
+
+ dst.DisableExternalNetwork = previous.DisableExternalNetwork
}
func (r *OpenStackCluster) ConvertTo(dstRaw ctrlconversion.Hub) error {
@@ -107,14 +130,19 @@ func (r *OpenStackClusterList) ConvertFrom(srcRaw ctrlconversion.Hub) error {
var _ ctrlconversion.Convertible = &OpenStackClusterTemplate{}
+func restorev1alpha8ClusterTemplateSpec(previous *infrav1.OpenStackClusterTemplateSpec, dst *infrav1.OpenStackClusterTemplateSpec) {
+ restorev1alpha8Bastion(&previous.Template.Spec.Bastion, &dst.Template.Spec.Bastion)
+ restorev1alpha8ClusterSpec(&previous.Template.Spec, &dst.Template.Spec)
+}
+
var v1alpha7OpenStackClusterTemplateRestorer = conversion.RestorerFor[*OpenStackClusterTemplate]{}
var v1alpha8OpenStackClusterTemplateRestorer = conversion.RestorerFor[*infrav1.OpenStackClusterTemplate]{
- "bastion": conversion.HashedFieldRestorer(
- func(c *infrav1.OpenStackClusterTemplate) **infrav1.Bastion {
- return &c.Spec.Template.Spec.Bastion
+ "spec": conversion.HashedFieldRestorer(
+ func(c *infrav1.OpenStackClusterTemplate) *infrav1.OpenStackClusterTemplateSpec {
+ return &c.Spec
},
- restorev1alpha8Bastion,
+ restorev1alpha8ClusterTemplateSpec,
),
}
@@ -300,3 +328,31 @@ func Convert_v1alpha8_Bastion_To_v1alpha7_Bastion(in *infrav1.Bastion, out *Bast
return nil
}
+
+func Convert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *OpenStackClusterSpec, out *infrav1.OpenStackClusterSpec, s apiconversion.Scope) error {
+ err := autoConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in, out, s)
+ if err != nil {
+ return err
+ }
+
+ if in.ExternalNetworkID != "" {
+ out.ExternalNetwork = infrav1.NetworkFilter{
+ ID: in.ExternalNetworkID,
+ }
+ }
+
+ return nil
+}
+
+func Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in *infrav1.OpenStackClusterSpec, out *OpenStackClusterSpec, s apiconversion.Scope) error {
+ err := autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in, out, s)
+ if err != nil {
+ return err
+ }
+
+ if in.ExternalNetwork.ID != "" {
+ out.ExternalNetworkID = in.ExternalNetwork.ID
+ }
+
+ return nil
+}
diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go
index 3739ade074..dc95a9500f 100644
--- a/api/v1alpha7/zz_generated.conversion.go
+++ b/api/v1alpha7/zz_generated.conversion.go
@@ -184,16 +184,6 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*OpenStackClusterSpec)(nil), (*v1alpha8.OpenStackClusterSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(a.(*OpenStackClusterSpec), b.(*v1alpha8.OpenStackClusterSpec), scope)
- }); err != nil {
- return err
- }
- if err := s.AddGeneratedConversionFunc((*v1alpha8.OpenStackClusterSpec)(nil), (*OpenStackClusterSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(a.(*v1alpha8.OpenStackClusterSpec), b.(*OpenStackClusterSpec), scope)
- }); err != nil {
- return err
- }
if err := s.AddGeneratedConversionFunc((*OpenStackClusterStatus)(nil), (*v1alpha8.OpenStackClusterStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha7_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterStatus(a.(*OpenStackClusterStatus), b.(*v1alpha8.OpenStackClusterStatus), scope)
}); err != nil {
@@ -424,6 +414,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
+ if err := s.AddConversionFunc((*OpenStackClusterSpec)(nil), (*v1alpha8.OpenStackClusterSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(a.(*OpenStackClusterSpec), b.(*v1alpha8.OpenStackClusterSpec), scope)
+ }); err != nil {
+ return err
+ }
if err := s.AddConversionFunc((*OpenStackMachineSpec)(nil), (*v1alpha8.OpenStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha7_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(a.(*OpenStackMachineSpec), b.(*v1alpha8.OpenStackMachineSpec), scope)
}); err != nil {
@@ -439,6 +434,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
+ if err := s.AddConversionFunc((*v1alpha8.OpenStackClusterSpec)(nil), (*OpenStackClusterSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(a.(*v1alpha8.OpenStackClusterSpec), b.(*OpenStackClusterSpec), scope)
+ }); err != nil {
+ return err
+ }
if err := s.AddConversionFunc((*v1alpha8.OpenStackMachineSpec)(nil), (*OpenStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(a.(*v1alpha8.OpenStackMachineSpec), b.(*OpenStackMachineSpec), scope)
}); err != nil {
@@ -887,7 +887,7 @@ func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(
out.NetworkMTU = in.NetworkMTU
out.DNSNameservers = *(*[]string)(unsafe.Pointer(&in.DNSNameservers))
out.ExternalRouterIPs = *(*[]v1alpha8.ExternalRouterIPParam)(unsafe.Pointer(&in.ExternalRouterIPs))
- out.ExternalNetworkID = in.ExternalNetworkID
+ // WARNING: in.ExternalNetworkID requires manual conversion: does not exist in peer-type
if err := Convert_v1alpha7_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil {
return err
}
@@ -915,11 +915,6 @@ func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(
return nil
}
-// Convert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec is an autogenerated conversion function.
-func Convert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *OpenStackClusterSpec, out *v1alpha8.OpenStackClusterSpec, s conversion.Scope) error {
- return autoConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in, out, s)
-}
-
func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in *v1alpha8.OpenStackClusterSpec, out *OpenStackClusterSpec, s conversion.Scope) error {
out.CloudName = in.CloudName
out.NodeCIDR = in.NodeCIDR
@@ -933,7 +928,8 @@ func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(
out.NetworkMTU = in.NetworkMTU
out.DNSNameservers = *(*[]string)(unsafe.Pointer(&in.DNSNameservers))
out.ExternalRouterIPs = *(*[]ExternalRouterIPParam)(unsafe.Pointer(&in.ExternalRouterIPs))
- out.ExternalNetworkID = in.ExternalNetworkID
+ // WARNING: in.ExternalNetwork requires manual conversion: does not exist in peer-type
+ // WARNING: in.DisableExternalNetwork requires manual conversion: does not exist in peer-type
if err := Convert_v1alpha8_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil {
return err
}
@@ -961,11 +957,6 @@ func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(
return nil
}
-// Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in *v1alpha8.OpenStackClusterSpec, out *OpenStackClusterSpec, s conversion.Scope) error {
- return autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in, out, s)
-}
-
func autoConvert_v1alpha7_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterStatus(in *OpenStackClusterStatus, out *v1alpha8.OpenStackClusterStatus, s conversion.Scope) error {
out.Ready = in.Ready
out.Network = (*v1alpha8.NetworkStatusWithSubnets)(unsafe.Pointer(in.Network))
diff --git a/api/v1alpha8/openstackcluster_types.go b/api/v1alpha8/openstackcluster_types.go
index 902e9c7c03..fafa4eb95a 100644
--- a/api/v1alpha8/openstackcluster_types.go
+++ b/api/v1alpha8/openstackcluster_types.go
@@ -65,10 +65,16 @@ type OpenStackClusterSpec struct {
// ExternalRouterIPs is an array of externalIPs on the respective subnets.
// This is necessary if the router needs a fixed ip in a specific subnet.
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.
+ // +optional
+ ExternalNetwork NetworkFilter `json:"externalNetwork,omitempty"`
+
+ // DisableExternalNetwork determines 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 bool `json:"disableExternalNetwork"`
// APIServerLoadBalancer configures the optional LoadBalancer for the APIServer.
// It must be activated by setting `enabled: true`.
diff --git a/api/v1alpha8/zz_generated.deepcopy.go b/api/v1alpha8/zz_generated.deepcopy.go
index a25da87fd4..c2d6b9fbc0 100644
--- a/api/v1alpha8/zz_generated.deepcopy.go
+++ b/api/v1alpha8/zz_generated.deepcopy.go
@@ -363,6 +363,7 @@ func (in *OpenStackClusterSpec) DeepCopyInto(out *OpenStackClusterSpec) {
*out = make([]ExternalRouterIPParam, len(*in))
copy(*out, *in)
}
+ out.ExternalNetwork = in.ExternalNetwork
in.APIServerLoadBalancer.DeepCopyInto(&out.APIServerLoadBalancer)
if in.Tags != nil {
in, out := &in.Tags, &out.Tags
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 9ce8a7259d..1c34e408d2 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -5232,6 +5232,12 @@ spec:
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 determines 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
@@ -5245,10 +5251,27 @@ spec:
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.
- type: string
+ externalNetwork:
+ description: ExternalNetwork is the OpenStack Network to be used to
+ get public internet to the VMs.
+ properties:
+ description:
+ type: string
+ id:
+ type: string
+ name:
+ type: string
+ notTags:
+ type: string
+ notTagsAny:
+ type: string
+ projectId:
+ type: string
+ tags:
+ type: string
+ tagsAny:
+ 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
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 f37bc32494..a04ae26e69 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -2778,6 +2778,13 @@ spec:
configuration to manage the VIP on the control plane machines,
which falls outside of the scope of this controller.
type: boolean
+ disableExternalNetwork:
+ description: DisableExternalNetwork determines 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
@@ -2792,11 +2799,27 @@ spec:
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.
- type: string
+ externalNetwork:
+ description: ExternalNetwork is the OpenStack Network to be
+ used to get public internet to the VMs.
+ properties:
+ description:
+ type: string
+ id:
+ type: string
+ name:
+ type: string
+ notTags:
+ type: string
+ notTagsAny:
+ type: string
+ projectId:
+ type: string
+ tags:
+ type: string
+ tagsAny:
+ type: string
+ type: object
externalRouterIPs:
description: ExternalRouterIPs is an array of externalIPs
on the respective subnets. This is necessary if the router
diff --git a/controllers/openstackcluster_controller_test.go b/controllers/openstackcluster_controller_test.go
index 400710ee42..d94e590cc2 100644
--- a/controllers/openstackcluster_controller_test.go
+++ b/controllers/openstackcluster_controller_test.go
@@ -23,6 +23,7 @@ import (
"github.com/go-logr/logr"
"github.com/golang/mock/gomock"
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external"
"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"
@@ -218,7 +219,9 @@ var _ = Describe("OpenStackCluster controller", func() {
testCluster.Spec = infrav1.OpenStackClusterSpec{
DisableAPIServerFloatingIP: true,
APIServerFixedIP: "10.0.0.1",
- ExternalNetworkID: externalNetworkID,
+ ExternalNetwork: infrav1.NetworkFilter{
+ ID: externalNetworkID,
+ },
Network: infrav1.NetworkFilter{
ID: clusterNetworkID,
},
@@ -233,8 +236,10 @@ var _ = Describe("OpenStackCluster controller", func() {
networkClientRecorder := mockScopeFactory.NetworkClient.EXPECT()
// Fetch external network
- networkClientRecorder.ListNetwork(networks.ListOpts{
- ID: externalNetworkID,
+ networkClientRecorder.ListNetwork(external.ListOptsExt{
+ ListOptsBuilder: networks.ListOpts{
+ ID: externalNetworkID,
+ },
}).Return([]networks.Network{
{
ID: externalNetworkID,
diff --git a/docs/book/src/SUMMARY.md b/docs/book/src/SUMMARY.md
index 0d309b83fc..a03f4c5fc7 100644
--- a/docs/book/src/SUMMARY.md
+++ b/docs/book/src/SUMMARY.md
@@ -11,5 +11,6 @@
- [v1alpha4 to v1alpha5](./topics/crd-changes/v1alpha4-to-v1alpha5.md)
- [v1alpha5 to v1alpha6](./topics/crd-changes/v1alpha5-to-v1alpha6.md)
- [v1alpha6 to v1alpha7](./topics/crd-changes/v1alpha6-to-v1alpha7.md)
+ - [v1alpha7 to v1alpha8](./topics/crd-changes/v1alpha7-to-v1alpha8.md)
- [Development](./development/development.md)
- [Hacking CI](./development/ci.md)
diff --git a/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md b/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md
index e52885b5f4..ed8558bbfe 100644
--- a/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md
+++ b/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md
@@ -7,6 +7,8 @@
- [API Changes](#api-changes)
- [`OpenStackMachine`](#openstackmachine)
- [Change to `serverGroupID`](#change-to-servergroupid)
+ - [`OpenStackCluster`](#openstackcluster)
+ - [Change to externalNetworkID](#change-to-externalnetworkid)
@@ -48,4 +50,41 @@ serverGroup:
```
If a server group is provided and found, it'll be added to `OpenStackMachine.Status.ReferencedResources.ServerGroupID`. If the server group can't be found or filter matches multiple server groups, an error will be returned.
-If empty object or null is provided, Machine will not be added to any server group and `OpenStackMachine.Status.ReferencedResources.ServerGroupID` will be empty.
\ No newline at end of file
+If empty object or null is provided, Machine will not be added to any server group and `OpenStackMachine.Status.ReferencedResources.ServerGroupID` will be empty.
+
+### `OpenStackCluster`
+
+#### Change to externalNetworkID
+
+
+The field `externalNetworkID` has been renamed to `externalNetwork` and is now a `NetworkFilter` object rather than a string ID.
+The `NetworkFilter` object allows selection of a network by name, by ID or by tags.
+
+```yaml
+externalNetworkID: "e60f19e7-cb37-49f9-a2ee-0a1281f6e03e"
+```
+
+becomes
+
+```yaml
+externalNetwork:
+ id: "e60f19e7-cb37-49f9-a2ee-0a1281f6e03e"
+```
+
+It is now possible to specify a `NetworkFilter` object to select the external network to use for the cluster. The `NetworkFilter` object allows to select the network by name, by ID or by tags.
+
+```yaml
+externalNetwork:
+ name: "public"
+```
+
+If a network is provided, it'll be added to `OpenStackCluster.Status.ExternalNetwork`. If the network can't be found, an error will be returned.
+If no network is provided, CAPO will try to find network marked "External" and add it to `OpenStackCluster.Status.ExternalNetwork`. If it can't find a network marked "External",
+`OpenStackCluster.Status.ExternalNetwork` will be set to nil.
+If more than one network is found, an error will be returned.
+
+It is now possible for a user to specify that no external network should be used by setting `DisableExternalNetwork` to `true`:
+
+```yaml
+disableExternalNetwork: true
+```
diff --git a/kustomize/v1alpha8/default/cluster-template.yaml b/kustomize/v1alpha8/default/cluster-template.yaml
index 4bf130b0a9..5c0d1113d6 100644
--- a/kustomize/v1alpha8/default/cluster-template.yaml
+++ b/kustomize/v1alpha8/default/cluster-template.yaml
@@ -32,7 +32,8 @@ spec:
nodeCidr: 10.6.0.0/24
dnsNameservers:
- ${OPENSTACK_DNS_NAMESERVERS}
- externalNetworkId: ${OPENSTACK_EXTERNAL_NETWORK_ID}
+ externalNetwork:
+ id: ${OPENSTACK_EXTERNAL_NETWORK_ID}
---
kind: KubeadmControlPlane
apiVersion: controlplane.cluster.x-k8s.io/v1beta1
diff --git a/pkg/cloud/services/networking/network.go b/pkg/cloud/services/networking/network.go
index 031d0b053c..601ac70a79 100644
--- a/pkg/cloud/services/networking/network.go
+++ b/pkg/cloud/services/networking/network.go
@@ -70,28 +70,33 @@ func (c createOpts) ToNetworkCreateMap() (map[string]interface{}, error) {
return gophercloud.BuildRequestBody(c, "network")
}
+// ReconcileExternalNetwork will try to find an external network and set it in the cluster status.
+// The external network can be specified in the cluster spec or will be searched for if not specified.
+// OpenStackCluster.Status.ExternalNetwork will be set to nil if one of these conditions are met:
+// - no external network was given in the cluster spec and no external network was found
+// - the user has set OpenStackCluster.Spec.DisableExternalNetwork to true.
func (s *Service) ReconcileExternalNetwork(openStackCluster *infrav1.OpenStackCluster) error {
- if openStackCluster.Spec.ExternalNetworkID != "" {
- externalNetwork, err := s.getNetworkByID(openStackCluster.Spec.ExternalNetworkID)
- if err != nil {
- return err
- }
- if externalNetwork.ID != "" {
- openStackCluster.Status.ExternalNetwork = &infrav1.NetworkStatus{
- ID: externalNetwork.ID,
- Name: externalNetwork.Name,
- Tags: externalNetwork.Tags,
- }
- return nil
- }
+ var listOpts external.ListOptsExt
+ var emptyExternalnetwork infrav1.NetworkFilter
+ var isAutoDetecting bool
+
+ if openStackCluster.Spec.DisableExternalNetwork {
+ s.scope.Logger().Info("External network is disabled - proceeding with internal network only")
+ openStackCluster.Status.ExternalNetwork = nil
+ return nil
}
- // ExternalNetworkID is not given
- iTrue := true
- networkListOpts := networks.ListOpts{}
- listOpts := external.ListOptsExt{
- ListOptsBuilder: networkListOpts,
- External: &iTrue,
+ if openStackCluster.Spec.ExternalNetwork != emptyExternalnetwork {
+ listOpts = external.ListOptsExt{
+ ListOptsBuilder: openStackCluster.Spec.ExternalNetwork.ToListOpt(),
+ }
+ } else {
+ // ExternalNetwork is not given so we'll list all networks and filter for external networks
+ isAutoDetecting = true
+ listOpts = external.ListOptsExt{
+ ListOptsBuilder: networks.ListOpts{},
+ External: &isAutoDetecting,
+ }
}
networkList, err := s.client.ListNetwork(listOpts)
@@ -101,10 +106,13 @@ func (s *Service) ReconcileExternalNetwork(openStackCluster *infrav1.OpenStackCl
switch len(networkList) {
case 0:
- // Not finding an external network is fine
- openStackCluster.Status.ExternalNetwork = &infrav1.NetworkStatus{}
- s.scope.Logger().Info("No external network found - proceeding with internal network only")
- return nil
+ if isAutoDetecting {
+ // Not finding an external network is fine if ExternalNetwork is not set
+ openStackCluster.Status.ExternalNetwork = nil
+ s.scope.Logger().Info("No external network found - proceeding with internal network only")
+ return nil
+ }
+ return fmt.Errorf("no external network found")
case 1:
openStackCluster.Status.ExternalNetwork = &infrav1.NetworkStatus{
ID: networkList[0].ID,
@@ -266,25 +274,6 @@ func (s *Service) createSubnet(openStackCluster *infrav1.OpenStackCluster, clust
return subnet, nil
}
-func (s *Service) getNetworkByID(networkID string) (networks.Network, error) {
- opts := networks.ListOpts{
- ID: networkID,
- }
-
- networkList, err := s.client.ListNetwork(opts)
- if err != nil {
- return networks.Network{}, err
- }
-
- switch len(networkList) {
- case 0:
- return networks.Network{}, nil
- case 1:
- return networkList[0], nil
- }
- return networks.Network{}, fmt.Errorf("found %d networks with id %s, which should not happen", len(networkList), networkID)
-}
-
func (s *Service) getNetworkByName(networkName string) (networks.Network, error) {
opts := networks.ListOpts{
Name: networkName,
diff --git a/pkg/cloud/services/networking/network_test.go b/pkg/cloud/services/networking/network_test.go
index f01bf859da..47ff27783a 100644
--- a/pkg/cloud/services/networking/network_test.go
+++ b/pkg/cloud/services/networking/network_test.go
@@ -22,6 +22,7 @@ import (
"github.com/go-logr/logr"
"github.com/golang/mock/gomock"
"github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external"
"github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
. "github.com/onsi/gomega"
"k8s.io/utils/pointer"
@@ -194,3 +195,228 @@ func Test_ReconcileNetwork(t *testing.T) {
})
}
}
+
+func Test_ReconcileExternalNetwork(t *testing.T) {
+ mockCtrl := gomock.NewController(t)
+ defer mockCtrl.Finish()
+
+ fakeNetworkID := "d08803fc-2fa5-4179-b9f7-8c43d0af2fe6"
+ fakeNetworkname := "external-network"
+ isAutodetecting := true
+
+ tests := []struct {
+ name string
+ openStackCluster *infrav1.OpenStackCluster
+ expect func(m *mock.MockNetworkClientMockRecorder)
+ want *infrav1.OpenStackCluster
+ wantErr bool
+ }{
+ {
+ name: "reconcile external network by ID",
+ openStackCluster: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ ExternalNetwork: infrav1.NetworkFilter{
+ ID: fakeNetworkID,
+ },
+ },
+ },
+ expect: func(m *mock.MockNetworkClientMockRecorder) {
+ m.
+ ListNetwork(external.ListOptsExt{
+ ListOptsBuilder: networks.ListOpts{ID: fakeNetworkID},
+ }).
+ Return([]networks.Network{
+ {
+ ID: fakeNetworkID,
+ Name: fakeNetworkname,
+ },
+ }, nil)
+ },
+ want: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ ExternalNetwork: infrav1.NetworkFilter{
+ ID: fakeNetworkID,
+ },
+ },
+ Status: infrav1.OpenStackClusterStatus{
+ ExternalNetwork: &infrav1.NetworkStatus{
+ ID: fakeNetworkID,
+ Name: fakeNetworkname,
+ },
+ },
+ },
+ wantErr: false,
+ },
+ {
+ name: "reconcile external network by name",
+ openStackCluster: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ ExternalNetwork: infrav1.NetworkFilter{
+ Name: fakeNetworkname,
+ },
+ },
+ },
+ expect: func(m *mock.MockNetworkClientMockRecorder) {
+ m.
+ ListNetwork(external.ListOptsExt{
+ ListOptsBuilder: networks.ListOpts{Name: fakeNetworkname},
+ }).
+ Return([]networks.Network{
+ {
+ ID: fakeNetworkID,
+ Name: fakeNetworkname,
+ },
+ }, nil)
+ },
+ want: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ ExternalNetwork: infrav1.NetworkFilter{
+ Name: fakeNetworkname,
+ },
+ },
+ Status: infrav1.OpenStackClusterStatus{
+ ExternalNetwork: &infrav1.NetworkStatus{
+ ID: fakeNetworkID,
+ Name: fakeNetworkname,
+ },
+ },
+ },
+ wantErr: false,
+ },
+ {
+ name: "reconcile external network by ID when no external network found",
+ openStackCluster: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ ExternalNetwork: infrav1.NetworkFilter{
+ ID: fakeNetworkID,
+ },
+ },
+ },
+ expect: func(m *mock.MockNetworkClientMockRecorder) {
+ m.
+ ListNetwork(external.ListOptsExt{
+ ListOptsBuilder: networks.ListOpts{ID: fakeNetworkID},
+ }).
+ Return([]networks.Network{}, nil)
+ },
+ want: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ ExternalNetwork: infrav1.NetworkFilter{
+ ID: fakeNetworkID,
+ },
+ },
+ },
+ wantErr: true,
+ },
+ {
+ name: "not reconcile external network when external network disabled",
+ openStackCluster: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ DisableExternalNetwork: true,
+ },
+ },
+ expect: func(m *mock.MockNetworkClientMockRecorder) {},
+ want: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ DisableExternalNetwork: true,
+ },
+ Status: infrav1.OpenStackClusterStatus{
+ ExternalNetwork: nil,
+ },
+ },
+ wantErr: false,
+ },
+ {
+ name: "reconcile external network with no filter when zero external network found",
+ openStackCluster: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{},
+ },
+ expect: func(m *mock.MockNetworkClientMockRecorder) {
+ m.
+ ListNetwork(external.ListOptsExt{
+ ListOptsBuilder: networks.ListOpts{},
+ External: &isAutodetecting,
+ }).
+ Return([]networks.Network{}, nil)
+ },
+ want: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{},
+ Status: infrav1.OpenStackClusterStatus{
+ ExternalNetwork: nil,
+ },
+ },
+ wantErr: false,
+ },
+ {
+ name: "reconcile external network with no filter when one external network found",
+ openStackCluster: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{},
+ },
+ expect: func(m *mock.MockNetworkClientMockRecorder) {
+ m.
+ ListNetwork(external.ListOptsExt{
+ ListOptsBuilder: networks.ListOpts{},
+ External: &isAutodetecting,
+ }).
+ Return([]networks.Network{
+ {
+ ID: fakeNetworkID,
+ Name: fakeNetworkname,
+ },
+ }, nil)
+ },
+ want: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{},
+ Status: infrav1.OpenStackClusterStatus{
+ ExternalNetwork: &infrav1.NetworkStatus{
+ ID: fakeNetworkID,
+ Name: fakeNetworkname,
+ },
+ },
+ },
+ wantErr: false,
+ },
+ {
+ name: "reconcile external network with no filter when more than one external network found",
+ openStackCluster: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{},
+ },
+ expect: func(m *mock.MockNetworkClientMockRecorder) {
+ m.
+ ListNetwork(external.ListOptsExt{
+ ListOptsBuilder: networks.ListOpts{},
+ External: &isAutodetecting,
+ }).
+ Return([]networks.Network{
+ {
+ ID: fakeNetworkID,
+ Name: fakeNetworkname,
+ },
+ {
+ ID: "d08803fc-2fa5-4179-b9f7-8c43d0af2fe7",
+ Name: "external-network-2",
+ },
+ }, nil)
+ },
+ want: &infrav1.OpenStackCluster{},
+ wantErr: true,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ g := NewWithT(t)
+ mockClient := mock.NewMockNetworkClient(mockCtrl)
+ tt.expect(mockClient.EXPECT())
+ s := Service{
+ client: mockClient,
+ scope: scope.NewMockScopeFactory(mockCtrl, "", logr.Discard()),
+ }
+ err := s.ReconcileExternalNetwork(tt.openStackCluster)
+ if (err != nil) != tt.wantErr {
+ t.Errorf("ReconcileExternalNetwork() error = %v, wantErr %v", err, tt.wantErr)
+ }
+ g.Expect(tt.openStackCluster).To(Equal(tt.want))
+ })
+ }
+}
diff --git a/pkg/utils/conversion/restore.go b/pkg/utils/conversion/restore.go
index 04701a19e8..5b0477d382 100644
--- a/pkg/utils/conversion/restore.go
+++ b/pkg/utils/conversion/restore.go
@@ -129,7 +129,12 @@ func (r hashedFieldRestorer[T, F]) getHash(obj T) []byte {
//nolint:unused
func (r hashedFieldRestorer[T, F]) marshalState(src, compare T) (json.RawMessage, error) {
- b, err := json.Marshal(r.getField(src))
+ f := r.getField(src)
+ if r.filterField != nil {
+ f = r.filterField(f)
+ }
+
+ b, err := json.Marshal(f)
if err != nil {
return nil, err
}
diff --git a/templates/cluster-template-flatcar-sysext.yaml b/templates/cluster-template-flatcar-sysext.yaml
index 3de5d4fb07..1aefb0aaff 100644
--- a/templates/cluster-template-flatcar-sysext.yaml
+++ b/templates/cluster-template-flatcar-sysext.yaml
@@ -227,7 +227,8 @@ spec:
cloudName: ${OPENSTACK_CLOUD}
dnsNameservers:
- ${OPENSTACK_DNS_NAMESERVERS}
- externalNetworkId: ${OPENSTACK_EXTERNAL_NETWORK_ID}
+ externalNetwork:
+ id: ${OPENSTACK_EXTERNAL_NETWORK_ID}
identityRef:
kind: Secret
name: ${CLUSTER_NAME}-cloud-config
diff --git a/templates/cluster-template-flatcar.yaml b/templates/cluster-template-flatcar.yaml
index cb3cf1b0eb..29b3443f0a 100644
--- a/templates/cluster-template-flatcar.yaml
+++ b/templates/cluster-template-flatcar.yaml
@@ -151,7 +151,8 @@ spec:
cloudName: ${OPENSTACK_CLOUD}
dnsNameservers:
- ${OPENSTACK_DNS_NAMESERVERS}
- externalNetworkId: ${OPENSTACK_EXTERNAL_NETWORK_ID}
+ externalNetwork:
+ id: ${OPENSTACK_EXTERNAL_NETWORK_ID}
identityRef:
kind: Secret
name: ${CLUSTER_NAME}-cloud-config
diff --git a/templates/cluster-template-without-lb.yaml b/templates/cluster-template-without-lb.yaml
index 4081e804ff..a9e6755bf1 100644
--- a/templates/cluster-template-without-lb.yaml
+++ b/templates/cluster-template-without-lb.yaml
@@ -108,7 +108,8 @@ spec:
cloudName: ${OPENSTACK_CLOUD}
dnsNameservers:
- ${OPENSTACK_DNS_NAMESERVERS}
- externalNetworkId: ${OPENSTACK_EXTERNAL_NETWORK_ID}
+ externalNetwork:
+ id: ${OPENSTACK_EXTERNAL_NETWORK_ID}
identityRef:
kind: Secret
name: ${CLUSTER_NAME}-cloud-config
diff --git a/templates/cluster-template.yaml b/templates/cluster-template.yaml
index 71f9f5695c..6760b7e917 100644
--- a/templates/cluster-template.yaml
+++ b/templates/cluster-template.yaml
@@ -110,7 +110,8 @@ spec:
cloudName: ${OPENSTACK_CLOUD}
dnsNameservers:
- ${OPENSTACK_DNS_NAMESERVERS}
- externalNetworkId: ${OPENSTACK_EXTERNAL_NETWORK_ID}
+ externalNetwork:
+ id: ${OPENSTACK_EXTERNAL_NETWORK_ID}
identityRef:
kind: Secret
name: ${CLUSTER_NAME}-cloud-config
From 591b2c433ff8374b2ab40e03605419efd5b252f0 Mon Sep 17 00:00:00 2001
From: Tobias Giese
Date: Wed, 10 Jan 2024 09:58:12 +0100
Subject: [PATCH 022/180] =?UTF-8?q?=E2=9C=A8=20Add=20flags=20for=20configu?=
=?UTF-8?q?ring=20rate=20limits?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Our controller have built-in rate limits. It throttles itself
if it hits this limit. So far it has not been possible to configure
these limits. This commit adds flags to the controller for setting both
the QPS and the burst for the rate limits. The default remains the same
as before (20 QPS, 30 burst).
Signed-off-by: Tobias Giese
Co-Authored-by: Lennart Jern
---
main.go | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/main.go b/main.go
index 62ad0a04b4..40ee63009c 100644
--- a/main.go
+++ b/main.go
@@ -69,6 +69,8 @@ var (
openStackClusterConcurrency int
openStackMachineConcurrency int
syncPeriod time.Duration
+ restConfigQPS float32
+ restConfigBurst int
webhookPort int
webhookCertDir string
healthAddr string
@@ -128,6 +130,12 @@ func InitFlags(fs *pflag.FlagSet) {
fs.DurationVar(&syncPeriod, "sync-period", 10*time.Minute,
"The minimum interval at which watched resources are reconciled (e.g. 15m)")
+ fs.Float32Var(&restConfigQPS, "kube-api-qps", 20,
+ "Maximum queries per second from the controller client to the Kubernetes API server. Defaults to 20")
+
+ fs.IntVar(&restConfigBurst, "kube-api-burst", 30,
+ "Maximum number of queries that should be allowed in one burst from the controller client to the Kubernetes API server. Defaults to 30")
+
fs.IntVar(&webhookPort, "webhook-port", 9443,
"Webhook Server port")
@@ -181,6 +189,8 @@ func main() {
if err != nil {
setupLog.Error(err, "unable to get kubeconfig")
}
+ cfg.QPS = restConfigQPS
+ cfg.Burst = restConfigBurst
var caCerts []byte
if caCertsPath != "" {
From e939503f450a0a54de30351d94ea6240bb6d295b Mon Sep 17 00:00:00 2001
From: Jan Mraz
Date: Tue, 2 Jan 2024 11:18:12 +0100
Subject: [PATCH 023/180] Fix patching OpenstackMachine's immutable spec during
reconcile when the VM is vanished (cannot be fetched but existed at some
point)
---
controllers/openstackmachine_controller.go | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/controllers/openstackmachine_controller.go b/controllers/openstackmachine_controller.go
index d5acde67cb..bf3e268f42 100644
--- a/controllers/openstackmachine_controller.go
+++ b/controllers/openstackmachine_controller.go
@@ -329,7 +329,7 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope
}
instanceStatus, err := r.getOrCreate(scope.Logger(), cluster, openStackCluster, machine, openStackMachine, computeService, userData)
- if err != nil {
+ if err != nil || instanceStatus == nil {
// Conditions set in getOrCreate
return ctrl.Result{}, err
}
@@ -439,6 +439,12 @@ func (r *OpenStackMachineReconciler) getOrCreate(logger logr.Logger, cluster *cl
}
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
+ }
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)
From 626c359624561a977239ea08f3d92d1611ad17f0 Mon Sep 17 00:00:00 2001
From: okozachenko
Date: Tue, 19 Dec 2023 01:07:36 +1100
Subject: [PATCH 024/180] fix: skip port deletion when instances have no port
---
pkg/cloud/services/networking/port.go | 4 ++++
pkg/cloud/services/networking/port_test.go | 13 +++++++++++++
2 files changed, 17 insertions(+)
diff --git a/pkg/cloud/services/networking/port.go b/pkg/cloud/services/networking/port.go
index 4c213851f8..84b9bfc618 100644
--- a/pkg/cloud/services/networking/port.go
+++ b/pkg/cloud/services/networking/port.go
@@ -315,6 +315,10 @@ func (s *Service) GarbageCollectErrorInstancesPort(eventObject runtime.Object, i
return fmt.Errorf("garbage collection of port %s failed, found %d ports with the same name", portName, len(portList))
}
+ if len(portList) == 0 {
+ continue
+ }
+
if err := s.DeletePort(eventObject, portList[0].ID); err != nil {
return err
}
diff --git a/pkg/cloud/services/networking/port_test.go b/pkg/cloud/services/networking/port_test.go
index 962ac2256d..a86837778e 100644
--- a/pkg/cloud/services/networking/port_test.go
+++ b/pkg/cloud/services/networking/port_test.go
@@ -588,6 +588,19 @@ func Test_GarbageCollectErrorInstancesPort(t *testing.T) {
{},
},
wantErr: false,
+ }, {
+ name: "garbage collects no ports in an instance",
+ expect: func(m *mock.MockNetworkClientMockRecorder) {
+ o1 := ports.ListOpts{
+ Name: portName1,
+ }
+ p1 := []ports.Port{}
+ m.ListPort(o1).Return(p1, nil)
+ },
+ portOpts: []infrav1.PortOpts{
+ {},
+ },
+ wantErr: false,
},
}
From 0e7808b2e21fb7e622d2ecc9e4011cd690b3549d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Andr=C3=A9?=
Date: Tue, 9 Jan 2024 14:26:23 +0100
Subject: [PATCH 025/180] CI: Hide errors for expected failures
The CI script should not show errors for expected failures, such as when
checking if a resource exists. This commit redirects the standard error
to standard output, which is in turn redirected to `/dev/null`.
---
hack/ci/gce-project.sh | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/hack/ci/gce-project.sh b/hack/ci/gce-project.sh
index 2b7a1a981a..c596ac42bc 100755
--- a/hack/ci/gce-project.sh
+++ b/hack/ci/gce-project.sh
@@ -34,12 +34,12 @@ function cloud_init {
# Generate local ssh configuration
# NOTE(mdbooth): This command successfully populates ssh config and then
# fails for some reason I don't understand. We ignore the failure.
- gcloud compute config-ssh || true
+ gcloud compute config-ssh >/dev/null 2>&1 || true
}
function init_infrastructure() {
if [[ ${GCP_NETWORK_NAME} != "default" ]]; then
- if ! gcloud compute networks describe "$GCP_NETWORK_NAME" --project "$GCP_PROJECT" >/dev/null; then
+ if ! gcloud compute networks describe "$GCP_NETWORK_NAME" --project "$GCP_PROJECT" >/dev/null 2>&1; then
gcloud compute networks create --project "$GCP_PROJECT" "$GCP_NETWORK_NAME" --subnet-mode custom
gcloud compute networks subnets create "$GCP_NETWORK_NAME" --project "$GCP_PROJECT" \
--network="$GCP_NETWORK_NAME" --range="$PRIVATE_NETWORK_CIDR" --region "$GCP_REGION"
@@ -64,12 +64,12 @@ function init_infrastructure() {
gcloud compute networks list --project="$GCP_PROJECT"
gcloud compute networks describe "$GCP_NETWORK_NAME" --project="$GCP_PROJECT"
- if ! gcloud compute routers describe "${CLUSTER_NAME}-myrouter" --project="$GCP_PROJECT" --region="$GCP_REGION" >/dev/null; then
+ if ! gcloud compute routers describe "${CLUSTER_NAME}-myrouter" --project="$GCP_PROJECT" --region="$GCP_REGION" >/dev/null 2>&1; then
gcloud compute routers create "${CLUSTER_NAME}-myrouter" --project="$GCP_PROJECT" \
--region="$GCP_REGION" --network="$GCP_NETWORK_NAME"
fi
if ! gcloud compute routers nats describe --router="$CLUSTER_NAME-myrouter" "$CLUSTER_NAME-mynat" \
- --project="$GCP_PROJECT" --region="${GCP_REGION}" >/dev/null; then
+ --project="$GCP_PROJECT" --region="${GCP_REGION}" >/dev/null 2>&1; then
gcloud compute routers nats create "${CLUSTER_NAME}-mynat" --project="$GCP_PROJECT" \
--router-region="$GCP_REGION" --router="${CLUSTER_NAME}-myrouter" \
--nat-all-subnet-ip-ranges --auto-allocate-nat-external-ips
@@ -89,7 +89,7 @@ function create_vm {
# Loop over all zones in the GCP region to ignore a full zone.
# We are not able to use 'gcloud compute zones list' as the gcloud.compute.zones.list permission is missing.
for GCP_ZONE in "${GCP_REGION}-a" "${GCP_REGION}-b" "${GCP_REGION}-c"; do
- if ! gcloud compute instances describe "$servername" --project "$GCP_PROJECT" --zone "$GCP_ZONE" >/dev/null; then
+ if ! gcloud compute instances describe "$servername" --project "$GCP_PROJECT" --zone "$GCP_ZONE" >/dev/null 2>&1; then
if gcloud compute instances create "$servername" \
--project "$GCP_PROJECT" \
--zone "$GCP_ZONE" \
From 6bdc4b297367db8d918db44e5d761d35b85f2ae2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Andr=C3=A9?=
Date: Wed, 10 Jan 2024 10:42:42 +0100
Subject: [PATCH 026/180] Consolidate test names
It should start with lowercase, and should not include the redundant `It`.
---
test/e2e/suites/e2e/e2e_test.go | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/test/e2e/suites/e2e/e2e_test.go b/test/e2e/suites/e2e/e2e_test.go
index 0086a22e23..fbaabdce33 100644
--- a/test/e2e/suites/e2e/e2e_test.go
+++ b/test/e2e/suites/e2e/e2e_test.go
@@ -81,7 +81,7 @@ var _ = Describe("e2e tests [PR-Blocking]", func() {
})
Describe("Workload cluster (default)", func() {
- It("It should be creatable and deletable", func() {
+ It("should be creatable and deletable", func() {
shared.Logf("Creating a cluster")
clusterName := fmt.Sprintf("cluster-%s", namespace.Name)
configCluster := defaultConfigCluster(clusterName, namespace.Name)
@@ -247,7 +247,7 @@ var _ = Describe("e2e tests [PR-Blocking]", func() {
})
Describe("Workload cluster (without lb)", func() {
- It("Should create port(s) with custom options", func() {
+ It("should create port(s) with custom options", func() {
shared.Logf("Creating a cluster")
clusterName := fmt.Sprintf("cluster-%s", namespace.Name)
configCluster := defaultConfigCluster(clusterName, namespace.Name)
@@ -466,7 +466,7 @@ var _ = Describe("e2e tests [PR-Blocking]", func() {
})
Describe("MachineDeployment misconfigurations", func() {
- It("Should fail to create MachineDeployment with invalid subnet or invalid availability zone", func() {
+ It("should fail to create MachineDeployment with invalid subnet or invalid availability zone", func() {
shared.Logf("Creating a cluster")
clusterName := fmt.Sprintf("cluster-%s", namespace.Name)
configCluster := defaultConfigCluster(clusterName, namespace.Name)
@@ -534,7 +534,7 @@ var _ = Describe("e2e tests [PR-Blocking]", func() {
Expect(err).NotTo(HaveOccurred())
})
- It("It should be creatable and deletable", func() {
+ It("should be creatable and deletable", func() {
workerMachines := framework.GetMachinesByMachineDeployments(ctx, framework.GetMachinesByMachineDeploymentsInput{
Lister: e2eCtx.Environment.BootstrapClusterProxy.GetClient(),
ClusterName: clusterName,
From 75ffe73f88544dbc26c6636a491bca5b3f63c3d4 Mon Sep 17 00:00:00 2001
From: Francois Eleouet
Date: Fri, 17 Nov 2023 11:55:40 +0100
Subject: [PATCH 027/180] Use get instead of list to retrieve servers
Under certain circumstances, when they are non-responsive cells, nova
may return a partial result instead of an error.
(this is controlled by list_records_by_skipping_down_cells parameter
that is true by default - no error will be thrown)
When it faces this issue, capo controller will try to create a new
server for the machine, resulting in deleting ports of existing one.
In order avoid this issue, use GET instead of LIST with server uuid stored
in machine spec when it is created, and store server ID in machine spec
immediately.
For that purpose server status polling that used to take place in
CreateMachine has to be moved to main reconcile loop. ReconcileBastion
also needed to be revisited to properly support requeuing.
---
api/v1alpha5/types.go | 7 +-
api/v1alpha6/types.go | 7 +-
api/v1alpha7/types.go | 7 +-
api/v1alpha8/types.go | 7 +-
controllers/openstackcluster_controller.go | 144 +++++++++------
.../openstackcluster_controller_test.go | 168 +++++++++++++++++-
controllers/openstackmachine_controller.go | 45 +++--
controllers/suite_test.go | 25 ++-
pkg/cloud/services/compute/instance.go | 23 +--
pkg/cloud/services/compute/instance_test.go | 43 -----
pkg/cloud/services/compute/instance_types.go | 24 +--
11 files changed, 349 insertions(+), 151 deletions(-)
diff --git a/api/v1alpha5/types.go b/api/v1alpha5/types.go
index d7b2c9ba28..fd3a58e240 100644
--- a/api/v1alpha5/types.go
+++ b/api/v1alpha5/types.go
@@ -273,8 +273,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 +290,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.go b/api/v1alpha6/types.go
index 2e81c35fd2..0301d8d8cc 100644
--- a/api/v1alpha6/types.go
+++ b/api/v1alpha6/types.go
@@ -285,8 +285,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 +302,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.go b/api/v1alpha7/types.go
index 3ef5305ff2..dd14b84877 100644
--- a/api/v1alpha7/types.go
+++ b/api/v1alpha7/types.go
@@ -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/v1alpha8/types.go b/api/v1alpha8/types.go
index cccf992e70..d945249e00 100644
--- a/api/v1alpha8/types.go
+++ b/api/v1alpha8/types.go
@@ -321,8 +321,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")
@@ -338,6 +338,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/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index f83b8b75a9..cc574755d5 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -215,10 +215,24 @@ 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)
+ }
+ }
+
+ var instanceStatus *compute.InstanceStatus
+ if openStackCluster.Status.Bastion != nil && openStackCluster.Status.Bastion.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 {
@@ -230,6 +244,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)
@@ -277,8 +292,9 @@ func reconcileNormal(scope scope.Scope, cluster *clusterv1.Cluster, openStackClu
return reconcile.Result{}, err
}
- if err = reconcileBastion(scope, cluster, openStackCluster); err != nil {
- return reconcile.Result{}, err
+ result, err := reconcileBastion(scope, cluster, openStackCluster)
+ if err != nil || !reflect.DeepEqual(result, reconcile.Result{}) {
+ return result, err
}
availabilityZones, err := computeService.GetAvailabilityZones()
@@ -308,88 +324,112 @@ 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 {
+func reconcileBastion(scope scope.Scope, cluster *clusterv1.Cluster, openStackCluster *infrav1.OpenStackCluster) (ctrl.Result, error) {
scope.Logger().Info("Reconciling Bastion")
if openStackCluster.Spec.Bastion == nil || !openStackCluster.Spec.Bastion.Enabled {
- return deleteBastion(scope, cluster, openStackCluster)
+ return reconcile.Result{}, deleteBastion(scope, cluster, openStackCluster)
}
computeService, err := compute.NewService(scope)
if err != nil {
- return err
+ return reconcile.Result{}, err
}
instanceSpec := bastionToInstanceSpec(openStackCluster, cluster.Name)
bastionHash, err := compute.HashInstanceSpec(instanceSpec)
if err != nil {
- return fmt.Errorf("failed computing bastion hash from instance spec: %w", err)
+ return reconcile.Result{}, fmt.Errorf("failed computing bastion hash from instance spec: %w", err)
+ }
+ if bastionHashHasChanged(bastionHash, openStackCluster.ObjectMeta.Annotations) {
+ if err := deleteBastion(scope, cluster, openStackCluster); err != nil {
+ return ctrl.Result{}, err
+ }
}
- instanceStatus, err := computeService.GetInstanceStatusByName(openStackCluster, fmt.Sprintf("%s-bastion", cluster.Name))
- 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 reconcile.Result{}, 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
+ 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 reconcile.Result{}, err
}
-
- if err := deleteBastion(scope, cluster, openStackCluster); err != nil {
- return err
+ }
+ if instanceStatus == nil {
+ instanceStatus, err = computeService.CreateInstance(openStackCluster, openStackCluster, instanceSpec, cluster.Name)
+ if err != nil {
+ return reconcile.Result{}, fmt.Errorf("failed to create bastion: %w", err)
}
}
- instanceStatus, err = computeService.CreateInstance(openStackCluster, openStackCluster, instanceSpec, cluster.Name)
- if err != nil {
- return fmt.Errorf("failed to reconcile bastion: %w", err)
+ // Save hash & status as soon as we know we have an instance
+ instanceStatus.UpdateBastionStatus(openStackCluster)
+ annotations.AddAnnotations(openStackCluster, map[string]string{BastionInstanceHashAnnotation: bastionHash})
+
+ // Make sure that bastion instance has a valid state
+ switch instanceStatus.State() {
+ case infrav1.InstanceStateError:
+ return ctrl.Result{}, 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 ctrl.Result{RequeueAfter: waitForBuildingInstanceToReconcile}, nil
+ case infrav1.InstanceStateDeleted:
+ // This should normally be handled by deleteBastion
+ openStackCluster.Status.Bastion = nil
+ return ctrl.Result{}, nil
}
networkingService, err := networking.NewService(scope)
if err != nil {
- return 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)
+ return ctrl.Result{}, err
}
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 ctrl.Result{}, err
}
- err = networkingService.AssociateFloatingIP(openStackCluster, fp, port.ID)
+ fp, err := networkingService.GetFloatingIPByPortID(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)
+ handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to get or create floating IP for bastion: %w", err))
+ return ctrl.Result{}, 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 ctrl.Result{}, nil
}
- bastion, err := instanceStatus.BastionStatus(openStackCluster)
+ clusterName := fmt.Sprintf("%s-%s", cluster.Namespace, cluster.Name)
+ floatingIP := openStackCluster.Spec.Bastion.Instance.FloatingIP
+ if 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
+ }
+ // 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, clusterName, floatingIP)
if err != nil {
- return err
+ handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to get or create floating IP for bastion: %w", err))
+ return ctrl.Result{}, fmt.Errorf("failed to get or create floating IP for bastion: %w", err)
}
- bastion.FloatingIP = fp.FloatingIP
- openStackCluster.Status.Bastion = bastion
- annotations.AddAnnotations(openStackCluster, map[string]string{BastionInstanceHashAnnotation: bastionHash})
- return nil
+ 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 ctrl.Result{}, fmt.Errorf("failed to associate floating IP with bastion: %w", err)
+ }
+
+ return ctrl.Result{}, nil
}
func bastionToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, clusterName string) *compute.InstanceSpec {
- name := fmt.Sprintf("%s-bastion", clusterName)
instanceSpec := &compute.InstanceSpec{
- Name: name,
+ Name: bastionName(clusterName),
Flavor: openStackCluster.Spec.Bastion.Instance.Flavor,
SSHKeyName: openStackCluster.Spec.Bastion.Instance.SSHKeyName,
Image: openStackCluster.Spec.Bastion.Instance.Image,
@@ -412,6 +452,10 @@ func bastionToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, clusterNa
return instanceSpec
}
+func bastionName(clusterName string) string {
+ return fmt.Sprintf("%s-bastion", clusterName)
+}
+
// bastionHashHasChanged returns a boolean whether if the latest bastion hash, built from the instance spec, has changed or not.
func bastionHashHasChanged(computeHash string, clusterAnnotations map[string]string) bool {
latestHash, ok := clusterAnnotations[BastionInstanceHashAnnotation]
diff --git a/controllers/openstackcluster_controller_test.go b/controllers/openstackcluster_controller_test.go
index d94e590cc2..5c59e7c807 100644
--- a/controllers/openstackcluster_controller_test.go
+++ b/controllers/openstackcluster_controller_test.go
@@ -22,10 +22,15 @@ import (
"github.com/go-logr/logr"
"github.com/golang/mock/gomock"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/attachinterfaces"
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips"
"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/ports"
"github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
@@ -196,15 +201,176 @@ var _ = Describe("OpenStackCluster controller", func() {
Expect(err).To(BeNil())
err = k8sClient.Create(ctx, capiCluster)
Expect(err).To(BeNil())
+ testCluster.Status = infrav1.OpenStackClusterStatus{
+ Bastion: &infrav1.BastionStatus{
+ ID: "bastion-uuid",
+ },
+ }
+ err = k8sClient.Status().Update(ctx, testCluster)
+ Expect(err).To(BeNil())
scope, err := mockScopeFactory.NewClientScopeFromCluster(ctx, k8sClient, testCluster, nil, logr.Discard())
Expect(err).To(BeNil())
+ computeClientRecorder := mockScopeFactory.ComputeClient.EXPECT()
+ computeClientRecorder.GetServer("bastion-uuid").Return(nil, gophercloud.ErrResourceNotFound{})
+
+ networkClientRecorder := mockScopeFactory.NetworkClient.EXPECT()
+ networkClientRecorder.ListSecGroup(gomock.Any()).Return([]groups.SecGroup{}, nil)
+
+ err = deleteBastion(scope, capiCluster, testCluster)
+ Expect(testCluster.Status.Bastion).To(BeNil())
+ Expect(err).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: true,
+ },
+ }
+ 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",
+ },
+ },
+ }
+ err = k8sClient.Status().Update(ctx, testCluster)
+ Expect(err).To(BeNil())
+
+ scope, err := mockScopeFactory.NewClientScopeFromCluster(ctx, k8sClient, testCluster, nil, logr.Discard())
+ Expect(err).To(BeNil())
+
+ server := clients.ServerExt{}
+ server.ID = "adopted-bastion-uuid"
+ server.Status = "ACTIVE"
+
+ computeClientRecorder := mockScopeFactory.ComputeClient.EXPECT()
+ computeClientRecorder.ListServers(servers.ListOpts{
+ Name: "^capi-cluster-bastion$",
+ }).Return([]clients.ServerExt{server}, nil)
+
+ networkClientRecorder := mockScopeFactory.NetworkClient.EXPECT()
+ networkClientRecorder.ListPort(gomock.Any()).Return([]ports.Port{{ID: "portID"}}, nil)
+ networkClientRecorder.ListFloatingIP(floatingips.ListOpts{PortID: "portID"}).Return(make([]floatingips.FloatingIP, 1), nil)
+
+ res, err := reconcileBastion(scope, capiCluster, testCluster)
+ Expect(testCluster.Status.Bastion).To(Equal(&infrav1.BastionStatus{ID: "adopted-bastion-uuid", State: "ACTIVE"}))
+ Expect(err).To(BeNil())
+ Expect(res).To(Equal(reconcile.Result{}))
+ })
+ 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: true,
+ },
+ }
+ 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",
+ },
+ },
+ Bastion: &infrav1.BastionStatus{
+ ID: "adopted-fip-bastion-uuid",
+ },
+ }
+ err = k8sClient.Status().Update(ctx, testCluster)
+ Expect(err).To(BeNil())
+
+ scope, err := mockScopeFactory.NewClientScopeFromCluster(ctx, k8sClient, testCluster, nil, logr.Discard())
+ Expect(err).To(BeNil())
+
+ server := clients.ServerExt{}
+ server.ID = "adopted-fip-bastion-uuid"
+ server.Status = "ACTIVE"
+
+ computeClientRecorder := mockScopeFactory.ComputeClient.EXPECT()
+ computeClientRecorder.GetServer("adopted-fip-bastion-uuid").Return(&server, nil)
+
+ networkClientRecorder := mockScopeFactory.NetworkClient.EXPECT()
+ networkClientRecorder.ListPort(gomock.Any()).Return([]ports.Port{{ID: "portID"}}, nil)
+ networkClientRecorder.ListFloatingIP(floatingips.ListOpts{PortID: "portID"}).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", State: "ACTIVE", FloatingIP: "1.2.3.4"}))
+ Expect(err).To(BeNil())
+ Expect(res).To(Equal(reconcile.Result{}))
+ })
+ It("should requeue until bastion becomes active", func() {
+ testCluster.SetName("requeue-bastion")
+ testCluster.Spec = infrav1.OpenStackClusterSpec{
+ Bastion: &infrav1.Bastion{
+ Enabled: true,
+ },
+ }
+ 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",
+ },
+ },
+ Bastion: &infrav1.BastionStatus{
+ ID: "requeue-bastion-uuid",
+ },
+ }
+ err = k8sClient.Status().Update(ctx, testCluster)
+ Expect(err).To(BeNil())
+
+ scope, err := mockScopeFactory.NewClientScopeFromCluster(ctx, k8sClient, testCluster, nil, logr.Discard())
+ Expect(err).To(BeNil())
+
+ 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"}))
+ 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{
+ Bastion: &infrav1.Bastion{},
+ }
+ 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())
+ Expect(err).To(BeNil())
+
+ server := clients.ServerExt{}
+ server.ID = "delete-bastion-uuid"
+
computeClientRecorder := mockScopeFactory.ComputeClient.EXPECT()
computeClientRecorder.ListServers(servers.ListOpts{
Name: "^capi-cluster-bastion$",
- }).Return([]clients.ServerExt{}, nil)
+ }).Return([]clients.ServerExt{server}, nil)
+ computeClientRecorder.ListAttachedInterfaces("delete-bastion-uuid").Return([]attachinterfaces.Interface{}, nil)
+ computeClientRecorder.DeleteServer("delete-bastion-uuid").Return(nil)
+ computeClientRecorder.GetServer("delete-bastion-uuid").Return(nil, gophercloud.ErrResourceNotFound{})
networkClientRecorder := mockScopeFactory.NetworkClient.EXPECT()
+ networkClientRecorder.ListExtensions().Return([]extensions.Extension{}, nil)
networkClientRecorder.ListSecGroup(gomock.Any()).Return([]groups.SecGroup{}, nil)
err = deleteBastion(scope, capiCluster, testCluster)
diff --git a/controllers/openstackmachine_controller.go b/controllers/openstackmachine_controller.go
index c797e218b9..83ac3726a5 100644
--- a/controllers/openstackmachine_controller.go
+++ b/controllers/openstackmachine_controller.go
@@ -67,6 +67,7 @@ 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
@@ -252,8 +253,13 @@ func (r *OpenStackMachineReconciler) reconcileDelete(scope scope.Scope, cluster
}
}
- instanceStatus, err := computeService.GetInstanceStatusByName(openStackMachine, openStackMachine.Name)
- if err != nil {
+ var instanceStatus *compute.InstanceStatus
+ if openStackMachine.Spec.InstanceID != nil {
+ instanceStatus, err = computeService.GetInstanceStatus(*openStackMachine.Spec.InstanceID)
+ if err != nil {
+ return ctrl.Result{}, err
+ }
+ } else if instanceStatus, err = computeService.GetInstanceStatusByName(openStackMachine, openStackMachine.Name); err != nil {
return ctrl.Result{}, err
}
if !openStackCluster.Spec.APIServerLoadBalancer.Enabled && util.IsControlPlaneMachine(machine) && openStackCluster.Spec.APIServerFloatingIP == "" {
@@ -385,6 +391,9 @@ 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
@@ -437,19 +446,28 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope
}
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
+ var instanceStatus *compute.InstanceStatus
+ var err error
+ if openStackMachine.Spec.InstanceID != nil {
+ instanceStatus, err = computeService.GetInstanceStatus(*openStackMachine.Spec.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.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
+ }
}
instanceSpec := machineToInstanceSpec(openStackCluster, machine, openStackMachine, userData)
logger.Info("Machine does not exist, creating Machine", "name", openStackMachine.Name)
@@ -459,7 +477,6 @@ func (r *OpenStackMachineReconciler) getOrCreate(logger logr.Logger, cluster *cl
return nil, fmt.Errorf("create OpenStack instance: %w", err)
}
}
-
return instanceStatus, nil
}
diff --git a/controllers/suite_test.go b/controllers/suite_test.go
index 3a63e41d9a..fdbda08855 100644
--- a/controllers/suite_test.go
+++ b/controllers/suite_test.go
@@ -32,12 +32,14 @@ import (
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/rest"
+ "k8s.io/utils/pointer"
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/v1alpha8"
+ "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"
@@ -148,9 +150,13 @@ var _ = Describe("When calling getOrCreate", func() {
cluster := &clusterv1.Cluster{}
openStackCluster := &infrav1.OpenStackCluster{}
machine := &clusterv1.Machine{}
- openStackMachine := &infrav1.OpenStackMachine{}
+ openStackMachine := &infrav1.OpenStackMachine{
+ Spec: infrav1.OpenStackMachineSpec{
+ InstanceID: pointer.String("machine-uuid"),
+ },
+ }
- mockScopeFactory.ComputeClient.EXPECT().ListServers(gomock.Any()).Return(nil, errors.New("Test error when listing servers"))
+ mockScopeFactory.ComputeClient.EXPECT().GetServer(gomock.Any()).Return(nil, errors.New("Test error when getting server"))
instanceStatus, err := reconsiler.getOrCreate(logger, cluster, openStackCluster, machine, openStackMachine, computeService, "")
Expect(err).To(HaveOccurred())
Expect(instanceStatus).To(BeNil())
@@ -163,4 +169,19 @@ var _ = Describe("When calling getOrCreate", func() {
}
}
})
+
+ It("should retrieve instance by name if no ID is stored", func() {
+ cluster := &clusterv1.Cluster{}
+ 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.getOrCreate(logger, cluster, openStackCluster, machine, openStackMachine, computeService, "")
+ Expect(err).ToNot(HaveOccurred())
+ Expect(instanceStatus).ToNot(BeNil())
+ Expect(instanceStatus.ID()).To(Equal("machine-uuid"))
+ })
})
diff --git a/pkg/cloud/services/compute/instance.go b/pkg/cloud/services/compute/instance.go
index 15e9756895..b5a91b16c2 100644
--- a/pkg/cloud/services/compute/instance.go
+++ b/pkg/cloud/services/compute/instance.go
@@ -333,27 +333,8 @@ func (s *Service) createInstanceImpl(eventObject runtime.Object, openStackCluste
return nil, fmt.Errorf("error creating Openstack instance: %v", err)
}
- var createdInstance *InstanceStatus
- err = wait.PollUntilContextTimeout(context.TODO(), retryInterval, instanceCreateTimeout, true, func(_ context.Context) (bool, error) {
- createdInstance, err = s.GetInstanceStatus(server.ID)
- if err != nil {
- if capoerrors.IsRetryable(err) {
- return false, nil
- }
- return false, err
- }
- if createdInstance.State() == infrav1.InstanceStateError {
- return false, fmt.Errorf("error creating OpenStack instance %s, status changed to error", createdInstance.ID())
- }
- return createdInstance.State() == infrav1.InstanceStateActive, nil
- })
- if err != nil {
- record.Warnf(eventObject, "FailedCreateServer", "Failed to create server %s: %v", instanceSpec.Name, err)
- return nil, err
- }
-
- record.Eventf(eventObject, "SuccessfulCreateServer", "Created server %s with id %s", createdInstance.Name(), createdInstance.ID())
- return createdInstance, nil
+ record.Eventf(eventObject, "SuccessfulCreateServer", "Created server %s with id %s", server.Name, server.ID)
+ return &InstanceStatus{server, s.scope.Logger()}, nil
}
func volumeName(instanceName string, nameSuffix string) string {
diff --git a/pkg/cloud/services/compute/instance_test.go b/pkg/cloud/services/compute/instance_test.go
index 814fd807a9..350a54f74e 100644
--- a/pkg/cloud/services/compute/instance_test.go
+++ b/pkg/cloud/services/compute/instance_test.go
@@ -406,17 +406,6 @@ func TestService_ReconcileInstance(t *testing.T) {
})
}
- // Expected calls when polling for server creation
- expectServerPoll := func(computeRecorder *mock.MockComputeClientMockRecorder, states []string) {
- for _, state := range states {
- computeRecorder.GetServer(instanceUUID).Return(returnedServer(state), nil)
- }
- }
-
- expectServerPollSuccess := func(computeRecorder *mock.MockComputeClientMockRecorder) {
- expectServerPoll(computeRecorder, []string{"ACTIVE"})
- }
-
returnedVolume := func(uuid string, status string) *volumes.Volume {
return &volumes.Volume{
ID: uuid,
@@ -460,7 +449,6 @@ func TestService_ReconcileInstance(t *testing.T) {
expectDefaultImageAndFlavor(r.compute, r.image)
expectCreateServer(r.compute, getDefaultServerMap(), false)
- expectServerPollSuccess(r.compute)
},
wantErr: false,
},
@@ -503,32 +491,6 @@ func TestService_ReconcileInstance(t *testing.T) {
},
wantErr: true,
},
- {
- name: "Poll until server is created",
- getInstanceSpec: getDefaultInstanceSpec,
- expect: func(r *recorders) {
- expectUseExistingDefaultPort(r.network)
- expectDefaultImageAndFlavor(r.compute, r.image)
-
- expectCreateServer(r.compute, getDefaultServerMap(), false)
- expectServerPoll(r.compute, []string{"BUILDING", "ACTIVE"})
- },
- wantErr: false,
- },
- {
- name: "Server errors during creation",
- getInstanceSpec: getDefaultInstanceSpec,
- expect: func(r *recorders) {
- expectUseExistingDefaultPort(r.network)
- expectDefaultImageAndFlavor(r.compute, r.image)
-
- expectCreateServer(r.compute, getDefaultServerMap(), false)
- expectServerPoll(r.compute, []string{"BUILDING", "ERROR"})
-
- // Don't delete ports because the server is created: DeleteInstance will do it
- },
- wantErr: true,
- },
{
name: "Boot from volume success",
getInstanceSpec: func() *InstanceSpec {
@@ -567,7 +529,6 @@ func TestService_ReconcileInstance(t *testing.T) {
},
}
expectCreateServer(r.compute, createMap, false)
- expectServerPollSuccess(r.compute)
// Don't delete ports because the server is created: DeleteInstance will do it
},
@@ -614,7 +575,6 @@ func TestService_ReconcileInstance(t *testing.T) {
},
}
expectCreateServer(r.compute, createMap, false)
- expectServerPollSuccess(r.compute)
// Don't delete ports because the server is created: DeleteInstance will do it
},
@@ -734,7 +694,6 @@ func TestService_ReconcileInstance(t *testing.T) {
},
}
expectCreateServer(r.compute, createMap, false)
- expectServerPollSuccess(r.compute)
// Don't delete ports because the server is created: DeleteInstance will do it
},
@@ -809,7 +768,6 @@ func TestService_ReconcileInstance(t *testing.T) {
},
}
expectCreateServer(r.compute, createMap, false)
- expectServerPollSuccess(r.compute)
// Don't delete ports because the server is created: DeleteInstance will do it
},
@@ -870,7 +828,6 @@ func TestService_ReconcileInstance(t *testing.T) {
},
}
expectCreateServer(r.compute, createMap, false)
- expectServerPollSuccess(r.compute)
// Don't delete ports because the server is created: DeleteInstance will do it
},
diff --git a/pkg/cloud/services/compute/instance_types.go b/pkg/cloud/services/compute/instance_types.go
index d7b5634605..edac01b89d 100644
--- a/pkg/cloud/services/compute/instance_types.go
+++ b/pkg/cloud/services/compute/instance_types.go
@@ -100,25 +100,25 @@ func (is *InstanceStatus) AvailabilityZone() string {
return is.server.AvailabilityZone
}
-// BastionStatus returns an infrav1.BastionStatus for use in the cluster status.
-func (is *InstanceStatus) BastionStatus(openStackCluster *infrav1.OpenStackCluster) (*infrav1.BastionStatus, error) {
- i := infrav1.BastionStatus{
- ID: is.ID(),
- Name: is.Name(),
- SSHKeyName: is.SSHKeyName(),
- State: is.State(),
+// BastionStatus updates BastionStatus in openStackCluster.
+func (is *InstanceStatus) UpdateBastionStatus(openStackCluster *infrav1.OpenStackCluster) {
+ if openStackCluster.Status.Bastion == nil {
+ openStackCluster.Status.Bastion = &infrav1.BastionStatus{}
}
+ openStackCluster.Status.Bastion.ID = is.ID()
+ openStackCluster.Status.Bastion.Name = is.Name()
+ openStackCluster.Status.Bastion.SSHKeyName = is.SSHKeyName()
+ openStackCluster.Status.Bastion.State = is.State()
+
ns, err := is.NetworkStatus()
if err != nil {
- return nil, err
+ // Bastion IP won't be saved in status, error is not critical
+ return
}
clusterNetwork := openStackCluster.Status.Network.Name
- i.IP = ns.IP(clusterNetwork)
- i.FloatingIP = ns.FloatingIP(clusterNetwork)
-
- return &i, nil
+ openStackCluster.Status.Bastion.IP = ns.IP(clusterNetwork)
}
// InstanceIdentifier returns an InstanceIdentifier object for an InstanceStatus.
From f8e5364d297f0d0732cb6ac0c9c6fd3459ac8e21 Mon Sep 17 00:00:00 2001
From: Lennart Jern
Date: Fri, 12 Jan 2024 11:03:27 +0200
Subject: [PATCH 028/180] Bump e2e node images to v1.28.5
---
hack/ci/cloud-init/controller.yaml.tpl | 4 ++--
test/e2e/data/e2e_conf.yaml | 10 +++++-----
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/hack/ci/cloud-init/controller.yaml.tpl b/hack/ci/cloud-init/controller.yaml.tpl
index 89962b70e1..aef474e22e 100644
--- a/hack/ci/cloud-init/controller.yaml.tpl
+++ b/hack/ci/cloud-init/controller.yaml.tpl
@@ -63,8 +63,8 @@
IMAGE_URLS="https://storage.googleapis.com/artifacts.k8s-staging-capi-openstack.appspot.com/test/amphora/2022-12-05/amphora-x64-haproxy.qcow2,"
IMAGE_URLS+="https://storage.googleapis.com/artifacts.k8s-staging-capi-openstack.appspot.com/test/cirros/2022-12-05/cirros-0.6.1-x86_64-disk.img,"
IMAGE_URLS+="https://storage.googleapis.com/artifacts.k8s-staging-capi-openstack.appspot.com/test/ubuntu/2023-09-29/ubuntu-2204-kube-v1.27.2.img,"
- IMAGE_URLS+="https://storage.googleapis.com/artifacts.k8s-staging-capi-openstack.appspot.com/test/ubuntu/2023-09-29/ubuntu-2204-kube-v1.28.2.img,"
- IMAGE_URLS+="https://storage.googleapis.com/artifacts.k8s-staging-capi-openstack.appspot.com/test/flatcar/flatcar-stable-3602.2.0-kube-v1.28.2.img,"
+ IMAGE_URLS+="https://storage.googleapis.com/artifacts.k8s-staging-capi-openstack.appspot.com/test/ubuntu/2024-01-10/ubuntu-2204-kube-v1.28.5.img,"
+ IMAGE_URLS+="https://storage.googleapis.com/artifacts.k8s-staging-capi-openstack.appspot.com/test/flatcar/flatcar-stable-3602.2.3-kube-v1.28.5.img,"
IMAGE_URLS+="https://stable.release.flatcar-linux.net/amd64-usr/current/flatcar_production_openstack_image.img"
[[post-config|$NOVA_CONF]]
diff --git a/test/e2e/data/e2e_conf.yaml b/test/e2e/data/e2e_conf.yaml
index c4c54f9956..faae3fd4db 100644
--- a/test/e2e/data/e2e_conf.yaml
+++ b/test/e2e/data/e2e_conf.yaml
@@ -178,9 +178,9 @@ providers:
variables:
# used to ensure we deploy to the correct management cluster
KUBE_CONTEXT: "kind-capo-e2e"
- KUBERNETES_VERSION: "v1.28.2"
+ KUBERNETES_VERSION: "v1.28.5"
KUBERNETES_VERSION_UPGRADE_FROM: "v1.27.2"
- KUBERNETES_VERSION_UPGRADE_TO: "v1.28.2"
+ KUBERNETES_VERSION_UPGRADE_TO: "v1.28.5"
ETCD_VERSION_UPGRADE_TO: "3.5.9-0"
COREDNS_VERSION_UPGRADE_TO: "v1.10.1"
CONTROL_PLANE_MACHINE_TEMPLATE_UPGRADE_TO: "upgrade-to-control-plane"
@@ -198,7 +198,7 @@ variables:
OPENSTACK_DNS_NAMESERVERS: "8.8.8.8"
OPENSTACK_FAILURE_DOMAIN: "testaz1"
OPENSTACK_FAILURE_DOMAIN_ALT: "testaz2"
- OPENSTACK_IMAGE_NAME: "ubuntu-2204-kube-v1.28.2"
+ OPENSTACK_IMAGE_NAME: "ubuntu-2204-kube-v1.28.5"
OPENSTACK_IMAGE_NAME_UPGRADE_FROM: "ubuntu-2204-kube-v1.27.2"
OPENSTACK_NODE_MACHINE_FLAVOR: "m1.small"
OPENSTACK_SSH_KEY_NAME: "cluster-api-provider-openstack-sigs-k8s-io"
@@ -206,13 +206,13 @@ variables:
OPENSTACK_VOLUME_TYPE_ALT: "test-volume-type"
CONFORMANCE_WORKER_MACHINE_COUNT: "5"
CONFORMANCE_CONTROL_PLANE_MACHINE_COUNT: "1"
- INIT_WITH_KUBERNETES_VERSION: "v1.28.2"
+ INIT_WITH_KUBERNETES_VERSION: "v1.28.5"
E2E_IMAGE_URL: "http://10.0.3.15/capo-e2e-image.tar"
# The default user for SSH connections from bastion to machines
SSH_USER_MACHINE: "ubuntu"
EXP_KUBEADM_BOOTSTRAP_FORMAT_IGNITION: "true"
# The Flatcar image produced by the image-builder
- OPENSTACK_FLATCAR_IMAGE_NAME: "flatcar-stable-3602.2.0-kube-v1.28.2"
+ OPENSTACK_FLATCAR_IMAGE_NAME: "flatcar-stable-3602.2.3-kube-v1.28.5"
# A plain Flatcar from the Flatcar releases server
FLATCAR_IMAGE_NAME: "flatcar_production_openstack_image"
From 4368c4f2be1ffe05d332a9b35fd91dd63561ef23 Mon Sep 17 00:00:00 2001
From: Emilien Macchi
Date: Mon, 18 Dec 2023 13:28:48 -0500
Subject: [PATCH 029/180] Convert Image to use `ImageFilfter` instead of string
Right now, the image for an OpenStackMachine can be defined either
its name via Spec.Image or via Spec.ImageUUID.
Now we will use a single parameter which would be of type ImageFilter.
---
api/v1alpha5/conversion.go | 17 ++++
api/v1alpha5/conversion_test.go | 4 +-
api/v1alpha5/zz_generated.conversion.go | 7 +-
api/v1alpha6/conversion.go | 18 ++++
api/v1alpha6/zz_generated.conversion.go | 7 +-
api/v1alpha7/conversion.go | 18 ++++
api/v1alpha7/zz_generated.conversion.go | 7 +-
api/v1alpha8/filter_convert.go | 9 ++
api/v1alpha8/openstackcluster_webhook_test.go | 4 +-
api/v1alpha8/openstackmachine_types.go | 10 +-
.../openstackmachinetemplate_webhook_test.go | 16 +--
api/v1alpha8/types.go | 13 +++
api/v1alpha8/zz_generated.deepcopy.go | 21 ++++
...re.cluster.x-k8s.io_openstackclusters.yaml | 33 +++++--
...er.x-k8s.io_openstackclustertemplates.yaml | 32 ++++--
...re.cluster.x-k8s.io_openstackmachines.yaml | 32 ++++--
...er.x-k8s.io_openstackmachinetemplates.yaml | 29 ++++--
controllers/openstackcluster_controller.go | 23 +++--
.../openstackcluster_controller_test.go | 13 +++
controllers/openstackmachine_controller.go | 3 +-
.../openstackmachine_controller_test.go | 7 +-
.../crd-changes/v1alpha7-to-v1alpha8.md | 35 +++++++
.../v1alpha8/default/cluster-template.yaml | 6 +-
.../flatcar-sysext/patch-flatcar.yaml | 6 +-
kustomize/v1alpha8/flatcar/patch-flatcar.yaml | 6 +-
pkg/cloud/services/compute/instance.go | 38 ++------
pkg/cloud/services/compute/instance_test.go | 97 +++++++++----------
pkg/cloud/services/compute/instance_types.go | 3 +-
.../services/compute/referenced_resources.go | 10 ++
.../compute/referenced_resources_test.go | 53 ++++++++--
.../cluster-template-flatcar-sysext.yaml | 6 +-
templates/cluster-template-flatcar.yaml | 6 +-
templates/cluster-template-without-lb.yaml | 6 +-
templates/cluster-template.yaml | 6 +-
.../common-patches/cni/patch-cluster.yaml | 3 +-
.../k8s-upgrade/upgrade-from-template.yaml | 6 +-
.../k8s-upgrade/upgrade-to-template.yaml | 6 +-
test/e2e/data/kustomize/v1alpha5/bastion.yaml | 9 ++
.../kustomize/v1alpha5/kustomization.yaml | 6 ++
test/e2e/data/kustomize/v1alpha6/bastion.yaml | 9 ++
.../kustomize/v1alpha6/kustomization.yaml | 4 +
test/e2e/data/kustomize/v1alpha7/bastion.yaml | 9 ++
.../kustomize/v1alpha7/kustomization.yaml | 4 +
test/e2e/suites/e2e/e2e_test.go | 12 ++-
44 files changed, 482 insertions(+), 187 deletions(-)
create mode 100644 test/e2e/data/kustomize/v1alpha5/bastion.yaml
create mode 100644 test/e2e/data/kustomize/v1alpha6/bastion.yaml
create mode 100644 test/e2e/data/kustomize/v1alpha7/bastion.yaml
diff --git a/api/v1alpha5/conversion.go b/api/v1alpha5/conversion.go
index dc675d0c6a..3029ab1038 100644
--- a/api/v1alpha5/conversion.go
+++ b/api/v1alpha5/conversion.go
@@ -247,6 +247,15 @@ func Convert_v1alpha5_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(in *
out.ServerGroup = &infrav1.ServerGroupFilter{}
}
+ imageFilter := infrav1.ImageFilter{}
+ if in.Image != "" {
+ imageFilter.Name = in.Image
+ }
+ if in.ImageUUID != "" {
+ imageFilter.ID = in.ImageUUID
+ }
+ out.Image = imageFilter
+
return nil
}
@@ -480,6 +489,14 @@ func Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(in *
out.ServerGroupID = in.ServerGroup.ID
}
+ if in.Image.Name != "" {
+ out.Image = in.Image.Name
+ }
+
+ if in.Image.ID != "" {
+ out.ImageUUID = in.Image.ID
+ }
+
return nil
}
diff --git a/api/v1alpha5/conversion_test.go b/api/v1alpha5/conversion_test.go
index 839e9bd4a4..f8ad758fca 100644
--- a/api/v1alpha5/conversion_test.go
+++ b/api/v1alpha5/conversion_test.go
@@ -79,7 +79,7 @@ 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,\"referencedResources\":{}}}",
+ "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"cloudName\":\"\",\"flavor\":\"\",\"image\":{}},\"status\":{\"ready\":false,\"referencedResources\":{}}}",
},
},
},
@@ -94,7 +94,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\":{\"cloudName\":\"\",\"flavor\":\"\",\"image\":{}}}}}",
},
},
},
diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go
index b1deb78263..23e8f4595c 100644
--- a/api/v1alpha5/zz_generated.conversion.go
+++ b/api/v1alpha5/zz_generated.conversion.go
@@ -1057,8 +1057,8 @@ func autoConvert_v1alpha5_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(
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 (string vs sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8.ImageFilter)
+ // 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 {
@@ -1100,8 +1100,7 @@ func autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(
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/v1alpha8.ImageFilter vs string)
out.SSHKeyName = in.SSHKeyName
if in.Ports != nil {
in, out := &in.Ports, &out.Ports
diff --git a/api/v1alpha6/conversion.go b/api/v1alpha6/conversion.go
index 56aab5fbf7..ab8d50a1bd 100644
--- a/api/v1alpha6/conversion.go
+++ b/api/v1alpha6/conversion.go
@@ -62,6 +62,7 @@ func restorev1alpha8MachineSpec(previous *infrav1.OpenStackMachineSpec, dst *inf
dst.Ports = previous.Ports
dst.AdditionalBlockDevices = previous.AdditionalBlockDevices
dst.ServerGroup = previous.ServerGroup
+ dst.Image = previous.Image
}
func restorev1alpha8Bastion(previous **infrav1.Bastion, dst **infrav1.Bastion) {
@@ -393,6 +394,15 @@ func Convert_v1alpha6_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(in *
out.ServerGroup = nil
}
+ imageFilter := infrav1.ImageFilter{}
+ if in.Image != "" {
+ imageFilter.Name = in.Image
+ }
+ if in.ImageUUID != "" {
+ imageFilter.ID = in.ImageUUID
+ }
+ out.Image = imageFilter
+
return nil
}
@@ -721,6 +731,14 @@ func Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(in *
out.ServerGroupID = in.ServerGroup.ID
}
+ if in.Image.Name != "" {
+ out.Image = in.Image.Name
+ }
+
+ if in.Image.ID != "" {
+ out.ImageUUID = in.Image.ID
+ }
+
return nil
}
diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go
index 1501975342..63ab1b88b3 100644
--- a/api/v1alpha6/zz_generated.conversion.go
+++ b/api/v1alpha6/zz_generated.conversion.go
@@ -1070,8 +1070,8 @@ func autoConvert_v1alpha6_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(
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 (string vs sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8.ImageFilter)
+ // 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 {
@@ -1113,8 +1113,7 @@ func autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(
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/v1alpha8.ImageFilter vs string)
out.SSHKeyName = in.SSHKeyName
if in.Ports != nil {
in, out := &in.Ports, &out.Ports
diff --git a/api/v1alpha7/conversion.go b/api/v1alpha7/conversion.go
index 89fa5563b5..25dab7a655 100644
--- a/api/v1alpha7/conversion.go
+++ b/api/v1alpha7/conversion.go
@@ -67,6 +67,7 @@ var v1alpha8OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStack
func restorev1alpha8MachineSpec(previous *infrav1.OpenStackMachineSpec, dst *infrav1.OpenStackMachineSpec) {
dst.ServerGroup = previous.ServerGroup
+ dst.Image = previous.Image
}
func restorev1alpha8Bastion(previous **infrav1.Bastion, dst **infrav1.Bastion) {
@@ -273,6 +274,14 @@ func Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(in *
out.ServerGroupID = in.ServerGroup.ID
}
+ if in.Image.Name != "" {
+ out.Image = in.Image.Name
+ }
+
+ if in.Image.ID != "" {
+ out.ImageUUID = in.Image.ID
+ }
+
return nil
}
@@ -288,6 +297,15 @@ func Convert_v1alpha7_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(in *
out.ServerGroup = nil
}
+ imageFilter := infrav1.ImageFilter{}
+ if in.Image != "" {
+ imageFilter.Name = in.Image
+ }
+ if in.ImageUUID != "" {
+ imageFilter.ID = in.ImageUUID
+ }
+ out.Image = imageFilter
+
return nil
}
diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go
index dc95a9500f..25b03fcc7e 100644
--- a/api/v1alpha7/zz_generated.conversion.go
+++ b/api/v1alpha7/zz_generated.conversion.go
@@ -1232,8 +1232,8 @@ func autoConvert_v1alpha7_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(
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 (string vs sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8.ImageFilter)
+ // WARNING: in.ImageUUID requires manual conversion: does not exist in peer-type
out.SSHKeyName = in.SSHKeyName
out.Ports = *(*[]v1alpha8.PortOpts)(unsafe.Pointer(&in.Ports))
out.FloatingIP = in.FloatingIP
@@ -1254,8 +1254,7 @@ func autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(
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/v1alpha8.ImageFilter vs string)
out.SSHKeyName = in.SSHKeyName
out.Ports = *(*[]PortOpts)(unsafe.Pointer(&in.Ports))
out.FloatingIP = in.FloatingIP
diff --git a/api/v1alpha8/filter_convert.go b/api/v1alpha8/filter_convert.go
index 23e5330588..378642ce5f 100644
--- a/api/v1alpha8/filter_convert.go
+++ b/api/v1alpha8/filter_convert.go
@@ -17,6 +17,7 @@ limitations under the License.
package v1alpha8
import (
+ "github.com/gophercloud/gophercloud/openstack/imageservice/v2/images"
"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"
@@ -79,3 +80,11 @@ func (routerFilter RouterFilter) ToListOpt() routers.ListOpts {
NotTagsAny: routerFilter.NotTagsAny,
}
}
+
+func (imageFilter ImageFilter) ToListOpt() images.ListOpts {
+ return images.ListOpts{
+ ID: imageFilter.ID,
+ Name: imageFilter.Name,
+ Tags: imageFilter.Tags,
+ }
+}
diff --git a/api/v1alpha8/openstackcluster_webhook_test.go b/api/v1alpha8/openstackcluster_webhook_test.go
index 256988c81a..cf4f33da27 100644
--- a/api/v1alpha8/openstackcluster_webhook_test.go
+++ b/api/v1alpha8/openstackcluster_webhook_test.go
@@ -119,7 +119,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
Bastion: &Bastion{
Instance: OpenStackMachineSpec{
CloudName: "foobar",
- Image: "foobar",
+ Image: ImageFilter{Name: "foobar"},
Flavor: "minimal",
},
Enabled: true,
@@ -137,7 +137,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
Bastion: &Bastion{
Instance: OpenStackMachineSpec{
CloudName: "foobarbaz",
- Image: "foobarbaz",
+ Image: ImageFilter{Name: "foobarbaz"},
Flavor: "medium",
},
Enabled: true,
diff --git a/api/v1alpha8/openstackmachine_types.go b/api/v1alpha8/openstackmachine_types.go
index dc06385276..d5b27b4648 100644
--- a/api/v1alpha8/openstackmachine_types.go
+++ b/api/v1alpha8/openstackmachine_types.go
@@ -45,13 +45,9 @@ type OpenStackMachineSpec struct {
// 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.
+ Image ImageFilter `json:"image,omitempty"`
// The ssh key to inject in the instance
SSHKeyName string `json:"sshKeyName,omitempty"`
diff --git a/api/v1alpha8/openstackmachinetemplate_webhook_test.go b/api/v1alpha8/openstackmachinetemplate_webhook_test.go
index 6728f9d5fe..e441ef0583 100644
--- a/api/v1alpha8/openstackmachinetemplate_webhook_test.go
+++ b/api/v1alpha8/openstackmachinetemplate_webhook_test.go
@@ -45,7 +45,7 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) {
Template: OpenStackMachineTemplateResource{
Spec: OpenStackMachineSpec{
Flavor: "foo",
- Image: "bar",
+ Image: ImageFilter{Name: "bar"},
},
},
},
@@ -55,7 +55,7 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) {
Template: OpenStackMachineTemplateResource{
Spec: OpenStackMachineSpec{
Flavor: "foo",
- Image: "NewImage",
+ Image: ImageFilter{Name: "NewImage"},
},
},
},
@@ -70,7 +70,7 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) {
Template: OpenStackMachineTemplateResource{
Spec: OpenStackMachineSpec{
Flavor: "foo",
- Image: "bar",
+ Image: ImageFilter{Name: "bar"},
},
},
},
@@ -83,7 +83,7 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) {
Template: OpenStackMachineTemplateResource{
Spec: OpenStackMachineSpec{
Flavor: "foo",
- Image: "bar",
+ Image: ImageFilter{Name: "bar"},
},
},
},
@@ -100,7 +100,7 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) {
Template: OpenStackMachineTemplateResource{
Spec: OpenStackMachineSpec{
Flavor: "foo",
- Image: "bar",
+ Image: ImageFilter{Name: "bar"},
},
},
},
@@ -110,7 +110,7 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) {
Template: OpenStackMachineTemplateResource{
Spec: OpenStackMachineSpec{
Flavor: "foo",
- Image: "NewImage",
+ Image: ImageFilter{Name: "NewImage"},
},
},
},
@@ -125,7 +125,7 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) {
Template: OpenStackMachineTemplateResource{
Spec: OpenStackMachineSpec{
Flavor: "foo",
- Image: "bar",
+ Image: ImageFilter{Name: "bar"},
},
},
},
@@ -140,7 +140,7 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) {
Template: OpenStackMachineTemplateResource{
Spec: OpenStackMachineSpec{
Flavor: "foo",
- Image: "NewImage",
+ Image: ImageFilter{Name: "NewImage"},
},
},
},
diff --git a/api/v1alpha8/types.go b/api/v1alpha8/types.go
index d945249e00..016fb258ed 100644
--- a/api/v1alpha8/types.go
+++ b/api/v1alpha8/types.go
@@ -22,6 +22,15 @@ type OpenStackMachineTemplateResource struct {
Spec OpenStackMachineSpec `json:"spec"`
}
+type ImageFilter struct {
+ // The ID of the desired image. If this is provided, the other filters will be ignored.
+ ID string `json:"id,omitempty"`
+ // 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.
+ Name 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.
+ Tags []string `json:"tags,omitempty"`
+}
+
type ExternalRouterIPParam struct {
// The FixedIP in the corresponding subnet
FixedIP string `json:"fixedIP,omitempty"`
@@ -371,6 +380,10 @@ type ReferencedMachineResources 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"`
}
// ValueSpec represents a single value_spec key-value pair.
diff --git a/api/v1alpha8/zz_generated.deepcopy.go b/api/v1alpha8/zz_generated.deepcopy.go
index c2d6b9fbc0..6598146562 100644
--- a/api/v1alpha8/zz_generated.deepcopy.go
+++ b/api/v1alpha8/zz_generated.deepcopy.go
@@ -201,6 +201,26 @@ 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.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 *LoadBalancer) DeepCopyInto(out *LoadBalancer) {
*out = *in
@@ -647,6 +667,7 @@ func (in *OpenStackMachineSpec) DeepCopyInto(out *OpenStackMachineSpec) {
*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))
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 2041780515..0a8cf90fd1 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -4912,14 +4912,27 @@ spec:
- 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.
- type: string
- imageUUID:
- description: The uuid of the image to use for your server
- instance. if it's empty, Image name will be used
- type: string
+ description: The image to use for your server instance. If
+ the rootVolume is specified, this will be used when creating
+ the root volume.
+ properties:
+ id:
+ description: The ID of the desired image. If this is provided,
+ the other filters will be ignored.
+ type: string
+ 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
+ type: object
instanceID:
description: InstanceID is the OpenStack instance ID for this
machine.
@@ -5480,6 +5493,10 @@ spec:
description: ReferencedMachineResources contains resolved references
to resources required by the machine.
properties:
+ imageID:
+ description: ImageID is the ID of the image to use for the
+ machine and is calculated based on ImageFilter.
+ type: string
serverGroupID:
description: ServerGroupID is the ID of the server group the
machine should be added to and is calculated based on ServerGroupFilter.
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 b6a64b4fde..08e725eae4 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -2445,15 +2445,29 @@ spec:
- 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.
- type: string
- imageUUID:
- description: The uuid of the image to use for your
- server instance. if it's empty, Image name will
- be used
- type: string
+ description: The image to use for your server instance.
+ If the rootVolume is specified, this will be used
+ when creating the root volume.
+ properties:
+ id:
+ description: The ID of the desired image. If this
+ is provided, the other filters will be ignored.
+ type: string
+ 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
+ type: object
instanceID:
description: InstanceID is the OpenStack instance
ID for this machine.
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 0a0d924c8c..a0bde06ad8 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
@@ -1749,14 +1749,26 @@ spec:
- 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.
- type: string
- imageUUID:
- description: The uuid of the image to use for your server instance.
- if it's empty, Image name will be used
- type: string
+ description: The image to use for your server instance. If the rootVolume
+ is specified, this will be used when creating the root volume.
+ properties:
+ id:
+ description: The ID of the desired image. If this is provided,
+ the other filters will be ignored.
+ type: string
+ 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
+ type: object
instanceID:
description: InstanceID is the OpenStack instance ID for this machine.
type: string
@@ -2114,6 +2126,10 @@ spec:
description: ReferencedResources contains resolved references to resources
that the machine depends on.
properties:
+ imageID:
+ description: ImageID is the ID of the image to use for the machine
+ and is calculated based on ImageFilter.
+ type: string
serverGroupID:
description: ServerGroupID is the ID of the server group the machine
should be added to and is calculated based on ServerGroupFilter.
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 8fccb2d323..16da499668 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
@@ -1464,14 +1464,27 @@ spec:
- 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.
- type: string
- imageUUID:
- description: The uuid of the image to use for your server
- instance. if it's empty, Image name will be used
- type: string
+ description: The image to use for your server instance. If
+ the rootVolume is specified, this will be used when creating
+ the root volume.
+ properties:
+ id:
+ description: The ID of the desired image. If this is provided,
+ the other filters will be ignored.
+ type: string
+ 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
+ type: object
instanceID:
description: InstanceID is the OpenStack instance ID for this
machine.
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index cc574755d5..9b857b7011 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -252,7 +252,10 @@ func deleteBastion(scope scope.Scope, cluster *clusterv1.Cluster, openStackClust
}
}
- instanceSpec := bastionToInstanceSpec(openStackCluster, cluster.Name)
+ instanceSpec, err := bastionToInstanceSpec(openStackCluster, cluster.Name, computeService)
+ if err != nil {
+ return fmt.Errorf("failed to create bastion InstanceSpec: %w", err)
+ }
if err = computeService.DeleteInstance(openStackCluster, openStackCluster, instanceStatus, instanceSpec); err != nil {
handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to delete bastion: %w", err))
@@ -336,7 +339,11 @@ func reconcileBastion(scope scope.Scope, cluster *clusterv1.Cluster, openStackCl
return reconcile.Result{}, err
}
- instanceSpec := bastionToInstanceSpec(openStackCluster, cluster.Name)
+ instanceSpec, err := bastionToInstanceSpec(openStackCluster, cluster.Name, computeService)
+ if err != nil {
+ return reconcile.Result{}, fmt.Errorf("failed to create bastion InstanceSpec: %w", err)
+ }
+
bastionHash, err := compute.HashInstanceSpec(instanceSpec)
if err != nil {
return reconcile.Result{}, fmt.Errorf("failed computing bastion hash from instance spec: %w", err)
@@ -427,13 +434,17 @@ func reconcileBastion(scope scope.Scope, cluster *clusterv1.Cluster, openStackCl
return ctrl.Result{}, nil
}
-func bastionToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, clusterName string) *compute.InstanceSpec {
+func bastionToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, clusterName string, computeService *compute.Service) (*compute.InstanceSpec, error) {
+ imageID, err := computeService.GetImageID(openStackCluster.Spec.Bastion.Instance.Image)
+ if err != nil {
+ return nil, fmt.Errorf("failed to get image ID for bastion: %w", err)
+ }
+
instanceSpec := &compute.InstanceSpec{
Name: bastionName(clusterName),
Flavor: openStackCluster.Spec.Bastion.Instance.Flavor,
SSHKeyName: openStackCluster.Spec.Bastion.Instance.SSHKeyName,
- Image: openStackCluster.Spec.Bastion.Instance.Image,
- ImageUUID: openStackCluster.Spec.Bastion.Instance.ImageUUID,
+ ImageID: imageID,
FailureDomain: openStackCluster.Spec.Bastion.AvailabilityZone,
RootVolume: openStackCluster.Spec.Bastion.Instance.RootVolume,
}
@@ -449,7 +460,7 @@ func bastionToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, clusterNa
instanceSpec.Ports = openStackCluster.Spec.Bastion.Instance.Ports
- return instanceSpec
+ return instanceSpec, nil
}
func bastionName(clusterName string) string {
diff --git a/controllers/openstackcluster_controller_test.go b/controllers/openstackcluster_controller_test.go
index 5c59e7c807..5cf980b024 100644
--- a/controllers/openstackcluster_controller_test.go
+++ b/controllers/openstackcluster_controller_test.go
@@ -25,6 +25,7 @@ import (
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/attachinterfaces"
"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/external"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips"
@@ -249,6 +250,9 @@ var _ = Describe("OpenStackCluster controller", func() {
server.ID = "adopted-bastion-uuid"
server.Status = "ACTIVE"
+ imageClientRecorder := mockScopeFactory.ImageClient.EXPECT()
+ imageClientRecorder.ListImages(gomock.Any()).Return([]images.Image{{ID: "imageID"}}, nil)
+
computeClientRecorder := mockScopeFactory.ComputeClient.EXPECT()
computeClientRecorder.ListServers(servers.ListOpts{
Name: "^capi-cluster-bastion$",
@@ -294,6 +298,9 @@ var _ = Describe("OpenStackCluster controller", func() {
server.ID = "adopted-fip-bastion-uuid"
server.Status = "ACTIVE"
+ imageClientRecorder := mockScopeFactory.ImageClient.EXPECT()
+ imageClientRecorder.ListImages(gomock.Any()).Return([]images.Image{{ID: "imageID"}}, nil)
+
computeClientRecorder := mockScopeFactory.ComputeClient.EXPECT()
computeClientRecorder.GetServer("adopted-fip-bastion-uuid").Return(&server, nil)
@@ -337,6 +344,9 @@ var _ = Describe("OpenStackCluster controller", func() {
server.ID = "requeue-bastion-uuid"
server.Status = "BUILD"
+ imageClientRecorder := mockScopeFactory.ImageClient.EXPECT()
+ imageClientRecorder.ListImages(gomock.Any()).Return([]images.Image{{ID: "imageID"}}, nil)
+
computeClientRecorder := mockScopeFactory.ComputeClient.EXPECT()
computeClientRecorder.GetServer("requeue-bastion-uuid").Return(&server, nil)
@@ -361,6 +371,9 @@ var _ = Describe("OpenStackCluster controller", func() {
server := clients.ServerExt{}
server.ID = "delete-bastion-uuid"
+ imageClientRecorder := mockScopeFactory.ImageClient.EXPECT()
+ imageClientRecorder.ListImages(gomock.Any()).Return([]images.Image{{ID: "imageID"}}, nil)
+
computeClientRecorder := mockScopeFactory.ComputeClient.EXPECT()
computeClientRecorder.ListServers(servers.ListOpts{
Name: "^capi-cluster-bastion$",
diff --git a/controllers/openstackmachine_controller.go b/controllers/openstackmachine_controller.go
index 83ac3726a5..77104d804a 100644
--- a/controllers/openstackmachine_controller.go
+++ b/controllers/openstackmachine_controller.go
@@ -483,8 +483,7 @@ func (r *OpenStackMachineReconciler) getOrCreate(logger logr.Logger, cluster *cl
func machineToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, machine *clusterv1.Machine, openStackMachine *infrav1.OpenStackMachine, userData string) *compute.InstanceSpec {
instanceSpec := compute.InstanceSpec{
Name: openStackMachine.Name,
- Image: openStackMachine.Spec.Image,
- ImageUUID: openStackMachine.Spec.ImageUUID,
+ ImageID: openStackMachine.Status.ReferencedResources.ImageID,
Flavor: openStackMachine.Spec.Flavor,
SSHKeyName: openStackMachine.Spec.SSHKeyName,
UserData: userData,
diff --git a/controllers/openstackmachine_controller_test.go b/controllers/openstackmachine_controller_test.go
index cfdeed7bcf..bc0c3b96c5 100644
--- a/controllers/openstackmachine_controller_test.go
+++ b/controllers/openstackmachine_controller_test.go
@@ -35,10 +35,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"
@@ -83,7 +83,7 @@ func getDefaultOpenStackMachine() *infrav1.OpenStackMachine {
// TODO: Test Networks, Ports, Subnet, and Trunk separately
CloudName: "test-cloud",
Flavor: flavorName,
- Image: imageName,
+ Image: infrav1.ImageFilter{ID: imageUUID},
SSHKeyName: sshKeyName,
Tags: []string{"test-tag"},
ServerMetadata: map[string]string{
@@ -95,6 +95,7 @@ func getDefaultOpenStackMachine() *infrav1.OpenStackMachine {
},
Status: infrav1.OpenStackMachineStatus{
ReferencedResources: infrav1.ReferencedMachineResources{
+ ImageID: imageUUID,
ServerGroupID: serverGroupUUID,
},
},
@@ -104,7 +105,7 @@ func getDefaultOpenStackMachine() *infrav1.OpenStackMachine {
func getDefaultInstanceSpec() *compute.InstanceSpec {
return &compute.InstanceSpec{
Name: openStackMachineName,
- Image: imageName,
+ ImageID: imageUUID,
Flavor: flavorName,
SSHKeyName: sshKeyName,
UserData: "user-data",
diff --git a/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md b/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md
index ed8558bbfe..1183805d26 100644
--- a/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md
+++ b/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md
@@ -9,6 +9,8 @@
- [Change to `serverGroupID`](#change-to-servergroupid)
- [`OpenStackCluster`](#openstackcluster)
- [Change to externalNetworkID](#change-to-externalnetworkid)
+ - [Changes to image](#change-to-image)
+ - [Removal of imageUUID](#removal-of-imageuuid)
@@ -88,3 +90,36 @@ It is now possible for a user to specify that no external network should be used
```yaml
disableExternalNetwork: true
```
+
+#### ⚠️ Change to image
+
+The field `image` is now an `ImageFilter` object rather than a string name.
+The `ImageFilter` object allows selection of an image by name, by ID or by tags.
+
+```yaml
+image: "test-image"
+```
+
+becomes
+
+```yaml
+image:
+ name: "test-image"
+```
+
+The image ID will be added to `OpenStackMachine.Status.ReferencedResources.ImageID`. If the image can't be found or filter matches multiple images, an error will be returned.
+
+#### ⚠️ Removal of imageUUID
+
+The fild `imageUUID` has been removed in favor of the `image` field.
+
+```yaml
+imageUUID: "72a6a1e6-3e0a-4a8b-9b4c-2d6f9e3e5f0a"
+```
+
+becomes
+
+```yaml
+image:
+ id: "72a6a1e6-3e0a-4a8b-9b4c-2d6f9e3e5f0a"
+```
diff --git a/kustomize/v1alpha8/default/cluster-template.yaml b/kustomize/v1alpha8/default/cluster-template.yaml
index 5c0d1113d6..0dc7472f18 100644
--- a/kustomize/v1alpha8/default/cluster-template.yaml
+++ b/kustomize/v1alpha8/default/cluster-template.yaml
@@ -77,7 +77,8 @@ spec:
template:
spec:
flavor: ${OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR}
- image: ${OPENSTACK_IMAGE_NAME}
+ image:
+ name: ${OPENSTACK_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
cloudName: ${OPENSTACK_CLOUD}
identityRef:
@@ -120,7 +121,8 @@ spec:
name: ${CLUSTER_NAME}-cloud-config
kind: Secret
flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR}
- image: ${OPENSTACK_IMAGE_NAME}
+ image:
+ name: ${OPENSTACK_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
---
apiVersion: bootstrap.cluster.x-k8s.io/v1beta1
diff --git a/kustomize/v1alpha8/flatcar-sysext/patch-flatcar.yaml b/kustomize/v1alpha8/flatcar-sysext/patch-flatcar.yaml
index f1616ac759..e66245f777 100644
--- a/kustomize/v1alpha8/flatcar-sysext/patch-flatcar.yaml
+++ b/kustomize/v1alpha8/flatcar-sysext/patch-flatcar.yaml
@@ -173,7 +173,8 @@ metadata:
spec:
template:
spec:
- image: ${FLATCAR_IMAGE_NAME}
+ image:
+ name: ${FLATCAR_IMAGE_NAME}
---
apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
@@ -182,4 +183,5 @@ metadata:
spec:
template:
spec:
- image: ${FLATCAR_IMAGE_NAME}
+ image:
+ name: ${FLATCAR_IMAGE_NAME}
diff --git a/kustomize/v1alpha8/flatcar/patch-flatcar.yaml b/kustomize/v1alpha8/flatcar/patch-flatcar.yaml
index d3750014fb..4fb1c3a8d1 100644
--- a/kustomize/v1alpha8/flatcar/patch-flatcar.yaml
+++ b/kustomize/v1alpha8/flatcar/patch-flatcar.yaml
@@ -97,7 +97,8 @@ metadata:
spec:
template:
spec:
- image: ${OPENSTACK_FLATCAR_IMAGE_NAME}
+ image:
+ name: ${OPENSTACK_FLATCAR_IMAGE_NAME}
---
apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
@@ -106,4 +107,5 @@ metadata:
spec:
template:
spec:
- image: ${OPENSTACK_FLATCAR_IMAGE_NAME}
+ image:
+ name: ${OPENSTACK_FLATCAR_IMAGE_NAME}
diff --git a/pkg/cloud/services/compute/instance.go b/pkg/cloud/services/compute/instance.go
index b5a91b16c2..e5648a26f0 100644
--- a/pkg/cloud/services/compute/instance.go
+++ b/pkg/cloud/services/compute/instance.go
@@ -30,7 +30,6 @@ import (
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/schedulerhints"
"github.com/gophercloud/gophercloud/openstack/compute/v2/flavors"
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
- "github.com/gophercloud/gophercloud/openstack/imageservice/v2/images"
"github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/wait"
@@ -238,11 +237,6 @@ func (s *Service) createInstanceImpl(eventObject runtime.Object, openStackCluste
var server *clients.ServerExt
portList := []servers.Network{}
- imageID, err := s.getImageID(instanceSpec.ImageUUID, instanceSpec.Image)
- if err != nil {
- return nil, fmt.Errorf("error getting image ID: %v", err)
- }
-
flavor, err := s.getAndValidateFlavor(instanceSpec.Flavor)
if err != nil {
return nil, err
@@ -297,7 +291,7 @@ func (s *Service) createInstanceImpl(eventObject runtime.Object, openStackCluste
// Don't set ImageRef on the server if we're booting from volume
var serverImageRef string
if !hasRootVolume(instanceSpec) {
- serverImageRef = imageID
+ serverImageRef = instanceSpec.ImageID
}
var serverCreateOpts servers.CreateOptsBuilder = servers.CreateOpts{
@@ -312,7 +306,7 @@ func (s *Service) createInstanceImpl(eventObject runtime.Object, openStackCluste
ConfigDrive: &instanceSpec.ConfigDrive,
}
- blockDevices, err := s.getBlockDevices(eventObject, instanceSpec, imageID, instanceCreateTimeout, retryInterval)
+ blockDevices, err := s.getBlockDevices(eventObject, instanceSpec, instanceSpec.ImageID, instanceCreateTimeout, retryInterval)
if err != nil {
return nil, err
}
@@ -543,40 +537,28 @@ func applyServerGroupID(opts servers.CreateOptsBuilder, serverGroupID string) se
return opts
}
-// Helper function for getting image id from name.
-func (s *Service) getImageIDFromName(imageName string) (string, error) {
- var opts images.ListOpts
-
- opts.Name = imageName
+// Helper function for getting image ID from name, ID, or tags.
+func (s *Service) GetImageID(image infrav1.ImageFilter) (string, error) {
+ if image.ID != "" {
+ return image.ID, nil
+ }
- allImages, err := s.getImageClient().ListImages(opts)
+ allImages, err := s.getImageClient().ListImages(image.ToListOpt())
if err != nil {
return "", err
}
switch len(allImages) {
case 0:
- return "", fmt.Errorf("no image with the Name %s could be found", imageName)
+ return "", fmt.Errorf("no images were found with the given image filter: %v", image)
case 1:
return allImages[0].ID, nil
default:
// this should never happen
- return "", fmt.Errorf("too many images with the name, %s, were found", imageName)
+ return "", fmt.Errorf("too many images were found with the given image filter: %v", image)
}
}
-// Helper function for getting image ID from name or ID.
-func (s *Service) getImageID(imageUUID, imageName string) (string, error) {
- if imageUUID != "" {
- // we return imageUUID without check
- return imageUUID, nil
- } else if imageName != "" {
- return s.getImageIDFromName(imageName)
- }
-
- return "", nil
-}
-
// GetManagementPort returns the port which is used for management and external
// traffic. Cluster floating IPs must be associated with this port.
func (s *Service) GetManagementPort(openStackCluster *infrav1.OpenStackCluster, instanceStatus *InstanceStatus) (*ports.Port, error) {
diff --git a/pkg/cloud/services/compute/instance_test.go b/pkg/cloud/services/compute/instance_test.go
index 350a54f74e..d868e47940 100644
--- a/pkg/cloud/services/compute/instance_test.go
+++ b/pkg/cloud/services/compute/instance_test.go
@@ -119,51 +119,51 @@ func Test_getPortName(t *testing.T) {
}
func TestService_getImageID(t *testing.T) {
- const imageIDA = "ce96e584-7ebc-46d6-9e55-987d72e3806c"
- const imageIDB = "8f536889-5198-42d7-8314-cb78f4f4755c"
- const imageIDC = "8f536889-5198-42d7-8314-cb78f4f4755d"
+ const imageID = "ce96e584-7ebc-46d6-9e55-987d72e3806c"
+ const imageName = "test-image"
+ imageTags := []string{"test-tag"}
tests := []struct {
- testName string
- imageUUID string
- imageName string
- expect func(m *mock.MockImageClientMockRecorder)
- want string
- wantErr bool
+ testName string
+ image infrav1.ImageFilter
+ expect func(m *mock.MockImageClientMockRecorder)
+ want string
+ wantErr bool
}{
{
- testName: "Return image uuid if uuid given",
- imageUUID: imageIDC,
- want: imageIDC,
- expect: func(m *mock.MockImageClientMockRecorder) {
- },
- wantErr: false,
+ testName: "Return image ID when ID given",
+ image: infrav1.ImageFilter{ID: imageID},
+ want: imageID,
+ expect: func(m *mock.MockImageClientMockRecorder) {},
+ wantErr: false,
},
{
- testName: "Return through uuid if both uuid and name given",
- imageName: "dummy",
- imageUUID: imageIDC,
+ testName: "Return image ID when name given",
+ image: infrav1.ImageFilter{Name: imageName},
+ want: imageID,
expect: func(m *mock.MockImageClientMockRecorder) {
+ m.ListImages(images.ListOpts{Name: imageName}).Return(
+ []images.Image{{ID: imageID, Name: imageName}},
+ nil)
},
- want: imageIDC,
wantErr: false,
},
{
- testName: "Return image ID",
- imageName: "test-image",
+ testName: "Return image ID when tags given",
+ image: infrav1.ImageFilter{Tags: imageTags},
+ want: imageID,
expect: func(m *mock.MockImageClientMockRecorder) {
- m.ListImages(images.ListOpts{Name: "test-image"}).Return(
- []images.Image{{ID: imageIDA, Name: "test-image"}},
+ m.ListImages(images.ListOpts{Tags: imageTags}).Return(
+ []images.Image{{ID: imageID, Name: imageName, Tags: imageTags}},
nil)
},
- want: imageIDA,
wantErr: false,
},
{
- testName: "Return no results",
- imageName: "test-image",
+ testName: "Return no results",
+ image: infrav1.ImageFilter{Name: imageName},
expect: func(m *mock.MockImageClientMockRecorder) {
- m.ListImages(images.ListOpts{Name: "test-image"}).Return(
+ m.ListImages(images.ListOpts{Name: imageName}).Return(
[]images.Image{},
nil)
},
@@ -171,21 +171,21 @@ func TestService_getImageID(t *testing.T) {
wantErr: true,
},
{
- testName: "Return multiple results",
- imageName: "test-image",
+ testName: "Return multiple results",
+ image: infrav1.ImageFilter{Name: imageName},
expect: func(m *mock.MockImageClientMockRecorder) {
m.ListImages(images.ListOpts{Name: "test-image"}).Return(
[]images.Image{
- {ID: imageIDA, Name: "test-image"},
- {ID: imageIDB, Name: "test-image"},
+ {ID: imageID, Name: "test-image"},
+ {ID: "123", Name: "test-image"},
}, nil)
},
want: "",
wantErr: true,
},
{
- testName: "OpenStack returns error",
- imageName: "test-image",
+ testName: "OpenStack returns error",
+ image: infrav1.ImageFilter{Name: imageName},
expect: func(m *mock.MockImageClientMockRecorder) {
m.ListImages(images.ListOpts{Name: "test-image"}).Return(
nil,
@@ -206,7 +206,7 @@ func TestService_getImageID(t *testing.T) {
}
tt.expect(mockScopeFactory.ImageClient.EXPECT())
- got, err := s.getImageID(tt.imageUUID, tt.imageName)
+ got, err := s.GetImageID(tt.image)
if (err != nil) != tt.wantErr {
t.Errorf("Service.getImageID() error = %v, wantErr %v", err, tt.wantErr)
return
@@ -261,7 +261,7 @@ func getDefaultOpenStackCluster() *infrav1.OpenStackCluster {
func getDefaultInstanceSpec() *InstanceSpec {
return &InstanceSpec{
Name: openStackMachineName,
- Image: imageName,
+ ImageID: imageUUID,
Flavor: flavorName,
SSHKeyName: sshKeyName,
UserData: "user-data",
@@ -375,9 +375,8 @@ func TestService_ReconcileInstance(t *testing.T) {
networkRecorder.DeletePort(portUUID).Return(nil)
}
- // Expected calls when using default image and flavor
- expectDefaultImageAndFlavor := func(computeRecorder *mock.MockComputeClientMockRecorder, imageRecorder *mock.MockImageClientMockRecorder) {
- imageRecorder.ListImages(images.ListOpts{Name: imageName}).Return([]images.Image{{ID: imageUUID}}, nil)
+ // Expected calls when using default flavor
+ expectDefaultFlavor := func(computeRecorder *mock.MockComputeClientMockRecorder) {
f := flavors.Flavor{
ID: flavorUUID,
VCPUs: 2,
@@ -446,7 +445,7 @@ func TestService_ReconcileInstance(t *testing.T) {
getInstanceSpec: getDefaultInstanceSpec,
expect: func(r *recorders) {
expectUseExistingDefaultPort(r.network)
- expectDefaultImageAndFlavor(r.compute, r.image)
+ expectDefaultFlavor(r.compute)
expectCreateServer(r.compute, getDefaultServerMap(), false)
},
@@ -457,7 +456,7 @@ func TestService_ReconcileInstance(t *testing.T) {
getInstanceSpec: getDefaultInstanceSpec,
expect: func(r *recorders) {
expectUseExistingDefaultPort(r.network)
- expectDefaultImageAndFlavor(r.compute, r.image)
+ expectDefaultFlavor(r.compute)
expectCreateServer(r.compute, getDefaultServerMap(), true)
@@ -477,7 +476,7 @@ func TestService_ReconcileInstance(t *testing.T) {
return s
},
expect: func(r *recorders) {
- expectDefaultImageAndFlavor(r.compute, r.image)
+ expectDefaultFlavor(r.compute)
expectUseExistingDefaultPort(r.network)
// Looking up the second port fails
@@ -502,7 +501,7 @@ func TestService_ReconcileInstance(t *testing.T) {
},
expect: func(r *recorders) {
expectUseExistingDefaultPort(r.network)
- expectDefaultImageAndFlavor(r.compute, r.image)
+ expectDefaultFlavor(r.compute)
r.volume.ListVolumes(volumes.ListOpts{Name: fmt.Sprintf("%s-root", openStackMachineName)}).
Return([]volumes.Volume{}, nil)
@@ -547,7 +546,7 @@ func TestService_ReconcileInstance(t *testing.T) {
},
expect: func(r *recorders) {
expectUseExistingDefaultPort(r.network)
- expectDefaultImageAndFlavor(r.compute, r.image)
+ expectDefaultFlavor(r.compute)
r.volume.ListVolumes(volumes.ListOpts{Name: fmt.Sprintf("%s-root", openStackMachineName)}).
Return([]volumes.Volume{}, nil)
@@ -591,7 +590,7 @@ func TestService_ReconcileInstance(t *testing.T) {
},
expect: func(r *recorders) {
expectUseExistingDefaultPort(r.network)
- expectDefaultImageAndFlavor(r.compute, r.image)
+ expectDefaultFlavor(r.compute)
r.volume.ListVolumes(volumes.ListOpts{Name: fmt.Sprintf("%s-root", openStackMachineName)}).
Return([]volumes.Volume{}, nil)
@@ -639,7 +638,7 @@ func TestService_ReconcileInstance(t *testing.T) {
},
expect: func(r *recorders) {
expectUseExistingDefaultPort(r.network)
- expectDefaultImageAndFlavor(r.compute, r.image)
+ expectDefaultFlavor(r.compute)
r.volume.ListVolumes(volumes.ListOpts{Name: fmt.Sprintf("%s-root", openStackMachineName)}).
Return([]volumes.Volume{}, nil)
@@ -726,7 +725,7 @@ func TestService_ReconcileInstance(t *testing.T) {
},
expect: func(r *recorders) {
expectUseExistingDefaultPort(r.network)
- expectDefaultImageAndFlavor(r.compute, r.image)
+ expectDefaultFlavor(r.compute)
r.volume.ListVolumes(volumes.ListOpts{Name: fmt.Sprintf("%s-etcd", openStackMachineName)}).
Return([]volumes.Volume{}, nil)
@@ -794,7 +793,7 @@ func TestService_ReconcileInstance(t *testing.T) {
},
expect: func(r *recorders) {
expectUseExistingDefaultPort(r.network)
- expectDefaultImageAndFlavor(r.compute, r.image)
+ expectDefaultFlavor(r.compute)
r.volume.ListVolumes(volumes.ListOpts{Name: fmt.Sprintf("%s-etcd", openStackMachineName)}).
Return([]volumes.Volume{}, nil)
@@ -850,7 +849,7 @@ func TestService_ReconcileInstance(t *testing.T) {
},
expect: func(r *recorders) {
expectUseExistingDefaultPort(r.network)
- expectDefaultImageAndFlavor(r.compute, r.image)
+ expectDefaultFlavor(r.compute)
// Make sure we delete ports
expectCleanupDefaultPort(r.network)
@@ -868,7 +867,7 @@ func TestService_ReconcileInstance(t *testing.T) {
return s
},
expect: func(r *recorders) {
- expectDefaultImageAndFlavor(r.compute, r.image)
+ expectDefaultFlavor(r.compute)
extensions := []extensions.Extension{
{Extension: common.Extension{Alias: "trunk"}},
}
diff --git a/pkg/cloud/services/compute/instance_types.go b/pkg/cloud/services/compute/instance_types.go
index edac01b89d..0384e64f89 100644
--- a/pkg/cloud/services/compute/instance_types.go
+++ b/pkg/cloud/services/compute/instance_types.go
@@ -34,8 +34,7 @@ import (
// all of them can be set on a new instance.
type InstanceSpec struct {
Name string
- Image string
- ImageUUID string
+ ImageID string
Flavor string
SSHKeyName string
UserData string
diff --git a/pkg/cloud/services/compute/referenced_resources.go b/pkg/cloud/services/compute/referenced_resources.go
index 7b80947480..b9350f8d06 100644
--- a/pkg/cloud/services/compute/referenced_resources.go
+++ b/pkg/cloud/services/compute/referenced_resources.go
@@ -30,6 +30,7 @@ func ResolveReferencedMachineResources(scope scope.Scope, spec *infrav1.OpenStac
return err
}
+ // ServerGroup is optional, so we only need to resolve it if it's set in the spec and not in ReferencedMachineResources yet.
if spec.ServerGroup != nil && resources.ServerGroupID == "" {
serverGroupID, err := compute.GetServerGroupID(spec.ServerGroup)
if err != nil {
@@ -38,5 +39,14 @@ func ResolveReferencedMachineResources(scope scope.Scope, spec *infrav1.OpenStac
resources.ServerGroupID = serverGroupID
}
+ // Image is required, so we need to resolve it if it's not set in ReferencedMachineResources yet.
+ if resources.ImageID == "" {
+ imageID, err := compute.GetImageID(spec.Image)
+ if err != nil {
+ return err
+ }
+ resources.ImageID = imageID
+ }
+
return nil
}
diff --git a/pkg/cloud/services/compute/referenced_resources_test.go b/pkg/cloud/services/compute/referenced_resources_test.go
index 97e606ee71..6a976325c4 100644
--- a/pkg/cloud/services/compute/referenced_resources_test.go
+++ b/pkg/cloud/services/compute/referenced_resources_test.go
@@ -23,6 +23,7 @@ import (
"github.com/golang/mock/gomock"
"github.com/google/go-cmp/cmp"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/servergroups"
+ "github.com/gophercloud/gophercloud/openstack/imageservice/v2/images"
. "github.com/onsi/gomega"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
@@ -32,43 +33,67 @@ import (
func Test_ResolveReferencedMachineResources(t *testing.T) {
const serverGroupID1 = "ce96e584-7ebc-46d6-9e55-987d72e3806c"
+ const imageID1 = "de96e584-7ebc-46d6-9e55-987d72e3806c"
+
+ minimumReferences := &infrav1.ReferencedMachineResources{
+ ImageID: imageID1,
+ }
tests := []struct {
testName string
serverGroupFilter *infrav1.ServerGroupFilter
- expect func(m *mock.MockComputeClientMockRecorder)
+ imageFilter *infrav1.ImageFilter
+ expectComputeMock func(m *mock.MockComputeClientMockRecorder)
+ expectImageMock func(m *mock.MockImageClientMockRecorder)
want *infrav1.ReferencedMachineResources
wantErr bool
}{
{
- testName: "Server group ID passed",
+ testName: "Resources ID passed",
serverGroupFilter: &infrav1.ServerGroupFilter{ID: serverGroupID1},
- expect: func(m *mock.MockComputeClientMockRecorder) {},
- want: &infrav1.ReferencedMachineResources{ServerGroupID: serverGroupID1},
+ imageFilter: &infrav1.ImageFilter{ID: imageID1},
+ expectComputeMock: func(m *mock.MockComputeClientMockRecorder) {},
+ expectImageMock: func(m *mock.MockImageClientMockRecorder) {},
+ want: &infrav1.ReferencedMachineResources{ImageID: imageID1, ServerGroupID: serverGroupID1},
wantErr: false,
},
{
testName: "Server group filter nil",
serverGroupFilter: nil,
- expect: func(m *mock.MockComputeClientMockRecorder) {},
- want: &infrav1.ReferencedMachineResources{},
+ expectComputeMock: func(m *mock.MockComputeClientMockRecorder) {},
+ expectImageMock: func(m *mock.MockImageClientMockRecorder) {},
+ want: minimumReferences,
wantErr: false,
},
{
testName: "Server group ID empty",
serverGroupFilter: &infrav1.ServerGroupFilter{},
- expect: func(m *mock.MockComputeClientMockRecorder) {},
- want: &infrav1.ReferencedMachineResources{},
+ expectComputeMock: func(m *mock.MockComputeClientMockRecorder) {},
+ expectImageMock: func(m *mock.MockImageClientMockRecorder) {},
+ want: minimumReferences,
wantErr: false,
},
{
testName: "Server group by Name not found",
serverGroupFilter: &infrav1.ServerGroupFilter{Name: "test-server-group"},
- expect: func(m *mock.MockComputeClientMockRecorder) {
+ expectComputeMock: func(m *mock.MockComputeClientMockRecorder) {
m.ListServerGroups().Return(
[]servergroups.ServerGroup{},
nil)
},
+ expectImageMock: func(m *mock.MockImageClientMockRecorder) {},
+ want: &infrav1.ReferencedMachineResources{},
+ wantErr: true,
+ },
+ {
+ testName: "Image by Name not found",
+ imageFilter: &infrav1.ImageFilter{Name: "test-image"},
+ expectComputeMock: func(m *mock.MockComputeClientMockRecorder) {},
+ expectImageMock: func(m *mock.MockImageClientMockRecorder) {
+ m.ListImages(images.ListOpts{Name: "test-image"}).Return(
+ []images.Image{},
+ nil)
+ },
want: &infrav1.ReferencedMachineResources{},
wantErr: true,
},
@@ -79,10 +104,18 @@ func Test_ResolveReferencedMachineResources(t *testing.T) {
mockCtrl := gomock.NewController(t)
mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "", logr.Discard())
- tt.expect(mockScopeFactory.ComputeClient.EXPECT())
+ tt.expectComputeMock(mockScopeFactory.ComputeClient.EXPECT())
+ tt.expectImageMock(mockScopeFactory.ImageClient.EXPECT())
+
+ // Set defaults for required fields
+ imageFilter := &infrav1.ImageFilter{ID: imageID1}
+ if tt.imageFilter != nil {
+ imageFilter = tt.imageFilter
+ }
machineSpec := &infrav1.OpenStackMachineSpec{
ServerGroup: tt.serverGroupFilter,
+ Image: *imageFilter,
}
resources := &infrav1.ReferencedMachineResources{}
diff --git a/templates/cluster-template-flatcar-sysext.yaml b/templates/cluster-template-flatcar-sysext.yaml
index 1aefb0aaff..3994a67311 100644
--- a/templates/cluster-template-flatcar-sysext.yaml
+++ b/templates/cluster-template-flatcar-sysext.yaml
@@ -247,7 +247,8 @@ spec:
identityRef:
kind: Secret
name: ${CLUSTER_NAME}-cloud-config
- image: ${FLATCAR_IMAGE_NAME}
+ image:
+ name: ${FLATCAR_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
---
apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
@@ -262,5 +263,6 @@ spec:
identityRef:
kind: Secret
name: ${CLUSTER_NAME}-cloud-config
- image: ${FLATCAR_IMAGE_NAME}
+ image:
+ name: ${FLATCAR_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
diff --git a/templates/cluster-template-flatcar.yaml b/templates/cluster-template-flatcar.yaml
index 29b3443f0a..ff093ece03 100644
--- a/templates/cluster-template-flatcar.yaml
+++ b/templates/cluster-template-flatcar.yaml
@@ -171,7 +171,8 @@ spec:
identityRef:
kind: Secret
name: ${CLUSTER_NAME}-cloud-config
- image: ${OPENSTACK_FLATCAR_IMAGE_NAME}
+ image:
+ name: ${OPENSTACK_FLATCAR_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
---
apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
@@ -186,5 +187,6 @@ spec:
identityRef:
kind: Secret
name: ${CLUSTER_NAME}-cloud-config
- image: ${OPENSTACK_FLATCAR_IMAGE_NAME}
+ image:
+ name: ${OPENSTACK_FLATCAR_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
diff --git a/templates/cluster-template-without-lb.yaml b/templates/cluster-template-without-lb.yaml
index a9e6755bf1..665437a0a1 100644
--- a/templates/cluster-template-without-lb.yaml
+++ b/templates/cluster-template-without-lb.yaml
@@ -128,7 +128,8 @@ spec:
identityRef:
kind: Secret
name: ${CLUSTER_NAME}-cloud-config
- image: ${OPENSTACK_IMAGE_NAME}
+ image:
+ name: ${OPENSTACK_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
---
apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
@@ -143,5 +144,6 @@ spec:
identityRef:
kind: Secret
name: ${CLUSTER_NAME}-cloud-config
- image: ${OPENSTACK_IMAGE_NAME}
+ image:
+ name: ${OPENSTACK_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
diff --git a/templates/cluster-template.yaml b/templates/cluster-template.yaml
index 6760b7e917..af65b8865f 100644
--- a/templates/cluster-template.yaml
+++ b/templates/cluster-template.yaml
@@ -130,7 +130,8 @@ spec:
identityRef:
kind: Secret
name: ${CLUSTER_NAME}-cloud-config
- image: ${OPENSTACK_IMAGE_NAME}
+ image:
+ name: ${OPENSTACK_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
---
apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
@@ -145,5 +146,6 @@ spec:
identityRef:
kind: Secret
name: ${CLUSTER_NAME}-cloud-config
- image: ${OPENSTACK_IMAGE_NAME}
+ image:
+ name: ${OPENSTACK_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
diff --git a/test/e2e/data/kustomize/common-patches/cni/patch-cluster.yaml b/test/e2e/data/kustomize/common-patches/cni/patch-cluster.yaml
index 5399786f2f..26f94a6d4a 100644
--- a/test/e2e/data/kustomize/common-patches/cni/patch-cluster.yaml
+++ b/test/e2e/data/kustomize/common-patches/cni/patch-cluster.yaml
@@ -5,7 +5,8 @@
enabled: true
instance:
flavor: ${OPENSTACK_BASTION_MACHINE_FLAVOR}
- image: ${OPENSTACK_BASTION_IMAGE_NAME}
+ image:
+ name: ${OPENSTACK_BASTION_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
- op: add
path: /spec/controlPlaneAvailabilityZones
diff --git a/test/e2e/data/kustomize/k8s-upgrade/upgrade-from-template.yaml b/test/e2e/data/kustomize/k8s-upgrade/upgrade-from-template.yaml
index 4bba2d5165..339b52535a 100644
--- a/test/e2e/data/kustomize/k8s-upgrade/upgrade-from-template.yaml
+++ b/test/e2e/data/kustomize/k8s-upgrade/upgrade-from-template.yaml
@@ -11,7 +11,8 @@ spec:
identityRef:
kind: Secret
name: ${CLUSTER_NAME}-cloud-config
- image: ${OPENSTACK_IMAGE_NAME_UPGRADE_FROM}
+ image:
+ name: ${OPENSTACK_IMAGE_NAME_UPGRADE_FROM}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
tags:
- control-plane
@@ -28,7 +29,8 @@ spec:
identityRef:
kind: Secret
name: ${CLUSTER_NAME}-cloud-config
- image: ${OPENSTACK_IMAGE_NAME_UPGRADE_FROM}
+ image:
+ name: ${OPENSTACK_IMAGE_NAME_UPGRADE_FROM}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
tags:
- machine
diff --git a/test/e2e/data/kustomize/k8s-upgrade/upgrade-to-template.yaml b/test/e2e/data/kustomize/k8s-upgrade/upgrade-to-template.yaml
index 035aad375a..6e426d14a5 100644
--- a/test/e2e/data/kustomize/k8s-upgrade/upgrade-to-template.yaml
+++ b/test/e2e/data/kustomize/k8s-upgrade/upgrade-to-template.yaml
@@ -18,7 +18,8 @@ spec:
identityRef:
kind: Secret
name: ${CLUSTER_NAME}-cloud-config
- image: ${OPENSTACK_IMAGE_NAME}
+ image:
+ name: ${OPENSTACK_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
tags:
- control-plane
@@ -37,7 +38,8 @@ spec:
identityRef:
kind: Secret
name: ${CLUSTER_NAME}-cloud-config
- image: ${OPENSTACK_IMAGE_NAME}
+ image:
+ name: ${OPENSTACK_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
tags:
- machine
diff --git a/test/e2e/data/kustomize/v1alpha5/bastion.yaml b/test/e2e/data/kustomize/v1alpha5/bastion.yaml
new file mode 100644
index 0000000000..45c9e0f508
--- /dev/null
+++ b/test/e2e/data/kustomize/v1alpha5/bastion.yaml
@@ -0,0 +1,9 @@
+---
+- op: add
+ path: /spec/bastion
+ value:
+ enabled: true
+ instance:
+ flavor: ${OPENSTACK_BASTION_MACHINE_FLAVOR}
+ image: ${OPENSTACK_BASTION_IMAGE_NAME}
+ sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
diff --git a/test/e2e/data/kustomize/v1alpha5/kustomization.yaml b/test/e2e/data/kustomize/v1alpha5/kustomization.yaml
index d11eead116..ae29db64d9 100644
--- a/test/e2e/data/kustomize/v1alpha5/kustomization.yaml
+++ b/test/e2e/data/kustomize/v1alpha5/kustomization.yaml
@@ -6,3 +6,9 @@ resources:
components:
- ../common-patches/cni
- ../common-patches/ccm
+
+patches:
+- path: bastion.yaml
+ target:
+ kind: OpenStackCluster
+ name: \${CLUSTER_NAME}
diff --git a/test/e2e/data/kustomize/v1alpha6/bastion.yaml b/test/e2e/data/kustomize/v1alpha6/bastion.yaml
new file mode 100644
index 0000000000..45c9e0f508
--- /dev/null
+++ b/test/e2e/data/kustomize/v1alpha6/bastion.yaml
@@ -0,0 +1,9 @@
+---
+- op: add
+ path: /spec/bastion
+ value:
+ enabled: true
+ instance:
+ flavor: ${OPENSTACK_BASTION_MACHINE_FLAVOR}
+ image: ${OPENSTACK_BASTION_IMAGE_NAME}
+ sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
diff --git a/test/e2e/data/kustomize/v1alpha6/kustomization.yaml b/test/e2e/data/kustomize/v1alpha6/kustomization.yaml
index f455c1d60c..aa3e9c0e5c 100644
--- a/test/e2e/data/kustomize/v1alpha6/kustomization.yaml
+++ b/test/e2e/data/kustomize/v1alpha6/kustomization.yaml
@@ -20,3 +20,7 @@ patches:
- {}
target:
kind: OpenStackMachineTemplate
+- path: bastion.yaml
+ target:
+ kind: OpenStackCluster
+ name: \${CLUSTER_NAME}
diff --git a/test/e2e/data/kustomize/v1alpha7/bastion.yaml b/test/e2e/data/kustomize/v1alpha7/bastion.yaml
new file mode 100644
index 0000000000..45c9e0f508
--- /dev/null
+++ b/test/e2e/data/kustomize/v1alpha7/bastion.yaml
@@ -0,0 +1,9 @@
+---
+- op: add
+ path: /spec/bastion
+ value:
+ enabled: true
+ instance:
+ flavor: ${OPENSTACK_BASTION_MACHINE_FLAVOR}
+ image: ${OPENSTACK_BASTION_IMAGE_NAME}
+ sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
diff --git a/test/e2e/data/kustomize/v1alpha7/kustomization.yaml b/test/e2e/data/kustomize/v1alpha7/kustomization.yaml
index 3ad33a43b0..fe53c35f3f 100644
--- a/test/e2e/data/kustomize/v1alpha7/kustomization.yaml
+++ b/test/e2e/data/kustomize/v1alpha7/kustomization.yaml
@@ -20,3 +20,7 @@ patches:
- {}
target:
kind: OpenStackMachineTemplate
+- path: bastion.yaml
+ target:
+ kind: OpenStackCluster
+ name: \${CLUSTER_NAME}
diff --git a/test/e2e/suites/e2e/e2e_test.go b/test/e2e/suites/e2e/e2e_test.go
index fbaabdce33..e18c19a149 100644
--- a/test/e2e/suites/e2e/e2e_test.go
+++ b/test/e2e/suites/e2e/e2e_test.go
@@ -769,8 +769,10 @@ func makeOpenStackMachineTemplate(namespace, clusterName, name string) *infrav1.
Spec: infrav1.OpenStackMachineTemplateSpec{
Template: infrav1.OpenStackMachineTemplateResource{
Spec: infrav1.OpenStackMachineSpec{
- Flavor: e2eCtx.E2EConfig.GetVariable(shared.OpenStackNodeMachineFlavor),
- Image: e2eCtx.E2EConfig.GetVariable(shared.OpenStackImageName),
+ Flavor: e2eCtx.E2EConfig.GetVariable(shared.OpenStackNodeMachineFlavor),
+ Image: infrav1.ImageFilter{
+ Name: e2eCtx.E2EConfig.GetVariable(shared.OpenStackImageName),
+ },
SSHKeyName: shared.DefaultSSHKeyPairName,
CloudName: e2eCtx.E2EConfig.GetVariable(shared.OpenStackCloud),
IdentityRef: &infrav1.OpenStackIdentityReference{
@@ -792,8 +794,10 @@ func makeOpenStackMachineTemplateWithPortOptions(namespace, clusterName, name st
Spec: infrav1.OpenStackMachineTemplateSpec{
Template: infrav1.OpenStackMachineTemplateResource{
Spec: infrav1.OpenStackMachineSpec{
- Flavor: e2eCtx.E2EConfig.GetVariable(shared.OpenStackNodeMachineFlavor),
- Image: e2eCtx.E2EConfig.GetVariable(shared.OpenStackImageName),
+ Flavor: e2eCtx.E2EConfig.GetVariable(shared.OpenStackNodeMachineFlavor),
+ Image: infrav1.ImageFilter{
+ Name: e2eCtx.E2EConfig.GetVariable(shared.OpenStackImageName),
+ },
SSHKeyName: shared.DefaultSSHKeyPairName,
CloudName: e2eCtx.E2EConfig.GetVariable(shared.OpenStackCloud),
IdentityRef: &infrav1.OpenStackIdentityReference{
From cbd9b44b9205d02272e52c355bdc4669e98efe0a Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Fri, 12 Jan 2024 16:18:57 +0000
Subject: [PATCH 030/180] Bump controller-tools to v0.14.0
Fixes a panic generating deepcopy for v1alpha1
---
...re.cluster.x-k8s.io_openstackclusters.yaml | 1871 +++++++++--------
...er.x-k8s.io_openstackclustertemplates.yaml | 1267 ++++++-----
...re.cluster.x-k8s.io_openstackmachines.yaml | 805 +++----
...er.x-k8s.io_openstackmachinetemplates.yaml | 564 ++---
go.mod | 2 +-
go.sum | 32 +
hack/tools/go.mod | 49 +-
hack/tools/go.sum | 116 +-
8 files changed, 2455 insertions(+), 2251 deletions(-)
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 0a8cf90fd1..347e64c6ef 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
@@ -1099,10 +1115,10 @@ spec:
- 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 +1126,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
@@ -1156,8 +1173,9 @@ spec:
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 +1215,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 +1227,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 +1273,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 +1297,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 +1355,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 +1421,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 +1439,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 +1528,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 +1540,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 +1586,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 +1610,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 +1668,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 +1735,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 +1745,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
@@ -1802,14 +1831,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
@@ -1817,31 +1851,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 +1901,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 +1933,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 +2035,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 +2070,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 +2083,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 +2129,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 +2153,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 +2212,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 +2226,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 +2238,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 +2336,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 +2377,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 +2459,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 +2474,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 +2519,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 +2595,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 +2641,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 +2654,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 +2700,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 +2724,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 +2783,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 +2797,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 +2809,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 +2912,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 +2922,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
@@ -2923,10 +2965,10 @@ spec:
- 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 +2976,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
@@ -2980,8 +3023,9 @@ spec:
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 +3069,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 +3081,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 +3127,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 +3151,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 +3210,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 +3224,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 +3236,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 +3306,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 +3324,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 +3417,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 +3429,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 +3475,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 +3499,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 +3558,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 +3572,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 +3584,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 +3655,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 +3665,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
@@ -3692,14 +3747,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 +3767,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 +3817,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 +3845,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 +3858,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,49 +3910,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. If not specified, the
- identity ref of the cluster will be used instead.
+ 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:
@@ -3902,10 +3969,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.
@@ -3916,10 +3982,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
@@ -3963,9 +4028,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
@@ -3985,12 +4050,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
@@ -4029,10 +4093,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
@@ -4042,10 +4105,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.
@@ -4054,9 +4117,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
@@ -4127,7 +4190,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
@@ -4166,46 +4231,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:
@@ -4251,26 +4318,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
@@ -4294,22 +4363,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
@@ -4413,8 +4482,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
@@ -4422,8 +4492,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
@@ -4464,10 +4535,10 @@ spec:
- 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
@@ -4475,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
@@ -4534,9 +4606,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:
@@ -4552,36 +4624,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
@@ -4645,9 +4727,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
@@ -4655,8 +4737,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
@@ -4736,14 +4819,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
@@ -4751,31 +4839,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
@@ -4798,14 +4889,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
@@ -4822,12 +4917,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:
@@ -4835,32 +4930,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:
@@ -4887,34 +4982,34 @@ 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 image to use for your server instance. If
- the rootVolume is specified, this will be used when creating
- the root volume.
+ description: |-
+ The image to use for your server instance.
+ If the rootVolume is specified, this will be used when creating the root volume.
properties:
id:
description: The ID of the desired image. If this is provided,
@@ -4938,10 +5033,9 @@ spec:
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:
@@ -4958,10 +5052,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.
@@ -4972,10 +5065,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
@@ -5019,9 +5111,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
@@ -5041,12 +5133,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
@@ -5085,10 +5176,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
@@ -5098,10 +5188,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.
@@ -5110,9 +5200,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
@@ -5188,7 +5278,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
@@ -5227,40 +5319,41 @@ 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
disableExternalNetwork:
- description: DisableExternalNetwork determines 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.
+ description: |-
+ DisableExternalNetwork determines 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
+ 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
@@ -5287,9 +5380,9 @@ spec:
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.
+ 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:
@@ -5335,26 +5428,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
@@ -5378,22 +5473,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
@@ -5510,8 +5605,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
@@ -5519,8 +5615,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
@@ -5561,10 +5658,10 @@ spec:
- 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
@@ -5572,8 +5669,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
@@ -5631,9 +5729,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:
@@ -5649,36 +5747,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
@@ -5742,9 +5850,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
@@ -5752,8 +5860,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
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 08e725eae4..6d6a75f1e6 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
@@ -750,14 +750,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
@@ -774,35 +779,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 +829,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 +861,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 +964,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 +999,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 +1012,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 +1059,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 +1083,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 +1143,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 +1158,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 +1171,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 +1271,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 +1313,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 +1395,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 +1410,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 +1455,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 +1514,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 +1543,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 +1593,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 +1622,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 +1635,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,51 +1687,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. If not
- specified, the identity ref of the cluster will
- be used instead.
+ 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:
@@ -1750,10 +1746,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
@@ -1764,11 +1759,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
@@ -1813,10 +1806,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
@@ -1836,12 +1828,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
@@ -1882,10 +1873,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
@@ -1896,11 +1886,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.
@@ -1910,10 +1899,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
@@ -1985,7 +1973,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
@@ -2025,50 +2015,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:
@@ -2114,29 +2102,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
@@ -2160,24 +2147,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
@@ -2250,14 +2235,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
@@ -2274,35 +2264,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
@@ -2325,14 +2314,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
@@ -2350,13 +2343,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:
@@ -2364,35 +2356,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
@@ -2420,34 +2408,34 @@ 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 image to use for your server instance.
- If the rootVolume is specified, this will be used
- when creating the root volume.
+ description: |-
+ The image to use for your server instance.
+ If the rootVolume is specified, this will be used when creating the root volume.
properties:
id:
description: The ID of the desired image. If this
@@ -2473,10 +2461,9 @@ spec:
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:
@@ -2493,10 +2480,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
@@ -2507,11 +2493,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
@@ -2556,10 +2540,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
@@ -2579,12 +2562,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
@@ -2625,10 +2607,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
@@ -2639,11 +2620,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.
@@ -2653,10 +2633,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
@@ -2733,7 +2712,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
@@ -2773,44 +2754,41 @@ 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
disableExternalNetwork:
- description: DisableExternalNetwork determines 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.
+ description: |-
+ DisableExternalNetwork determines 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
+ 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
@@ -2837,9 +2815,9 @@ spec:
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.
+ 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:
@@ -2885,29 +2863,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
@@ -2931,24 +2908,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
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 a0bde06ad8..32e9b314bf 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
@@ -583,14 +600,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
@@ -607,45 +629,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 +730,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 +765,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 +777,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 +822,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 +846,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 +905,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 +919,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 +931,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 +1026,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 +1069,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 +1108,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 +1176,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 +1203,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 +1230,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,46 +1266,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. If not specified, the identity ref of
- the cluster will be used instead.
+ 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:
@@ -1283,9 +1324,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
@@ -1295,10 +1336,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
@@ -1341,9 +1381,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
@@ -1363,11 +1403,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
@@ -1406,10 +1446,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
@@ -1419,10 +1458,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.
@@ -1431,9 +1470,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.
@@ -1502,7 +1541,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
@@ -1543,37 +1584,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
@@ -1582,19 +1623,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
@@ -1644,14 +1691,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
@@ -1666,23 +1718,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:
@@ -1690,18 +1745,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:
@@ -1726,31 +1781,34 @@ 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 image to use for your server instance. If the rootVolume
- is specified, this will be used when creating the root volume.
+ description: |-
+ The image to use for your server instance.
+ If the rootVolume is specified, this will be used when creating the root volume.
properties:
id:
description: The ID of the desired image. If this is provided,
@@ -1773,10 +1831,9 @@ spec:
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:
@@ -1793,9 +1850,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
@@ -1805,10 +1862,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
@@ -1851,9 +1907,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
@@ -1873,11 +1929,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
@@ -1916,10 +1972,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
@@ -1929,10 +1984,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.
@@ -1941,9 +1996,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.
@@ -2017,7 +2072,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
@@ -2058,37 +2115,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
@@ -2097,19 +2154,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
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 16da499668..48ca01f8e1 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
@@ -465,14 +471,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
@@ -500,48 +511,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 +613,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 +648,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 +661,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 +707,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 +731,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 +790,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 +804,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 +816,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 +914,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 +944,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 +980,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 +993,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,49 +1045,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. If not specified, the
- identity ref of the cluster will be used instead.
+ 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:
@@ -1090,10 +1104,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.
@@ -1104,10 +1117,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
@@ -1151,9 +1163,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
@@ -1173,12 +1185,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
@@ -1217,10 +1228,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
@@ -1230,10 +1240,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.
@@ -1242,9 +1252,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
@@ -1315,7 +1325,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
@@ -1343,14 +1355,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
@@ -1374,12 +1391,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:
@@ -1387,32 +1404,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:
@@ -1439,34 +1456,34 @@ 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 image to use for your server instance. If
- the rootVolume is specified, this will be used when creating
- the root volume.
+ description: |-
+ The image to use for your server instance.
+ If the rootVolume is specified, this will be used when creating the root volume.
properties:
id:
description: The ID of the desired image. If this is provided,
@@ -1490,10 +1507,9 @@ spec:
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:
@@ -1510,10 +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.
@@ -1524,10 +1539,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
@@ -1571,9 +1585,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
@@ -1593,12 +1607,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
@@ -1637,10 +1650,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
@@ -1650,10 +1662,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.
@@ -1662,9 +1674,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
@@ -1740,7 +1752,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
diff --git a/go.mod b/go.mod
index 997f835404..4c59f8ec77 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
module sigs.k8s.io/cluster-api-provider-openstack
-go 1.20
+go 1.21
require (
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc
diff --git a/go.sum b/go.sum
index e3d46fdc89..c5f22dace3 100644
--- a/go.sum
+++ b/go.sum
@@ -25,7 +25,9 @@ cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUM
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY=
+cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM=
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
+cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
@@ -69,6 +71,7 @@ github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3d
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
+github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
@@ -90,8 +93,11 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k=
+github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/coredns/caddy v1.1.1 h1:2eYKZT7i6yxIfGP3qLJoJ7HAsDJqYB+X68g4NYjSrE0=
+github.com/coredns/caddy v1.1.1/go.mod h1:A6ntJQlAWuQfFlsd9hvigKbo2WS0VUs2l1e2F+BawD4=
github.com/coredns/corefile-migration v1.0.21 h1:W/DCETrHDiFo0Wj03EyMkaQ9fwsmSgqTCQDHpceaSsE=
+github.com/coredns/corefile-migration v1.0.21/go.mod h1:XnhgULOEouimnzgn0t4WPuFDN2/PJQcTxdWKC5eXNGE=
github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
@@ -116,6 +122,7 @@ github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD
github.com/drone/envsubst/v2 v2.0.0-20210730161058-179042472c46 h1:7QPwrLT79GlD5sizHf27aoY2RTvw62mO6x7mxkScNk0=
github.com/drone/envsubst/v2 v2.0.0-20210730161058-179042472c46/go.mod h1:esf2rsHFNlZlxsqsZDojNBcnNs5REqIvRrWRHqX0vEU=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
+github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
@@ -125,6 +132,7 @@ github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5y
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA=
+github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE=
github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U=
github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4=
@@ -133,6 +141,7 @@ github.com/evanphx/json-patch/v5 v5.7.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
+github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
@@ -161,8 +170,10 @@ github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
+github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo=
+github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -197,6 +208,7 @@ github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
+github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
github.com/google/cel-go v0.16.1 h1:3hZfSNiAU3KOiNtxuFXVp5WFy4hf/Ly3Sa4/7F8SXNo=
github.com/google/cel-go v0.16.1/go.mod h1:HXZKzB0LXqer5lHHgfWAnlYwJaQBDKMjxjulNQzhwhY=
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
@@ -252,10 +264,13 @@ github.com/gophercloud/gophercloud v1.7.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgz
github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56 h1:sH7xkTfYzxIEgzq1tDHIMKRh1vThOEOGNsettdEeLbE=
github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56/go.mod h1:VSalo4adEk+3sNkmVJLnhHoOyOYYS8sTWLG4mv5BKto=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
+github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw=
+github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
+github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg=
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
@@ -279,6 +294,7 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ=
+github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
@@ -291,6 +307,7 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
@@ -315,12 +332,14 @@ github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/moby/term v0.0.0-20221205130635-1aeaba878587 h1:HfkjXDfhgVaN5rmueG8cL8KKeFNecRCXFhaJ2qZ5SKA=
+github.com/moby/term v0.0.0-20221205130635-1aeaba878587/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
+github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
@@ -343,6 +362,7 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
+github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q=
github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
@@ -354,6 +374,7 @@ github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwa
github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
+github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sagikazarmark/locafero v0.3.0 h1:zT7VEGWC2DTflmccN/5T1etyKvxSxpHsjb9cJvm4SvQ=
github.com/sagikazarmark/locafero v0.3.0/go.mod h1:w+v7UsPNFwzF1cHuOajOOzoq4U7v/ig1mpRjqV+Bu1U=
@@ -363,7 +384,9 @@ github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFR
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
+github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js=
+github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0=
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY=
@@ -397,9 +420,11 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 h1:6fotK7otjonDflCTK0BCfls4SPy3NcCVb5dqqmbRknE=
+github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75/go.mod h1:KO6IkyS8Y3j8OdNO85qEYBsRPuteD+YciPomcXdrMnk=
github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
+github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -407,16 +432,21 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ=
+go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
go.etcd.io/etcd/api/v3 v3.5.10 h1:szRajuUUbLyppkhs9K6BRtjY37l66XQQmw7oZRANE4k=
go.etcd.io/etcd/api/v3 v3.5.10/go.mod h1:TidfmT4Uycad3NM/o25fG3J07odo4GBB9hoxaodFCtI=
go.etcd.io/etcd/client/pkg/v3 v3.5.10 h1:kfYIdQftBnbAq8pUWFXfpuuxFSKzlmM5cSn76JByiT0=
go.etcd.io/etcd/client/pkg/v3 v3.5.10/go.mod h1:DYivfIviIuQ8+/lCq4vcxuseg2P2XbHygkKwFo9fc8U=
go.etcd.io/etcd/client/v2 v2.305.9 h1:YZ2OLi0OvR0H75AcgSUajjd5uqKDKocQUqROTG11jIo=
+go.etcd.io/etcd/client/v2 v2.305.9/go.mod h1:0NBdNx9wbxtEQLwAQtrDHwx58m02vXpDcgSYI2seohQ=
go.etcd.io/etcd/client/v3 v3.5.10 h1:W9TXNZ+oB3MCd/8UjxHTWK5J9Nquw9fQBLJd5ne5/Ao=
go.etcd.io/etcd/client/v3 v3.5.10/go.mod h1:RVeBnDz2PUEZqTpgqwAtUd8nAPf5kjyFyND7P1VkOKc=
go.etcd.io/etcd/pkg/v3 v3.5.9 h1:6R2jg/aWd/zB9+9JxmijDKStGJAPFsX3e6BeJkMi6eQ=
+go.etcd.io/etcd/pkg/v3 v3.5.9/go.mod h1:BZl0SAShQFk0IpLWR78T/+pyt8AruMHhTNNX73hkNVY=
go.etcd.io/etcd/raft/v3 v3.5.9 h1:ZZ1GIHoUlHsn0QVqiRysAm3/81Xx7+i2d7nSdWxlOiI=
+go.etcd.io/etcd/raft/v3 v3.5.9/go.mod h1:WnFkqzFdZua4LVlVXQEGhmooLeyS7mqzS4Pf4BCVqXg=
go.etcd.io/etcd/server/v3 v3.5.9 h1:vomEmmxeztLtS5OEH7d0hBAg4cjVIu9wXuNzUZx2ZA0=
+go.etcd.io/etcd/server/v3 v3.5.9/go.mod h1:GgI1fQClQCFIzuVjlvdbMxNbnISt90gdfYyqiAIt65g=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
@@ -444,6 +474,7 @@ go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v8
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
+go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
@@ -814,6 +845,7 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=
+gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/hack/tools/go.mod b/hack/tools/go.mod
index 217dcac765..95ddc1f19b 100644
--- a/hack/tools/go.mod
+++ b/hack/tools/go.mod
@@ -1,26 +1,26 @@
module sigs.k8s.io/cluster-api-provider-openstack/hack/tools
-go 1.19
+go 1.21
require (
github.com/a8m/envsubst v1.2.0
github.com/golang/mock v1.6.0
github.com/itchyny/gojq v0.12.2
- github.com/onsi/ginkgo/v2 v2.11.0
- k8s.io/code-generator v0.28.0
+ github.com/onsi/ginkgo/v2 v2.13.0
+ k8s.io/code-generator v0.29.0
sigs.k8s.io/cluster-api/hack/tools v0.0.0-20221129083400-679ae3e9e6b6
sigs.k8s.io/controller-runtime/tools/setup-envtest v0.0.0-20230926180527-c93e2abcb28e
- sigs.k8s.io/controller-tools v0.13.0
+ sigs.k8s.io/controller-tools v0.14.0
sigs.k8s.io/kustomize/kustomize/v5 v5.2.1
)
require (
github.com/blang/semver v3.5.1+incompatible // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
- github.com/emicklei/go-restful/v3 v3.9.0 // indirect
- github.com/fatih/color v1.15.0 // indirect
+ github.com/emicklei/go-restful/v3 v3.11.0 // indirect
+ github.com/fatih/color v1.16.0 // indirect
github.com/go-errors/errors v1.4.2 // indirect
- github.com/go-logr/logr v1.2.4 // indirect
+ github.com/go-logr/logr v1.3.0 // indirect
github.com/go-logr/zapr v1.2.0 // indirect
github.com/go-openapi/jsonpointer v0.19.6 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
@@ -30,7 +30,6 @@ require (
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
- github.com/google/go-cmp v0.5.9 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
@@ -42,43 +41,43 @@ require (
github.com/json-iterator/go v1.1.12 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
- github.com/mattn/go-isatty v0.0.17 // indirect
+ github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.9 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/spf13/afero v1.9.2 // indirect
- github.com/spf13/cobra v1.7.0 // indirect
+ github.com/spf13/cobra v1.8.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/xlab/treeprint v1.2.0 // indirect
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect
go.uber.org/atomic v1.10.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.19.1 // indirect
- golang.org/x/mod v0.12.0 // indirect
- golang.org/x/net v0.15.0 // indirect
- golang.org/x/sys v0.12.0 // indirect
- golang.org/x/text v0.13.0 // indirect
- golang.org/x/tools v0.13.0 // indirect
+ golang.org/x/mod v0.14.0 // indirect
+ golang.org/x/net v0.19.0 // indirect
+ golang.org/x/sys v0.15.0 // indirect
+ golang.org/x/text v0.14.0 // indirect
+ golang.org/x/tools v0.16.1 // indirect
golang.org/x/tools/go/vcs v0.1.0-deprecated // indirect
- google.golang.org/protobuf v1.30.0 // indirect
+ google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/evanphx/json-patch.v5 v5.6.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
- k8s.io/api v0.28.0 // indirect
- k8s.io/apiextensions-apiserver v0.28.0 // indirect
- k8s.io/apimachinery v0.28.0 // indirect
- k8s.io/gengo v0.0.0-20220902162205-c0856e24416d // indirect
- k8s.io/klog/v2 v2.100.1 // indirect
- k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect
- k8s.io/utils v0.0.0-20230505201702-9f6742963106 // indirect
+ k8s.io/api v0.29.0 // indirect
+ k8s.io/apiextensions-apiserver v0.29.0 // indirect
+ k8s.io/apimachinery v0.29.0 // indirect
+ k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01 // indirect
+ k8s.io/klog/v2 v2.110.1 // indirect
+ k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect
+ k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/kubebuilder/docs/book/utils v0.0.0-20211028165026-57688c578b5d // indirect
sigs.k8s.io/kustomize/api v0.15.0 // indirect
sigs.k8s.io/kustomize/cmd/config v0.12.0 // indirect
sigs.k8s.io/kustomize/kyaml v0.15.0 // indirect
- sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
- sigs.k8s.io/yaml v1.3.0 // indirect
+ sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
+ sigs.k8s.io/yaml v1.4.0 // indirect
)
diff --git a/hack/tools/go.sum b/hack/tools/go.sum
index db7226f80d..8d2cb148c6 100644
--- a/hack/tools/go.sum
+++ b/hack/tools/go.sum
@@ -52,22 +52,23 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
-github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
+github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE=
-github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
+github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
+github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
-github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
-github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
-github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
+github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
+github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
+github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
+github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
@@ -75,8 +76,8 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
-github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
-github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=
+github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/zapr v1.2.0 h1:n4JnPI1T3Qq1SFEi/F8rwLrZERp2bso19PJZDB9dayk=
github.com/go-logr/zapr v1.2.0/go.mod h1:Qa4Bsj2Vb+FAVeAKsLD8RLQ+YRJB8YDmOAKxaBQf7Ro=
github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
@@ -135,8 +136,9 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
@@ -190,6 +192,7 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
@@ -200,8 +203,8 @@ github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxec
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
-github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
-github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -212,10 +215,13 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0=
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
+github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
-github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU=
-github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM=
-github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
+github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
+github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4=
+github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o=
+github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8=
+github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -225,12 +231,14 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
+github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
+github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/spf13/afero v1.9.2 h1:j49Hj62F0n+DaZ1dDCvhABaPNSGNkt32oRFxI33IEMw=
github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
-github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
-github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
+github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
+github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@@ -245,7 +253,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
-github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
+github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
+github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ=
github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -314,8 +323,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
-golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
+golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -348,8 +357,8 @@ golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
-golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8=
-golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
+golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
+golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -370,7 +379,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
+golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
+golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -411,8 +421,9 @@ golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
-golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
+golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -420,8 +431,8 @@ golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
-golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
+golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -478,8 +489,8 @@ golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
-golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
+golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA=
+golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0=
golang.org/x/tools/go/vcs v0.1.0-deprecated h1:cOIJqWBl99H1dH5LWizPa+0ImeeJq3t3cJjaeOWUAL4=
golang.org/x/tools/go/vcs v0.1.0-deprecated/go.mod h1:zUrvATBAvEI9535oC0yWYsLsHIV4Z7g63sNPVMtuBy8=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -576,8 +587,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
-google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
+google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -589,6 +600,7 @@ gopkg.in/evanphx/json-patch.v5 v5.6.0/go.mod h1:/kvTRh1TVm5wuM6OkHxqXtE/1nUZZpih
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
@@ -605,23 +617,23 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
-k8s.io/api v0.28.0 h1:3j3VPWmN9tTDI68NETBWlDiA9qOiGJ7sdKeufehBYsM=
-k8s.io/api v0.28.0/go.mod h1:0l8NZJzB0i/etuWnIXcwfIv+xnDOhL3lLW919AWYDuY=
-k8s.io/apiextensions-apiserver v0.28.0 h1:CszgmBL8CizEnj4sj7/PtLGey6Na3YgWyGCPONv7E9E=
-k8s.io/apiextensions-apiserver v0.28.0/go.mod h1:uRdYiwIuu0SyqJKriKmqEN2jThIJPhVmOWETm8ud1VE=
-k8s.io/apimachinery v0.28.0 h1:ScHS2AG16UlYWk63r46oU3D5y54T53cVI5mMJwwqFNA=
-k8s.io/apimachinery v0.28.0/go.mod h1:X0xh/chESs2hP9koe+SdIAcXWcQ+RM5hy0ZynB+yEvw=
-k8s.io/code-generator v0.28.0 h1:msdkRVJNVFgdiIJ8REl/d3cZsMB9HByFcWMmn13NyuE=
-k8s.io/code-generator v0.28.0/go.mod h1:ueeSJZJ61NHBa0ccWLey6mwawum25vX61nRZ6WOzN9A=
-k8s.io/gengo v0.0.0-20220902162205-c0856e24416d h1:U9tB195lKdzwqicbJvyJeOXV7Klv+wNAWENRnXEGi08=
-k8s.io/gengo v0.0.0-20220902162205-c0856e24416d/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
+k8s.io/api v0.29.0 h1:NiCdQMY1QOp1H8lfRyeEf8eOwV6+0xA6XEE44ohDX2A=
+k8s.io/api v0.29.0/go.mod h1:sdVmXoz2Bo/cb77Pxi71IPTSErEW32xa4aXwKH7gfBA=
+k8s.io/apiextensions-apiserver v0.29.0 h1:0VuspFG7Hj+SxyF/Z/2T0uFbI5gb5LRgEyUVE3Q4lV0=
+k8s.io/apiextensions-apiserver v0.29.0/go.mod h1:TKmpy3bTS0mr9pylH0nOt/QzQRrW7/h7yLdRForMZwc=
+k8s.io/apimachinery v0.29.0 h1:+ACVktwyicPz0oc6MTMLwa2Pw3ouLAfAon1wPLtG48o=
+k8s.io/apimachinery v0.29.0/go.mod h1:eVBxQ/cwiJxH58eK/jd/vAk4mrxmVlnpBH5J2GbMeis=
+k8s.io/code-generator v0.29.0 h1:2LQfayGDhaIlaamXjIjEQlCMy4JNCH9lrzas4DNW1GQ=
+k8s.io/code-generator v0.29.0/go.mod h1:5bqIZoCxs2zTRKMWNYqyQWW/bajc+ah4rh0tMY8zdGA=
+k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01 h1:pWEwq4Asjm4vjW7vcsmijwBhOr1/shsbSYiWXmNGlks=
+k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
-k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg=
-k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
-k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 h1:LyMgNKD2P8Wn1iAwQU5OhxCKlKJy0sHc+PcDwFB24dQ=
-k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9/go.mod h1:wZK2AVp1uHCp4VamDVgBP2COHZjqD1T68Rf0CM3YjSM=
-k8s.io/utils v0.0.0-20230505201702-9f6742963106 h1:EObNQ3TW2D+WptiYXlApGNLVy0zm/JIBVY9i+M4wpAU=
-k8s.io/utils v0.0.0-20230505201702-9f6742963106/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
+k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0=
+k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo=
+k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780=
+k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA=
+k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI=
+k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
@@ -629,8 +641,8 @@ sigs.k8s.io/cluster-api/hack/tools v0.0.0-20221129083400-679ae3e9e6b6 h1:YF+g/Mr
sigs.k8s.io/cluster-api/hack/tools v0.0.0-20221129083400-679ae3e9e6b6/go.mod h1:7luenhlsUTb9obnAferuDFEvhtITw7JjHpXkiDmCmKY=
sigs.k8s.io/controller-runtime/tools/setup-envtest v0.0.0-20230926180527-c93e2abcb28e h1:xYNzzoK+cwgBnaRqrYFLQCSwMAYcR6a06gf3FJ369Kw=
sigs.k8s.io/controller-runtime/tools/setup-envtest v0.0.0-20230926180527-c93e2abcb28e/go.mod h1:B6HLcvOy2S1qq2eWOFm9xepiKPMIc8Z9OXSPsnUDaR4=
-sigs.k8s.io/controller-tools v0.13.0 h1:NfrvuZ4bxyolhDBt/rCZhDnx3M2hzlhgo5n3Iv2RykI=
-sigs.k8s.io/controller-tools v0.13.0/go.mod h1:5vw3En2NazbejQGCeWKRrE7q4P+CW8/klfVqP8QZkgA=
+sigs.k8s.io/controller-tools v0.14.0 h1:rnNoCC5wSXlrNoBKKzL70LNJKIQKEzT6lloG6/LF73A=
+sigs.k8s.io/controller-tools v0.14.0/go.mod h1:TV7uOtNNnnR72SpzhStvPkoS/U5ir0nMudrkrC4M9Sc=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
sigs.k8s.io/kubebuilder/docs/book/utils v0.0.0-20211028165026-57688c578b5d h1:KLiQzLW3RZJR19+j4pw2h5iioyAyqCkDBEAFdnGa3N8=
@@ -643,8 +655,8 @@ sigs.k8s.io/kustomize/kustomize/v5 v5.2.1 h1:bI0UnT+UJiEEl1BaomL71ESl3w5rJo2Aw6C
sigs.k8s.io/kustomize/kustomize/v5 v5.2.1/go.mod h1:qzRni4VPV6LxTEY5eC5qH3+995Atdi9E46jiwArROik=
sigs.k8s.io/kustomize/kyaml v0.15.0 h1:ynlLMAxDhrY9otSg5GYE2TcIz31XkGZ2Pkj7SdolD84=
sigs.k8s.io/kustomize/kyaml v0.15.0/go.mod h1:+uMkBahdU1KNOj78Uta4rrXH+iH7wvg+nW7+GULvREA=
-sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE=
-sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E=
+sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
+sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
-sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
-sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
+sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
+sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
From 48e0f91f48fecac645034e144e98f93ca44a2c0d Mon Sep 17 00:00:00 2001
From: Emilien Macchi
Date: Fri, 22 Dec 2023 10:54:30 -0500
Subject: [PATCH 031/180] Update CI to use OpenStack Bobcat & Ubuntu 22.04
---
README.md | 12 +++++------
docs/book/src/development/ci.md | 8 ++++---
hack/ci/aws-project.sh | 4 ++--
hack/ci/cloud-init/controller.yaml.tpl | 29 ++++++++++++++++++--------
hack/ci/cloud-init/worker.yaml.tpl | 22 ++++++++++++-------
hack/ci/create_devstack.sh | 12 +++++------
hack/ci/gce-project.sh | 2 +-
hack/ci/openstack.sh | 8 +++----
scripts/ci-conformance.sh | 2 +-
scripts/ci-e2e.sh | 2 +-
10 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/README.md b/README.md
index d2ccc9f6ad..134890bfa9 100644
--- a/README.md
+++ b/README.md
@@ -58,12 +58,12 @@ This provider's versions are able to install and manage the following versions o
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 (v0.9) | | + | + | + | + | ✓ | ✓ | ✓ | ★ |
-| OpenStack Provider v1alpha8 | | + | + | + | + | ✓ | ✓ | ✓ | ★ |
+| | 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 v1alpha8 | | + | + | + | + | ✓ | ✓ | ✓ | ✓ | ★ |
Test status:
diff --git a/docs/book/src/development/ci.md b/docs/book/src/development/ci.md
index d547e5a1f6..5b9ec0398e 100644
--- a/docs/book/src/development/ci.md
+++ b/docs/book/src/development/ci.md
@@ -28,7 +28,7 @@ The entry point for the creation of the test DevStack is `hack/ci/create_devstac
### DevStack OS
-In GCE, DevStack is installed on a community-maintained Ubuntu 20.04 LTS cloud image. The cloud-init config is also intended to work on CentOS 8, and this is known to work as of 2021-01-12. However, note that this is not regularly tested. See the comment in `hack/ci/gce-project.sh` for how to deploy on CentOS.
+In GCE, DevStack is installed on a community-maintained Ubuntu 22.04 LTS cloud image. The cloud-init config is also intended to work on CentOS 8, and this is known to work as of 2021-01-12. However, note that this is not regularly tested. See the comment in `hack/ci/gce-project.sh` for how to deploy on CentOS.
It is convenient to the project to have a viable second OS option as it gives us an option to work around issues which only affect one or the other. This is most likely when enabling new DevStack features, but may also include infrastructure issues. Consequently, when making changes to cloud-init, try not to use features specific to Ubuntu or CentOS. DevStack already supports both operating systems, so we just need to be careful in our peripheral configuration, for example by using cloud-init's `packages` module rather than manually invoking `apt-get` or `yum`. Fortunately package names tend to be consistent across the two distributions.
@@ -40,13 +40,13 @@ We configure a 2 node DevStack. `controller` is running:
* Nova: all services, including compute
* Glance: all services
* Octavia: all services
-* Neutron: all services with ML2/OVS, including L3 agent
+* Neutron: all services with ML2/OVN
* Cinder: all services, including volume with default LVM/iSCSI backend
`worker` is running:
* Nova: compute only
-* Neutron: agent only (not L3 agent)
+* Neutron: OVN agents only
* Cinder: volume only with default LVM/iSCSI backend
`controller` is using the `n2-standard-16` machine type with 16 vCPUs and 64 GB RAM. `worker` is using the `n2-standard-8` machine type with 8 vCPUs and 32 GB RAM. Each job has a quota limit of 24 vCPUs.
@@ -66,6 +66,8 @@ In addition, DevStack will create a floating IP network using CIDR defined in `F
The effect of this is that instances created on either `controller` or `worker` can get a floating ip from the `public` network. Traffic using this floating IP will be routed via `controller` and externally via NAT.
+We are configuring OVN to provide default DNS servers if a subnet is created without specifying DNS servers. This can be overridden in `OPENSTACK_DNS_NAMESERVERS`.
+
### Availability zones
We are running `nova compute` and `cinder volume` on each of `controller` and `worker`. Each `nova compute` and `cinder volume` are configured to be in their own availability zone. The names of the availability zones are defined in `OPENSTACK_FAILURE_DOMAIN` and `OPENSTACK_FAILURE_DOMAIN_ALT` in `test/e2e/data/e2e_conf.yaml`, with the services running on `controller` being in `OPENSTACK_FAILURE_DOMAIN` and the services running on `worker` being in `OPENSTACK_FAILURE_DOMAIN_ALT`.
diff --git a/hack/ci/aws-project.sh b/hack/ci/aws-project.sh
index d1661838a7..221065a99a 100755
--- a/hack/ci/aws-project.sh
+++ b/hack/ci/aws-project.sh
@@ -23,8 +23,8 @@ function cloud_init {
AWS_ZONE=${AWS_ZONE:-"eu-central-1a"}
# AMIs:
# * capa-ami-ubuntu-20.04-1.20.4-00-1613898574 id: ami-0120656d38c206057
- # * ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-20210223 id: ami-0767046d1677be5a0
- AWS_AMI=${AWS_AMI:-"ami-0767046d1677be5a0"}
+ # * ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-arm64-server-20231207 id: ami-05d47d29a4c2d19e1
+ AWS_AMI=${AWS_AMI:-"ami-05d47d29a4c2d19e1"}
# Choose via: https://eu-central-1.console.aws.amazon.com/ec2/v2/home?region=eu-central-1#InstanceTypes:
AWS_MACHINE_TYPE=${AWS_MACHINE_TYPE:-"c5.metal"}
AWS_NETWORK_NAME=${AWS_NETWORK_NAME:-"${CLUSTER_NAME}-mynetwork"}
diff --git a/hack/ci/cloud-init/controller.yaml.tpl b/hack/ci/cloud-init/controller.yaml.tpl
index aef474e22e..45bf607fff 100644
--- a/hack/ci/cloud-init/controller.yaml.tpl
+++ b/hack/ci/cloud-init/controller.yaml.tpl
@@ -12,9 +12,6 @@
VERBOSE=True
LOG_COLOR=True
- # Neutron
- enable_plugin neutron https://github.com/openstack/neutron stable/${OPENSTACK_RELEASE}
-
# Octavia
enable_plugin octavia https://github.com/openstack/octavia stable/${OPENSTACK_RELEASE}
enable_plugin octavia-dashboard https://github.com/openstack/octavia-dashboard stable/${OPENSTACK_RELEASE}
@@ -35,9 +32,17 @@
ENABLED_SERVICES+=,g-api
# Neutron
- ENABLED_SERVICES+=,neutron-api,neutron-agent,neutron-dhcp,neutron-l3,neutron-trunk
+ enable_plugin neutron https://github.com/openstack/neutron stable/${OPENSTACK_RELEASE}
+ ENABLED_SERVICES+=,q-svc,neutron-trunk,ovn-controller,ovs-vswitchd,ovn-northd,ovsdb-server,q-ovn-metadata-agent
+
+ DISABLED_SERVICES=q-agt,q-dhcp,q-l3,q-meta,q-metering
+ PUBLIC_BRIDGE_MTU=${MTU}
+ ENABLE_CHASSIS_AS_GW="True"
+ OVN_DBS_LOG_LEVEL="dbg"
+ Q_ML2_PLUGIN_MECHANISM_DRIVERS="ovn,logger"
+ OVN_L3_CREATE_PUBLIC_NETWORK="True"
+ Q_AGENT="ovn"
- ENABLED_SERVICES+=,neutron-metadata-agent,neutron-qos
# Octavia
ENABLED_SERVICES+=,octavia,o-api,o-cw,o-hm,o-hk,o-da
@@ -50,6 +55,7 @@
# Additional services
ENABLED_SERVICES+=${OPENSTACK_ADDITIONAL_SERVICES}
+ DISABLED_SERVICES+=${OPENSTACK_DISABLED_SERVICES}
# Don't download default images, just our test images
DOWNLOAD_DEFAULT_IMAGES=False
@@ -87,13 +93,18 @@
[DEFAULT]
storage_availability_zone = ${PRIMARY_AZ}
- [[post-config|/$NEUTRON_CORE_PLUGIN_CONF]]
- [ml2]
- path_mtu = ${MTU}
-
[[post-config|$NEUTRON_CONF]]
[DEFAULT]
+ global_physnet_mtu = ${MTU}
service_plugins = trunk,router
+
+ # The following are required for OVN to set default DNS when a subnet is
+ # created without specifying DNS servers.
+ # Not specifying these will result in the default DNS servers being set to
+ # 127.0.0.53 which might be problematic in some environments.
+ [[post-config|/$Q_PLUGIN_CONF_FILE]]
+ [ovn]
+ dns_servers = ${OPENSTACK_DNS_NAMESERVERS}
- path: /tmp/register-worker.sh
permissions: "0755"
content: |
diff --git a/hack/ci/cloud-init/worker.yaml.tpl b/hack/ci/cloud-init/worker.yaml.tpl
index 73e642f55f..ccbf79411d 100644
--- a/hack/ci/cloud-init/worker.yaml.tpl
+++ b/hack/ci/cloud-init/worker.yaml.tpl
@@ -25,15 +25,23 @@
DATABASE_TYPE=mysql
DATABASE_HOST=$SERVICE_HOST
- # Neutron
- enable_plugin neutron https://github.com/openstack/neutron stable/${OPENSTACK_RELEASE}
-
# Nova
- ENABLED_SERVICES=n-cpu,placement-client,c-vol,neutron-agent
+ ENABLED_SERVICES=n-cpu,placement-client,c-vol
VOLUME_BACKING_FILE_SIZE=100G
+ # Neutron
+ enable_plugin neutron https://github.com/openstack/neutron stable/${OPENSTACK_RELEASE}
+ ENABLED_SERVICES+=,ovn-controller,ovs-vswitchd,ovsdb-server,q-fake,q-ovn-metadata-agent
+ DISABLED_SERVICES=q-svc,horizon,ovn-northd,q-agt,q-dhcp,q-l3,q-meta,q-metering,q-vpn
+ PUBLIC_BRIDGE_MTU=${MTU}
+ ENABLE_CHASSIS_AS_GW="False"
+ OVN_DBS_LOG_LEVEL="dbg"
+ Q_ML2_PLUGIN_MECHANISM_DRIVERS="ovn,logger"
+ Q_AGENT="ovn"
+
# Additional services
ENABLED_SERVICES+=${OPENSTACK_ADDITIONAL_SERVICES}
+ DISABLED_SERVICES+=${OPENSTACK_DISABLED_SERVICES}
[[post-config|$NOVA_CONF]]
[DEFAULT]
@@ -43,9 +51,9 @@
[DEFAULT]
storage_availability_zone = ${SECONDARY_AZ}
- [[post-config|/$NEUTRON_CORE_PLUGIN_CONF]]
- [ml2]
- path_mtu = ${MTU}
+ [[post-config|$NEUTRON_CONF]]
+ [DEFAULT]
+ global_physnet_mtu = ${MTU}
- path: /root/devstack.sh
permissions: "0755"
content: |
diff --git a/hack/ci/create_devstack.sh b/hack/ci/create_devstack.sh
index 6431b26b08..77ac0f05bf 100755
--- a/hack/ci/create_devstack.sh
+++ b/hack/ci/create_devstack.sh
@@ -31,13 +31,16 @@ source "${scriptdir}/${RESOURCE_TYPE}.sh"
CLUSTER_NAME=${CLUSTER_NAME:-"capo-e2e"}
-OPENSTACK_RELEASE=${OPENSTACK_RELEASE:-"yoga"}
+OPENSTACK_RELEASE=${OPENSTACK_RELEASE:-"2023.2"}
OPENSTACK_ENABLE_HORIZON=${OPENSTACK_ENABLE_HORIZON:-"false"}
# Devstack will create a provider network using this range
# We create a route to it with sshuttle
FLOATING_RANGE=${FLOATING_RANGE:-"172.24.4.0/24"}
+# That will be the default DNS server for the Neutron subnets
+OPENSTACK_DNS_NAMESERVERS=${OPENSTACK_DNS_NAMESERVERS:-"8.8.8.8"}
+
# Servers will be directly attached to the private network
# We create a route to it with sshuttle
PRIVATE_NETWORK_CIDR=${PRIVATE_NETWORK_CIDR:-"10.0.3.0/24"}
@@ -86,10 +89,6 @@ function ensure_openstack_client {
# We explicitly pin to the stable branch version of openstackclient.
curl -L https://releases.openstack.org/constraints/upper/${OPENSTACK_RELEASE} -o /tmp/openstack-constraints
- # Hack for yoga only: wrapt <1.14 doesn't support python 3.11
- [ "${OPENSTACK_RELEASE}" == "yoga" ] || exit 1 # Delete this hack
- sed -i "s/^wrapt===1\.13.*/wrapt===1.14.1/" /tmp/openstack-constraints
-
pip install -c /tmp/openstack-constraints \
python-openstackclient python-cinderclient \
python-glanceclient python-keystoneclient \
@@ -213,10 +212,11 @@ function create_devstack {
HOST_IP="$ip" \
CONTROLLER_IP="$CONTROLLER_IP" \
FLOATING_RANGE="$FLOATING_RANGE" \
+ OPENSTACK_DNS_NAMESERVERS="$OPENSTACK_DNS_NAMESERVERS" \
MTU="$(get_mtu)" \
PRIMARY_AZ="$PRIMARY_AZ" SECONDARY_AZ="$SECONDARY_AZ" \
envsubst '${SSH_PUBLIC_KEY} ${OPENSTACK_ADDITIONAL_SERVICES}
- ${OPENSTACK_RELEASE} ${HOST_IP} ${FLOATING_RANGE}
+ ${OPENSTACK_RELEASE} ${HOST_IP} ${FLOATING_RANGE} ${OPENSTACK_DNS_NAMESERVERS}
${CONTROLLER_IP} ${MTU} ${PRIMARY_AZ} ${SECONDARY_AZ}' \
< "./hack/ci/cloud-init/${tpl}.yaml.tpl" >> "$cloud_init"
done
diff --git a/hack/ci/gce-project.sh b/hack/ci/gce-project.sh
index c596ac42bc..1aae2de9b9 100755
--- a/hack/ci/gce-project.sh
+++ b/hack/ci/gce-project.sh
@@ -95,7 +95,7 @@ function create_vm {
--zone "$GCP_ZONE" \
--enable-nested-virtualization \
--image-project ubuntu-os-cloud \
- --image-family ubuntu-2004-lts \
+ --image-family ubuntu-2204-lts \
--boot-disk-size 200G \
--boot-disk-type pd-ssd \
--can-ip-forward \
diff --git a/hack/ci/openstack.sh b/hack/ci/openstack.sh
index 6326b26db3..49e4f61bcc 100755
--- a/hack/ci/openstack.sh
+++ b/hack/ci/openstack.sh
@@ -30,7 +30,7 @@ function cloud_init {
OPENSTACK_SUBNET_NAME=${OPENSTACK_SUBNET_NAME:-${CLUSTER_NAME}-subnet}
OPENSTACK_SECGROUP_NAME=${OPENSTACK_SECGROUP_NAME:-${CLUSTER_NAME}-secgroup}
OPENSTACK_ROUTER_NAME=${OPENSTACK_ROUTER_NAME:-${CLUSTER_NAME}-router}
- OPENSTACK_IMAGE_NAME=${OPENSTACK_IMAGE_NAME:-ubuntu-2004-lts}
+ OPENSTACK_IMAGE_NAME=${OPENSTACK_IMAGE_NAME:-ubuntu-2204-lts}
OPENSTACK_FLAVOR=${OPENSTACK_FLAVOR:-m1.xlarge}
OPENSTACK_FLAVOR_controller=${OPENSTACK_FLAVOR_controller:-$OPENSTACK_FLAVOR}
@@ -88,9 +88,9 @@ function init_infrastructure() {
# We don't tag the image with the cluster name as we expect it to be shared
if ! imageid=$(openstack image show "$OPENSTACK_IMAGE_NAME" -f value -c id 2>/dev/null)
then
- curl -o /tmp/ubuntu-2004.qcow2 https://cloud-images.ubuntu.com/releases/focal/release/ubuntu-20.04-server-cloudimg-amd64.img
- imageid=$(openstack image create --disk-format qcow2 --file /tmp/ubuntu-2004.qcow2 "$OPENSTACK_IMAGE_NAME" -f value -c id)
- rm /tmp/ubuntu-2004.qcow2
+ curl -o /tmp/ubuntu-2204.qcow2 https://cloud-images.ubuntu.com/releases/jammy/release/ubuntu-22.04-server-cloudimg-amd64.img
+ imageid=$(openstack image create --disk-format qcow2 --file /tmp/ubuntu-2204.qcow2 "$OPENSTACK_IMAGE_NAME" -f value -c id)
+ rm /tmp/ubuntu-2204.qcow2
fi
}
diff --git a/scripts/ci-conformance.sh b/scripts/ci-conformance.sh
index a32223dabc..0c926901a7 100755
--- a/scripts/ci-conformance.sh
+++ b/scripts/ci-conformance.sh
@@ -47,7 +47,7 @@ trap cleanup EXIT
apt-get update -y
# Install requests module explicitly for HTTP calls.
-# libffi required for pip install cffi (yoga dependency)
+# libffi required for pip install cffi (bobcat dependency)
apt-get install -y python3-requests libffi-dev
rm -rf /var/lib/apt/lists/*
diff --git a/scripts/ci-e2e.sh b/scripts/ci-e2e.sh
index e056827c0d..ca4180c1cb 100755
--- a/scripts/ci-e2e.sh
+++ b/scripts/ci-e2e.sh
@@ -48,7 +48,7 @@ trap cleanup EXIT
apt-get update -y
# Install requests module explicitly for HTTP calls.
-# libffi required for pip install cffi (yoga dependency)
+# libffi required for pip install cffi (bobcat dependency)
apt-get install -y python3-requests libffi-dev
rm -rf /var/lib/apt/lists/*
From 0796264e1a9a9c51332b0ae8a892e28320074e9f Mon Sep 17 00:00:00 2001
From: Emilien Macchi
Date: Wed, 1 Nov 2023 14:08:52 -0400
Subject: [PATCH 032/180] Move FloatingIP to Bastion spec
Re-adding commit which was previously erroneously added to v1alpha7 and
reverted.
(cherry picked from commit f19a6cc61bc5698f8292e851dba2d0b491d14ed0)
Updated to target v1alpha8 instead of v1alpha7.
Conversion code is reworked from previous commit to be minimal.
Co-Authored-By: Matthew Booth
---
api/v1alpha5/conversion.go | 18 ++++++++++
api/v1alpha5/zz_generated.conversion.go | 34 +++++++-----------
api/v1alpha6/conversion.go | 6 ++++
api/v1alpha6/zz_generated.conversion.go | 4 +--
api/v1alpha7/conversion.go | 28 +++++++++++++--
api/v1alpha7/zz_generated.conversion.go | 4 +--
api/v1alpha8/openstackmachine_types.go | 4 ---
api/v1alpha8/types.go | 5 +++
...re.cluster.x-k8s.io_openstackclusters.yaml | 10 +++---
...er.x-k8s.io_openstackclustertemplates.yaml | 10 +++---
...re.cluster.x-k8s.io_openstackmachines.yaml | 5 ---
...er.x-k8s.io_openstackmachinetemplates.yaml | 5 ---
controllers/openstackcluster_controller.go | 2 +-
.../src/clusteropenstack/configuration.md | 2 +-
.../crd-changes/v1alpha7-to-v1alpha8.md | 35 ++++++++++++++++++-
15 files changed, 117 insertions(+), 55 deletions(-)
diff --git a/api/v1alpha5/conversion.go b/api/v1alpha5/conversion.go
index 3029ab1038..b4855587e0 100644
--- a/api/v1alpha5/conversion.go
+++ b/api/v1alpha5/conversion.go
@@ -504,3 +504,21 @@ func Convert_v1alpha8_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineStatus(
// ReferencedResources have no equivalent in v1alpha5
return autoConvert_v1alpha8_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineStatus(in, out, s)
}
+
+func Convert_v1alpha8_Bastion_To_v1alpha5_Bastion(in *infrav1.Bastion, out *Bastion, s conversion.Scope) error {
+ err := autoConvert_v1alpha8_Bastion_To_v1alpha5_Bastion(in, out, s)
+ if err != nil {
+ return err
+ }
+ in.FloatingIP = out.Instance.FloatingIP
+ return nil
+}
+
+func Convert_v1alpha5_Bastion_To_v1alpha8_Bastion(in *Bastion, out *infrav1.Bastion, s conversion.Scope) error {
+ err := autoConvert_v1alpha5_Bastion_To_v1alpha8_Bastion(in, out, s)
+ if err != nil {
+ return err
+ }
+ in.Instance.FloatingIP = out.FloatingIP
+ return nil
+}
diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go
index 23e8f4595c..af5bc6fcbf 100644
--- a/api/v1alpha5/zz_generated.conversion.go
+++ b/api/v1alpha5/zz_generated.conversion.go
@@ -54,16 +54,6 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*Bastion)(nil), (*v1alpha8.Bastion)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_Bastion_To_v1alpha8_Bastion(a.(*Bastion), b.(*v1alpha8.Bastion), scope)
- }); err != nil {
- return err
- }
- if err := s.AddGeneratedConversionFunc((*v1alpha8.Bastion)(nil), (*Bastion)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_Bastion_To_v1alpha5_Bastion(a.(*v1alpha8.Bastion), b.(*Bastion), scope)
- }); err != nil {
- return err
- }
if err := s.AddGeneratedConversionFunc((*ExternalRouterIPParam)(nil), (*v1alpha8.ExternalRouterIPParam)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha5_ExternalRouterIPParam_To_v1alpha8_ExternalRouterIPParam(a.(*ExternalRouterIPParam), b.(*v1alpha8.ExternalRouterIPParam), scope)
}); err != nil {
@@ -299,6 +289,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
+ if err := s.AddConversionFunc((*Bastion)(nil), (*v1alpha8.Bastion)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_Bastion_To_v1alpha8_Bastion(a.(*Bastion), b.(*v1alpha8.Bastion), scope)
+ }); err != nil {
+ return err
+ }
if err := s.AddConversionFunc((*Instance)(nil), (*v1alpha8.BastionStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha5_Instance_To_v1alpha8_BastionStatus(a.(*Instance), b.(*v1alpha8.BastionStatus), scope)
}); err != nil {
@@ -359,6 +354,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
+ if err := s.AddConversionFunc((*v1alpha8.Bastion)(nil), (*Bastion)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_Bastion_To_v1alpha5_Bastion(a.(*v1alpha8.Bastion), b.(*Bastion), scope)
+ }); err != nil {
+ return err
+ }
if err := s.AddConversionFunc((*v1alpha8.LoadBalancer)(nil), (*LoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha8_LoadBalancer_To_v1alpha5_LoadBalancer(a.(*v1alpha8.LoadBalancer), b.(*LoadBalancer), scope)
}); err != nil {
@@ -463,25 +463,16 @@ func autoConvert_v1alpha5_Bastion_To_v1alpha8_Bastion(in *Bastion, out *v1alpha8
return nil
}
-// Convert_v1alpha5_Bastion_To_v1alpha8_Bastion is an autogenerated conversion function.
-func Convert_v1alpha5_Bastion_To_v1alpha8_Bastion(in *Bastion, out *v1alpha8.Bastion, s conversion.Scope) error {
- return autoConvert_v1alpha5_Bastion_To_v1alpha8_Bastion(in, out, s)
-}
-
func autoConvert_v1alpha8_Bastion_To_v1alpha5_Bastion(in *v1alpha8.Bastion, out *Bastion, s conversion.Scope) error {
out.Enabled = in.Enabled
if err := Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(&in.Instance, &out.Instance, s); err != nil {
return err
}
out.AvailabilityZone = in.AvailabilityZone
+ // WARNING: in.FloatingIP requires manual conversion: does not exist in peer-type
return nil
}
-// Convert_v1alpha8_Bastion_To_v1alpha5_Bastion is an autogenerated conversion function.
-func Convert_v1alpha8_Bastion_To_v1alpha5_Bastion(in *v1alpha8.Bastion, out *Bastion, s conversion.Scope) error {
- return autoConvert_v1alpha8_Bastion_To_v1alpha5_Bastion(in, out, s)
-}
-
func autoConvert_v1alpha5_ExternalRouterIPParam_To_v1alpha8_ExternalRouterIPParam(in *ExternalRouterIPParam, out *v1alpha8.ExternalRouterIPParam, s conversion.Scope) error {
out.FixedIP = in.FixedIP
if err := Convert_v1alpha5_SubnetParam_To_v1alpha8_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil {
@@ -1073,7 +1064,7 @@ func autoConvert_v1alpha5_OpenStackMachineSpec_To_v1alpha8_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([]v1alpha8.SecurityGroupFilter, len(*in))
@@ -1113,7 +1104,6 @@ func autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(
} else {
out.Ports = nil
}
- out.FloatingIP = in.FloatingIP
if in.SecurityGroups != nil {
in, out := &in.SecurityGroups, &out.SecurityGroups
*out = make([]SecurityGroupParam, len(*in))
diff --git a/api/v1alpha6/conversion.go b/api/v1alpha6/conversion.go
index ab8d50a1bd..2e2000cfd4 100644
--- a/api/v1alpha6/conversion.go
+++ b/api/v1alpha6/conversion.go
@@ -40,6 +40,10 @@ func restorev1alpha6MachineSpec(previous *OpenStackMachineSpec, dst *OpenStackMa
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
}
func restorev1alpha6ClusterStatus(previous *OpenStackClusterStatus, dst *OpenStackClusterStatus) {
@@ -759,6 +763,7 @@ func Convert_v1alpha6_Bastion_To_v1alpha8_Bastion(in *Bastion, out *infrav1.Bast
out.Instance.ServerGroup = nil
}
+ out.FloatingIP = in.Instance.FloatingIP
return nil
}
@@ -772,5 +777,6 @@ func Convert_v1alpha8_Bastion_To_v1alpha6_Bastion(in *infrav1.Bastion, out *Bast
out.Instance.ServerGroupID = in.Instance.ServerGroup.ID
}
+ out.Instance.FloatingIP = in.FloatingIP
return nil
}
diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go
index 63ab1b88b3..8a00f25e45 100644
--- a/api/v1alpha6/zz_generated.conversion.go
+++ b/api/v1alpha6/zz_generated.conversion.go
@@ -485,6 +485,7 @@ func autoConvert_v1alpha8_Bastion_To_v1alpha6_Bastion(in *v1alpha8.Bastion, out
return err
}
out.AvailabilityZone = in.AvailabilityZone
+ // WARNING: in.FloatingIP requires manual conversion: does not exist in peer-type
return nil
}
@@ -1086,7 +1087,7 @@ func autoConvert_v1alpha6_OpenStackMachineSpec_To_v1alpha8_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([]v1alpha8.SecurityGroupFilter, len(*in))
@@ -1126,7 +1127,6 @@ func autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(
} else {
out.Ports = nil
}
- out.FloatingIP = in.FloatingIP
if in.SecurityGroups != nil {
in, out := &in.SecurityGroups, &out.SecurityGroups
*out = make([]SecurityGroupParam, len(*in))
diff --git a/api/v1alpha7/conversion.go b/api/v1alpha7/conversion.go
index 25dab7a655..31862c3f86 100644
--- a/api/v1alpha7/conversion.go
+++ b/api/v1alpha7/conversion.go
@@ -65,6 +65,10 @@ var v1alpha8OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStack
),
}
+func restorev1alpha7MachineSpec(previous *OpenStackMachineSpec, dst *OpenStackMachineSpec) {
+ dst.FloatingIP = previous.FloatingIP
+}
+
func restorev1alpha8MachineSpec(previous *infrav1.OpenStackMachineSpec, dst *infrav1.OpenStackMachineSpec) {
dst.ServerGroup = previous.ServerGroup
dst.Image = previous.Image
@@ -169,7 +173,14 @@ func (r *OpenStackClusterTemplate) ConvertFrom(srcRaw ctrlconversion.Hub) error
var _ ctrlconversion.Convertible = &OpenStackMachine{}
-var v1alpha7OpenStackMachineRestorer = conversion.RestorerFor[*OpenStackMachine]{}
+var v1alpha7OpenStackMachineRestorer = conversion.RestorerFor[*OpenStackMachine]{
+ "spec": conversion.HashedFieldRestorer(
+ func(c *OpenStackMachine) *OpenStackMachineSpec {
+ return &c.Spec
+ },
+ restorev1alpha7MachineSpec,
+ ),
+}
var v1alpha8OpenStackMachineRestorer = conversion.RestorerFor[*infrav1.OpenStackMachine]{
"spec": conversion.HashedFieldRestorer(
@@ -221,7 +232,18 @@ func (r *OpenStackMachineList) ConvertFrom(srcRaw ctrlconversion.Hub) error {
var _ ctrlconversion.Convertible = &OpenStackMachineTemplate{}
-var v1alpha7OpenStackMachineTemplateRestorer = conversion.RestorerFor[*OpenStackMachineTemplate]{}
+func restorev1alpha7MachineTemplateSpec(previous *OpenStackMachineTemplateSpec, dst *OpenStackMachineTemplateSpec) {
+ restorev1alpha7MachineSpec(&previous.Template.Spec, &dst.Template.Spec)
+}
+
+var v1alpha7OpenStackMachineTemplateRestorer = conversion.RestorerFor[*OpenStackMachineTemplate]{
+ "spec": conversion.HashedFieldRestorer(
+ func(c *OpenStackMachineTemplate) *OpenStackMachineTemplateSpec {
+ return &c.Spec
+ },
+ restorev1alpha7MachineTemplateSpec,
+ ),
+}
var v1alpha8OpenStackMachineTemplateRestorer = conversion.RestorerFor[*infrav1.OpenStackMachineTemplate]{
"spec": conversion.HashedFieldRestorer(
@@ -331,6 +353,7 @@ func Convert_v1alpha7_Bastion_To_v1alpha8_Bastion(in *Bastion, out *infrav1.Bast
out.Instance.ServerGroup = nil
}
+ out.FloatingIP = in.Instance.FloatingIP
return nil
}
@@ -344,6 +367,7 @@ func Convert_v1alpha8_Bastion_To_v1alpha7_Bastion(in *infrav1.Bastion, out *Bast
out.Instance.ServerGroupID = in.Instance.ServerGroup.ID
}
+ out.Instance.FloatingIP = in.FloatingIP
return nil
}
diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go
index 25b03fcc7e..2df0972e6e 100644
--- a/api/v1alpha7/zz_generated.conversion.go
+++ b/api/v1alpha7/zz_generated.conversion.go
@@ -543,6 +543,7 @@ func autoConvert_v1alpha8_Bastion_To_v1alpha7_Bastion(in *v1alpha8.Bastion, out
return err
}
out.AvailabilityZone = in.AvailabilityZone
+ // WARNING: in.FloatingIP requires manual conversion: does not exist in peer-type
return nil
}
@@ -1236,7 +1237,7 @@ func autoConvert_v1alpha7_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(
// WARNING: in.ImageUUID requires manual conversion: does not exist in peer-type
out.SSHKeyName = in.SSHKeyName
out.Ports = *(*[]v1alpha8.PortOpts)(unsafe.Pointer(&in.Ports))
- out.FloatingIP = in.FloatingIP
+ // WARNING: in.FloatingIP requires manual conversion: does not exist in peer-type
out.SecurityGroups = *(*[]v1alpha8.SecurityGroupFilter)(unsafe.Pointer(&in.SecurityGroups))
out.Trunk = in.Trunk
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
@@ -1257,7 +1258,6 @@ func autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(
// WARNING: in.Image requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8.ImageFilter vs string)
out.SSHKeyName = in.SSHKeyName
out.Ports = *(*[]PortOpts)(unsafe.Pointer(&in.Ports))
- out.FloatingIP = in.FloatingIP
out.SecurityGroups = *(*[]SecurityGroupFilter)(unsafe.Pointer(&in.SecurityGroups))
out.Trunk = in.Trunk
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
diff --git a/api/v1alpha8/openstackmachine_types.go b/api/v1alpha8/openstackmachine_types.go
index d5b27b4648..61d29bad86 100644
--- a/api/v1alpha8/openstackmachine_types.go
+++ b/api/v1alpha8/openstackmachine_types.go
@@ -56,10 +56,6 @@ 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"`
diff --git a/api/v1alpha8/types.go b/api/v1alpha8/types.go
index 016fb258ed..bdbf2155bf 100644
--- a/api/v1alpha8/types.go
+++ b/api/v1alpha8/types.go
@@ -362,6 +362,11 @@ type Bastion struct {
//+optional
AvailabilityZone string `json:"availabilityZone,omitempty"`
+
+ // FloatingIP which will be associated to the bastion machine.
+ // The floating IP should already exist and should not be associated with a port.
+ //+optional
+ FloatingIP string `json:"floatingIP,omitempty"`
}
type APIServerLoadBalancer struct {
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 347e64c6ef..c22d9fcea5 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -4906,6 +4906,11 @@ spec:
type: string
enabled:
type: boolean
+ floatingIP:
+ description: |-
+ FloatingIP which will be associated to the bastion machine.
+ The floating IP should already exist and should not be associated with a port.
+ type: string
instance:
description: Instance for the bastion itself
properties:
@@ -4981,11 +4986,6 @@ 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.
- type: string
identityRef:
description: IdentityRef is a reference to a identity to be
used when reconciling this cluster
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 6d6a75f1e6..4f96c272aa 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -2331,6 +2331,11 @@ spec:
type: string
enabled:
type: boolean
+ floatingIP:
+ description: |-
+ FloatingIP which will be associated to the bastion machine.
+ The floating IP should already exist and should not be associated with a port.
+ type: string
instance:
description: Instance for the bastion itself
properties:
@@ -2407,11 +2412,6 @@ 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.
- type: string
identityRef:
description: IdentityRef is a reference to a identity
to be used when reconciling this cluster
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 32e9b314bf..340057cfef 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
@@ -1780,11 +1780,6 @@ spec:
flavor:
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.
- type: string
identityRef:
description: IdentityRef is a reference to a identity to be used when
reconciling this cluster
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 48ca01f8e1..264c893e49 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
@@ -1455,11 +1455,6 @@ 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.
- type: string
identityRef:
description: IdentityRef is a reference to a identity to be
used when reconciling this cluster
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index 9b857b7011..e954631e1d 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -412,7 +412,7 @@ func reconcileBastion(scope scope.Scope, cluster *clusterv1.Cluster, openStackCl
}
clusterName := fmt.Sprintf("%s-%s", cluster.Namespace, cluster.Name)
- floatingIP := openStackCluster.Spec.Bastion.Instance.FloatingIP
+ floatingIP := openStackCluster.Spec.Bastion.FloatingIP
if 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
diff --git a/docs/book/src/clusteropenstack/configuration.md b/docs/book/src/clusteropenstack/configuration.md
index 7802107f02..1a075bc57e 100644
--- a/docs/book/src/clusteropenstack/configuration.md
+++ b/docs/book/src/clusteropenstack/configuration.md
@@ -649,7 +649,7 @@ spec:
...
bastion:
...
- floatingIP:
+ floatingIP:
```
If `managedSecurityGroups: true`, security group rule opening 22/tcp is added to security groups for bastion, controller, and worker nodes respectively. Otherwise, you have to add `securityGroups` to the `bastion` in `OpenStackCluster` spec and `OpenStackMachineTemplate` spec template respectively.
diff --git a/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md b/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md
index 1183805d26..512f61d83a 100644
--- a/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md
+++ b/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md
@@ -6,11 +6,12 @@
- [Migration](#migration)
- [API Changes](#api-changes)
- [`OpenStackMachine`](#openstackmachine)
- - [Change to `serverGroupID`](#change-to-servergroupid)
+ - [⚠️ Change to `serverGroupID`](#️-change-to-servergroupid)
- [`OpenStackCluster`](#openstackcluster)
- [Change to externalNetworkID](#change-to-externalnetworkid)
- [Changes to image](#change-to-image)
- [Removal of imageUUID](#removal-of-imageuuid)
+ - [Change to floatingIP](#change-to-floatingip)
@@ -123,3 +124,35 @@ becomes
image:
id: "72a6a1e6-3e0a-4a8b-9b4c-2d6f9e3e5f0a"
```
+
+#### Change to floatingIP
+
+The `OpenStackMachineSpec.FloatingIP` field has moved to `OpenStackClusterSpec.Bastion.FloatingIP`.
+For example, if you had the following `OpenStackMachineTemplate`:
+
+```yaml
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha6
+kind: OpenStackMachineTemplate
+metadata:
+ name: ${CLUSTER_NAME}-md-0
+spec:
+ template:
+ spec:
+ ..
+ floatingIP: "1.2.3.4"
+```
+
+This will safely converted to use `Bastion.FloatingIP` when upgrading to version 0.8.
+
+To use the new `Bastion.FloatingIP` field, here is an example:
+
+```yaml
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
+kind: OpenStackCluster
+metadata:
+ name: ${CLUSTER_NAME}
+spec:
+ ..
+ bastion:
+ floatingIP: "1.2.3.4"
+```
From b75c40a315535a2682ee1d67f02b00bba3f9ba80 Mon Sep 17 00:00:00 2001
From: Emilien Macchi
Date: Fri, 12 Jan 2024 22:49:26 -0500
Subject: [PATCH 033/180] ci: reduce vcpu for m1.medium
---
hack/ci/cloud-init/controller.yaml.tpl | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hack/ci/cloud-init/controller.yaml.tpl b/hack/ci/cloud-init/controller.yaml.tpl
index 45bf607fff..a86204b965 100644
--- a/hack/ci/cloud-init/controller.yaml.tpl
+++ b/hack/ci/cloud-init/controller.yaml.tpl
@@ -176,7 +176,7 @@
openstack flavor delete m1.small
openstack flavor create --ram 4192 --disk 20 --ephemeral 5 --vcpus 2 --public --id 2 m1.small --property hw_rng:allowed='True'
openstack flavor delete m1.medium
- openstack flavor create --ram 6144 --disk 20 --ephemeral 5 --vcpus 4 --public --id 3 m1.medium --property hw_rng:allowed='True'
+ openstack flavor create --ram 6144 --disk 20 --ephemeral 5 --vcpus 2 --public --id 3 m1.medium --property hw_rng:allowed='True'
# Adjust the CPU quota
openstack quota set --cores 32 demo
From 04ee2bbdbcda3690f284e38b8b76093e084e8af9 Mon Sep 17 00:00:00 2001
From: Simon Murray
Date: Mon, 4 Dec 2023 11:48:44 +0000
Subject: [PATCH 034/180] Allow AZs to be Omitted at Runtime
CAPI appears to make implicit CP scheduling decisions based on what it's
told is available by CAPO on an "LRU" basis. It also assumes an infinite
sized AZ, so problems begin when the "next" AZ cannot accommodate the
VM. We could manually specify an AZ that aggregates all machines
explcitly, however this is another mechanism that disables scheduling by
CAPI altogether and allows Nova to do what it does, along with a soft-AA
rule. However, switching from CAPI scheduling to Nova scheduling is
impossible as the field is immutable, so allow this. Testing shows
existing scheduled clusters undergo no topology changes, which will be
due to the KCPM not taking action, but you can force the changes with a
rolling upgrade of some variety. Crucially, if a cluster with CAPI
scheduling gets stuck, we can modify to Nova scheduling and it should
pick up the new specification and get past the hurdle.
---
api/v1alpha8/openstackcluster_webhook.go | 5 +++++
api/v1alpha8/openstackcluster_webhook_test.go | 15 +++++++++++++++
2 files changed, 20 insertions(+)
diff --git a/api/v1alpha8/openstackcluster_webhook.go b/api/v1alpha8/openstackcluster_webhook.go
index 6821b6c1df..2344870c7d 100644
--- a/api/v1alpha8/openstackcluster_webhook.go
+++ b/api/v1alpha8/openstackcluster_webhook.go
@@ -130,6 +130,11 @@ func (r *OpenStackCluster) ValidateUpdate(oldRaw runtime.Object) (admission.Warn
old.Spec.ControlPlaneAvailabilityZones = []string{}
r.Spec.ControlPlaneAvailabilityZones = []string{}
+ // Allow the scheduling to be changed from CAPI managed to Nova and
+ // vice versa.
+ old.Spec.ControlPlaneOmitAvailabilityZone = false
+ r.Spec.ControlPlaneOmitAvailabilityZone = false
+
// Allow change to the allowAllInClusterTraffic.
old.Spec.AllowAllInClusterTraffic = false
r.Spec.AllowAllInClusterTraffic = false
diff --git a/api/v1alpha8/openstackcluster_webhook_test.go b/api/v1alpha8/openstackcluster_webhook_test.go
index cf4f33da27..27e8ab34db 100644
--- a/api/v1alpha8/openstackcluster_webhook_test.go
+++ b/api/v1alpha8/openstackcluster_webhook_test.go
@@ -234,6 +234,21 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
wantErr: false,
},
+ {
+ name: "Modifying OpenstackCluster.Spec.ControlPlaneOmitAvailabilityZone is allowed",
+ oldTemplate: &OpenStackCluster{
+ Spec: OpenStackClusterSpec{
+ CloudName: "foobar",
+ },
+ },
+ newTemplate: &OpenStackCluster{
+ Spec: OpenStackClusterSpec{
+ CloudName: "foobar",
+ ControlPlaneOmitAvailabilityZone: true,
+ },
+ },
+ wantErr: false,
+ },
{
name: "Changing OpenStackCluster.Spec.APIServerFixedIP is allowed when API Server Floating IP is disabled",
oldTemplate: &OpenStackCluster{
From fc644808beea9810764847f9da2ff8b64fa86fe0 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Tue, 16 Jan 2024 23:10:43 +0000
Subject: [PATCH 035/180] Persist API FloatingIP immediately on creation
If loadbalancer reconciliation failed at any time after the floating IP
was created, we would lead the floating IP and create a new one on the
next reconciliation.
---
.../services/loadbalancer/loadbalancer.go | 33 +++++++++++++------
1 file changed, 23 insertions(+), 10 deletions(-)
diff --git a/pkg/cloud/services/loadbalancer/loadbalancer.go b/pkg/cloud/services/loadbalancer/loadbalancer.go
index e395373c66..75e2201779 100644
--- a/pkg/cloud/services/loadbalancer/loadbalancer.go
+++ b/pkg/cloud/services/loadbalancer/loadbalancer.go
@@ -50,8 +50,16 @@ func (s *Service) ReconcileLoadBalancer(openStackCluster *infrav1.OpenStackClust
loadBalancerName := getLoadBalancerName(clusterName)
s.scope.Logger().Info("Reconciling load balancer", "name", loadBalancerName)
+ lbStatus := openStackCluster.Status.APIServerLoadBalancer
+ if lbStatus == nil {
+ lbStatus = &infrav1.LoadBalancer{}
+ openStackCluster.Status.APIServerLoadBalancer = lbStatus
+ }
+
var fixedIPAddress string
switch {
+ case lbStatus.InternalIP != "":
+ fixedIPAddress = lbStatus.InternalIP
case openStackCluster.Spec.APIServerFixedIP != "":
fixedIPAddress = openStackCluster.Spec.APIServerFixedIP
case openStackCluster.Spec.DisableAPIServerFloatingIP && openStackCluster.Spec.ControlPlaneEndpoint.IsValid():
@@ -82,14 +90,21 @@ func (s *Service) ReconcileLoadBalancer(openStackCluster *infrav1.OpenStackClust
if err != nil {
return false, err
}
+
+ lbStatus.Name = lb.Name
+ lbStatus.ID = lb.ID
+ lbStatus.InternalIP = lb.VipAddress
+ lbStatus.Tags = lb.Tags
+
if err := s.waitForLoadBalancerActive(lb.ID); err != nil {
return false, fmt.Errorf("load balancer %q with id %s is not active after timeout: %v", loadBalancerName, lb.ID, err)
}
- var lbFloatingIP string
if !openStackCluster.Spec.DisableAPIServerFloatingIP {
var floatingIPAddress string
switch {
+ case lbStatus.IP != "":
+ floatingIPAddress = lbStatus.IP
case openStackCluster.Spec.APIServerFloatingIP != "":
floatingIPAddress = openStackCluster.Spec.APIServerFloatingIP
case openStackCluster.Spec.ControlPlaneEndpoint.IsValid():
@@ -99,10 +114,15 @@ func (s *Service) ReconcileLoadBalancer(openStackCluster *infrav1.OpenStackClust
if err != nil {
return false, err
}
+
+ // Write the floating IP to the status immediately so we won't
+ // create a new floating IP on the next reconcile if something
+ // fails below.
+ lbStatus.IP = fp.FloatingIP
+
if err = s.networkingService.AssociateFloatingIP(openStackCluster, fp, lb.VipPortID); err != nil {
return false, err
}
- lbFloatingIP = fp.FloatingIP
}
allowedCIDRs := []string{}
@@ -147,15 +167,8 @@ func (s *Service) ReconcileLoadBalancer(openStackCluster *infrav1.OpenStackClust
}
}
}
+ lbStatus.AllowedCIDRs = allowedCIDRs
- openStackCluster.Status.APIServerLoadBalancer = &infrav1.LoadBalancer{
- Name: lb.Name,
- ID: lb.ID,
- InternalIP: lb.VipAddress,
- IP: lbFloatingIP,
- AllowedCIDRs: allowedCIDRs,
- Tags: lb.Tags,
- }
return false, nil
}
From 368ff896e192e04929bb5f6033ad7f965f08bf3c Mon Sep 17 00:00:00 2001
From: bilbo
Date: Thu, 18 Jan 2024 14:37:46 +0100
Subject: [PATCH 036/180] IPAM provider for floating ips
---
Makefile | 1 +
PROJECT | 27 +-
api/v1alpha1/conditions_consts.go | 22 +
api/v1alpha1/doc.go | 17 +
api/v1alpha1/groupversion_info.go | 36 ++
api/v1alpha1/openstackfloatingippool_types.go | 136 +++++
api/v1alpha1/zz_generated.deepcopy.go | 154 ++++++
...ter.x-k8s.io_openstackfloatingippools.yaml | 191 +++++++
config/crd/kustomization.yaml | 2 +
...injection_in_openstackfloatingippools.yaml | 8 +
.../webhook_in_openstackfloatingippools.yaml | 17 +
.../openstackfloatingippool_editor_role.yaml | 24 +
.../openstackfloatingippool_viewer_role.yaml | 20 +
config/rbac/role.yaml | 44 ++
.../openstackfloatingippool_controller.go | 475 ++++++++++++++++++
main.go | 15 +-
pkg/cloud/services/networking/floatingip.go | 45 ++
pkg/scope/mock.go | 8 +
pkg/scope/provider.go | 24 +
pkg/scope/scope.go | 2 +
pkg/utils/ipam/predicates.go | 96 ++++
21 files changed, 1353 insertions(+), 11 deletions(-)
create mode 100644 api/v1alpha1/conditions_consts.go
create mode 100644 api/v1alpha1/doc.go
create mode 100644 api/v1alpha1/groupversion_info.go
create mode 100644 api/v1alpha1/openstackfloatingippool_types.go
create mode 100644 api/v1alpha1/zz_generated.deepcopy.go
create mode 100644 config/crd/bases/infrastructure.cluster.x-k8s.io_openstackfloatingippools.yaml
create mode 100644 config/crd/patches/cainjection_in_openstackfloatingippools.yaml
create mode 100644 config/crd/patches/webhook_in_openstackfloatingippools.yaml
create mode 100644 config/rbac/openstackfloatingippool_editor_role.yaml
create mode 100644 config/rbac/openstackfloatingippool_viewer_role.yaml
create mode 100644 controllers/openstackfloatingippool_controller.go
create mode 100644 pkg/utils/ipam/predicates.go
diff --git a/Makefile b/Makefile
index c1968fe83a..e25fb5badb 100644
--- a/Makefile
+++ b/Makefile
@@ -257,6 +257,7 @@ generate-go: $(MOCKGEN)
paths=./api/... \
object:headerFile=./hack/boilerplate/boilerplate.generatego.txt
$(CONVERSION_GEN) \
+ --input-dirs=./api/v1alpha1 \
--input-dirs=./api/v1alpha5 \
--input-dirs=./api/v1alpha6 \
--input-dirs=./api/v1alpha7 \
diff --git a/PROJECT b/PROJECT
index 7874bda38c..6514dde9b3 100644
--- a/PROJECT
+++ b/PROJECT
@@ -1,40 +1,43 @@
-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
@@ -50,3 +53,7 @@ resources:
- group: infrastructure
kind: OpenStackClusterTemplate
version: v1alpha8
+- group: infrastructure
+ kind: OpenStackFloatingIPPool
+ version: v1alpha1
+version: "2"
diff --git a/api/v1alpha1/conditions_consts.go b/api/v1alpha1/conditions_consts.go
new file mode 100644
index 0000000000..32d80d51d7
--- /dev/null
+++ b/api/v1alpha1/conditions_consts.go
@@ -0,0 +1,22 @@
+/*
+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
+
+const (
+ // OpenstackFloatingIPPoolReadyCondition reports on the current status of the floating ip pool. Ready indicates that the pool is ready to be used.
+ OpenstackFloatingIPPoolReadyCondition = "OpenstackFloatingIPPoolReadyCondition"
+)
diff --git a/api/v1alpha1/doc.go b/api/v1alpha1/doc.go
new file mode 100644
index 0000000000..7fff087c61
--- /dev/null
+++ b/api/v1alpha1/doc.go
@@ -0,0 +1,17 @@
+/*
+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
diff --git a/api/v1alpha1/groupversion_info.go b/api/v1alpha1/groupversion_info.go
new file mode 100644
index 0000000000..fee80edbaa
--- /dev/null
+++ b/api/v1alpha1/groupversion_info.go
@@ -0,0 +1,36 @@
+/*
+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
+
+import (
+ "k8s.io/apimachinery/pkg/runtime/schema"
+ "sigs.k8s.io/controller-runtime/pkg/scheme"
+)
+
+var (
+ // GroupVersion is group version used to register these objects.
+ 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}
+
+ // AddToScheme adds the types in this group-version to the given scheme.
+ AddToScheme = SchemeBuilder.AddToScheme
+)
diff --git a/api/v1alpha1/openstackfloatingippool_types.go b/api/v1alpha1/openstackfloatingippool_types.go
new file mode 100644
index 0000000000..0f6c4e129f
--- /dev/null
+++ b/api/v1alpha1/openstackfloatingippool_types.go
@@ -0,0 +1,136 @@
+/*
+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"
+
+ // We use v1alpha7 here rather than anything newer because as of writing
+ // it is the newest API version we should no longer be making breaking
+ // changes to. If we bump this we need to look carefully for resulting
+ // CRD changes in v1alpha1 to ensure they are compatible.
+ infrav1alpha7 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
+)
+
+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"`
+
+ // IdentityRef is a reference to a identity to be used when reconciling this pool.
+ // +optional
+ IdentityRef *infrav1alpha7.OpenStackIdentityReference `json:"identityRef,omitempty"`
+
+ // 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 infrav1alpha7.NetworkFilter `json:"floatingIPNetwork"`
+
+ // The name of the cloud to use from the clouds secret
+ // +optional
+ CloudName string `json:"cloudName"`
+
+ // The stratergy to use for reclaiming floating ips when they are released from a machine
+ // +kubebuilder:validation:Optional
+ // +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 *infrav1alpha7.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..0eef1f41d3
--- /dev/null
+++ b/api/v1alpha1/zz_generated.deepcopy.go
@@ -0,0 +1,154 @@
+//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/v1alpha7"
+ "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.IdentityRef != nil {
+ in, out := &in.IdentityRef, &out.IdentityRef
+ *out = new(v1alpha7.OpenStackIdentityReference)
+ **out = **in
+ }
+ out.FloatingIPNetwork = in.FloatingIPNetwork
+}
+
+// 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(v1alpha7.NetworkStatus)
+ (*in).DeepCopyInto(*out)
+ }
+ if in.Conditions != nil {
+ in, out := &in.Conditions, &out.Conditions
+ *out = make(v1beta1.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/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..a38c86c0cc
--- /dev/null
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackfloatingippools.yaml
@@ -0,0 +1,191 @@
+---
+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:
+ cloudName:
+ description: The name of the cloud to use from the clouds secret
+ type: string
+ 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
+ properties:
+ description:
+ type: string
+ id:
+ type: string
+ name:
+ type: string
+ notTags:
+ type: string
+ notTagsAny:
+ type: string
+ projectId:
+ type: string
+ tags:
+ type: string
+ tagsAny:
+ type: string
+ type: object
+ identityRef:
+ description: IdentityRef is a reference to a identity to be used when
+ reconciling this pool.
+ properties:
+ kind:
+ 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.
+ type: string
+ required:
+ - kind
+ - name
+ type: object
+ 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
+ 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/kustomization.yaml b/config/crd/kustomization.yaml
index 283048b008..c153237cc4 100644
--- a/config/crd/kustomization.yaml
+++ b/config/crd/kustomization.yaml
@@ -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/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..6a40632602 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,27 @@ rules:
- get
- patch
- update
+- apiGroups:
+ - ipam.cluster.x-k8s.io
+ resources:
+ - ipaddressclaims
+ - ipaddressclaims/status
+ verbs:
+ - create
+ - delete
+ - get
+ - list
+ - update
+ - watch
+- apiGroups:
+ - ipam.cluster.x-k8s.io
+ resources:
+ - ipaddresses
+ - ipaddresses/status
+ verbs:
+ - create
+ - delete
+ - get
+ - list
+ - update
+ - watch
diff --git a/controllers/openstackfloatingippool_controller.go b/controllers/openstackfloatingippool_controller.go
new file mode 100644
index 0000000000..6ee65140a3
--- /dev/null
+++ b/controllers/openstackfloatingippool_controller.go
@@ -0,0 +1,475 @@
+/*
+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"
+
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external"
+ 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/pointer"
+ 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"
+ infrav1alpha7 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ "sigs.k8s.io/cluster-api-provider-openstack/pkg/cloud/services/networking"
+ "sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
+)
+
+const (
+ openStackFloatingIPPool = "OpenStackFloatingIPPool"
+)
+
+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)
+ }
+
+ scope, err := r.ScopeFactory.NewClientScopeFromFloatingIPPool(ctx, r.Client, pool, r.CaCertificates, log)
+ if err != nil {
+ return reconcile.Result{}, err
+ }
+
+ // 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 {
+ 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: pointer.String(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)
+ }
+ }
+ return ctrl.Result{}, r.Client.Status().Update(ctx, pool)
+}
+
+func (r *OpenStackFloatingIPPoolReconciler) reconcileDelete(ctx context.Context, scope scope.Scope, 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.Scope, 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
+ }
+ }
+ unclaimedPreAllocatedIPs := diff(pool.Spec.PreAllocatedFloatingIPs, pool.Status.ClaimedIPs)
+ unclaimedIPs := union(pool.Status.AvailableIPs, unclaimedPreAllocatedIPs)
+ pool.Status.AvailableIPs = diff(unclaimedIPs, pool.Status.FailedIPs)
+ return nil
+}
+
+func (r *OpenStackFloatingIPPoolReconciler) getIP(ctx context.Context, scope scope.Scope, 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 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:]
+ }
+
+ if ip != "" {
+ fp, err := networkingService.GetFloatingIP(ip)
+ if err != nil {
+ return "", fmt.Errorf("get floating IP: %w", err)
+ }
+ if fp != nil {
+ return fp.FloatingIP, nil
+ }
+ }
+
+ 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)
+ if ip != "" {
+ pool.Status.FailedIPs = append(pool.Status.FailedIPs, ip)
+ }
+ 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.Scope, 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
+ }
+
+ netListOpts := external.ListOptsExt{
+ ListOptsBuilder: pool.Spec.FloatingIPNetwork.ToListOpt(),
+ External: pointer.Bool(true),
+ }
+
+ networkList, err := networkingService.GetNetworksByFilter(&netListOpts)
+ if err != nil {
+ return fmt.Errorf("failed to find network: %w", err)
+ }
+ if len(networkList) > 1 {
+ return fmt.Errorf("found multiple networks, expects filter to match one (result: %v)", networkList)
+ }
+
+ pool.Status.FloatingIPNetwork = &infrav1alpha7.NetworkStatus{
+ ID: networkList[0].ID,
+ Name: networkList[0].Name,
+ Tags: networkList[0].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)
+ 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/main.go b/main.go
index 40ee63009c..01c6caa6a3 100644
--- a/main.go
+++ b/main.go
@@ -34,6 +34,7 @@ import (
_ "k8s.io/component-base/logs/json/register"
"k8s.io/klog/v2"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
+ ipamv1 "sigs.k8s.io/cluster-api/exp/ipam/api/v1beta1"
"sigs.k8s.io/cluster-api/util/flags"
ctrl "sigs.k8s.io/controller-runtime"
cache "sigs.k8s.io/controller-runtime/pkg/cache"
@@ -42,6 +43,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/controller"
"sigs.k8s.io/controller-runtime/pkg/webhook"
+ infrav1alpha1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha1"
infrav1alpha5 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha5"
infrav1alpha6 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha6"
infrav1alpha7 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
@@ -84,10 +86,12 @@ var (
func init() {
_ = clientgoscheme.AddToScheme(scheme)
_ = clusterv1.AddToScheme(scheme)
+ _ = ipamv1.AddToScheme(scheme)
_ = infrav1.AddToScheme(scheme)
_ = infrav1alpha5.AddToScheme(scheme)
_ = infrav1alpha6.AddToScheme(scheme)
_ = infrav1alpha7.AddToScheme(scheme)
+ _ = infrav1alpha1.AddToScheme(scheme)
// +kubebuilder:scaffold:scheme
metrics.RegisterAPIPrometheusMetrics()
@@ -254,7 +258,6 @@ func main() {
setupChecks(mgr)
setupReconcilers(ctx, mgr, caCerts, scopeFactory)
setupWebhooks(mgr)
-
// +kubebuilder:scaffold:builder
setupLog.Info("starting manager", "version", version.Get().String())
if err := mgr.Start(ctx); err != nil {
@@ -296,6 +299,16 @@ func setupReconcilers(ctx context.Context, mgr ctrl.Manager, caCerts []byte, sco
setupLog.Error(err, "unable to create controller", "controller", "OpenStackMachine")
os.Exit(1)
}
+ if err := (&controllers.OpenStackFloatingIPPoolReconciler{
+ Client: mgr.GetClient(),
+ Recorder: mgr.GetEventRecorderFor("floatingippool-controller"),
+ ScopeFactory: scopeFactory,
+ Scheme: mgr.GetScheme(),
+ CaCertificates: caCerts,
+ }).SetupWithManager(ctx, mgr); err != nil {
+ setupLog.Error(err, "unable to create controller", "controller", "FloatingIPPool")
+ os.Exit(1)
+ }
}
func setupWebhooks(mgr ctrl.Manager) {
diff --git a/pkg/cloud/services/networking/floatingip.go b/pkg/cloud/services/networking/floatingip.go
index 61b7e77d94..8586ba6223 100644
--- a/pkg/cloud/services/networking/floatingip.go
+++ b/pkg/cloud/services/networking/floatingip.go
@@ -17,6 +17,7 @@ limitations under the License.
package networking
import (
+ "fmt"
"time"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/attributestags"
@@ -24,6 +25,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/wait"
+ "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha1"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/metrics"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/record"
@@ -70,6 +72,49 @@ func (s *Service) GetOrCreateFloatingIP(eventObject runtime.Object, openStackClu
return fp, nil
}
+func (s *Service) CreateFloatingIPForPool(pool *v1alpha1.OpenStackFloatingIPPool) (*floatingips.FloatingIP, error) {
+ var fpCreateOpts floatingips.CreateOpts
+
+ fpCreateOpts.FloatingNetworkID = pool.Status.FloatingIPNetwork.ID
+ fpCreateOpts.Description = fmt.Sprintf("Created by cluster-api-provider-openstack OpenStackFloatingIPPool %s", pool.Name)
+
+ fp, err := s.client.CreateFloatingIP(fpCreateOpts)
+ if err != nil {
+ record.Warnf(pool, "FailedCreateFloatingIP", "%s failed to create floating IP: %v", pool.Name, err)
+ return nil, err
+ }
+
+ record.Eventf(pool, "SuccessfulCreateFloatingIP", "%s created floating IP %s with id %s", pool.Name, fp.FloatingIP, fp.ID)
+ return fp, nil
+}
+
+func (s *Service) TagFloatingIP(ip string, tag string) error {
+ fip, err := s.GetFloatingIP(ip)
+ if err != nil {
+ return err
+ }
+ if fip == nil {
+ return nil
+ }
+
+ mc := metrics.NewMetricPrometheusContext("floating_ip", "update")
+ _, err = s.client.ReplaceAllAttributesTags("floatingips", fip.ID, attributestags.ReplaceAllOpts{
+ Tags: []string{tag},
+ })
+ if mc.ObserveRequest(err) != nil {
+ return err
+ }
+ return nil
+}
+
+func (s *Service) GetFloatingIPsByTag(tag string) ([]floatingips.FloatingIP, error) {
+ fipList, err := s.client.ListFloatingIP(floatingips.ListOpts{Tags: tag})
+ if err != nil {
+ return nil, err
+ }
+ return fipList, nil
+}
+
func (s *Service) GetFloatingIP(ip string) (*floatingips.FloatingIP, error) {
fpList, err := s.client.ListFloatingIP(floatingips.ListOpts{FloatingIP: ip})
if err != nil {
diff --git a/pkg/scope/mock.go b/pkg/scope/mock.go
index b4025c63d2..7dd2364b92 100644
--- a/pkg/scope/mock.go
+++ b/pkg/scope/mock.go
@@ -25,6 +25,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/identity/v3/tokens"
"sigs.k8s.io/controller-runtime/pkg/client"
+ "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha1"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/mock"
@@ -80,6 +81,13 @@ func (f *MockScopeFactory) NewClientScopeFromCluster(_ context.Context, _ client
return f, nil
}
+func (f *MockScopeFactory) NewClientScopeFromFloatingIPPool(_ context.Context, _ client.Client, _ *v1alpha1.OpenStackFloatingIPPool, _ []byte, _ logr.Logger) (Scope, error) {
+ if f.clientScopeCreateError != nil {
+ return nil, f.clientScopeCreateError
+ }
+ return f, nil
+}
+
func (f *MockScopeFactory) NewComputeClient() (clients.ComputeClient, error) {
return f.ComputeClient, nil
}
diff --git a/pkg/scope/provider.go b/pkg/scope/provider.go
index 991b5f4805..e7a060d3f4 100644
--- a/pkg/scope/provider.go
+++ b/pkg/scope/provider.go
@@ -37,6 +37,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/yaml"
+ "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha1"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/hash"
@@ -104,6 +105,29 @@ func (f *providerScopeFactory) NewClientScopeFromCluster(ctx context.Context, ct
return NewCachedProviderScope(f.clientCache, cloud, caCert, logger)
}
+func (f *providerScopeFactory) NewClientScopeFromFloatingIPPool(ctx context.Context, ctrlClient client.Client, openstackFloatingIPPool *v1alpha1.OpenStackFloatingIPPool, defaultCACert []byte, logger logr.Logger) (Scope, error) {
+ var cloud clientconfig.Cloud
+ var caCert []byte
+
+ if openstackFloatingIPPool.Spec.IdentityRef != nil {
+ var err error
+ cloud, caCert, err = getCloudFromSecret(ctx, ctrlClient, openstackFloatingIPPool.Namespace, openstackFloatingIPPool.Spec.IdentityRef.Name, openstackFloatingIPPool.Spec.CloudName)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ if caCert == nil {
+ caCert = defaultCACert
+ }
+
+ if f.clientCache == nil {
+ return NewProviderScope(cloud, caCert, logger)
+ }
+
+ return NewCachedProviderScope(f.clientCache, cloud, caCert, logger)
+}
+
func getScopeCacheKey(cloud clientconfig.Cloud) (string, error) {
key, err := hash.ComputeSpewHash(cloud)
if err != nil {
diff --git a/pkg/scope/scope.go b/pkg/scope/scope.go
index d7458152fb..5c8f24b968 100644
--- a/pkg/scope/scope.go
+++ b/pkg/scope/scope.go
@@ -24,6 +24,7 @@ import (
"k8s.io/apimachinery/pkg/util/cache"
"sigs.k8s.io/controller-runtime/pkg/client"
+ "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha1"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients"
)
@@ -43,6 +44,7 @@ func NewFactory(maxCacheSize int) Factory {
type Factory interface {
NewClientScopeFromMachine(ctx context.Context, ctrlClient client.Client, openStackMachine *infrav1.OpenStackMachine, openStackCluster *infrav1.OpenStackCluster, defaultCACert []byte, logger logr.Logger) (Scope, error)
NewClientScopeFromCluster(ctx context.Context, ctrlClient client.Client, openStackCluster *infrav1.OpenStackCluster, defaultCACert []byte, logger logr.Logger) (Scope, error)
+ NewClientScopeFromFloatingIPPool(ctx context.Context, ctrlClient client.Client, openStackCluster *v1alpha1.OpenStackFloatingIPPool, defaultCACert []byte, logger logr.Logger) (Scope, error)
}
// Scope contains arguments common to most operations.
diff --git a/pkg/utils/ipam/predicates.go b/pkg/utils/ipam/predicates.go
new file mode 100644
index 0000000000..43f3d3fb10
--- /dev/null
+++ b/pkg/utils/ipam/predicates.go
@@ -0,0 +1,96 @@
+/*
+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 ipam
+
+import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ ipamv1 "sigs.k8s.io/cluster-api/exp/ipam/api/v1beta1"
+ "sigs.k8s.io/controller-runtime/pkg/client"
+ "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
+ "sigs.k8s.io/controller-runtime/pkg/event"
+ "sigs.k8s.io/controller-runtime/pkg/predicate"
+)
+
+func processIfClaimReferencesPoolKind(gk metav1.GroupKind, obj client.Object) bool {
+ var claim *ipamv1.IPAddressClaim
+ var ok bool
+ if claim, ok = obj.(*ipamv1.IPAddressClaim); !ok {
+ return false
+ }
+
+ if claim.Spec.PoolRef.Kind != gk.Kind || claim.Spec.PoolRef.APIGroup == nil || *claim.Spec.PoolRef.APIGroup != gk.Group {
+ return false
+ }
+
+ return true
+}
+
+// ClaimReferencesPoolKind is a predicate that ensures an ipamv1.IPAddressClaim references a specified pool kind.
+func ClaimReferencesPoolKind(gk metav1.GroupKind) predicate.Funcs {
+ return predicate.Funcs{
+ CreateFunc: func(e event.CreateEvent) bool {
+ return processIfClaimReferencesPoolKind(gk, e.Object)
+ },
+ DeleteFunc: func(e event.DeleteEvent) bool {
+ return processIfClaimReferencesPoolKind(gk, e.Object)
+ },
+ UpdateFunc: func(e event.UpdateEvent) bool {
+ return processIfClaimReferencesPoolKind(gk, e.ObjectNew)
+ },
+ GenericFunc: func(e event.GenericEvent) bool {
+ return processIfClaimReferencesPoolKind(gk, e.Object)
+ },
+ }
+}
+
+func processIfAddressReferencesPoolKind(gk metav1.GroupKind, obj client.Object) bool {
+ var addr *ipamv1.IPAddress
+ var ok bool
+ if addr, ok = obj.(*ipamv1.IPAddress); !ok {
+ return false
+ }
+
+ if addr.Spec.PoolRef.Kind != gk.Kind || addr.Spec.PoolRef.APIGroup == nil || *addr.Spec.PoolRef.APIGroup != gk.Group {
+ return false
+ }
+
+ return true
+}
+
+// AddressReferencesPoolKind is a predicate that ensures an ipamv1.IPAddress references a specified pool kind.
+func AddressReferencesPoolKind(gk metav1.GroupKind) predicate.Funcs {
+ return predicate.Funcs{
+ CreateFunc: func(e event.CreateEvent) bool {
+ return processIfAddressReferencesPoolKind(gk, e.Object)
+ },
+ DeleteFunc: func(e event.DeleteEvent) bool {
+ return processIfAddressReferencesPoolKind(gk, e.Object)
+ },
+ UpdateFunc: func(e event.UpdateEvent) bool {
+ return processIfAddressReferencesPoolKind(gk, e.ObjectNew)
+ },
+ GenericFunc: func(e event.GenericEvent) bool {
+ return processIfAddressReferencesPoolKind(gk, e.Object)
+ },
+ }
+}
+
+func HasFinalizerAndIsDeleting(finalizer string) predicate.Funcs {
+ return predicate.NewPredicateFuncs(func(obj client.Object) bool {
+ return !obj.GetDeletionTimestamp().IsZero() && controllerutil.ContainsFinalizer(obj, finalizer)
+ })
+}
From 341f2fbb73b04653e24180b8e51d229e29cc1a69 Mon Sep 17 00:00:00 2001
From: Maysa Macedo
Date: Tue, 12 Dec 2023 10:35:52 -0300
Subject: [PATCH 037/180] Support BYO dual-stack Network
This commit adds support to specify more than one
existent subnet on the `OpenStackCluster`. The existent
`OpenStackClusterSpec.Subnet` is removed in favor
of `OpenStackClusterSpec.Subnets`.
Co-Authored-By: Emilien Macchi
---
api/v1alpha5/conversion.go | 17 +++
api/v1alpha5/conversion_test.go | 4 +-
api/v1alpha5/zz_generated.conversion.go | 8 +-
api/v1alpha6/conversion.go | 15 +++
api/v1alpha6/zz_generated.conversion.go | 8 +-
api/v1alpha7/conversion.go | 15 +++
api/v1alpha7/zz_generated.conversion.go | 8 +-
api/v1alpha8/openstackcluster_types.go | 5 +-
api/v1alpha8/zz_generated.deepcopy.go | 6 +-
...re.cluster.x-k8s.io_openstackclusters.yaml | 63 +++++------
...er.x-k8s.io_openstackclustertemplates.yaml | 63 +++++------
controllers/openstackcluster_controller.go | 62 ++++++++---
.../openstackcluster_controller_test.go | 68 ++++++++++++
pkg/cloud/services/networking/network.go | 12 +++
pkg/cloud/services/networking/network_test.go | 42 ++++++++
pkg/utils/controllers/controllers.go | 48 +++++++++
pkg/utils/controllers/controllers_test.go | 101 ++++++++++++++++++
17 files changed, 447 insertions(+), 98 deletions(-)
create mode 100644 pkg/utils/controllers/controllers.go
create mode 100644 pkg/utils/controllers/controllers_test.go
diff --git a/api/v1alpha5/conversion.go b/api/v1alpha5/conversion.go
index b4855587e0..ddaf5d71ab 100644
--- a/api/v1alpha5/conversion.go
+++ b/api/v1alpha5/conversion.go
@@ -196,6 +196,14 @@ func Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(in *
out.ExternalNetworkID = in.ExternalNetwork.ID
}
+ if in.Subnets != nil {
+ if len(in.Subnets) >= 1 {
+ if err := Convert_v1alpha8_SubnetFilter_To_v1alpha5_SubnetFilter(&in.Subnets[0], &out.Subnet, s); err != nil {
+ return err
+ }
+ }
+ }
+
return nil
}
@@ -211,6 +219,15 @@ func Convert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *
}
}
+ emptySubnet := SubnetFilter{}
+ if in.Subnet != emptySubnet {
+ subnet := infrav1.SubnetFilter{}
+ if err := Convert_v1alpha5_SubnetFilter_To_v1alpha8_SubnetFilter(&in.Subnet, &subnet, s); err != nil {
+ return err
+ }
+ out.Subnets = []infrav1.SubnetFilter{subnet}
+ }
+
return nil
}
diff --git a/api/v1alpha5/conversion_test.go b/api/v1alpha5/conversion_test.go
index f8ad758fca..e4357782c4 100644
--- a/api/v1alpha5/conversion_test.go
+++ b/api/v1alpha5/conversion_test.go
@@ -49,7 +49,7 @@ func TestConvertFrom(t *testing.T) {
Spec: OpenStackClusterSpec{},
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
- "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"allowAllInClusterTraffic\":false,\"apiServerLoadBalancer\":{},\"cloudName\":\"\",\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"disableExternalNetwork\":false,\"externalNetwork\":{},\"managedSecurityGroups\":false,\"network\":{},\"subnet\":{}},\"status\":{\"ready\":false}}",
+ "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"allowAllInClusterTraffic\":false,\"apiServerLoadBalancer\":{},\"cloudName\":\"\",\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"disableExternalNetwork\":false,\"externalNetwork\":{},\"managedSecurityGroups\":false,\"network\":{}},\"status\":{\"ready\":false}}",
},
},
},
@@ -64,7 +64,7 @@ func TestConvertFrom(t *testing.T) {
Spec: OpenStackClusterTemplateSpec{},
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,\"disableExternalNetwork\":false,\"externalNetwork\":{},\"managedSecurityGroups\":false,\"network\":{},\"subnet\":{}}}}}",
+ "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"template\":{\"spec\":{\"allowAllInClusterTraffic\":false,\"apiServerLoadBalancer\":{},\"cloudName\":\"\",\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"disableExternalNetwork\":false,\"externalNetwork\":{},\"managedSecurityGroups\":false,\"network\":{}}}}}",
},
},
},
diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go
index af5bc6fcbf..b10bd71be9 100644
--- a/api/v1alpha5/zz_generated.conversion.go
+++ b/api/v1alpha5/zz_generated.conversion.go
@@ -659,9 +659,7 @@ func autoConvert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(
if err := Convert_v1alpha5_NetworkFilter_To_v1alpha8_NetworkFilter(&in.Network, &out.Network, s); err != nil {
return err
}
- if err := Convert_v1alpha5_SubnetFilter_To_v1alpha8_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil {
- return err
- }
+ // WARNING: in.Subnet 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
@@ -708,9 +706,7 @@ func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(
if err := Convert_v1alpha8_NetworkFilter_To_v1alpha5_NetworkFilter(&in.Network, &out.Network, s); err != nil {
return err
}
- if err := Convert_v1alpha8_SubnetFilter_To_v1alpha5_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil {
- return err
- }
+ // 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 {
diff --git a/api/v1alpha6/conversion.go b/api/v1alpha6/conversion.go
index 2e2000cfd4..dfee3a6290 100644
--- a/api/v1alpha6/conversion.go
+++ b/api/v1alpha6/conversion.go
@@ -486,6 +486,12 @@ func Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(in *
out.ExternalNetworkID = in.ExternalNetwork.ID
}
+ if len(in.Subnets) >= 1 {
+ if err := Convert_v1alpha8_SubnetFilter_To_v1alpha6_SubnetFilter(&in.Subnets[0], &out.Subnet, s); err != nil {
+ return err
+ }
+ }
+
return nil
}
@@ -501,6 +507,15 @@ func Convert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *
}
}
+ emptySubnet := SubnetFilter{}
+ if in.Subnet != emptySubnet {
+ subnet := infrav1.SubnetFilter{}
+ if err := Convert_v1alpha6_SubnetFilter_To_v1alpha8_SubnetFilter(&in.Subnet, &subnet, s); err != nil {
+ return err
+ }
+ out.Subnets = []infrav1.SubnetFilter{subnet}
+ }
+
return nil
}
diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go
index 8a00f25e45..41761e8db2 100644
--- a/api/v1alpha6/zz_generated.conversion.go
+++ b/api/v1alpha6/zz_generated.conversion.go
@@ -681,9 +681,7 @@ func autoConvert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(
if err := Convert_v1alpha6_NetworkFilter_To_v1alpha8_NetworkFilter(&in.Network, &out.Network, s); err != nil {
return err
}
- if err := Convert_v1alpha6_SubnetFilter_To_v1alpha8_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil {
- return err
- }
+ // WARNING: in.Subnet 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
@@ -731,9 +729,7 @@ func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(
if err := Convert_v1alpha8_NetworkFilter_To_v1alpha6_NetworkFilter(&in.Network, &out.Network, s); err != nil {
return err
}
- if err := Convert_v1alpha8_SubnetFilter_To_v1alpha6_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil {
- return err
- }
+ // 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 {
diff --git a/api/v1alpha7/conversion.go b/api/v1alpha7/conversion.go
index 31862c3f86..fe58245113 100644
--- a/api/v1alpha7/conversion.go
+++ b/api/v1alpha7/conversion.go
@@ -383,6 +383,15 @@ func Convert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *
}
}
+ emptySubnet := SubnetFilter{}
+ if in.Subnet != emptySubnet {
+ subnet := infrav1.SubnetFilter{}
+ if err := Convert_v1alpha7_SubnetFilter_To_v1alpha8_SubnetFilter(&in.Subnet, &subnet, s); err != nil {
+ return err
+ }
+ out.Subnets = []infrav1.SubnetFilter{subnet}
+ }
+
return nil
}
@@ -396,5 +405,11 @@ func Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in *
out.ExternalNetworkID = in.ExternalNetwork.ID
}
+ if len(in.Subnets) >= 1 {
+ if err := Convert_v1alpha8_SubnetFilter_To_v1alpha7_SubnetFilter(&in.Subnets[0], &out.Subnet, s); err != nil {
+ return err
+ }
+ }
+
return nil
}
diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go
index 2df0972e6e..773d9892fd 100644
--- a/api/v1alpha7/zz_generated.conversion.go
+++ b/api/v1alpha7/zz_generated.conversion.go
@@ -882,9 +882,7 @@ func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(
if err := Convert_v1alpha7_NetworkFilter_To_v1alpha8_NetworkFilter(&in.Network, &out.Network, s); err != nil {
return err
}
- if err := Convert_v1alpha7_SubnetFilter_To_v1alpha8_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil {
- return err
- }
+ // WARNING: in.Subnet requires manual conversion: does not exist in peer-type
out.NetworkMTU = in.NetworkMTU
out.DNSNameservers = *(*[]string)(unsafe.Pointer(&in.DNSNameservers))
out.ExternalRouterIPs = *(*[]v1alpha8.ExternalRouterIPParam)(unsafe.Pointer(&in.ExternalRouterIPs))
@@ -923,9 +921,7 @@ func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(
if err := Convert_v1alpha8_NetworkFilter_To_v1alpha7_NetworkFilter(&in.Network, &out.Network, s); err != nil {
return err
}
- if err := Convert_v1alpha8_SubnetFilter_To_v1alpha7_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil {
- return err
- }
+ // WARNING: in.Subnets requires manual conversion: does not exist in peer-type
out.NetworkMTU = in.NetworkMTU
out.DNSNameservers = *(*[]string)(unsafe.Pointer(&in.DNSNameservers))
out.ExternalRouterIPs = *(*[]ExternalRouterIPParam)(unsafe.Pointer(&in.ExternalRouterIPs))
diff --git a/api/v1alpha8/openstackcluster_types.go b/api/v1alpha8/openstackcluster_types.go
index b0b6aaabcf..7430fab1ab 100644
--- a/api/v1alpha8/openstackcluster_types.go
+++ b/api/v1alpha8/openstackcluster_types.go
@@ -47,8 +47,9 @@ type OpenStackClusterSpec struct {
// If NodeCIDR cannot be set this can be used to detect an existing network.
Network NetworkFilter `json:"network,omitempty"`
- // If NodeCIDR cannot be set this can be used to detect an existing subnet.
- Subnet SubnetFilter `json:"subnet,omitempty"`
+ // If NodeCIDR cannot be set this can be used to detect existing IPv4 and/or IPv6 subnets.
+ // +kubebuilder:validation:MaxItems=2
+ Subnets []SubnetFilter `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.
diff --git a/api/v1alpha8/zz_generated.deepcopy.go b/api/v1alpha8/zz_generated.deepcopy.go
index 6598146562..eebb59993e 100644
--- a/api/v1alpha8/zz_generated.deepcopy.go
+++ b/api/v1alpha8/zz_generated.deepcopy.go
@@ -372,7 +372,11 @@ func (in *OpenStackClusterSpec) DeepCopyInto(out *OpenStackClusterSpec) {
**out = **in
}
out.Network = in.Network
- out.Subnet = in.Subnet
+ if in.Subnets != nil {
+ in, out := &in.Subnets, &out.Subnets
+ *out = make([]SubnetFilter, len(*in))
+ copy(*out, *in)
+ }
if in.DNSNameservers != nil {
in, out := &in.DNSNameservers, &out.DNSNameservers
*out = make([]string, len(*in))
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 c22d9fcea5..00b1ba6cc9 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -5507,37 +5507,40 @@ spec:
tagsAny:
type: string
type: object
- subnet:
+ subnets:
description: If NodeCIDR cannot be set this can be used to detect
- an existing subnet.
- properties:
- cidr:
- type: string
- description:
- type: string
- gateway_ip:
- type: string
- id:
- type: string
- ipVersion:
- type: integer
- ipv6AddressMode:
- type: string
- ipv6RaMode:
- type: string
- name:
- type: string
- notTags:
- type: string
- notTagsAny:
- type: string
- projectId:
- type: string
- tags:
- type: string
- tagsAny:
- type: string
- type: object
+ existing IPv4 and/or IPv6 subnets.
+ items:
+ properties:
+ cidr:
+ type: string
+ description:
+ type: string
+ gateway_ip:
+ type: string
+ id:
+ type: string
+ ipVersion:
+ type: integer
+ ipv6AddressMode:
+ type: string
+ ipv6RaMode:
+ type: string
+ name:
+ type: string
+ notTags:
+ type: string
+ notTagsAny:
+ type: string
+ projectId:
+ type: string
+ tags:
+ type: string
+ tagsAny:
+ type: string
+ type: object
+ maxItems: 2
+ type: array
tags:
description: Tags for all resources in cluster
items:
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 4f96c272aa..cb56c31021 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -2942,37 +2942,40 @@ spec:
tagsAny:
type: string
type: object
- subnet:
+ subnets:
description: If NodeCIDR cannot be set this can be used to
- detect an existing subnet.
- properties:
- cidr:
- type: string
- description:
- type: string
- gateway_ip:
- type: string
- id:
- type: string
- ipVersion:
- type: integer
- ipv6AddressMode:
- type: string
- ipv6RaMode:
- type: string
- name:
- type: string
- notTags:
- type: string
- notTagsAny:
- type: string
- projectId:
- type: string
- tags:
- type: string
- tagsAny:
- type: string
- type: object
+ detect existing IPv4 and/or IPv6 subnets.
+ items:
+ properties:
+ cidr:
+ type: string
+ description:
+ type: string
+ gateway_ip:
+ type: string
+ id:
+ type: string
+ ipVersion:
+ type: integer
+ ipv6AddressMode:
+ type: string
+ ipv6RaMode:
+ type: string
+ name:
+ type: string
+ notTags:
+ type: string
+ notTagsAny:
+ type: string
+ projectId:
+ type: string
+ tags:
+ type: string
+ tagsAny:
+ type: string
+ type: object
+ maxItems: 2
+ type: array
tags:
description: Tags for all resources in cluster
items:
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index e954631e1d..3b2c5f1110 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -49,6 +49,7 @@ import (
"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"
)
const (
@@ -516,26 +517,15 @@ func reconcileNetworkComponents(scope scope.Scope, cluster *clusterv1.Cluster, o
openStackCluster.Status.Network.Name = networkList[0].Name
openStackCluster.Status.Network.Tags = networkList[0].Tags
- subnet, err := networkingService.GetNetworkSubnetByFilter(openStackCluster.Status.Network.ID, &openStackCluster.Spec.Subnet)
+ subnets, err := filterSubnets(networkingService, openStackCluster)
if err != nil {
- err = fmt.Errorf("failed to find subnet: %w", err)
-
- // Set the cluster to failed if subnet filter is invalid
- if errors.Is(err, networking.ErrFilterMatch) {
- handleUpdateOSCError(openStackCluster, err)
- }
-
return err
}
- openStackCluster.Status.Network.Subnets = []infrav1.Subnet{
- {
- ID: subnet.ID,
- Name: subnet.Name,
- CIDR: subnet.CIDR,
- Tags: subnet.Tags,
- },
+ if err := utils.ValidateSubnets(subnets); err != nil {
+ return err
}
+ openStackCluster.Status.Network.Subnets = subnets
} else {
err := networkingService.ReconcileNetwork(openStackCluster, clusterName)
if err != nil {
@@ -682,3 +672,45 @@ func handleUpdateOSCError(openstackCluster *infrav1.OpenStackCluster, message er
openstackCluster.Status.FailureReason = &err
openstackCluster.Status.FailureMessage = pointer.String(message.Error())
}
+
+// filterSubnets retrieves the subnets based on the Subnet filters specified on OpenstackCluster.
+func filterSubnets(networkingService *networking.Service, openStackCluster *infrav1.OpenStackCluster) ([]infrav1.Subnet, error) {
+ var subnets []infrav1.Subnet
+ openStackClusterSubnets := openStackCluster.Spec.Subnets
+ if openStackCluster.Status.Network == nil {
+ return nil, nil
+ }
+ networkID := openStackCluster.Status.Network.ID
+ if len(openStackClusterSubnets) == 0 {
+ empty := &infrav1.SubnetFilter{}
+ listOpt := empty.ToListOpt()
+ listOpt.NetworkID = networkID
+ filteredSubnets, err := networkingService.GetSubnetsByFilter(listOpt)
+ 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(filteredSubnets) > 2 {
+ return nil, fmt.Errorf("more than two subnets found in the Network. Specify the subnets in the OpenStackCluster.Spec instead")
+ }
+ for subnet := range filteredSubnets {
+ subnets = networkingService.ConvertOpenStackSubnetToCAPOSubnet(subnets, &filteredSubnets[subnet])
+ }
+ } else {
+ for subnet := range openStackClusterSubnets {
+ filteredSubnet, err := networkingService.GetNetworkSubnetByFilter(networkID, &openStackClusterSubnets[subnet])
+ if err != nil {
+ err = fmt.Errorf("failed to find subnet: %w", err)
+ if errors.Is(err, networking.ErrFilterMatch) {
+ handleUpdateOSCError(openStackCluster, err)
+ }
+ return nil, err
+ }
+ subnets = networkingService.ConvertOpenStackSubnetToCAPOSubnet(subnets, filteredSubnet)
+ }
+ }
+ return subnets, nil
+}
diff --git a/controllers/openstackcluster_controller_test.go b/controllers/openstackcluster_controller_test.go
index 5cf980b024..f45e5d8431 100644
--- a/controllers/openstackcluster_controller_test.go
+++ b/controllers/openstackcluster_controller_test.go
@@ -450,6 +450,74 @@ 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{
+ DisableAPIServerFloatingIP: true,
+ APIServerFixedIP: "10.0.0.1",
+ ExternalNetwork: infrav1.NetworkFilter{
+ ID: externalNetworkID,
+ },
+ Network: infrav1.NetworkFilter{
+ ID: clusterNetworkID,
+ },
+ Subnets: []infrav1.SubnetFilter{
+ {ID: clusterSubnets[0]},
+ {ID: clusterSubnets[1]},
+ },
+ }
+ 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())
+ Expect(err).To(BeNil())
+
+ networkClientRecorder := mockScopeFactory.NetworkClient.EXPECT()
+
+ // Fetch external network
+ networkClientRecorder.ListNetwork(external.ListOptsExt{
+ ListOptsBuilder: networks.ListOpts{
+ ID: 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",
+ },
+ }, nil)
+
+ networkClientRecorder.GetSubnet(clusterSubnets[0]).Return(&subnets.Subnet{
+ ID: clusterSubnets[0],
+ Name: "cluster-subnet",
+ CIDR: "192.168.0.0/24",
+ }, nil)
+
+ networkClientRecorder.GetSubnet(clusterSubnets[1]).Return(&subnets.Subnet{
+ ID: clusterSubnets[1],
+ 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))
+ })
})
func createRequestFromOSCluster(openStackCluster *infrav1.OpenStackCluster) reconcile.Request {
diff --git a/pkg/cloud/services/networking/network.go b/pkg/cloud/services/networking/network.go
index 601ac70a79..5eaf691471 100644
--- a/pkg/cloud/services/networking/network.go
+++ b/pkg/cloud/services/networking/network.go
@@ -383,3 +383,15 @@ func getSubnetName(clusterName string) string {
func getNetworkName(clusterName string) string {
return fmt.Sprintf("%s-cluster-%s", networkPrefix, clusterName)
}
+
+// ConvertOpenStackSubnetToCAPOSubnet converts an OpenStack subnet to a capo subnet and adds to a slice.
+// It returns the slice with the converted subnet.
+func (s *Service) ConvertOpenStackSubnetToCAPOSubnet(subnets []infrav1.Subnet, filteredSubnet *subnets.Subnet) []infrav1.Subnet {
+ subnets = append(subnets, infrav1.Subnet{
+ ID: filteredSubnet.ID,
+ Name: filteredSubnet.Name,
+ CIDR: filteredSubnet.CIDR,
+ Tags: filteredSubnet.Tags,
+ })
+ return subnets
+}
diff --git a/pkg/cloud/services/networking/network_test.go b/pkg/cloud/services/networking/network_test.go
index 47ff27783a..512cc53146 100644
--- a/pkg/cloud/services/networking/network_test.go
+++ b/pkg/cloud/services/networking/network_test.go
@@ -17,6 +17,7 @@ limitations under the License.
package networking
import (
+ "reflect"
"testing"
"github.com/go-logr/logr"
@@ -24,6 +25,7 @@ import (
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external"
"github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
. "github.com/onsi/gomega"
"k8s.io/utils/pointer"
@@ -420,3 +422,43 @@ func Test_ReconcileExternalNetwork(t *testing.T) {
})
}
}
+
+func Test_ConvertOpenStackSubnetToCAPOSubnet(t *testing.T) {
+ caposubnets := []infrav1.Subnet{
+ {
+ ID: "subnet1",
+ Name: "subnet1",
+ CIDR: "10.0.0.0/24",
+ Tags: []string{"tag1", "tag2"},
+ },
+ }
+
+ filteredSubnet := &subnets.Subnet{
+ ID: "subnet2",
+ Name: "subnet2",
+ CIDR: "192.168.0.0/24",
+ Tags: []string{"tag3", "tag4"},
+ }
+
+ s := Service{}
+ result := s.ConvertOpenStackSubnetToCAPOSubnet(caposubnets, filteredSubnet)
+
+ expected := []infrav1.Subnet{
+ {
+ ID: "subnet1",
+ Name: "subnet1",
+ CIDR: "10.0.0.0/24",
+ Tags: []string{"tag1", "tag2"},
+ },
+ {
+ ID: "subnet2",
+ Name: "subnet2",
+ CIDR: "192.168.0.0/24",
+ Tags: []string{"tag3", "tag4"},
+ },
+ }
+
+ if !reflect.DeepEqual(result, expected) {
+ t.Errorf("ConvertOpenStackSubnetToCAPOSubnet() = %v, want %v", result, expected)
+ }
+}
diff --git a/pkg/utils/controllers/controllers.go b/pkg/utils/controllers/controllers.go
new file mode 100644
index 0000000000..94dfb11ac4
--- /dev/null
+++ b/pkg/utils/controllers/controllers.go
@@ -0,0 +1,48 @@
+/*
+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 controllers
+
+import (
+ "fmt"
+ "net"
+
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+)
+
+// ValidateSubnets validates if the amount of IPv4 and IPv6 subnets is allowed by OpenStackCluster.
+func ValidateSubnets(subnets []infrav1.Subnet) error {
+ isIPv6 := []bool{false, false}
+ for i, subnet := range subnets {
+ ip, _, err := net.ParseCIDR(subnet.CIDR)
+ if err != nil {
+ return err
+ }
+
+ if ip.To4() == nil {
+ isIPv6[i] = true
+ }
+ }
+
+ if len(subnets) > 1 && isIPv6[0] == isIPv6[1] {
+ ethertype := 4
+ if isIPv6[0] {
+ ethertype = 6
+ }
+ return fmt.Errorf("multiple IPv%d Subnet not allowed on OpenStackCluster", ethertype)
+ }
+ return nil
+}
diff --git a/pkg/utils/controllers/controllers_test.go b/pkg/utils/controllers/controllers_test.go
new file mode 100644
index 0000000000..eadff95b77
--- /dev/null
+++ b/pkg/utils/controllers/controllers_test.go
@@ -0,0 +1,101 @@
+/*
+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 controllers
+
+import (
+ "testing"
+
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+)
+
+func Test_validateSubnets(t *testing.T) {
+ tests := []struct {
+ name string
+ subnets []infrav1.Subnet
+ wantErr bool
+ }{
+ {
+ name: "valid IPv4 and IPv6 subnets",
+ subnets: []infrav1.Subnet{
+ {
+ CIDR: "192.168.0.0/24",
+ },
+ {
+ CIDR: "2001:db8:2222:5555::/64",
+ },
+ },
+ wantErr: false,
+ },
+ {
+ name: "valid IPv4 and IPv6 subnets",
+ subnets: []infrav1.Subnet{
+ {
+ CIDR: "2001:db8:2222:5555::/64",
+ },
+ {
+ CIDR: "192.168.0.0/24",
+ },
+ },
+ wantErr: false,
+ },
+ {
+ name: "multiple IPv4 subnets",
+ subnets: []infrav1.Subnet{
+ {
+ CIDR: "192.168.0.0/24",
+ },
+ {
+ CIDR: "10.0.0.0/24",
+ },
+ },
+ wantErr: true,
+ },
+ {
+ name: "multiple IPv6 subnets",
+ subnets: []infrav1.Subnet{
+ {
+ CIDR: "2001:db8:2222:5555::/64",
+ },
+ {
+ CIDR: "2001:db8:2222:5555::/64",
+ },
+ },
+ wantErr: true,
+ },
+ {
+ name: "invalid IP address",
+ subnets: []infrav1.Subnet{
+ {
+ CIDR: "192.168.0.0/24",
+ },
+ {
+ CIDR: "invalid",
+ },
+ },
+ wantErr: true,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ err := ValidateSubnets(tt.subnets)
+ if (err != nil) != tt.wantErr {
+ t.Errorf("validateSubnets() error = %v, wantErr %v", err, tt.wantErr)
+ }
+ })
+ }
+}
From 29b3a888d42ad06dba49a09aa63229594b5a6929 Mon Sep 17 00:00:00 2001
From: Maysa Macedo
Date: Wed, 20 Dec 2023 11:07:25 -0300
Subject: [PATCH 038/180] Document BYO dual-stack network
This commit adds a section to the book explaining the
modification of the `OpenStackClusterSpec.Subnet` API field.
---
.../crd-changes/v1alpha7-to-v1alpha8.md | 21 +++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md b/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md
index 512f61d83a..efcf44d169 100644
--- a/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md
+++ b/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md
@@ -12,6 +12,7 @@
- [Changes to image](#change-to-image)
- [Removal of imageUUID](#removal-of-imageuuid)
- [Change to floatingIP](#change-to-floatingip)
+ - [Change to subnet](#change-to-subnet)
@@ -156,3 +157,23 @@ spec:
bastion:
floatingIP: "1.2.3.4"
```
+
+#### ⚠️ Change to subnet
+
+In v1alpha8, `Subnet` of `OpenStackCluster` is modified to `Subnets` to allow specification of two existent subnets for the dual-stack scenario.
+
+```yaml
+ subnet:
+ id: a532beb0-c73a-4b5d-af66-3ad05b73d063
+```
+
+In v1alpha8, this will be automatically converted to:
+
+```yaml
+ subnets:
+ - id: a532beb0-c73a-4b5d-af66-3ad05b73d063
+```
+
+`Subnets` allows specifications of maximum two `SubnetFilter` one being IPv4 and the other IPv6. Both subnets must be on the same network. Any filtered subnets will be added to `OpenStackCluster.Status.Network.Subnets`.
+
+When subnets are not specified on `OpenStackCluster` and only the network is, the network is used to identify the subnets to use. If more than two subnets exist in the network, the user must specify which ones to use by defining the `OpenStackCluster.Spec.Subnets` field.
\ No newline at end of file
From 2ef8ee555ebb4b9ed4ef642cabcb6cb9ab366bd1 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Wed, 17 Jan 2024 11:29:52 +0000
Subject: [PATCH 039/180] Dual-stack: ensure fuzzer tests multiple subnets
---
api/v1alpha6/conversion.go | 18 ++++++++++++++++++
api/v1alpha6/conversion_test.go | 21 +++++++++++++++++++++
api/v1alpha7/conversion.go | 4 ++++
api/v1alpha7/conversion_test.go | 32 ++++++++++++++++++++++++++++++++
4 files changed, 75 insertions(+)
diff --git a/api/v1alpha6/conversion.go b/api/v1alpha6/conversion.go
index dfee3a6290..c2170b980b 100644
--- a/api/v1alpha6/conversion.go
+++ b/api/v1alpha6/conversion.go
@@ -75,6 +75,12 @@ func restorev1alpha8Bastion(previous **infrav1.Bastion, dst **infrav1.Bastion) {
}
}
+func restorev1alpha8Subnets(previous *[]infrav1.SubnetFilter, dst *[]infrav1.SubnetFilter) {
+ if len(*previous) > 1 {
+ *dst = append(*dst, (*previous)[1:]...)
+ }
+}
+
func restorev1alpha8ClusterStatus(previous *infrav1.OpenStackClusterStatus, dst *infrav1.OpenStackClusterStatus) {
// It's (theoretically) possible in v1alpha8 to have Network nil but
// Router or APIServerLoadBalancer not nil. In hub-spoke-hub conversion this will
@@ -154,6 +160,12 @@ var v1alpha8OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStack
},
restorev1alpha8Bastion,
),
+ "subnets": conversion.HashedFieldRestorer(
+ func(c *infrav1.OpenStackCluster) *[]infrav1.SubnetFilter {
+ return &c.Spec.Subnets
+ },
+ restorev1alpha8Subnets,
+ ),
"status": conversion.HashedFieldRestorer(
func(c *infrav1.OpenStackCluster) *infrav1.OpenStackClusterStatus {
return &c.Status
@@ -234,6 +246,12 @@ var v1alpha8OpenStackClusterTemplateRestorer = conversion.RestorerFor[*infrav1.O
},
restorev1alpha8Bastion,
),
+ "subnets": conversion.HashedFieldRestorer(
+ func(c *infrav1.OpenStackClusterTemplate) *[]infrav1.SubnetFilter {
+ return &c.Spec.Template.Spec.Subnets
+ },
+ restorev1alpha8Subnets,
+ ),
}
func (r *OpenStackClusterTemplate) ConvertTo(dstRaw ctrlconversion.Hub) error {
diff --git a/api/v1alpha6/conversion_test.go b/api/v1alpha6/conversion_test.go
index 7f67ad9ef9..2099a1467d 100644
--- a/api/v1alpha6/conversion_test.go
+++ b/api/v1alpha6/conversion_test.go
@@ -88,6 +88,19 @@ func TestFuzzyConversion(t *testing.T) {
status.ExternalNetwork.APIServerLoadBalancer = nil
}
},
+
+ func(spec *infrav1.OpenStackClusterSpec, c fuzz.Continue) {
+ c.FuzzNoCustom(spec)
+
+ // The fuzzer only seems to generate Subnets of
+ // length 1, but we need to also test length 2.
+ // Ensure it is occasionally generated.
+ if len(spec.Subnets) == 1 && c.RandBool() {
+ subnet := infrav1.SubnetFilter{}
+ c.FuzzNoCustom(&subnet)
+ spec.Subnets = append(spec.Subnets, subnet)
+ }
+ },
}
}
@@ -119,13 +132,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 +149,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 +166,9 @@ func TestFuzzyConversion(t *testing.T) {
Hub: &infrav1.OpenStackMachineTemplate{},
Spoke: &OpenStackMachineTemplate{},
HubAfterMutation: ignoreDataAnnotation,
+ FuzzerFuncs: []fuzzer.FuzzerFuncs{fuzzerFuncs},
},
+ MutateFuzzerFuncs: []fuzzer.FuzzerFuncs{fuzzerFuncs},
})))
}
diff --git a/api/v1alpha7/conversion.go b/api/v1alpha7/conversion.go
index fe58245113..e51c698e29 100644
--- a/api/v1alpha7/conversion.go
+++ b/api/v1alpha7/conversion.go
@@ -97,6 +97,10 @@ func restorev1alpha8ClusterSpec(previous *infrav1.OpenStackClusterSpec, dst *inf
dst.ExternalNetwork.NotTagsAny = previous.ExternalNetwork.NotTagsAny
dst.DisableExternalNetwork = previous.DisableExternalNetwork
+
+ if len(previous.Subnets) > 1 {
+ dst.Subnets = append(dst.Subnets, previous.Subnets[1:]...)
+ }
}
func (r *OpenStackCluster) ConvertTo(dstRaw ctrlconversion.Hub) error {
diff --git a/api/v1alpha7/conversion_test.go b/api/v1alpha7/conversion_test.go
index 8613db762b..d26546a9d8 100644
--- a/api/v1alpha7/conversion_test.go
+++ b/api/v1alpha7/conversion_test.go
@@ -19,9 +19,12 @@ package v1alpha7
import (
"testing"
+ 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"
utilconversion "sigs.k8s.io/cluster-api/util/conversion"
"sigs.k8s.io/controller-runtime/pkg/conversion"
@@ -52,10 +55,28 @@ func TestFuzzyConversion(t *testing.T) {
delete(obj.GetAnnotations(), utilconversion.DataAnnotation)
}
+ fuzzerFuncs := func(_ runtimeserializer.CodecFactory) []interface{} {
+ return []interface{}{
+ func(spec *infrav1.OpenStackClusterSpec, c fuzz.Continue) {
+ c.FuzzNoCustom(spec)
+
+ // The fuzzer only seems to generate Subnets of
+ // length 1, but we need to also test length 2.
+ // Ensure it is occasionally generated.
+ if len(spec.Subnets) == 1 && c.RandBool() {
+ subnet := infrav1.SubnetFilter{}
+ c.FuzzNoCustom(&subnet)
+ spec.Subnets = append(spec.Subnets, subnet)
+ }
+ },
+ }
+ }
+
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{
@@ -63,13 +84,16 @@ func TestFuzzyConversion(t *testing.T) {
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{
@@ -77,13 +101,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{
@@ -91,13 +118,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{
@@ -105,7 +135,9 @@ func TestFuzzyConversion(t *testing.T) {
Hub: &infrav1.OpenStackMachineTemplate{},
Spoke: &OpenStackMachineTemplate{},
HubAfterMutation: ignoreDataAnnotation,
+ FuzzerFuncs: []fuzzer.FuzzerFuncs{fuzzerFuncs},
},
+ MutateFuzzerFuncs: []fuzzer.FuzzerFuncs{fuzzerFuncs},
})))
}
From 7921be701fe9e491e4677586a732af990b833310 Mon Sep 17 00:00:00 2001
From: Emilien Macchi
Date: Fri, 19 Jan 2024 08:30:46 -0500
Subject: [PATCH 040/180] e2e: remove "allow-all-in-cluster-traffic" patch
The default rules should be sufficient for Calico which is used by e2e
clusters; let's remove the allow-all-in-cluster-traffic patch which
should not be needed.
---
test/e2e/data/kustomize/common-patches/ccm/kustomization.yaml | 4 ----
.../ccm/patch-allow-all-in-cluster-traffic.yaml | 4 ----
2 files changed, 8 deletions(-)
delete mode 100644 test/e2e/data/kustomize/common-patches/ccm/patch-allow-all-in-cluster-traffic.yaml
diff --git a/test/e2e/data/kustomize/common-patches/ccm/kustomization.yaml b/test/e2e/data/kustomize/common-patches/ccm/kustomization.yaml
index 07cf642d5d..ee38329dac 100644
--- a/test/e2e/data/kustomize/common-patches/ccm/kustomization.yaml
+++ b/test/e2e/data/kustomize/common-patches/ccm/kustomization.yaml
@@ -7,10 +7,6 @@ resources:
- ccm.yaml
patches:
-- target:
- kind: OpenStackCluster
- name: \${CLUSTER_NAME}
- path: patch-allow-all-in-cluster-traffic.yaml
- target:
kind: KubeadmControlPlane
name: \${CLUSTER_NAME}-control-plane
diff --git a/test/e2e/data/kustomize/common-patches/ccm/patch-allow-all-in-cluster-traffic.yaml b/test/e2e/data/kustomize/common-patches/ccm/patch-allow-all-in-cluster-traffic.yaml
deleted file mode 100644
index 240bc43cd0..0000000000
--- a/test/e2e/data/kustomize/common-patches/ccm/patch-allow-all-in-cluster-traffic.yaml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-- op: add
- path: /spec/allowAllInClusterTraffic
- value: true
From 42ca30ef9cdd685c9eacea391eca0ee1c5783b7e Mon Sep 17 00:00:00 2001
From: Emilien Macchi
Date: Tue, 23 Jan 2024 23:24:44 -0500
Subject: [PATCH 041/180] Fix returning non-empty reconcile result and error
---
controllers/openstackcluster_controller.go | 8 ++++----
controllers/openstackmachine_controller.go | 3 ++-
2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index 3b2c5f1110..e928b17847 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -25,6 +25,7 @@ import (
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"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
@@ -69,7 +70,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
@@ -108,9 +109,8 @@ 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)})
}
}()
diff --git a/controllers/openstackmachine_controller.go b/controllers/openstackmachine_controller.go
index 77104d804a..56d195d8eb 100644
--- a/controllers/openstackmachine_controller.go
+++ b/controllers/openstackmachine_controller.go
@@ -76,7 +76,7 @@ const (
// +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.
@@ -137,6 +137,7 @@ 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})
}
}()
From 26575b22c6b7859e09f392a2528c55c10fdcc436 Mon Sep 17 00:00:00 2001
From: Emilien Macchi
Date: Thu, 25 Jan 2024 16:12:19 -0500
Subject: [PATCH 042/180] Fill up OpenStack cluster ReferencedResources with
Image ID
---
controllers/openstackcluster_controller.go | 33 +++++------
.../openstackcluster_controller_test.go | 58 ++++++++++++++-----
2 files changed, 57 insertions(+), 34 deletions(-)
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index 3b2c5f1110..e7fa0908a9 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -119,6 +119,16 @@ func (r *OpenStackClusterReconciler) Reconcile(ctx context.Context, req ctrl.Req
return reconcile.Result{}, err
}
+ if openStackCluster.Spec.Bastion != nil && openStackCluster.Spec.Bastion.Enabled {
+ if openStackCluster.Status.Bastion == nil {
+ openStackCluster.Status.Bastion = &infrav1.BastionStatus{}
+ }
+ err = compute.ResolveReferencedMachineResources(scope, &openStackCluster.Spec.Bastion.Instance, &openStackCluster.Status.Bastion.ReferencedResources)
+ if err != nil {
+ return reconcile.Result{}, err
+ }
+ }
+
// Handle deleted clusters
if !openStackCluster.DeletionTimestamp.IsZero() {
return r.reconcileDelete(ctx, scope, cluster, openStackCluster)
@@ -253,11 +263,7 @@ func deleteBastion(scope scope.Scope, cluster *clusterv1.Cluster, openStackClust
}
}
- instanceSpec, err := bastionToInstanceSpec(openStackCluster, cluster.Name, computeService)
- if err != nil {
- return fmt.Errorf("failed to create bastion InstanceSpec: %w", err)
- }
-
+ instanceSpec := bastionToInstanceSpec(openStackCluster, cluster.Name)
if err = computeService.DeleteInstance(openStackCluster, openStackCluster, instanceStatus, instanceSpec); err != nil {
handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to delete bastion: %w", err))
return fmt.Errorf("failed to delete bastion: %w", err)
@@ -340,11 +346,7 @@ func reconcileBastion(scope scope.Scope, cluster *clusterv1.Cluster, openStackCl
return reconcile.Result{}, err
}
- instanceSpec, err := bastionToInstanceSpec(openStackCluster, cluster.Name, computeService)
- if err != nil {
- return reconcile.Result{}, fmt.Errorf("failed to create bastion InstanceSpec: %w", err)
- }
-
+ instanceSpec := bastionToInstanceSpec(openStackCluster, cluster.Name)
bastionHash, err := compute.HashInstanceSpec(instanceSpec)
if err != nil {
return reconcile.Result{}, fmt.Errorf("failed computing bastion hash from instance spec: %w", err)
@@ -435,17 +437,12 @@ func reconcileBastion(scope scope.Scope, cluster *clusterv1.Cluster, openStackCl
return ctrl.Result{}, nil
}
-func bastionToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, clusterName string, computeService *compute.Service) (*compute.InstanceSpec, error) {
- imageID, err := computeService.GetImageID(openStackCluster.Spec.Bastion.Instance.Image)
- if err != nil {
- return nil, fmt.Errorf("failed to get image ID for bastion: %w", err)
- }
-
+func bastionToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, clusterName string) *compute.InstanceSpec {
instanceSpec := &compute.InstanceSpec{
Name: bastionName(clusterName),
Flavor: openStackCluster.Spec.Bastion.Instance.Flavor,
SSHKeyName: openStackCluster.Spec.Bastion.Instance.SSHKeyName,
- ImageID: imageID,
+ ImageID: openStackCluster.Status.Bastion.ReferencedResources.ImageID,
FailureDomain: openStackCluster.Spec.Bastion.AvailabilityZone,
RootVolume: openStackCluster.Spec.Bastion.Instance.RootVolume,
}
@@ -461,7 +458,7 @@ func bastionToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, clusterNa
instanceSpec.Ports = openStackCluster.Spec.Bastion.Instance.Ports
- return instanceSpec, nil
+ return instanceSpec
}
func bastionName(clusterName string) string {
diff --git a/controllers/openstackcluster_controller_test.go b/controllers/openstackcluster_controller_test.go
index f45e5d8431..b512ac62f4 100644
--- a/controllers/openstackcluster_controller_test.go
+++ b/controllers/openstackcluster_controller_test.go
@@ -25,7 +25,6 @@ import (
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/attachinterfaces"
"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/external"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips"
@@ -234,6 +233,11 @@ var _ = Describe("OpenStackCluster controller", func() {
err = k8sClient.Create(ctx, capiCluster)
Expect(err).To(BeNil())
testCluster.Status = infrav1.OpenStackClusterStatus{
+ Bastion: &infrav1.BastionStatus{
+ ReferencedResources: infrav1.ReferencedMachineResources{
+ ImageID: "imageID",
+ },
+ },
Network: &infrav1.NetworkStatusWithSubnets{
NetworkStatus: infrav1.NetworkStatus{
Name: "network-name",
@@ -250,9 +254,6 @@ var _ = Describe("OpenStackCluster controller", func() {
server.ID = "adopted-bastion-uuid"
server.Status = "ACTIVE"
- imageClientRecorder := mockScopeFactory.ImageClient.EXPECT()
- imageClientRecorder.ListImages(gomock.Any()).Return([]images.Image{{ID: "imageID"}}, nil)
-
computeClientRecorder := mockScopeFactory.ComputeClient.EXPECT()
computeClientRecorder.ListServers(servers.ListOpts{
Name: "^capi-cluster-bastion$",
@@ -263,7 +264,13 @@ var _ = Describe("OpenStackCluster controller", func() {
networkClientRecorder.ListFloatingIP(floatingips.ListOpts{PortID: "portID"}).Return(make([]floatingips.FloatingIP, 1), nil)
res, err := reconcileBastion(scope, capiCluster, testCluster)
- Expect(testCluster.Status.Bastion).To(Equal(&infrav1.BastionStatus{ID: "adopted-bastion-uuid", State: "ACTIVE"}))
+ Expect(testCluster.Status.Bastion).To(Equal(&infrav1.BastionStatus{
+ ID: "adopted-bastion-uuid",
+ State: "ACTIVE",
+ ReferencedResources: infrav1.ReferencedMachineResources{
+ ImageID: "imageID",
+ },
+ }))
Expect(err).To(BeNil())
Expect(res).To(Equal(reconcile.Result{}))
})
@@ -286,6 +293,9 @@ var _ = Describe("OpenStackCluster controller", func() {
},
Bastion: &infrav1.BastionStatus{
ID: "adopted-fip-bastion-uuid",
+ ReferencedResources: infrav1.ReferencedMachineResources{
+ ImageID: "imageID",
+ },
},
}
err = k8sClient.Status().Update(ctx, testCluster)
@@ -298,9 +308,6 @@ var _ = Describe("OpenStackCluster controller", func() {
server.ID = "adopted-fip-bastion-uuid"
server.Status = "ACTIVE"
- imageClientRecorder := mockScopeFactory.ImageClient.EXPECT()
- imageClientRecorder.ListImages(gomock.Any()).Return([]images.Image{{ID: "imageID"}}, nil)
-
computeClientRecorder := mockScopeFactory.ComputeClient.EXPECT()
computeClientRecorder.GetServer("adopted-fip-bastion-uuid").Return(&server, nil)
@@ -309,7 +316,14 @@ var _ = Describe("OpenStackCluster controller", func() {
networkClientRecorder.ListFloatingIP(floatingips.ListOpts{PortID: "portID"}).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", State: "ACTIVE", FloatingIP: "1.2.3.4"}))
+ Expect(testCluster.Status.Bastion).To(Equal(&infrav1.BastionStatus{
+ ID: "adopted-fip-bastion-uuid",
+ FloatingIP: "1.2.3.4",
+ State: "ACTIVE",
+ ReferencedResources: infrav1.ReferencedMachineResources{
+ ImageID: "imageID",
+ },
+ }))
Expect(err).To(BeNil())
Expect(res).To(Equal(reconcile.Result{}))
})
@@ -332,6 +346,9 @@ var _ = Describe("OpenStackCluster controller", func() {
},
Bastion: &infrav1.BastionStatus{
ID: "requeue-bastion-uuid",
+ ReferencedResources: infrav1.ReferencedMachineResources{
+ ImageID: "imageID",
+ },
},
}
err = k8sClient.Status().Update(ctx, testCluster)
@@ -344,14 +361,17 @@ var _ = Describe("OpenStackCluster controller", func() {
server.ID = "requeue-bastion-uuid"
server.Status = "BUILD"
- imageClientRecorder := mockScopeFactory.ImageClient.EXPECT()
- imageClientRecorder.ListImages(gomock.Any()).Return([]images.Image{{ID: "imageID"}}, nil)
-
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"}))
+ Expect(testCluster.Status.Bastion).To(Equal(&infrav1.BastionStatus{
+ ID: "requeue-bastion-uuid",
+ State: "BUILD",
+ ReferencedResources: infrav1.ReferencedMachineResources{
+ ImageID: "imageID",
+ },
+ }))
Expect(err).To(BeNil())
Expect(res).To(Equal(reconcile.Result{RequeueAfter: waitForBuildingInstanceToReconcile}))
})
@@ -364,6 +384,15 @@ var _ = Describe("OpenStackCluster controller", func() {
Expect(err).To(BeNil())
err = k8sClient.Create(ctx, capiCluster)
Expect(err).To(BeNil())
+ testCluster.Status = infrav1.OpenStackClusterStatus{
+ Bastion: &infrav1.BastionStatus{
+ ReferencedResources: infrav1.ReferencedMachineResources{
+ ImageID: "imageID",
+ },
+ },
+ }
+ err = k8sClient.Status().Update(ctx, testCluster)
+ Expect(err).To(BeNil())
scope, err := mockScopeFactory.NewClientScopeFromCluster(ctx, k8sClient, testCluster, nil, logr.Discard())
Expect(err).To(BeNil())
@@ -371,9 +400,6 @@ var _ = Describe("OpenStackCluster controller", func() {
server := clients.ServerExt{}
server.ID = "delete-bastion-uuid"
- imageClientRecorder := mockScopeFactory.ImageClient.EXPECT()
- imageClientRecorder.ListImages(gomock.Any()).Return([]images.Image{{ID: "imageID"}}, nil)
-
computeClientRecorder := mockScopeFactory.ComputeClient.EXPECT()
computeClientRecorder.ListServers(servers.ListOpts{
Name: "^capi-cluster-bastion$",
From 9a714023bc159b02866d3539b0bf37d71da8fcc2 Mon Sep 17 00:00:00 2001
From: Max Rantil
Date: Wed, 17 Jan 2024 19:16:09 +0000
Subject: [PATCH 043/180] Enhance Tilt integration with CAPO using a
ClusterClass template
Signed-off-by: Max Rantil
---
docs/book/src/development/development.md | 97 ++++++++++++++-
templates/cluster-template-development.yaml | 13 ++
templates/clusterclass-dev-test.yaml | 128 ++++++++++++++++++++
3 files changed, 237 insertions(+), 1 deletion(-)
create mode 100644 templates/cluster-template-development.yaml
create mode 100644 templates/clusterclass-dev-test.yaml
diff --git a/docs/book/src/development/development.md b/docs/book/src/development/development.md
index f8719c9178..4efddd43c2 100644
--- a/docs/book/src/development/development.md
+++ b/docs/book/src/development/development.md
@@ -50,9 +50,104 @@ make docker-build docker-push
After generating `infrastructure-components.yaml`, replace the `us.gcr.io/k8s-artifacts-prod/capi-openstack/capi-openstack-controller:v0.3.4` with your image.
+## Testing Cluster Creation using the 'dev-test' ClusterClass with Tilt
+
+This guide demonstrates how to create a Kubernetes cluster using ClusterClass, specifically designed for a development environment. It includes initializing a Kind cluster, configuring secrets, and applying ClusterClass to deploy your cluster with Tilt.
+
+### Creating a Kind Cluster
+
+Create a Kind cluster. This process involves the initialization of Cluster API providers for OpenStack.
+
+```bash
+kind create cluster
+export CLUSTER_TOPOLOGY=true
+clusterctl init --infrastructure openstack
+```
+
+### Secret Configuration
+
+CAPO needs a clouds.yaml file in order to manage the OpenStack resources needed for the Cluster. This should be supplied as a secret named `${CLUSTER_NAME}-cloud-config`. You can create this secret for example with:
+
+```bash
+kubectl create secret generic ${CLUSTER_NAME}-cloud-config --from-file=clouds.yaml
+```
+
+You can also make Tilt create it for you when you run `tilt up`, more on that in the next section.
+
## Developing with Tilt
-We have support for using [Tilt](https://tilt.dev/) for rapid iterative development. Please visit the [Cluster API documentation on Tilt](https://cluster-api.sigs.k8s.io/developer/tilt.html) for information on how to set up your development environment.
+We have support for using [Tilt](https://tilt.dev/) for rapid iterative development. Please visit the [Cluster API documentation on Tilt](https://cluster-api.sigs.k8s.io/developer/tilt.html) for information on how to set up your development environment.
+
+Default values align with the devstack setup, as documented below. When specifying the `KUBERNETES_VERSION`, ensure an image named `ubuntu-2204-kube-{{ KUBERNETES_VERSION }}` is available in your environment, corresponding to that Kubernetes version.
+For using Tilt with ClusterClass, update your `tilt-settings.yaml` file as described:
+
+```yaml
+kustomize_substitutions:
+ CLUSTER_TOPOLOGY: "true"
+ # Define the name of your cluster (e.g., "dev-test")
+ CLUSTER_NAME: ""
+ # Desired Kubernetes Version for Your Cluster (e.g., "v1.28.5")
+ KUBERNETES_VERSION: ""
+ # [Optional] SSH Keypair Name for Instances in OpenStack (Default: "")
+ OPENSTACK_SSH_KEY_NAME: ""
+ # [Optional] Control Plane Machine Flavor (Default: m1.medium)
+ OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR: ""
+ # [Optional] Node Machine Flavor (Default: m1.small)
+ OPENSTACK_NODE_MACHINE_FLAVOR: ""
+ # [Optional] OpenStack Cloud Environment (Default: capo-e2e)
+ OPENSTACK_CLOUD: ""
+
+additional_kustomizations:
+ secret_kustomization: /path/to/kustomize/secret/configuration
+```
+
+Ensure the specified path (`/path/to/kustomize/secret/configuration`) contains both the `clouds.yaml` file and a `kustomization.yaml` file. The `kustomization.yaml` should define the necessary resources, such as a Kubernetes secret, using the `clouds.yaml` file.
+
+For example, if you want to automatically create a secret named `dev-test-cloud-config` with the content of your `clouds.yaml` every time you do `tilt up`, you could do the following.
+
+Create a folder to hold the kustomization.
+We will use `/tmp/capo-dev` as example here.
+
+Add the `clouds.yaml` file that you want to use to the folder.
+It could look something like this:
+
+```yaml
+clouds:
+ capo-e2e:
+ auth:
+ username: demo
+ password: secretadmin
+ # If using application credentials you would have something like this instead:
+ # auth_type: v3applicationcredential
+ # application_credential_id: abc123
+ # application_credential_secret: 456def
+ user_domain_id: default
+ auth_url: https://example.com/identity
+ domain_id: default
+ project_name: demo
+ verify: false
+ region_name: RegionOne
+```
+
+Create a kustomization file named `kustomization.yaml` in the same folder:
+
+```yaml
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+# Do not add random hash to the end of the secret name
+generatorOptions:
+ disableNameSuffixHash: true
+secretGenerator:
+- files:
+ - clouds.yaml
+ name: dev-test-cloud-config
+ type: Opaque
+```
+
+If you now add `/tmp/capo-dev` to the `additional_kustomizations`, tilt will automatically apply
+the secret when you do `tilt up`.
+
+To check that the kustomization produces the desired output, do `kustomize build /tmp/capo-dev`.
## Running E2E tests locally
diff --git a/templates/cluster-template-development.yaml b/templates/cluster-template-development.yaml
new file mode 100644
index 0000000000..d863604df1
--- /dev/null
+++ b/templates/cluster-template-development.yaml
@@ -0,0 +1,13 @@
+apiVersion: cluster.x-k8s.io/v1beta1
+kind: Cluster
+metadata:
+ name: ${CLUSTER_NAME}
+spec:
+ topology:
+ class: dev-test
+ version: ${KUBERNETES_VERSION}
+ workers:
+ machineDeployments:
+ - class: default-worker
+ name: md-0
+ replicas: 1
diff --git a/templates/clusterclass-dev-test.yaml b/templates/clusterclass-dev-test.yaml
new file mode 100644
index 0000000000..eb3019648b
--- /dev/null
+++ b/templates/clusterclass-dev-test.yaml
@@ -0,0 +1,128 @@
+apiVersion: cluster.x-k8s.io/v1beta1
+kind: ClusterClass
+metadata:
+ name: dev-test
+spec:
+ controlPlane:
+ ref:
+ apiVersion: controlplane.cluster.x-k8s.io/v1beta1
+ kind: KubeadmControlPlaneTemplate
+ name: ${CLUSTER_NAME}-control-plane-template
+ machineInfrastructure:
+ ref:
+ apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+ kind: OpenStackMachineTemplate
+ name: ${CLUSTER_NAME}-control-plane-machine-template
+ infrastructure:
+ ref:
+ apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+ kind: OpenStackClusterTemplate
+ name: ${CLUSTER_NAME}-openstackcluster-template
+ workers:
+ machineDeployments:
+ - class: default-worker
+ template:
+ bootstrap:
+ ref:
+ apiVersion: bootstrap.cluster.x-k8s.io/v1beta1
+ kind: KubeadmConfigTemplate
+ name: ${CLUSTER_NAME}-default-worker-bootstraptemplate
+ infrastructure:
+ ref:
+ apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+ kind: OpenStackMachineTemplate
+ name: ${CLUSTER_NAME}-default-worker-machine-template
+---
+apiVersion: bootstrap.cluster.x-k8s.io/v1beta1
+kind: KubeadmConfigTemplate
+metadata:
+ name: ${CLUSTER_NAME}-default-worker-bootstraptemplate
+spec:
+ template:
+ spec:
+ files: []
+ joinConfiguration:
+ nodeRegistration:
+ kubeletExtraArgs:
+ cloud-provider: external
+ provider-id: openstack:///'{{ instance_id }}'
+ name: '{{ local_hostname }}'
+---
+apiVersion: controlplane.cluster.x-k8s.io/v1beta1
+kind: KubeadmControlPlaneTemplate
+metadata:
+ name: ${CLUSTER_NAME}-control-plane-template
+spec:
+ template:
+ spec:
+ kubeadmConfigSpec:
+ clusterConfiguration:
+ apiServer:
+ extraArgs:
+ cloud-provider: external
+ controllerManager:
+ extraArgs:
+ cloud-provider: external
+ files: []
+ initConfiguration:
+ nodeRegistration:
+ kubeletExtraArgs:
+ cloud-provider: external
+ provider-id: openstack:///'{{ instance_id }}'
+ name: '{{ local_hostname }}'
+ joinConfiguration:
+ nodeRegistration:
+ kubeletExtraArgs:
+ cloud-provider: external
+ provider-id: openstack:///'{{ instance_id }}'
+ name: '{{ local_hostname }}'
+---
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+kind: OpenStackClusterTemplate
+metadata:
+ name: ${CLUSTER_NAME}-openstackcluster-template
+spec:
+ template:
+ spec:
+ apiServerLoadBalancer:
+ enabled: true
+ cloudName: ${OPENSTACK_CLOUD:=capo-e2e}
+ dnsNameservers:
+ - 8.8.8.8
+ identityRef:
+ kind: Secret
+ name: ${CLUSTER_NAME}-cloud-config
+ managedSecurityGroups: true
+ nodeCidr: 10.6.0.0/24
+---
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+kind: OpenStackMachineTemplate
+metadata:
+ name: ${CLUSTER_NAME}-control-plane-machine-template
+spec:
+ template:
+ spec:
+ cloudName: ${OPENSTACK_CLOUD:=capo-e2e}
+ flavor: ${OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR:=m1.medium}
+ identityRef:
+ kind: Secret
+ name: ${CLUSTER_NAME}-cloud-config
+ image:
+ name: ubuntu-2204-kube-${KUBERNETES_VERSION}
+ sshKeyName: ${OPENSTACK_SSH_KEY_NAME:=""}
+---
+apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+kind: OpenStackMachineTemplate
+metadata:
+ name: ${CLUSTER_NAME}-default-worker-machine-template
+spec:
+ template:
+ spec:
+ cloudName: ${OPENSTACK_CLOUD:=capo-e2e}
+ flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR:=m1.small}
+ identityRef:
+ kind: Secret
+ name: ${CLUSTER_NAME}-cloud-config
+ image:
+ name: ubuntu-2204-kube-${KUBERNETES_VERSION}
+ sshKeyName: ${OPENSTACK_SSH_KEY_NAME:=""}
From d410f822d4aa3e22c111f5d9a252ddb694f2d544 Mon Sep 17 00:00:00 2001
From: Lennart Jern
Date: Wed, 31 Jan 2024 11:13:47 +0200
Subject: [PATCH 044/180] Update the dev-test ClusterClass
This adds a patch to set the image automatically based on the kubernetes
version. It also removes the requirement to have the CLUSTER_NAME
variable set for the ClusterClass.
Finally, the docs are updated to reflect this and with a few additions.
Signed-off-by: Lennart Jern
---
docs/book/src/development/development.md | 119 +++++++++++++++++------
templates/clusterclass-dev-test.yaml | 61 +++++++++---
2 files changed, 134 insertions(+), 46 deletions(-)
diff --git a/docs/book/src/development/development.md b/docs/book/src/development/development.md
index 4efddd43c2..9f5309fd77 100644
--- a/docs/book/src/development/development.md
+++ b/docs/book/src/development/development.md
@@ -6,7 +6,14 @@
- [Using your own capi-openstack controller image for testing cluster creation or deletion](#using-your-own-capi-openstack-controller-image-for-testing-cluster-creation-or-deletion)
- [Building and upload your own capi-openstack controller image](#building-and-upload-your-own-capi-openstack-controller-image)
- [Using your own capi-openstack controller image](#using-your-own-capi-openstack-controller-image)
- - [Developing with Tilt](#developing-with-tilt)
+ - [Testing Cluster Creation using the 'dev-test' ClusterClass with Tilt](#testing-cluster-creation-using-the-dev-test-clusterclass-with-tilt)
+ - [Developing with Tilt](#developing-with-tilt)
+ - [Apply ClusterClass and create Cluster](#apply-clusterclass-and-create-cluster)
+ - [Automatically applying kustomizations with Tilt](#automatically-applying-kustomizations-with-tilt)
+ - [Using the 'dev-test' ClusterClass without Tilt](#using-the-dev-test-clusterclass-without-tilt)
+ - [Creating a Kind Cluster](#creating-a-kind-cluster)
+ - [Secret Configuration](#secret-configuration)
+ - [Apply the ClusterClass and create Clusters](#apply-the-clusterclass-and-create-clusters)
- [Running E2E tests locally](#running-e2e-tests-locally)
- [Support for clouds using SSL](#support-for-clouds-using-ssl)
- [Support for clouds with multiple external networks](#support-for-clouds-with-multiple-external-networks)
@@ -15,9 +22,13 @@
- [Create E2E test environment](#create-e2e-test-environment)
- [OpenStack](#openstack)
- [DevStack](#devstack)
+ - [Server side](#server-side)
+ - [CAPO side](#capo-side)
- [Running E2E tests using rootless podman](#running-e2e-tests-using-rootless-podman)
- [Host configuration](#host-configuration)
- [Running podman system service to emulate docker daemon](#running-podman-system-service-to-emulate-docker-daemon)
+ - [API concepts](#api-concepts)
+ - [`referencedResources`](#referencedresources)
@@ -52,42 +63,28 @@ After generating `infrastructure-components.yaml`, replace the `us.gcr.io/k8s-ar
## Testing Cluster Creation using the 'dev-test' ClusterClass with Tilt
-This guide demonstrates how to create a Kubernetes cluster using ClusterClass, specifically designed for a development environment. It includes initializing a Kind cluster, configuring secrets, and applying ClusterClass to deploy your cluster with Tilt.
+This guide demonstrates how to create a Kubernetes cluster using a ClusterClass, specifically designed for a development environment. It includes configuring secrets, applying the ClusterClass, and creating a cluster with Tilt.
-### Creating a Kind Cluster
-
-Create a Kind cluster. This process involves the initialization of Cluster API providers for OpenStack.
+The `dev-test` ClusterClass is designed for development.
+This means that it is using the latest (potentially unstable) API version.
+The defaults are also aligned with the devstack setup (documented below) to make it as easy as possible to use in a development flow.
+However, this also means that it may *not* be well suited for general usage.
-```bash
-kind create cluster
-export CLUSTER_TOPOLOGY=true
-clusterctl init --infrastructure openstack
-```
-
-### Secret Configuration
-
-CAPO needs a clouds.yaml file in order to manage the OpenStack resources needed for the Cluster. This should be supplied as a secret named `${CLUSTER_NAME}-cloud-config`. You can create this secret for example with:
-
-```bash
-kubectl create secret generic ${CLUSTER_NAME}-cloud-config --from-file=clouds.yaml
-```
-
-You can also make Tilt create it for you when you run `tilt up`, more on that in the next section.
-
-## Developing with Tilt
+### Developing with Tilt
We have support for using [Tilt](https://tilt.dev/) for rapid iterative development. Please visit the [Cluster API documentation on Tilt](https://cluster-api.sigs.k8s.io/developer/tilt.html) for information on how to set up your development environment.
-Default values align with the devstack setup, as documented below. When specifying the `KUBERNETES_VERSION`, ensure an image named `ubuntu-2204-kube-{{ KUBERNETES_VERSION }}` is available in your environment, corresponding to that Kubernetes version.
-For using Tilt with ClusterClass, update your `tilt-settings.yaml` file as described:
+The `Tiltfile` in the Cluster API repository can be used as is with CAPO, but we need to add some configuration.
+For using Tilt with ClusterClass, update your `tilt-settings.yaml` file (located in the root of the CAPI repository) as described:
```yaml
+template_dirs:
+ openstack:
+ # Make Tilt aware of the CAPO templates
+ - ../cluster-api-provider-openstack/templates
+
kustomize_substitutions:
CLUSTER_TOPOLOGY: "true"
- # Define the name of your cluster (e.g., "dev-test")
- CLUSTER_NAME: ""
- # Desired Kubernetes Version for Your Cluster (e.g., "v1.28.5")
- KUBERNETES_VERSION: ""
# [Optional] SSH Keypair Name for Instances in OpenStack (Default: "")
OPENSTACK_SSH_KEY_NAME: ""
# [Optional] Control Plane Machine Flavor (Default: m1.medium)
@@ -97,10 +94,30 @@ kustomize_substitutions:
# [Optional] OpenStack Cloud Environment (Default: capo-e2e)
OPENSTACK_CLOUD: ""
+# [Optional] Automatically apply a kustomization, e.g. for adding the clouds.yaml secret
additional_kustomizations:
secret_kustomization: /path/to/kustomize/secret/configuration
```
+### Apply ClusterClass and create Cluster
+
+When you are happy with the configuration, start the environment as explained in the CAPI documentation.
+Open the Tilt dashboard in your browser.
+After a while, you should be able to find resources called `CAPO.clusterclasses` and `CAPO.templates`.
+These shoud correspond to what exists in the `templates` folder and you should see widgets for applying and deleting them.
+
+**Note:** When you apply a cluster template, there will be a `KUBERNETES_VERSION` variable.
+This variable is used to pick the image used!
+Ensure that an image named `ubuntu-2204-kube-{{ KUBERNETES_VERSION }}` is available in your environment, corresponding to that Kubernetes version.
+
+**Note:** All clusters created from the dev-test ClusterClass will require a secret named `dev-test-cloud-config` with the `clouds.yaml` to be used by CAPO for interacting with OpenStack.
+You can create it manually or see below how to make Tilt automate it.
+
+### Automatically applying kustomizations with Tilt
+
+This explains how to automatically create the secret containing `clouds.yaml`.
+The same procedure can be used for any other things you want to create in the cluster.
+
Ensure the specified path (`/path/to/kustomize/secret/configuration`) contains both the `clouds.yaml` file and a `kustomization.yaml` file. The `kustomization.yaml` should define the necessary resources, such as a Kubernetes secret, using the `clouds.yaml` file.
For example, if you want to automatically create a secret named `dev-test-cloud-config` with the content of your `clouds.yaml` every time you do `tilt up`, you could do the following.
@@ -144,11 +161,51 @@ secretGenerator:
type: Opaque
```
-If you now add `/tmp/capo-dev` to the `additional_kustomizations`, tilt will automatically apply
-the secret when you do `tilt up`.
+If you now add `/tmp/capo-dev` to the `additional_kustomizations`, tilt will automatically apply
+the secret.
To check that the kustomization produces the desired output, do `kustomize build /tmp/capo-dev`.
+## Using the 'dev-test' ClusterClass without Tilt
+
+If you want to use the ClusterClass without Tilt, you will need to follow these steps instead of the above.
+
+### Creating a Kind Cluster
+
+Create a Kind cluster and deploy CAPO.
+
+**Note:** As the dev-test ClusterClass is made for development, it may be using a newer API version than what is in the latest release.
+You *will need* to [use local artifacts](https://cluster-api.sigs.k8s.io/clusterctl/developers#use-local-artifacts) for this to work in most cases!
+
+```bash
+kind create cluster
+export CLUSTER_TOPOLOGY=true
+clusterctl init --infrastructure openstack
+```
+
+### Secret Configuration
+
+CAPO needs a clouds.yaml file in order to manage the OpenStack resources needed for the Cluster. This should be supplied as a secret named `dev-test-cloud-config`. You can create this secret for example with:
+
+```bash
+kubectl create secret generic dev-test-cloud-config --from-file=clouds.yaml
+```
+
+### Apply the ClusterClass and create Clusters
+
+You can use `clusterctl` to render the ClusterClass:
+
+```bash
+clusterctl generate yaml --from templates/clusterclass-dev-test.yaml
+```
+
+Create a cluster using the development template, that makes use of the ClusterClass:
+
+```bash
+clusterctl generate cluster my-cluster --kubernetes-version=v1.29.0 --from templates/cluster-template-development.yaml > my-cluster.yaml
+kubectl apply -f my-cluster.yaml
+```
+
## Running E2E tests locally
You can run the E2E tests locally with:
@@ -445,4 +502,4 @@ This sections goal is to gather various insights into the API design that can se
Starting from v1alpha8 both `OpenStackMachineStatus` and `BastionsStatus` feature a field named `referencedResources` which aims to include fields that list individual IDs of the resources associated with the machine or bastion. These IDs are calculated on machine or bastion creation and are not intended to be changed during the object lifecycle.
-Having all the IDs of related resources saved in the statuses allows CAPO to make easy decisions about deleting the related resources when deleting the VM corresponding to the machine or bastion.
\ No newline at end of file
+Having all the IDs of related resources saved in the statuses allows CAPO to make easy decisions about deleting the related resources when deleting the VM corresponding to the machine or bastion.
diff --git a/templates/clusterclass-dev-test.yaml b/templates/clusterclass-dev-test.yaml
index eb3019648b..40b8758502 100644
--- a/templates/clusterclass-dev-test.yaml
+++ b/templates/clusterclass-dev-test.yaml
@@ -7,17 +7,17 @@ spec:
ref:
apiVersion: controlplane.cluster.x-k8s.io/v1beta1
kind: KubeadmControlPlaneTemplate
- name: ${CLUSTER_NAME}-control-plane-template
+ name: dev-test-control-plane
machineInfrastructure:
ref:
apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
- name: ${CLUSTER_NAME}-control-plane-machine-template
+ name: dev-test-control-plane-machine
infrastructure:
ref:
apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackClusterTemplate
- name: ${CLUSTER_NAME}-openstackcluster-template
+ name: dev-test-openstackcluster
workers:
machineDeployments:
- class: default-worker
@@ -26,17 +26,48 @@ spec:
ref:
apiVersion: bootstrap.cluster.x-k8s.io/v1beta1
kind: KubeadmConfigTemplate
- name: ${CLUSTER_NAME}-default-worker-bootstraptemplate
+ name: dev-test-default-worker-bootstraptemplate
infrastructure:
ref:
apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
- name: ${CLUSTER_NAME}-default-worker-machine-template
+ name: dev-test-default-worker-machine
+ patches:
+ - name: controlPlaneImage
+ description: "Sets the OpenStack image that is used for creating the servers."
+ definitions:
+ - selector:
+ apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+ kind: OpenStackMachineTemplate
+ matchResources:
+ controlPlane: true
+ jsonPatches:
+ - op: add
+ path: /spec/template/spec/image/name
+ valueFrom:
+ template: |
+ ubuntu-2204-kube-{{ .builtin.controlPlane.version }}
+ - name: workerImage
+ description: "Sets the OpenStack image that is used for creating the servers."
+ definitions:
+ - selector:
+ apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+ kind: OpenStackMachineTemplate
+ matchResources:
+ machineDeploymentClass:
+ names:
+ - default-worker
+ jsonPatches:
+ - op: add
+ path: /spec/template/spec/image/name
+ valueFrom:
+ template: |
+ ubuntu-2204-kube-{{ .builtin.machineDeployment.version }}
---
apiVersion: bootstrap.cluster.x-k8s.io/v1beta1
kind: KubeadmConfigTemplate
metadata:
- name: ${CLUSTER_NAME}-default-worker-bootstraptemplate
+ name: dev-test-default-worker-bootstraptemplate
spec:
template:
spec:
@@ -51,7 +82,7 @@ spec:
apiVersion: controlplane.cluster.x-k8s.io/v1beta1
kind: KubeadmControlPlaneTemplate
metadata:
- name: ${CLUSTER_NAME}-control-plane-template
+ name: dev-test-control-plane
spec:
template:
spec:
@@ -80,7 +111,7 @@ spec:
apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackClusterTemplate
metadata:
- name: ${CLUSTER_NAME}-openstackcluster-template
+ name: dev-test-openstackcluster
spec:
template:
spec:
@@ -91,14 +122,14 @@ spec:
- 8.8.8.8
identityRef:
kind: Secret
- name: ${CLUSTER_NAME}-cloud-config
+ name: dev-test-cloud-config
managedSecurityGroups: true
nodeCidr: 10.6.0.0/24
---
apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
metadata:
- name: ${CLUSTER_NAME}-control-plane-machine-template
+ name: dev-test-control-plane-machine
spec:
template:
spec:
@@ -106,15 +137,15 @@ spec:
flavor: ${OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR:=m1.medium}
identityRef:
kind: Secret
- name: ${CLUSTER_NAME}-cloud-config
+ name: dev-test-cloud-config
image:
- name: ubuntu-2204-kube-${KUBERNETES_VERSION}
+ name: overridden-by-patch
sshKeyName: ${OPENSTACK_SSH_KEY_NAME:=""}
---
apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
metadata:
- name: ${CLUSTER_NAME}-default-worker-machine-template
+ name: dev-test-default-worker-machine
spec:
template:
spec:
@@ -122,7 +153,7 @@ spec:
flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR:=m1.small}
identityRef:
kind: Secret
- name: ${CLUSTER_NAME}-cloud-config
+ name: dev-test-cloud-config
image:
- name: ubuntu-2204-kube-${KUBERNETES_VERSION}
+ name: overridden-by-patch
sshKeyName: ${OPENSTACK_SSH_KEY_NAME:=""}
From b0480b14bded64df497e22945efa4dbfd8d79246 Mon Sep 17 00:00:00 2001
From: Lennart Jern
Date: Wed, 31 Jan 2024 15:35:49 +0200
Subject: [PATCH 045/180] Decrease number of machines in e2e tests
The e2e tests are currently very unstable. I suspect lack of resources
in the devstack to be the issue. In an attempt to solve this, the number
of control-plane nodes are reduced in this commit. Now only the multi-az
test will use 3 CP. The rest will have 1 CP only.
Signed-off-by: Lennart Jern
---
test/e2e/suites/e2e/e2e_test.go | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/test/e2e/suites/e2e/e2e_test.go b/test/e2e/suites/e2e/e2e_test.go
index e18c19a149..2490d848ac 100644
--- a/test/e2e/suites/e2e/e2e_test.go
+++ b/test/e2e/suites/e2e/e2e_test.go
@@ -85,7 +85,7 @@ var _ = Describe("e2e tests [PR-Blocking]", func() {
shared.Logf("Creating a cluster")
clusterName := fmt.Sprintf("cluster-%s", namespace.Name)
configCluster := defaultConfigCluster(clusterName, namespace.Name)
- configCluster.ControlPlaneMachineCount = pointer.Int64(3)
+ configCluster.ControlPlaneMachineCount = pointer.Int64(1)
configCluster.WorkerMachineCount = pointer.Int64(1)
configCluster.Flavor = shared.FlavorDefault
createCluster(ctx, configCluster, clusterResources)
@@ -103,7 +103,7 @@ var _ = Describe("e2e tests [PR-Blocking]", func() {
Namespace: namespace.Name,
})
Expect(workerMachines).To(HaveLen(1))
- Expect(controlPlaneMachines).To(HaveLen(3))
+ Expect(controlPlaneMachines).To(HaveLen(1))
shared.Logf("Waiting for worker nodes to be in Running phase")
statusChecks := []framework.MachineStatusCheck{framework.MachinePhaseCheck(string(clusterv1.MachinePhaseRunning))}
@@ -118,20 +118,20 @@ var _ = Describe("e2e tests [PR-Blocking]", func() {
waitForDaemonSetRunning(ctx, workloadCluster.GetClient(), "kube-system", "openstack-cloud-controller-manager")
- waitForNodesReadyWithoutCCMTaint(ctx, workloadCluster.GetClient(), 4)
+ waitForNodesReadyWithoutCCMTaint(ctx, workloadCluster.GetClient(), 2)
// Tag: clusterName is declared on OpenStackCluster and gets propagated to all machines
// except the bastion host
allServers, err := shared.DumpOpenStackServers(e2eCtx, servers.ListOpts{Tags: clusterName})
Expect(err).NotTo(HaveOccurred())
- Expect(allServers).To(HaveLen(4))
+ Expect(allServers).To(HaveLen(2))
// When listing servers with multiple tags, nova api requires a single, comma-separated string
// with all the tags
controlPlaneTags := fmt.Sprintf("%s,%s", clusterName, "control-plane")
controlPlaneServers, err := shared.DumpOpenStackServers(e2eCtx, servers.ListOpts{Tags: controlPlaneTags})
Expect(err).NotTo(HaveOccurred())
- Expect(controlPlaneServers).To(HaveLen(3))
+ Expect(controlPlaneServers).To(HaveLen(1))
machineTags := fmt.Sprintf("%s,%s", clusterName, "machine")
machineServers, err := shared.DumpOpenStackServers(e2eCtx, servers.ListOpts{Tags: machineTags})
@@ -164,7 +164,7 @@ var _ = Describe("e2e tests [PR-Blocking]", func() {
shared.Logf("Creating a cluster")
clusterName := fmt.Sprintf("cluster-%s", namespace.Name)
configCluster := defaultConfigCluster(clusterName, namespace.Name)
- configCluster.ControlPlaneMachineCount = pointer.Int64(3)
+ configCluster.ControlPlaneMachineCount = pointer.Int64(1)
configCluster.WorkerMachineCount = pointer.Int64(1)
configCluster.Flavor = shared.FlavorFlatcar
createCluster(ctx, configCluster, clusterResources)
@@ -182,7 +182,7 @@ var _ = Describe("e2e tests [PR-Blocking]", func() {
Namespace: namespace.Name,
})
Expect(workerMachines).To(HaveLen(1))
- Expect(controlPlaneMachines).To(HaveLen(3))
+ Expect(controlPlaneMachines).To(HaveLen(1))
shared.Logf("Waiting for worker nodes to be in Running phase")
statusChecks := []framework.MachineStatusCheck{framework.MachinePhaseCheck(string(clusterv1.MachinePhaseRunning))}
@@ -197,7 +197,7 @@ var _ = Describe("e2e tests [PR-Blocking]", func() {
waitForDaemonSetRunning(ctx, workloadCluster.GetClient(), "kube-system", "openstack-cloud-controller-manager")
- waitForNodesReadyWithoutCCMTaint(ctx, workloadCluster.GetClient(), 4)
+ waitForNodesReadyWithoutCCMTaint(ctx, workloadCluster.GetClient(), 2)
})
})
@@ -209,7 +209,7 @@ var _ = Describe("e2e tests [PR-Blocking]", func() {
shared.Logf("Creating a cluster")
clusterName := fmt.Sprintf("cluster-%s", namespace.Name)
configCluster := defaultConfigCluster(clusterName, namespace.Name)
- configCluster.ControlPlaneMachineCount = pointer.Int64(3)
+ configCluster.ControlPlaneMachineCount = pointer.Int64(1)
configCluster.WorkerMachineCount = pointer.Int64(1)
configCluster.Flavor = shared.FlavorFlatcarSysext
createCluster(ctx, configCluster, clusterResources)
@@ -227,7 +227,7 @@ var _ = Describe("e2e tests [PR-Blocking]", func() {
Namespace: namespace.Name,
})
Expect(workerMachines).To(HaveLen(1))
- Expect(controlPlaneMachines).To(HaveLen(3))
+ Expect(controlPlaneMachines).To(HaveLen(1))
shared.Logf("Waiting for worker nodes to be in Running phase")
statusChecks := []framework.MachineStatusCheck{framework.MachinePhaseCheck(string(clusterv1.MachinePhaseRunning))}
@@ -242,7 +242,7 @@ var _ = Describe("e2e tests [PR-Blocking]", func() {
waitForDaemonSetRunning(ctx, workloadCluster.GetClient(), "kube-system", "openstack-cloud-controller-manager")
- waitForNodesReadyWithoutCCMTaint(ctx, workloadCluster.GetClient(), 4)
+ waitForNodesReadyWithoutCCMTaint(ctx, workloadCluster.GetClient(), 2)
})
})
From dfb963d7edd0828a745f85003bd4e1d4c5d1abe9 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Tue, 16 Jan 2024 15:33:36 +0000
Subject: [PATCH 046/180] Convert ServerMetadata from a map to a list
While we're changing it, we also add validation that keys and values
don't exceed 255 characters.
---
api/v1alpha5/zz_generated.conversion.go | 4 +-
api/v1alpha6/conversion.go | 45 ++++++++++++
api/v1alpha6/conversion_test.go | 31 ++++++++
api/v1alpha6/zz_generated.conversion.go | 4 +-
api/v1alpha7/conversion.go | 73 ++++++++++++++++++-
api/v1alpha7/conversion_test.go | 31 ++++++++
api/v1alpha7/zz_generated.conversion.go | 4 +-
api/v1alpha8/openstackmachine_types.go | 14 +++-
api/v1alpha8/zz_generated.deepcopy.go | 21 +++++-
...re.cluster.x-k8s.io_openstackclusters.yaml | 23 +++++-
...er.x-k8s.io_openstackclustertemplates.yaml | 23 +++++-
...re.cluster.x-k8s.io_openstackmachines.yaml | 23 +++++-
...er.x-k8s.io_openstackmachinetemplates.yaml | 23 +++++-
controllers/openstackmachine_controller.go | 9 ++-
.../openstackmachine_controller_test.go | 4 +-
15 files changed, 304 insertions(+), 28 deletions(-)
diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go
index b10bd71be9..20646768bf 100644
--- a/api/v1alpha5/zz_generated.conversion.go
+++ b/api/v1alpha5/zz_generated.conversion.go
@@ -1074,7 +1074,7 @@ func autoConvert_v1alpha5_OpenStackMachineSpec_To_v1alpha8_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/v1alpha8.ServerMetadata)
out.ConfigDrive = (*bool)(unsafe.Pointer(in.ConfigDrive))
out.RootVolume = (*v1alpha8.RootVolume)(unsafe.Pointer(in.RootVolume))
// WARNING: in.ServerGroupID requires manual conversion: does not exist in peer-type
@@ -1113,7 +1113,7 @@ func autoConvert_v1alpha8_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/v1alpha8.ServerMetadata vs map[string]string)
out.ConfigDrive = (*bool)(unsafe.Pointer(in.ConfigDrive))
out.RootVolume = (*RootVolume)(unsafe.Pointer(in.RootVolume))
// WARNING: in.AdditionalBlockDevices requires manual conversion: does not exist in peer-type
diff --git a/api/v1alpha6/conversion.go b/api/v1alpha6/conversion.go
index c2170b980b..a01430e935 100644
--- a/api/v1alpha6/conversion.go
+++ b/api/v1alpha6/conversion.go
@@ -44,6 +44,24 @@ func restorev1alpha6MachineSpec(previous *OpenStackMachineSpec, dst *OpenStackMa
// 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 v1alpha8 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 {
+ delete(dst.ServerMetadata, kd)
+ dst.ServerMetadata[k] = v
+ }
+ }
}
func restorev1alpha6ClusterStatus(previous *OpenStackClusterStatus, dst *OpenStackClusterStatus) {
@@ -425,6 +443,23 @@ func Convert_v1alpha6_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(in *
}
out.Image = imageFilter
+ 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 v1alpha8
+ 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
+ }
+
return nil
}
@@ -776,6 +811,16 @@ func Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(in *
out.ImageUUID = in.Image.ID
}
+ 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
+ }
+
return nil
}
diff --git a/api/v1alpha6/conversion_test.go b/api/v1alpha6/conversion_test.go
index 2099a1467d..5a2a9a6f6d 100644
--- a/api/v1alpha6/conversion_test.go
+++ b/api/v1alpha6/conversion_test.go
@@ -101,6 +101,37 @@ func TestFuzzyConversion(t *testing.T) {
spec.Subnets = append(spec.Subnets, subnet)
}
},
+
+ 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()
+ }
+ }
+ },
}
}
diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go
index 41761e8db2..0589be11fb 100644
--- a/api/v1alpha6/zz_generated.conversion.go
+++ b/api/v1alpha6/zz_generated.conversion.go
@@ -1097,7 +1097,7 @@ func autoConvert_v1alpha6_OpenStackMachineSpec_To_v1alpha8_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/v1alpha8.ServerMetadata)
out.ConfigDrive = (*bool)(unsafe.Pointer(in.ConfigDrive))
out.RootVolume = (*v1alpha8.RootVolume)(unsafe.Pointer(in.RootVolume))
// WARNING: in.ServerGroupID requires manual conversion: does not exist in peer-type
@@ -1136,7 +1136,7 @@ func autoConvert_v1alpha8_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/v1alpha8.ServerMetadata vs map[string]string)
out.ConfigDrive = (*bool)(unsafe.Pointer(in.ConfigDrive))
out.RootVolume = (*RootVolume)(unsafe.Pointer(in.RootVolume))
// WARNING: in.AdditionalBlockDevices requires manual conversion: does not exist in peer-type
diff --git a/api/v1alpha7/conversion.go b/api/v1alpha7/conversion.go
index e51c698e29..df31c7d81c 100644
--- a/api/v1alpha7/conversion.go
+++ b/api/v1alpha7/conversion.go
@@ -26,7 +26,20 @@ import (
var _ ctrlconversion.Convertible = &OpenStackCluster{}
-var v1alpha7OpenStackClusterRestorer = conversion.RestorerFor[*OpenStackCluster]{}
+func restorev1alpha7Bastion(previous **Bastion, dst **Bastion) {
+ if *previous != nil && *dst != nil {
+ restorev1alpha7MachineSpec(&(*previous).Instance, &(*dst).Instance)
+ }
+}
+
+var v1alpha7OpenStackClusterRestorer = conversion.RestorerFor[*OpenStackCluster]{
+ "bastion": conversion.HashedFieldRestorer(
+ func(c *OpenStackCluster) **Bastion {
+ return &c.Spec.Bastion
+ },
+ restorev1alpha7Bastion,
+ ),
+}
var v1alpha8OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStackCluster]{
"bastion": conversion.HashedFieldRestorer(
@@ -67,6 +80,24 @@ var v1alpha8OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStack
func restorev1alpha7MachineSpec(previous *OpenStackMachineSpec, dst *OpenStackMachineSpec) {
dst.FloatingIP = previous.FloatingIP
+
+ // Conversion to v1alpha8 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 {
+ delete(dst.ServerMetadata, kd)
+ dst.ServerMetadata[k] = v
+ }
+ }
}
func restorev1alpha8MachineSpec(previous *infrav1.OpenStackMachineSpec, dst *infrav1.OpenStackMachineSpec) {
@@ -139,12 +170,23 @@ func (r *OpenStackClusterList) ConvertFrom(srcRaw ctrlconversion.Hub) error {
var _ ctrlconversion.Convertible = &OpenStackClusterTemplate{}
+func restorev1alpha7ClusterTemplateSpec(previous *OpenStackClusterTemplateSpec, dst *OpenStackClusterTemplateSpec) {
+ restorev1alpha7Bastion(&previous.Template.Spec.Bastion, &dst.Template.Spec.Bastion)
+}
+
func restorev1alpha8ClusterTemplateSpec(previous *infrav1.OpenStackClusterTemplateSpec, dst *infrav1.OpenStackClusterTemplateSpec) {
restorev1alpha8Bastion(&previous.Template.Spec.Bastion, &dst.Template.Spec.Bastion)
restorev1alpha8ClusterSpec(&previous.Template.Spec, &dst.Template.Spec)
}
-var v1alpha7OpenStackClusterTemplateRestorer = conversion.RestorerFor[*OpenStackClusterTemplate]{}
+var v1alpha7OpenStackClusterTemplateRestorer = conversion.RestorerFor[*OpenStackClusterTemplate]{
+ "spec": conversion.HashedFieldRestorer(
+ func(c *OpenStackClusterTemplate) *OpenStackClusterTemplateSpec {
+ return &c.Spec
+ },
+ restorev1alpha7ClusterTemplateSpec,
+ ),
+}
var v1alpha8OpenStackClusterTemplateRestorer = conversion.RestorerFor[*infrav1.OpenStackClusterTemplate]{
"spec": conversion.HashedFieldRestorer(
@@ -308,6 +350,16 @@ func Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(in *
out.ImageUUID = in.Image.ID
}
+ 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
+ }
+
return nil
}
@@ -332,6 +384,23 @@ func Convert_v1alpha7_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(in *
}
out.Image = imageFilter
+ 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 v1alpha8
+ 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
+ }
+
return nil
}
diff --git a/api/v1alpha7/conversion_test.go b/api/v1alpha7/conversion_test.go
index d26546a9d8..c57cc5d163 100644
--- a/api/v1alpha7/conversion_test.go
+++ b/api/v1alpha7/conversion_test.go
@@ -69,6 +69,37 @@ func TestFuzzyConversion(t *testing.T) {
spec.Subnets = append(spec.Subnets, subnet)
}
},
+
+ 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()
+ }
+ }
+ },
}
}
diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go
index 773d9892fd..42a17e16eb 100644
--- a/api/v1alpha7/zz_generated.conversion.go
+++ b/api/v1alpha7/zz_generated.conversion.go
@@ -1237,7 +1237,7 @@ func autoConvert_v1alpha7_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(
out.SecurityGroups = *(*[]v1alpha8.SecurityGroupFilter)(unsafe.Pointer(&in.SecurityGroups))
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/v1alpha8.ServerMetadata)
out.ConfigDrive = (*bool)(unsafe.Pointer(in.ConfigDrive))
out.RootVolume = (*v1alpha8.RootVolume)(unsafe.Pointer(in.RootVolume))
out.AdditionalBlockDevices = *(*[]v1alpha8.AdditionalBlockDevice)(unsafe.Pointer(&in.AdditionalBlockDevices))
@@ -1257,7 +1257,7 @@ func autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(
out.SecurityGroups = *(*[]SecurityGroupFilter)(unsafe.Pointer(&in.SecurityGroups))
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/v1alpha8.ServerMetadata vs map[string]string)
out.ConfigDrive = (*bool)(unsafe.Pointer(in.ConfigDrive))
out.RootVolume = (*RootVolume)(unsafe.Pointer(in.RootVolume))
out.AdditionalBlockDevices = *(*[]AdditionalBlockDevice)(unsafe.Pointer(&in.AdditionalBlockDevices))
diff --git a/api/v1alpha8/openstackmachine_types.go b/api/v1alpha8/openstackmachine_types.go
index 61d29bad86..bc98e02a98 100644
--- a/api/v1alpha8/openstackmachine_types.go
+++ b/api/v1alpha8/openstackmachine_types.go
@@ -68,7 +68,9 @@ type OpenStackMachineSpec struct {
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"`
@@ -91,6 +93,16 @@ type OpenStackMachineSpec struct {
IdentityRef *OpenStackIdentityReference `json:"identityRef,omitempty"`
}
+type ServerMetadata struct {
+ // Key is the server metadata key
+ // kubebuilder:validation:MaxLength:=255
+ Key string `json:"key"`
+
+ // Value is the server metadata value
+ // kubebuilder:validation:MaxLength:=255
+ Value string `json:"value"`
+}
+
// OpenStackMachineStatus defines the observed state of OpenStackMachine.
type OpenStackMachineStatus struct {
// Ready is true when the provider resource is ready.
diff --git a/api/v1alpha8/zz_generated.deepcopy.go b/api/v1alpha8/zz_generated.deepcopy.go
index eebb59993e..df370f8983 100644
--- a/api/v1alpha8/zz_generated.deepcopy.go
+++ b/api/v1alpha8/zz_generated.deepcopy.go
@@ -691,10 +691,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
@@ -1071,6 +1069,21 @@ func (in *ServerGroupFilter) DeepCopy() *ServerGroupFilter {
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
+}
+
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Subnet) DeepCopyInto(out *Subnet) {
*out = *in
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 00b1ba6cc9..0b48da7dc2 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -5269,11 +5269,28 @@ spec:
type: string
type: object
serverMetadata:
- additionalProperties:
- type: string
description: Metadata mapping. Allows you to create a map
of key value pairs to add to the server instance.
- type: object
+ items:
+ properties:
+ key:
+ description: |-
+ Key is the server metadata key
+ kubebuilder:validation:MaxLength:=255
+ type: string
+ value:
+ description: |-
+ Value is the server metadata value
+ kubebuilder:validation: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
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 cb56c31021..2cab684d19 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -2703,11 +2703,28 @@ spec:
type: string
type: object
serverMetadata:
- additionalProperties:
- type: string
description: Metadata mapping. Allows you to create
a map of key value pairs to add to the server instance.
- type: object
+ items:
+ properties:
+ key:
+ description: |-
+ Key is the server metadata key
+ kubebuilder:validation:MaxLength:=255
+ type: string
+ value:
+ description: |-
+ Value is the server metadata value
+ kubebuilder:validation: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
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 340057cfef..e1a23d33be 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
@@ -2058,11 +2058,28 @@ spec:
type: string
type: object
serverMetadata:
- additionalProperties:
- type: string
description: Metadata mapping. Allows you to create a map of key value
pairs to add to the server instance.
- type: object
+ items:
+ properties:
+ key:
+ description: |-
+ Key is the server metadata key
+ kubebuilder:validation:MaxLength:=255
+ type: string
+ value:
+ description: |-
+ Value is the server metadata value
+ kubebuilder:validation: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
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 264c893e49..db63d9ade3 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
@@ -1738,11 +1738,28 @@ spec:
type: string
type: object
serverMetadata:
- additionalProperties:
- type: string
description: Metadata mapping. Allows you to create a map
of key value pairs to add to the server instance.
- type: object
+ items:
+ properties:
+ key:
+ description: |-
+ Key is the server metadata key
+ kubebuilder:validation:MaxLength:=255
+ type: string
+ value:
+ description: |-
+ Value is the server metadata value
+ kubebuilder:validation: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
diff --git a/controllers/openstackmachine_controller.go b/controllers/openstackmachine_controller.go
index 56d195d8eb..5d6095177c 100644
--- a/controllers/openstackmachine_controller.go
+++ b/controllers/openstackmachine_controller.go
@@ -482,13 +482,20 @@ func (r *OpenStackMachineReconciler) getOrCreate(logger logr.Logger, cluster *cl
}
func machineToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, machine *clusterv1.Machine, openStackMachine *infrav1.OpenStackMachine, userData string) *compute.InstanceSpec {
+ 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,
ImageID: openStackMachine.Status.ReferencedResources.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,
diff --git a/controllers/openstackmachine_controller_test.go b/controllers/openstackmachine_controller_test.go
index bc0c3b96c5..b204111708 100644
--- a/controllers/openstackmachine_controller_test.go
+++ b/controllers/openstackmachine_controller_test.go
@@ -86,8 +86,8 @@ func getDefaultOpenStackMachine() *infrav1.OpenStackMachine {
Image: infrav1.ImageFilter{ID: 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: pointer.Bool(true),
SecurityGroups: []infrav1.SecurityGroupFilter{},
From 06d940aa988ae9373c86aed98a29a0be831b8725 Mon Sep 17 00:00:00 2001
From: Hugo Blom <6117705+huxcrux@users.noreply.github.com>
Date: Thu, 1 Feb 2024 19:23:51 +0100
Subject: [PATCH 047/180] Make sure that allowedcidr lists are compared
correctly
---
.../services/loadbalancer/loadbalancer.go | 10 ++--
pkg/utils/strings/strings.go | 18 +++---
pkg/utils/strings/strings_test.go | 60 +++++++++++++++++++
3 files changed, 73 insertions(+), 15 deletions(-)
create mode 100644 pkg/utils/strings/strings_test.go
diff --git a/pkg/cloud/services/loadbalancer/loadbalancer.go b/pkg/cloud/services/loadbalancer/loadbalancer.go
index 75e2201779..00730d673e 100644
--- a/pkg/cloud/services/loadbalancer/loadbalancer.go
+++ b/pkg/cloud/services/loadbalancer/loadbalancer.go
@@ -19,7 +19,7 @@ package loadbalancer
import (
"errors"
"fmt"
- "reflect"
+ "slices"
"time"
"github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/listeners"
@@ -275,11 +275,11 @@ func (s *Service) getOrUpdateAllowedCIDRS(openStackCluster *infrav1.OpenStackClu
// Validate CIDRs and convert any given IP into a CIDR.
allowedCIDRs = validateIPs(openStackCluster, allowedCIDRs)
- // Remove duplicates.
- allowedCIDRs = capostrings.Unique(allowedCIDRs)
- listener.AllowedCIDRs = capostrings.Unique(listener.AllowedCIDRs)
+ // Sort and remove duplicates
+ allowedCIDRs = capostrings.Canonicalize(allowedCIDRs)
+ listener.AllowedCIDRs = capostrings.Canonicalize(listener.AllowedCIDRs)
- if !reflect.DeepEqual(allowedCIDRs, listener.AllowedCIDRs) {
+ if !slices.Equal(allowedCIDRs, listener.AllowedCIDRs) {
s.scope.Logger().Info("CIDRs do not match, updating listener", "expectedCIDRs", allowedCIDRs, "currentCIDRs", listener.AllowedCIDRs)
listenerUpdateOpts := listeners.UpdateOpts{
AllowedCIDRs: &allowedCIDRs,
diff --git a/pkg/utils/strings/strings.go b/pkg/utils/strings/strings.go
index 6db532e1d8..ec97911fe2 100644
--- a/pkg/utils/strings/strings.go
+++ b/pkg/utils/strings/strings.go
@@ -16,14 +16,12 @@ limitations under the License.
package strings
-func Unique(s []string) []string {
- inResult := make(map[string]bool)
- var result []string
- for _, str := range s {
- if _, ok := inResult[str]; !ok {
- inResult[str] = true
- result = append(result, str)
- }
- }
- return result
+import (
+ "cmp"
+ "slices"
+)
+
+func Canonicalize[S ~[]E, E cmp.Ordered](s S) S {
+ slices.Sort(s)
+ return slices.Compact(s)
}
diff --git a/pkg/utils/strings/strings_test.go b/pkg/utils/strings/strings_test.go
new file mode 100644
index 0000000000..7502f060ad
--- /dev/null
+++ b/pkg/utils/strings/strings_test.go
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 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 strings
+
+import (
+ "slices"
+ "testing"
+)
+
+func TestCanonicalize(t *testing.T) {
+ tests := []struct {
+ name string
+ value []string
+ want []string
+ }{
+ {
+ name: "Empty list",
+ value: []string{},
+ want: []string{},
+ },
+ {
+ name: "Identity",
+ value: []string{"a", "b", "c"},
+ want: []string{"a", "b", "c"},
+ },
+ {
+ name: "Out of order",
+ value: []string{"c", "b", "a"},
+ want: []string{"a", "b", "c"},
+ },
+ {
+ name: "Duplicate elements",
+ value: []string{"c", "b", "a", "c"},
+ want: []string{"a", "b", "c"},
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := Canonicalize(tt.value)
+ if !slices.Equal(got, tt.want) {
+ t.Errorf("CompareLists() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
From b416af70fa272e70c8112b15c20ddf96c311d359 Mon Sep 17 00:00:00 2001
From: huxcrux
Date: Fri, 2 Feb 2024 14:27:23 +0100
Subject: [PATCH 048/180] Migrate Dockerfile to use golang 1.21 to match go.mod
in project
---
Dockerfile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Dockerfile b/Dockerfile
index 03a064bd63..2cffa6bbed 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.21.6 as builder
WORKDIR /workspace
# Run this with docker build --build_arg goproxy=$(go env GOPROXY) to override the goproxy
From 403c98fa85c7d605627a19a924d6c0d1be01dc06 Mon Sep 17 00:00:00 2001
From: Hugo Blom <6117705+huxcrux@users.noreply.github.com>
Date: Thu, 1 Feb 2024 16:57:24 +0100
Subject: [PATCH 049/180] Remove listener.name from from error message when not
set
---
pkg/cloud/services/loadbalancer/loadbalancer.go | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/pkg/cloud/services/loadbalancer/loadbalancer.go b/pkg/cloud/services/loadbalancer/loadbalancer.go
index 75e2201779..6ed0f83c2a 100644
--- a/pkg/cloud/services/loadbalancer/loadbalancer.go
+++ b/pkg/cloud/services/loadbalancer/loadbalancer.go
@@ -285,9 +285,10 @@ func (s *Service) getOrUpdateAllowedCIDRS(openStackCluster *infrav1.OpenStackClu
AllowedCIDRs: &allowedCIDRs,
}
+ listenerID := listener.ID
listener, err := s.loadbalancerClient.UpdateListener(listener.ID, listenerUpdateOpts)
if err != nil {
- record.Warnf(openStackCluster, "FailedUpdateListener", "Failed to update listener %s: %v", listener.Name, err)
+ record.Warnf(openStackCluster, "FailedUpdateListener", "Failed to update listener %s: %v", listenerID, err)
return err
}
From 9e356ad0db37fcbc828436ac3263506e15b7e1d4 Mon Sep 17 00:00:00 2001
From: huxcrux
Date: Fri, 2 Feb 2024 14:27:23 +0100
Subject: [PATCH 050/180] Migrate Dockerfile to use golang 1.21 to match go.mod
in project
---
Dockerfile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Dockerfile b/Dockerfile
index 03a064bd63..2cffa6bbed 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.21.6 as builder
WORKDIR /workspace
# Run this with docker build --build_arg goproxy=$(go env GOPROXY) to override the goproxy
From d6908274fe60b80fd5c75d48fa2cf954a26bfb4f Mon Sep 17 00:00:00 2001
From: Mathieu Tortuyaux
Date: Mon, 5 Feb 2024 11:52:29 +0100
Subject: [PATCH 051/180] test: bump Flatcar version
Signed-off-by: Mathieu Tortuyaux
---
hack/ci/cloud-init/controller.yaml.tpl | 2 +-
test/e2e/data/e2e_conf.yaml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/hack/ci/cloud-init/controller.yaml.tpl b/hack/ci/cloud-init/controller.yaml.tpl
index a86204b965..21fc3cf4aa 100644
--- a/hack/ci/cloud-init/controller.yaml.tpl
+++ b/hack/ci/cloud-init/controller.yaml.tpl
@@ -70,7 +70,7 @@
IMAGE_URLS+="https://storage.googleapis.com/artifacts.k8s-staging-capi-openstack.appspot.com/test/cirros/2022-12-05/cirros-0.6.1-x86_64-disk.img,"
IMAGE_URLS+="https://storage.googleapis.com/artifacts.k8s-staging-capi-openstack.appspot.com/test/ubuntu/2023-09-29/ubuntu-2204-kube-v1.27.2.img,"
IMAGE_URLS+="https://storage.googleapis.com/artifacts.k8s-staging-capi-openstack.appspot.com/test/ubuntu/2024-01-10/ubuntu-2204-kube-v1.28.5.img,"
- IMAGE_URLS+="https://storage.googleapis.com/artifacts.k8s-staging-capi-openstack.appspot.com/test/flatcar/flatcar-stable-3602.2.3-kube-v1.28.5.img,"
+ IMAGE_URLS+="https://storage.googleapis.com/artifacts.k8s-staging-capi-openstack.appspot.com/test/flatcar/flatcar-stable-3760.2.0-kube-v1.28.5.img,"
IMAGE_URLS+="https://stable.release.flatcar-linux.net/amd64-usr/current/flatcar_production_openstack_image.img"
[[post-config|$NOVA_CONF]]
diff --git a/test/e2e/data/e2e_conf.yaml b/test/e2e/data/e2e_conf.yaml
index faae3fd4db..a499a983ec 100644
--- a/test/e2e/data/e2e_conf.yaml
+++ b/test/e2e/data/e2e_conf.yaml
@@ -212,7 +212,7 @@ variables:
SSH_USER_MACHINE: "ubuntu"
EXP_KUBEADM_BOOTSTRAP_FORMAT_IGNITION: "true"
# The Flatcar image produced by the image-builder
- OPENSTACK_FLATCAR_IMAGE_NAME: "flatcar-stable-3602.2.3-kube-v1.28.5"
+ OPENSTACK_FLATCAR_IMAGE_NAME: "flatcar-stable-3760.2.0-kube-v1.28.5"
# A plain Flatcar from the Flatcar releases server
FLATCAR_IMAGE_NAME: "flatcar_production_openstack_image"
From 8fe1c8fc6aeaaab2c09141e11db3f171c74c9b2e Mon Sep 17 00:00:00 2001
From: bilbo
Date: Tue, 6 Feb 2024 15:28:19 +0100
Subject: [PATCH 052/180] Adds Kind to ipaddress pool name index
---
controllers/openstackfloatingippool_controller.go | 3 +++
1 file changed, 3 insertions(+)
diff --git a/controllers/openstackfloatingippool_controller.go b/controllers/openstackfloatingippool_controller.go
index 6ee65140a3..7e2e78f612 100644
--- a/controllers/openstackfloatingippool_controller.go
+++ b/controllers/openstackfloatingippool_controller.go
@@ -456,6 +456,9 @@ func (r *OpenStackFloatingIPPoolReconciler) SetupWithManager(ctx context.Context
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
From 3f806e0f48ae72a539359bfe08698b78c3368062 Mon Sep 17 00:00:00 2001
From: Oleksandr K
Date: Tue, 6 Feb 2024 16:22:58 +0100
Subject: [PATCH 053/180] fix: fix the block device type name in doc
---
docs/book/src/topics/crd-changes/v1alpha6-to-v1alpha7.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/book/src/topics/crd-changes/v1alpha6-to-v1alpha7.md b/docs/book/src/topics/crd-changes/v1alpha6-to-v1alpha7.md
index 25937afa52..ffb1cb7635 100644
--- a/docs/book/src/topics/crd-changes/v1alpha6-to-v1alpha7.md
+++ b/docs/book/src/topics/crd-changes/v1alpha6-to-v1alpha7.md
@@ -226,7 +226,7 @@ additionalBlockDevices:
- name: database
sizeGiB: 50
storage:
- type: volume
+ type: Volume
```
Here is an example on how to use `additionalBlockDevices` for adding an additional Cinder volume attached
@@ -237,7 +237,7 @@ additionalBlockDevices:
- name: database
sizeGiB: 50
storage:
- type: volume
+ type: Volume
volume:
type: my-volume-type
availabilityZone: az0
From cca22139805ae72fec45a97b23785413c3e9c106 Mon Sep 17 00:00:00 2001
From: bilbo
Date: Tue, 6 Feb 2024 16:33:12 +0100
Subject: [PATCH 054/180] Make sure to keep availableIPs and is in sync
---
controllers/openstackfloatingippool_controller.go | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/controllers/openstackfloatingippool_controller.go b/controllers/openstackfloatingippool_controller.go
index 6ee65140a3..40a6e8f9f5 100644
--- a/controllers/openstackfloatingippool_controller.go
+++ b/controllers/openstackfloatingippool_controller.go
@@ -296,8 +296,8 @@ func (r *OpenStackFloatingIPPoolReconciler) reconcileIPAddresses(ctx context.Con
return err
}
}
- unclaimedPreAllocatedIPs := diff(pool.Spec.PreAllocatedFloatingIPs, pool.Status.ClaimedIPs)
- unclaimedIPs := union(pool.Status.AvailableIPs, unclaimedPreAllocatedIPs)
+ allIPs := union(pool.Status.AvailableIPs, pool.Spec.PreAllocatedFloatingIPs)
+ unclaimedIPs := diff(allIPs, pool.Status.ClaimedIPs)
pool.Status.AvailableIPs = diff(unclaimedIPs, pool.Status.FailedIPs)
return nil
}
@@ -313,7 +313,7 @@ func (r *OpenStackFloatingIPPoolReconciler) getIP(ctx context.Context, scope sco
}
// 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 to prevent leaking floating IPs if the floating IP was created but the IPAddress object was not
+ // 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 {
@@ -332,6 +332,7 @@ func (r *OpenStackFloatingIPPoolReconciler) getIP(ctx context.Context, scope sco
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 != "" {
@@ -342,15 +343,13 @@ func (r *OpenStackFloatingIPPoolReconciler) getIP(ctx context.Context, scope sco
if fp != nil {
return fp.FloatingIP, nil
}
+ pool.Status.FailedIPs = append(pool.Status.FailedIPs, ip)
}
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)
- if ip != "" {
- pool.Status.FailedIPs = append(pool.Status.FailedIPs, ip)
- }
return "", err
}
defer func() {
From 2c8a1a62303fa7beb62a3afd559de5ee16906340 Mon Sep 17 00:00:00 2001
From: Tuomo Tanskanen
Date: Wed, 7 Feb 2024 15:34:59 +0200
Subject: [PATCH 055/180] add TLS configuration flags support
Add --tls-min-version and --tls-max-versin configuration flags.
Same flags can be found in k8s, CAPI, CAPM3 etc.
Co-authored-by: Jawad Zaheer
Signed-off-by: Tuomo Tanskanen
---
main.go | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++-
main_test.go | 111 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 224 insertions(+), 2 deletions(-)
create mode 100644 main_test.go
diff --git a/main.go b/main.go
index 01c6caa6a3..f9dfdd5d03 100644
--- a/main.go
+++ b/main.go
@@ -17,11 +17,13 @@ package main
import (
"context"
+ "crypto/tls"
"flag"
"fmt"
"net/http"
_ "net/http/pprof"
"os"
+ "strings"
"time"
"github.com/spf13/pflag"
@@ -55,9 +57,23 @@ import (
"sigs.k8s.io/cluster-api-provider-openstack/version"
)
+// Constants for TLS versions.
+const (
+ TLSVersion12 = "TLS12"
+ TLSVersion13 = "TLS13"
+)
+
+type TLSOptions struct {
+ TLSMaxVersion string
+ TLSMinVersion string
+ TLSCipherSuites string
+}
+
var (
- scheme = runtime.NewScheme()
- setupLog = ctrl.Log.WithName("setup")
+ scheme = runtime.NewScheme()
+ setupLog = ctrl.Log.WithName("setup")
+ tlsOptions = TLSOptions{}
+ tlsSupportedVersions = []string{TLSVersion12, TLSVersion13}
// flags.
diagnosticsOptions = flags.DiagnosticsOptions{}
@@ -157,6 +173,24 @@ func InitFlags(fs *pflag.FlagSet) {
fs.IntVar(&scopeCacheMaxSize, "scope-cache-max-size", 10, "The maximum credentials count the operator should keep in cache. Setting this value to 0 means no cache.")
fs.BoolVar(&showVersion, "version", false, "Show current version and exit.")
+
+ fs.StringVar(&tlsOptions.TLSMinVersion, "tls-min-version", TLSVersion12,
+ "The minimum TLS version in use by the webhook server.\n"+
+ fmt.Sprintf("Possible values are %s.", strings.Join(tlsSupportedVersions, ", ")),
+ )
+
+ fs.StringVar(&tlsOptions.TLSMaxVersion, "tls-max-version", TLSVersion13,
+ "The maximum TLS version in use by the webhook server.\n"+
+ fmt.Sprintf("Possible values are %s.", strings.Join(tlsSupportedVersions, ", ")),
+ )
+
+ tlsCipherPreferredValues := cliflag.PreferredTLSCipherNames()
+ tlsCipherInsecureValues := cliflag.InsecureTLSCipherNames()
+ fs.StringVar(&tlsOptions.TLSCipherSuites, "tls-cipher-suites", "",
+ "Comma-separated list of cipher suites for the webhook server. "+
+ "If omitted, the default Go cipher suites will be used. \n"+
+ "Preferred values: "+strings.Join(tlsCipherPreferredValues, ", ")+". \n"+
+ "Insecure values: "+strings.Join(tlsCipherInsecureValues, ", ")+".")
}
// Add RBAC for the authorized diagnostics endpoint.
@@ -189,6 +223,12 @@ func main() {
}()
}
+ tlsOptionOverrides, err := GetTLSOptionOverrideFuncs(tlsOptions)
+ if err != nil {
+ setupLog.Error(err, "unable to add TLS settings to the webhook server")
+ os.Exit(1)
+ }
+
cfg, err := config.GetConfigWithContext(os.Getenv("KUBECONTEXT"))
if err != nil {
setupLog.Error(err, "unable to get kubeconfig")
@@ -238,6 +278,7 @@ func main() {
webhook.Options{
Port: webhookPort,
CertDir: webhookCertDir,
+ TLSOpts: tlsOptionOverrides,
},
),
HealthProbeBindAddress: healthAddr,
@@ -345,3 +386,73 @@ func setupWebhooks(mgr ctrl.Manager) {
func concurrency(c int) controller.Options {
return controller.Options{MaxConcurrentReconciles: c}
}
+
+// GetTLSOptionOverrideFuncs returns a list of TLS configuration overrides to be used
+// by the webhook server.
+func GetTLSOptionOverrideFuncs(options TLSOptions) ([]func(*tls.Config), error) {
+ var tlsOptions []func(config *tls.Config)
+
+ tlsMinVersion, err := GetTLSVersion(options.TLSMinVersion)
+ if err != nil {
+ return nil, err
+ }
+
+ tlsMaxVersion, err := GetTLSVersion(options.TLSMaxVersion)
+ if err != nil {
+ return nil, err
+ }
+
+ if tlsMaxVersion != 0 && tlsMinVersion > tlsMaxVersion {
+ return nil, fmt.Errorf("TLS version flag min version (%s) is greater than max version (%s)",
+ options.TLSMinVersion, options.TLSMaxVersion)
+ }
+
+ tlsOptions = append(tlsOptions, func(cfg *tls.Config) {
+ cfg.MinVersion = tlsMinVersion
+ cfg.MaxVersion = tlsMaxVersion
+ })
+
+ // Cipher suites should not be set if empty.
+ if tlsMinVersion >= tls.VersionTLS13 &&
+ options.TLSCipherSuites != "" {
+ setupLog.Info("warning: Cipher suites should not be set for TLS version 1.3. Ignoring ciphers")
+ options.TLSCipherSuites = ""
+ }
+
+ if options.TLSCipherSuites != "" {
+ tlsCipherSuites := strings.Split(options.TLSCipherSuites, ",")
+ suites, err := cliflag.TLSCipherSuites(tlsCipherSuites)
+ if err != nil {
+ return nil, err
+ }
+
+ insecureCipherValues := cliflag.InsecureTLSCipherNames()
+ for _, cipher := range tlsCipherSuites {
+ for _, insecureCipherName := range insecureCipherValues {
+ if insecureCipherName == cipher {
+ setupLog.Info(fmt.Sprintf("warning: use of insecure cipher '%s' detected.", cipher))
+ }
+ }
+ }
+ tlsOptions = append(tlsOptions, func(cfg *tls.Config) {
+ cfg.CipherSuites = suites
+ })
+ }
+
+ return tlsOptions, nil
+}
+
+// GetTLSVersion returns the corresponding tls.Version or error.
+func GetTLSVersion(version string) (uint16, error) {
+ var v uint16
+
+ switch version {
+ case TLSVersion12:
+ v = tls.VersionTLS12
+ case TLSVersion13:
+ v = tls.VersionTLS13
+ default:
+ return 0, fmt.Errorf("unexpected TLS version %q (must be one of: %s)", version, strings.Join(tlsSupportedVersions, ", "))
+ }
+ return v, nil
+}
diff --git a/main_test.go b/main_test.go
new file mode 100644
index 0000000000..b4139280c8
--- /dev/null
+++ b/main_test.go
@@ -0,0 +1,111 @@
+/*
+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 main
+
+import (
+ "bytes"
+ "testing"
+
+ . "github.com/onsi/gomega"
+ "k8s.io/klog/v2"
+ ctrl "sigs.k8s.io/controller-runtime"
+)
+
+func TestTLSInsecureCiperSuite(t *testing.T) {
+ t.Run("test insecure cipher suite passed as TLS flag", func(t *testing.T) {
+ g := NewWithT(t)
+ tlsMockOptions := TLSOptions{
+ TLSMaxVersion: "TLS13",
+ TLSMinVersion: "TLS12",
+ TLSCipherSuites: "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
+ }
+ ctrl.Log.WithName("setup")
+ ctrl.SetLogger(klog.Background())
+
+ bufWriter := bytes.NewBuffer(nil)
+ klog.SetOutput(bufWriter)
+ klog.LogToStderr(false) // this is important, because klog by default logs to stderr only
+ _, err := GetTLSOptionOverrideFuncs(tlsMockOptions)
+ g.Expect(err).Should(BeNil())
+ g.Expect(bufWriter.String()).Should(ContainSubstring("use of insecure cipher 'TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256' detected."))
+ })
+}
+
+func TestTLSMinAndMaxVersion(t *testing.T) {
+ t.Run("should fail if TLS min version is greater than max version.", func(t *testing.T) {
+ g := NewWithT(t)
+ tlsMockOptions := TLSOptions{
+ TLSMaxVersion: "TLS12",
+ TLSMinVersion: "TLS13",
+ }
+ _, err := GetTLSOptionOverrideFuncs(tlsMockOptions)
+ g.Expect(err.Error()).To(Equal("TLS version flag min version (TLS13) is greater than max version (TLS12)"))
+ })
+}
+
+func Test13CipherSuite(t *testing.T) {
+ t.Run("should reset ciphersuite flag if TLS min and max version are set to 1.3", func(t *testing.T) {
+ g := NewWithT(t)
+
+ // Here TLS_RSA_WITH_AES_128_CBC_SHA is a tls12 cipher suite.
+ tlsMockOptions := TLSOptions{
+ TLSMaxVersion: "TLS13",
+ TLSMinVersion: "TLS13",
+ TLSCipherSuites: "TLS_RSA_WITH_AES_128_CBC_SHA,TLS_AES_256_GCM_SHA384",
+ }
+
+ ctrl.Log.WithName("setup")
+ ctrl.SetLogger(klog.Background())
+
+ bufWriter := bytes.NewBuffer(nil)
+ klog.SetOutput(bufWriter)
+ klog.LogToStderr(false) // this is important, because klog by default logs to stderr only
+ _, err := GetTLSOptionOverrideFuncs(tlsMockOptions)
+ g.Expect(bufWriter.String()).Should(ContainSubstring("warning: Cipher suites should not be set for TLS version 1.3. Ignoring ciphers"))
+ g.Expect(err).Should(BeNil())
+ })
+}
+
+func TestGetTLSVersion(t *testing.T) {
+ t.Run("should error out when incorrect tls version passed", func(t *testing.T) {
+ g := NewWithT(t)
+ tlsVersion := "TLS11"
+ _, err := GetTLSVersion(tlsVersion)
+ g.Expect(err.Error()).Should(Equal("unexpected TLS version \"TLS11\" (must be one of: TLS12, TLS13)"))
+ })
+ t.Run("should pass and output correct tls version", func(t *testing.T) {
+ const VersionTLS12 uint16 = 771
+ g := NewWithT(t)
+ tlsVersion := "TLS12"
+ version, err := GetTLSVersion(tlsVersion)
+ g.Expect(version).To(Equal(VersionTLS12))
+ g.Expect(err).Should(BeNil())
+ })
+}
+
+func TestTLSOptions(t *testing.T) {
+ t.Run("should pass with all the correct options below with no error.", func(t *testing.T) {
+ g := NewWithT(t)
+ tlsMockOptions := TLSOptions{
+ TLSMinVersion: "TLS12",
+ TLSMaxVersion: "TLS13",
+ TLSCipherSuites: "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
+ }
+ _, err := GetTLSOptionOverrideFuncs(tlsMockOptions)
+ g.Expect(err).Should(BeNil())
+ })
+}
From e6092b8c497fe1a2eea462b6442950bb76dc8f64 Mon Sep 17 00:00:00 2001
From: Emilien Macchi
Date: Wed, 24 Jan 2024 06:36:12 -0500
Subject: [PATCH 056/180] api: openstackcluster.status default to false
When a reconcile loop for the bastion is requeued, we have
this error:
```
OpenStackCluster.infrastructure.cluster.x-k8s.io \"cluster-e2e-rha0r3\" is invalid: ready: Required value"
```
The OpenStackMachine.Status is false by default now, so if the status
has not been set to anything, patching the object will not fail with the
previous error.
---
api/v1alpha8/openstackcluster_types.go | 2 ++
.../infrastructure.cluster.x-k8s.io_openstackclusters.yaml | 2 ++
2 files changed, 4 insertions(+)
diff --git a/api/v1alpha8/openstackcluster_types.go b/api/v1alpha8/openstackcluster_types.go
index 7430fab1ab..67a1bc4a0a 100644
--- a/api/v1alpha8/openstackcluster_types.go
+++ b/api/v1alpha8/openstackcluster_types.go
@@ -167,6 +167,8 @@ type OpenStackClusterSpec struct {
// 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.
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 0b48da7dc2..3caa2cbe2f 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -5849,6 +5849,8 @@ spec:
- 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
From 20f2a3c864611b61ccca88dd3d8aef6095d52f02 Mon Sep 17 00:00:00 2001
From: Emilien Macchi
Date: Tue, 6 Feb 2024 18:16:05 -0500
Subject: [PATCH 057/180] Prevent the bastion to be removed before it's been
disabled
We now have a webhook that checks that a bastion has been disabled if a
change has to be made (update or delete) in the bastion field.
We also document it better.
Also, we added some code to prevent that we don't have a nil pointer if
the Spec.Bastion or Status.Bastion are unset.
---
api/v1alpha8/openstackcluster_types.go | 4 +--
api/v1alpha8/openstackcluster_webhook.go | 7 ++++
api/v1alpha8/openstackcluster_webhook_test.go | 36 +++++++++++++++++++
...re.cluster.x-k8s.io_openstackclusters.yaml | 4 +--
...er.x-k8s.io_openstackclustertemplates.yaml | 4 +--
controllers/openstackcluster_controller.go | 22 +++++++++---
.../src/clusteropenstack/configuration.md | 15 ++++++++
7 files changed, 82 insertions(+), 10 deletions(-)
diff --git a/api/v1alpha8/openstackcluster_types.go b/api/v1alpha8/openstackcluster_types.go
index 7430fab1ab..2409a91841 100644
--- a/api/v1alpha8/openstackcluster_types.go
+++ b/api/v1alpha8/openstackcluster_types.go
@@ -155,8 +155,8 @@ type OpenStackClusterSpec struct {
// 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"`
diff --git a/api/v1alpha8/openstackcluster_webhook.go b/api/v1alpha8/openstackcluster_webhook.go
index 2344870c7d..b47c2ac612 100644
--- a/api/v1alpha8/openstackcluster_webhook.go
+++ b/api/v1alpha8/openstackcluster_webhook.go
@@ -116,6 +116,13 @@ func (r *OpenStackCluster) ValidateUpdate(oldRaw runtime.Object) (admission.Warn
r.Spec.APIServerPort = 0
}
+ // Allow to remove the bastion spec only if it was disabled before.
+ if r.Spec.Bastion == nil {
+ if old.Spec.Bastion != nil && old.Spec.Bastion.Enabled {
+ allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "bastion"), "cannot be removed before disabling it"))
+ }
+ }
+
// Allow changes to the bastion spec.
old.Spec.Bastion = &Bastion{}
r.Spec.Bastion = &Bastion{}
diff --git a/api/v1alpha8/openstackcluster_webhook_test.go b/api/v1alpha8/openstackcluster_webhook_test.go
index 27e8ab34db..734a388763 100644
--- a/api/v1alpha8/openstackcluster_webhook_test.go
+++ b/api/v1alpha8/openstackcluster_webhook_test.go
@@ -358,6 +358,42 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
wantErr: true,
},
+ {
+ name: "Removing OpenStackCluster.Spec.Bastion when it is enabled is not allowed",
+ oldTemplate: &OpenStackCluster{
+ Spec: OpenStackClusterSpec{
+ Bastion: &Bastion{
+ Enabled: true,
+ Instance: OpenStackMachineSpec{
+ Flavor: "m1.small",
+ Image: ImageFilter{Name: "ubuntu"},
+ },
+ },
+ },
+ },
+ newTemplate: &OpenStackCluster{
+ Spec: OpenStackClusterSpec{},
+ },
+ wantErr: true,
+ },
+ {
+ name: "Removing OpenStackCluster.Spec.Bastion when it is disabled is allowed",
+ oldTemplate: &OpenStackCluster{
+ Spec: OpenStackClusterSpec{
+ Bastion: &Bastion{
+ Enabled: false,
+ Instance: OpenStackMachineSpec{
+ Flavor: "m1.small",
+ Image: ImageFilter{Name: "ubuntu"},
+ },
+ },
+ },
+ },
+ newTemplate: &OpenStackCluster{
+ Spec: OpenStackClusterSpec{},
+ },
+ wantErr: false,
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
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 0b48da7dc2..583b473650 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -4899,8 +4899,8 @@ spec:
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.
properties:
availabilityZone:
type: string
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 2cab684d19..ae5555b4a2 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -2324,8 +2324,8 @@ spec:
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.
properties:
availabilityZone:
type: string
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index 51361a1a85..d63a6692da 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -263,7 +263,10 @@ func deleteBastion(scope scope.Scope, cluster *clusterv1.Cluster, openStackClust
}
}
- instanceSpec := bastionToInstanceSpec(openStackCluster, cluster.Name)
+ instanceSpec, err := bastionToInstanceSpec(openStackCluster, cluster.Name)
+ if err != nil {
+ return err
+ }
if err = computeService.DeleteInstance(openStackCluster, openStackCluster, instanceStatus, instanceSpec); err != nil {
handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to delete bastion: %w", err))
return fmt.Errorf("failed to delete bastion: %w", err)
@@ -346,7 +349,10 @@ func reconcileBastion(scope scope.Scope, cluster *clusterv1.Cluster, openStackCl
return reconcile.Result{}, err
}
- instanceSpec := bastionToInstanceSpec(openStackCluster, cluster.Name)
+ instanceSpec, err := bastionToInstanceSpec(openStackCluster, cluster.Name)
+ if err != nil {
+ return reconcile.Result{}, err
+ }
bastionHash, err := compute.HashInstanceSpec(instanceSpec)
if err != nil {
return reconcile.Result{}, fmt.Errorf("failed computing bastion hash from instance spec: %w", err)
@@ -437,7 +443,15 @@ func reconcileBastion(scope scope.Scope, cluster *clusterv1.Cluster, openStackCl
return ctrl.Result{}, nil
}
-func bastionToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, clusterName string) *compute.InstanceSpec {
+func bastionToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, clusterName string) (*compute.InstanceSpec, error) {
+ if openStackCluster.Spec.Bastion == nil {
+ return nil, fmt.Errorf("bastion spec is nil")
+ }
+
+ if openStackCluster.Status.Bastion == nil {
+ return nil, fmt.Errorf("bastion status is nil")
+ }
+
instanceSpec := &compute.InstanceSpec{
Name: bastionName(clusterName),
Flavor: openStackCluster.Spec.Bastion.Instance.Flavor,
@@ -458,7 +472,7 @@ func bastionToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, clusterNa
instanceSpec.Ports = openStackCluster.Spec.Bastion.Instance.Ports
- return instanceSpec
+ return instanceSpec, nil
}
func bastionName(clusterName string) string {
diff --git a/docs/book/src/clusteropenstack/configuration.md b/docs/book/src/clusteropenstack/configuration.md
index 1a075bc57e..3ae013333f 100644
--- a/docs/book/src/clusteropenstack/configuration.md
+++ b/docs/book/src/clusteropenstack/configuration.md
@@ -35,6 +35,8 @@
- [Custom pod network CIDR](#custom-pod-network-cidr)
- [Accessing nodes through the bastion host via SSH](#accessing-nodes-through-the-bastion-host-via-ssh)
- [Enabling the bastion host](#enabling-the-bastion-host)
+ - [Making changes to the bastion host](#making-changes-to-the-bastion-host)
+ - [Disabling the bastion](#disabling-the-bastion)
- [Obtain floating IP address of the bastion node](#obtain-floating-ip-address-of-the-bastion-node)
@@ -654,6 +656,19 @@ spec:
If `managedSecurityGroups: true`, security group rule opening 22/tcp is added to security groups for bastion, controller, and worker nodes respectively. Otherwise, you have to add `securityGroups` to the `bastion` in `OpenStackCluster` spec and `OpenStackMachineTemplate` spec template respectively.
+### Making changes to the bastion host
+
+Changes can be made to the bastion instance, like for example changing the flavor.
+First, you have to disable the bastion host by setting `enabled: false` in the `OpenStackCluster.Spec.Bastion` field.
+The bastion will be deleted, you can check the status of the bastion host by running `kubectl get openstackcluster` and looking at the `Bastion` field in status.
+Once it's gone, you can re-enable the bastion host by setting `enabled: true` and then making changes to the bastion instance spec by modifying the `OpenStackCluster.Spec.Bastion.Instance` field.
+The bastion host will be re-created with the new instance spec.
+
+### Disabling the bastion
+
+To disable the bastion host, set `enabled: false` in the `OpenStackCluster.Spec.Bastion` field. The bastion host will be deleted, you can check the status of the bastion host by running `kubectl get openstackcluster` and looking at the `Bastion` field in status.
+Once it's gone, you can now remove the `OpenStackCluster.Spec.Bastion` field from the `OpenStackCluster` spec.
+
### Obtain floating IP address of the bastion node
Once the workload cluster is up and running after being configured for an SSH bastion host, you can use the kubectl get openstackcluster command to look up the floating IP address of the bastion host (make sure the kubectl context is set to the management cluster). The output will look something like this:
From b31989356b85891b6413b09ce86dbdf91280c843 Mon Sep 17 00:00:00 2001
From: Emilien Macchi
Date: Mon, 30 Oct 2023 11:36:55 -0400
Subject: [PATCH 058/180] loadbalancer: resolve ControlPlaneEndpoint.Host when
needed
`ControlPlaneEndpoint.Host` is not guaranteed to be an IP address, it
can also be an hostname.
Now we'll try to lookup the hostname if it's not an IP and set that for
the LB VipAddress.
---
.../services/loadbalancer/loadbalancer.go | 38 ++++++++++++++++---
.../loadbalancer/loadbalancer_test.go | 18 +++++++++
2 files changed, 51 insertions(+), 5 deletions(-)
diff --git a/pkg/cloud/services/loadbalancer/loadbalancer.go b/pkg/cloud/services/loadbalancer/loadbalancer.go
index 9b0cd15b4f..956e346002 100644
--- a/pkg/cloud/services/loadbalancer/loadbalancer.go
+++ b/pkg/cloud/services/loadbalancer/loadbalancer.go
@@ -17,8 +17,10 @@ limitations under the License.
package loadbalancer
import (
+ "context"
"errors"
"fmt"
+ "net"
"slices"
"time"
@@ -27,7 +29,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/monitors"
"github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/pools"
"k8s.io/apimachinery/pkg/util/wait"
- "k8s.io/utils/net"
+ utilsnet "k8s.io/utils/net"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
"sigs.k8s.io/cluster-api/util"
@@ -42,10 +44,28 @@ import (
const (
networkPrefix string = "k8s-clusterapi"
kubeapiLBSuffix string = "kubeapi"
+ resolvedMsg string = "ControlPlaneEndpoint.Host is not an IP address, using the first resolved IP address"
)
const loadBalancerProvisioningStatusActive = "ACTIVE"
+// We wrap the LookupHost function in a variable to allow overriding it in unit tests.
+//
+//nolint:gocritic
+var lookupHost = func(host string) (string, error) {
+ ctx, cancel := context.WithTimeout(context.TODO(), 30*time.Second)
+ defer cancel()
+ ips, err := net.DefaultResolver.LookupHost(ctx, host)
+ if err != nil {
+ return "", err
+ }
+ if ip := net.ParseIP(ips[0]); ip == nil {
+ return "", fmt.Errorf("failed to resolve IP address for host %s", host)
+ }
+ return ips[0], nil
+}
+
+// ReconcileLoadBalancer reconciles the load balancer for the given cluster.
func (s *Service) ReconcileLoadBalancer(openStackCluster *infrav1.OpenStackCluster, clusterName string, apiServerPort int) (bool, error) {
loadBalancerName := getLoadBalancerName(clusterName)
s.scope.Logger().Info("Reconciling load balancer", "name", loadBalancerName)
@@ -57,13 +77,18 @@ func (s *Service) ReconcileLoadBalancer(openStackCluster *infrav1.OpenStackClust
}
var fixedIPAddress string
+ var err error
+
switch {
case lbStatus.InternalIP != "":
fixedIPAddress = lbStatus.InternalIP
case openStackCluster.Spec.APIServerFixedIP != "":
fixedIPAddress = openStackCluster.Spec.APIServerFixedIP
case openStackCluster.Spec.DisableAPIServerFloatingIP && openStackCluster.Spec.ControlPlaneEndpoint.IsValid():
- fixedIPAddress = openStackCluster.Spec.ControlPlaneEndpoint.Host
+ fixedIPAddress, err = lookupHost(openStackCluster.Spec.ControlPlaneEndpoint.Host)
+ if err != nil {
+ return false, fmt.Errorf("lookup host: %w", err)
+ }
}
providers, err := s.loadbalancerClient.ListLoadBalancerProviders()
@@ -108,7 +133,10 @@ func (s *Service) ReconcileLoadBalancer(openStackCluster *infrav1.OpenStackClust
case openStackCluster.Spec.APIServerFloatingIP != "":
floatingIPAddress = openStackCluster.Spec.APIServerFloatingIP
case openStackCluster.Spec.ControlPlaneEndpoint.IsValid():
- floatingIPAddress = openStackCluster.Spec.ControlPlaneEndpoint.Host
+ floatingIPAddress, err = lookupHost(openStackCluster.Spec.ControlPlaneEndpoint.Host)
+ if err != nil {
+ return false, fmt.Errorf("lookup host: %w", err)
+ }
}
fp, err := s.networkingService.GetOrCreateFloatingIP(openStackCluster, openStackCluster, clusterName, floatingIPAddress)
if err != nil {
@@ -308,9 +336,9 @@ func validateIPs(openStackCluster *infrav1.OpenStackCluster, definedCIDRs []stri
for _, v := range definedCIDRs {
switch {
- case net.IsIPv4String(v):
+ case utilsnet.IsIPv4String(v):
marshaledCIDRs = append(marshaledCIDRs, v+"/32")
- case net.IsIPv4CIDRString(v):
+ case utilsnet.IsIPv4CIDRString(v):
marshaledCIDRs = append(marshaledCIDRs, v)
default:
record.Warnf(openStackCluster, "FailedIPAddressValidation", "%s is not a valid IPv4 nor CIDR address and will not get applied to allowed_cidrs", v)
diff --git a/pkg/cloud/services/loadbalancer/loadbalancer_test.go b/pkg/cloud/services/loadbalancer/loadbalancer_test.go
index 4eb4737712..b4a8960a29 100644
--- a/pkg/cloud/services/loadbalancer/loadbalancer_test.go
+++ b/pkg/cloud/services/loadbalancer/loadbalancer_test.go
@@ -17,6 +17,8 @@ limitations under the License.
package loadbalancer
import (
+ "errors"
+ "net"
"testing"
"github.com/go-logr/logr"
@@ -28,6 +30,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/pools"
"github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/providers"
. "github.com/onsi/gomega"
+ clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/mock"
@@ -38,9 +41,24 @@ func Test_ReconcileLoadBalancer(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
+ // Stub the call to net.LookupHost
+ lookupHost = func(host string) (addrs string, err error) {
+ if net.ParseIP(host) != nil {
+ return host, nil
+ } else if host == "api.test-cluster.test" {
+ ips := []string{"192.168.100.10"}
+ return ips[0], nil
+ }
+ return "", errors.New("Unknown Host " + host)
+ }
+
openStackCluster := &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
DisableAPIServerFloatingIP: true,
+ ControlPlaneEndpoint: clusterv1.APIEndpoint{
+ Host: "api.test-cluster.test",
+ Port: 6443,
+ },
},
Status: infrav1.OpenStackClusterStatus{
ExternalNetwork: &infrav1.NetworkStatus{
From 42c0ef97b11b1bf71dac2a9285b6601e70c33f16 Mon Sep 17 00:00:00 2001
From: bilbo
Date: Tue, 6 Feb 2024 10:38:17 +0100
Subject: [PATCH 059/180] Adds MaxIPs to OpenstackFloatingIPPool
---
api/v1alpha1/conditions_consts.go | 3 +++
api/v1alpha1/openstackfloatingippool_types.go | 5 +++++
api/v1alpha1/zz_generated.deepcopy.go | 5 +++++
...luster.x-k8s.io_openstackfloatingippools.yaml | 5 +++++
.../openstackfloatingippool_controller.go | 16 +++++++++++++++-
5 files changed, 33 insertions(+), 1 deletion(-)
diff --git a/api/v1alpha1/conditions_consts.go b/api/v1alpha1/conditions_consts.go
index 32d80d51d7..bc1627604a 100644
--- a/api/v1alpha1/conditions_consts.go
+++ b/api/v1alpha1/conditions_consts.go
@@ -19,4 +19,7 @@ package v1alpha1
const (
// OpenstackFloatingIPPoolReadyCondition reports on the current status of the floating ip pool. Ready indicates that the pool is ready to be used.
OpenstackFloatingIPPoolReadyCondition = "OpenstackFloatingIPPoolReadyCondition"
+
+ // MaxIPsReachedReason is set when the maximum number of floating IPs has been reached.
+ MaxIPsReachedReason = "MaxIPsReached"
)
diff --git a/api/v1alpha1/openstackfloatingippool_types.go b/api/v1alpha1/openstackfloatingippool_types.go
index 0f6c4e129f..fe3316e4af 100644
--- a/api/v1alpha1/openstackfloatingippool_types.go
+++ b/api/v1alpha1/openstackfloatingippool_types.go
@@ -56,6 +56,11 @@ type OpenStackFloatingIPPoolSpec struct {
// 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.
// +optional
IdentityRef *infrav1alpha7.OpenStackIdentityReference `json:"identityRef,omitempty"`
diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go
index 0eef1f41d3..353d53b3b7 100644
--- a/api/v1alpha1/zz_generated.deepcopy.go
+++ b/api/v1alpha1/zz_generated.deepcopy.go
@@ -93,6 +93,11 @@ func (in *OpenStackFloatingIPPoolSpec) DeepCopyInto(out *OpenStackFloatingIPPool
*out = make([]string, len(*in))
copy(*out, *in)
}
+ if in.MaxIPs != nil {
+ in, out := &in.MaxIPs, &out.MaxIPs
+ *out = new(int)
+ **out = **in
+ }
if in.IdentityRef != nil {
in, out := &in.IdentityRef, &out.IdentityRef
*out = new(v1alpha7.OpenStackIdentityReference)
diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackfloatingippools.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackfloatingippools.yaml
index a38c86c0cc..e7677735be 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackfloatingippools.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackfloatingippools.yaml
@@ -86,6 +86,11 @@ spec:
- kind
- 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.
diff --git a/controllers/openstackfloatingippool_controller.go b/controllers/openstackfloatingippool_controller.go
index a5887e88df..c01a5603dd 100644
--- a/controllers/openstackfloatingippool_controller.go
+++ b/controllers/openstackfloatingippool_controller.go
@@ -51,6 +51,8 @@ const (
openStackFloatingIPPool = "OpenStackFloatingIPPool"
)
+var errMaxIPsReached = errors.New("maximum number of IPs reached")
+
var backoff = wait.Backoff{
Steps: 4,
Duration: 10 * time.Millisecond,
@@ -139,6 +141,10 @@ func (r *OpenStackFloatingIPPoolReconciler) Reconcile(ctx context.Context, req c
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
}
@@ -193,6 +199,7 @@ func (r *OpenStackFloatingIPPoolReconciler) Reconcile(ctx context.Context, req c
scope.Logger().Info("Claimed IP", "ip", ipAddress.Spec.Address)
}
}
+ conditions.MarkTrue(pool, infrav1alpha1.OpenstackFloatingIPPoolReadyCondition)
return ctrl.Result{}, r.Client.Status().Update(ctx, pool)
}
@@ -341,10 +348,18 @@ func (r *OpenStackFloatingIPPoolReconciler) getIP(ctx context.Context, scope sco
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 := pointer.IntDeref(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 {
@@ -368,7 +383,6 @@ func (r *OpenStackFloatingIPPoolReconciler) getIP(ctx context.Context, scope sco
}()
conditions.MarkTrue(pool, infrav1alpha1.OpenstackFloatingIPPoolReadyCondition)
-
ip = fp.FloatingIP
pool.Status.ClaimedIPs = append(pool.Status.ClaimedIPs, ip)
return ip, nil
From 12a7b7270ed0fa89559b3d9c280aac9965281614 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20Dulko?=
Date: Fri, 2 Feb 2024 11:42:44 +0100
Subject: [PATCH 060/180] Move subnet options to SubnetSpec
This commit introduces SubnetSpec field onto the OpenStackClusterSpec
that is supposed to hold all options related to subnets created by CAPO.
This means nodeCidr and DNSNameservers are moved into that struct.
---
api/v1alpha5/conversion.go | 15 ++++++
api/v1alpha5/zz_generated.conversion.go | 7 ++-
api/v1alpha6/conversion.go | 20 ++++++++
api/v1alpha6/conversion_test.go | 11 +++++
api/v1alpha6/zz_generated.conversion.go | 7 ++-
api/v1alpha7/conversion.go | 49 +++++++++++++++++++
api/v1alpha7/conversion_test.go | 10 ++++
api/v1alpha7/zz_generated.conversion.go | 7 ++-
api/v1alpha8/openstackcluster_types.go | 14 ++----
api/v1alpha8/types.go | 10 ++++
api/v1alpha8/zz_generated.deepcopy.go | 32 ++++++++++--
...re.cluster.x-k8s.io_openstackclusters.yaml | 39 +++++++++------
...er.x-k8s.io_openstackclustertemplates.yaml | 39 +++++++++------
controllers/openstackcluster_controller.go | 10 ++--
.../src/clusteropenstack/configuration.md | 2 +-
.../crd-changes/v1alpha7-to-v1alpha8.md | 21 +++++++-
.../v1alpha8/default/cluster-template.yaml | 7 +--
pkg/cloud/services/networking/network.go | 10 ++--
.../cluster-template-flatcar-sysext.yaml | 7 +--
templates/cluster-template-flatcar.yaml | 7 +--
templates/cluster-template-without-lb.yaml | 7 +--
templates/cluster-template.yaml | 7 +--
templates/clusterclass-dev-test.yaml | 7 +--
23 files changed, 261 insertions(+), 84 deletions(-)
diff --git a/api/v1alpha5/conversion.go b/api/v1alpha5/conversion.go
index ddaf5d71ab..bfb8329cf4 100644
--- a/api/v1alpha5/conversion.go
+++ b/api/v1alpha5/conversion.go
@@ -196,6 +196,11 @@ func Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(in *
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_v1alpha8_SubnetFilter_To_v1alpha5_SubnetFilter(&in.Subnets[0], &out.Subnet, s); err != nil {
@@ -228,6 +233,16 @@ func Convert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *
out.Subnets = []infrav1.SubnetFilter{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.
+
return nil
}
diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go
index 20646768bf..c9e8b952a2 100644
--- a/api/v1alpha5/zz_generated.conversion.go
+++ b/api/v1alpha5/zz_generated.conversion.go
@@ -655,12 +655,12 @@ func Convert_v1alpha8_OpenStackClusterList_To_v1alpha5_OpenStackClusterList(in *
func autoConvert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *OpenStackClusterSpec, out *v1alpha8.OpenStackClusterSpec, s conversion.Scope) error {
out.CloudName = in.CloudName
- out.NodeCIDR = in.NodeCIDR
+ // WARNING: in.NodeCIDR requires manual conversion: does not exist in peer-type
if err := Convert_v1alpha5_NetworkFilter_To_v1alpha8_NetworkFilter(&in.Network, &out.Network, s); err != nil {
return err
}
// WARNING: in.Subnet requires manual conversion: does not exist in peer-type
- out.DNSNameservers = *(*[]string)(unsafe.Pointer(&in.DNSNameservers))
+ // WARNING: in.DNSNameservers requires manual conversion: does not exist in peer-type
if in.ExternalRouterIPs != nil {
in, out := &in.ExternalRouterIPs, &out.ExternalRouterIPs
*out = make([]v1alpha8.ExternalRouterIPParam, len(*in))
@@ -701,14 +701,13 @@ func autoConvert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(
func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(in *v1alpha8.OpenStackClusterSpec, out *OpenStackClusterSpec, s conversion.Scope) error {
out.CloudName = in.CloudName
- out.NodeCIDR = in.NodeCIDR
+ // 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_v1alpha8_NetworkFilter_To_v1alpha5_NetworkFilter(&in.Network, &out.Network, s); err != nil {
return err
}
// 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))
diff --git a/api/v1alpha6/conversion.go b/api/v1alpha6/conversion.go
index a01430e935..177a2f0f8c 100644
--- a/api/v1alpha6/conversion.go
+++ b/api/v1alpha6/conversion.go
@@ -127,6 +127,11 @@ func restorev1alpha6ClusterSpec(previous *OpenStackClusterSpec, dst *OpenStackCl
}
}
+ // 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 {
@@ -545,6 +550,11 @@ func Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(in *
}
}
+ if len(in.ManagedSubnets) > 0 {
+ out.NodeCIDR = in.ManagedSubnets[0].CIDR
+ out.DNSNameservers = in.ManagedSubnets[0].DNSNameservers
+ }
+
return nil
}
@@ -569,6 +579,16 @@ func Convert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *
out.Subnets = []infrav1.SubnetFilter{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,
+ },
+ }
+ }
+
return nil
}
diff --git a/api/v1alpha6/conversion_test.go b/api/v1alpha6/conversion_test.go
index 5a2a9a6f6d..e6ed8f4c9e 100644
--- a/api/v1alpha6/conversion_test.go
+++ b/api/v1alpha6/conversion_test.go
@@ -132,6 +132,16 @@ func TestFuzzyConversion(t *testing.T) {
}
}
},
+
+ func(spec *infrav1.SubnetSpec, c fuzz.Continue) {
+ c.FuzzNoCustom(spec)
+
+ // CIDR is required and API validates that it's present, so
+ // we force it to always be set.
+ for spec.CIDR == "" {
+ spec.CIDR = c.RandString()
+ }
+ },
}
}
@@ -156,6 +166,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{
diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go
index 0589be11fb..08c25e97cf 100644
--- a/api/v1alpha6/zz_generated.conversion.go
+++ b/api/v1alpha6/zz_generated.conversion.go
@@ -677,12 +677,12 @@ func Convert_v1alpha8_OpenStackClusterList_To_v1alpha6_OpenStackClusterList(in *
func autoConvert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *OpenStackClusterSpec, out *v1alpha8.OpenStackClusterSpec, s conversion.Scope) error {
out.CloudName = in.CloudName
- out.NodeCIDR = in.NodeCIDR
+ // WARNING: in.NodeCIDR requires manual conversion: does not exist in peer-type
if err := Convert_v1alpha6_NetworkFilter_To_v1alpha8_NetworkFilter(&in.Network, &out.Network, s); err != nil {
return err
}
// WARNING: in.Subnet requires manual conversion: does not exist in peer-type
- out.DNSNameservers = *(*[]string)(unsafe.Pointer(&in.DNSNameservers))
+ // WARNING: in.DNSNameservers requires manual conversion: does not exist in peer-type
if in.ExternalRouterIPs != nil {
in, out := &in.ExternalRouterIPs, &out.ExternalRouterIPs
*out = make([]v1alpha8.ExternalRouterIPParam, len(*in))
@@ -724,14 +724,13 @@ func autoConvert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(
func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(in *v1alpha8.OpenStackClusterSpec, out *OpenStackClusterSpec, s conversion.Scope) error {
out.CloudName = in.CloudName
- out.NodeCIDR = in.NodeCIDR
+ // 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_v1alpha8_NetworkFilter_To_v1alpha6_NetworkFilter(&in.Network, &out.Network, s); err != nil {
return err
}
// 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))
diff --git a/api/v1alpha7/conversion.go b/api/v1alpha7/conversion.go
index df31c7d81c..9bfa6ad90d 100644
--- a/api/v1alpha7/conversion.go
+++ b/api/v1alpha7/conversion.go
@@ -39,6 +39,24 @@ var v1alpha7OpenStackClusterRestorer = conversion.RestorerFor[*OpenStackCluster]
},
restorev1alpha7Bastion,
),
+ "spec": conversion.HashedFieldRestorer(
+ func(c *OpenStackCluster) *OpenStackClusterSpec {
+ return &c.Spec
+ },
+ restorev1alpha7ClusterSpec,
+
+ // Filter out Bastion, which is restored separately
+ conversion.HashedFilterField[*OpenStackCluster, OpenStackClusterSpec](
+ func(s *OpenStackClusterSpec) *OpenStackClusterSpec {
+ if s.Bastion != nil {
+ f := *s
+ f.Bastion = nil
+ return &f
+ }
+ return s
+ },
+ ),
+ ),
}
var v1alpha8OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStackCluster]{
@@ -111,6 +129,19 @@ func restorev1alpha8Bastion(previous **infrav1.Bastion, dst **infrav1.Bastion) {
}
}
+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
+ }
+}
+
func restorev1alpha8ClusterSpec(previous *infrav1.OpenStackClusterSpec, dst *infrav1.OpenStackClusterSpec) {
prevBastion := previous.Bastion
dstBastion := dst.Bastion
@@ -132,6 +163,8 @@ func restorev1alpha8ClusterSpec(previous *infrav1.OpenStackClusterSpec, dst *inf
if len(previous.Subnets) > 1 {
dst.Subnets = append(dst.Subnets, previous.Subnets[1:]...)
}
+
+ dst.ManagedSubnets = previous.ManagedSubnets
}
func (r *OpenStackCluster) ConvertTo(dstRaw ctrlconversion.Hub) error {
@@ -171,6 +204,7 @@ func (r *OpenStackClusterList) ConvertFrom(srcRaw ctrlconversion.Hub) error {
var _ ctrlconversion.Convertible = &OpenStackClusterTemplate{}
func restorev1alpha7ClusterTemplateSpec(previous *OpenStackClusterTemplateSpec, dst *OpenStackClusterTemplateSpec) {
+ restorev1alpha7ClusterSpec(&previous.Template.Spec, &dst.Template.Spec)
restorev1alpha7Bastion(&previous.Template.Spec.Bastion, &dst.Template.Spec.Bastion)
}
@@ -465,6 +499,16 @@ func Convert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *
out.Subnets = []infrav1.SubnetFilter{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,
+ },
+ }
+ }
+
return nil
}
@@ -484,5 +528,10 @@ func Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in *
}
}
+ if len(in.ManagedSubnets) > 0 {
+ out.NodeCIDR = in.ManagedSubnets[0].CIDR
+ out.DNSNameservers = in.ManagedSubnets[0].DNSNameservers
+ }
+
return nil
}
diff --git a/api/v1alpha7/conversion_test.go b/api/v1alpha7/conversion_test.go
index c57cc5d163..97763d7d4b 100644
--- a/api/v1alpha7/conversion_test.go
+++ b/api/v1alpha7/conversion_test.go
@@ -100,6 +100,16 @@ func TestFuzzyConversion(t *testing.T) {
}
}
},
+
+ func(spec *infrav1.SubnetSpec, c fuzz.Continue) {
+ c.FuzzNoCustom(spec)
+
+ // CIDR is required and API validates that it's present, so
+ // we force it to always be set.
+ for spec.CIDR == "" {
+ spec.CIDR = c.RandString()
+ }
+ },
}
}
diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go
index 42a17e16eb..de0e42be72 100644
--- a/api/v1alpha7/zz_generated.conversion.go
+++ b/api/v1alpha7/zz_generated.conversion.go
@@ -877,14 +877,14 @@ func Convert_v1alpha8_OpenStackClusterList_To_v1alpha7_OpenStackClusterList(in *
func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *OpenStackClusterSpec, out *v1alpha8.OpenStackClusterSpec, s conversion.Scope) error {
out.CloudName = in.CloudName
- out.NodeCIDR = in.NodeCIDR
+ // WARNING: in.NodeCIDR requires manual conversion: does not exist in peer-type
out.Router = (*v1alpha8.RouterFilter)(unsafe.Pointer(in.Router))
if err := Convert_v1alpha7_NetworkFilter_To_v1alpha8_NetworkFilter(&in.Network, &out.Network, s); err != nil {
return err
}
// WARNING: in.Subnet requires manual conversion: does not exist in peer-type
out.NetworkMTU = in.NetworkMTU
- out.DNSNameservers = *(*[]string)(unsafe.Pointer(&in.DNSNameservers))
+ // WARNING: in.DNSNameservers requires manual conversion: does not exist in peer-type
out.ExternalRouterIPs = *(*[]v1alpha8.ExternalRouterIPParam)(unsafe.Pointer(&in.ExternalRouterIPs))
// WARNING: in.ExternalNetworkID requires manual conversion: does not exist in peer-type
if err := Convert_v1alpha7_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil {
@@ -916,14 +916,13 @@ func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(
func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in *v1alpha8.OpenStackClusterSpec, out *OpenStackClusterSpec, s conversion.Scope) error {
out.CloudName = in.CloudName
- out.NodeCIDR = in.NodeCIDR
+ // WARNING: in.ManagedSubnets requires manual conversion: does not exist in peer-type
out.Router = (*RouterFilter)(unsafe.Pointer(in.Router))
if err := Convert_v1alpha8_NetworkFilter_To_v1alpha7_NetworkFilter(&in.Network, &out.Network, s); err != nil {
return err
}
// WARNING: in.Subnets requires manual conversion: does not exist in peer-type
out.NetworkMTU = in.NetworkMTU
- out.DNSNameservers = *(*[]string)(unsafe.Pointer(&in.DNSNameservers))
out.ExternalRouterIPs = *(*[]ExternalRouterIPParam)(unsafe.Pointer(&in.ExternalRouterIPs))
// WARNING: in.ExternalNetwork requires manual conversion: does not exist in peer-type
// WARNING: in.DisableExternalNetwork requires manual conversion: does not exist in peer-type
diff --git a/api/v1alpha8/openstackcluster_types.go b/api/v1alpha8/openstackcluster_types.go
index a669c8317d..7002daf3dc 100644
--- a/api/v1alpha8/openstackcluster_types.go
+++ b/api/v1alpha8/openstackcluster_types.go
@@ -34,10 +34,11 @@ type OpenStackClusterSpec struct {
// +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 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
+ 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.
@@ -58,11 +59,6 @@ type OpenStackClusterSpec struct {
// +optional
NetworkMTU 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.
ExternalRouterIPs []ExternalRouterIPParam `json:"externalRouterIPs,omitempty"`
diff --git a/api/v1alpha8/types.go b/api/v1alpha8/types.go
index bdbf2155bf..1278f83639 100644
--- a/api/v1alpha8/types.go
+++ b/api/v1alpha8/types.go
@@ -87,6 +87,16 @@ type RouterFilter struct {
NotTagsAny string `json:"notTagsAny,omitempty"`
}
+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"`
+}
+
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.
diff --git a/api/v1alpha8/zz_generated.deepcopy.go b/api/v1alpha8/zz_generated.deepcopy.go
index df370f8983..5be338cb7f 100644
--- a/api/v1alpha8/zz_generated.deepcopy.go
+++ b/api/v1alpha8/zz_generated.deepcopy.go
@@ -366,6 +366,13 @@ 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)
@@ -377,11 +384,6 @@ func (in *OpenStackClusterSpec) DeepCopyInto(out *OpenStackClusterSpec) {
*out = make([]SubnetFilter, len(*in))
copy(*out, *in)
}
- if in.DNSNameservers != nil {
- in, out := &in.DNSNameservers, &out.DNSNameservers
- *out = make([]string, len(*in))
- copy(*out, *in)
- }
if in.ExternalRouterIPs != nil {
in, out := &in.ExternalRouterIPs, &out.ExternalRouterIPs
*out = make([]ExternalRouterIPParam, len(*in))
@@ -1119,6 +1121,26 @@ 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 *SubnetSpec) DeepCopyInto(out *SubnetSpec) {
+ *out = *in
+ if in.DNSNameservers != nil {
+ in, out := &in.DNSNameservers, &out.DNSNameservers
+ *out = make([]string, 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
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 0e929c11c8..31c214580b 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -5366,15 +5366,6 @@ spec:
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.
- items:
- type: string
- type: array
- x-kubernetes-list-type: set
externalNetwork:
description: ExternalNetwork is the OpenStack Network to be used to
get public internet to the VMs.
@@ -5468,6 +5459,30 @@ spec:
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
+ 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:
+ 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
network:
description: If NodeCIDR cannot be set this can be used to detect
an existing network.
@@ -5496,12 +5511,6 @@ spec:
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.
- type: string
router:
description: |-
If NodeCIDR is set this option can be used to detect an existing router.
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 ae5555b4a2..b9c154dc7f 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -2801,15 +2801,6 @@ spec:
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.
- items:
- type: string
- type: array
- x-kubernetes-list-type: set
externalNetwork:
description: ExternalNetwork is the OpenStack Network to be
used to get public internet to the VMs.
@@ -2903,6 +2894,30 @@ spec:
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
+ 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:
+ 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
network:
description: If NodeCIDR cannot be set this can be used to
detect an existing network.
@@ -2931,12 +2946,6 @@ spec:
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.
- type: string
router:
description: |-
If NodeCIDR is set this option can be used to detect an existing router.
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index d63a6692da..661d399434 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -183,8 +183,8 @@ func (r *OpenStackClusterReconciler) reconcileDelete(ctx context.Context, scope
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 ManagedSubnets was not set, no network was created.
+ if len(openStackCluster.Spec.ManagedSubnets) == 0 {
if err = networkingService.DeleteRouter(openStackCluster, clusterName); err != nil {
handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to delete router: %w", err))
return ctrl.Result{}, fmt.Errorf("failed to delete router: %w", err)
@@ -504,7 +504,7 @@ func reconcileNetworkComponents(scope scope.Scope, cluster *clusterv1.Cluster, o
return fmt.Errorf("failed to reconcile external network: %w", err)
}
- if openStackCluster.Spec.NodeCIDR == "" {
+ if len(openStackCluster.Spec.ManagedSubnets) == 0 {
scope.Logger().V(4).Info("No need to reconcile network, searching network and subnet instead")
netOpts := openStackCluster.Spec.Network.ToListOpt()
@@ -537,7 +537,7 @@ func reconcileNetworkComponents(scope scope.Scope, cluster *clusterv1.Cluster, o
return err
}
openStackCluster.Status.Network.Subnets = subnets
- } else {
+ } else if len(openStackCluster.Spec.ManagedSubnets) == 1 {
err := networkingService.ReconcileNetwork(openStackCluster, clusterName)
if err != nil {
handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to reconcile network: %w", err))
@@ -553,6 +553,8 @@ func reconcileNetworkComponents(scope scope.Scope, cluster *clusterv1.Cluster, o
handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to reconcile router: %w", err))
return fmt.Errorf("failed to reconcile router: %w", err)
}
+ } else {
+ return fmt.Errorf("failed to reconcile network: ManagedSubnets only supports one element, %d provided", len(openStackCluster.Spec.ManagedSubnets))
}
err = networkingService.ReconcileSecurityGroups(openStackCluster, clusterName)
diff --git a/docs/book/src/clusteropenstack/configuration.md b/docs/book/src/clusteropenstack/configuration.md
index 3ae013333f..46c7b00363 100644
--- a/docs/book/src/clusteropenstack/configuration.md
+++ b/docs/book/src/clusteropenstack/configuration.md
@@ -247,7 +247,7 @@ prevent a floating IP from being allocated.
> This can be a project-specific network, if the management cluster lives in the same project
> as the workload cluster, or a network that is shared across multiple projects.
>
-> In particular, this means that the cluster **cannot** use `OpenStackCluster.spec.nodeCidr`
+> In particular, this means that the cluster **cannot** use `OpenStackCluster.spec.managedSubnets`
> to provision a new network for the cluster. Instead, use `OpenStackCluster.spec.network`
> to explicitly specify the same network as the management cluster is on.
diff --git a/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md b/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md
index efcf44d169..37df012a8c 100644
--- a/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md
+++ b/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md
@@ -176,4 +176,23 @@ In v1alpha8, this will be automatically converted to:
`Subnets` allows specifications of maximum two `SubnetFilter` one being IPv4 and the other IPv6. Both subnets must be on the same network. Any filtered subnets will be added to `OpenStackCluster.Status.Network.Subnets`.
-When subnets are not specified on `OpenStackCluster` and only the network is, the network is used to identify the subnets to use. If more than two subnets exist in the network, the user must specify which ones to use by defining the `OpenStackCluster.Spec.Subnets` field.
\ No newline at end of file
+When subnets are not specified on `OpenStackCluster` and only the network is, the network is used to identify the subnets to use. If more than two subnets exist in the network, the user must specify which ones to use by defining the `OpenStackCluster.Spec.Subnets` field.
+
+#### ⚠️ Change to nodeCidr and dnsNameservers
+
+In v1alpha8, `OpenStackCluster.Spec.ManagedSubnets` array field is introduced. The `NodeCIDR` and `DNSNameservers` fields of `OpenStackCluster.Spec` are moved into that structure (renaming `NodeCIDR` to `CIDR`). For example:
+
+```yaml
+ nodeCidr: "10.0.0.0/24"
+ dnsNameservers: "10.0.0.123"
+```
+
+In v1alpha8, this will be automatically converted to:
+
+```yaml
+ managedSubnets:
+ - cidr: "10.0.0.0/24"
+ dnsNameservers: "10.0.0.123"
+```
+
+Please note that currently `managedSubnets` can only hold one element.
\ No newline at end of file
diff --git a/kustomize/v1alpha8/default/cluster-template.yaml b/kustomize/v1alpha8/default/cluster-template.yaml
index 0dc7472f18..5482f50448 100644
--- a/kustomize/v1alpha8/default/cluster-template.yaml
+++ b/kustomize/v1alpha8/default/cluster-template.yaml
@@ -29,9 +29,10 @@ spec:
apiServerLoadBalancer:
enabled: true
managedSecurityGroups: true
- nodeCidr: 10.6.0.0/24
- dnsNameservers:
- - ${OPENSTACK_DNS_NAMESERVERS}
+ managedSubnets:
+ - cidr: 10.6.0.0/24
+ dnsNameservers:
+ - ${OPENSTACK_DNS_NAMESERVERS}
externalNetwork:
id: ${OPENSTACK_EXTERNAL_NETWORK_ID}
---
diff --git a/pkg/cloud/services/networking/network.go b/pkg/cloud/services/networking/network.go
index 5eaf691471..540dce22f4 100644
--- a/pkg/cloud/services/networking/network.go
+++ b/pkg/cloud/services/networking/network.go
@@ -211,14 +211,16 @@ func (s *Service) ReconcileSubnet(openStackCluster *infrav1.OpenStackCluster, cl
subnetList, err := s.client.ListSubnet(subnets.ListOpts{
NetworkID: openStackCluster.Status.Network.ID,
- CIDR: openStackCluster.Spec.NodeCIDR,
+ // Currently we only support 1 SubnetSpec.
+ CIDR: openStackCluster.Spec.ManagedSubnets[0].CIDR,
})
if err != nil {
return err
}
if len(subnetList) > 1 {
- return fmt.Errorf("found %d subnets with the name %s, which should not happen", len(subnetList), subnetName)
+ return fmt.Errorf("found %d subnets with the CIDR %s and network %s, which should not happen",
+ len(subnetList), openStackCluster.Spec.ManagedSubnets[0], openStackCluster.Status.Network.ID)
}
var subnet *subnets.Subnet
@@ -249,8 +251,8 @@ func (s *Service) createSubnet(openStackCluster *infrav1.OpenStackCluster, clust
NetworkID: openStackCluster.Status.Network.ID,
Name: name,
IPVersion: 4,
- CIDR: openStackCluster.Spec.NodeCIDR,
- DNSNameservers: openStackCluster.Spec.DNSNameservers,
+ CIDR: openStackCluster.Spec.ManagedSubnets[0].CIDR,
+ DNSNameservers: openStackCluster.Spec.ManagedSubnets[0].DNSNameservers,
Description: names.GetDescription(clusterName),
}
diff --git a/templates/cluster-template-flatcar-sysext.yaml b/templates/cluster-template-flatcar-sysext.yaml
index 3994a67311..8e2f89ea2a 100644
--- a/templates/cluster-template-flatcar-sysext.yaml
+++ b/templates/cluster-template-flatcar-sysext.yaml
@@ -225,15 +225,16 @@ metadata:
name: ${CLUSTER_NAME}
spec:
cloudName: ${OPENSTACK_CLOUD}
- dnsNameservers:
- - ${OPENSTACK_DNS_NAMESERVERS}
externalNetwork:
id: ${OPENSTACK_EXTERNAL_NETWORK_ID}
identityRef:
kind: Secret
name: ${CLUSTER_NAME}-cloud-config
managedSecurityGroups: true
- nodeCidr: 10.6.0.0/24
+ managedSubnets:
+ - cidr: 10.6.0.0/24
+ dnsNameservers:
+ - ${OPENSTACK_DNS_NAMESERVERS}
---
apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
diff --git a/templates/cluster-template-flatcar.yaml b/templates/cluster-template-flatcar.yaml
index ff093ece03..edccdf99ab 100644
--- a/templates/cluster-template-flatcar.yaml
+++ b/templates/cluster-template-flatcar.yaml
@@ -149,15 +149,16 @@ metadata:
name: ${CLUSTER_NAME}
spec:
cloudName: ${OPENSTACK_CLOUD}
- dnsNameservers:
- - ${OPENSTACK_DNS_NAMESERVERS}
externalNetwork:
id: ${OPENSTACK_EXTERNAL_NETWORK_ID}
identityRef:
kind: Secret
name: ${CLUSTER_NAME}-cloud-config
managedSecurityGroups: true
- nodeCidr: 10.6.0.0/24
+ managedSubnets:
+ - cidr: 10.6.0.0/24
+ dnsNameservers:
+ - ${OPENSTACK_DNS_NAMESERVERS}
---
apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
diff --git a/templates/cluster-template-without-lb.yaml b/templates/cluster-template-without-lb.yaml
index 665437a0a1..97d39b1d17 100644
--- a/templates/cluster-template-without-lb.yaml
+++ b/templates/cluster-template-without-lb.yaml
@@ -106,15 +106,16 @@ metadata:
name: ${CLUSTER_NAME}
spec:
cloudName: ${OPENSTACK_CLOUD}
- dnsNameservers:
- - ${OPENSTACK_DNS_NAMESERVERS}
externalNetwork:
id: ${OPENSTACK_EXTERNAL_NETWORK_ID}
identityRef:
kind: Secret
name: ${CLUSTER_NAME}-cloud-config
managedSecurityGroups: true
- nodeCidr: 10.6.0.0/24
+ managedSubnets:
+ - cidr: 10.6.0.0/24
+ dnsNameservers:
+ - ${OPENSTACK_DNS_NAMESERVERS}
---
apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
diff --git a/templates/cluster-template.yaml b/templates/cluster-template.yaml
index af65b8865f..1384b473b0 100644
--- a/templates/cluster-template.yaml
+++ b/templates/cluster-template.yaml
@@ -108,15 +108,16 @@ spec:
apiServerLoadBalancer:
enabled: true
cloudName: ${OPENSTACK_CLOUD}
- dnsNameservers:
- - ${OPENSTACK_DNS_NAMESERVERS}
externalNetwork:
id: ${OPENSTACK_EXTERNAL_NETWORK_ID}
identityRef:
kind: Secret
name: ${CLUSTER_NAME}-cloud-config
managedSecurityGroups: true
- nodeCidr: 10.6.0.0/24
+ managedSubnets:
+ - cidr: 10.6.0.0/24
+ dnsNameservers:
+ - ${OPENSTACK_DNS_NAMESERVERS}
---
apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
diff --git a/templates/clusterclass-dev-test.yaml b/templates/clusterclass-dev-test.yaml
index 40b8758502..44930abc7d 100644
--- a/templates/clusterclass-dev-test.yaml
+++ b/templates/clusterclass-dev-test.yaml
@@ -118,13 +118,14 @@ spec:
apiServerLoadBalancer:
enabled: true
cloudName: ${OPENSTACK_CLOUD:=capo-e2e}
- dnsNameservers:
- - 8.8.8.8
identityRef:
kind: Secret
name: dev-test-cloud-config
managedSecurityGroups: true
- nodeCidr: 10.6.0.0/24
+ managedSubnets:
+ - cidr: 10.6.0.0/24
+ dnsNameservers:
+ - 8.8.8.8
---
apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
kind: OpenStackMachineTemplate
From a68d9461d0e06437ece44c9fa432078e1c7ad68a Mon Sep 17 00:00:00 2001
From: Emilien Macchi
Date: Wed, 14 Feb 2024 15:33:11 -0500
Subject: [PATCH 061/180] Bump Go to 1.22.0
---
Dockerfile | 2 +-
go.mod | 2 +-
hack/tools/go.mod | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index 2cffa6bbed..9cfb9287cf 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -13,7 +13,7 @@
# limitations under the License.
# Build the manager binary
-FROM golang:1.21.6 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/go.mod b/go.mod
index 4c59f8ec77..565999d219 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
module sigs.k8s.io/cluster-api-provider-openstack
-go 1.21
+go 1.22
require (
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc
diff --git a/hack/tools/go.mod b/hack/tools/go.mod
index 95ddc1f19b..79cbbebe17 100644
--- a/hack/tools/go.mod
+++ b/hack/tools/go.mod
@@ -1,6 +1,6 @@
module sigs.k8s.io/cluster-api-provider-openstack/hack/tools
-go 1.21
+go 1.22
require (
github.com/a8m/envsubst v1.2.0
From 2f3e5f4520b681d72a9e066237f22af8159f0f4f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20Dulko?=
Date: Thu, 15 Feb 2024 16:54:28 +0100
Subject: [PATCH 062/180] Fix cluster network cleanup
---
controllers/openstackcluster_controller.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index 661d399434..6cd037383c 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -184,7 +184,7 @@ func (r *OpenStackClusterReconciler) reconcileDelete(ctx context.Context, scope
}
// if ManagedSubnets was not set, no network was created.
- if len(openStackCluster.Spec.ManagedSubnets) == 0 {
+ if len(openStackCluster.Spec.ManagedSubnets) > 0 {
if err = networkingService.DeleteRouter(openStackCluster, clusterName); err != nil {
handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to delete router: %w", err))
return ctrl.Result{}, fmt.Errorf("failed to delete router: %w", err)
From 23e30c7033e3876f597b428d41a39f91d62ccf74 Mon Sep 17 00:00:00 2001
From: Stephen Finucane
Date: Thu, 15 Feb 2024 18:17:08 +0000
Subject: [PATCH 063/180] provider: Ignore environment variables
Users should configure things via a secret, not via environment
variables.
Signed-off-by: Stephen Finucane
---
pkg/scope/provider.go | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/pkg/scope/provider.go b/pkg/scope/provider.go
index e7a060d3f4..707b08b5b9 100644
--- a/pkg/scope/provider.go
+++ b/pkg/scope/provider.go
@@ -224,6 +224,12 @@ func (s *providerScope) ExtractToken() (*tokens.Token, error) {
func NewProviderClient(cloud clientconfig.Cloud, caCert []byte, logger logr.Logger) (*gophercloud.ProviderClient, *clientconfig.ClientOpts, string, error) {
clientOpts := new(clientconfig.ClientOpts)
+
+ // We explicitly disable reading auth data from env variables by setting an invalid EnvPrefix.
+ // By doing this, we make sure that the data from clouds.yaml is enough to authenticate.
+ // For more information: https://github.com/gophercloud/utils/blob/8677e053dcf1f05d0fa0a616094aace04690eb94/openstack/clientconfig/requests.go#L508
+ clientOpts.EnvPrefix = "NO_ENV_VARIABLES_"
+
if cloud.AuthInfo != nil {
clientOpts.AuthInfo = cloud.AuthInfo
clientOpts.AuthType = cloud.AuthType
From d33c1bc487fecf5ce6ede3f0d08c0cc3047fb166 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Thu, 15 Feb 2024 21:43:32 +0000
Subject: [PATCH 064/180] Stop serving v1alpha5
---
api/v1alpha5/openstackcluster_types.go | 1 +
api/v1alpha5/openstackclustertemplate_types.go | 1 +
api/v1alpha5/openstackmachine_types.go | 1 +
api/v1alpha5/openstackmachinetemplate_types.go | 1 +
.../infrastructure.cluster.x-k8s.io_openstackclusters.yaml | 2 +-
...frastructure.cluster.x-k8s.io_openstackclustertemplates.yaml | 2 +-
.../infrastructure.cluster.x-k8s.io_openstackmachines.yaml | 2 +-
...frastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml | 2 +-
8 files changed, 8 insertions(+), 4 deletions(-)
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/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
index 31c214580b..7364ef7157 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -1791,7 +1791,7 @@ spec:
- ready
type: object
type: object
- served: true
+ served: false
storage: false
subresources:
status: {}
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 b9c154dc7f..6cdd764039 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -741,7 +741,7 @@ spec:
- template
type: object
type: object
- served: true
+ served: false
storage: false
- name: v1alpha6
schema:
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 e1a23d33be..15b1bee559 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
@@ -565,7 +565,7 @@ spec:
type: boolean
type: object
type: object
- served: true
+ served: false
storage: false
subresources:
status: {}
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 db63d9ade3..dac6f9c36e 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
@@ -462,7 +462,7 @@ spec:
- template
type: object
type: object
- served: true
+ served: false
storage: false
- name: v1alpha6
schema:
From 4eec0e7b5a2b37424ab4320122e54f3d04a1ebca Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Fri, 16 Feb 2024 00:26:40 +0000
Subject: [PATCH 065/180] Fix doc references to NodeCIDR in v1alpha8
---
api/v1alpha8/openstackcluster_types.go | 16 +++++++++++-----
...re.cluster.x-k8s.io_openstackclusters.yaml | 19 ++++++++++++-------
...er.x-k8s.io_openstackclustertemplates.yaml | 19 ++++++++++++-------
3 files changed, 35 insertions(+), 19 deletions(-)
diff --git a/api/v1alpha8/openstackcluster_types.go b/api/v1alpha8/openstackcluster_types.go
index 7002daf3dc..5f25489e24 100644
--- a/api/v1alpha8/openstackcluster_types.go
+++ b/api/v1alpha8/openstackcluster_types.go
@@ -40,21 +40,27 @@ type OpenStackClusterSpec struct {
// +kubebuilder:validation:MaxItems=1
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 specifies an existing network to use if no ManagedSubnets
+ // are specified.
Network NetworkFilter `json:"network,omitempty"`
- // If NodeCIDR cannot be set this can be used to detect existing IPv4 and/or IPv6 subnets.
+ // 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
+ // +optional
Subnets []SubnetFilter `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"`
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 31c214580b..1c84b14114 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -5484,8 +5484,9 @@ spec:
maxItems: 1
type: array
network:
- description: If NodeCIDR cannot be set this can be used to detect
- an existing network.
+ description: |-
+ Network specifies an existing network to use if no ManagedSubnets
+ are specified.
properties:
description:
type: string
@@ -5508,13 +5509,13 @@ spec:
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.
+ 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: |-
- 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.
properties:
description:
type: string
@@ -5534,8 +5535,12 @@ spec:
type: string
type: object
subnets:
- description: If NodeCIDR cannot be set this can be used to detect
- existing IPv4 and/or IPv6 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:
properties:
cidr:
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 b9c154dc7f..809e5363c0 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -2919,8 +2919,9 @@ spec:
maxItems: 1
type: array
network:
- description: If NodeCIDR cannot be set this can be used to
- detect an existing network.
+ description: |-
+ Network specifies an existing network to use if no ManagedSubnets
+ are specified.
properties:
description:
type: string
@@ -2943,13 +2944,13 @@ spec:
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.
+ 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: |-
- 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.
properties:
description:
type: string
@@ -2969,8 +2970,12 @@ spec:
type: string
type: object
subnets:
- description: If NodeCIDR cannot be set this can be used to
- detect existing IPv4 and/or IPv6 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:
properties:
cidr:
From c51197e82d76ea21a11db80d15aa658365c58ea8 Mon Sep 17 00:00:00 2001
From: Emilien Macchi
Date: Mon, 19 Feb 2024 13:58:09 -0500
Subject: [PATCH 066/180] CI/e2e: stop testing upgrades from v1alpha5 (v0.6)
---
Makefile | 1 -
test/e2e/data/e2e_conf.yaml | 14 -----------
test/e2e/data/kustomize/v1alpha5/bastion.yaml | 9 --------
.../kustomize/v1alpha5/kustomization.yaml | 14 -----------
test/e2e/shared/defaults.go | 1 -
.../e2e/suites/e2e/clusterctl_upgrade_test.go | 23 -------------------
6 files changed, 62 deletions(-)
delete mode 100644 test/e2e/data/kustomize/v1alpha5/bastion.yaml
delete mode 100644 test/e2e/data/kustomize/v1alpha5/kustomization.yaml
diff --git a/Makefile b/Makefile
index e25fb5badb..b66e60a5c6 100644
--- a/Makefile
+++ b/Makefile
@@ -148,7 +148,6 @@ 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 \
diff --git a/test/e2e/data/e2e_conf.yaml b/test/e2e/data/e2e_conf.yaml
index a499a983ec..47724aaa33 100644
--- a/test/e2e/data/e2e_conf.yaml
+++ b/test/e2e/data/e2e_conf.yaml
@@ -111,20 +111,6 @@ providers:
type: InfrastructureProvider
versions:
# This is only for clusterctl upgrade tests
- - name: v0.6.4
- value: "https://github.com/kubernetes-sigs/cluster-api-provider-openstack/releases/download/v0.6.4/infrastructure-components.yaml"
- type: url
- contract: v1beta1
- files:
- - sourcePath: "../data/shared/v1beta1_provider/metadata.yaml"
- - sourcePath: "./infrastructure-openstack-no-artifact/cluster-template.yaml"
- replacements:
- - old: "imagePullPolicy: Always"
- new: "imagePullPolicy: IfNotPresent"
- - old: "--v=2"
- new: "--v=4"
- - old: "--leader-elect"
- new: "--leader-elect=false\n - --sync-period=1m"
- name: v0.7.2
value: "https://github.com/kubernetes-sigs/cluster-api-provider-openstack/releases/download/v0.7.2/infrastructure-components.yaml"
type: url
diff --git a/test/e2e/data/kustomize/v1alpha5/bastion.yaml b/test/e2e/data/kustomize/v1alpha5/bastion.yaml
deleted file mode 100644
index 45c9e0f508..0000000000
--- a/test/e2e/data/kustomize/v1alpha5/bastion.yaml
+++ /dev/null
@@ -1,9 +0,0 @@
----
-- op: add
- path: /spec/bastion
- value:
- enabled: true
- instance:
- flavor: ${OPENSTACK_BASTION_MACHINE_FLAVOR}
- image: ${OPENSTACK_BASTION_IMAGE_NAME}
- sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
diff --git a/test/e2e/data/kustomize/v1alpha5/kustomization.yaml b/test/e2e/data/kustomize/v1alpha5/kustomization.yaml
deleted file mode 100644
index ae29db64d9..0000000000
--- a/test/e2e/data/kustomize/v1alpha5/kustomization.yaml
+++ /dev/null
@@ -1,14 +0,0 @@
-apiVersion: kustomize.config.k8s.io/v1beta1
-kind: Kustomization
-resources:
-- ../../../../../kustomize/v1alpha5/external-cloud-provider
-
-components:
-- ../common-patches/cni
-- ../common-patches/ccm
-
-patches:
-- path: bastion.yaml
- target:
- kind: OpenStackCluster
- name: \${CLUSTER_NAME}
diff --git a/test/e2e/shared/defaults.go b/test/e2e/shared/defaults.go
index 4ab3e9a7db..df6315f773 100644
--- a/test/e2e/shared/defaults.go
+++ b/test/e2e/shared/defaults.go
@@ -48,7 +48,6 @@ const (
FlavorWithoutLB = "without-lb"
FlavorMultiNetwork = "multi-network"
FlavorMultiAZ = "multi-az"
- FlavorV1alpha5 = "v1alpha5"
FlavorV1alpha6 = "v1alpha6"
FlavorV1alpha7 = "v1alpha7"
FlavorMDRemediation = "md-remediation"
diff --git a/test/e2e/suites/e2e/clusterctl_upgrade_test.go b/test/e2e/suites/e2e/clusterctl_upgrade_test.go
index e31c1c6256..ab77af2872 100644
--- a/test/e2e/suites/e2e/clusterctl_upgrade_test.go
+++ b/test/e2e/suites/e2e/clusterctl_upgrade_test.go
@@ -30,29 +30,6 @@ import (
const OldCAPIVersion = "v1.4.6"
-var _ = Describe("When testing clusterctl upgrades (v0.6=>current) [clusterctl-upgrade]", func() {
- ctx := context.TODO()
- shared.SetEnvVar("DOWNLOAD_E2E_IMAGE", "true", false)
-
- capi_e2e.ClusterctlUpgradeSpec(ctx, func() capi_e2e.ClusterctlUpgradeSpecInput {
- return capi_e2e.ClusterctlUpgradeSpecInput{
- E2EConfig: e2eCtx.E2EConfig,
- ClusterctlConfigPath: e2eCtx.Environment.ClusterctlConfigPath,
- BootstrapClusterProxy: e2eCtx.Environment.BootstrapClusterProxy,
- ArtifactFolder: e2eCtx.Settings.ArtifactFolder,
- SkipCleanup: false,
- InitWithBinary: "https://github.com/kubernetes-sigs/cluster-api/releases/download/" + OldCAPIVersion + "/clusterctl-{OS}-{ARCH}",
- InitWithProvidersContract: "v1beta1",
- InitWithInfrastructureProviders: []string{"openstack:v0.6.4"},
- InitWithCoreProvider: "cluster-api:" + OldCAPIVersion,
- InitWithBootstrapProviders: []string{"kubeadm:" + OldCAPIVersion},
- InitWithControlPlaneProviders: []string{"kubeadm:" + OldCAPIVersion},
- MgmtFlavor: shared.FlavorDefault,
- WorkloadFlavor: shared.FlavorV1alpha5,
- }
- })
-})
-
var _ = Describe("When testing clusterctl upgrades (v0.7=>current) [clusterctl-upgrade]", func() {
ctx := context.TODO()
shared.SetEnvVar("DOWNLOAD_E2E_IMAGE", "true", false)
From ce11691f31efc49b34542d33abbfd2ae947d812d Mon Sep 17 00:00:00 2001
From: Lennart Jern
Date: Tue, 20 Feb 2024 13:23:43 +0200
Subject: [PATCH 067/180] E2E: Add clusterctl upgrade test for v0.9 -> main
Signed-off-by: Lennart Jern
---
test/e2e/data/e2e_conf.yaml | 14 +++++++++++
.../e2e/suites/e2e/clusterctl_upgrade_test.go | 23 +++++++++++++++++++
2 files changed, 37 insertions(+)
diff --git a/test/e2e/data/e2e_conf.yaml b/test/e2e/data/e2e_conf.yaml
index a499a983ec..73b9ab66b6 100644
--- a/test/e2e/data/e2e_conf.yaml
+++ b/test/e2e/data/e2e_conf.yaml
@@ -153,6 +153,20 @@ providers:
new: "--v=4"
- old: "--leader-elect"
new: "--leader-elect=false\n - --sync-period=1m"
+ - name: v0.9.0
+ value: "https://github.com/kubernetes-sigs/cluster-api-provider-openstack/releases/download/v0.9.0/infrastructure-components.yaml"
+ type: url
+ contract: v1beta1
+ files:
+ - sourcePath: "../data/shared/v1beta1_provider/metadata.yaml"
+ - sourcePath: "./infrastructure-openstack-no-artifact/cluster-template.yaml"
+ replacements:
+ - old: "imagePullPolicy: Always"
+ new: "imagePullPolicy: IfNotPresent"
+ - old: "--v=2"
+ new: "--v=4"
+ - old: "--leader-elect"
+ new: "--leader-elect=false\n - --sync-period=1m"
- name: v0.9.99
value: ../../../config/default
# This is the upcoming version.
diff --git a/test/e2e/suites/e2e/clusterctl_upgrade_test.go b/test/e2e/suites/e2e/clusterctl_upgrade_test.go
index e31c1c6256..41db2e1447 100644
--- a/test/e2e/suites/e2e/clusterctl_upgrade_test.go
+++ b/test/e2e/suites/e2e/clusterctl_upgrade_test.go
@@ -98,3 +98,26 @@ var _ = Describe("When testing clusterctl upgrades (v0.8=>current) [clusterctl-u
}
})
})
+
+var _ = Describe("When testing clusterctl upgrades (v0.9=>current) [clusterctl-upgrade]", func() {
+ ctx := context.TODO()
+ shared.SetEnvVar("DOWNLOAD_E2E_IMAGE", "true", false)
+
+ capi_e2e.ClusterctlUpgradeSpec(ctx, func() capi_e2e.ClusterctlUpgradeSpecInput {
+ return capi_e2e.ClusterctlUpgradeSpecInput{
+ E2EConfig: e2eCtx.E2EConfig,
+ ClusterctlConfigPath: e2eCtx.Environment.ClusterctlConfigPath,
+ BootstrapClusterProxy: e2eCtx.Environment.BootstrapClusterProxy,
+ ArtifactFolder: e2eCtx.Settings.ArtifactFolder,
+ SkipCleanup: false,
+ InitWithBinary: "https://github.com/kubernetes-sigs/cluster-api/releases/download/" + OldCAPIVersion + "/clusterctl-{OS}-{ARCH}",
+ InitWithProvidersContract: "v1beta1",
+ InitWithInfrastructureProviders: []string{"openstack:v0.9.0"},
+ InitWithCoreProvider: "cluster-api:" + OldCAPIVersion,
+ InitWithBootstrapProviders: []string{"kubeadm:" + OldCAPIVersion},
+ InitWithControlPlaneProviders: []string{"kubeadm:" + OldCAPIVersion},
+ MgmtFlavor: shared.FlavorDefault,
+ WorkloadFlavor: shared.FlavorV1alpha7,
+ }
+ })
+})
From 3121d3ae5ae13a37304afc9903a4fe5ffc5098a0 Mon Sep 17 00:00:00 2001
From: Lennart Jern
Date: Tue, 20 Feb 2024 13:44:47 +0200
Subject: [PATCH 068/180] =?UTF-8?q?=E2=9A=A0=20Enforce=20restricted=20pod?=
=?UTF-8?q?=20security=20standards?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
We should be able to run with the restricted policy and this will
inprove our security.
Signed-off-by: Lennart Jern
---
config/default/namespace.yaml | 4 ++++
1 file changed, 4 insertions(+)
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
From 418ce3d5e977f6c940917b206680c3380f47a942 Mon Sep 17 00:00:00 2001
From: Emilien Macchi
Date: Mon, 15 Jan 2024 16:30:54 -0500
Subject: [PATCH 069/180] AllNodes security groups API
Co-Authored-By: Emilien Macchi
Co-Authored-By: Matthew Booth
---
api/v1alpha5/conversion.go | 67 +++
api/v1alpha5/conversion_test.go | 51 +-
api/v1alpha5/zz_generated.conversion.go | 156 +++--
api/v1alpha6/conversion.go | 101 ++++
api/v1alpha6/conversion_test.go | 47 ++
api/v1alpha6/zz_generated.conversion.go | 156 +++--
api/v1alpha7/conversion.go | 148 ++++-
api/v1alpha7/conversion_test.go | 47 ++
api/v1alpha7/zz_generated.conversion.go | 156 +++--
api/v1alpha8/conversion.go | 28 +
api/v1alpha8/openstackcluster_types.go | 25 +-
api/v1alpha8/openstackcluster_webhook.go | 20 +
api/v1alpha8/openstackcluster_webhook_test.go | 81 +++
api/v1alpha8/types.go | 151 ++++-
api/v1alpha8/zz_generated.deepcopy.go | 155 ++++-
...re.cluster.x-k8s.io_openstackclusters.yaml | 224 ++++++--
...er.x-k8s.io_openstackclustertemplates.yaml | 84 ++-
controllers/openstackcluster_controller.go | 2 +-
controllers/openstackmachine_controller.go | 2 +-
.../openstackmachine_controller_test.go | 14 +-
.../src/clusteropenstack/configuration.md | 75 ++-
.../crd-changes/v1alpha7-to-v1alpha8.md | 49 +-
.../v1alpha8/default/cluster-template.yaml | 21 +-
pkg/cloud/services/compute/instance_test.go | 4 +-
.../services/networking/securitygroups.go | 229 ++++++--
.../networking/securitygroups_rules.go | 130 +----
.../networking/securitygroups_test.go | 531 ++++++++++++++++++
.../cluster-template-flatcar-sysext.yaml | 21 +-
templates/cluster-template-flatcar.yaml | 21 +-
templates/cluster-template-without-lb.yaml | 21 +-
templates/cluster-template.yaml | 21 +-
templates/clusterclass-dev-test.yaml | 21 +-
test/e2e/shared/openstack.go | 53 ++
test/e2e/suites/e2e/e2e_test.go | 9 +
34 files changed, 2348 insertions(+), 573 deletions(-)
create mode 100644 pkg/cloud/services/networking/securitygroups_test.go
diff --git a/api/v1alpha5/conversion.go b/api/v1alpha5/conversion.go
index bfb8329cf4..4dfc78a140 100644
--- a/api/v1alpha5/conversion.go
+++ b/api/v1alpha5/conversion.go
@@ -20,6 +20,7 @@ import (
"strings"
conversion "k8s.io/apimachinery/pkg/conversion"
+ "k8s.io/utils/pointer"
utilconversion "sigs.k8s.io/cluster-api/util/conversion"
ctrlconversion "sigs.k8s.io/controller-runtime/pkg/conversion"
@@ -209,6 +210,10 @@ func Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(in *
}
}
+ if in.ManagedSecurityGroups != nil {
+ out.ManagedSecurityGroups = true
+ }
+
return nil
}
@@ -243,6 +248,13 @@ func Convert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *
}
// 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()
+ }
+ }
+
return nil
}
@@ -554,3 +566,58 @@ func Convert_v1alpha5_Bastion_To_v1alpha8_Bastion(in *Bastion, out *infrav1.Bast
in.Instance.FloatingIP = out.FloatingIP
return nil
}
+
+func Convert_v1alpha8_SecurityGroupStatus_To_v1alpha5_SecurityGroup(in *infrav1.SecurityGroupStatus, out *SecurityGroup, s conversion.Scope) error { //nolint:revive
+ out.ID = in.ID
+ out.Name = in.Name
+ out.Rules = make([]SecurityGroupRule, len(in.Rules))
+ for i, rule := range in.Rules {
+ out.Rules[i] = SecurityGroupRule{
+ ID: rule.ID,
+ Direction: rule.Direction,
+ }
+ if rule.Description != nil {
+ out.Rules[i].Description = *rule.Description
+ }
+ if rule.EtherType != nil {
+ out.Rules[i].EtherType = *rule.EtherType
+ }
+ if rule.PortRangeMin != nil {
+ out.Rules[i].PortRangeMin = *rule.PortRangeMin
+ }
+ if rule.PortRangeMax != nil {
+ out.Rules[i].PortRangeMax = *rule.PortRangeMax
+ }
+ if rule.Protocol != nil {
+ out.Rules[i].Protocol = *rule.Protocol
+ }
+ if rule.RemoteGroupID != nil {
+ out.Rules[i].RemoteGroupID = *rule.RemoteGroupID
+ }
+ if rule.RemoteIPPrefix != nil {
+ out.Rules[i].RemoteIPPrefix = *rule.RemoteIPPrefix
+ }
+ }
+ return nil
+}
+
+func Convert_v1alpha5_SecurityGroup_To_v1alpha8_SecurityGroupStatus(in *SecurityGroup, out *infrav1.SecurityGroupStatus, s conversion.Scope) error { //nolint:revive
+ out.ID = in.ID
+ out.Name = in.Name
+ out.Rules = make([]infrav1.SecurityGroupRuleStatus, len(in.Rules))
+ for i, rule := range in.Rules {
+ out.Rules[i] = infrav1.SecurityGroupRuleStatus{
+ ID: rule.ID,
+ Description: pointer.String(rule.Description),
+ Direction: rule.Direction,
+ EtherType: pointer.String(rule.EtherType),
+ PortRangeMin: pointer.Int(rule.PortRangeMin),
+ PortRangeMax: pointer.Int(rule.PortRangeMax),
+ Protocol: pointer.String(rule.Protocol),
+ RemoteGroupID: pointer.String(rule.RemoteGroupID),
+ RemoteIPPrefix: pointer.String(rule.RemoteIPPrefix),
+ }
+ }
+
+ return nil
+}
diff --git a/api/v1alpha5/conversion_test.go b/api/v1alpha5/conversion_test.go
index e4357782c4..b51adaff7c 100644
--- a/api/v1alpha5/conversion_test.go
+++ b/api/v1alpha5/conversion_test.go
@@ -49,7 +49,7 @@ func TestConvertFrom(t *testing.T) {
Spec: OpenStackClusterSpec{},
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
- "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"allowAllInClusterTraffic\":false,\"apiServerLoadBalancer\":{},\"cloudName\":\"\",\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"disableExternalNetwork\":false,\"externalNetwork\":{},\"managedSecurityGroups\":false,\"network\":{}},\"status\":{\"ready\":false}}",
+ "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"allowAllInClusterTraffic\":false,\"apiServerLoadBalancer\":{},\"cloudName\":\"\",\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"disableExternalNetwork\":false,\"externalNetwork\":{},\"managedSecurityGroups\":null,\"network\":{}},\"status\":{\"ready\":false}}",
},
},
},
@@ -64,7 +64,7 @@ func TestConvertFrom(t *testing.T) {
Spec: OpenStackClusterTemplateSpec{},
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,\"disableExternalNetwork\":false,\"externalNetwork\":{},\"managedSecurityGroups\":false,\"network\":{}}}}}",
+ "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"template\":{\"spec\":{\"allowAllInClusterTraffic\":false,\"apiServerLoadBalancer\":{},\"cloudName\":\"\",\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"disableExternalNetwork\":false,\"externalNetwork\":{},\"managedSecurityGroups\":null,\"network\":{}}}}}",
},
},
},
@@ -109,3 +109,50 @@ func TestConvertFrom(t *testing.T) {
})
}
}
+
+func TestConvert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_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_v1alpha8_OpenStackClusterSpec(tt.in, out, nil)
+ g.Expect(err).NotTo(gomega.HaveOccurred())
+ g.Expect(out).To(gomega.Equal(tt.expectedOut))
+ })
+ }
+}
diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go
index c9e8b952a2..0d4ef4e7b5 100644
--- a/api/v1alpha5/zz_generated.conversion.go
+++ b/api/v1alpha5/zz_generated.conversion.go
@@ -244,31 +244,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*SecurityGroup)(nil), (*v1alpha8.SecurityGroup)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_SecurityGroup_To_v1alpha8_SecurityGroup(a.(*SecurityGroup), b.(*v1alpha8.SecurityGroup), scope)
- }); err != nil {
- return err
- }
- if err := s.AddGeneratedConversionFunc((*v1alpha8.SecurityGroup)(nil), (*SecurityGroup)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_SecurityGroup_To_v1alpha5_SecurityGroup(a.(*v1alpha8.SecurityGroup), b.(*SecurityGroup), scope)
- }); err != nil {
- return err
- }
if err := s.AddGeneratedConversionFunc((*v1alpha8.SecurityGroupFilter)(nil), (*SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha8_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(a.(*v1alpha8.SecurityGroupFilter), b.(*SecurityGroupFilter), scope)
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*SecurityGroupRule)(nil), (*v1alpha8.SecurityGroupRule)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_SecurityGroupRule_To_v1alpha8_SecurityGroupRule(a.(*SecurityGroupRule), b.(*v1alpha8.SecurityGroupRule), scope)
- }); err != nil {
- return err
- }
- if err := s.AddGeneratedConversionFunc((*v1alpha8.SecurityGroupRule)(nil), (*SecurityGroupRule)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_SecurityGroupRule_To_v1alpha5_SecurityGroupRule(a.(*v1alpha8.SecurityGroupRule), b.(*SecurityGroupRule), scope)
- }); err != nil {
- return err
- }
if err := s.AddGeneratedConversionFunc((*Subnet)(nil), (*v1alpha8.Subnet)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha5_Subnet_To_v1alpha8_Subnet(a.(*Subnet), b.(*v1alpha8.Subnet), scope)
}); err != nil {
@@ -339,6 +319,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
+ if err := s.AddConversionFunc((*SecurityGroup)(nil), (*v1alpha8.SecurityGroupStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_SecurityGroup_To_v1alpha8_SecurityGroupStatus(a.(*SecurityGroup), b.(*v1alpha8.SecurityGroupStatus), scope)
+ }); err != nil {
+ return err
+ }
if err := s.AddConversionFunc((*SubnetParam)(nil), (*v1alpha8.SubnetFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha5_SubnetParam_To_v1alpha8_SubnetFilter(a.(*SubnetParam), b.(*v1alpha8.SubnetFilter), scope)
}); err != nil {
@@ -404,6 +389,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
+ if err := s.AddConversionFunc((*v1alpha8.SecurityGroupStatus)(nil), (*SecurityGroup)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_SecurityGroupStatus_To_v1alpha5_SecurityGroup(a.(*v1alpha8.SecurityGroupStatus), b.(*SecurityGroup), scope)
+ }); err != nil {
+ return err
+ }
if err := s.AddConversionFunc((*v1alpha8.SubnetFilter)(nil), (*SubnetParam)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha8_SubnetFilter_To_v1alpha5_SubnetParam(a.(*v1alpha8.SubnetFilter), b.(*SubnetParam), scope)
}); err != nil {
@@ -680,7 +670,7 @@ func autoConvert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(
out.APIServerFloatingIP = in.APIServerFloatingIP
out.APIServerFixedIP = in.APIServerFixedIP
out.APIServerPort = in.APIServerPort
- out.ManagedSecurityGroups = in.ManagedSecurityGroups
+ // WARNING: in.ManagedSecurityGroups requires manual conversion: inconvertible types (bool vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8.ManagedSecurityGroups)
out.AllowAllInClusterTraffic = in.AllowAllInClusterTraffic
out.DisablePortSecurity = in.DisablePortSecurity
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
@@ -728,7 +718,7 @@ func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(
out.APIServerFloatingIP = in.APIServerFloatingIP
out.APIServerFixedIP = in.APIServerFixedIP
out.APIServerPort = in.APIServerPort
- out.ManagedSecurityGroups = in.ManagedSecurityGroups
+ // WARNING: in.ManagedSecurityGroups requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8.ManagedSecurityGroups vs bool)
out.AllowAllInClusterTraffic = in.AllowAllInClusterTraffic
out.DisablePortSecurity = in.DisablePortSecurity
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
@@ -769,9 +759,33 @@ func autoConvert_v1alpha5_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterSta
out.ExternalNetwork = nil
}
out.FailureDomains = *(*v1beta1.FailureDomains)(unsafe.Pointer(&in.FailureDomains))
- out.ControlPlaneSecurityGroup = (*v1alpha8.SecurityGroup)(unsafe.Pointer(in.ControlPlaneSecurityGroup))
- out.WorkerSecurityGroup = (*v1alpha8.SecurityGroup)(unsafe.Pointer(in.WorkerSecurityGroup))
- out.BastionSecurityGroup = (*v1alpha8.SecurityGroup)(unsafe.Pointer(in.BastionSecurityGroup))
+ if in.ControlPlaneSecurityGroup != nil {
+ in, out := &in.ControlPlaneSecurityGroup, &out.ControlPlaneSecurityGroup
+ *out = new(v1alpha8.SecurityGroupStatus)
+ if err := Convert_v1alpha5_SecurityGroup_To_v1alpha8_SecurityGroupStatus(*in, *out, s); err != nil {
+ return err
+ }
+ } else {
+ out.ControlPlaneSecurityGroup = nil
+ }
+ if in.WorkerSecurityGroup != nil {
+ in, out := &in.WorkerSecurityGroup, &out.WorkerSecurityGroup
+ *out = new(v1alpha8.SecurityGroupStatus)
+ if err := Convert_v1alpha5_SecurityGroup_To_v1alpha8_SecurityGroupStatus(*in, *out, s); err != nil {
+ return err
+ }
+ } else {
+ out.WorkerSecurityGroup = nil
+ }
+ if in.BastionSecurityGroup != nil {
+ in, out := &in.BastionSecurityGroup, &out.BastionSecurityGroup
+ *out = new(v1alpha8.SecurityGroupStatus)
+ if err := Convert_v1alpha5_SecurityGroup_To_v1alpha8_SecurityGroupStatus(*in, *out, s); err != nil {
+ return err
+ }
+ } else {
+ out.BastionSecurityGroup = nil
+ }
if in.Bastion != nil {
in, out := &in.Bastion, &out.Bastion
*out = new(v1alpha8.BastionStatus)
@@ -809,9 +823,33 @@ func autoConvert_v1alpha8_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))
+ if in.ControlPlaneSecurityGroup != nil {
+ in, out := &in.ControlPlaneSecurityGroup, &out.ControlPlaneSecurityGroup
+ *out = new(SecurityGroup)
+ if err := Convert_v1alpha8_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_v1alpha8_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_v1alpha8_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)
@@ -1374,30 +1412,6 @@ func Convert_v1alpha8_Router_To_v1alpha5_Router(in *v1alpha8.Router, out *Router
return autoConvert_v1alpha8_Router_To_v1alpha5_Router(in, out, s)
}
-func autoConvert_v1alpha5_SecurityGroup_To_v1alpha8_SecurityGroup(in *SecurityGroup, out *v1alpha8.SecurityGroup, s conversion.Scope) error {
- out.Name = in.Name
- out.ID = in.ID
- out.Rules = *(*[]v1alpha8.SecurityGroupRule)(unsafe.Pointer(&in.Rules))
- return nil
-}
-
-// Convert_v1alpha5_SecurityGroup_To_v1alpha8_SecurityGroup is an autogenerated conversion function.
-func Convert_v1alpha5_SecurityGroup_To_v1alpha8_SecurityGroup(in *SecurityGroup, out *v1alpha8.SecurityGroup, s conversion.Scope) error {
- return autoConvert_v1alpha5_SecurityGroup_To_v1alpha8_SecurityGroup(in, out, s)
-}
-
-func autoConvert_v1alpha8_SecurityGroup_To_v1alpha5_SecurityGroup(in *v1alpha8.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_v1alpha8_SecurityGroup_To_v1alpha5_SecurityGroup is an autogenerated conversion function.
-func Convert_v1alpha8_SecurityGroup_To_v1alpha5_SecurityGroup(in *v1alpha8.SecurityGroup, out *SecurityGroup, s conversion.Scope) error {
- return autoConvert_v1alpha8_SecurityGroup_To_v1alpha5_SecurityGroup(in, out, s)
-}
-
func autoConvert_v1alpha5_SecurityGroupFilter_To_v1alpha8_SecurityGroupFilter(in *SecurityGroupFilter, out *v1alpha8.SecurityGroupFilter, s conversion.Scope) error {
out.ID = in.ID
out.Name = in.Name
@@ -1432,44 +1446,6 @@ func Convert_v1alpha8_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(in *v1
return autoConvert_v1alpha8_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(in, out, s)
}
-func autoConvert_v1alpha5_SecurityGroupRule_To_v1alpha8_SecurityGroupRule(in *SecurityGroupRule, out *v1alpha8.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
- return nil
-}
-
-// Convert_v1alpha5_SecurityGroupRule_To_v1alpha8_SecurityGroupRule is an autogenerated conversion function.
-func Convert_v1alpha5_SecurityGroupRule_To_v1alpha8_SecurityGroupRule(in *SecurityGroupRule, out *v1alpha8.SecurityGroupRule, s conversion.Scope) error {
- return autoConvert_v1alpha5_SecurityGroupRule_To_v1alpha8_SecurityGroupRule(in, out, s)
-}
-
-func autoConvert_v1alpha8_SecurityGroupRule_To_v1alpha5_SecurityGroupRule(in *v1alpha8.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
- return nil
-}
-
-// Convert_v1alpha8_SecurityGroupRule_To_v1alpha5_SecurityGroupRule is an autogenerated conversion function.
-func Convert_v1alpha8_SecurityGroupRule_To_v1alpha5_SecurityGroupRule(in *v1alpha8.SecurityGroupRule, out *SecurityGroupRule, s conversion.Scope) error {
- return autoConvert_v1alpha8_SecurityGroupRule_To_v1alpha5_SecurityGroupRule(in, out, s)
-}
-
func autoConvert_v1alpha5_Subnet_To_v1alpha8_Subnet(in *Subnet, out *v1alpha8.Subnet, s conversion.Scope) error {
out.Name = in.Name
out.ID = in.ID
diff --git a/api/v1alpha6/conversion.go b/api/v1alpha6/conversion.go
index 177a2f0f8c..417d161237 100644
--- a/api/v1alpha6/conversion.go
+++ b/api/v1alpha6/conversion.go
@@ -21,6 +21,7 @@ import (
"strings"
apiconversion "k8s.io/apimachinery/pkg/conversion"
+ "k8s.io/utils/pointer"
ctrlconversion "sigs.k8s.io/controller-runtime/pkg/conversion"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
@@ -29,6 +30,16 @@ import (
const trueString = "true"
+func restorev1alpha6SecurityGroup(previous *SecurityGroup, dst *SecurityGroup) {
+ if previous == nil || dst == nil {
+ return
+ }
+
+ for i, rule := range previous.Rules {
+ dst.Rules[i].SecurityGroupID = rule.SecurityGroupID
+ }
+}
+
func restorev1alpha6MachineSpec(previous *OpenStackMachineSpec, dst *OpenStackMachineSpec) {
// Subnet is removed from v1alpha8 with no replacement, so can't be
// losslessly converted. Restore the previously stored value on down-conversion.
@@ -76,6 +87,10 @@ func restorev1alpha6ClusterStatus(previous *OpenStackClusterStatus, dst *OpenSta
if previous.Bastion != nil && previous.Bastion.Networks != nil {
dst.Bastion.Networks = previous.Bastion.Networks
}
+
+ restorev1alpha6SecurityGroup(previous.ControlPlaneSecurityGroup, dst.ControlPlaneSecurityGroup)
+ restorev1alpha6SecurityGroup(previous.WorkerSecurityGroup, dst.WorkerSecurityGroup)
+ restorev1alpha6SecurityGroup(previous.BastionSecurityGroup, dst.BastionSecurityGroup)
}
func restorev1alpha8MachineSpec(previous *infrav1.OpenStackMachineSpec, dst *infrav1.OpenStackMachineSpec) {
@@ -110,6 +125,10 @@ func restorev1alpha8ClusterStatus(previous *infrav1.OpenStackClusterStatus, dst
if previous.Bastion != nil {
dst.Bastion.ReferencedResources = previous.Bastion.ReferencedResources
}
+
+ dst.ControlPlaneSecurityGroup = previous.ControlPlaneSecurityGroup
+ dst.WorkerSecurityGroup = previous.WorkerSecurityGroup
+ dst.BastionSecurityGroup = previous.BastionSecurityGroup
}
func restorev1alpha6ClusterSpec(previous *OpenStackClusterSpec, dst *OpenStackClusterSpec) {
@@ -189,6 +208,12 @@ var v1alpha8OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStack
},
restorev1alpha8Subnets,
),
+ "allNodesSecurityGroupRules": conversion.HashedFieldRestorer(
+ func(c *infrav1.OpenStackCluster) *infrav1.ManagedSecurityGroups {
+ return c.Spec.ManagedSecurityGroups
+ },
+ restorev1alpha8ManagedSecurityGroups,
+ ),
"status": conversion.HashedFieldRestorer(
func(c *infrav1.OpenStackCluster) *infrav1.OpenStackClusterStatus {
return &c.Status
@@ -242,6 +267,10 @@ var v1alpha6OpenStackClusterTemplateRestorer = conversion.RestorerFor[*OpenStack
),
}
+func restorev1alpha8ManagedSecurityGroups(previous *infrav1.ManagedSecurityGroups, dst *infrav1.ManagedSecurityGroups) {
+ dst.AllNodesSecurityGroupRules = previous.AllNodesSecurityGroupRules
+}
+
var v1alpha8OpenStackClusterTemplateRestorer = conversion.RestorerFor[*infrav1.OpenStackClusterTemplate]{
"externalNetwork": conversion.UnconditionalFieldRestorer(
func(c *infrav1.OpenStackClusterTemplate) *infrav1.NetworkFilter {
@@ -275,6 +304,12 @@ var v1alpha8OpenStackClusterTemplateRestorer = conversion.RestorerFor[*infrav1.O
},
restorev1alpha8Subnets,
),
+ "allNodesSecurityGroupRules": conversion.HashedFieldRestorer(
+ func(c *infrav1.OpenStackClusterTemplate) *infrav1.ManagedSecurityGroups {
+ return c.Spec.Template.Spec.ManagedSecurityGroups
+ },
+ restorev1alpha8ManagedSecurityGroups,
+ ),
}
func (r *OpenStackClusterTemplate) ConvertTo(dstRaw ctrlconversion.Hub) error {
@@ -555,6 +590,10 @@ func Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(in *
out.DNSNameservers = in.ManagedSubnets[0].DNSNameservers
}
+ if in.ManagedSecurityGroups != nil {
+ out.ManagedSecurityGroups = true
+ }
+
return nil
}
@@ -589,6 +628,13 @@ func Convert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *
}
}
+ if in.ManagedSecurityGroups {
+ out.ManagedSecurityGroups = &infrav1.ManagedSecurityGroups{}
+ if !in.AllowAllInClusterTraffic {
+ out.ManagedSecurityGroups.AllNodesSecurityGroupRules = infrav1.LegacyCalicoSecurityGroupRules()
+ }
+ }
+
return nil
}
@@ -878,3 +924,58 @@ func Convert_v1alpha8_Bastion_To_v1alpha6_Bastion(in *infrav1.Bastion, out *Bast
out.Instance.FloatingIP = in.FloatingIP
return nil
}
+
+func Convert_v1alpha8_SecurityGroupStatus_To_v1alpha6_SecurityGroup(in *infrav1.SecurityGroupStatus, out *SecurityGroup, s apiconversion.Scope) error { //nolint:revive
+ out.ID = in.ID
+ out.Name = in.Name
+ out.Rules = make([]SecurityGroupRule, len(in.Rules))
+ for i, rule := range in.Rules {
+ out.Rules[i] = SecurityGroupRule{
+ ID: rule.ID,
+ Direction: rule.Direction,
+ }
+ if rule.Description != nil {
+ out.Rules[i].Description = *rule.Description
+ }
+ if rule.EtherType != nil {
+ out.Rules[i].EtherType = *rule.EtherType
+ }
+ if rule.PortRangeMin != nil {
+ out.Rules[i].PortRangeMin = *rule.PortRangeMin
+ }
+ if rule.PortRangeMax != nil {
+ out.Rules[i].PortRangeMax = *rule.PortRangeMax
+ }
+ if rule.Protocol != nil {
+ out.Rules[i].Protocol = *rule.Protocol
+ }
+ if rule.RemoteGroupID != nil {
+ out.Rules[i].RemoteGroupID = *rule.RemoteGroupID
+ }
+ if rule.RemoteIPPrefix != nil {
+ out.Rules[i].RemoteIPPrefix = *rule.RemoteIPPrefix
+ }
+ }
+ return nil
+}
+
+func Convert_v1alpha6_SecurityGroup_To_v1alpha8_SecurityGroupStatus(in *SecurityGroup, out *infrav1.SecurityGroupStatus, s apiconversion.Scope) error { //nolint:revive
+ out.ID = in.ID
+ out.Name = in.Name
+ out.Rules = make([]infrav1.SecurityGroupRuleStatus, len(in.Rules))
+ for i, rule := range in.Rules {
+ out.Rules[i] = infrav1.SecurityGroupRuleStatus{
+ ID: rule.ID,
+ Description: pointer.String(rule.Description),
+ Direction: rule.Direction,
+ EtherType: pointer.String(rule.EtherType),
+ PortRangeMin: pointer.Int(rule.PortRangeMin),
+ PortRangeMax: pointer.Int(rule.PortRangeMax),
+ Protocol: pointer.String(rule.Protocol),
+ RemoteGroupID: pointer.String(rule.RemoteGroupID),
+ RemoteIPPrefix: pointer.String(rule.RemoteIPPrefix),
+ }
+ }
+
+ return nil
+}
diff --git a/api/v1alpha6/conversion_test.go b/api/v1alpha6/conversion_test.go
index e6ed8f4c9e..2e684b8e35 100644
--- a/api/v1alpha6/conversion_test.go
+++ b/api/v1alpha6/conversion_test.go
@@ -654,3 +654,50 @@ func TestMachineConversionControllerSpecFields(t *testing.T) {
})
}
}
+
+func TestConvert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_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_v1alpha8_OpenStackClusterSpec(tt.in, out, nil)
+ g.Expect(err).NotTo(gomega.HaveOccurred())
+ g.Expect(out).To(gomega.Equal(tt.expectedOut))
+ })
+ }
+}
diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go
index 08c25e97cf..7df2ce7482 100644
--- a/api/v1alpha6/zz_generated.conversion.go
+++ b/api/v1alpha6/zz_generated.conversion.go
@@ -254,31 +254,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*SecurityGroup)(nil), (*v1alpha8.SecurityGroup)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_SecurityGroup_To_v1alpha8_SecurityGroup(a.(*SecurityGroup), b.(*v1alpha8.SecurityGroup), scope)
- }); err != nil {
- return err
- }
- if err := s.AddGeneratedConversionFunc((*v1alpha8.SecurityGroup)(nil), (*SecurityGroup)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_SecurityGroup_To_v1alpha6_SecurityGroup(a.(*v1alpha8.SecurityGroup), b.(*SecurityGroup), scope)
- }); err != nil {
- return err
- }
if err := s.AddGeneratedConversionFunc((*v1alpha8.SecurityGroupFilter)(nil), (*SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha8_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(a.(*v1alpha8.SecurityGroupFilter), b.(*SecurityGroupFilter), scope)
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*SecurityGroupRule)(nil), (*v1alpha8.SecurityGroupRule)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_SecurityGroupRule_To_v1alpha8_SecurityGroupRule(a.(*SecurityGroupRule), b.(*v1alpha8.SecurityGroupRule), scope)
- }); err != nil {
- return err
- }
- if err := s.AddGeneratedConversionFunc((*v1alpha8.SecurityGroupRule)(nil), (*SecurityGroupRule)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_SecurityGroupRule_To_v1alpha6_SecurityGroupRule(a.(*v1alpha8.SecurityGroupRule), b.(*SecurityGroupRule), scope)
- }); err != nil {
- return err
- }
if err := s.AddGeneratedConversionFunc((*Subnet)(nil), (*v1alpha8.Subnet)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha6_Subnet_To_v1alpha8_Subnet(a.(*Subnet), b.(*v1alpha8.Subnet), scope)
}); err != nil {
@@ -359,6 +339,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
+ if err := s.AddConversionFunc((*SecurityGroup)(nil), (*v1alpha8.SecurityGroupStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_SecurityGroup_To_v1alpha8_SecurityGroupStatus(a.(*SecurityGroup), b.(*v1alpha8.SecurityGroupStatus), scope)
+ }); err != nil {
+ return err
+ }
if err := s.AddConversionFunc((*SubnetParam)(nil), (*v1alpha8.SubnetFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha6_SubnetParam_To_v1alpha8_SubnetFilter(a.(*SubnetParam), b.(*v1alpha8.SubnetFilter), scope)
}); err != nil {
@@ -414,6 +399,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
+ if err := s.AddConversionFunc((*v1alpha8.SecurityGroupStatus)(nil), (*SecurityGroup)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_SecurityGroupStatus_To_v1alpha6_SecurityGroup(a.(*v1alpha8.SecurityGroupStatus), b.(*SecurityGroup), scope)
+ }); err != nil {
+ return err
+ }
if err := s.AddConversionFunc((*v1alpha8.SubnetFilter)(nil), (*SubnetParam)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha8_SubnetFilter_To_v1alpha6_SubnetParam(a.(*v1alpha8.SubnetFilter), b.(*SubnetParam), scope)
}); err != nil {
@@ -702,7 +692,7 @@ func autoConvert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(
out.APIServerFloatingIP = in.APIServerFloatingIP
out.APIServerFixedIP = in.APIServerFixedIP
out.APIServerPort = in.APIServerPort
- out.ManagedSecurityGroups = in.ManagedSecurityGroups
+ // WARNING: in.ManagedSecurityGroups requires manual conversion: inconvertible types (bool vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8.ManagedSecurityGroups)
out.AllowAllInClusterTraffic = in.AllowAllInClusterTraffic
out.DisablePortSecurity = in.DisablePortSecurity
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
@@ -751,7 +741,7 @@ func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(
out.APIServerFloatingIP = in.APIServerFloatingIP
out.APIServerFixedIP = in.APIServerFixedIP
out.APIServerPort = in.APIServerPort
- out.ManagedSecurityGroups = in.ManagedSecurityGroups
+ // WARNING: in.ManagedSecurityGroups requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8.ManagedSecurityGroups vs bool)
out.AllowAllInClusterTraffic = in.AllowAllInClusterTraffic
out.DisablePortSecurity = in.DisablePortSecurity
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
@@ -792,9 +782,33 @@ func autoConvert_v1alpha6_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterSta
out.ExternalNetwork = nil
}
out.FailureDomains = *(*v1beta1.FailureDomains)(unsafe.Pointer(&in.FailureDomains))
- out.ControlPlaneSecurityGroup = (*v1alpha8.SecurityGroup)(unsafe.Pointer(in.ControlPlaneSecurityGroup))
- out.WorkerSecurityGroup = (*v1alpha8.SecurityGroup)(unsafe.Pointer(in.WorkerSecurityGroup))
- out.BastionSecurityGroup = (*v1alpha8.SecurityGroup)(unsafe.Pointer(in.BastionSecurityGroup))
+ if in.ControlPlaneSecurityGroup != nil {
+ in, out := &in.ControlPlaneSecurityGroup, &out.ControlPlaneSecurityGroup
+ *out = new(v1alpha8.SecurityGroupStatus)
+ if err := Convert_v1alpha6_SecurityGroup_To_v1alpha8_SecurityGroupStatus(*in, *out, s); err != nil {
+ return err
+ }
+ } else {
+ out.ControlPlaneSecurityGroup = nil
+ }
+ if in.WorkerSecurityGroup != nil {
+ in, out := &in.WorkerSecurityGroup, &out.WorkerSecurityGroup
+ *out = new(v1alpha8.SecurityGroupStatus)
+ if err := Convert_v1alpha6_SecurityGroup_To_v1alpha8_SecurityGroupStatus(*in, *out, s); err != nil {
+ return err
+ }
+ } else {
+ out.WorkerSecurityGroup = nil
+ }
+ if in.BastionSecurityGroup != nil {
+ in, out := &in.BastionSecurityGroup, &out.BastionSecurityGroup
+ *out = new(v1alpha8.SecurityGroupStatus)
+ if err := Convert_v1alpha6_SecurityGroup_To_v1alpha8_SecurityGroupStatus(*in, *out, s); err != nil {
+ return err
+ }
+ } else {
+ out.BastionSecurityGroup = nil
+ }
if in.Bastion != nil {
in, out := &in.Bastion, &out.Bastion
*out = new(v1alpha8.BastionStatus)
@@ -832,9 +846,33 @@ func autoConvert_v1alpha8_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))
+ if in.ControlPlaneSecurityGroup != nil {
+ in, out := &in.ControlPlaneSecurityGroup, &out.ControlPlaneSecurityGroup
+ *out = new(SecurityGroup)
+ if err := Convert_v1alpha8_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_v1alpha8_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_v1alpha8_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)
@@ -1398,30 +1436,6 @@ func Convert_v1alpha8_Router_To_v1alpha6_Router(in *v1alpha8.Router, out *Router
return autoConvert_v1alpha8_Router_To_v1alpha6_Router(in, out, s)
}
-func autoConvert_v1alpha6_SecurityGroup_To_v1alpha8_SecurityGroup(in *SecurityGroup, out *v1alpha8.SecurityGroup, s conversion.Scope) error {
- out.Name = in.Name
- out.ID = in.ID
- out.Rules = *(*[]v1alpha8.SecurityGroupRule)(unsafe.Pointer(&in.Rules))
- return nil
-}
-
-// Convert_v1alpha6_SecurityGroup_To_v1alpha8_SecurityGroup is an autogenerated conversion function.
-func Convert_v1alpha6_SecurityGroup_To_v1alpha8_SecurityGroup(in *SecurityGroup, out *v1alpha8.SecurityGroup, s conversion.Scope) error {
- return autoConvert_v1alpha6_SecurityGroup_To_v1alpha8_SecurityGroup(in, out, s)
-}
-
-func autoConvert_v1alpha8_SecurityGroup_To_v1alpha6_SecurityGroup(in *v1alpha8.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_v1alpha8_SecurityGroup_To_v1alpha6_SecurityGroup is an autogenerated conversion function.
-func Convert_v1alpha8_SecurityGroup_To_v1alpha6_SecurityGroup(in *v1alpha8.SecurityGroup, out *SecurityGroup, s conversion.Scope) error {
- return autoConvert_v1alpha8_SecurityGroup_To_v1alpha6_SecurityGroup(in, out, s)
-}
-
func autoConvert_v1alpha6_SecurityGroupFilter_To_v1alpha8_SecurityGroupFilter(in *SecurityGroupFilter, out *v1alpha8.SecurityGroupFilter, s conversion.Scope) error {
out.ID = in.ID
out.Name = in.Name
@@ -1456,44 +1470,6 @@ func Convert_v1alpha8_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(in *v1
return autoConvert_v1alpha8_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(in, out, s)
}
-func autoConvert_v1alpha6_SecurityGroupRule_To_v1alpha8_SecurityGroupRule(in *SecurityGroupRule, out *v1alpha8.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
- return nil
-}
-
-// Convert_v1alpha6_SecurityGroupRule_To_v1alpha8_SecurityGroupRule is an autogenerated conversion function.
-func Convert_v1alpha6_SecurityGroupRule_To_v1alpha8_SecurityGroupRule(in *SecurityGroupRule, out *v1alpha8.SecurityGroupRule, s conversion.Scope) error {
- return autoConvert_v1alpha6_SecurityGroupRule_To_v1alpha8_SecurityGroupRule(in, out, s)
-}
-
-func autoConvert_v1alpha8_SecurityGroupRule_To_v1alpha6_SecurityGroupRule(in *v1alpha8.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
- return nil
-}
-
-// Convert_v1alpha8_SecurityGroupRule_To_v1alpha6_SecurityGroupRule is an autogenerated conversion function.
-func Convert_v1alpha8_SecurityGroupRule_To_v1alpha6_SecurityGroupRule(in *v1alpha8.SecurityGroupRule, out *SecurityGroupRule, s conversion.Scope) error {
- return autoConvert_v1alpha8_SecurityGroupRule_To_v1alpha6_SecurityGroupRule(in, out, s)
-}
-
func autoConvert_v1alpha6_Subnet_To_v1alpha8_Subnet(in *Subnet, out *v1alpha8.Subnet, s conversion.Scope) error {
out.Name = in.Name
out.ID = in.ID
diff --git a/api/v1alpha7/conversion.go b/api/v1alpha7/conversion.go
index 9bfa6ad90d..1e84d4f0b9 100644
--- a/api/v1alpha7/conversion.go
+++ b/api/v1alpha7/conversion.go
@@ -18,6 +18,7 @@ package v1alpha7
import (
apiconversion "k8s.io/apimachinery/pkg/conversion"
+ "k8s.io/utils/pointer"
ctrlconversion "sigs.k8s.io/controller-runtime/pkg/conversion"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
@@ -57,6 +58,72 @@ var v1alpha7OpenStackClusterRestorer = conversion.RestorerFor[*OpenStackCluster]
},
),
),
+ "status": conversion.HashedFieldRestorer(
+ func(c *OpenStackCluster) *OpenStackClusterStatus {
+ return &c.Status
+ },
+ restorev1alpha7ClusterStatus,
+ ),
+}
+
+func restorev1alpha7SecurityGroup(previous *SecurityGroup, dst *SecurityGroup) {
+ if previous == nil || dst == nil {
+ return
+ }
+
+ for i, rule := range previous.Rules {
+ dst.Rules[i].SecurityGroupID = rule.SecurityGroupID
+ }
+}
+
+func restorev1alpha7ClusterStatus(previous *OpenStackClusterStatus, dst *OpenStackClusterStatus) {
+ restorev1alpha7SecurityGroup(previous.ControlPlaneSecurityGroup, dst.ControlPlaneSecurityGroup)
+ restorev1alpha7SecurityGroup(previous.WorkerSecurityGroup, dst.WorkerSecurityGroup)
+ restorev1alpha7SecurityGroup(previous.BastionSecurityGroup, dst.BastionSecurityGroup)
+}
+
+func restorev1alpha8SecurityGroupStatus(previous *infrav1.SecurityGroupStatus, dst *infrav1.SecurityGroupStatus) {
+ if previous == nil || dst == nil {
+ return
+ }
+
+ for i := range dst.Rules {
+ dstRule := &dst.Rules[i]
+
+ // Conversion from scalar to *scalar is lossy for zero values. We need to restore only nil values.
+ if dstRule.Description != nil && *dstRule.Description == "" {
+ dstRule.Description = previous.Rules[i].Description
+ }
+ if dstRule.EtherType != nil && *dstRule.EtherType == "" {
+ dstRule.EtherType = previous.Rules[i].EtherType
+ }
+ if dstRule.PortRangeMin != nil && *dstRule.PortRangeMin == 0 {
+ dstRule.PortRangeMin = previous.Rules[i].PortRangeMin
+ }
+ if dstRule.PortRangeMax != nil && *dstRule.PortRangeMax == 0 {
+ dstRule.PortRangeMax = previous.Rules[i].PortRangeMax
+ }
+ if dstRule.Protocol != nil && *dstRule.Protocol == "" {
+ dstRule.Protocol = previous.Rules[i].Protocol
+ }
+ if dstRule.RemoteGroupID != nil && *dstRule.RemoteGroupID == "" {
+ dstRule.RemoteGroupID = previous.Rules[i].RemoteGroupID
+ }
+ if dstRule.RemoteIPPrefix != nil && *dstRule.RemoteIPPrefix == "" {
+ dstRule.RemoteIPPrefix = previous.Rules[i].RemoteIPPrefix
+ }
+ }
+}
+
+func restorev1alpha8ClusterStatus(previous *infrav1.OpenStackClusterStatus, dst *infrav1.OpenStackClusterStatus) {
+ restorev1alpha8SecurityGroupStatus(previous.ControlPlaneSecurityGroup, dst.ControlPlaneSecurityGroup)
+ restorev1alpha8SecurityGroupStatus(previous.WorkerSecurityGroup, dst.WorkerSecurityGroup)
+ restorev1alpha8SecurityGroupStatus(previous.BastionSecurityGroup, dst.BastionSecurityGroup)
+
+ // ReferencedResources have no equivalent in v1alpha7
+ if dst.Bastion != nil {
+ dst.Bastion.ReferencedResources = previous.Bastion.ReferencedResources
+ }
}
var v1alpha8OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStackCluster]{
@@ -85,14 +152,11 @@ var v1alpha8OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStack
),
),
- // No equivalent in v1alpha7
- "bastionrefresources": conversion.UnconditionalFieldRestorer(
- func(c *infrav1.OpenStackCluster) *infrav1.ReferencedMachineResources {
- if c.Status.Bastion == nil {
- return nil
- }
- return &c.Status.Bastion.ReferencedResources
+ "status": conversion.HashedFieldRestorer(
+ func(c *infrav1.OpenStackCluster) *infrav1.OpenStackClusterStatus {
+ return &c.Status
},
+ restorev1alpha8ClusterStatus,
),
}
@@ -165,6 +229,10 @@ func restorev1alpha8ClusterSpec(previous *infrav1.OpenStackClusterSpec, dst *inf
}
dst.ManagedSubnets = previous.ManagedSubnets
+
+ if previous.ManagedSecurityGroups != nil {
+ dst.ManagedSecurityGroups.AllNodesSecurityGroupRules = previous.ManagedSecurityGroups.AllNodesSecurityGroupRules
+ }
}
func (r *OpenStackCluster) ConvertTo(dstRaw ctrlconversion.Hub) error {
@@ -509,6 +577,13 @@ func Convert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *
}
}
+ if in.ManagedSecurityGroups {
+ out.ManagedSecurityGroups = &infrav1.ManagedSecurityGroups{}
+ if !in.AllowAllInClusterTraffic {
+ out.ManagedSecurityGroups.AllNodesSecurityGroupRules = infrav1.LegacyCalicoSecurityGroupRules()
+ }
+ }
+
return nil
}
@@ -533,5 +608,64 @@ func Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in *
out.DNSNameservers = in.ManagedSubnets[0].DNSNameservers
}
+ if in.ManagedSecurityGroups != nil {
+ out.ManagedSecurityGroups = true
+ }
+
+ return nil
+}
+
+func Convert_v1alpha8_SecurityGroupStatus_To_v1alpha7_SecurityGroup(in *infrav1.SecurityGroupStatus, out *SecurityGroup, s apiconversion.Scope) error { //nolint:revive
+ out.ID = in.ID
+ out.Name = in.Name
+ out.Rules = make([]SecurityGroupRule, len(in.Rules))
+ for i, rule := range in.Rules {
+ out.Rules[i] = SecurityGroupRule{
+ ID: rule.ID,
+ Direction: rule.Direction,
+ }
+ if rule.Description != nil {
+ out.Rules[i].Description = *rule.Description
+ }
+ if rule.EtherType != nil {
+ out.Rules[i].EtherType = *rule.EtherType
+ }
+ if rule.PortRangeMin != nil {
+ out.Rules[i].PortRangeMin = *rule.PortRangeMin
+ }
+ if rule.PortRangeMax != nil {
+ out.Rules[i].PortRangeMax = *rule.PortRangeMax
+ }
+ if rule.Protocol != nil {
+ out.Rules[i].Protocol = *rule.Protocol
+ }
+ if rule.RemoteGroupID != nil {
+ out.Rules[i].RemoteGroupID = *rule.RemoteGroupID
+ }
+ if rule.RemoteIPPrefix != nil {
+ out.Rules[i].RemoteIPPrefix = *rule.RemoteIPPrefix
+ }
+ }
+ return nil
+}
+
+func Convert_v1alpha7_SecurityGroup_To_v1alpha8_SecurityGroupStatus(in *SecurityGroup, out *infrav1.SecurityGroupStatus, s apiconversion.Scope) error { //nolint:revive
+ out.ID = in.ID
+ out.Name = in.Name
+ out.Rules = make([]infrav1.SecurityGroupRuleStatus, len(in.Rules))
+ for i, rule := range in.Rules {
+ out.Rules[i] = infrav1.SecurityGroupRuleStatus{
+ ID: rule.ID,
+ Description: pointer.String(rule.Description),
+ Direction: rule.Direction,
+ EtherType: pointer.String(rule.EtherType),
+ PortRangeMin: pointer.Int(rule.PortRangeMin),
+ PortRangeMax: pointer.Int(rule.PortRangeMax),
+ Protocol: pointer.String(rule.Protocol),
+ RemoteGroupID: pointer.String(rule.RemoteGroupID),
+ RemoteIPPrefix: pointer.String(rule.RemoteIPPrefix),
+ }
+ }
+
return nil
}
diff --git a/api/v1alpha7/conversion_test.go b/api/v1alpha7/conversion_test.go
index 97763d7d4b..90b391f037 100644
--- a/api/v1alpha7/conversion_test.go
+++ b/api/v1alpha7/conversion_test.go
@@ -269,3 +269,50 @@ func TestMachineConversionControllerSpecFields(t *testing.T) {
})
}
}
+
+func TestConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_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_v1alpha8_OpenStackClusterSpec(tt.in, out, nil)
+ g.Expect(err).NotTo(gomega.HaveOccurred())
+ g.Expect(out).To(gomega.Equal(tt.expectedOut))
+ })
+ }
+}
diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go
index de0e42be72..5ff683e8fb 100644
--- a/api/v1alpha7/zz_generated.conversion.go
+++ b/api/v1alpha7/zz_generated.conversion.go
@@ -349,16 +349,6 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*SecurityGroup)(nil), (*v1alpha8.SecurityGroup)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_SecurityGroup_To_v1alpha8_SecurityGroup(a.(*SecurityGroup), b.(*v1alpha8.SecurityGroup), scope)
- }); err != nil {
- return err
- }
- if err := s.AddGeneratedConversionFunc((*v1alpha8.SecurityGroup)(nil), (*SecurityGroup)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_SecurityGroup_To_v1alpha7_SecurityGroup(a.(*v1alpha8.SecurityGroup), b.(*SecurityGroup), scope)
- }); err != nil {
- return err
- }
if err := s.AddGeneratedConversionFunc((*SecurityGroupFilter)(nil), (*v1alpha8.SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha7_SecurityGroupFilter_To_v1alpha8_SecurityGroupFilter(a.(*SecurityGroupFilter), b.(*v1alpha8.SecurityGroupFilter), scope)
}); err != nil {
@@ -369,16 +359,6 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*SecurityGroupRule)(nil), (*v1alpha8.SecurityGroupRule)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_SecurityGroupRule_To_v1alpha8_SecurityGroupRule(a.(*SecurityGroupRule), b.(*v1alpha8.SecurityGroupRule), scope)
- }); err != nil {
- return err
- }
- if err := s.AddGeneratedConversionFunc((*v1alpha8.SecurityGroupRule)(nil), (*SecurityGroupRule)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_SecurityGroupRule_To_v1alpha7_SecurityGroupRule(a.(*v1alpha8.SecurityGroupRule), b.(*SecurityGroupRule), scope)
- }); err != nil {
- return err
- }
if err := s.AddGeneratedConversionFunc((*Subnet)(nil), (*v1alpha8.Subnet)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha7_Subnet_To_v1alpha8_Subnet(a.(*Subnet), b.(*v1alpha8.Subnet), scope)
}); err != nil {
@@ -424,6 +404,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
+ if err := s.AddConversionFunc((*SecurityGroup)(nil), (*v1alpha8.SecurityGroupStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_SecurityGroup_To_v1alpha8_SecurityGroupStatus(a.(*SecurityGroup), b.(*v1alpha8.SecurityGroupStatus), scope)
+ }); err != nil {
+ return err
+ }
if err := s.AddConversionFunc((*v1alpha8.BastionStatus)(nil), (*BastionStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha8_BastionStatus_To_v1alpha7_BastionStatus(a.(*v1alpha8.BastionStatus), b.(*BastionStatus), scope)
}); err != nil {
@@ -449,6 +434,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
+ if err := s.AddConversionFunc((*v1alpha8.SecurityGroupStatus)(nil), (*SecurityGroup)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_SecurityGroupStatus_To_v1alpha7_SecurityGroup(a.(*v1alpha8.SecurityGroupStatus), b.(*SecurityGroup), scope)
+ }); err != nil {
+ return err
+ }
return nil
}
@@ -894,7 +884,7 @@ func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(
out.APIServerFloatingIP = in.APIServerFloatingIP
out.APIServerFixedIP = in.APIServerFixedIP
out.APIServerPort = in.APIServerPort
- out.ManagedSecurityGroups = in.ManagedSecurityGroups
+ // WARNING: in.ManagedSecurityGroups requires manual conversion: inconvertible types (bool vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8.ManagedSecurityGroups)
out.AllowAllInClusterTraffic = in.AllowAllInClusterTraffic
out.DisablePortSecurity = in.DisablePortSecurity
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
@@ -933,7 +923,7 @@ func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(
out.APIServerFloatingIP = in.APIServerFloatingIP
out.APIServerFixedIP = in.APIServerFixedIP
out.APIServerPort = in.APIServerPort
- out.ManagedSecurityGroups = in.ManagedSecurityGroups
+ // WARNING: in.ManagedSecurityGroups requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8.ManagedSecurityGroups vs bool)
out.AllowAllInClusterTraffic = in.AllowAllInClusterTraffic
out.DisablePortSecurity = in.DisablePortSecurity
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
@@ -960,9 +950,33 @@ func autoConvert_v1alpha7_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterSta
out.Router = (*v1alpha8.Router)(unsafe.Pointer(in.Router))
out.APIServerLoadBalancer = (*v1alpha8.LoadBalancer)(unsafe.Pointer(in.APIServerLoadBalancer))
out.FailureDomains = *(*v1beta1.FailureDomains)(unsafe.Pointer(&in.FailureDomains))
- out.ControlPlaneSecurityGroup = (*v1alpha8.SecurityGroup)(unsafe.Pointer(in.ControlPlaneSecurityGroup))
- out.WorkerSecurityGroup = (*v1alpha8.SecurityGroup)(unsafe.Pointer(in.WorkerSecurityGroup))
- out.BastionSecurityGroup = (*v1alpha8.SecurityGroup)(unsafe.Pointer(in.BastionSecurityGroup))
+ if in.ControlPlaneSecurityGroup != nil {
+ in, out := &in.ControlPlaneSecurityGroup, &out.ControlPlaneSecurityGroup
+ *out = new(v1alpha8.SecurityGroupStatus)
+ if err := Convert_v1alpha7_SecurityGroup_To_v1alpha8_SecurityGroupStatus(*in, *out, s); err != nil {
+ return err
+ }
+ } else {
+ out.ControlPlaneSecurityGroup = nil
+ }
+ if in.WorkerSecurityGroup != nil {
+ in, out := &in.WorkerSecurityGroup, &out.WorkerSecurityGroup
+ *out = new(v1alpha8.SecurityGroupStatus)
+ if err := Convert_v1alpha7_SecurityGroup_To_v1alpha8_SecurityGroupStatus(*in, *out, s); err != nil {
+ return err
+ }
+ } else {
+ out.WorkerSecurityGroup = nil
+ }
+ if in.BastionSecurityGroup != nil {
+ in, out := &in.BastionSecurityGroup, &out.BastionSecurityGroup
+ *out = new(v1alpha8.SecurityGroupStatus)
+ if err := Convert_v1alpha7_SecurityGroup_To_v1alpha8_SecurityGroupStatus(*in, *out, s); err != nil {
+ return err
+ }
+ } else {
+ out.BastionSecurityGroup = nil
+ }
if in.Bastion != nil {
in, out := &in.Bastion, &out.Bastion
*out = new(v1alpha8.BastionStatus)
@@ -989,9 +1003,33 @@ func autoConvert_v1alpha8_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterSta
out.Router = (*Router)(unsafe.Pointer(in.Router))
out.APIServerLoadBalancer = (*LoadBalancer)(unsafe.Pointer(in.APIServerLoadBalancer))
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))
+ if in.ControlPlaneSecurityGroup != nil {
+ in, out := &in.ControlPlaneSecurityGroup, &out.ControlPlaneSecurityGroup
+ *out = new(SecurityGroup)
+ if err := Convert_v1alpha8_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_v1alpha8_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_v1alpha8_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)
@@ -1545,30 +1583,6 @@ func Convert_v1alpha8_RouterFilter_To_v1alpha7_RouterFilter(in *v1alpha8.RouterF
return autoConvert_v1alpha8_RouterFilter_To_v1alpha7_RouterFilter(in, out, s)
}
-func autoConvert_v1alpha7_SecurityGroup_To_v1alpha8_SecurityGroup(in *SecurityGroup, out *v1alpha8.SecurityGroup, s conversion.Scope) error {
- out.Name = in.Name
- out.ID = in.ID
- out.Rules = *(*[]v1alpha8.SecurityGroupRule)(unsafe.Pointer(&in.Rules))
- return nil
-}
-
-// Convert_v1alpha7_SecurityGroup_To_v1alpha8_SecurityGroup is an autogenerated conversion function.
-func Convert_v1alpha7_SecurityGroup_To_v1alpha8_SecurityGroup(in *SecurityGroup, out *v1alpha8.SecurityGroup, s conversion.Scope) error {
- return autoConvert_v1alpha7_SecurityGroup_To_v1alpha8_SecurityGroup(in, out, s)
-}
-
-func autoConvert_v1alpha8_SecurityGroup_To_v1alpha7_SecurityGroup(in *v1alpha8.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_v1alpha8_SecurityGroup_To_v1alpha7_SecurityGroup is an autogenerated conversion function.
-func Convert_v1alpha8_SecurityGroup_To_v1alpha7_SecurityGroup(in *v1alpha8.SecurityGroup, out *SecurityGroup, s conversion.Scope) error {
- return autoConvert_v1alpha8_SecurityGroup_To_v1alpha7_SecurityGroup(in, out, s)
-}
-
func autoConvert_v1alpha7_SecurityGroupFilter_To_v1alpha8_SecurityGroupFilter(in *SecurityGroupFilter, out *v1alpha8.SecurityGroupFilter, s conversion.Scope) error {
out.ID = in.ID
out.Name = in.Name
@@ -1603,44 +1617,6 @@ func Convert_v1alpha8_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in *v1
return autoConvert_v1alpha8_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in, out, s)
}
-func autoConvert_v1alpha7_SecurityGroupRule_To_v1alpha8_SecurityGroupRule(in *SecurityGroupRule, out *v1alpha8.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
- return nil
-}
-
-// Convert_v1alpha7_SecurityGroupRule_To_v1alpha8_SecurityGroupRule is an autogenerated conversion function.
-func Convert_v1alpha7_SecurityGroupRule_To_v1alpha8_SecurityGroupRule(in *SecurityGroupRule, out *v1alpha8.SecurityGroupRule, s conversion.Scope) error {
- return autoConvert_v1alpha7_SecurityGroupRule_To_v1alpha8_SecurityGroupRule(in, out, s)
-}
-
-func autoConvert_v1alpha8_SecurityGroupRule_To_v1alpha7_SecurityGroupRule(in *v1alpha8.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
- return nil
-}
-
-// Convert_v1alpha8_SecurityGroupRule_To_v1alpha7_SecurityGroupRule is an autogenerated conversion function.
-func Convert_v1alpha8_SecurityGroupRule_To_v1alpha7_SecurityGroupRule(in *v1alpha8.SecurityGroupRule, out *SecurityGroupRule, s conversion.Scope) error {
- return autoConvert_v1alpha8_SecurityGroupRule_To_v1alpha7_SecurityGroupRule(in, out, s)
-}
-
func autoConvert_v1alpha7_Subnet_To_v1alpha8_Subnet(in *Subnet, out *v1alpha8.Subnet, s conversion.Scope) error {
out.Name = in.Name
out.ID = in.ID
diff --git a/api/v1alpha8/conversion.go b/api/v1alpha8/conversion.go
index 49a817623d..d59b51d96f 100644
--- a/api/v1alpha8/conversion.go
+++ b/api/v1alpha8/conversion.go
@@ -16,6 +16,8 @@ limitations under the License.
package v1alpha8
+import "k8s.io/utils/pointer"
+
// Hub marks OpenStackCluster as a conversion hub.
func (*OpenStackCluster) Hub() {}
@@ -39,3 +41,29 @@ 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 v1alpha8.
+func LegacyCalicoSecurityGroupRules() []SecurityGroupRuleSpec {
+ return []SecurityGroupRuleSpec{
+ {
+ Name: "BGP (calico)",
+ Description: pointer.String("Created by cluster-api-provider-openstack API conversion - BGP (calico)"),
+ Direction: "ingress",
+ EtherType: pointer.String("IPv4"),
+ PortRangeMin: pointer.Int(179),
+ PortRangeMax: pointer.Int(179),
+ Protocol: pointer.String("tcp"),
+ RemoteManagedGroups: []ManagedSecurityGroupName{"controlplane", "worker"},
+ },
+ {
+ Name: "IP-in-IP (calico)",
+ Description: pointer.String("Created by cluster-api-provider-openstack API conversion - IP-in-IP (calico)"),
+ Direction: "ingress",
+ EtherType: pointer.String("IPv4"),
+ Protocol: pointer.String("4"),
+ RemoteManagedGroups: []ManagedSecurityGroupName{"controlplane", "worker"},
+ },
+ }
+}
diff --git a/api/v1alpha8/openstackcluster_types.go b/api/v1alpha8/openstackcluster_types.go
index 5f25489e24..cabb2a55ca 100644
--- a/api/v1alpha8/openstackcluster_types.go
+++ b/api/v1alpha8/openstackcluster_types.go
@@ -122,10 +122,12 @@ type OpenStackClusterSpec struct {
// 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.
+ // 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
- ManagedSecurityGroups bool `json:"managedSecurityGroups"`
+ ManagedSecurityGroups *ManagedSecurityGroups `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
@@ -191,13 +193,13 @@ type OpenStackClusterStatus struct {
// 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 *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 *SecurityGroupStatus `json:"workerSecurityGroup,omitempty"`
- BastionSecurityGroup *SecurityGroup `json:"bastionSecurityGroup,omitempty"`
+ BastionSecurityGroup *SecurityGroupStatus `json:"bastionSecurityGroup,omitempty"`
Bastion *BastionStatus `json:"bastion,omitempty"`
@@ -269,6 +271,17 @@ 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" patchStrategy:"merge" patchMergeKey:"name"`
+}
+
func init() {
objectTypes = append(objectTypes, &OpenStackCluster{}, &OpenStackClusterList{})
}
diff --git a/api/v1alpha8/openstackcluster_webhook.go b/api/v1alpha8/openstackcluster_webhook.go
index b47c2ac612..d2051a09e5 100644
--- a/api/v1alpha8/openstackcluster_webhook.go
+++ b/api/v1alpha8/openstackcluster_webhook.go
@@ -63,6 +63,20 @@ func (r *OpenStackCluster) ValidateCreate() (admission.Warnings, error) {
allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "identityRef", "kind"), "must be a Secret"))
}
+ if r.Spec.ManagedSecurityGroups != nil {
+ for _, rule := range r.Spec.ManagedSecurityGroups.AllNodesSecurityGroupRules {
+ if rule.RemoteManagedGroups != nil && (rule.RemoteGroupID != nil || rule.RemoteIPPrefix != nil) {
+ allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "managedSecurityGroups", "allNodesSecurityGroupRules"), "remoteManagedGroups cannot be used with remoteGroupID or remoteIPPrefix"))
+ }
+ if rule.RemoteGroupID != nil && (rule.RemoteManagedGroups != nil || rule.RemoteIPPrefix != nil) {
+ allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "managedSecurityGroups", "allNodesSecurityGroupRules"), "remoteGroupID cannot be used with remoteManagedGroups or remoteIPPrefix"))
+ }
+ if rule.RemoteIPPrefix != nil && (rule.RemoteManagedGroups != nil || rule.RemoteGroupID != nil) {
+ allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "managedSecurityGroups", "allNodesSecurityGroupRules"), "remoteIPPrefix cannot be used with remoteManagedGroups or remoteGroupID"))
+ }
+ }
+ }
+
return aggregateObjErrors(r.GroupVersionKind().GroupKind(), r.Name, allErrs)
}
@@ -127,6 +141,12 @@ func (r *OpenStackCluster) ValidateUpdate(oldRaw runtime.Object) (admission.Warn
old.Spec.Bastion = &Bastion{}
r.Spec.Bastion = &Bastion{}
+ // Allow changes to the managed allNodesSecurityGroupRules.
+ if r.Spec.ManagedSecurityGroups != nil {
+ old.Spec.ManagedSecurityGroups.AllNodesSecurityGroupRules = []SecurityGroupRuleSpec{}
+ r.Spec.ManagedSecurityGroups.AllNodesSecurityGroupRules = []SecurityGroupRuleSpec{}
+ }
+
// Allow changes on AllowedCIDRs
if r.Spec.APIServerLoadBalancer.Enabled {
old.Spec.APIServerLoadBalancer.AllowedCIDRs = []string{}
diff --git a/api/v1alpha8/openstackcluster_webhook_test.go b/api/v1alpha8/openstackcluster_webhook_test.go
index 734a388763..3985e76605 100644
--- a/api/v1alpha8/openstackcluster_webhook_test.go
+++ b/api/v1alpha8/openstackcluster_webhook_test.go
@@ -20,6 +20,7 @@ import (
"testing"
. "github.com/onsi/gomega"
+ "k8s.io/utils/pointer"
)
func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
@@ -146,6 +147,44 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
wantErr: false,
},
+ {
+ name: "Changing security group rules on the OpenStackCluster.Spec.ManagedSecurityGroups.AllNodesSecurityGroupRules is allowed",
+ oldTemplate: &OpenStackCluster{
+ Spec: OpenStackClusterSpec{
+ CloudName: "foobar",
+ ManagedSecurityGroups: &ManagedSecurityGroups{
+ AllNodesSecurityGroupRules: []SecurityGroupRuleSpec{
+ {
+ Name: "foobar",
+ Description: pointer.String("foobar"),
+ PortRangeMin: pointer.Int(80),
+ PortRangeMax: pointer.Int(80),
+ Protocol: pointer.String("tcp"),
+ RemoteManagedGroups: []ManagedSecurityGroupName{"controlplane"},
+ },
+ },
+ },
+ },
+ },
+ newTemplate: &OpenStackCluster{
+ Spec: OpenStackClusterSpec{
+ CloudName: "foobar",
+ ManagedSecurityGroups: &ManagedSecurityGroups{
+ AllNodesSecurityGroupRules: []SecurityGroupRuleSpec{
+ {
+ Name: "foobar",
+ Description: pointer.String("foobar"),
+ PortRangeMin: pointer.Int(80),
+ PortRangeMax: pointer.Int(80),
+ Protocol: pointer.String("tcp"),
+ RemoteManagedGroups: []ManagedSecurityGroupName{"controlplane", "worker"},
+ },
+ },
+ },
+ },
+ },
+ wantErr: false,
+ },
{
name: "Changing CIDRs on the OpenStackCluster.Spec.APIServerLoadBalancer.AllowedCIDRs is allowed",
oldTemplate: &OpenStackCluster{
@@ -443,6 +482,48 @@ func TestOpenStackCluster_ValidateCreate(t *testing.T) {
},
wantErr: true,
},
+ {
+ name: "OpenStackCluster.Spec.ManagedSecurityGroups.AllNodesSecurityGroupRules with correct spec on create",
+ template: &OpenStackCluster{
+ Spec: OpenStackClusterSpec{
+ CloudName: "foobar",
+ ManagedSecurityGroups: &ManagedSecurityGroups{
+ AllNodesSecurityGroupRules: []SecurityGroupRuleSpec{
+ {
+ Name: "foobar",
+ Description: pointer.String("foobar"),
+ PortRangeMin: pointer.Int(80),
+ PortRangeMax: pointer.Int(80),
+ Protocol: pointer.String("tcp"),
+ },
+ },
+ },
+ },
+ },
+ wantErr: false,
+ },
+ {
+ name: "OpenStackCluster.Spec.ManagedSecurityGroups.AllNodesSecurityGroupRules with mutually exclusive fields on create",
+ template: &OpenStackCluster{
+ Spec: OpenStackClusterSpec{
+ CloudName: "foobar",
+ ManagedSecurityGroups: &ManagedSecurityGroups{
+ AllNodesSecurityGroupRules: []SecurityGroupRuleSpec{
+ {
+ Name: "foobar",
+ Description: pointer.String("foobar"),
+ PortRangeMin: pointer.Int(80),
+ PortRangeMax: pointer.Int(80),
+ Protocol: pointer.String("tcp"),
+ RemoteManagedGroups: []ManagedSecurityGroupName{"controlplane"},
+ RemoteGroupID: pointer.String("foobar"),
+ },
+ },
+ },
+ },
+ },
+ wantErr: true,
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
diff --git a/api/v1alpha8/types.go b/api/v1alpha8/types.go
index 1278f83639..8c206d803d 100644
--- a/api/v1alpha8/types.go
+++ b/api/v1alpha8/types.go
@@ -301,39 +301,136 @@ type LoadBalancer struct {
Tags []string `json:"tags,omitempty"`
}
-// SecurityGroup represents the basic information of the associated
+// SecurityGroupStatus represents the basic information of the associated
// OpenStack Neutron Security Group.
-type SecurityGroup struct {
- Name string `json:"name"`
- ID string `json:"id"`
- Rules []SecurityGroupRule `json:"rules"`
+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"`
+
+ // list of security group rules
+ // +optional
+ Rules []SecurityGroupRuleStatus `json:"rules,omitempty"`
}
-// SecurityGroupRule represent the basic information of the associated OpenStack
+// SecurityGroupRuleSpec represent the basic information of the associated OpenStack
// Security Group Role.
-type SecurityGroupRule struct {
- Description string `json:"description"`
- ID string `json:"name"`
- Direction string `json:"direction"`
- EtherType string `json:"etherType"`
- SecurityGroupID string `json:"securityGroupID"`
- PortRangeMin int `json:"portRangeMin"`
- PortRangeMax int `json:"portRangeMax"`
- Protocol string `json:"protocol"`
- RemoteGroupID string `json:"remoteGroupID"`
- RemoteIPPrefix string `json:"remoteIPPrefix"`
+// 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"`
}
-// Equal checks if two SecurityGroupRules are the same.
-func (r SecurityGroupRule) Equal(x SecurityGroupRule) bool {
- return (r.Direction == x.Direction &&
- r.Description == x.Description &&
- r.EtherType == x.EtherType &&
- r.PortRangeMin == x.PortRangeMin &&
- r.PortRangeMax == x.PortRangeMax &&
- r.Protocol == x.Protocol &&
- r.RemoteGroupID == x.RemoteGroupID &&
- r.RemoteIPPrefix == x.RemoteIPPrefix)
+type SecurityGroupRuleStatus struct {
+ // id of the security group rule
+ // +kubebuilder:validation:Required
+ ID string `json:"id"`
+
+ // 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"`
+}
+
+// +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.
diff --git a/api/v1alpha8/zz_generated.deepcopy.go b/api/v1alpha8/zz_generated.deepcopy.go
index 5be338cb7f..2b52b02cd2 100644
--- a/api/v1alpha8/zz_generated.deepcopy.go
+++ b/api/v1alpha8/zz_generated.deepcopy.go
@@ -246,6 +246,28 @@ 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 *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
@@ -391,6 +413,11 @@ func (in *OpenStackClusterSpec) DeepCopyInto(out *OpenStackClusterSpec) {
}
out.ExternalNetwork = in.ExternalNetwork
in.APIServerLoadBalancer.DeepCopyInto(&out.APIServerLoadBalancer)
+ if in.ManagedSecurityGroups != nil {
+ in, out := &in.ManagedSecurityGroups, &out.ManagedSecurityGroups
+ *out = new(ManagedSecurityGroups)
+ (*in).DeepCopyInto(*out)
+ }
if in.Tags != nil {
in, out := &in.Tags, &out.Tags
*out = make([]string, len(*in))
@@ -456,17 +483,17 @@ func (in *OpenStackClusterStatus) DeepCopyInto(out *OpenStackClusterStatus) {
}
if in.ControlPlaneSecurityGroup != nil {
in, out := &in.ControlPlaneSecurityGroup, &out.ControlPlaneSecurityGroup
- *out = new(SecurityGroup)
+ *out = new(SecurityGroupStatus)
(*in).DeepCopyInto(*out)
}
if in.WorkerSecurityGroup != nil {
in, out := &in.WorkerSecurityGroup, &out.WorkerSecurityGroup
- *out = new(SecurityGroup)
+ *out = new(SecurityGroupStatus)
(*in).DeepCopyInto(*out)
}
if in.BastionSecurityGroup != nil {
in, out := &in.BastionSecurityGroup, &out.BastionSecurityGroup
- *out = new(SecurityGroup)
+ *out = new(SecurityGroupStatus)
(*in).DeepCopyInto(*out)
}
if in.Bastion != nil {
@@ -1007,51 +1034,143 @@ 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 *SecurityGroupFilter) DeepCopyInto(out *SecurityGroupFilter) {
*out = *in
- if in.Rules != nil {
- in, out := &in.Rules, &out.Rules
- *out = make([]SecurityGroupRule, len(*in))
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecurityGroupFilter.
+func (in *SecurityGroupFilter) DeepCopy() *SecurityGroupFilter {
+ if in == nil {
+ return nil
+ }
+ out := new(SecurityGroupFilter)
+ 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 SecurityGroup.
-func (in *SecurityGroup) DeepCopy() *SecurityGroup {
+// 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(SecurityGroup)
+ 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 *SecurityGroupFilter) DeepCopyInto(out *SecurityGroupFilter) {
+func (in *SecurityGroupRuleStatus) DeepCopyInto(out *SecurityGroupRuleStatus) {
*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
+ }
}
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecurityGroupFilter.
-func (in *SecurityGroupFilter) DeepCopy() *SecurityGroupFilter {
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecurityGroupRuleStatus.
+func (in *SecurityGroupRuleStatus) DeepCopy() *SecurityGroupRuleStatus {
if in == nil {
return nil
}
- out := new(SecurityGroupFilter)
+ out := new(SecurityGroupRuleStatus)
in.DeepCopyInto(out)
return out
}
// 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 *SecurityGroupStatus) DeepCopyInto(out *SecurityGroupStatus) {
*out = *in
+ if in.Rules != nil {
+ in, out := &in.Rules, &out.Rules
+ *out = make([]SecurityGroupRuleStatus, len(*in))
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
+ }
}
-// 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 SecurityGroupStatus.
+func (in *SecurityGroupStatus) DeepCopy() *SecurityGroupStatus {
if in == nil {
return nil
}
- out := new(SecurityGroupRule)
+ out := new(SecurityGroupStatus)
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 35f142e9ff..a9d2d44d11 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -5456,9 +5456,87 @@ spec:
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
+ 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
+ type: object
managedSubnets:
description: |-
ManagedSubnets describe OpenStack Subnets to be created. Cluster actuator will create a network,
@@ -5640,56 +5718,70 @@ spec:
type: object
bastionSecurityGroup:
description: |-
- SecurityGroup represents the basic information of the associated
+ SecurityGroupStatus represents the basic information of the associated
OpenStack Neutron Security Group.
properties:
id:
+ description: id of the security group
type: string
name:
+ description: name of the security group
type: string
rules:
+ description: list of security group rules
items:
- description: |-
- SecurityGroupRule represent the basic information of the associated OpenStack
- Security Group Role.
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:
+ id:
+ description: id of the security group rule
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:
- type: string
- securityGroupID:
+ 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
required:
- - description
- direction
- - etherType
- - name
- - portRangeMax
- - portRangeMin
- - protocol
- - remoteGroupID
- - remoteIPPrefix
- - securityGroupID
+ - id
type: object
type: array
required:
- id
- name
- - rules
type: object
controlPlaneSecurityGroup:
description: |-
@@ -5698,52 +5790,66 @@ spec:
TODO: Maybe instead of two properties, we add a property to the group?
properties:
id:
+ description: id of the security group
type: string
name:
+ description: name of the security group
type: string
rules:
+ description: list of security group rules
items:
- description: |-
- SecurityGroupRule represent the basic information of the associated OpenStack
- Security Group Role.
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:
+ id:
+ description: id of the security group rule
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:
- type: string
- securityGroupID:
+ 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
required:
- - description
- direction
- - etherType
- - name
- - portRangeMax
- - portRangeMin
- - protocol
- - remoteGroupID
- - remoteIPPrefix
- - securityGroupID
+ - id
type: object
type: array
required:
- id
- name
- - rules
type: object
externalNetwork:
description: externalNetwork contains information about the external
@@ -5891,52 +5997,66 @@ spec:
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
rules:
+ description: list of security group rules
items:
- description: |-
- SecurityGroupRule represent the basic information of the associated OpenStack
- Security Group Role.
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:
+ id:
+ description: id of the security group rule
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:
- type: string
- securityGroupID:
+ 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
required:
- - description
- direction
- - etherType
- - name
- - portRangeMax
- - portRangeMin
- - protocol
- - remoteGroupID
- - remoteIPPrefix
- - securityGroupID
+ - id
type: object
type: array
required:
- id
- name
- - rules
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 b0dcf7fac1..10a79fa903 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -2891,9 +2891,87 @@ spec:
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
+ 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
+ type: object
managedSubnets:
description: |-
ManagedSubnets describe OpenStack Subnets to be created. Cluster actuator will create a network,
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index 6cd037383c..5246ba218d 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -462,7 +462,7 @@ func bastionToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, clusterNa
}
instanceSpec.SecurityGroups = openStackCluster.Spec.Bastion.Instance.SecurityGroups
- if openStackCluster.Spec.ManagedSecurityGroups {
+ if openStackCluster.Spec.ManagedSecurityGroups != nil {
if openStackCluster.Status.BastionSecurityGroup != nil {
instanceSpec.SecurityGroups = append(instanceSpec.SecurityGroups, infrav1.SecurityGroupFilter{
ID: openStackCluster.Status.BastionSecurityGroup.ID,
diff --git a/controllers/openstackmachine_controller.go b/controllers/openstackmachine_controller.go
index 5d6095177c..71972fdeff 100644
--- a/controllers/openstackmachine_controller.go
+++ b/controllers/openstackmachine_controller.go
@@ -533,7 +533,7 @@ func machineToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, machine *
instanceSpec.Tags = machineTags
instanceSpec.SecurityGroups = openStackMachine.Spec.SecurityGroups
- if openStackCluster.Spec.ManagedSecurityGroups {
+ if openStackCluster.Spec.ManagedSecurityGroups != nil {
var managedSecurityGroup string
if util.IsControlPlaneMachine(machine) {
if openStackCluster.Status.ControlPlaneSecurityGroup != nil {
diff --git a/controllers/openstackmachine_controller_test.go b/controllers/openstackmachine_controller_test.go
index b204111708..32db7b92bb 100644
--- a/controllers/openstackmachine_controller_test.go
+++ b/controllers/openstackmachine_controller_test.go
@@ -56,8 +56,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},
},
}
}
@@ -141,7 +141,7 @@ func Test_machineToInstanceSpec(t *testing.T) {
name: "Control plane security group",
openStackCluster: func() *infrav1.OpenStackCluster {
c := getDefaultOpenStackCluster()
- c.Spec.ManagedSecurityGroups = true
+ c.Spec.ManagedSecurityGroups = &infrav1.ManagedSecurityGroups{}
return c
},
machine: func() *clusterv1.Machine {
@@ -162,7 +162,7 @@ func Test_machineToInstanceSpec(t *testing.T) {
name: "Worker security group",
openStackCluster: func() *infrav1.OpenStackCluster {
c := getDefaultOpenStackCluster()
- c.Spec.ManagedSecurityGroups = true
+ c.Spec.ManagedSecurityGroups = &infrav1.ManagedSecurityGroups{}
return c
},
machine: getDefaultMachine,
@@ -177,7 +177,7 @@ func Test_machineToInstanceSpec(t *testing.T) {
name: "Control plane security group not applied to worker",
openStackCluster: func() *infrav1.OpenStackCluster {
c := getDefaultOpenStackCluster()
- c.Spec.ManagedSecurityGroups = true
+ c.Spec.ManagedSecurityGroups = &infrav1.ManagedSecurityGroups{}
c.Status.WorkerSecurityGroup = nil
return c
},
@@ -193,7 +193,7 @@ func Test_machineToInstanceSpec(t *testing.T) {
name: "Worker security group not applied to control plane",
openStackCluster: func() *infrav1.OpenStackCluster {
c := getDefaultOpenStackCluster()
- c.Spec.ManagedSecurityGroups = true
+ c.Spec.ManagedSecurityGroups = &infrav1.ManagedSecurityGroups{}
c.Status.ControlPlaneSecurityGroup = nil
return c
},
@@ -215,7 +215,7 @@ func Test_machineToInstanceSpec(t *testing.T) {
name: "Extra security group",
openStackCluster: func() *infrav1.OpenStackCluster {
c := getDefaultOpenStackCluster()
- c.Spec.ManagedSecurityGroups = true
+ c.Spec.ManagedSecurityGroups = &infrav1.ManagedSecurityGroups{}
return c
},
machine: getDefaultMachine,
diff --git a/docs/book/src/clusteropenstack/configuration.md b/docs/book/src/clusteropenstack/configuration.md
index 46c7b00363..18f1269f66 100644
--- a/docs/book/src/clusteropenstack/configuration.md
+++ b/docs/book/src/clusteropenstack/configuration.md
@@ -16,6 +16,7 @@
- [Availability zone](#availability-zone)
- [DNS server](#dns-server)
- [Machine flavor](#machine-flavor)
+ - [CNI security group rules](#cni-security-group-rules)
- [Optional Configuration](#optional-configuration)
- [Log level](#log-level)
- [External network](#external-network)
@@ -180,6 +181,41 @@ The flavors for control plane and worker node machines must be exposed as enviro
The recommmend minimum value of control plane flavor's vCPU is 2 and minimum value of worker node flavor's vCPU is 1.
+## CNI security group rules
+
+Depending on the CNI that will be deployed on the cluster, you may need to add specific security group rules to the control plane and worker nodes. For example, if you are using Calico with BGP, you will need to add the following security group rules to the control plane and worker nodes:
+
+ ```yaml
+ apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+ kind: OpenStackCluster
+ metadata:
+ name:
+ namespace:
+ spec:
+ ...
+ allowAllInClusterTraffic: false
+ managedSecurityGroups:
+ allNodesSecurityGroupRules:
+ - remoteManagedGroups:
+ - controlplane
+ - worker
+ direction: ingress
+ etherType: IPv4
+ name: BGP (Calico)
+ portRangeMin: 179
+ portRangeMax: 179
+ protocol: tcp
+ description: "Allow BGP between control plane and workers"
+ - remoteManagedGroups:
+ - controlplane
+ - worker
+ direction: ingress
+ etherType: IPv4
+ name: IP-in-IP (Calico)
+ protocol: 4
+ description: "Allow IP-in-IP between control plane and workers"
+ ```
+
# Optional Configuration
## Log level
@@ -503,28 +539,53 @@ spec:
Security groups are used to determine which ports of the cluster nodes are accessible from where.
-If `spec.managedSecurityGroups` of `OpenStackCluster` is set to `true`, two security groups named
+If `spec.managedSecurityGroups` of `OpenStackCluster` is set to a non-nil value (e.g. `{}`), two security groups named
`k8s-cluster-${NAMESPACE}-${CLUSTER_NAME}-secgroup-controlplane` and
`k8s-cluster-${NAMESPACE}-${CLUSTER_NAME}-secgroup-worker` will be created and added to the control
plane and worker nodes respectively.
-By default, these groups have rules that allow the following traffic:
+Example of `spec.managedSecurityGroups` in `OpenStackCluster` spec when we want to enable the managed security groups:
+
+```yaml
+managedSecurityGroups: {}
+```
- Control plane nodes
- API server traffic from anywhere
- Etcd traffic from other control plane nodes
- Kubelet traffic from other cluster nodes
- - Calico CNI traffic from other cluster nodes
- Worker nodes
- Node port traffic from anywhere
- Kubelet traffic from other cluster nodes
- - Calico CNI traffic from other cluster nodes
-To use a CNI other than Calico, the flag `OpenStackCluster.spec.allowAllInClusterTraffic` can be
-set to `true`. With this flag set, the rules for the managed security groups permit all traffic
+When the flag `OpenStackCluster.spec.allowAllInClusterTraffic` is
+set to `true`, the rules for the managed security groups permit all traffic
between cluster nodes on all ports and protocols (API server and node port traffic is still
permitted from anywhere, as with the default rules).
+We can add security group rules that authorize traffic from all nodes via `allNodesSecurityGroupRules`.
+It takes a list of security groups rules that should be applied to selected nodes.
+The following rule fields are mutually exclusive: `remoteManagedGroups`, `remoteGroupID` and `remoteIPPrefix`.
+
+Valid values for `remoteManagedGroups` are `controlplane`, `worker` and `bastion`.
+
+To apply a security group rule that will allow BGP between the control plane and workers, you can follow this example:
+
+```yaml
+managedSecurityGroups:
+ allNodesSecurityGroupRules:
+ - remoteManagedGroups:
+ - controlplane
+ - worker
+ direction: ingress
+ etherType: IPv4
+ name: BGP (Calico)
+ portRangeMin: 179
+ portRangeMax: 179
+ protocol: tcp
+ description: "Allow BGP between control plane and workers"
+ ```
+
If this is not flexible enough, pre-existing security groups can be added to the
spec of an `OpenStackMachineTemplate`, e.g.:
@@ -654,7 +715,7 @@ spec:
floatingIP:
```
-If `managedSecurityGroups: true`, security group rule opening 22/tcp is added to security groups for bastion, controller, and worker nodes respectively. Otherwise, you have to add `securityGroups` to the `bastion` in `OpenStackCluster` spec and `OpenStackMachineTemplate` spec template respectively.
+If `managedSecurityGroups` is set to a non-nil value (e.g. `{}`), security group rule opening 22/tcp is added to security groups for bastion, controller, and worker nodes respectively. Otherwise, you have to add `securityGroups` to the `bastion` in `OpenStackCluster` spec and `OpenStackMachineTemplate` spec template respectively.
### Making changes to the bastion host
diff --git a/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md b/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md
index 37df012a8c..be1b3b63c8 100644
--- a/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md
+++ b/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md
@@ -13,6 +13,9 @@
- [Removal of imageUUID](#removal-of-imageuuid)
- [Change to floatingIP](#change-to-floatingip)
- [Change to subnet](#change-to-subnet)
+ - [Change to nodeCidr and dnsNameservers](#change-to-nodecidr-and-dnsnameservers)
+ - [Change to managedSecurityGroups](#change-to-managedsecuritygroups)
+ - [Calico CNI](#calico-cni)
@@ -195,4 +198,48 @@ In v1alpha8, this will be automatically converted to:
dnsNameservers: "10.0.0.123"
```
-Please note that currently `managedSubnets` can only hold one element.
\ No newline at end of file
+Please note that currently `managedSubnets` can only hold one element.
+
+#### ⚠️ Change to managedSecurityGroups
+
+The field `managedSecurityGroups` is now a pointer to a `ManagedSecurityGroups` object rather than a boolean.
+
+Also, we can now add security group rules that authorize traffic from all nodes via `allNodesSecurityGroupRules`.
+It takes a list of security groups rules that should be applied to selected nodes.
+The following rule fields are mutually exclusive: `remoteManagedGroups`, `remoteGroupID` and `remoteIPPrefix`.
+Valid values for `remoteManagedGroups` are `controlplane`, `worker` and `bastion`.
+
+```yaml
+managedSecurityGroups: true
+```
+
+becomes
+
+```yaml
+managedSecurityGroups: {}
+```
+
+To apply a security group rule that will allow BGP between the control plane and workers, you can follow this example:
+
+```yaml
+managedSecurityGroups:
+ allNodesSecurityGroupRules:
+ - remoteManagedGroups:
+ - controlplane
+ - worker
+ direction: ingress
+ etherType: IPv4
+ name: BGP (Calico)
+ portRangeMin: 179
+ portRangeMax: 179
+ protocol: tcp
+ description: "Allow BGP between control plane and workers"
+```
+
+#### ⚠️ Calico CNI
+
+Historically we used to create the necessary security group rules for Calico CNI to work. This is no longer the case.
+Now the user needs to request creation of the security group rules by using the `managedSecurityGroups.allNodesSecurityGroupRules` feature.
+
+Note that when upgrading from a previous version, the Calico CNI security group rules will be added automatically to
+allow backwards compatibility if `allowAllInClusterTraffic` is set to false.
diff --git a/kustomize/v1alpha8/default/cluster-template.yaml b/kustomize/v1alpha8/default/cluster-template.yaml
index 5482f50448..c7554d7d7c 100644
--- a/kustomize/v1alpha8/default/cluster-template.yaml
+++ b/kustomize/v1alpha8/default/cluster-template.yaml
@@ -28,11 +28,30 @@ spec:
kind: Secret
apiServerLoadBalancer:
enabled: true
- managedSecurityGroups: true
managedSubnets:
- cidr: 10.6.0.0/24
dnsNameservers:
- ${OPENSTACK_DNS_NAMESERVERS}
+ managedSecurityGroups:
+ allNodesSecurityGroupRules:
+ - description: Created by cluster-api-provider-openstack - BGP (calico)
+ direction: ingress
+ etherType: IPv4
+ name: BGP (Calico)
+ portRangeMax: 179
+ portRangeMin: 179
+ protocol: tcp
+ remoteManagedGroups:
+ - controlplane
+ - worker
+ - description: Created by cluster-api-provider-openstack - IP-in-IP (calico)
+ direction: ingress
+ etherType: IPv4
+ name: IP-in-IP (calico)
+ protocol: "4"
+ remoteManagedGroups:
+ - controlplane
+ - worker
externalNetwork:
id: ${OPENSTACK_EXTERNAL_NETWORK_ID}
---
diff --git a/pkg/cloud/services/compute/instance_test.go b/pkg/cloud/services/compute/instance_test.go
index d868e47940..d89849f507 100644
--- a/pkg/cloud/services/compute/instance_test.go
+++ b/pkg/cloud/services/compute/instance_test.go
@@ -252,8 +252,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},
},
}
}
diff --git a/pkg/cloud/services/networking/securitygroups.go b/pkg/cloud/services/networking/securitygroups.go
index e2a5617de6..03c63327d3 100644
--- a/pkg/cloud/services/networking/securitygroups.go
+++ b/pkg/cloud/services/networking/securitygroups.go
@@ -32,13 +32,14 @@ const (
controlPlaneSuffix string = "controlplane"
workerSuffix string = "worker"
bastionSuffix string = "bastion"
+ allNodesSuffix string = "allNodes"
remoteGroupIDSelf string = "self"
)
// ReconcileSecurityGroups reconcile the security groups.
func (s *Service) ReconcileSecurityGroups(openStackCluster *infrav1.OpenStackCluster, clusterName string) error {
s.scope.Logger().Info("Reconciling security groups")
- if !openStackCluster.Spec.ManagedSecurityGroups {
+ if openStackCluster.Spec.ManagedSecurityGroups == nil {
s.scope.Logger().V(4).Info("No need to reconcile security groups")
return nil
}
@@ -67,7 +68,7 @@ func (s *Service) ReconcileSecurityGroups(openStackCluster *infrav1.OpenStackClu
return err
}
- observedSecGroups := make(map[string]*infrav1.SecurityGroup)
+ observedSecGroups := make(map[string]*infrav1.SecurityGroupStatus)
for k, desiredSecGroup := range desiredSecGroups {
var err error
observedSecGroups[k], err = s.getSecurityGroupByName(desiredSecGroup.Name)
@@ -93,12 +94,50 @@ func (s *Service) ReconcileSecurityGroups(openStackCluster *infrav1.OpenStackClu
return nil
}
-func (s *Service) generateDesiredSecGroups(openStackCluster *infrav1.OpenStackCluster, secGroupNames map[string]string) (map[string]infrav1.SecurityGroup, error) {
- desiredSecGroups := make(map[string]infrav1.SecurityGroup)
+type securityGroupSpec struct {
+ Name string
+ Rules []resolvedSecurityGroupRuleSpec
+}
+
+type resolvedSecurityGroupRuleSpec struct {
+ Description string `json:"description,omitempty"`
+ Direction string `json:"direction,omitempty"`
+ EtherType string `json:"etherType,omitempty"`
+ PortRangeMin int `json:"portRangeMin,omitempty"`
+ PortRangeMax int `json:"portRangeMax,omitempty"`
+ Protocol string `json:"protocol,omitempty"`
+ RemoteGroupID string `json:"remoteGroupID,omitempty"`
+ RemoteIPPrefix string `json:"remoteIPPrefix,omitempty"`
+}
+
+func (r resolvedSecurityGroupRuleSpec) Matches(other infrav1.SecurityGroupRuleStatus) bool {
+ return r.Description == *other.Description &&
+ r.Direction == other.Direction &&
+ r.EtherType == *other.EtherType &&
+ r.PortRangeMin == *other.PortRangeMin &&
+ r.PortRangeMax == *other.PortRangeMax &&
+ r.Protocol == *other.Protocol &&
+ r.RemoteGroupID == *other.RemoteGroupID &&
+ r.RemoteIPPrefix == *other.RemoteIPPrefix
+}
+
+func (s *Service) generateDesiredSecGroups(openStackCluster *infrav1.OpenStackCluster, secGroupNames map[string]string) (map[string]securityGroupSpec, error) {
+ if openStackCluster.Spec.ManagedSecurityGroups == nil {
+ return nil, nil
+ }
+
+ desiredSecGroups := make(map[string]securityGroupSpec)
var secControlPlaneGroupID string
var secWorkerGroupID string
var secBastionGroupID string
+
+ // remoteManagedGroups is a map of suffix to security group ID.
+ // It will be used to fill in the RemoteGroupID field of the security group rules
+ // that reference a managed security group.
+ // For now, we only reference the control plane and worker security groups.
+ remoteManagedGroups := make(map[string]string)
+
for i, v := range secGroupNames {
secGroup, err := s.getSecurityGroupByName(v)
if err != nil {
@@ -107,42 +146,54 @@ func (s *Service) generateDesiredSecGroups(openStackCluster *infrav1.OpenStackCl
switch i {
case controlPlaneSuffix:
secControlPlaneGroupID = secGroup.ID
+ remoteManagedGroups[controlPlaneSuffix] = secControlPlaneGroupID
case workerSuffix:
secWorkerGroupID = secGroup.ID
+ remoteManagedGroups[workerSuffix] = secWorkerGroupID
case bastionSuffix:
secBastionGroupID = secGroup.ID
+ remoteManagedGroups[bastionSuffix] = secBastionGroupID
}
}
// Start with the default rules
- controlPlaneRules := append([]infrav1.SecurityGroupRule{}, defaultRules...)
- workerRules := append([]infrav1.SecurityGroupRule{}, defaultRules...)
+ controlPlaneRules := append([]resolvedSecurityGroupRuleSpec{}, defaultRules...)
+ workerRules := append([]resolvedSecurityGroupRuleSpec{}, defaultRules...)
- controlPlaneRules = append(controlPlaneRules, GetSGControlPlaneHTTPS()...)
- workerRules = append(workerRules, GetSGWorkerNodePort()...)
+ controlPlaneRules = append(controlPlaneRules, getSGControlPlaneHTTPS()...)
+ workerRules = append(workerRules, getSGWorkerNodePort()...)
// If we set additional ports to LB, we need create secgroup rules those ports, this apply to controlPlaneRules only
if openStackCluster.Spec.APIServerLoadBalancer.Enabled {
- controlPlaneRules = append(controlPlaneRules, GetSGControlPlaneAdditionalPorts(openStackCluster.Spec.APIServerLoadBalancer.AdditionalPorts)...)
+ controlPlaneRules = append(controlPlaneRules, getSGControlPlaneAdditionalPorts(openStackCluster.Spec.APIServerLoadBalancer.AdditionalPorts)...)
}
if openStackCluster.Spec.AllowAllInClusterTraffic {
// Permit all ingress from the cluster security groups
- controlPlaneRules = append(controlPlaneRules, GetSGControlPlaneAllowAll(remoteGroupIDSelf, secWorkerGroupID)...)
- workerRules = append(workerRules, GetSGWorkerAllowAll(remoteGroupIDSelf, secControlPlaneGroupID)...)
+ controlPlaneRules = append(controlPlaneRules, getSGControlPlaneAllowAll(remoteGroupIDSelf, secWorkerGroupID)...)
+ workerRules = append(workerRules, getSGWorkerAllowAll(remoteGroupIDSelf, secControlPlaneGroupID)...)
} else {
- controlPlaneRules = append(controlPlaneRules, GetSGControlPlaneGeneral(remoteGroupIDSelf, secWorkerGroupID)...)
- workerRules = append(workerRules, GetSGWorkerGeneral(remoteGroupIDSelf, secControlPlaneGroupID)...)
+ controlPlaneRules = append(controlPlaneRules, getSGControlPlaneGeneral(remoteGroupIDSelf, secWorkerGroupID)...)
+ workerRules = append(workerRules, getSGWorkerGeneral(remoteGroupIDSelf, secControlPlaneGroupID)...)
}
+ // For now, we do not create a separate security group for allNodes.
+ // Instead, we append the rules for allNodes to the control plane and worker security groups.
+ allNodesRules, err := getAllNodesRules(remoteManagedGroups, openStackCluster.Spec.ManagedSecurityGroups.AllNodesSecurityGroupRules)
+ if err != nil {
+ return desiredSecGroups, err
+ }
+ controlPlaneRules = append(controlPlaneRules, allNodesRules...)
+ workerRules = append(workerRules, allNodesRules...)
+
if openStackCluster.Spec.Bastion != nil && openStackCluster.Spec.Bastion.Enabled {
- controlPlaneRules = append(controlPlaneRules, GetSGControlPlaneSSH(secBastionGroupID)...)
- workerRules = append(workerRules, GetSGWorkerSSH(secBastionGroupID)...)
+ controlPlaneRules = append(controlPlaneRules, getSGControlPlaneSSH(secBastionGroupID)...)
+ workerRules = append(workerRules, getSGWorkerSSH(secBastionGroupID)...)
- desiredSecGroups[bastionSuffix] = infrav1.SecurityGroup{
+ desiredSecGroups[bastionSuffix] = securityGroupSpec{
Name: secGroupNames[bastionSuffix],
Rules: append(
- []infrav1.SecurityGroupRule{
+ []resolvedSecurityGroupRuleSpec{
{
Description: "SSH",
Direction: "ingress",
@@ -157,19 +208,81 @@ func (s *Service) generateDesiredSecGroups(openStackCluster *infrav1.OpenStackCl
}
}
- desiredSecGroups[controlPlaneSuffix] = infrav1.SecurityGroup{
+ desiredSecGroups[controlPlaneSuffix] = securityGroupSpec{
Name: secGroupNames[controlPlaneSuffix],
Rules: controlPlaneRules,
}
- desiredSecGroups[workerSuffix] = infrav1.SecurityGroup{
+ desiredSecGroups[workerSuffix] = securityGroupSpec{
Name: secGroupNames[workerSuffix],
Rules: workerRules,
}
-
return desiredSecGroups, nil
}
+// getAllNodesRules returns the rules for the allNodes security group that should be created.
+func getAllNodesRules(remoteManagedGroups map[string]string, allNodesSecurityGroupRules []infrav1.SecurityGroupRuleSpec) ([]resolvedSecurityGroupRuleSpec, error) {
+ rules := make([]resolvedSecurityGroupRuleSpec, 0, len(allNodesSecurityGroupRules))
+ for _, rule := range allNodesSecurityGroupRules {
+ if err := validateRemoteManagedGroups(remoteManagedGroups, rule.RemoteManagedGroups); err != nil {
+ return nil, err
+ }
+ r := resolvedSecurityGroupRuleSpec{
+ Direction: rule.Direction,
+ }
+ if rule.Description != nil {
+ r.Description = *rule.Description
+ }
+ if rule.EtherType != nil {
+ r.EtherType = *rule.EtherType
+ }
+ if rule.PortRangeMin != nil {
+ r.PortRangeMin = *rule.PortRangeMin
+ }
+ if rule.PortRangeMax != nil {
+ r.PortRangeMax = *rule.PortRangeMax
+ }
+ if rule.Protocol != nil {
+ r.Protocol = *rule.Protocol
+ }
+ if rule.RemoteGroupID != nil {
+ r.RemoteGroupID = *rule.RemoteGroupID
+ }
+ if rule.RemoteIPPrefix != nil {
+ r.RemoteIPPrefix = *rule.RemoteIPPrefix
+ }
+
+ if len(rule.RemoteManagedGroups) > 0 {
+ if rule.RemoteGroupID != nil {
+ return nil, fmt.Errorf("remoteGroupID must not be set when remoteManagedGroups is set")
+ }
+
+ for _, rg := range rule.RemoteManagedGroups {
+ rc := r
+ rc.RemoteGroupID = remoteManagedGroups[rg.String()]
+ rules = append(rules, rc)
+ }
+ } else {
+ rules = append(rules, r)
+ }
+ }
+ return rules, nil
+}
+
+// validateRemoteManagedGroups validates that the remoteManagedGroups target existing managed security groups.
+func validateRemoteManagedGroups(remoteManagedGroups map[string]string, ruleRemoteManagedGroups []infrav1.ManagedSecurityGroupName) error {
+ if len(ruleRemoteManagedGroups) == 0 {
+ return fmt.Errorf("remoteManagedGroups is required")
+ }
+
+ for _, group := range ruleRemoteManagedGroups {
+ if _, ok := remoteManagedGroups[group.String()]; !ok {
+ return fmt.Errorf("remoteManagedGroups: %s is not a valid remote managed security group", group)
+ }
+ }
+ return nil
+}
+
func (s *Service) GetSecurityGroups(securityGroupParams []infrav1.SecurityGroupFilter) ([]string, error) {
var sgIDs []string
for _, sg := range securityGroupParams {
@@ -245,8 +358,8 @@ func (s *Service) deleteSecurityGroup(openStackCluster *infrav1.OpenStackCluster
// reconcileGroupRules reconciles an already existing observed group by deleting rules not needed anymore and
// creating rules that are missing.
-func (s *Service) reconcileGroupRules(desired, observed infrav1.SecurityGroup) (infrav1.SecurityGroup, error) {
- rulesToDelete := []infrav1.SecurityGroupRule{}
+func (s *Service) reconcileGroupRules(desired securityGroupSpec, observed infrav1.SecurityGroupStatus) (infrav1.SecurityGroupStatus, error) {
+ var rulesToDelete []string
// fills rulesToDelete by calculating observed - desired
for _, observedRule := range observed.Rules {
deleteRule := true
@@ -255,20 +368,20 @@ func (s *Service) reconcileGroupRules(desired, observed infrav1.SecurityGroup) (
if r.RemoteGroupID == remoteGroupIDSelf {
r.RemoteGroupID = observed.ID
}
- if r.Equal(observedRule) {
+ if r.Matches(observedRule) {
deleteRule = false
break
}
}
if deleteRule {
- rulesToDelete = append(rulesToDelete, observedRule)
+ rulesToDelete = append(rulesToDelete, observedRule.ID)
}
}
- rulesToCreate := []infrav1.SecurityGroupRule{}
- reconciledRules := make([]infrav1.SecurityGroupRule, 0, len(desired.Rules))
+ rulesToCreate := []resolvedSecurityGroupRuleSpec{}
+ reconciledRules := make([]infrav1.SecurityGroupRuleStatus, 0, len(desired.Rules))
// fills rulesToCreate by calculating desired - observed
- // also adds rules which are in observed and desired to reconciledRules.
+ // also adds rules which are in observed and desired to reconcileGroupRules.
for _, desiredRule := range desired.Rules {
r := desiredRule
if r.RemoteGroupID == remoteGroupIDSelf {
@@ -276,7 +389,7 @@ func (s *Service) reconcileGroupRules(desired, observed infrav1.SecurityGroup) (
}
createRule := true
for _, observedRule := range observed.Rules {
- if r.Equal(observedRule) {
+ if r.Matches(observedRule) {
// add already existing rules to reconciledRules because we won't touch them anymore
reconciledRules = append(reconciledRules, observedRule)
createRule = false
@@ -290,28 +403,31 @@ func (s *Service) reconcileGroupRules(desired, observed infrav1.SecurityGroup) (
s.scope.Logger().V(4).Info("Deleting rules not needed anymore for group", "name", observed.Name, "amount", len(rulesToDelete))
for _, rule := range rulesToDelete {
- s.scope.Logger().V(6).Info("Deleting rule", "ID", rule.ID, "name", observed.Name)
- err := s.client.DeleteSecGroupRule(rule.ID)
+ s.scope.Logger().V(6).Info("Deleting rule", "ID", rule, "name", observed.Name)
+ err := s.client.DeleteSecGroupRule(rule)
if err != nil {
- return infrav1.SecurityGroup{}, err
+ return infrav1.SecurityGroupStatus{}, err
}
}
s.scope.Logger().V(4).Info("Creating new rules needed for group", "name", observed.Name, "amount", len(rulesToCreate))
for _, rule := range rulesToCreate {
r := rule
- r.SecurityGroupID = observed.ID
if r.RemoteGroupID == remoteGroupIDSelf {
r.RemoteGroupID = observed.ID
}
- newRule, err := s.createRule(r)
+ newRule, err := s.createRule(observed.ID, r)
if err != nil {
- return infrav1.SecurityGroup{}, err
+ return infrav1.SecurityGroupStatus{}, err
}
reconciledRules = append(reconciledRules, newRule)
}
observed.Rules = reconciledRules
+ if len(reconciledRules) == 0 {
+ return infrav1.SecurityGroupStatus{}, nil
+ }
+
return observed, nil
}
@@ -354,7 +470,7 @@ func (s *Service) createSecurityGroupIfNotExists(openStackCluster *infrav1.OpenS
return nil
}
-func (s *Service) getSecurityGroupByName(name string) (*infrav1.SecurityGroup, error) {
+func (s *Service) getSecurityGroupByName(name string) (*infrav1.SecurityGroupStatus, error) {
opts := groups.ListOpts{
Name: name,
}
@@ -362,20 +478,20 @@ func (s *Service) getSecurityGroupByName(name string) (*infrav1.SecurityGroup, e
s.scope.Logger().V(6).Info("Attempting to fetch security group with", "name", name)
allGroups, err := s.client.ListSecGroup(opts)
if err != nil {
- return &infrav1.SecurityGroup{}, err
+ return &infrav1.SecurityGroupStatus{}, err
}
switch len(allGroups) {
case 0:
- return &infrav1.SecurityGroup{}, nil
+ return &infrav1.SecurityGroupStatus{}, nil
case 1:
return convertOSSecGroupToConfigSecGroup(allGroups[0]), nil
}
- return &infrav1.SecurityGroup{}, fmt.Errorf("more than one security group found named: %s", name)
+ return &infrav1.SecurityGroupStatus{}, fmt.Errorf("more than one security group found named: %s", name)
}
-func (s *Service) createRule(r infrav1.SecurityGroupRule) (infrav1.SecurityGroupRule, error) {
+func (s *Service) createRule(securityGroupID string, r resolvedSecurityGroupRuleSpec) (infrav1.SecurityGroupRuleStatus, error) {
dir := rules.RuleDirection(r.Direction)
proto := rules.RuleProtocol(r.Protocol)
etherType := rules.RuleEtherType(r.EtherType)
@@ -389,12 +505,12 @@ func (s *Service) createRule(r infrav1.SecurityGroupRule) (infrav1.SecurityGroup
EtherType: etherType,
RemoteGroupID: r.RemoteGroupID,
RemoteIPPrefix: r.RemoteIPPrefix,
- SecGroupID: r.SecurityGroupID,
+ SecGroupID: securityGroupID,
}
- s.scope.Logger().V(6).Info("Creating rule", "description", r.Description, "direction", dir, "portRangeMin", r.PortRangeMin, "portRangeMax", r.PortRangeMax, "proto", proto, "etherType", etherType, "remoteGroupID", r.RemoteGroupID, "remoteIPPrefix", r.RemoteIPPrefix, "securityGroupID", r.SecurityGroupID)
+ s.scope.Logger().V(6).Info("Creating rule", "description", r.Description, "direction", dir, "portRangeMin", r.PortRangeMin, "portRangeMax", r.PortRangeMax, "proto", proto, "etherType", etherType, "remoteGroupID", r.RemoteGroupID, "remoteIPPrefix", r.RemoteIPPrefix, "securityGroupID", securityGroupID)
rule, err := s.client.CreateSecGroupRule(createOpts)
if err != nil {
- return infrav1.SecurityGroupRule{}, err
+ return infrav1.SecurityGroupRuleStatus{}, err
}
return convertOSSecGroupRuleToConfigSecGroupRule(*rule), nil
}
@@ -411,30 +527,29 @@ func getSecBastionGroupName(clusterName string) string {
return fmt.Sprintf("%s-cluster-%s-secgroup-%s", secGroupPrefix, clusterName, bastionSuffix)
}
-func convertOSSecGroupToConfigSecGroup(osSecGroup groups.SecGroup) *infrav1.SecurityGroup {
- securityGroupRules := make([]infrav1.SecurityGroupRule, len(osSecGroup.Rules))
+func convertOSSecGroupToConfigSecGroup(osSecGroup groups.SecGroup) *infrav1.SecurityGroupStatus {
+ securityGroupRules := make([]infrav1.SecurityGroupRuleStatus, len(osSecGroup.Rules))
for i, rule := range osSecGroup.Rules {
securityGroupRules[i] = convertOSSecGroupRuleToConfigSecGroupRule(rule)
}
- return &infrav1.SecurityGroup{
+ return &infrav1.SecurityGroupStatus{
ID: osSecGroup.ID,
Name: osSecGroup.Name,
Rules: securityGroupRules,
}
}
-func convertOSSecGroupRuleToConfigSecGroupRule(osSecGroupRule rules.SecGroupRule) infrav1.SecurityGroupRule {
- return infrav1.SecurityGroupRule{
- ID: osSecGroupRule.ID,
- Direction: osSecGroupRule.Direction,
- Description: osSecGroupRule.Description,
- EtherType: osSecGroupRule.EtherType,
- SecurityGroupID: osSecGroupRule.SecGroupID,
- PortRangeMin: osSecGroupRule.PortRangeMin,
- PortRangeMax: osSecGroupRule.PortRangeMax,
- Protocol: osSecGroupRule.Protocol,
- RemoteGroupID: osSecGroupRule.RemoteGroupID,
- RemoteIPPrefix: osSecGroupRule.RemoteIPPrefix,
+func convertOSSecGroupRuleToConfigSecGroupRule(osSecGroupRule rules.SecGroupRule) infrav1.SecurityGroupRuleStatus {
+ return infrav1.SecurityGroupRuleStatus{
+ ID: osSecGroupRule.ID,
+ Direction: osSecGroupRule.Direction,
+ Description: &osSecGroupRule.Description,
+ EtherType: &osSecGroupRule.EtherType,
+ PortRangeMin: &osSecGroupRule.PortRangeMin,
+ PortRangeMax: &osSecGroupRule.PortRangeMax,
+ Protocol: &osSecGroupRule.Protocol,
+ RemoteGroupID: &osSecGroupRule.RemoteGroupID,
+ RemoteIPPrefix: &osSecGroupRule.RemoteIPPrefix,
}
}
diff --git a/pkg/cloud/services/networking/securitygroups_rules.go b/pkg/cloud/services/networking/securitygroups_rules.go
index 5889867127..91effed16e 100644
--- a/pkg/cloud/services/networking/securitygroups_rules.go
+++ b/pkg/cloud/services/networking/securitygroups_rules.go
@@ -16,11 +16,7 @@ limitations under the License.
package networking
-import (
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
-)
-
-var defaultRules = []infrav1.SecurityGroupRule{
+var defaultRules = []resolvedSecurityGroupRuleSpec{
{
Direction: "egress",
Description: "Full open",
@@ -42,8 +38,8 @@ var defaultRules = []infrav1.SecurityGroupRule{
}
// Permit traffic for etcd, kubelet.
-func getSGControlPlaneCommon(remoteGroupIDSelf, secWorkerGroupID string) []infrav1.SecurityGroupRule {
- return []infrav1.SecurityGroupRule{
+func getSGControlPlaneCommon(remoteGroupIDSelf, secWorkerGroupID string) []resolvedSecurityGroupRuleSpec {
+ return []resolvedSecurityGroupRuleSpec{
{
Description: "Etcd",
Direction: "ingress",
@@ -76,47 +72,9 @@ func getSGControlPlaneCommon(remoteGroupIDSelf, secWorkerGroupID string) []infra
}
}
-// Permit traffic for calico.
-func getSGControlPlaneCalico(remoteGroupIDSelf, secWorkerGroupID string) []infrav1.SecurityGroupRule {
- return []infrav1.SecurityGroupRule{
- {
- Description: "BGP (calico)",
- Direction: "ingress",
- EtherType: "IPv4",
- PortRangeMin: 179,
- PortRangeMax: 179,
- Protocol: "tcp",
- RemoteGroupID: remoteGroupIDSelf,
- },
- {
- Description: "BGP (calico)",
- Direction: "ingress",
- EtherType: "IPv4",
- PortRangeMin: 179,
- PortRangeMax: 179,
- Protocol: "tcp",
- RemoteGroupID: secWorkerGroupID,
- },
- {
- Description: "IP-in-IP (calico)",
- Direction: "ingress",
- EtherType: "IPv4",
- Protocol: "4",
- RemoteGroupID: remoteGroupIDSelf,
- },
- {
- Description: "IP-in-IP (calico)",
- Direction: "ingress",
- EtherType: "IPv4",
- Protocol: "4",
- RemoteGroupID: secWorkerGroupID,
- },
- }
-}
-
// Permit traffic for kubelet.
-func getSGWorkerCommon(remoteGroupIDSelf, secControlPlaneGroupID string) []infrav1.SecurityGroupRule {
- return []infrav1.SecurityGroupRule{
+func getSGWorkerCommon(remoteGroupIDSelf, secControlPlaneGroupID string) []resolvedSecurityGroupRuleSpec {
+ return []resolvedSecurityGroupRuleSpec{
{
// This is needed to support metrics-server deployments
Description: "Kubelet API",
@@ -139,47 +97,9 @@ func getSGWorkerCommon(remoteGroupIDSelf, secControlPlaneGroupID string) []infra
}
}
-// Permit traffic for calico.
-func getSGWorkerCalico(remoteGroupIDSelf, secControlPlaneGroupID string) []infrav1.SecurityGroupRule {
- return []infrav1.SecurityGroupRule{
- {
- Description: "BGP (calico)",
- Direction: "ingress",
- EtherType: "IPv4",
- PortRangeMin: 179,
- PortRangeMax: 179,
- Protocol: "tcp",
- RemoteGroupID: remoteGroupIDSelf,
- },
- {
- Description: "BGP (calico)",
- Direction: "ingress",
- EtherType: "IPv4",
- PortRangeMin: 179,
- PortRangeMax: 179,
- Protocol: "tcp",
- RemoteGroupID: secControlPlaneGroupID,
- },
- {
- Description: "IP-in-IP (calico)",
- Direction: "ingress",
- EtherType: "IPv4",
- Protocol: "4",
- RemoteGroupID: remoteGroupIDSelf,
- },
- {
- Description: "IP-in-IP (calico)",
- Direction: "ingress",
- EtherType: "IPv4",
- Protocol: "4",
- RemoteGroupID: secControlPlaneGroupID,
- },
- }
-}
-
// Permit traffic for ssh control plane.
-func GetSGControlPlaneSSH(secBastionGroupID string) []infrav1.SecurityGroupRule {
- return []infrav1.SecurityGroupRule{
+func getSGControlPlaneSSH(secBastionGroupID string) []resolvedSecurityGroupRuleSpec {
+ return []resolvedSecurityGroupRuleSpec{
{
Description: "SSH",
Direction: "ingress",
@@ -193,8 +113,8 @@ func GetSGControlPlaneSSH(secBastionGroupID string) []infrav1.SecurityGroupRule
}
// Permit traffic for ssh worker.
-func GetSGWorkerSSH(secBastionGroupID string) []infrav1.SecurityGroupRule {
- return []infrav1.SecurityGroupRule{
+func getSGWorkerSSH(secBastionGroupID string) []resolvedSecurityGroupRuleSpec {
+ return []resolvedSecurityGroupRuleSpec{
{
Description: "SSH",
Direction: "ingress",
@@ -208,8 +128,8 @@ func GetSGWorkerSSH(secBastionGroupID string) []infrav1.SecurityGroupRule {
}
// Allow all traffic, including from outside the cluster, to access the API.
-func GetSGControlPlaneHTTPS() []infrav1.SecurityGroupRule {
- return []infrav1.SecurityGroupRule{
+func getSGControlPlaneHTTPS() []resolvedSecurityGroupRuleSpec {
+ return []resolvedSecurityGroupRuleSpec{
{
Description: "Kubernetes API",
Direction: "ingress",
@@ -222,8 +142,8 @@ func GetSGControlPlaneHTTPS() []infrav1.SecurityGroupRule {
}
// Allow all traffic, including from outside the cluster, to access node port services.
-func GetSGWorkerNodePort() []infrav1.SecurityGroupRule {
- return []infrav1.SecurityGroupRule{
+func getSGWorkerNodePort() []resolvedSecurityGroupRuleSpec {
+ return []resolvedSecurityGroupRuleSpec{
{
Description: "Node Port Services",
Direction: "ingress",
@@ -244,8 +164,8 @@ func GetSGWorkerNodePort() []infrav1.SecurityGroupRule {
}
// Permit all ingress from the cluster security groups.
-func GetSGControlPlaneAllowAll(remoteGroupIDSelf, secWorkerGroupID string) []infrav1.SecurityGroupRule {
- return []infrav1.SecurityGroupRule{
+func getSGControlPlaneAllowAll(remoteGroupIDSelf, secWorkerGroupID string) []resolvedSecurityGroupRuleSpec {
+ return []resolvedSecurityGroupRuleSpec{
{
Description: "In-cluster Ingress",
Direction: "ingress",
@@ -268,8 +188,8 @@ func GetSGControlPlaneAllowAll(remoteGroupIDSelf, secWorkerGroupID string) []inf
}
// Permit all ingress from the cluster security groups.
-func GetSGWorkerAllowAll(remoteGroupIDSelf, secControlPlaneGroupID string) []infrav1.SecurityGroupRule {
- return []infrav1.SecurityGroupRule{
+func getSGWorkerAllowAll(remoteGroupIDSelf, secControlPlaneGroupID string) []resolvedSecurityGroupRuleSpec {
+ return []resolvedSecurityGroupRuleSpec{
{
Description: "In-cluster Ingress",
Direction: "ingress",
@@ -292,10 +212,10 @@ func GetSGWorkerAllowAll(remoteGroupIDSelf, secControlPlaneGroupID string) []inf
}
// Permit ports that defined in openStackCluster.Spec.APIServerLoadBalancer.AdditionalPorts.
-func GetSGControlPlaneAdditionalPorts(ports []int) []infrav1.SecurityGroupRule {
- controlPlaneRules := []infrav1.SecurityGroupRule{}
+func getSGControlPlaneAdditionalPorts(ports []int) []resolvedSecurityGroupRuleSpec {
+ controlPlaneRules := []resolvedSecurityGroupRuleSpec{}
- r := []infrav1.SecurityGroupRule{
+ r := []resolvedSecurityGroupRuleSpec{
{
Description: "Additional ports",
Direction: "ingress",
@@ -319,16 +239,14 @@ func GetSGControlPlaneAdditionalPorts(ports []int) []infrav1.SecurityGroupRule {
return controlPlaneRules
}
-func GetSGControlPlaneGeneral(remoteGroupIDSelf, secWorkerGroupID string) []infrav1.SecurityGroupRule {
- controlPlaneRules := []infrav1.SecurityGroupRule{}
+func getSGControlPlaneGeneral(remoteGroupIDSelf, secWorkerGroupID string) []resolvedSecurityGroupRuleSpec {
+ controlPlaneRules := []resolvedSecurityGroupRuleSpec{}
controlPlaneRules = append(controlPlaneRules, getSGControlPlaneCommon(remoteGroupIDSelf, secWorkerGroupID)...)
- controlPlaneRules = append(controlPlaneRules, getSGControlPlaneCalico(remoteGroupIDSelf, secWorkerGroupID)...)
return controlPlaneRules
}
-func GetSGWorkerGeneral(remoteGroupIDSelf, secControlPlaneGroupID string) []infrav1.SecurityGroupRule {
- workerRules := []infrav1.SecurityGroupRule{}
+func getSGWorkerGeneral(remoteGroupIDSelf, secControlPlaneGroupID string) []resolvedSecurityGroupRuleSpec {
+ workerRules := []resolvedSecurityGroupRuleSpec{}
workerRules = append(workerRules, getSGWorkerCommon(remoteGroupIDSelf, secControlPlaneGroupID)...)
- workerRules = append(workerRules, getSGWorkerCalico(remoteGroupIDSelf, secControlPlaneGroupID)...)
return workerRules
}
diff --git a/pkg/cloud/services/networking/securitygroups_test.go b/pkg/cloud/services/networking/securitygroups_test.go
new file mode 100644
index 0000000000..407f964559
--- /dev/null
+++ b/pkg/cloud/services/networking/securitygroups_test.go
@@ -0,0 +1,531 @@
+/*
+Copyright 2024 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 networking
+
+import (
+ "reflect"
+ "testing"
+
+ "github.com/go-logr/logr"
+ "github.com/golang/mock/gomock"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules"
+ . "github.com/onsi/gomega"
+ "k8s.io/utils/pointer"
+
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ "sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/mock"
+ "sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
+)
+
+func TestValidateRemoteManagedGroups(t *testing.T) {
+ tests := []struct {
+ name string
+ rule infrav1.SecurityGroupRuleSpec
+ remoteManagedGroups map[string]string
+ wantErr bool
+ }{
+ {
+ name: "Invalid rule with unknown remoteManagedGroup",
+ rule: infrav1.SecurityGroupRuleSpec{
+ RemoteManagedGroups: []infrav1.ManagedSecurityGroupName{"unknownGroup"},
+ },
+ wantErr: true,
+ },
+ {
+ name: "Valid rule with missing remoteManagedGroups",
+ rule: infrav1.SecurityGroupRuleSpec{
+ PortRangeMin: pointer.Int(22),
+ PortRangeMax: pointer.Int(22),
+ Protocol: pointer.String("tcp"),
+ },
+ remoteManagedGroups: map[string]string{
+ "self": "self",
+ "controlplane": "1",
+ "worker": "2",
+ "bastion": "3",
+ },
+ wantErr: true,
+ },
+ {
+ name: "Valid rule with remoteManagedGroups",
+ rule: infrav1.SecurityGroupRuleSpec{
+ RemoteManagedGroups: []infrav1.ManagedSecurityGroupName{"controlplane", "worker", "bastion"},
+ },
+ remoteManagedGroups: map[string]string{
+ "self": "self",
+ "controlplane": "1",
+ "worker": "2",
+ "bastion": "3",
+ },
+ wantErr: false,
+ },
+ {
+ name: "Invalid rule with bastion in remoteManagedGroups",
+ rule: infrav1.SecurityGroupRuleSpec{
+ RemoteManagedGroups: []infrav1.ManagedSecurityGroupName{"controlplane", "worker", "bastion"},
+ },
+ remoteManagedGroups: map[string]string{
+ "self": "self",
+ "controlplane": "1",
+ "worker": "2",
+ },
+ wantErr: true,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ err := validateRemoteManagedGroups(tt.remoteManagedGroups, tt.rule.RemoteManagedGroups)
+ if (err != nil) != tt.wantErr {
+ t.Errorf("validateAllNodesRule() error = %v, wantErr %v", err, tt.wantErr)
+ }
+ })
+ }
+}
+
+func TestGetAllNodesRules(t *testing.T) {
+ tests := []struct {
+ name string
+ remoteManagedGroups map[string]string
+ allNodesSecurityGroupRules []infrav1.SecurityGroupRuleSpec
+ wantRules []resolvedSecurityGroupRuleSpec
+ wantErr bool
+ }{
+ {
+ name: "Empty remoteManagedGroups and allNodesSecurityGroupRules",
+ remoteManagedGroups: map[string]string{},
+ allNodesSecurityGroupRules: []infrav1.SecurityGroupRuleSpec{},
+ wantRules: []resolvedSecurityGroupRuleSpec{},
+ wantErr: false,
+ },
+ {
+ name: "Valid remoteManagedGroups and allNodesSecurityGroupRules",
+ remoteManagedGroups: map[string]string{
+ "controlplane": "1",
+ "worker": "2",
+ },
+ allNodesSecurityGroupRules: []infrav1.SecurityGroupRuleSpec{
+ {
+ Protocol: pointer.String("tcp"),
+ PortRangeMin: pointer.Int(22),
+ PortRangeMax: pointer.Int(22),
+ RemoteManagedGroups: []infrav1.ManagedSecurityGroupName{
+ "controlplane",
+ "worker",
+ },
+ },
+ },
+ wantRules: []resolvedSecurityGroupRuleSpec{
+ {
+ Protocol: "tcp",
+ PortRangeMin: 22,
+ PortRangeMax: 22,
+ RemoteGroupID: "1",
+ },
+ {
+ Protocol: "tcp",
+ PortRangeMin: 22,
+ PortRangeMax: 22,
+ RemoteGroupID: "2",
+ },
+ },
+ wantErr: false,
+ },
+ {
+ name: "Valid remoteManagedGroups in a rule",
+ remoteManagedGroups: map[string]string{
+ "controlplane": "1",
+ "worker": "2",
+ },
+ allNodesSecurityGroupRules: []infrav1.SecurityGroupRuleSpec{
+ {
+ Protocol: pointer.String("tcp"),
+ PortRangeMin: pointer.Int(22),
+ PortRangeMax: pointer.Int(22),
+ RemoteManagedGroups: []infrav1.ManagedSecurityGroupName{"controlplane"},
+ },
+ },
+ wantRules: []resolvedSecurityGroupRuleSpec{
+ {
+ Protocol: "tcp",
+ PortRangeMin: 22,
+ PortRangeMax: 22,
+ RemoteGroupID: "1",
+ },
+ },
+ },
+ {
+ name: "Invalid allNodesSecurityGroupRules with wrong remoteManagedGroups",
+ remoteManagedGroups: map[string]string{
+ "controlplane": "1",
+ "worker": "2",
+ },
+ allNodesSecurityGroupRules: []infrav1.SecurityGroupRuleSpec{
+ {
+ Protocol: pointer.String("tcp"),
+ PortRangeMin: pointer.Int(22),
+ PortRangeMax: pointer.Int(22),
+ RemoteManagedGroups: []infrav1.ManagedSecurityGroupName{
+ "controlplanezzz",
+ "worker",
+ },
+ },
+ },
+ wantRules: nil,
+ wantErr: true,
+ },
+ {
+ name: "Invalid allNodesSecurityGroupRules with bastion while remoteManagedGroups does not have bastion",
+ remoteManagedGroups: map[string]string{
+ "controlplane": "1",
+ "worker": "2",
+ },
+ allNodesSecurityGroupRules: []infrav1.SecurityGroupRuleSpec{
+ {
+ Protocol: pointer.String("tcp"),
+ PortRangeMin: pointer.Int(22),
+ PortRangeMax: pointer.Int(22),
+ RemoteManagedGroups: []infrav1.ManagedSecurityGroupName{
+ "bastion",
+ },
+ },
+ },
+ wantRules: nil,
+ wantErr: true,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ gotRules, err := getAllNodesRules(tt.remoteManagedGroups, tt.allNodesSecurityGroupRules)
+ if (err != nil) != tt.wantErr {
+ t.Errorf("getAllNodesRules() error = %v, wantErr %v", err, tt.wantErr)
+ return
+ }
+ if !reflect.DeepEqual(gotRules, tt.wantRules) {
+ t.Errorf("getAllNodesRules() gotRules = %v, want %v", gotRules, tt.wantRules)
+ }
+ })
+ }
+}
+
+func TestGenerateDesiredSecGroups(t *testing.T) {
+ mockCtrl := gomock.NewController(t)
+ defer mockCtrl.Finish()
+
+ secGroupNames := map[string]string{
+ "controlplane": "k8s-cluster-mycluster-secgroup-controlplane",
+ "worker": "k8s-cluster-mycluster-secgroup-worker",
+ }
+
+ tests := []struct {
+ name string
+ openStackCluster *infrav1.OpenStackCluster
+ mockExpect func(m *mock.MockNetworkClientMockRecorder)
+ // We could also test the exact rules that are returned, but that'll be a lot data to write out.
+ // For now we just make sure that the number of rules is correct.
+ expectedNumberSecurityGroupRules int
+ wantErr bool
+ }{
+ {
+ name: "Valid openStackCluster with unmanaged securityGroups",
+ openStackCluster: &infrav1.OpenStackCluster{},
+ mockExpect: func(m *mock.MockNetworkClientMockRecorder) {},
+ expectedNumberSecurityGroupRules: 0,
+ wantErr: false,
+ },
+ {
+ name: "Valid openStackCluster with securityGroups",
+ openStackCluster: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ ManagedSecurityGroups: &infrav1.ManagedSecurityGroups{},
+ },
+ },
+ mockExpect: func(m *mock.MockNetworkClientMockRecorder) {
+ m.ListSecGroup(groups.ListOpts{Name: "k8s-cluster-mycluster-secgroup-controlplane"}).Return([]groups.SecGroup{
+ {
+ ID: "0",
+ Name: "k8s-cluster-mycluster-secgroup-controlplane",
+ },
+ }, nil)
+ m.ListSecGroup(groups.ListOpts{Name: "k8s-cluster-mycluster-secgroup-worker"}).Return([]groups.SecGroup{
+ {
+ ID: "1",
+ Name: "k8s-cluster-mycluster-secgroup-worker",
+ },
+ }, nil)
+ },
+ expectedNumberSecurityGroupRules: 12,
+ wantErr: false,
+ },
+ {
+ name: "Valid openStackCluster with securityGroups and allNodesSecurityGroupRules",
+ openStackCluster: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ ManagedSecurityGroups: &infrav1.ManagedSecurityGroups{
+ AllNodesSecurityGroupRules: []infrav1.SecurityGroupRuleSpec{
+ {
+ Protocol: pointer.String("tcp"),
+ PortRangeMin: pointer.Int(22),
+ PortRangeMax: pointer.Int(22),
+ RemoteManagedGroups: []infrav1.ManagedSecurityGroupName{"controlplane", "worker"},
+ },
+ },
+ },
+ },
+ },
+ mockExpect: func(m *mock.MockNetworkClientMockRecorder) {
+ m.ListSecGroup(groups.ListOpts{Name: "k8s-cluster-mycluster-secgroup-controlplane"}).Return([]groups.SecGroup{
+ {
+ ID: "0",
+ Name: "k8s-cluster-mycluster-secgroup-controlplane",
+ },
+ }, nil)
+ m.ListSecGroup(groups.ListOpts{Name: "k8s-cluster-mycluster-secgroup-worker"}).Return([]groups.SecGroup{
+ {
+ ID: "1",
+ Name: "k8s-cluster-mycluster-secgroup-worker",
+ },
+ }, nil)
+ },
+ expectedNumberSecurityGroupRules: 16,
+ wantErr: false,
+ },
+ {
+ name: "Valid openStackCluster with securityGroups with invalid allNodesSecurityGroupRules",
+ openStackCluster: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ ManagedSecurityGroups: &infrav1.ManagedSecurityGroups{
+ AllNodesSecurityGroupRules: []infrav1.SecurityGroupRuleSpec{
+ {
+ Protocol: pointer.String("tcp"),
+ PortRangeMin: pointer.Int(22),
+ PortRangeMax: pointer.Int(22),
+ RemoteManagedGroups: []infrav1.ManagedSecurityGroupName{"controlplane", "worker", "unknownGroup"},
+ },
+ },
+ },
+ },
+ },
+ mockExpect: func(m *mock.MockNetworkClientMockRecorder) {
+ m.ListSecGroup(groups.ListOpts{Name: "k8s-cluster-mycluster-secgroup-controlplane"}).Return([]groups.SecGroup{
+ {
+ ID: "0",
+ Name: "k8s-cluster-mycluster-secgroup-controlplane",
+ },
+ }, nil)
+ m.ListSecGroup(groups.ListOpts{Name: "k8s-cluster-mycluster-secgroup-worker"}).Return([]groups.SecGroup{
+ {
+ ID: "1",
+ Name: "k8s-cluster-mycluster-secgroup-worker",
+ },
+ }, nil)
+ },
+ wantErr: true,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ g := NewWithT(t)
+ mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "", logr.Discard())
+
+ s, err := NewService(mockScopeFactory)
+ if err != nil {
+ t.Fatalf("Failed to create service: %v", err)
+ }
+ tt.mockExpect(mockScopeFactory.NetworkClient.EXPECT())
+
+ gotSecurityGroups, err := s.generateDesiredSecGroups(tt.openStackCluster, secGroupNames)
+ if tt.wantErr {
+ g.Expect(err).To(HaveOccurred())
+ } else {
+ g.Expect(err).NotTo(HaveOccurred())
+ }
+ var gotNumberSecurityGroupRules int
+ for _, secGroup := range gotSecurityGroups {
+ gotNumberSecurityGroupRules += len(secGroup.Rules)
+ }
+ g.Expect(gotNumberSecurityGroupRules).To(Equal(tt.expectedNumberSecurityGroupRules))
+ })
+ }
+}
+
+func TestReconcileGroupRules(t *testing.T) {
+ mockCtrl := gomock.NewController(t)
+ defer mockCtrl.Finish()
+
+ tests := []struct {
+ name string
+ desiredSGSpecs securityGroupSpec
+ observedSGStatus infrav1.SecurityGroupStatus
+ mockExpect func(m *mock.MockNetworkClientMockRecorder)
+ wantSGStatus infrav1.SecurityGroupStatus
+ }{
+ {
+ name: "Empty desiredSGSpecs and observedSGStatus",
+ desiredSGSpecs: securityGroupSpec{},
+ observedSGStatus: infrav1.SecurityGroupStatus{},
+ mockExpect: func(m *mock.MockNetworkClientMockRecorder) {},
+ wantSGStatus: infrav1.SecurityGroupStatus{},
+ },
+ {
+ name: "Same desiredSGSpecs and observedSGStatus produces no changes",
+ desiredSGSpecs: securityGroupSpec{
+ Name: "k8s-cluster-mycluster-secgroup-controlplane",
+ Rules: []resolvedSecurityGroupRuleSpec{
+ {
+ Description: "Allow SSH",
+ Direction: "ingress",
+ EtherType: "IPv4",
+ Protocol: "tcp",
+ PortRangeMin: 22,
+ PortRangeMax: 22,
+ RemoteGroupID: "1",
+ RemoteIPPrefix: "",
+ },
+ },
+ },
+ observedSGStatus: infrav1.SecurityGroupStatus{
+ ID: "idSG",
+ Name: "k8s-cluster-mycluster-secgroup-controlplane",
+ Rules: []infrav1.SecurityGroupRuleStatus{
+ {
+ Description: pointer.String("Allow SSH"),
+ Direction: "ingress",
+ EtherType: pointer.String("IPv4"),
+ ID: "idSGRule",
+ Protocol: pointer.String("tcp"),
+ PortRangeMin: pointer.Int(22),
+ PortRangeMax: pointer.Int(22),
+ RemoteGroupID: pointer.String("1"),
+ RemoteIPPrefix: pointer.String(""),
+ },
+ },
+ },
+ mockExpect: func(m *mock.MockNetworkClientMockRecorder) {},
+ wantSGStatus: infrav1.SecurityGroupStatus{
+ ID: "idSG",
+ Name: "k8s-cluster-mycluster-secgroup-controlplane",
+ Rules: []infrav1.SecurityGroupRuleStatus{
+ {
+ Description: pointer.String("Allow SSH"),
+ Direction: "ingress",
+ EtherType: pointer.String("IPv4"),
+ ID: "idSGRule",
+ Protocol: pointer.String("tcp"),
+ PortRangeMin: pointer.Int(22),
+ PortRangeMax: pointer.Int(22),
+ RemoteGroupID: pointer.String("1"),
+ RemoteIPPrefix: pointer.String(""),
+ },
+ },
+ },
+ },
+ {
+ name: "Different desiredSGSpecs and observedSGStatus produces changes",
+ desiredSGSpecs: securityGroupSpec{
+ Name: "k8s-cluster-mycluster-secgroup-controlplane",
+ Rules: []resolvedSecurityGroupRuleSpec{
+ {
+ Description: "Allow SSH",
+ Direction: "ingress",
+ EtherType: "IPv4",
+ Protocol: "tcp",
+ PortRangeMin: 22,
+ PortRangeMax: 22,
+ RemoteGroupID: "1",
+ RemoteIPPrefix: "",
+ },
+ },
+ },
+ observedSGStatus: infrav1.SecurityGroupStatus{
+ ID: "idSG",
+ Name: "k8s-cluster-mycluster-secgroup-controlplane",
+ Rules: []infrav1.SecurityGroupRuleStatus{
+ {
+ Description: pointer.String("Allow SSH legacy"),
+ Direction: "ingress",
+ EtherType: pointer.String("IPv4"),
+ ID: "idSGRuleLegacy",
+ Protocol: pointer.String("tcp"),
+ PortRangeMin: pointer.Int(222),
+ PortRangeMax: pointer.Int(222),
+ RemoteGroupID: pointer.String("2"),
+ RemoteIPPrefix: pointer.String(""),
+ },
+ },
+ },
+ mockExpect: func(m *mock.MockNetworkClientMockRecorder) {
+ m.DeleteSecGroupRule("idSGRuleLegacy").Return(nil)
+ m.CreateSecGroupRule(rules.CreateOpts{
+ SecGroupID: "idSG",
+ Description: "Allow SSH",
+ Direction: "ingress",
+ EtherType: "IPv4",
+ Protocol: "tcp",
+ PortRangeMin: 22,
+ PortRangeMax: 22,
+ RemoteGroupID: "1",
+ }).Return(&rules.SecGroupRule{
+ ID: "idSGRule",
+ Description: "Allow SSH",
+ Direction: "ingress",
+ EtherType: "IPv4",
+ Protocol: "tcp",
+ PortRangeMin: 22,
+ PortRangeMax: 22,
+ RemoteGroupID: "1",
+ }, nil)
+ },
+ wantSGStatus: infrav1.SecurityGroupStatus{
+ ID: "idSG",
+ Name: "k8s-cluster-mycluster-secgroup-controlplane",
+ Rules: []infrav1.SecurityGroupRuleStatus{
+ {
+ Description: pointer.String("Allow SSH"),
+ Direction: "ingress",
+ EtherType: pointer.String("IPv4"),
+ ID: "idSGRule",
+ Protocol: pointer.String("tcp"),
+ PortRangeMin: pointer.Int(22),
+ PortRangeMax: pointer.Int(22),
+ RemoteGroupID: pointer.String("1"),
+ RemoteIPPrefix: pointer.String(""),
+ },
+ },
+ },
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ g := NewWithT(t)
+ mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "", logr.Discard())
+
+ s, err := NewService(mockScopeFactory)
+ if err != nil {
+ t.Fatalf("Failed to create service: %v", err)
+ }
+ tt.mockExpect(mockScopeFactory.NetworkClient.EXPECT())
+
+ sgStatus, err := s.reconcileGroupRules(tt.desiredSGSpecs, tt.observedSGStatus)
+ g.Expect(err).To(BeNil())
+ g.Expect(sgStatus).To(Equal(tt.wantSGStatus))
+ })
+ }
+}
diff --git a/templates/cluster-template-flatcar-sysext.yaml b/templates/cluster-template-flatcar-sysext.yaml
index 8e2f89ea2a..ca02b3c639 100644
--- a/templates/cluster-template-flatcar-sysext.yaml
+++ b/templates/cluster-template-flatcar-sysext.yaml
@@ -230,7 +230,26 @@ spec:
identityRef:
kind: Secret
name: ${CLUSTER_NAME}-cloud-config
- managedSecurityGroups: true
+ managedSecurityGroups:
+ allNodesSecurityGroupRules:
+ - description: Created by cluster-api-provider-openstack - BGP (calico)
+ direction: ingress
+ etherType: IPv4
+ name: BGP (Calico)
+ portRangeMax: 179
+ portRangeMin: 179
+ protocol: tcp
+ remoteManagedGroups:
+ - controlplane
+ - worker
+ - description: Created by cluster-api-provider-openstack - IP-in-IP (calico)
+ direction: ingress
+ etherType: IPv4
+ name: IP-in-IP (calico)
+ protocol: "4"
+ remoteManagedGroups:
+ - controlplane
+ - worker
managedSubnets:
- cidr: 10.6.0.0/24
dnsNameservers:
diff --git a/templates/cluster-template-flatcar.yaml b/templates/cluster-template-flatcar.yaml
index edccdf99ab..c2cfdc6934 100644
--- a/templates/cluster-template-flatcar.yaml
+++ b/templates/cluster-template-flatcar.yaml
@@ -154,7 +154,26 @@ spec:
identityRef:
kind: Secret
name: ${CLUSTER_NAME}-cloud-config
- managedSecurityGroups: true
+ managedSecurityGroups:
+ allNodesSecurityGroupRules:
+ - description: Created by cluster-api-provider-openstack - BGP (calico)
+ direction: ingress
+ etherType: IPv4
+ name: BGP (Calico)
+ portRangeMax: 179
+ portRangeMin: 179
+ protocol: tcp
+ remoteManagedGroups:
+ - controlplane
+ - worker
+ - description: Created by cluster-api-provider-openstack - IP-in-IP (calico)
+ direction: ingress
+ etherType: IPv4
+ name: IP-in-IP (calico)
+ protocol: "4"
+ remoteManagedGroups:
+ - controlplane
+ - worker
managedSubnets:
- cidr: 10.6.0.0/24
dnsNameservers:
diff --git a/templates/cluster-template-without-lb.yaml b/templates/cluster-template-without-lb.yaml
index 97d39b1d17..2b206b65cd 100644
--- a/templates/cluster-template-without-lb.yaml
+++ b/templates/cluster-template-without-lb.yaml
@@ -111,7 +111,26 @@ spec:
identityRef:
kind: Secret
name: ${CLUSTER_NAME}-cloud-config
- managedSecurityGroups: true
+ managedSecurityGroups:
+ allNodesSecurityGroupRules:
+ - description: Created by cluster-api-provider-openstack - BGP (calico)
+ direction: ingress
+ etherType: IPv4
+ name: BGP (Calico)
+ portRangeMax: 179
+ portRangeMin: 179
+ protocol: tcp
+ remoteManagedGroups:
+ - controlplane
+ - worker
+ - description: Created by cluster-api-provider-openstack - IP-in-IP (calico)
+ direction: ingress
+ etherType: IPv4
+ name: IP-in-IP (calico)
+ protocol: "4"
+ remoteManagedGroups:
+ - controlplane
+ - worker
managedSubnets:
- cidr: 10.6.0.0/24
dnsNameservers:
diff --git a/templates/cluster-template.yaml b/templates/cluster-template.yaml
index 1384b473b0..e2b1ff52db 100644
--- a/templates/cluster-template.yaml
+++ b/templates/cluster-template.yaml
@@ -113,7 +113,26 @@ spec:
identityRef:
kind: Secret
name: ${CLUSTER_NAME}-cloud-config
- managedSecurityGroups: true
+ managedSecurityGroups:
+ allNodesSecurityGroupRules:
+ - description: Created by cluster-api-provider-openstack - BGP (calico)
+ direction: ingress
+ etherType: IPv4
+ name: BGP (Calico)
+ portRangeMax: 179
+ portRangeMin: 179
+ protocol: tcp
+ remoteManagedGroups:
+ - controlplane
+ - worker
+ - description: Created by cluster-api-provider-openstack - IP-in-IP (calico)
+ direction: ingress
+ etherType: IPv4
+ name: IP-in-IP (calico)
+ protocol: "4"
+ remoteManagedGroups:
+ - controlplane
+ - worker
managedSubnets:
- cidr: 10.6.0.0/24
dnsNameservers:
diff --git a/templates/clusterclass-dev-test.yaml b/templates/clusterclass-dev-test.yaml
index 44930abc7d..4112633624 100644
--- a/templates/clusterclass-dev-test.yaml
+++ b/templates/clusterclass-dev-test.yaml
@@ -121,7 +121,26 @@ spec:
identityRef:
kind: Secret
name: dev-test-cloud-config
- managedSecurityGroups: true
+ managedSecurityGroups:
+ allNodesSecurityGroupRules:
+ - description: Created by cluster-api-provider-openstack - BGP (calico)
+ direction: ingress
+ etherType: IPv4
+ name: BGP (Calico)
+ portRangeMin: 179
+ portRangeMax: 179
+ protocol: tcp
+ remoteManagedGroups:
+ - controlplane
+ - worker
+ - description: Created by cluster-api-provider-openstack - IP-in-IP (calico)
+ direction: ingress
+ etherType: IPv4
+ name: IP-in-IP (calico)
+ protocol: "4"
+ remoteManagedGroups:
+ - controlplane
+ - worker
managedSubnets:
- cidr: 10.6.0.0/24
dnsNameservers:
diff --git a/test/e2e/shared/openstack.go b/test/e2e/shared/openstack.go
index 4d46837775..85661092f3 100644
--- a/test/e2e/shared/openstack.go
+++ b/test/e2e/shared/openstack.go
@@ -40,6 +40,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/imageservice/v2/images"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/trunks"
"github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
"github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
@@ -370,6 +371,58 @@ func DumpOpenStackSecurityGroups(e2eCtx *E2EContext, filter groups.ListOpts) ([]
return groupsList, nil
}
+// DumpCalicoSecurityGroupRules returns the number of Calico security group rules.
+func DumpCalicoSecurityGroupRules(e2eCtx *E2EContext, openStackCluster *infrav1.OpenStackCluster) (int, error) {
+ var count int
+
+ providerClient, clientOpts, _, err := GetTenantProviderClient(e2eCtx)
+ if err != nil {
+ return 0, fmt.Errorf("error creating provider client: %s", err)
+ }
+
+ networkClient, err := openstack.NewNetworkV2(providerClient, gophercloud.EndpointOpts{
+ Region: clientOpts.RegionName,
+ })
+ if err != nil {
+ return 0, fmt.Errorf("error creating network client: %s", err)
+ }
+
+ controlPlaneSGID := openStackCluster.Status.ControlPlaneSecurityGroup.ID
+ controlPlaneSGRules, err := rules.List(networkClient, rules.ListOpts{SecGroupID: controlPlaneSGID}).AllPages()
+ if err != nil {
+ return 0, fmt.Errorf("error listing control plane security group rules: %s", err)
+ }
+ controlPlaneRulesList, err := rules.ExtractRules(controlPlaneSGRules)
+ if err != nil {
+ return 0, fmt.Errorf("error extracting control plane security group rules: %s", err)
+ }
+
+ workerSGID := openStackCluster.Status.WorkerSecurityGroup.ID
+ workerSGRules, err := rules.List(networkClient, rules.ListOpts{SecGroupID: workerSGID}).AllPages()
+ if err != nil {
+ return 0, fmt.Errorf("error listing worker security group rules: %s", err)
+ }
+ workerRulesList, err := rules.ExtractRules(workerSGRules)
+ if err != nil {
+ return 0, fmt.Errorf("error extracting worker security group rules: %s", err)
+ }
+ allRules := append(controlPlaneRulesList, workerRulesList...)
+ count += checkCalicoSecurityGroupRules(allRules)
+
+ return count, nil
+}
+
+// checkCalicoSecurityGroupRules returns the number of Calico security group rules.
+func checkCalicoSecurityGroupRules(rules []rules.SecGroupRule) int {
+ var count int
+ for _, rule := range rules {
+ if strings.Contains(rule.Description, "calico") {
+ count++
+ }
+ }
+ return count
+}
+
// DumpOpenStackVolumes returns all OpenStack volumes to a file in the artifact folder.
func DumpOpenStackVolumes(e2eCtx *E2EContext, filter volumes.ListOpts) ([]volumes.Volume, error) {
providerClient, clientOpts, _, err := GetTenantProviderClient(e2eCtx)
diff --git a/test/e2e/suites/e2e/e2e_test.go b/test/e2e/suites/e2e/e2e_test.go
index 2490d848ac..f4b92c9a42 100644
--- a/test/e2e/suites/e2e/e2e_test.go
+++ b/test/e2e/suites/e2e/e2e_test.go
@@ -120,6 +120,9 @@ var _ = Describe("e2e tests [PR-Blocking]", func() {
waitForNodesReadyWithoutCCMTaint(ctx, workloadCluster.GetClient(), 2)
+ openStackCluster, err := shared.ClusterForSpec(ctx, e2eCtx, namespace)
+ Expect(err).NotTo(HaveOccurred())
+
// Tag: clusterName is declared on OpenStackCluster and gets propagated to all machines
// except the bastion host
allServers, err := shared.DumpOpenStackServers(e2eCtx, servers.ListOpts{Tags: clusterName})
@@ -153,6 +156,12 @@ var _ = Describe("e2e tests [PR-Blocking]", func() {
securityGroupsList, err := shared.DumpOpenStackSecurityGroups(e2eCtx, groups.ListOpts{Tags: clusterName})
Expect(err).NotTo(HaveOccurred())
Expect(securityGroupsList).To(HaveLen(3))
+
+ calicoSGRules, err := shared.DumpCalicoSecurityGroupRules(e2eCtx, openStackCluster)
+ Expect(err).NotTo(HaveOccurred())
+ // We expect 4 security group rules that allow Calico traffic on the control plane
+ // from both the control plane and worker machines and vice versa, that makes 8 rules.
+ Expect(calicoSGRules).To(Equal(8))
})
})
From c1e0f508e792a65caa8c7ccd7175ea6d0f465eb3 Mon Sep 17 00:00:00 2001
From: Emilien Macchi
Date: Wed, 21 Feb 2024 09:54:15 -0500
Subject: [PATCH 070/180] Add emilienm to CAPO reviewers
---
OWNERS_ALIASES | 1 +
1 file changed, 1 insertion(+)
diff --git a/OWNERS_ALIASES b/OWNERS_ALIASES
index 146f103863..e4bda950ca 100644
--- a/OWNERS_ALIASES
+++ b/OWNERS_ALIASES
@@ -23,4 +23,5 @@ aliases:
- lentzi90
- mdbooth
cluster-api-openstack-reviewers:
+ - emilienm
- dulek
From a5590170a673ea53a91e435158f667e0fce8f9ee Mon Sep 17 00:00:00 2001
From: Emilien Macchi
Date: Wed, 21 Feb 2024 10:10:27 -0500
Subject: [PATCH 071/180] api/additionalPorts: don't create UDP rules
When providing additional ports to open on the control plane security
group, we'll only open TCP from now as it was initially documented.
Opening UDP by default might not be desired for security reasons.
---
pkg/cloud/services/networking/securitygroups_rules.go | 6 ------
1 file changed, 6 deletions(-)
diff --git a/pkg/cloud/services/networking/securitygroups_rules.go b/pkg/cloud/services/networking/securitygroups_rules.go
index 91effed16e..e7dcdd1d3b 100644
--- a/pkg/cloud/services/networking/securitygroups_rules.go
+++ b/pkg/cloud/services/networking/securitygroups_rules.go
@@ -222,12 +222,6 @@ func getSGControlPlaneAdditionalPorts(ports []int) []resolvedSecurityGroupRuleSp
EtherType: "IPv4",
Protocol: "tcp",
},
- {
- Description: "Additional ports",
- Direction: "ingress",
- EtherType: "IPv4",
- Protocol: "udp",
- },
}
for _, p := range ports {
r[0].PortRangeMin = p
From 350b7e60ca116e8349035a65a263d4cddab651eb Mon Sep 17 00:00:00 2001
From: Emilien Macchi
Date: Mon, 19 Feb 2024 10:29:03 -0500
Subject: [PATCH 072/180] Move spec.allowAllInClusterTraffic to
spec.managedSecurityGroups
---
api/v1alpha5/conversion.go | 3 +++
api/v1alpha5/conversion_test.go | 9 +++++----
api/v1alpha5/zz_generated.conversion.go | 3 +--
api/v1alpha6/conversion.go | 9 +++++++++
api/v1alpha6/conversion_test.go | 5 +++--
api/v1alpha6/zz_generated.conversion.go | 3 +--
api/v1alpha7/conversion.go | 9 +++++++++
api/v1alpha7/conversion_test.go | 5 +++--
api/v1alpha7/zz_generated.conversion.go | 3 +--
api/v1alpha8/openstackcluster_types.go | 12 +++++-------
api/v1alpha8/openstackcluster_webhook.go | 8 ++++----
...cture.cluster.x-k8s.io_openstackclusters.yaml | 14 +++++++-------
...uster.x-k8s.io_openstackclustertemplates.yaml | 15 ++++++++-------
docs/book/src/clusteropenstack/configuration.md | 5 ++---
.../topics/crd-changes/v1alpha7-to-v1alpha8.md | 16 ++++++++++++++++
pkg/cloud/services/networking/securitygroups.go | 2 +-
16 files changed, 78 insertions(+), 43 deletions(-)
diff --git a/api/v1alpha5/conversion.go b/api/v1alpha5/conversion.go
index 4dfc78a140..95177baa3e 100644
--- a/api/v1alpha5/conversion.go
+++ b/api/v1alpha5/conversion.go
@@ -212,6 +212,7 @@ func Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(in *
if in.ManagedSecurityGroups != nil {
out.ManagedSecurityGroups = true
+ out.AllowAllInClusterTraffic = in.ManagedSecurityGroups.AllowAllInClusterTraffic
}
return nil
@@ -252,6 +253,8 @@ func Convert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *
out.ManagedSecurityGroups = &infrav1.ManagedSecurityGroups{}
if !in.AllowAllInClusterTraffic {
out.ManagedSecurityGroups.AllNodesSecurityGroupRules = infrav1.LegacyCalicoSecurityGroupRules()
+ } else {
+ out.ManagedSecurityGroups.AllowAllInClusterTraffic = true
}
}
diff --git a/api/v1alpha5/conversion_test.go b/api/v1alpha5/conversion_test.go
index b51adaff7c..480471b3c6 100644
--- a/api/v1alpha5/conversion_test.go
+++ b/api/v1alpha5/conversion_test.go
@@ -49,7 +49,7 @@ func TestConvertFrom(t *testing.T) {
Spec: OpenStackClusterSpec{},
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
- "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"allowAllInClusterTraffic\":false,\"apiServerLoadBalancer\":{},\"cloudName\":\"\",\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"disableExternalNetwork\":false,\"externalNetwork\":{},\"managedSecurityGroups\":null,\"network\":{}},\"status\":{\"ready\":false}}",
+ "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"apiServerLoadBalancer\":{},\"cloudName\":\"\",\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"disableExternalNetwork\":false,\"externalNetwork\":{},\"managedSecurityGroups\":null,\"network\":{}},\"status\":{\"ready\":false}}",
},
},
},
@@ -64,7 +64,7 @@ func TestConvertFrom(t *testing.T) {
Spec: OpenStackClusterTemplateSpec{},
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,\"disableExternalNetwork\":false,\"externalNetwork\":{},\"managedSecurityGroups\":null,\"network\":{}}}}}",
+ "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"template\":{\"spec\":{\"apiServerLoadBalancer\":{},\"cloudName\":\"\",\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"disableExternalNetwork\":false,\"externalNetwork\":{},\"managedSecurityGroups\":null,\"network\":{}}}}}",
},
},
},
@@ -140,8 +140,9 @@ func TestConvert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(
AllowAllInClusterTraffic: true,
},
expectedOut: &infrav1.OpenStackClusterSpec{
- ManagedSecurityGroups: &infrav1.ManagedSecurityGroups{},
- AllowAllInClusterTraffic: true,
+ ManagedSecurityGroups: &infrav1.ManagedSecurityGroups{
+ AllowAllInClusterTraffic: true,
+ },
},
},
}
diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go
index 0d4ef4e7b5..8ec8034142 100644
--- a/api/v1alpha5/zz_generated.conversion.go
+++ b/api/v1alpha5/zz_generated.conversion.go
@@ -671,7 +671,7 @@ func autoConvert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(
out.APIServerFixedIP = in.APIServerFixedIP
out.APIServerPort = in.APIServerPort
// WARNING: in.ManagedSecurityGroups requires manual conversion: inconvertible types (bool vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8.ManagedSecurityGroups)
- out.AllowAllInClusterTraffic = in.AllowAllInClusterTraffic
+ // WARNING: in.AllowAllInClusterTraffic requires manual conversion: does not exist in peer-type
out.DisablePortSecurity = in.DisablePortSecurity
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
out.ControlPlaneEndpoint = in.ControlPlaneEndpoint
@@ -719,7 +719,6 @@ func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(
out.APIServerFixedIP = in.APIServerFixedIP
out.APIServerPort = in.APIServerPort
// WARNING: in.ManagedSecurityGroups requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8.ManagedSecurityGroups vs bool)
- out.AllowAllInClusterTraffic = in.AllowAllInClusterTraffic
out.DisablePortSecurity = in.DisablePortSecurity
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
out.ControlPlaneEndpoint = in.ControlPlaneEndpoint
diff --git a/api/v1alpha6/conversion.go b/api/v1alpha6/conversion.go
index 417d161237..5068c87b07 100644
--- a/api/v1alpha6/conversion.go
+++ b/api/v1alpha6/conversion.go
@@ -156,6 +156,12 @@ func restorev1alpha6ClusterSpec(previous *OpenStackClusterSpec, dst *OpenStackCl
if prevBastion != nil && dstBastion != nil {
restorev1alpha6MachineSpec(&prevBastion.Instance, &dstBastion.Instance)
}
+
+ // To avoid lossy conversion, we need to restore AllowAllInClusterTraffic
+ // even if ManagedSecurityGroups is set to false
+ if previous.AllowAllInClusterTraffic && !previous.ManagedSecurityGroups {
+ dst.AllowAllInClusterTraffic = true
+ }
}
var _ ctrlconversion.Convertible = &OpenStackCluster{}
@@ -592,6 +598,7 @@ func Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(in *
if in.ManagedSecurityGroups != nil {
out.ManagedSecurityGroups = true
+ out.AllowAllInClusterTraffic = in.ManagedSecurityGroups.AllowAllInClusterTraffic
}
return nil
@@ -632,6 +639,8 @@ func Convert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *
out.ManagedSecurityGroups = &infrav1.ManagedSecurityGroups{}
if !in.AllowAllInClusterTraffic {
out.ManagedSecurityGroups.AllNodesSecurityGroupRules = infrav1.LegacyCalicoSecurityGroupRules()
+ } else {
+ out.ManagedSecurityGroups.AllowAllInClusterTraffic = true
}
}
diff --git a/api/v1alpha6/conversion_test.go b/api/v1alpha6/conversion_test.go
index 2e684b8e35..77f5c4de76 100644
--- a/api/v1alpha6/conversion_test.go
+++ b/api/v1alpha6/conversion_test.go
@@ -685,8 +685,9 @@ func TestConvert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(
AllowAllInClusterTraffic: true,
},
expectedOut: &infrav1.OpenStackClusterSpec{
- ManagedSecurityGroups: &infrav1.ManagedSecurityGroups{},
- AllowAllInClusterTraffic: true,
+ ManagedSecurityGroups: &infrav1.ManagedSecurityGroups{
+ AllowAllInClusterTraffic: true,
+ },
},
},
}
diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go
index 7df2ce7482..2bbcd48d10 100644
--- a/api/v1alpha6/zz_generated.conversion.go
+++ b/api/v1alpha6/zz_generated.conversion.go
@@ -693,7 +693,7 @@ func autoConvert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(
out.APIServerFixedIP = in.APIServerFixedIP
out.APIServerPort = in.APIServerPort
// WARNING: in.ManagedSecurityGroups requires manual conversion: inconvertible types (bool vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8.ManagedSecurityGroups)
- out.AllowAllInClusterTraffic = in.AllowAllInClusterTraffic
+ // WARNING: in.AllowAllInClusterTraffic requires manual conversion: does not exist in peer-type
out.DisablePortSecurity = in.DisablePortSecurity
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
out.ControlPlaneEndpoint = in.ControlPlaneEndpoint
@@ -742,7 +742,6 @@ func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(
out.APIServerFixedIP = in.APIServerFixedIP
out.APIServerPort = in.APIServerPort
// WARNING: in.ManagedSecurityGroups requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8.ManagedSecurityGroups vs bool)
- out.AllowAllInClusterTraffic = in.AllowAllInClusterTraffic
out.DisablePortSecurity = in.DisablePortSecurity
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
out.ControlPlaneEndpoint = in.ControlPlaneEndpoint
diff --git a/api/v1alpha7/conversion.go b/api/v1alpha7/conversion.go
index 1e84d4f0b9..2183d37386 100644
--- a/api/v1alpha7/conversion.go
+++ b/api/v1alpha7/conversion.go
@@ -204,6 +204,12 @@ func restorev1alpha7ClusterSpec(previous *OpenStackClusterSpec, dst *OpenStackCl
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
+ }
}
func restorev1alpha8ClusterSpec(previous *infrav1.OpenStackClusterSpec, dst *infrav1.OpenStackClusterSpec) {
@@ -581,6 +587,8 @@ func Convert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *
out.ManagedSecurityGroups = &infrav1.ManagedSecurityGroups{}
if !in.AllowAllInClusterTraffic {
out.ManagedSecurityGroups.AllNodesSecurityGroupRules = infrav1.LegacyCalicoSecurityGroupRules()
+ } else {
+ out.ManagedSecurityGroups.AllowAllInClusterTraffic = true
}
}
@@ -610,6 +618,7 @@ func Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in *
if in.ManagedSecurityGroups != nil {
out.ManagedSecurityGroups = true
+ out.AllowAllInClusterTraffic = in.ManagedSecurityGroups.AllowAllInClusterTraffic
}
return nil
diff --git a/api/v1alpha7/conversion_test.go b/api/v1alpha7/conversion_test.go
index 90b391f037..f3c2338e70 100644
--- a/api/v1alpha7/conversion_test.go
+++ b/api/v1alpha7/conversion_test.go
@@ -300,8 +300,9 @@ func TestConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(
AllowAllInClusterTraffic: true,
},
expectedOut: &infrav1.OpenStackClusterSpec{
- ManagedSecurityGroups: &infrav1.ManagedSecurityGroups{},
- AllowAllInClusterTraffic: true,
+ ManagedSecurityGroups: &infrav1.ManagedSecurityGroups{
+ AllowAllInClusterTraffic: true,
+ },
},
},
}
diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go
index 5ff683e8fb..c29aaf334f 100644
--- a/api/v1alpha7/zz_generated.conversion.go
+++ b/api/v1alpha7/zz_generated.conversion.go
@@ -885,7 +885,7 @@ func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(
out.APIServerFixedIP = in.APIServerFixedIP
out.APIServerPort = in.APIServerPort
// WARNING: in.ManagedSecurityGroups requires manual conversion: inconvertible types (bool vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8.ManagedSecurityGroups)
- out.AllowAllInClusterTraffic = in.AllowAllInClusterTraffic
+ // WARNING: in.AllowAllInClusterTraffic requires manual conversion: does not exist in peer-type
out.DisablePortSecurity = in.DisablePortSecurity
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
out.ControlPlaneEndpoint = in.ControlPlaneEndpoint
@@ -924,7 +924,6 @@ func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(
out.APIServerFixedIP = in.APIServerFixedIP
out.APIServerPort = in.APIServerPort
// WARNING: in.ManagedSecurityGroups requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8.ManagedSecurityGroups vs bool)
- out.AllowAllInClusterTraffic = in.AllowAllInClusterTraffic
out.DisablePortSecurity = in.DisablePortSecurity
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
out.ControlPlaneEndpoint = in.ControlPlaneEndpoint
diff --git a/api/v1alpha8/openstackcluster_types.go b/api/v1alpha8/openstackcluster_types.go
index cabb2a55ca..a6f9c0b15f 100644
--- a/api/v1alpha8/openstackcluster_types.go
+++ b/api/v1alpha8/openstackcluster_types.go
@@ -129,13 +129,6 @@ type OpenStackClusterSpec struct {
// +optional
ManagedSecurityGroups *ManagedSecurityGroups `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.
- // +optional
- AllowAllInClusterTraffic bool `json:"allowAllInClusterTraffic"`
-
// DisablePortSecurity disables the port security of the network created for the
// Kubernetes cluster, which also disables SecurityGroups
DisablePortSecurity bool `json:"disablePortSecurity,omitempty"`
@@ -280,6 +273,11 @@ type ManagedSecurityGroups struct {
// +listMapKey=name
// +optional
AllNodesSecurityGroupRules []SecurityGroupRuleSpec `json:"allNodesSecurityGroupRules" 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() {
diff --git a/api/v1alpha8/openstackcluster_webhook.go b/api/v1alpha8/openstackcluster_webhook.go
index d2051a09e5..78eb4a21b5 100644
--- a/api/v1alpha8/openstackcluster_webhook.go
+++ b/api/v1alpha8/openstackcluster_webhook.go
@@ -145,6 +145,10 @@ func (r *OpenStackCluster) ValidateUpdate(oldRaw runtime.Object) (admission.Warn
if r.Spec.ManagedSecurityGroups != nil {
old.Spec.ManagedSecurityGroups.AllNodesSecurityGroupRules = []SecurityGroupRuleSpec{}
r.Spec.ManagedSecurityGroups.AllNodesSecurityGroupRules = []SecurityGroupRuleSpec{}
+
+ // Allow change to the allowAllInClusterTraffic.
+ old.Spec.ManagedSecurityGroups.AllowAllInClusterTraffic = false
+ r.Spec.ManagedSecurityGroups.AllowAllInClusterTraffic = false
}
// Allow changes on AllowedCIDRs
@@ -162,10 +166,6 @@ func (r *OpenStackCluster) ValidateUpdate(oldRaw runtime.Object) (admission.Warn
old.Spec.ControlPlaneOmitAvailabilityZone = false
r.Spec.ControlPlaneOmitAvailabilityZone = false
- // 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 = ""
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 a9d2d44d11..7dcb6b87ce 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -4838,13 +4838,6 @@ spec:
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.
- type: boolean
apiServerFixedIP:
description: |-
APIServerFixedIP is the fixed IP which will be associated with the API server.
@@ -5536,6 +5529,13 @@ spec:
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: |-
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 10a79fa903..bead63c584 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -2263,13 +2263,6 @@ 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.
- type: boolean
apiServerFixedIP:
description: |-
APIServerFixedIP is the fixed IP which will be associated with the API server.
@@ -2971,6 +2964,14 @@ spec:
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: |-
diff --git a/docs/book/src/clusteropenstack/configuration.md b/docs/book/src/clusteropenstack/configuration.md
index 18f1269f66..0a87afcee1 100644
--- a/docs/book/src/clusteropenstack/configuration.md
+++ b/docs/book/src/clusteropenstack/configuration.md
@@ -193,7 +193,6 @@ Depending on the CNI that will be deployed on the cluster, you may need to add s
namespace:
spec:
...
- allowAllInClusterTraffic: false
managedSecurityGroups:
allNodesSecurityGroupRules:
- remoteManagedGroups:
@@ -214,6 +213,7 @@ Depending on the CNI that will be deployed on the cluster, you may need to add s
name: IP-in-IP (Calico)
protocol: 4
description: "Allow IP-in-IP between control plane and workers"
+ allowAllInClusterTraffic: false
```
# Optional Configuration
@@ -312,7 +312,6 @@ metadata:
name:
namespace:
spec:
- allowAllInClusterTraffic: true
apiServerLoadBalancer:
allowedCidrs:
- 192.168.10/24
@@ -558,7 +557,7 @@ managedSecurityGroups: {}
- Node port traffic from anywhere
- Kubelet traffic from other cluster nodes
-When the flag `OpenStackCluster.spec.allowAllInClusterTraffic` is
+When the flag `OpenStackCluster.spec.managedSecurityGroups.allowAllInClusterTraffic` is
set to `true`, the rules for the managed security groups permit all traffic
between cluster nodes on all ports and protocols (API server and node port traffic is still
permitted from anywhere, as with the default rules).
diff --git a/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md b/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md
index be1b3b63c8..44124f8b8f 100644
--- a/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md
+++ b/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md
@@ -209,6 +209,8 @@ It takes a list of security groups rules that should be applied to selected node
The following rule fields are mutually exclusive: `remoteManagedGroups`, `remoteGroupID` and `remoteIPPrefix`.
Valid values for `remoteManagedGroups` are `controlplane`, `worker` and `bastion`.
+Also, `OpenStackCluster.Spec.AllowAllInClusterTraffic` moved under `ManagedSecurityGroups`.
+
```yaml
managedSecurityGroups: true
```
@@ -219,6 +221,20 @@ becomes
managedSecurityGroups: {}
```
+and
+
+```yaml
+allowAllInClusterTraffic: true
+managedSecurityGroups: true
+```
+
+becomes
+
+```yaml
+managedSecurityGroups:
+ allowAllInClusterTraffic: true
+```
+
To apply a security group rule that will allow BGP between the control plane and workers, you can follow this example:
```yaml
diff --git a/pkg/cloud/services/networking/securitygroups.go b/pkg/cloud/services/networking/securitygroups.go
index 03c63327d3..6707b2fbe4 100644
--- a/pkg/cloud/services/networking/securitygroups.go
+++ b/pkg/cloud/services/networking/securitygroups.go
@@ -168,7 +168,7 @@ func (s *Service) generateDesiredSecGroups(openStackCluster *infrav1.OpenStackCl
controlPlaneRules = append(controlPlaneRules, getSGControlPlaneAdditionalPorts(openStackCluster.Spec.APIServerLoadBalancer.AdditionalPorts)...)
}
- if openStackCluster.Spec.AllowAllInClusterTraffic {
+ if openStackCluster.Spec.ManagedSecurityGroups != nil && openStackCluster.Spec.ManagedSecurityGroups.AllowAllInClusterTraffic {
// Permit all ingress from the cluster security groups
controlPlaneRules = append(controlPlaneRules, getSGControlPlaneAllowAll(remoteGroupIDSelf, secWorkerGroupID)...)
workerRules = append(workerRules, getSGWorkerAllowAll(remoteGroupIDSelf, secControlPlaneGroupID)...)
From 2e4ca73eb1978ebd7e09735c3131c9a342fd9d84 Mon Sep 17 00:00:00 2001
From: Maysa Macedo
Date: Fri, 19 Jan 2024 17:27:46 -0300
Subject: [PATCH 073/180] Modify `OpenStackCluster.Spec.Network` API
For the BYO scenario, when the `OpenStackCluster.Spec.Network`
is not specified the query to OpenStack would return all the
Networks available in the cloud and fail the reconciliation.
To avoid this, if any Subnets were specified under
`OpenStackCluster.Spec.Subnets` this can be used to identify
which Network to use.
---
controllers/openstackcluster_controller.go | 114 +++++++++++++-----
.../openstackcluster_controller_test.go | 63 ++++++++++
.../crd-changes/v1alpha7-to-v1alpha8.md | 4 +
pkg/cloud/services/networking/network.go | 17 ++-
pkg/cloud/services/networking/network_test.go | 42 -------
5 files changed, 159 insertions(+), 81 deletions(-)
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index 5246ba218d..914e662fa4 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -23,6 +23,8 @@ import (
"reflect"
"time"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
+ "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"
@@ -507,36 +509,41 @@ func reconcileNetworkComponents(scope scope.Scope, cluster *clusterv1.Cluster, o
if len(openStackCluster.Spec.ManagedSubnets) == 0 {
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 openStackCluster.Status.Network == nil {
openStackCluster.Status.Network = &infrav1.NetworkStatusWithSubnets{}
}
- openStackCluster.Status.Network.ID = networkList[0].ID
- openStackCluster.Status.Network.Name = networkList[0].Name
- openStackCluster.Status.Network.Tags = networkList[0].Tags
- subnets, err := filterSubnets(networkingService, openStackCluster)
+ err := getCAPONetwork(openStackCluster, networkingService)
if err != nil {
return err
}
+ filteredSubnets, err := filterSubnets(networkingService, openStackCluster)
+ if err != nil {
+ return err
+ }
+
+ var subnets []infrav1.Subnet
+ for subnet := range filteredSubnets {
+ filterSubnet := &filteredSubnets[subnet]
+ subnets = append(subnets, infrav1.Subnet{
+ ID: filterSubnet.ID,
+ Name: filterSubnet.Name,
+ CIDR: filterSubnet.CIDR,
+ Tags: filterSubnet.Tags,
+ })
+ }
+
if err := utils.ValidateSubnets(subnets); err != nil {
return err
}
openStackCluster.Status.Network.Subnets = subnets
+
+ // If network is not yet populated on the Status, use networkID defined in the filtered subnets to get the Network.
+ err = populateCAPONetworkFromSubnet(networkingService, filteredSubnets, openStackCluster)
+ if err != nil {
+ return err
+ }
} else if len(openStackCluster.Spec.ManagedSubnets) == 1 {
err := networkingService.ReconcileNetwork(openStackCluster, clusterName)
if err != nil {
@@ -687,18 +694,23 @@ func handleUpdateOSCError(openstackCluster *infrav1.OpenStackCluster, message er
}
// filterSubnets retrieves the subnets based on the Subnet filters specified on OpenstackCluster.
-func filterSubnets(networkingService *networking.Service, openStackCluster *infrav1.OpenStackCluster) ([]infrav1.Subnet, error) {
- var subnets []infrav1.Subnet
+func filterSubnets(networkingService *networking.Service, openStackCluster *infrav1.OpenStackCluster) ([]subnets.Subnet, error) {
+ var filteredSubnets []subnets.Subnet
+ var err error
openStackClusterSubnets := openStackCluster.Spec.Subnets
- if openStackCluster.Status.Network == nil {
- return nil, nil
+ networkID := ""
+ if openStackCluster.Status.Network != nil {
+ networkID = openStackCluster.Status.Network.ID
}
- networkID := openStackCluster.Status.Network.ID
+
if len(openStackClusterSubnets) == 0 {
+ if networkID == "" {
+ return nil, nil
+ }
empty := &infrav1.SubnetFilter{}
listOpt := empty.ToListOpt()
listOpt.NetworkID = networkID
- filteredSubnets, err := networkingService.GetSubnetsByFilter(listOpt)
+ filteredSubnets, err = networkingService.GetSubnetsByFilter(listOpt)
if err != nil {
err = fmt.Errorf("failed to find subnets: %w", err)
if errors.Is(err, networking.ErrFilterMatch) {
@@ -709,9 +721,6 @@ func filterSubnets(networkingService *networking.Service, openStackCluster *infr
if len(filteredSubnets) > 2 {
return nil, fmt.Errorf("more than two subnets found in the Network. Specify the subnets in the OpenStackCluster.Spec instead")
}
- for subnet := range filteredSubnets {
- subnets = networkingService.ConvertOpenStackSubnetToCAPOSubnet(subnets, &filteredSubnets[subnet])
- }
} else {
for subnet := range openStackClusterSubnets {
filteredSubnet, err := networkingService.GetNetworkSubnetByFilter(networkID, &openStackClusterSubnets[subnet])
@@ -722,8 +731,55 @@ func filterSubnets(networkingService *networking.Service, openStackCluster *infr
}
return nil, err
}
- subnets = networkingService.ConvertOpenStackSubnetToCAPOSubnet(subnets, filteredSubnet)
+ filteredSubnets = append(filteredSubnets, *filteredSubnet)
}
}
- return subnets, nil
+ return filteredSubnets, nil
+}
+
+// convertOpenStackNetworkToCAPONetwork converts an OpenStack network to a capo network.
+// It returns the converted subnet.
+func convertOpenStackNetworkToCAPONetwork(openStackCluster *infrav1.OpenStackCluster, network *networks.Network) {
+ openStackCluster.Status.Network.ID = network.ID
+ openStackCluster.Status.Network.Name = network.Name
+ openStackCluster.Status.Network.Tags = network.Tags
+}
+
+// populateCAPONetworkFromSubnet gets a network based on the networkID of the subnets and converts it to the CAPO format.
+// It returns an error in case it failed to retrieve the network.
+func populateCAPONetworkFromSubnet(networkingService *networking.Service, subnets []subnets.Subnet, openStackCluster *infrav1.OpenStackCluster) error {
+ if openStackCluster.Status.Network.ID == "" && len(subnets) > 0 {
+ if len(subnets) > 1 && subnets[0].NetworkID != subnets[1].NetworkID {
+ return fmt.Errorf("unable to identify the network to use. NetworkID %s from subnet %s does not match NetworkID %s from subnet %s", subnets[0].NetworkID, subnets[0].ID, subnets[1].NetworkID, subnets[1].ID)
+ }
+
+ network, err := networkingService.GetNetworkByID(subnets[0].NetworkID)
+ if err != nil {
+ return err
+ }
+ convertOpenStackNetworkToCAPONetwork(openStackCluster, network)
+ }
+ return nil
+}
+
+// getCAPONetwork gets a network based on a filter, if defined, and convert the network to the CAPO format.
+// It returns an error in case it failed to retrieve the network.
+func getCAPONetwork(openStackCluster *infrav1.OpenStackCluster, networkingService *networking.Service) error {
+ emptyNetwork := infrav1.NetworkFilter{}
+ if openStackCluster.Spec.Network != emptyNetwork {
+ 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 {
+ convertOpenStackNetworkToCAPONetwork(openStackCluster, &networkList[0])
+ }
+ }
+ return nil
}
diff --git a/controllers/openstackcluster_controller_test.go b/controllers/openstackcluster_controller_test.go
index b512ac62f4..3a51ad6413 100644
--- a/controllers/openstackcluster_controller_test.go
+++ b/controllers/openstackcluster_controller_test.go
@@ -19,6 +19,8 @@ package controllers
import (
"context"
"fmt"
+ "reflect"
+ "testing"
"github.com/go-logr/logr"
"github.com/golang/mock/gomock"
@@ -544,6 +546,45 @@ var _ = Describe("OpenStackCluster controller", func() {
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: true,
+ APIServerFixedIP: "10.0.0.1",
+ DisableExternalNetwork: true,
+ Subnets: []infrav1.SubnetFilter{
+ {ID: clusterSubnetID},
+ },
+ }
+ 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())
+ Expect(err).To(BeNil())
+
+ 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 {
@@ -554,3 +595,25 @@ func createRequestFromOSCluster(openStackCluster *infrav1.OpenStackCluster) reco
},
}
}
+
+func Test_ConvertOpenStackNetworkToCAPONetwork(t *testing.T) {
+ openStackCluster := &infrav1.OpenStackCluster{}
+ openStackCluster.Status.Network = &infrav1.NetworkStatusWithSubnets{}
+
+ filterednetwork := &networks.Network{
+ ID: "network1",
+ Name: "network1",
+ Tags: []string{"tag1", "tag2"},
+ }
+
+ convertOpenStackNetworkToCAPONetwork(openStackCluster, filterednetwork)
+ expected := infrav1.NetworkStatus{
+ ID: "network1",
+ Name: "network1",
+ Tags: []string{"tag1", "tag2"},
+ }
+
+ if !reflect.DeepEqual(openStackCluster.Status.Network.NetworkStatus, expected) {
+ t.Errorf("ConvertOpenStackNetworkToCAPONetwork() = %v, want %v", openStackCluster.Status.Network.NetworkStatus, expected)
+ }
+}
diff --git a/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md b/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md
index be1b3b63c8..67f338ea49 100644
--- a/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md
+++ b/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md
@@ -243,3 +243,7 @@ Now the user needs to request creation of the security group rules by using the
Note that when upgrading from a previous version, the Calico CNI security group rules will be added automatically to
allow backwards compatibility if `allowAllInClusterTraffic` is set to false.
+
+#### ⚠️ Change to network
+
+In v1alpha8, when the `OpenStackCluster.Spec.Network` is not defined, the `Subnets` are now used to identify the `Network`.
diff --git a/pkg/cloud/services/networking/network.go b/pkg/cloud/services/networking/network.go
index 540dce22f4..7629abdee8 100644
--- a/pkg/cloud/services/networking/network.go
+++ b/pkg/cloud/services/networking/network.go
@@ -386,14 +386,11 @@ func getNetworkName(clusterName string) string {
return fmt.Sprintf("%s-cluster-%s", networkPrefix, clusterName)
}
-// ConvertOpenStackSubnetToCAPOSubnet converts an OpenStack subnet to a capo subnet and adds to a slice.
-// It returns the slice with the converted subnet.
-func (s *Service) ConvertOpenStackSubnetToCAPOSubnet(subnets []infrav1.Subnet, filteredSubnet *subnets.Subnet) []infrav1.Subnet {
- subnets = append(subnets, infrav1.Subnet{
- ID: filteredSubnet.ID,
- Name: filteredSubnet.Name,
- CIDR: filteredSubnet.CIDR,
- Tags: filteredSubnet.Tags,
- })
- return subnets
+// GetNetworkByID retrieves network by the ID.
+func (s *Service) GetNetworkByID(networkID string) (*networks.Network, error) {
+ network, err := s.client.GetNetwork(networkID)
+ if err != nil {
+ return &networks.Network{}, err
+ }
+ return network, nil
}
diff --git a/pkg/cloud/services/networking/network_test.go b/pkg/cloud/services/networking/network_test.go
index 512cc53146..47ff27783a 100644
--- a/pkg/cloud/services/networking/network_test.go
+++ b/pkg/cloud/services/networking/network_test.go
@@ -17,7 +17,6 @@ limitations under the License.
package networking
import (
- "reflect"
"testing"
"github.com/go-logr/logr"
@@ -25,7 +24,6 @@ import (
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external"
"github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
- "github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
. "github.com/onsi/gomega"
"k8s.io/utils/pointer"
@@ -422,43 +420,3 @@ func Test_ReconcileExternalNetwork(t *testing.T) {
})
}
}
-
-func Test_ConvertOpenStackSubnetToCAPOSubnet(t *testing.T) {
- caposubnets := []infrav1.Subnet{
- {
- ID: "subnet1",
- Name: "subnet1",
- CIDR: "10.0.0.0/24",
- Tags: []string{"tag1", "tag2"},
- },
- }
-
- filteredSubnet := &subnets.Subnet{
- ID: "subnet2",
- Name: "subnet2",
- CIDR: "192.168.0.0/24",
- Tags: []string{"tag3", "tag4"},
- }
-
- s := Service{}
- result := s.ConvertOpenStackSubnetToCAPOSubnet(caposubnets, filteredSubnet)
-
- expected := []infrav1.Subnet{
- {
- ID: "subnet1",
- Name: "subnet1",
- CIDR: "10.0.0.0/24",
- Tags: []string{"tag1", "tag2"},
- },
- {
- ID: "subnet2",
- Name: "subnet2",
- CIDR: "192.168.0.0/24",
- Tags: []string{"tag3", "tag4"},
- },
- }
-
- if !reflect.DeepEqual(result, expected) {
- t.Errorf("ConvertOpenStackSubnetToCAPOSubnet() = %v, want %v", result, expected)
- }
-}
From 05537fb5cb3a9be2315b220ec4ae0fc6075752ff Mon Sep 17 00:00:00 2001
From: Emilien Macchi
Date: Wed, 21 Feb 2024 14:03:43 -0500
Subject: [PATCH 074/180] Deprecate v1alpha6
---
api/v1alpha6/openstackcluster_types.go | 5 +++++
api/v1alpha6/openstackclustertemplate_types.go | 11 ++++++++---
api/v1alpha6/openstackmachine_types.go | 5 +++++
api/v1alpha6/openstackmachinetemplate_types.go | 5 +++++
...structure.cluster.x-k8s.io_openstackclusters.yaml | 9 ++++++++-
...e.cluster.x-k8s.io_openstackclustertemplates.yaml | 12 +++++++++---
...structure.cluster.x-k8s.io_openstackmachines.yaml | 9 ++++++++-
...e.cluster.x-k8s.io_openstackmachinetemplates.yaml | 12 +++++++++---
8 files changed, 57 insertions(+), 11 deletions(-)
diff --git a/api/v1alpha6/openstackcluster_types.go b/api/v1alpha6/openstackcluster_types.go
index 6b60c83b9e..3d7ba3d13c 100644
--- a/api/v1alpha6/openstackcluster_types.go
+++ b/api/v1alpha6/openstackcluster_types.go
@@ -213,6 +213,7 @@ type OpenStackClusterStatus struct {
}
// +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 +225,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 +238,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_types.go b/api/v1alpha6/openstackclustertemplate_types.go
index f79730240c..c76170dd52 100644
--- a/api/v1alpha6/openstackclustertemplate_types.go
+++ b/api/v1alpha6/openstackclustertemplate_types.go
@@ -30,10 +30,13 @@ type OpenStackClusterTemplateSpec struct {
Template OpenStackClusterTemplateResource `json:"template"`
}
-//+kubebuilder:object:root=true
-//+kubebuilder:resource:path=openstackclustertemplates,scope=Namespaced,categories=cluster-api,shortName=osct
+// +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 +44,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_types.go b/api/v1alpha6/openstackmachine_types.go
index c73505de3f..7dc263f099 100644
--- a/api/v1alpha6/openstackmachine_types.go
+++ b/api/v1alpha6/openstackmachine_types.go
@@ -137,6 +137,7 @@ type OpenStackMachineStatus struct {
}
// +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 +148,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 +161,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"`
diff --git a/api/v1alpha6/openstackmachinetemplate_types.go b/api/v1alpha6/openstackmachinetemplate_types.go
index aca2be9c70..6dbddaa85e 100644
--- a/api/v1alpha6/openstackmachinetemplate_types.go
+++ b/api/v1alpha6/openstackmachinetemplate_types.go
@@ -26,9 +26,12 @@ type OpenStackMachineTemplateSpec struct {
}
// +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 +42,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/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
index a9d2d44d11..40a2ba9b31 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -1825,10 +1825,17 @@ 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: |-
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 10a79fa903..0c7183f8ee 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -743,11 +743,17 @@ spec:
type: object
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: |-
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 15b1bee559..67da66b7ea 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
@@ -594,10 +594,17 @@ 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: |-
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 dac6f9c36e..c96a204003 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
@@ -464,11 +464,17 @@ spec:
type: object
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: |-
From 4ff2cf836fcb6814fa5d772f738fdbef803a1d80 Mon Sep 17 00:00:00 2001
From: Emilien Macchi
Date: Thu, 11 Jan 2024 08:48:44 -0500
Subject: [PATCH 075/180] e2e: bastion tests
---
hack/ci/cloud-init/controller.yaml.tpl | 2 +
test/e2e/data/e2e_conf.yaml | 2 +
test/e2e/shared/defaults.go | 1 +
test/e2e/shared/openstack.go | 18 ++++++
test/e2e/suites/e2e/e2e_test.go | 81 ++++++++++++++++++++++++++
5 files changed, 104 insertions(+)
diff --git a/hack/ci/cloud-init/controller.yaml.tpl b/hack/ci/cloud-init/controller.yaml.tpl
index 21fc3cf4aa..20eb78627f 100644
--- a/hack/ci/cloud-init/controller.yaml.tpl
+++ b/hack/ci/cloud-init/controller.yaml.tpl
@@ -177,6 +177,8 @@
openstack flavor create --ram 4192 --disk 20 --ephemeral 5 --vcpus 2 --public --id 2 m1.small --property hw_rng:allowed='True'
openstack flavor delete m1.medium
openstack flavor create --ram 6144 --disk 20 --ephemeral 5 --vcpus 2 --public --id 3 m1.medium --property hw_rng:allowed='True'
+ # Create an additional flavor for the e2e tests that will be used by the e2e bastion tests
+ openstack flavor create --ram 512 --disk 1 --ephemeral 1 --vcpus 1 --public --id 10 m1.tiny.alt --property hw_rng:allowed='True'
# Adjust the CPU quota
openstack quota set --cores 32 demo
diff --git a/test/e2e/data/e2e_conf.yaml b/test/e2e/data/e2e_conf.yaml
index a7c885d303..03ac783247 100644
--- a/test/e2e/data/e2e_conf.yaml
+++ b/test/e2e/data/e2e_conf.yaml
@@ -190,6 +190,7 @@ variables:
EXP_CLUSTER_RESOURCE_SET: "true"
OPENSTACK_BASTION_IMAGE_NAME: "cirros-0.6.1-x86_64-disk"
OPENSTACK_BASTION_MACHINE_FLAVOR: "m1.tiny"
+ OPENSTACK_BASTION_MACHINE_FLAVOR_ALT: "m1.tiny.alt"
OPENSTACK_CLOUD: "capo-e2e"
OPENSTACK_CLOUD_ADMIN: "capo-e2e-admin"
OPENSTACK_CLOUD_CACERT_B64: "Cg=="
@@ -220,6 +221,7 @@ intervals:
conformance/wait-control-plane: ["30m", "10s"]
conformance/wait-worker-nodes: ["30m", "10s"]
default/wait-controllers: ["3m", "10s"]
+ default/wait-bastion: ["5m", "10s"]
default/wait-cluster: ["20m", "10s"]
default/wait-control-plane: ["30m", "10s"]
default/wait-worker-nodes: ["30m", "10s"]
diff --git a/test/e2e/shared/defaults.go b/test/e2e/shared/defaults.go
index df6315f773..ab2079381f 100644
--- a/test/e2e/shared/defaults.go
+++ b/test/e2e/shared/defaults.go
@@ -35,6 +35,7 @@ const (
KubernetesVersion = "KUBERNETES_VERSION"
CCMPath = "CCM"
CCMResources = "CCM_RESOURCES"
+ OpenStackBastionFlavorAlt = "OPENSTACK_BASTION_MACHINE_FLAVOR_ALT"
OpenStackCloudYAMLFile = "OPENSTACK_CLOUD_YAML_FILE"
OpenStackCloud = "OPENSTACK_CLOUD"
OpenStackCloudAdmin = "OPENSTACK_CLOUD_ADMIN"
diff --git a/test/e2e/shared/openstack.go b/test/e2e/shared/openstack.go
index 85661092f3..b974b01820 100644
--- a/test/e2e/shared/openstack.go
+++ b/test/e2e/shared/openstack.go
@@ -36,6 +36,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/availabilityzones"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/keypairs"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/flavors"
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
"github.com/gophercloud/gophercloud/openstack/imageservice/v2/images"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers"
@@ -46,6 +47,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
"github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
"github.com/gophercloud/utils/openstack/clientconfig"
+ uflavors "github.com/gophercloud/utils/openstack/compute/v2/flavors"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"gopkg.in/ini.v1"
@@ -847,3 +849,19 @@ func GetOpenStackVolume(e2eCtx *E2EContext, name string) (*volumes.Volume, error
return volume, nil
}
+
+func GetFlavorFromName(e2eCtx *E2EContext, name string) (*flavors.Flavor, error) {
+ providerClient, clientOpts, _, err := GetTenantProviderClient(e2eCtx)
+ if err != nil {
+ _, _ = fmt.Fprintf(GinkgoWriter, "error creating provider client: %s\n", err)
+ return nil, err
+ }
+
+ computeClient, err := openstack.NewComputeV2(providerClient, gophercloud.EndpointOpts{Region: clientOpts.RegionName})
+ Expect(err).NotTo(HaveOccurred())
+
+ flavorID, err := uflavors.IDFromName(computeClient, name)
+ Expect(err).NotTo(HaveOccurred())
+
+ return flavors.Get(computeClient, flavorID).Extract()
+}
diff --git a/test/e2e/suites/e2e/e2e_test.go b/test/e2e/suites/e2e/e2e_test.go
index f4b92c9a42..f802b2bd83 100644
--- a/test/e2e/suites/e2e/e2e_test.go
+++ b/test/e2e/suites/e2e/e2e_test.go
@@ -162,6 +162,87 @@ var _ = Describe("e2e tests [PR-Blocking]", func() {
// We expect 4 security group rules that allow Calico traffic on the control plane
// from both the control plane and worker machines and vice versa, that makes 8 rules.
Expect(calicoSGRules).To(Equal(8))
+
+ shared.Logf("Check the bastion")
+ openStackCluster, err = shared.ClusterForSpec(ctx, e2eCtx, namespace)
+ Expect(err).NotTo(HaveOccurred())
+ bastionSpec := openStackCluster.Spec.Bastion
+ Expect(openStackCluster.Status.Bastion).NotTo(BeNil(), "OpenStackCluster.Status.Bastion has not been populated")
+ bastionServerName := openStackCluster.Status.Bastion.Name
+ bastionServer, err := shared.DumpOpenStackServers(e2eCtx, servers.ListOpts{Name: bastionServerName})
+ Expect(err).NotTo(HaveOccurred())
+ Expect(bastionServer).To(HaveLen(1), "Did not find the bastion in OpenStack")
+
+ shared.Logf("Disable the bastion")
+ openStackCluster, err = shared.ClusterForSpec(ctx, e2eCtx, namespace)
+ Expect(err).NotTo(HaveOccurred())
+ openStackClusterDisabledBastion := openStackCluster.DeepCopy()
+ openStackClusterDisabledBastion.Spec.Bastion.Enabled = false
+ Expect(e2eCtx.Environment.BootstrapClusterProxy.GetClient().Update(ctx, openStackClusterDisabledBastion)).To(Succeed())
+ Eventually(
+ func() (bool, error) {
+ bastionServer, err := shared.DumpOpenStackServers(e2eCtx, servers.ListOpts{Name: bastionServerName})
+ Expect(err).NotTo(HaveOccurred())
+ if len(bastionServer) == 0 {
+ return true, nil
+ }
+ return false, errors.New("Bastion was not deleted in OpenStack")
+ }, e2eCtx.E2EConfig.GetIntervals(specName, "wait-bastion")...,
+ ).Should(BeTrue())
+ Eventually(
+ func() (bool, error) {
+ openStackCluster, err = shared.ClusterForSpec(ctx, e2eCtx, namespace)
+ Expect(err).NotTo(HaveOccurred())
+ if openStackCluster.Status.Bastion == nil {
+ return true, nil
+ }
+ return false, errors.New("Bastion was not removed in OpenStackCluster.Status")
+ }, e2eCtx.E2EConfig.GetIntervals(specName, "wait-bastion")...,
+ ).Should(BeTrue())
+
+ shared.Logf("Delete the bastion")
+ openStackCluster, err = shared.ClusterForSpec(ctx, e2eCtx, namespace)
+ Expect(err).NotTo(HaveOccurred())
+ openStackClusterWithoutBastion := openStackCluster.DeepCopy()
+ openStackClusterWithoutBastion.Spec.Bastion = nil
+ Expect(e2eCtx.Environment.BootstrapClusterProxy.GetClient().Update(ctx, openStackClusterWithoutBastion)).To(Succeed())
+ openStackCluster, err = shared.ClusterForSpec(ctx, e2eCtx, namespace)
+ Expect(err).NotTo(HaveOccurred())
+ Eventually(
+ func() (bool, error) {
+ openStackCluster, err = shared.ClusterForSpec(ctx, e2eCtx, namespace)
+ Expect(err).NotTo(HaveOccurred())
+ if openStackCluster.Spec.Bastion == nil {
+ return true, nil
+ }
+ return false, errors.New("Bastion was not removed in OpenStackCluster.Spec")
+ }, e2eCtx.E2EConfig.GetIntervals(specName, "wait-bastion")...,
+ ).Should(BeTrue())
+
+ shared.Logf("Create the bastion with a new flavor")
+ bastionNewFlavorName := e2eCtx.E2EConfig.GetVariable(shared.OpenStackBastionFlavorAlt)
+ bastionNewFlavor, err := shared.GetFlavorFromName(e2eCtx, bastionNewFlavorName)
+ Expect(err).NotTo(HaveOccurred())
+ openStackCluster, err = shared.ClusterForSpec(ctx, e2eCtx, namespace)
+ Expect(err).NotTo(HaveOccurred())
+ openStackClusterWithNewBastionFlavor := openStackCluster.DeepCopy()
+ openStackClusterWithNewBastionFlavor.Spec.Bastion = bastionSpec
+ openStackClusterWithNewBastionFlavor.Spec.Bastion.Instance.Flavor = bastionNewFlavorName
+ Expect(e2eCtx.Environment.BootstrapClusterProxy.GetClient().Update(ctx, openStackClusterWithNewBastionFlavor)).To(Succeed())
+ Eventually(
+ func() (bool, error) {
+ bastionServer, err := shared.DumpOpenStackServers(e2eCtx, servers.ListOpts{Name: bastionServerName, Flavor: bastionNewFlavor.ID})
+ Expect(err).NotTo(HaveOccurred())
+ if len(bastionServer) == 1 {
+ return true, nil
+ }
+ return false, errors.New("Bastion with new flavor was not created in OpenStack")
+ }, e2eCtx.E2EConfig.GetIntervals(specName, "wait-bastion")...,
+ ).Should(BeTrue())
+ openStackCluster, err = shared.ClusterForSpec(ctx, e2eCtx, namespace)
+ Expect(err).NotTo(HaveOccurred())
+ Expect(openStackCluster.Spec.Bastion).To(Equal(openStackClusterWithNewBastionFlavor.Spec.Bastion))
+ Expect(openStackCluster.Status.Bastion).NotTo(BeNil(), "OpenStackCluster.Status.Bastion with new flavor has not been populated")
})
})
From fc810d87a168f165c7a84c138e7f8fc7c0c1f175 Mon Sep 17 00:00:00 2001
From: Emilien Macchi
Date: Wed, 21 Feb 2024 15:13:10 -0500
Subject: [PATCH 076/180] Remove `IdentityRef.Kind`
---
api/v1alpha5/conversion.go | 4 ++
api/v1alpha5/zz_generated.conversion.go | 58 ++++++++++++++-----
api/v1alpha6/conversion.go | 10 ++++
api/v1alpha6/zz_generated.conversion.go | 58 ++++++++++++++-----
api/v1alpha7/conversion.go | 10 ++++
api/v1alpha7/zz_generated.conversion.go | 58 ++++++++++++++-----
api/v1alpha8/identity_types.go | 7 ---
api/v1alpha8/openstackcluster_webhook.go | 14 -----
api/v1alpha8/openstackcluster_webhook_test.go | 40 -------------
.../openstackclustertemplate_webhook.go | 7 ---
api/v1alpha8/openstackmachine_webhook.go | 11 ----
...re.cluster.x-k8s.io_openstackclusters.yaml | 14 -----
...er.x-k8s.io_openstackclustertemplates.yaml | 14 -----
...re.cluster.x-k8s.io_openstackmachines.yaml | 7 ---
...er.x-k8s.io_openstackmachinetemplates.yaml | 7 ---
.../crd-changes/v1alpha7-to-v1alpha8.md | 30 ++++++----
.../v1alpha8/default/cluster-template.yaml | 3 -
.../cluster-template-flatcar-sysext.yaml | 3 -
templates/cluster-template-flatcar.yaml | 3 -
templates/cluster-template-without-lb.yaml | 3 -
templates/cluster-template.yaml | 3 -
templates/clusterclass-dev-test.yaml | 3 -
.../k8s-upgrade/upgrade-from-template.yaml | 2 -
.../k8s-upgrade/upgrade-to-template.yaml | 2 -
test/e2e/suites/e2e/e2e_test.go | 2 -
25 files changed, 170 insertions(+), 203 deletions(-)
diff --git a/api/v1alpha5/conversion.go b/api/v1alpha5/conversion.go
index 95177baa3e..5fefbc7136 100644
--- a/api/v1alpha5/conversion.go
+++ b/api/v1alpha5/conversion.go
@@ -624,3 +624,7 @@ func Convert_v1alpha5_SecurityGroup_To_v1alpha8_SecurityGroupStatus(in *Security
return nil
}
+
+func Convert_v1alpha5_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(in *OpenStackIdentityReference, out *infrav1.OpenStackIdentityReference, s conversion.Scope) error {
+ return autoConvert_v1alpha5_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(in, out, s)
+}
diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go
index 8ec8034142..bdf6402b6d 100644
--- a/api/v1alpha5/zz_generated.conversion.go
+++ b/api/v1alpha5/zz_generated.conversion.go
@@ -149,11 +149,6 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*OpenStackIdentityReference)(nil), (*v1alpha8.OpenStackIdentityReference)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(a.(*OpenStackIdentityReference), b.(*v1alpha8.OpenStackIdentityReference), scope)
- }); err != nil {
- return err
- }
if err := s.AddGeneratedConversionFunc((*v1alpha8.OpenStackIdentityReference)(nil), (*OpenStackIdentityReference)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha8_OpenStackIdentityReference_To_v1alpha5_OpenStackIdentityReference(a.(*v1alpha8.OpenStackIdentityReference), b.(*OpenStackIdentityReference), scope)
}); err != nil {
@@ -299,6 +294,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
+ if err := s.AddConversionFunc((*OpenStackIdentityReference)(nil), (*v1alpha8.OpenStackIdentityReference)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(a.(*OpenStackIdentityReference), b.(*v1alpha8.OpenStackIdentityReference), scope)
+ }); err != nil {
+ return err
+ }
if err := s.AddConversionFunc((*OpenStackMachineSpec)(nil), (*v1alpha8.OpenStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha5_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(a.(*OpenStackMachineSpec), b.(*v1alpha8.OpenStackMachineSpec), scope)
}); err != nil {
@@ -685,7 +685,15 @@ func autoConvert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(
} else {
out.Bastion = nil
}
- out.IdentityRef = (*v1alpha8.OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef))
+ if in.IdentityRef != nil {
+ in, out := &in.IdentityRef, &out.IdentityRef
+ *out = new(v1alpha8.OpenStackIdentityReference)
+ if err := Convert_v1alpha5_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(*in, *out, s); err != nil {
+ return err
+ }
+ } else {
+ out.IdentityRef = nil
+ }
return nil
}
@@ -733,7 +741,15 @@ func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(
} else {
out.Bastion = nil
}
- out.IdentityRef = (*OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef))
+ if in.IdentityRef != nil {
+ in, out := &in.IdentityRef, &out.IdentityRef
+ *out = new(OpenStackIdentityReference)
+ if err := Convert_v1alpha8_OpenStackIdentityReference_To_v1alpha5_OpenStackIdentityReference(*in, *out, s); err != nil {
+ return err
+ }
+ } else {
+ out.IdentityRef = nil
+ }
return nil
}
@@ -980,18 +996,12 @@ func Convert_v1alpha8_OpenStackClusterTemplateSpec_To_v1alpha5_OpenStackClusterT
}
func autoConvert_v1alpha5_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(in *OpenStackIdentityReference, out *v1alpha8.OpenStackIdentityReference, s conversion.Scope) error {
- out.Kind = in.Kind
+ // WARNING: in.Kind requires manual conversion: does not exist in peer-type
out.Name = in.Name
return nil
}
-// Convert_v1alpha5_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference is an autogenerated conversion function.
-func Convert_v1alpha5_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(in *OpenStackIdentityReference, out *v1alpha8.OpenStackIdentityReference, s conversion.Scope) error {
- return autoConvert_v1alpha5_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(in, out, s)
-}
-
func autoConvert_v1alpha8_OpenStackIdentityReference_To_v1alpha5_OpenStackIdentityReference(in *v1alpha8.OpenStackIdentityReference, out *OpenStackIdentityReference, s conversion.Scope) error {
- out.Kind = in.Kind
out.Name = in.Name
return nil
}
@@ -1114,7 +1124,15 @@ func autoConvert_v1alpha5_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(
out.ConfigDrive = (*bool)(unsafe.Pointer(in.ConfigDrive))
out.RootVolume = (*v1alpha8.RootVolume)(unsafe.Pointer(in.RootVolume))
// WARNING: in.ServerGroupID requires manual conversion: does not exist in peer-type
- out.IdentityRef = (*v1alpha8.OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef))
+ if in.IdentityRef != nil {
+ in, out := &in.IdentityRef, &out.IdentityRef
+ *out = new(v1alpha8.OpenStackIdentityReference)
+ if err := Convert_v1alpha5_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(*in, *out, s); err != nil {
+ return err
+ }
+ } else {
+ out.IdentityRef = nil
+ }
return nil
}
@@ -1154,7 +1172,15 @@ func autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(
out.RootVolume = (*RootVolume)(unsafe.Pointer(in.RootVolume))
// WARNING: in.AdditionalBlockDevices requires manual conversion: does not exist in peer-type
// WARNING: in.ServerGroup requires manual conversion: does not exist in peer-type
- out.IdentityRef = (*OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef))
+ if in.IdentityRef != nil {
+ in, out := &in.IdentityRef, &out.IdentityRef
+ *out = new(OpenStackIdentityReference)
+ if err := Convert_v1alpha8_OpenStackIdentityReference_To_v1alpha5_OpenStackIdentityReference(*in, *out, s); err != nil {
+ return err
+ }
+ } else {
+ out.IdentityRef = nil
+ }
return nil
}
diff --git a/api/v1alpha6/conversion.go b/api/v1alpha6/conversion.go
index 5068c87b07..21e6e4f325 100644
--- a/api/v1alpha6/conversion.go
+++ b/api/v1alpha6/conversion.go
@@ -73,6 +73,9 @@ func restorev1alpha6MachineSpec(previous *OpenStackMachineSpec, dst *OpenStackMa
dst.ServerMetadata[k] = v
}
}
+
+ // Conversion to v1alpha8 removes the Kind fild
+ dst.IdentityRef = previous.IdentityRef
}
func restorev1alpha6ClusterStatus(previous *OpenStackClusterStatus, dst *OpenStackClusterStatus) {
@@ -162,6 +165,9 @@ func restorev1alpha6ClusterSpec(previous *OpenStackClusterSpec, dst *OpenStackCl
if previous.AllowAllInClusterTraffic && !previous.ManagedSecurityGroups {
dst.AllowAllInClusterTraffic = true
}
+
+ // Conversion to v1alpha8 removes the Kind field
+ dst.IdentityRef = previous.IdentityRef
}
var _ ctrlconversion.Convertible = &OpenStackCluster{}
@@ -988,3 +994,7 @@ func Convert_v1alpha6_SecurityGroup_To_v1alpha8_SecurityGroupStatus(in *Security
return nil
}
+
+func Convert_v1alpha6_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(in *OpenStackIdentityReference, out *infrav1.OpenStackIdentityReference, s apiconversion.Scope) error {
+ return autoConvert_v1alpha6_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(in, out, s)
+}
diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go
index 2bbcd48d10..a9d397034d 100644
--- a/api/v1alpha6/zz_generated.conversion.go
+++ b/api/v1alpha6/zz_generated.conversion.go
@@ -159,11 +159,6 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*OpenStackIdentityReference)(nil), (*v1alpha8.OpenStackIdentityReference)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(a.(*OpenStackIdentityReference), b.(*v1alpha8.OpenStackIdentityReference), scope)
- }); err != nil {
- return err
- }
if err := s.AddGeneratedConversionFunc((*v1alpha8.OpenStackIdentityReference)(nil), (*OpenStackIdentityReference)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha8_OpenStackIdentityReference_To_v1alpha6_OpenStackIdentityReference(a.(*v1alpha8.OpenStackIdentityReference), b.(*OpenStackIdentityReference), scope)
}); err != nil {
@@ -319,6 +314,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
+ if err := s.AddConversionFunc((*OpenStackIdentityReference)(nil), (*v1alpha8.OpenStackIdentityReference)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(a.(*OpenStackIdentityReference), b.(*v1alpha8.OpenStackIdentityReference), scope)
+ }); err != nil {
+ return err
+ }
if err := s.AddConversionFunc((*OpenStackMachineSpec)(nil), (*v1alpha8.OpenStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha6_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(a.(*OpenStackMachineSpec), b.(*v1alpha8.OpenStackMachineSpec), scope)
}); err != nil {
@@ -708,7 +708,15 @@ func autoConvert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(
} else {
out.Bastion = nil
}
- out.IdentityRef = (*v1alpha8.OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef))
+ if in.IdentityRef != nil {
+ in, out := &in.IdentityRef, &out.IdentityRef
+ *out = new(v1alpha8.OpenStackIdentityReference)
+ if err := Convert_v1alpha6_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(*in, *out, s); err != nil {
+ return err
+ }
+ } else {
+ out.IdentityRef = nil
+ }
return nil
}
@@ -756,7 +764,15 @@ func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(
} else {
out.Bastion = nil
}
- out.IdentityRef = (*OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef))
+ if in.IdentityRef != nil {
+ in, out := &in.IdentityRef, &out.IdentityRef
+ *out = new(OpenStackIdentityReference)
+ if err := Convert_v1alpha8_OpenStackIdentityReference_To_v1alpha6_OpenStackIdentityReference(*in, *out, s); err != nil {
+ return err
+ }
+ } else {
+ out.IdentityRef = nil
+ }
return nil
}
@@ -1003,18 +1019,12 @@ func Convert_v1alpha8_OpenStackClusterTemplateSpec_To_v1alpha6_OpenStackClusterT
}
func autoConvert_v1alpha6_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(in *OpenStackIdentityReference, out *v1alpha8.OpenStackIdentityReference, s conversion.Scope) error {
- out.Kind = in.Kind
+ // WARNING: in.Kind requires manual conversion: does not exist in peer-type
out.Name = in.Name
return nil
}
-// Convert_v1alpha6_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference is an autogenerated conversion function.
-func Convert_v1alpha6_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(in *OpenStackIdentityReference, out *v1alpha8.OpenStackIdentityReference, s conversion.Scope) error {
- return autoConvert_v1alpha6_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(in, out, s)
-}
-
func autoConvert_v1alpha8_OpenStackIdentityReference_To_v1alpha6_OpenStackIdentityReference(in *v1alpha8.OpenStackIdentityReference, out *OpenStackIdentityReference, s conversion.Scope) error {
- out.Kind = in.Kind
out.Name = in.Name
return nil
}
@@ -1137,7 +1147,15 @@ func autoConvert_v1alpha6_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(
out.ConfigDrive = (*bool)(unsafe.Pointer(in.ConfigDrive))
out.RootVolume = (*v1alpha8.RootVolume)(unsafe.Pointer(in.RootVolume))
// WARNING: in.ServerGroupID requires manual conversion: does not exist in peer-type
- out.IdentityRef = (*v1alpha8.OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef))
+ if in.IdentityRef != nil {
+ in, out := &in.IdentityRef, &out.IdentityRef
+ *out = new(v1alpha8.OpenStackIdentityReference)
+ if err := Convert_v1alpha6_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(*in, *out, s); err != nil {
+ return err
+ }
+ } else {
+ out.IdentityRef = nil
+ }
return nil
}
@@ -1177,7 +1195,15 @@ func autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(
out.RootVolume = (*RootVolume)(unsafe.Pointer(in.RootVolume))
// WARNING: in.AdditionalBlockDevices requires manual conversion: does not exist in peer-type
// WARNING: in.ServerGroup requires manual conversion: does not exist in peer-type
- out.IdentityRef = (*OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef))
+ if in.IdentityRef != nil {
+ in, out := &in.IdentityRef, &out.IdentityRef
+ *out = new(OpenStackIdentityReference)
+ if err := Convert_v1alpha8_OpenStackIdentityReference_To_v1alpha6_OpenStackIdentityReference(*in, *out, s); err != nil {
+ return err
+ }
+ } else {
+ out.IdentityRef = nil
+ }
return nil
}
diff --git a/api/v1alpha7/conversion.go b/api/v1alpha7/conversion.go
index 2183d37386..cefd794c0b 100644
--- a/api/v1alpha7/conversion.go
+++ b/api/v1alpha7/conversion.go
@@ -180,6 +180,9 @@ func restorev1alpha7MachineSpec(previous *OpenStackMachineSpec, dst *OpenStackMa
dst.ServerMetadata[k] = v
}
}
+
+ // Conversion to v1alpha8 removes the Kind field
+ dst.IdentityRef = previous.IdentityRef
}
func restorev1alpha8MachineSpec(previous *infrav1.OpenStackMachineSpec, dst *infrav1.OpenStackMachineSpec) {
@@ -210,6 +213,9 @@ func restorev1alpha7ClusterSpec(previous *OpenStackClusterSpec, dst *OpenStackCl
if previous.AllowAllInClusterTraffic && !previous.ManagedSecurityGroups {
dst.AllowAllInClusterTraffic = true
}
+
+ // Conversion to v1alpha8 removes the Kind field
+ dst.IdentityRef = previous.IdentityRef
}
func restorev1alpha8ClusterSpec(previous *infrav1.OpenStackClusterSpec, dst *infrav1.OpenStackClusterSpec) {
@@ -678,3 +684,7 @@ func Convert_v1alpha7_SecurityGroup_To_v1alpha8_SecurityGroupStatus(in *Security
return nil
}
+
+func Convert_v1alpha7_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(in *OpenStackIdentityReference, out *infrav1.OpenStackIdentityReference, s apiconversion.Scope) error {
+ return autoConvert_v1alpha7_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(in, out, s)
+}
diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go
index c29aaf334f..fa7abe3520 100644
--- a/api/v1alpha7/zz_generated.conversion.go
+++ b/api/v1alpha7/zz_generated.conversion.go
@@ -234,11 +234,6 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*OpenStackIdentityReference)(nil), (*v1alpha8.OpenStackIdentityReference)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(a.(*OpenStackIdentityReference), b.(*v1alpha8.OpenStackIdentityReference), scope)
- }); err != nil {
- return err
- }
if err := s.AddGeneratedConversionFunc((*v1alpha8.OpenStackIdentityReference)(nil), (*OpenStackIdentityReference)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha8_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference(a.(*v1alpha8.OpenStackIdentityReference), b.(*OpenStackIdentityReference), scope)
}); err != nil {
@@ -399,6 +394,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
+ if err := s.AddConversionFunc((*OpenStackIdentityReference)(nil), (*v1alpha8.OpenStackIdentityReference)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha7_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(a.(*OpenStackIdentityReference), b.(*v1alpha8.OpenStackIdentityReference), scope)
+ }); err != nil {
+ return err
+ }
if err := s.AddConversionFunc((*OpenStackMachineSpec)(nil), (*v1alpha8.OpenStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha7_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(a.(*OpenStackMachineSpec), b.(*v1alpha8.OpenStackMachineSpec), scope)
}); err != nil {
@@ -900,7 +900,15 @@ func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(
} else {
out.Bastion = nil
}
- out.IdentityRef = (*v1alpha8.OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef))
+ if in.IdentityRef != nil {
+ in, out := &in.IdentityRef, &out.IdentityRef
+ *out = new(v1alpha8.OpenStackIdentityReference)
+ if err := Convert_v1alpha7_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(*in, *out, s); err != nil {
+ return err
+ }
+ } else {
+ out.IdentityRef = nil
+ }
return nil
}
@@ -938,7 +946,15 @@ func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(
} else {
out.Bastion = nil
}
- out.IdentityRef = (*OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef))
+ if in.IdentityRef != nil {
+ in, out := &in.IdentityRef, &out.IdentityRef
+ *out = new(OpenStackIdentityReference)
+ if err := Convert_v1alpha8_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference(*in, *out, s); err != nil {
+ return err
+ }
+ } else {
+ out.IdentityRef = nil
+ }
return nil
}
@@ -1165,18 +1181,12 @@ func Convert_v1alpha8_OpenStackClusterTemplateSpec_To_v1alpha7_OpenStackClusterT
}
func autoConvert_v1alpha7_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(in *OpenStackIdentityReference, out *v1alpha8.OpenStackIdentityReference, s conversion.Scope) error {
- out.Kind = in.Kind
+ // WARNING: in.Kind requires manual conversion: does not exist in peer-type
out.Name = in.Name
return nil
}
-// Convert_v1alpha7_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference is an autogenerated conversion function.
-func Convert_v1alpha7_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(in *OpenStackIdentityReference, out *v1alpha8.OpenStackIdentityReference, s conversion.Scope) error {
- return autoConvert_v1alpha7_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(in, out, s)
-}
-
func autoConvert_v1alpha8_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference(in *v1alpha8.OpenStackIdentityReference, out *OpenStackIdentityReference, s conversion.Scope) error {
- out.Kind = in.Kind
out.Name = in.Name
return nil
}
@@ -1278,7 +1288,15 @@ func autoConvert_v1alpha7_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(
out.RootVolume = (*v1alpha8.RootVolume)(unsafe.Pointer(in.RootVolume))
out.AdditionalBlockDevices = *(*[]v1alpha8.AdditionalBlockDevice)(unsafe.Pointer(&in.AdditionalBlockDevices))
// WARNING: in.ServerGroupID requires manual conversion: does not exist in peer-type
- out.IdentityRef = (*v1alpha8.OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef))
+ if in.IdentityRef != nil {
+ in, out := &in.IdentityRef, &out.IdentityRef
+ *out = new(v1alpha8.OpenStackIdentityReference)
+ if err := Convert_v1alpha7_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(*in, *out, s); err != nil {
+ return err
+ }
+ } else {
+ out.IdentityRef = nil
+ }
return nil
}
@@ -1298,7 +1316,15 @@ func autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(
out.RootVolume = (*RootVolume)(unsafe.Pointer(in.RootVolume))
out.AdditionalBlockDevices = *(*[]AdditionalBlockDevice)(unsafe.Pointer(&in.AdditionalBlockDevices))
// WARNING: in.ServerGroup requires manual conversion: does not exist in peer-type
- out.IdentityRef = (*OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef))
+ if in.IdentityRef != nil {
+ in, out := &in.IdentityRef, &out.IdentityRef
+ *out = new(OpenStackIdentityReference)
+ if err := Convert_v1alpha8_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference(*in, *out, s); err != nil {
+ return err
+ }
+ } else {
+ out.IdentityRef = nil
+ }
return nil
}
diff --git a/api/v1alpha8/identity_types.go b/api/v1alpha8/identity_types.go
index b77700c2df..d9bf1f4f92 100644
--- a/api/v1alpha8/identity_types.go
+++ b/api/v1alpha8/identity_types.go
@@ -16,16 +16,9 @@ limitations under the License.
package v1alpha8
-const defaultIdentityRefKind = "Secret"
-
// 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.
diff --git a/api/v1alpha8/openstackcluster_webhook.go b/api/v1alpha8/openstackcluster_webhook.go
index 78eb4a21b5..b9e148f589 100644
--- a/api/v1alpha8/openstackcluster_webhook.go
+++ b/api/v1alpha8/openstackcluster_webhook.go
@@ -50,19 +50,12 @@ var (
// 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"))
- }
-
if r.Spec.ManagedSecurityGroups != nil {
for _, rule := range r.Spec.ManagedSecurityGroups.AllNodesSecurityGroupRules {
if rule.RemoteManagedGroups != nil && (rule.RemoteGroupID != nil || rule.RemoteIPPrefix != nil) {
@@ -88,13 +81,6 @@ func (r *OpenStackCluster) ValidateUpdate(oldRaw runtime.Object) (admission.Warn
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 = ""
diff --git a/api/v1alpha8/openstackcluster_webhook_test.go b/api/v1alpha8/openstackcluster_webhook_test.go
index 3985e76605..40bfa731f0 100644
--- a/api/v1alpha8/openstackcluster_webhook_test.go
+++ b/api/v1alpha8/openstackcluster_webhook_test.go
@@ -32,35 +32,12 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
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",
},
},
@@ -69,7 +46,6 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
Spec: OpenStackClusterSpec{
CloudName: "foobar",
IdentityRef: &OpenStackIdentityReference{
- Kind: "Secret",
Name: "foobarbaz",
},
},
@@ -87,7 +63,6 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
Spec: OpenStackClusterSpec{
CloudName: "foobar",
IdentityRef: &OpenStackIdentityReference{
- Kind: "Secret",
Name: "foobar",
},
},
@@ -100,7 +75,6 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
Spec: OpenStackClusterSpec{
CloudName: "foobar",
IdentityRef: &OpenStackIdentityReference{
- Kind: "Secret",
Name: "foobar",
},
},
@@ -462,26 +436,12 @@ func TestOpenStackCluster_ValidateCreate(t *testing.T) {
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,
- },
{
name: "OpenStackCluster.Spec.ManagedSecurityGroups.AllNodesSecurityGroupRules with correct spec on create",
template: &OpenStackCluster{
diff --git a/api/v1alpha8/openstackclustertemplate_webhook.go b/api/v1alpha8/openstackclustertemplate_webhook.go
index 5cfbc6b92d..03aa2b1dff 100644
--- a/api/v1alpha8/openstackclustertemplate_webhook.go
+++ b/api/v1alpha8/openstackclustertemplate_webhook.go
@@ -46,19 +46,12 @@ var (
// 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)
}
diff --git a/api/v1alpha8/openstackmachine_webhook.go b/api/v1alpha8/openstackmachine_webhook.go
index b5ddbaf0e3..8f5e1ee1f3 100644
--- a/api/v1alpha8/openstackmachine_webhook.go
+++ b/api/v1alpha8/openstackmachine_webhook.go
@@ -49,19 +49,12 @@ var (
// 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" {
@@ -90,10 +83,6 @@ func (r *OpenStackMachine) ValidateUpdate(old runtime.Object) (admission.Warning
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{})
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 aa96ad27ea..bdf1340bbe 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -4990,12 +4990,6 @@ spec:
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.
- minLength: 1
- type: string
name:
description: |-
Name of the infrastructure identity to be used.
@@ -5003,7 +4997,6 @@ spec:
resource the same namespace as the resource(s) being provisioned.
type: string
required:
- - kind
- name
type: object
image:
@@ -5435,12 +5428,6 @@ spec:
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.
- minLength: 1
- type: string
name:
description: |-
Name of the infrastructure identity to be used.
@@ -5448,7 +5435,6 @@ spec:
resource the same namespace as the resource(s) being provisioned.
type: string
required:
- - kind
- name
type: object
managedSecurityGroups:
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 cb48bc42f4..5624a26977 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -2415,12 +2415,6 @@ spec:
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.
- minLength: 1
- type: string
name:
description: |-
Name of the infrastructure identity to be used.
@@ -2428,7 +2422,6 @@ spec:
resource the same namespace as the resource(s) being provisioned.
type: string
required:
- - kind
- name
type: object
image:
@@ -2869,12 +2862,6 @@ spec:
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.
- minLength: 1
- type: string
name:
description: |-
Name of the infrastructure identity to be used.
@@ -2882,7 +2869,6 @@ spec:
resource the same namespace as the resource(s) being provisioned.
type: string
required:
- - kind
- name
type: object
managedSecurityGroups:
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 67da66b7ea..56790cde7a 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
@@ -1791,12 +1791,6 @@ spec:
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.
- minLength: 1
- type: string
name:
description: |-
Name of the infrastructure identity to be used.
@@ -1804,7 +1798,6 @@ spec:
resource the same namespace as the resource(s) being provisioned.
type: string
required:
- - kind
- name
type: object
image:
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 c96a204003..95d1c52ecf 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
@@ -1465,12 +1465,6 @@ spec:
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.
- minLength: 1
- type: string
name:
description: |-
Name of the infrastructure identity to be used.
@@ -1478,7 +1472,6 @@ spec:
resource the same namespace as the resource(s) being provisioned.
type: string
required:
- - kind
- name
type: object
image:
diff --git a/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md b/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md
index a5f4c3121a..8b929c1ea2 100644
--- a/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md
+++ b/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md
@@ -6,8 +6,10 @@
- [Migration](#migration)
- [API Changes](#api-changes)
- [`OpenStackMachine`](#openstackmachine)
- - [⚠️ Change to `serverGroupID`](#️-change-to-servergroupid)
+ - [Removal of machine identityRef.kind](#removal-of-machine-identityrefkind)
+ - [Change to serverGroupID](#change-to-servergroupid)
- [`OpenStackCluster`](#openstackcluster)
+ - [Removal of cluster identityRef.kind](#removal-of-cluster-identityrefkind)
- [Change to externalNetworkID](#change-to-externalnetworkid)
- [Changes to image](#change-to-image)
- [Removal of imageUUID](#removal-of-imageuuid)
@@ -22,6 +24,7 @@
# v1alpha7 compared to v1alpha8
> ⚠️ v1alpha8 has not been released yet.
+
## Migration
All users are encouraged to migrate their usage of the CAPO CRDs from older versions to `v1alpha8`. This includes yaml files and source code. As CAPO implements automatic conversions between the CRD versions, this migration can happen after installing the new CAPO release.
@@ -32,7 +35,11 @@ This only documents backwards incompatible changes. Fields that were added to v1
### `OpenStackMachine`
-#### ⚠️ Change to `serverGroupID`
+#### Removal of machine identityRef.kind
+
+The `identityRef.Kind` field has been removed. It was used to specify the kind of the identity provider to use but was actually ignored.
+
+#### Change to serverGroupID
The field `serverGroupID` has been renamed to `serverGroup` and is now a `ServerGroupFilter` object rather than a string ID.
@@ -61,8 +68,11 @@ If empty object or null is provided, Machine will not be added to any server gro
### `OpenStackCluster`
-#### Change to externalNetworkID
+#### Removal of cluster identityRef.kind
+
+The `identityRef.Kind` field has been removed. It was used to specify the kind of the identity provider to use but was actually ignored.
+#### Change to externalNetworkID
The field `externalNetworkID` has been renamed to `externalNetwork` and is now a `NetworkFilter` object rather than a string ID.
The `NetworkFilter` object allows selection of a network by name, by ID or by tags.
@@ -96,7 +106,7 @@ It is now possible for a user to specify that no external network should be used
disableExternalNetwork: true
```
-#### ⚠️ Change to image
+#### Change to image
The field `image` is now an `ImageFilter` object rather than a string name.
The `ImageFilter` object allows selection of an image by name, by ID or by tags.
@@ -114,7 +124,7 @@ image:
The image ID will be added to `OpenStackMachine.Status.ReferencedResources.ImageID`. If the image can't be found or filter matches multiple images, an error will be returned.
-#### ⚠️ Removal of imageUUID
+#### Removal of imageUUID
The fild `imageUUID` has been removed in favor of the `image` field.
@@ -161,7 +171,7 @@ spec:
floatingIP: "1.2.3.4"
```
-#### ⚠️ Change to subnet
+#### Change to subnet
In v1alpha8, `Subnet` of `OpenStackCluster` is modified to `Subnets` to allow specification of two existent subnets for the dual-stack scenario.
@@ -181,7 +191,7 @@ In v1alpha8, this will be automatically converted to:
When subnets are not specified on `OpenStackCluster` and only the network is, the network is used to identify the subnets to use. If more than two subnets exist in the network, the user must specify which ones to use by defining the `OpenStackCluster.Spec.Subnets` field.
-#### ⚠️ Change to nodeCidr and dnsNameservers
+#### Change to nodeCidr and dnsNameservers
In v1alpha8, `OpenStackCluster.Spec.ManagedSubnets` array field is introduced. The `NodeCIDR` and `DNSNameservers` fields of `OpenStackCluster.Spec` are moved into that structure (renaming `NodeCIDR` to `CIDR`). For example:
@@ -200,7 +210,7 @@ In v1alpha8, this will be automatically converted to:
Please note that currently `managedSubnets` can only hold one element.
-#### ⚠️ Change to managedSecurityGroups
+#### Change to managedSecurityGroups
The field `managedSecurityGroups` is now a pointer to a `ManagedSecurityGroups` object rather than a boolean.
@@ -252,7 +262,7 @@ managedSecurityGroups:
description: "Allow BGP between control plane and workers"
```
-#### ⚠️ Calico CNI
+#### Calico CNI
Historically we used to create the necessary security group rules for Calico CNI to work. This is no longer the case.
Now the user needs to request creation of the security group rules by using the `managedSecurityGroups.allNodesSecurityGroupRules` feature.
@@ -260,6 +270,6 @@ Now the user needs to request creation of the security group rules by using the
Note that when upgrading from a previous version, the Calico CNI security group rules will be added automatically to
allow backwards compatibility if `allowAllInClusterTraffic` is set to false.
-#### ⚠️ Change to network
+#### Change to network
In v1alpha8, when the `OpenStackCluster.Spec.Network` is not defined, the `Subnets` are now used to identify the `Network`.
diff --git a/kustomize/v1alpha8/default/cluster-template.yaml b/kustomize/v1alpha8/default/cluster-template.yaml
index c7554d7d7c..cdee2550fc 100644
--- a/kustomize/v1alpha8/default/cluster-template.yaml
+++ b/kustomize/v1alpha8/default/cluster-template.yaml
@@ -25,7 +25,6 @@ spec:
cloudName: ${OPENSTACK_CLOUD}
identityRef:
name: ${CLUSTER_NAME}-cloud-config
- kind: Secret
apiServerLoadBalancer:
enabled: true
managedSubnets:
@@ -103,7 +102,6 @@ spec:
cloudName: ${OPENSTACK_CLOUD}
identityRef:
name: ${CLUSTER_NAME}-cloud-config
- kind: Secret
---
apiVersion: cluster.x-k8s.io/v1beta1
kind: MachineDeployment
@@ -139,7 +137,6 @@ spec:
cloudName: ${OPENSTACK_CLOUD}
identityRef:
name: ${CLUSTER_NAME}-cloud-config
- kind: Secret
flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR}
image:
name: ${OPENSTACK_IMAGE_NAME}
diff --git a/templates/cluster-template-flatcar-sysext.yaml b/templates/cluster-template-flatcar-sysext.yaml
index ca02b3c639..0cdd02dc0e 100644
--- a/templates/cluster-template-flatcar-sysext.yaml
+++ b/templates/cluster-template-flatcar-sysext.yaml
@@ -228,7 +228,6 @@ spec:
externalNetwork:
id: ${OPENSTACK_EXTERNAL_NETWORK_ID}
identityRef:
- kind: Secret
name: ${CLUSTER_NAME}-cloud-config
managedSecurityGroups:
allNodesSecurityGroupRules:
@@ -265,7 +264,6 @@ spec:
cloudName: ${OPENSTACK_CLOUD}
flavor: ${OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR}
identityRef:
- kind: Secret
name: ${CLUSTER_NAME}-cloud-config
image:
name: ${FLATCAR_IMAGE_NAME}
@@ -281,7 +279,6 @@ spec:
cloudName: ${OPENSTACK_CLOUD}
flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR}
identityRef:
- kind: Secret
name: ${CLUSTER_NAME}-cloud-config
image:
name: ${FLATCAR_IMAGE_NAME}
diff --git a/templates/cluster-template-flatcar.yaml b/templates/cluster-template-flatcar.yaml
index c2cfdc6934..535a177fcd 100644
--- a/templates/cluster-template-flatcar.yaml
+++ b/templates/cluster-template-flatcar.yaml
@@ -152,7 +152,6 @@ spec:
externalNetwork:
id: ${OPENSTACK_EXTERNAL_NETWORK_ID}
identityRef:
- kind: Secret
name: ${CLUSTER_NAME}-cloud-config
managedSecurityGroups:
allNodesSecurityGroupRules:
@@ -189,7 +188,6 @@ spec:
cloudName: ${OPENSTACK_CLOUD}
flavor: ${OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR}
identityRef:
- kind: Secret
name: ${CLUSTER_NAME}-cloud-config
image:
name: ${OPENSTACK_FLATCAR_IMAGE_NAME}
@@ -205,7 +203,6 @@ spec:
cloudName: ${OPENSTACK_CLOUD}
flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR}
identityRef:
- kind: Secret
name: ${CLUSTER_NAME}-cloud-config
image:
name: ${OPENSTACK_FLATCAR_IMAGE_NAME}
diff --git a/templates/cluster-template-without-lb.yaml b/templates/cluster-template-without-lb.yaml
index 2b206b65cd..6b3e402d4f 100644
--- a/templates/cluster-template-without-lb.yaml
+++ b/templates/cluster-template-without-lb.yaml
@@ -109,7 +109,6 @@ spec:
externalNetwork:
id: ${OPENSTACK_EXTERNAL_NETWORK_ID}
identityRef:
- kind: Secret
name: ${CLUSTER_NAME}-cloud-config
managedSecurityGroups:
allNodesSecurityGroupRules:
@@ -146,7 +145,6 @@ spec:
cloudName: ${OPENSTACK_CLOUD}
flavor: ${OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR}
identityRef:
- kind: Secret
name: ${CLUSTER_NAME}-cloud-config
image:
name: ${OPENSTACK_IMAGE_NAME}
@@ -162,7 +160,6 @@ spec:
cloudName: ${OPENSTACK_CLOUD}
flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR}
identityRef:
- kind: Secret
name: ${CLUSTER_NAME}-cloud-config
image:
name: ${OPENSTACK_IMAGE_NAME}
diff --git a/templates/cluster-template.yaml b/templates/cluster-template.yaml
index e2b1ff52db..f3886fc8ec 100644
--- a/templates/cluster-template.yaml
+++ b/templates/cluster-template.yaml
@@ -111,7 +111,6 @@ spec:
externalNetwork:
id: ${OPENSTACK_EXTERNAL_NETWORK_ID}
identityRef:
- kind: Secret
name: ${CLUSTER_NAME}-cloud-config
managedSecurityGroups:
allNodesSecurityGroupRules:
@@ -148,7 +147,6 @@ spec:
cloudName: ${OPENSTACK_CLOUD}
flavor: ${OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR}
identityRef:
- kind: Secret
name: ${CLUSTER_NAME}-cloud-config
image:
name: ${OPENSTACK_IMAGE_NAME}
@@ -164,7 +162,6 @@ spec:
cloudName: ${OPENSTACK_CLOUD}
flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR}
identityRef:
- kind: Secret
name: ${CLUSTER_NAME}-cloud-config
image:
name: ${OPENSTACK_IMAGE_NAME}
diff --git a/templates/clusterclass-dev-test.yaml b/templates/clusterclass-dev-test.yaml
index 4112633624..a73e07dd3b 100644
--- a/templates/clusterclass-dev-test.yaml
+++ b/templates/clusterclass-dev-test.yaml
@@ -119,7 +119,6 @@ spec:
enabled: true
cloudName: ${OPENSTACK_CLOUD:=capo-e2e}
identityRef:
- kind: Secret
name: dev-test-cloud-config
managedSecurityGroups:
allNodesSecurityGroupRules:
@@ -156,7 +155,6 @@ spec:
cloudName: ${OPENSTACK_CLOUD:=capo-e2e}
flavor: ${OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR:=m1.medium}
identityRef:
- kind: Secret
name: dev-test-cloud-config
image:
name: overridden-by-patch
@@ -172,7 +170,6 @@ spec:
cloudName: ${OPENSTACK_CLOUD:=capo-e2e}
flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR:=m1.small}
identityRef:
- kind: Secret
name: dev-test-cloud-config
image:
name: overridden-by-patch
diff --git a/test/e2e/data/kustomize/k8s-upgrade/upgrade-from-template.yaml b/test/e2e/data/kustomize/k8s-upgrade/upgrade-from-template.yaml
index 339b52535a..60136e0823 100644
--- a/test/e2e/data/kustomize/k8s-upgrade/upgrade-from-template.yaml
+++ b/test/e2e/data/kustomize/k8s-upgrade/upgrade-from-template.yaml
@@ -9,7 +9,6 @@ spec:
cloudName: ${OPENSTACK_CLOUD}
flavor: ${OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR}
identityRef:
- kind: Secret
name: ${CLUSTER_NAME}-cloud-config
image:
name: ${OPENSTACK_IMAGE_NAME_UPGRADE_FROM}
@@ -27,7 +26,6 @@ spec:
cloudName: ${OPENSTACK_CLOUD}
flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR}
identityRef:
- kind: Secret
name: ${CLUSTER_NAME}-cloud-config
image:
name: ${OPENSTACK_IMAGE_NAME_UPGRADE_FROM}
diff --git a/test/e2e/data/kustomize/k8s-upgrade/upgrade-to-template.yaml b/test/e2e/data/kustomize/k8s-upgrade/upgrade-to-template.yaml
index 6e426d14a5..b8e499e42c 100644
--- a/test/e2e/data/kustomize/k8s-upgrade/upgrade-to-template.yaml
+++ b/test/e2e/data/kustomize/k8s-upgrade/upgrade-to-template.yaml
@@ -16,7 +16,6 @@ spec:
cloudName: ${OPENSTACK_CLOUD}
flavor: ${OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR}
identityRef:
- kind: Secret
name: ${CLUSTER_NAME}-cloud-config
image:
name: ${OPENSTACK_IMAGE_NAME}
@@ -36,7 +35,6 @@ spec:
cloudName: ${OPENSTACK_CLOUD}
flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR}
identityRef:
- kind: Secret
name: ${CLUSTER_NAME}-cloud-config
image:
name: ${OPENSTACK_IMAGE_NAME}
diff --git a/test/e2e/suites/e2e/e2e_test.go b/test/e2e/suites/e2e/e2e_test.go
index f4b92c9a42..3ba40942f7 100644
--- a/test/e2e/suites/e2e/e2e_test.go
+++ b/test/e2e/suites/e2e/e2e_test.go
@@ -785,7 +785,6 @@ func makeOpenStackMachineTemplate(namespace, clusterName, name string) *infrav1.
SSHKeyName: shared.DefaultSSHKeyPairName,
CloudName: e2eCtx.E2EConfig.GetVariable(shared.OpenStackCloud),
IdentityRef: &infrav1.OpenStackIdentityReference{
- Kind: "Secret",
Name: fmt.Sprintf("%s-cloud-config", clusterName),
},
},
@@ -810,7 +809,6 @@ func makeOpenStackMachineTemplateWithPortOptions(namespace, clusterName, name st
SSHKeyName: shared.DefaultSSHKeyPairName,
CloudName: e2eCtx.E2EConfig.GetVariable(shared.OpenStackCloud),
IdentityRef: &infrav1.OpenStackIdentityReference{
- Kind: "Secret",
Name: fmt.Sprintf("%s-cloud-config", clusterName),
},
Ports: *portOpts,
From ccfcb5996a21b1e8029f402747196a645ce6a49a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20Dulko?=
Date: Tue, 30 Jan 2024 18:25:15 +0100
Subject: [PATCH 077/180] Add support to set `allocation_pools` for subnet
This commit adds API that allows users to set `allocations_pools` in the
subnet created by CAPO. This allows the users to restrict the IP address
ranges that will be allocated automatically by OpenStack when creating
Machines.
Users can utilize this to reserve addresses for VIPs (virtual IPs) or
special nodes that will have predefined addresses and will be created
later.
---
api/v1alpha6/conversion.go | 10 +
api/v1alpha6/conversion_test.go | 13 +
api/v1alpha7/conversion_test.go | 13 +
api/v1alpha8/types.go | 16 ++
api/v1alpha8/zz_generated.deepcopy.go | 20 ++
...re.cluster.x-k8s.io_openstackclusters.yaml | 20 ++
...er.x-k8s.io_openstackclustertemplates.yaml | 21 ++
.../crd-changes/v1alpha7-to-v1alpha8.md | 4 +
pkg/cloud/services/networking/network.go | 4 +
pkg/cloud/services/networking/network_test.go | 260 ++++++++++++++++++
10 files changed, 381 insertions(+)
diff --git a/api/v1alpha6/conversion.go b/api/v1alpha6/conversion.go
index 21e6e4f325..6168353c23 100644
--- a/api/v1alpha6/conversion.go
+++ b/api/v1alpha6/conversion.go
@@ -232,6 +232,11 @@ var v1alpha8OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStack
},
restorev1alpha8ClusterStatus,
),
+ "managedSubnets": conversion.UnconditionalFieldRestorer(
+ func(c *infrav1.OpenStackCluster) *[]infrav1.SubnetSpec {
+ return &c.Spec.ManagedSubnets
+ },
+ ),
}
func (r *OpenStackCluster) ConvertTo(dstRaw ctrlconversion.Hub) error {
@@ -322,6 +327,11 @@ var v1alpha8OpenStackClusterTemplateRestorer = conversion.RestorerFor[*infrav1.O
},
restorev1alpha8ManagedSecurityGroups,
),
+ "managedSubnets": conversion.UnconditionalFieldRestorer(
+ func(c *infrav1.OpenStackClusterTemplate) *[]infrav1.SubnetSpec {
+ return &c.Spec.Template.Spec.ManagedSubnets
+ },
+ ),
}
func (r *OpenStackClusterTemplate) ConvertTo(dstRaw ctrlconversion.Hub) error {
diff --git a/api/v1alpha6/conversion_test.go b/api/v1alpha6/conversion_test.go
index 77f5c4de76..d457f48e06 100644
--- a/api/v1alpha6/conversion_test.go
+++ b/api/v1alpha6/conversion_test.go
@@ -142,6 +142,19 @@ func TestFuzzyConversion(t *testing.T) {
spec.CIDR = c.RandString()
}
},
+
+ func(pool *infrav1.AllocationPool, c fuzz.Continue) {
+ c.FuzzNoCustom(pool)
+
+ // Start and End are required properties, let's make sure both are set
+ for pool.Start == "" {
+ pool.Start = c.RandString()
+ }
+
+ for pool.End == "" {
+ pool.End = c.RandString()
+ }
+ },
}
}
diff --git a/api/v1alpha7/conversion_test.go b/api/v1alpha7/conversion_test.go
index f3c2338e70..7487eedaa0 100644
--- a/api/v1alpha7/conversion_test.go
+++ b/api/v1alpha7/conversion_test.go
@@ -110,6 +110,19 @@ func TestFuzzyConversion(t *testing.T) {
spec.CIDR = c.RandString()
}
},
+
+ func(pool *infrav1.AllocationPool, c fuzz.Continue) {
+ c.FuzzNoCustom(pool)
+
+ // Start and End are required properties, let's make sure both are set
+ for pool.Start == "" {
+ pool.Start = c.RandString()
+ }
+
+ for pool.End == "" {
+ pool.End = c.RandString()
+ }
+ },
}
}
diff --git a/api/v1alpha8/types.go b/api/v1alpha8/types.go
index 8c206d803d..f47a9ba6ca 100644
--- a/api/v1alpha8/types.go
+++ b/api/v1alpha8/types.go
@@ -92,9 +92,25 @@ type SubnetSpec struct {
// 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 {
diff --git a/api/v1alpha8/zz_generated.deepcopy.go b/api/v1alpha8/zz_generated.deepcopy.go
index 2b52b02cd2..01aa5b7698 100644
--- a/api/v1alpha8/zz_generated.deepcopy.go
+++ b/api/v1alpha8/zz_generated.deepcopy.go
@@ -83,6 +83,21 @@ 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
@@ -1248,6 +1263,11 @@ func (in *SubnetSpec) DeepCopyInto(out *SubnetSpec) {
*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.
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 bdf1340bbe..c8e8b86013 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -5537,6 +5537,26 @@ spec:
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.
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 5624a26977..629284730c 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -2972,6 +2972,27 @@ spec:
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.
diff --git a/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md b/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md
index 8b929c1ea2..8ea68de168 100644
--- a/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md
+++ b/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md
@@ -210,6 +210,10 @@ In v1alpha8, this will be automatically converted to:
Please note that currently `managedSubnets` can only hold one element.
+#### Addition of allocationPools
+
+In v1alpha8, an `AllocationPools` property is introduced to `OpenStackCluster.Spec.ManagedSubnets`. When specified, OpenStack subnet created by CAPO will have the given values set as the `allocation_pools` property. This allows users to make sure OpenStack will not allocate some IP ranges in the subnet automatically. If the subnet is precreated and configured, CAPO will ignore `AllocationPools` property.
+
#### Change to managedSecurityGroups
The field `managedSecurityGroups` is now a pointer to a `ManagedSecurityGroups` object rather than a boolean.
diff --git a/pkg/cloud/services/networking/network.go b/pkg/cloud/services/networking/network.go
index 7629abdee8..18c79d9433 100644
--- a/pkg/cloud/services/networking/network.go
+++ b/pkg/cloud/services/networking/network.go
@@ -256,6 +256,10 @@ func (s *Service) createSubnet(openStackCluster *infrav1.OpenStackCluster, clust
Description: names.GetDescription(clusterName),
}
+ for _, pool := range openStackCluster.Spec.ManagedSubnets[0].AllocationPools {
+ opts.AllocationPools = append(opts.AllocationPools, subnets.AllocationPool{Start: pool.Start, End: pool.End})
+ }
+
subnet, err := s.client.CreateSubnet(opts)
if err != nil {
record.Warnf(openStackCluster, "FailedCreateSubnet", "Failed to create subnet %s: %v", name, err)
diff --git a/pkg/cloud/services/networking/network_test.go b/pkg/cloud/services/networking/network_test.go
index 47ff27783a..f1c351fc8a 100644
--- a/pkg/cloud/services/networking/network_test.go
+++ b/pkg/cloud/services/networking/network_test.go
@@ -24,12 +24,14 @@ import (
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external"
"github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
. "github.com/onsi/gomega"
"k8s.io/utils/pointer"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/mock"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
+ "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/names"
)
func Test_ReconcileNetwork(t *testing.T) {
@@ -420,3 +422,261 @@ func Test_ReconcileExternalNetwork(t *testing.T) {
})
}
}
+
+func Test_ReconcileSubnet(t *testing.T) {
+ mockCtrl := gomock.NewController(t)
+ defer mockCtrl.Finish()
+
+ clusterName := "test-cluster"
+ expectedSubnetName := getSubnetName(clusterName)
+ expectedSubnetDesc := names.GetDescription(clusterName)
+ fakeSubnetID := "d08803fc-2fa5-4179-b9d7-8c43d0af2fe6"
+ fakeCIDR := "10.0.0.0/24"
+ fakeNetworkID := "d08803fc-2fa5-4279-b9f7-8c45d0ff2fe6"
+ fakeDNS := "10.0.10.200"
+
+ tests := []struct {
+ name string
+ openStackCluster *infrav1.OpenStackCluster
+ expect func(m *mock.MockNetworkClientMockRecorder)
+ want *infrav1.OpenStackClusterStatus
+ }{
+ {
+ name: "ensures status set when reconciling an existing subnet",
+ openStackCluster: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ ManagedSubnets: []infrav1.SubnetSpec{
+ {
+ CIDR: fakeCIDR,
+ },
+ },
+ },
+ Status: infrav1.OpenStackClusterStatus{
+ Network: &infrav1.NetworkStatusWithSubnets{
+ NetworkStatus: infrav1.NetworkStatus{
+ ID: fakeNetworkID,
+ },
+ },
+ },
+ },
+ expect: func(m *mock.MockNetworkClientMockRecorder) {
+ m.
+ ListSubnet(subnets.ListOpts{NetworkID: fakeNetworkID, CIDR: fakeCIDR}).
+ Return([]subnets.Subnet{
+ {
+ ID: fakeSubnetID,
+ Name: expectedSubnetName,
+ CIDR: fakeCIDR,
+ },
+ }, nil)
+ },
+ want: &infrav1.OpenStackClusterStatus{
+ Network: &infrav1.NetworkStatusWithSubnets{
+ NetworkStatus: infrav1.NetworkStatus{
+ ID: fakeNetworkID,
+ },
+ Subnets: []infrav1.Subnet{
+ {
+ Name: expectedSubnetName,
+ ID: fakeSubnetID,
+ CIDR: fakeCIDR,
+ },
+ },
+ },
+ },
+ },
+ {
+ name: "creation without any parameter",
+ openStackCluster: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ ManagedSubnets: []infrav1.SubnetSpec{
+ {
+ CIDR: fakeCIDR,
+ },
+ },
+ },
+ Status: infrav1.OpenStackClusterStatus{
+ Network: &infrav1.NetworkStatusWithSubnets{
+ NetworkStatus: infrav1.NetworkStatus{
+ ID: fakeNetworkID,
+ },
+ },
+ },
+ },
+ expect: func(m *mock.MockNetworkClientMockRecorder) {
+ m.
+ ListSubnet(subnets.ListOpts{NetworkID: fakeNetworkID, CIDR: fakeCIDR}).
+ Return([]subnets.Subnet{}, nil)
+
+ m.
+ CreateSubnet(subnets.CreateOpts{
+ NetworkID: fakeNetworkID,
+ Name: expectedSubnetName,
+ IPVersion: 4,
+ CIDR: fakeCIDR,
+ Description: expectedSubnetDesc,
+ }).
+ Return(&subnets.Subnet{
+ ID: fakeSubnetID,
+ Name: expectedSubnetName,
+ CIDR: fakeCIDR,
+ }, nil)
+ },
+ want: &infrav1.OpenStackClusterStatus{
+ Network: &infrav1.NetworkStatusWithSubnets{
+ NetworkStatus: infrav1.NetworkStatus{
+ ID: fakeNetworkID,
+ },
+ Subnets: []infrav1.Subnet{
+ {
+ Name: expectedSubnetName,
+ ID: fakeSubnetID,
+ CIDR: fakeCIDR,
+ },
+ },
+ },
+ },
+ },
+ {
+ name: "creation with DNSNameservers",
+ openStackCluster: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ ManagedSubnets: []infrav1.SubnetSpec{
+ {
+ CIDR: fakeCIDR,
+ DNSNameservers: []string{fakeDNS},
+ },
+ },
+ },
+ Status: infrav1.OpenStackClusterStatus{
+ Network: &infrav1.NetworkStatusWithSubnets{
+ NetworkStatus: infrav1.NetworkStatus{
+ ID: fakeNetworkID,
+ },
+ },
+ },
+ },
+ expect: func(m *mock.MockNetworkClientMockRecorder) {
+ m.
+ ListSubnet(subnets.ListOpts{NetworkID: fakeNetworkID, CIDR: fakeCIDR}).
+ Return([]subnets.Subnet{}, nil)
+
+ m.
+ CreateSubnet(subnets.CreateOpts{
+ NetworkID: fakeNetworkID,
+ Name: expectedSubnetName,
+ IPVersion: 4,
+ CIDR: fakeCIDR,
+ Description: expectedSubnetDesc,
+ DNSNameservers: []string{fakeDNS},
+ }).
+ Return(&subnets.Subnet{
+ ID: fakeSubnetID,
+ Name: expectedSubnetName,
+ CIDR: fakeCIDR,
+ }, nil)
+ },
+ want: &infrav1.OpenStackClusterStatus{
+ Network: &infrav1.NetworkStatusWithSubnets{
+ NetworkStatus: infrav1.NetworkStatus{
+ ID: fakeNetworkID,
+ },
+ Subnets: []infrav1.Subnet{
+ {
+ Name: expectedSubnetName,
+ ID: fakeSubnetID,
+ CIDR: fakeCIDR,
+ },
+ },
+ },
+ },
+ },
+ {
+ name: "creation with allocationPools",
+ openStackCluster: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ ManagedSubnets: []infrav1.SubnetSpec{
+ {
+ CIDR: fakeCIDR,
+ AllocationPools: []infrav1.AllocationPool{
+ {
+ Start: "10.0.0.1",
+ End: "10.0.0.10",
+ },
+ {
+ Start: "10.0.0.20",
+ End: "10.0.0.254",
+ },
+ },
+ },
+ },
+ },
+ Status: infrav1.OpenStackClusterStatus{
+ Network: &infrav1.NetworkStatusWithSubnets{
+ NetworkStatus: infrav1.NetworkStatus{
+ ID: fakeNetworkID,
+ },
+ },
+ },
+ },
+ expect: func(m *mock.MockNetworkClientMockRecorder) {
+ m.
+ ListSubnet(subnets.ListOpts{NetworkID: fakeNetworkID, CIDR: fakeCIDR}).
+ Return([]subnets.Subnet{}, nil)
+
+ m.
+ CreateSubnet(subnets.CreateOpts{
+ NetworkID: fakeNetworkID,
+ Name: expectedSubnetName,
+ IPVersion: 4,
+ CIDR: fakeCIDR,
+ Description: expectedSubnetDesc,
+ AllocationPools: []subnets.AllocationPool{
+ {
+ Start: "10.0.0.1",
+ End: "10.0.0.10",
+ },
+ {
+ Start: "10.0.0.20",
+ End: "10.0.0.254",
+ },
+ },
+ }).
+ Return(&subnets.Subnet{
+ ID: fakeSubnetID,
+ Name: expectedSubnetName,
+ CIDR: fakeCIDR,
+ }, nil)
+ },
+ want: &infrav1.OpenStackClusterStatus{
+ Network: &infrav1.NetworkStatusWithSubnets{
+ NetworkStatus: infrav1.NetworkStatus{
+ ID: fakeNetworkID,
+ },
+ Subnets: []infrav1.Subnet{
+ {
+ Name: expectedSubnetName,
+ ID: fakeSubnetID,
+ CIDR: fakeCIDR,
+ },
+ },
+ },
+ },
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ g := NewWithT(t)
+ mockClient := mock.NewMockNetworkClient(mockCtrl)
+ tt.expect(mockClient.EXPECT())
+ s := Service{
+ client: mockClient,
+ scope: scope.NewMockScopeFactory(mockCtrl, "", logr.Discard()),
+ }
+ err := s.ReconcileSubnet(tt.openStackCluster, clusterName)
+ g.Expect(err).ShouldNot(HaveOccurred())
+ g.Expect(tt.openStackCluster.Status).To(Equal(*tt.want))
+ })
+ }
+}
From 7ec4c14aa254748e298a59d1623d700fccf39519 Mon Sep 17 00:00:00 2001
From: Emilien Macchi
Date: Mon, 11 Dec 2023 12:43:42 -0500
Subject: [PATCH 078/180] Move ports management outside of instances
---
api/v1alpha5/conversion_test.go | 2 +-
api/v1alpha5/zz_generated.conversion.go | 1 +
api/v1alpha6/conversion.go | 17 +-
api/v1alpha6/zz_generated.conversion.go | 1 +
api/v1alpha7/conversion.go | 15 +-
api/v1alpha7/zz_generated.conversion.go | 17 +-
api/v1alpha8/openstackmachine_types.go | 3 +
api/v1alpha8/types.go | 17 +
api/v1alpha8/zz_generated.deepcopy.go | 50 +-
...re.cluster.x-k8s.io_openstackclusters.yaml | 205 ++++++
...re.cluster.x-k8s.io_openstackmachines.yaml | 206 ++++++
controllers/openstackcluster_controller.go | 144 +++-
.../openstackcluster_controller_test.go | 182 ++++-
controllers/openstackmachine_controller.go | 140 +++-
.../openstackmachine_controller_test.go | 252 +++++++
controllers/suite_test.go | 6 +-
.../services/compute/dependent_resources.go | 45 ++
.../compute/dependent_resources_test.go | 217 ++++++
pkg/cloud/services/compute/instance.go | 327 +--------
pkg/cloud/services/compute/instance_test.go | 637 +-----------------
.../services/compute/referenced_resources.go | 45 +-
.../compute/referenced_resources_test.go | 70 +-
pkg/cloud/services/networking/port.go | 394 +++++++++--
pkg/cloud/services/networking/port_test.go | 629 ++++++++++++-----
.../services/networking/securitygroups.go | 10 +-
25 files changed, 2350 insertions(+), 1282 deletions(-)
create mode 100644 pkg/cloud/services/compute/dependent_resources.go
create mode 100644 pkg/cloud/services/compute/dependent_resources_test.go
diff --git a/api/v1alpha5/conversion_test.go b/api/v1alpha5/conversion_test.go
index 480471b3c6..8848d47379 100644
--- a/api/v1alpha5/conversion_test.go
+++ b/api/v1alpha5/conversion_test.go
@@ -79,7 +79,7 @@ func TestConvertFrom(t *testing.T) {
Spec: OpenStackMachineSpec{},
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
- "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"cloudName\":\"\",\"flavor\":\"\",\"image\":{}},\"status\":{\"ready\":false,\"referencedResources\":{}}}",
+ "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"cloudName\":\"\",\"flavor\":\"\",\"image\":{}},\"status\":{\"dependentResources\":{},\"ready\":false,\"referencedResources\":{}}}",
},
},
},
diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go
index bdf6402b6d..0e9c9315b8 100644
--- a/api/v1alpha5/zz_generated.conversion.go
+++ b/api/v1alpha5/zz_generated.conversion.go
@@ -1204,6 +1204,7 @@ func autoConvert_v1alpha8_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineSta
out.Addresses = *(*[]v1.NodeAddress)(unsafe.Pointer(&in.Addresses))
out.InstanceState = (*InstanceState)(unsafe.Pointer(in.InstanceState))
// WARNING: in.ReferencedResources requires manual conversion: does not exist in peer-type
+ // WARNING: in.DependentResources 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))
diff --git a/api/v1alpha6/conversion.go b/api/v1alpha6/conversion.go
index 21e6e4f325..8a1025c57c 100644
--- a/api/v1alpha6/conversion.go
+++ b/api/v1alpha6/conversion.go
@@ -125,13 +125,16 @@ func restorev1alpha8ClusterStatus(previous *infrav1.OpenStackClusterStatus, dst
dst.Network = nil
}
- if previous.Bastion != nil {
- dst.Bastion.ReferencedResources = previous.Bastion.ReferencedResources
- }
-
dst.ControlPlaneSecurityGroup = previous.ControlPlaneSecurityGroup
dst.WorkerSecurityGroup = previous.WorkerSecurityGroup
dst.BastionSecurityGroup = previous.BastionSecurityGroup
+
+ if previous.Bastion != nil {
+ dst.Bastion.ReferencedResources = previous.Bastion.ReferencedResources
+ }
+ if previous.Bastion != nil && previous.Bastion.DependentResources.PortsStatus != nil {
+ dst.Bastion.DependentResources.PortsStatus = previous.Bastion.DependentResources.PortsStatus
+ }
}
func restorev1alpha6ClusterSpec(previous *OpenStackClusterSpec, dst *OpenStackClusterSpec) {
@@ -375,7 +378,11 @@ var v1alpha8OpenStackMachineRestorer = conversion.RestorerFor[*infrav1.OpenStack
},
restorev1alpha8MachineSpec,
),
-
+ "depresources": conversion.UnconditionalFieldRestorer(
+ func(c *infrav1.OpenStackMachine) *infrav1.DependentMachineResources {
+ return &c.Status.DependentResources
+ },
+ ),
// No equivalent in v1alpha6
"refresources": conversion.UnconditionalFieldRestorer(
func(c *infrav1.OpenStackMachine) *infrav1.ReferencedMachineResources {
diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go
index a9d397034d..2bda83e05c 100644
--- a/api/v1alpha6/zz_generated.conversion.go
+++ b/api/v1alpha6/zz_generated.conversion.go
@@ -1227,6 +1227,7 @@ func autoConvert_v1alpha8_OpenStackMachineStatus_To_v1alpha6_OpenStackMachineSta
out.Addresses = *(*[]v1.NodeAddress)(unsafe.Pointer(&in.Addresses))
out.InstanceState = (*InstanceState)(unsafe.Pointer(in.InstanceState))
// WARNING: in.ReferencedResources requires manual conversion: does not exist in peer-type
+ // WARNING: in.DependentResources 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))
diff --git a/api/v1alpha7/conversion.go b/api/v1alpha7/conversion.go
index cefd794c0b..cc0e62756f 100644
--- a/api/v1alpha7/conversion.go
+++ b/api/v1alpha7/conversion.go
@@ -121,9 +121,13 @@ func restorev1alpha8ClusterStatus(previous *infrav1.OpenStackClusterStatus, dst
restorev1alpha8SecurityGroupStatus(previous.BastionSecurityGroup, dst.BastionSecurityGroup)
// ReferencedResources have no equivalent in v1alpha7
- if dst.Bastion != nil {
+ if previous.Bastion != nil {
dst.Bastion.ReferencedResources = previous.Bastion.ReferencedResources
}
+
+ if previous.Bastion != nil && previous.Bastion.DependentResources.PortsStatus != nil {
+ dst.Bastion.DependentResources.PortsStatus = previous.Bastion.DependentResources.PortsStatus
+ }
}
var v1alpha8OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStackCluster]{
@@ -349,6 +353,11 @@ var v1alpha8OpenStackMachineRestorer = conversion.RestorerFor[*infrav1.OpenStack
},
restorev1alpha8MachineSpec,
),
+ "depresources": conversion.UnconditionalFieldRestorer(
+ func(c *infrav1.OpenStackMachine) *infrav1.DependentMachineResources {
+ return &c.Status.DependentResources
+ },
+ ),
// No equivalent in v1alpha7
"refresources": conversion.UnconditionalFieldRestorer(
@@ -688,3 +697,7 @@ func Convert_v1alpha7_SecurityGroup_To_v1alpha8_SecurityGroupStatus(in *Security
func Convert_v1alpha7_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(in *OpenStackIdentityReference, out *infrav1.OpenStackIdentityReference, s apiconversion.Scope) error {
return autoConvert_v1alpha7_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(in, out, s)
}
+
+func Convert_v1alpha8_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(in *infrav1.OpenStackClusterStatus, out *OpenStackClusterStatus, s apiconversion.Scope) error {
+ return autoConvert_v1alpha8_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(in, out, s)
+}
diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go
index fa7abe3520..1eae94c731 100644
--- a/api/v1alpha7/zz_generated.conversion.go
+++ b/api/v1alpha7/zz_generated.conversion.go
@@ -189,11 +189,6 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*v1alpha8.OpenStackClusterStatus)(nil), (*OpenStackClusterStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(a.(*v1alpha8.OpenStackClusterStatus), b.(*OpenStackClusterStatus), scope)
- }); err != nil {
- return err
- }
if err := s.AddGeneratedConversionFunc((*OpenStackClusterTemplate)(nil), (*v1alpha8.OpenStackClusterTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha7_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate(a.(*OpenStackClusterTemplate), b.(*v1alpha8.OpenStackClusterTemplate), scope)
}); err != nil {
@@ -424,6 +419,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
+ if err := s.AddConversionFunc((*v1alpha8.OpenStackClusterStatus)(nil), (*OpenStackClusterStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha8_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(a.(*v1alpha8.OpenStackClusterStatus), b.(*OpenStackClusterStatus), scope)
+ }); err != nil {
+ return err
+ }
if err := s.AddConversionFunc((*v1alpha8.OpenStackMachineSpec)(nil), (*OpenStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(a.(*v1alpha8.OpenStackMachineSpec), b.(*OpenStackMachineSpec), scope)
}); err != nil {
@@ -560,6 +560,7 @@ func autoConvert_v1alpha8_BastionStatus_To_v1alpha7_BastionStatus(in *v1alpha8.B
out.IP = in.IP
out.FloatingIP = in.FloatingIP
// WARNING: in.ReferencedResources requires manual conversion: does not exist in peer-type
+ // WARNING: in.DependentResources requires manual conversion: does not exist in peer-type
return nil
}
@@ -1059,11 +1060,6 @@ func autoConvert_v1alpha8_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterSta
return nil
}
-// Convert_v1alpha8_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(in *v1alpha8.OpenStackClusterStatus, out *OpenStackClusterStatus, s conversion.Scope) error {
- return autoConvert_v1alpha8_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(in, out, s)
-}
-
func autoConvert_v1alpha7_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate(in *OpenStackClusterTemplate, out *v1alpha8.OpenStackClusterTemplate, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
if err := Convert_v1alpha7_OpenStackClusterTemplateSpec_To_v1alpha8_OpenStackClusterTemplateSpec(&in.Spec, &out.Spec, s); err != nil {
@@ -1348,6 +1344,7 @@ func autoConvert_v1alpha8_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineSta
out.Addresses = *(*[]v1.NodeAddress)(unsafe.Pointer(&in.Addresses))
out.InstanceState = (*InstanceState)(unsafe.Pointer(in.InstanceState))
// WARNING: in.ReferencedResources requires manual conversion: does not exist in peer-type
+ // WARNING: in.DependentResources 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))
diff --git a/api/v1alpha8/openstackmachine_types.go b/api/v1alpha8/openstackmachine_types.go
index bc98e02a98..b8c03d7b6c 100644
--- a/api/v1alpha8/openstackmachine_types.go
+++ b/api/v1alpha8/openstackmachine_types.go
@@ -119,6 +119,9 @@ type OpenStackMachineStatus struct {
// ReferencedResources contains resolved references to resources that the machine depends on.
ReferencedResources ReferencedMachineResources `json:"referencedResources,omitempty"`
+ // DependentResources contains resolved dependent resources that were created by the machine.
+ DependentResources DependentMachineResources `json:"dependentResources,omitempty"`
+
FailureReason *errors.MachineStatusError `json:"failureReason,omitempty"`
// FailureMessage will be set in the event that there is a terminal problem
diff --git a/api/v1alpha8/types.go b/api/v1alpha8/types.go
index 8c206d803d..7cb290feb2 100644
--- a/api/v1alpha8/types.go
+++ b/api/v1alpha8/types.go
@@ -147,6 +147,12 @@ type PortOpts struct {
ValueSpecs []ValueSpec `json:"valueSpecs,omitempty"`
}
+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.
OVSHWOffload bool `json:"ovsHWOffload,omitempty"`
@@ -175,6 +181,7 @@ type BastionStatus struct {
IP string `json:"ip,omitempty"`
FloatingIP string `json:"floatingIP,omitempty"`
ReferencedResources ReferencedMachineResources `json:"referencedResources,omitempty"`
+ DependentResources DependentMachineResources `json:"dependentResources,omitempty"`
}
type RootVolume struct {
@@ -496,6 +503,16 @@ type ReferencedMachineResources struct {
// ImageID is the ID of the image to use for the machine and is calculated based on ImageFilter.
// +optional
ImageID string `json:"imageID,omitempty"`
+
+ // portsOpts is the list of ports options to create for the machine.
+ // +optional
+ PortsOpts []PortOpts `json:"portsOpts,omitempty"`
+}
+
+type DependentMachineResources struct {
+ // PortsStatus is the status of the ports created for the machine.
+ // +optional
+ PortsStatus []PortStatus `json:"portsStatus,omitempty"`
}
// ValueSpec represents a single value_spec key-value pair.
diff --git a/api/v1alpha8/zz_generated.deepcopy.go b/api/v1alpha8/zz_generated.deepcopy.go
index 2b52b02cd2..a6dfee64cb 100644
--- a/api/v1alpha8/zz_generated.deepcopy.go
+++ b/api/v1alpha8/zz_generated.deepcopy.go
@@ -102,7 +102,8 @@ 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
- out.ReferencedResources = in.ReferencedResources
+ in.ReferencedResources.DeepCopyInto(&out.ReferencedResources)
+ in.DependentResources.DeepCopyInto(&out.DependentResources)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BastionStatus.
@@ -165,6 +166,26 @@ func (in *BlockDeviceVolume) DeepCopy() *BlockDeviceVolume {
return out
}
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *DependentMachineResources) DeepCopyInto(out *DependentMachineResources) {
+ *out = *in
+ if in.PortsStatus != nil {
+ in, out := &in.PortsStatus, &out.PortsStatus
+ *out = make([]PortStatus, len(*in))
+ copy(*out, *in)
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DependentMachineResources.
+func (in *DependentMachineResources) DeepCopy() *DependentMachineResources {
+ if in == nil {
+ return nil
+ }
+ out := new(DependentMachineResources)
+ in.DeepCopyInto(out)
+ return out
+}
+
// 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
@@ -499,7 +520,7 @@ func (in *OpenStackClusterStatus) DeepCopyInto(out *OpenStackClusterStatus) {
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
@@ -775,7 +796,8 @@ func (in *OpenStackMachineStatus) DeepCopyInto(out *OpenStackMachineStatus) {
*out = new(InstanceState)
**out = **in
}
- out.ReferencedResources = in.ReferencedResources
+ in.ReferencedResources.DeepCopyInto(&out.ReferencedResources)
+ in.DependentResources.DeepCopyInto(&out.DependentResources)
if in.FailureReason != nil {
in, out := &in.FailureReason, &out.FailureReason
*out = new(errors.MachineStatusError)
@@ -963,9 +985,31 @@ func (in *PortOpts) DeepCopy() *PortOpts {
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 *ReferencedMachineResources) DeepCopyInto(out *ReferencedMachineResources) {
*out = *in
+ if in.PortsOpts != nil {
+ in, out := &in.PortsOpts, &out.PortsOpts
+ *out = make([]PortOpts, len(*in))
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReferencedMachineResources.
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 bdf1340bbe..d2ade078b3 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -5681,6 +5681,21 @@ spec:
type: object
bastion:
properties:
+ dependentResources:
+ properties:
+ portsStatus:
+ description: PortsStatus 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
floatingIP:
type: string
id:
@@ -5697,6 +5712,196 @@ spec:
description: ImageID is the ID of the image to use for the
machine and is calculated based on ImageFilter.
type: string
+ portsOpts:
+ description: portsOpts is the list of ports options to create
+ for the machine.
+ items:
+ properties:
+ adminStateUp:
+ type: boolean
+ allowedAddressPairs:
+ items:
+ properties:
+ ipAddress:
+ type: string
+ macAddress:
+ type: string
+ type: object
+ type: array
+ 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.
+ type: boolean
+ fixedIPs:
+ description: Specify pairs of subnet and/or IP address.
+ These should be subnets of the network with the given
+ NetworkID.
+ items:
+ properties:
+ 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.
+ properties:
+ cidr:
+ type: string
+ description:
+ type: string
+ gateway_ip:
+ type: string
+ id:
+ type: string
+ ipVersion:
+ type: integer
+ ipv6AddressMode:
+ type: string
+ ipv6RaMode:
+ type: string
+ name:
+ type: string
+ notTags:
+ type: string
+ notTagsAny:
+ type: string
+ projectId:
+ type: string
+ tags:
+ type: string
+ tagsAny:
+ type: string
+ type: object
+ required:
+ - subnet
+ type: object
+ type: array
+ hostId:
+ description: The ID of the host where the port is allocated
+ type: string
+ macAddress:
+ type: string
+ nameSuffix:
+ description: Used to make the name of the port unique.
+ 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.
+ properties:
+ description:
+ type: string
+ id:
+ type: string
+ name:
+ type: string
+ notTags:
+ type: string
+ notTagsAny:
+ type: string
+ projectId:
+ type: string
+ tags:
+ type: string
+ tagsAny:
+ 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
+ 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
+ securityGroupFilters:
+ description: The names, uuids, filters or any combination
+ these of the security groups to assign to the instance
+ items:
+ properties:
+ description:
+ type: string
+ id:
+ type: string
+ name:
+ type: string
+ notTags:
+ type: string
+ notTagsAny:
+ type: string
+ projectId:
+ type: string
+ tags:
+ type: string
+ tagsAny:
+ type: string
+ 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.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: set
+ trunk:
+ description: Enables and disables trunk at port level.
+ 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.
+ 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: The virtual network interface card (vNIC)
+ type that is bound to the neutron port.
+ type: string
+ 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.
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 56790cde7a..69ae2d52b1 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
@@ -2165,6 +2165,23 @@ spec:
- type
type: object
type: array
+ dependentResources:
+ description: DependentResources contains resolved dependent resources
+ that were created by the machine.
+ properties:
+ portsStatus:
+ description: PortsStatus 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
failureMessage:
description: |-
FailureMessage will be set in the event that there is a terminal problem
@@ -2205,6 +2222,195 @@ spec:
description: ImageID is the ID of the image to use for the machine
and is calculated based on ImageFilter.
type: string
+ portsOpts:
+ description: portsOpts is the list of ports options to create
+ for the machine.
+ items:
+ properties:
+ adminStateUp:
+ type: boolean
+ allowedAddressPairs:
+ items:
+ properties:
+ ipAddress:
+ type: string
+ macAddress:
+ type: string
+ type: object
+ type: array
+ 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.
+ type: boolean
+ fixedIPs:
+ description: Specify pairs of subnet and/or IP address.
+ These should be subnets of the network with the given
+ NetworkID.
+ items:
+ properties:
+ 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.
+ properties:
+ cidr:
+ type: string
+ description:
+ type: string
+ gateway_ip:
+ type: string
+ id:
+ type: string
+ ipVersion:
+ type: integer
+ ipv6AddressMode:
+ type: string
+ ipv6RaMode:
+ type: string
+ name:
+ type: string
+ notTags:
+ type: string
+ notTagsAny:
+ type: string
+ projectId:
+ type: string
+ tags:
+ type: string
+ tagsAny:
+ type: string
+ type: object
+ required:
+ - subnet
+ type: object
+ type: array
+ hostId:
+ description: The ID of the host where the port is allocated
+ type: string
+ macAddress:
+ type: string
+ nameSuffix:
+ description: Used to make the name of the port unique. 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.
+ properties:
+ description:
+ type: string
+ id:
+ type: string
+ name:
+ type: string
+ notTags:
+ type: string
+ notTagsAny:
+ type: string
+ projectId:
+ type: string
+ tags:
+ type: string
+ tagsAny:
+ 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
+ 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
+ securityGroupFilters:
+ description: The names, uuids, filters or any combination
+ these of the security groups to assign to the instance
+ items:
+ properties:
+ description:
+ type: string
+ id:
+ type: string
+ name:
+ type: string
+ notTags:
+ type: string
+ notTagsAny:
+ type: string
+ projectId:
+ type: string
+ tags:
+ type: string
+ tagsAny:
+ type: string
+ 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.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: set
+ trunk:
+ description: Enables and disables trunk at port level. 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.
+ 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: The virtual network interface card (vNIC) type
+ that is bound to the neutron port.
+ type: string
+ 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.
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index 914e662fa4..a06e9e4aa8 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -121,14 +121,28 @@ func (r *OpenStackClusterReconciler) Reconcile(ctx context.Context, req ctrl.Req
return reconcile.Result{}, err
}
+ // Resolve and store referenced & dependent resources for the bastion
if openStackCluster.Spec.Bastion != nil && openStackCluster.Spec.Bastion.Enabled {
if openStackCluster.Status.Bastion == nil {
openStackCluster.Status.Bastion = &infrav1.BastionStatus{}
}
- err = compute.ResolveReferencedMachineResources(scope, &openStackCluster.Spec.Bastion.Instance, &openStackCluster.Status.Bastion.ReferencedResources)
+ changed, err := compute.ResolveReferencedMachineResources(scope, openStackCluster, &openStackCluster.Spec.Bastion.Instance, &openStackCluster.Status.Bastion.ReferencedResources)
if err != nil {
return reconcile.Result{}, err
}
+ if changed {
+ // If the referenced resources have changed, we need to update the OpenStackCluster status now.
+ return reconcile.Result{}, nil
+ }
+
+ changed, err = compute.ResolveDependentBastionResources(scope, openStackCluster, bastionName(cluster.Name))
+ if err != nil {
+ return reconcile.Result{}, err
+ }
+ if changed {
+ // If the dependent resources have changed, we need to update the OpenStackCluster status now.
+ return reconcile.Result{}, nil
+ }
}
// Handle deleted clusters
@@ -180,11 +194,6 @@ func (r *OpenStackClusterReconciler) reconcileDelete(ctx context.Context, scope
}
}
- 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 ManagedSubnets was not set, no network was created.
if len(openStackCluster.Spec.ManagedSubnets) > 0 {
if err = networkingService.DeleteRouter(openStackCluster, clusterName); err != nil {
@@ -192,7 +201,7 @@ func (r *OpenStackClusterReconciler) reconcileDelete(ctx context.Context, scope
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)
}
@@ -203,6 +212,11 @@ func (r *OpenStackClusterReconciler) reconcileDelete(ctx context.Context, scope
}
}
+ 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)
+ }
+
// Cluster is deleted so remove the finalizer.
controllerutil.RemoveFinalizer(openStackCluster, infrav1.ClusterFinalizer)
scope.Logger().Info("Reconciled Cluster deleted successfully")
@@ -219,6 +233,8 @@ func contains(arr []string, target string) bool {
}
func deleteBastion(scope scope.Scope, cluster *clusterv1.Cluster, openStackCluster *infrav1.OpenStackCluster) error {
+ scope.Logger().Info("Deleting Bastion")
+
computeService, err := compute.NewService(scope)
if err != nil {
return err
@@ -265,24 +281,33 @@ func deleteBastion(scope scope.Scope, cluster *clusterv1.Cluster, openStackClust
}
}
- instanceSpec, err := bastionToInstanceSpec(openStackCluster, cluster.Name)
+ instanceSpec, err := bastionToInstanceSpec(openStackCluster, cluster)
if err != nil {
return err
}
- if err = computeService.DeleteInstance(openStackCluster, openStackCluster, instanceStatus, instanceSpec); err != nil {
+ if err = computeService.DeleteInstance(openStackCluster, instanceStatus, instanceSpec); 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 openStackCluster.Status.Bastion != nil && len(openStackCluster.Status.Bastion.DependentResources.PortsStatus) > 0 {
+ trunkSupported, err := networkingService.IsTrunkExtSupported()
+ if err != nil {
+ return err
+ }
+ for _, port := range openStackCluster.Status.Bastion.DependentResources.PortsStatus {
+ 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)
+ }
+ }
+ openStackCluster.Status.Bastion.DependentResources.PortsStatus = nil
}
- openStackCluster.Status.BastionSecurityGroup = nil
+ scope.Logger().Info("Deleted Bastion for cluster %s", cluster.Name)
+
+ openStackCluster.Status.Bastion = nil
delete(openStackCluster.ObjectMeta.Annotations, BastionInstanceHashAnnotation)
return nil
@@ -346,15 +371,27 @@ func reconcileBastion(scope scope.Scope, cluster *clusterv1.Cluster, openStackCl
return reconcile.Result{}, deleteBastion(scope, cluster, openStackCluster)
}
+ // If ports options aren't in the status, we'll re-trigger the reconcile to get them
+ // via adopting the referenced resources.
+ if len(openStackCluster.Status.Bastion.ReferencedResources.PortsOpts) == 0 {
+ return reconcile.Result{}, nil
+ }
+
computeService, err := compute.NewService(scope)
if err != nil {
return reconcile.Result{}, err
}
- instanceSpec, err := bastionToInstanceSpec(openStackCluster, cluster.Name)
+ networkingService, err := networking.NewService(scope)
+ if err != nil {
+ return reconcile.Result{}, err
+ }
+
+ instanceSpec, err := bastionToInstanceSpec(openStackCluster, cluster)
if err != nil {
return reconcile.Result{}, err
}
+ clusterName := fmt.Sprintf("%s-%s", cluster.Namespace, cluster.Name)
bastionHash, err := compute.HashInstanceSpec(instanceSpec)
if err != nil {
return reconcile.Result{}, fmt.Errorf("failed computing bastion hash from instance spec: %w", err)
@@ -365,6 +402,13 @@ func reconcileBastion(scope scope.Scope, cluster *clusterv1.Cluster, openStackCl
}
}
+ err = getOrCreateBastionPorts(scope, cluster, openStackCluster, networkingService, cluster.Name)
+ if err != nil {
+ handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to get or create ports for bastion: %w", err))
+ return ctrl.Result{}, fmt.Errorf("failed to get or create ports for bastion: %w", err)
+ }
+ bastionPortIDs := GetPortIDs(openStackCluster.Status.Bastion.DependentResources.PortsStatus)
+
var instanceStatus *compute.InstanceStatus
if openStackCluster.Status.Bastion != nil && openStackCluster.Status.Bastion.ID != "" {
if instanceStatus, err = computeService.GetInstanceStatus(openStackCluster.Status.Bastion.ID); err != nil {
@@ -378,7 +422,7 @@ func reconcileBastion(scope scope.Scope, cluster *clusterv1.Cluster, openStackCl
}
}
if instanceStatus == nil {
- instanceStatus, err = computeService.CreateInstance(openStackCluster, openStackCluster, instanceSpec, cluster.Name)
+ instanceStatus, err = computeService.CreateInstance(openStackCluster, instanceSpec, bastionPortIDs)
if err != nil {
return reconcile.Result{}, fmt.Errorf("failed to create bastion: %w", err)
}
@@ -401,10 +445,6 @@ func reconcileBastion(scope scope.Scope, cluster *clusterv1.Cluster, openStackCl
return ctrl.Result{}, nil
}
- networkingService, err := networking.NewService(scope)
- if err != nil {
- return ctrl.Result{}, err
- }
port, err := computeService.GetManagementPort(openStackCluster, instanceStatus)
if err != nil {
err = fmt.Errorf("getting management port for bastion: %w", err)
@@ -422,7 +462,6 @@ func reconcileBastion(scope scope.Scope, cluster *clusterv1.Cluster, openStackCl
return ctrl.Result{}, nil
}
- clusterName := fmt.Sprintf("%s-%s", cluster.Namespace, cluster.Name)
floatingIP := openStackCluster.Spec.Bastion.FloatingIP
if openStackCluster.Status.Bastion.FloatingIP != "" {
// Some floating IP has already been created for this bastion, make sure we re-use it
@@ -445,7 +484,7 @@ func reconcileBastion(scope scope.Scope, cluster *clusterv1.Cluster, openStackCl
return ctrl.Result{}, nil
}
-func bastionToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, clusterName string) (*compute.InstanceSpec, error) {
+func bastionToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, cluster *clusterv1.Cluster) (*compute.InstanceSpec, error) {
if openStackCluster.Spec.Bastion == nil {
return nil, fmt.Errorf("bastion spec is nil")
}
@@ -453,9 +492,8 @@ func bastionToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, clusterNa
if openStackCluster.Status.Bastion == nil {
return nil, fmt.Errorf("bastion status is nil")
}
-
instanceSpec := &compute.InstanceSpec{
- Name: bastionName(clusterName),
+ Name: bastionName(cluster.Name),
Flavor: openStackCluster.Spec.Bastion.Instance.Flavor,
SSHKeyName: openStackCluster.Spec.Bastion.Instance.SSHKeyName,
ImageID: openStackCluster.Status.Bastion.ReferencedResources.ImageID,
@@ -471,6 +509,7 @@ func bastionToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, clusterNa
})
}
}
+ instanceSpec.SecurityGroups = getBastionSecurityGroups(openStackCluster)
instanceSpec.Ports = openStackCluster.Spec.Bastion.Instance.Ports
@@ -481,6 +520,61 @@ func bastionName(clusterName string) string {
return fmt.Sprintf("%s-bastion", clusterName)
}
+// getBastionSecurityGroups returns a combination of openStackCluster.Spec.Bastion.Instance.SecurityGroups
+// and the security group managed by the OpenStackCluster.
+func getBastionSecurityGroups(openStackCluster *infrav1.OpenStackCluster) []infrav1.SecurityGroupFilter {
+ instanceSpecSecurityGroups := openStackCluster.Spec.Bastion.Instance.SecurityGroups
+
+ if openStackCluster.Spec.ManagedSecurityGroups == nil {
+ return instanceSpecSecurityGroups
+ }
+
+ var managedSecurityGroup string
+ if openStackCluster.Status.BastionSecurityGroup != nil {
+ managedSecurityGroup = openStackCluster.Status.BastionSecurityGroup.ID
+ }
+
+ if managedSecurityGroup != "" {
+ instanceSpecSecurityGroups = append(instanceSpecSecurityGroups, infrav1.SecurityGroupFilter{
+ ID: managedSecurityGroup,
+ })
+ }
+ return instanceSpecSecurityGroups
+}
+
+func getOrCreateBastionPorts(scope scope.Scope, cluster *clusterv1.Cluster, openStackCluster *infrav1.OpenStackCluster, networkingService *networking.Service, clusterName string) error {
+ scope.Logger().Info("Reconciling ports for bastion", "bastion", bastionName(openStackCluster.Name))
+
+ if openStackCluster.Status.Bastion == nil {
+ openStackCluster.Status.Bastion = &infrav1.BastionStatus{}
+ }
+
+ desiredPorts := openStackCluster.Status.Bastion.ReferencedResources.PortsOpts
+ portsToCreate := networking.MissingPorts(openStackCluster.Status.Bastion.DependentResources.PortsStatus, desiredPorts)
+
+ // Sanity check that the number of desired ports is equal to the addition of ports to create and ports that already exist.
+ if len(desiredPorts) != len(portsToCreate)+len(openStackCluster.Status.Bastion.DependentResources.PortsStatus) {
+ return fmt.Errorf("length of desired ports (%d) is not equal to the length of ports to create (%d) + the length of ports that already exist (%d)", len(desiredPorts), len(portsToCreate), len(openStackCluster.Status.Bastion.DependentResources.PortsStatus))
+ }
+
+ if len(portsToCreate) > 0 {
+ securityGroups := getBastionSecurityGroups(openStackCluster)
+ bastionPortsStatus, err := networkingService.CreatePorts(openStackCluster, clusterName, portsToCreate, securityGroups, []string{}, bastionName(cluster.Name))
+ if err != nil {
+ return fmt.Errorf("failed to create ports for bastion %s: %w", bastionName(openStackCluster.Name), err)
+ }
+
+ openStackCluster.Status.Bastion.DependentResources.PortsStatus = append(openStackCluster.Status.Bastion.DependentResources.PortsStatus, bastionPortsStatus...)
+ }
+
+ // Sanity check that the number of ports that have been put into PortsStatus is equal to the number of desired ports now that we have created them all.
+ if len(openStackCluster.Status.Bastion.DependentResources.PortsStatus) != len(desiredPorts) {
+ return fmt.Errorf("length of ports that already exist (%d) is not equal to the length of desired ports (%d)", len(openStackCluster.Status.Bastion.DependentResources.PortsStatus), len(desiredPorts))
+ }
+
+ return nil
+}
+
// bastionHashHasChanged returns a boolean whether if the latest bastion hash, built from the instance spec, has changed or not.
func bastionHashHasChanged(computeHash string, clusterAnnotations map[string]string) bool {
latestHash, ok := clusterAnnotations[BastionInstanceHashAnnotation]
diff --git a/controllers/openstackcluster_controller_test.go b/controllers/openstackcluster_controller_test.go
index 3a51ad6413..87d63ff7cc 100644
--- a/controllers/openstackcluster_controller_test.go
+++ b/controllers/openstackcluster_controller_test.go
@@ -25,12 +25,9 @@ import (
"github.com/go-logr/logr"
"github.com/golang/mock/gomock"
"github.com/gophercloud/gophercloud"
- "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/attachinterfaces"
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
- "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips"
- "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/ports"
"github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
@@ -216,9 +213,6 @@ var _ = Describe("OpenStackCluster controller", func() {
computeClientRecorder := mockScopeFactory.ComputeClient.EXPECT()
computeClientRecorder.GetServer("bastion-uuid").Return(nil, gophercloud.ErrResourceNotFound{})
- networkClientRecorder := mockScopeFactory.NetworkClient.EXPECT()
- networkClientRecorder.ListSecGroup(gomock.Any()).Return([]groups.SecGroup{}, nil)
-
err = deleteBastion(scope, capiCluster, testCluster)
Expect(testCluster.Status.Bastion).To(BeNil())
Expect(err).To(BeNil())
@@ -238,11 +232,26 @@ var _ = Describe("OpenStackCluster controller", func() {
Bastion: &infrav1.BastionStatus{
ReferencedResources: infrav1.ReferencedMachineResources{
ImageID: "imageID",
+ PortsOpts: []infrav1.PortOpts{
+ {
+ Network: &infrav1.NetworkFilter{
+ ID: "network-id",
+ },
+ },
+ },
+ },
+ DependentResources: infrav1.DependentMachineResources{
+ PortsStatus: []infrav1.PortStatus{
+ {
+ ID: "portID1",
+ },
+ },
},
},
Network: &infrav1.NetworkStatusWithSubnets{
NetworkStatus: infrav1.NetworkStatus{
Name: "network-name",
+ ID: "network-id",
},
},
}
@@ -256,14 +265,15 @@ var _ = Describe("OpenStackCluster controller", func() {
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{server}, nil)
- networkClientRecorder := mockScopeFactory.NetworkClient.EXPECT()
- networkClientRecorder.ListPort(gomock.Any()).Return([]ports.Port{{ID: "portID"}}, nil)
- networkClientRecorder.ListFloatingIP(floatingips.ListOpts{PortID: "portID"}).Return(make([]floatingips.FloatingIP, 1), nil)
+ networkClientRecorder.ListFloatingIP(floatingips.ListOpts{PortID: "portID1"}).Return(make([]floatingips.FloatingIP, 1), nil)
res, err := reconcileBastion(scope, capiCluster, testCluster)
Expect(testCluster.Status.Bastion).To(Equal(&infrav1.BastionStatus{
@@ -271,6 +281,20 @@ var _ = Describe("OpenStackCluster controller", func() {
State: "ACTIVE",
ReferencedResources: infrav1.ReferencedMachineResources{
ImageID: "imageID",
+ PortsOpts: []infrav1.PortOpts{
+ {
+ Network: &infrav1.NetworkFilter{
+ ID: "network-id",
+ },
+ },
+ },
+ },
+ DependentResources: infrav1.DependentMachineResources{
+ PortsStatus: []infrav1.PortStatus{
+ {
+ ID: "portID1",
+ },
+ },
},
}))
Expect(err).To(BeNil())
@@ -291,12 +315,27 @@ var _ = Describe("OpenStackCluster controller", func() {
Network: &infrav1.NetworkStatusWithSubnets{
NetworkStatus: infrav1.NetworkStatus{
Name: "network-name",
+ ID: "network-id",
},
},
Bastion: &infrav1.BastionStatus{
ID: "adopted-fip-bastion-uuid",
ReferencedResources: infrav1.ReferencedMachineResources{
ImageID: "imageID",
+ PortsOpts: []infrav1.PortOpts{
+ {
+ Network: &infrav1.NetworkFilter{
+ ID: "network-id",
+ },
+ },
+ },
+ },
+ DependentResources: infrav1.DependentMachineResources{
+ PortsStatus: []infrav1.PortStatus{
+ {
+ ID: "portID1",
+ },
+ },
},
},
}
@@ -310,12 +349,13 @@ var _ = Describe("OpenStackCluster controller", func() {
server.ID = "adopted-fip-bastion-uuid"
server.Status = "ACTIVE"
+ networkClientRecorder := mockScopeFactory.NetworkClient.EXPECT()
+ networkClientRecorder.ListPort(gomock.Any()).Return([]ports.Port{{ID: "portID1"}}, nil)
+
computeClientRecorder := mockScopeFactory.ComputeClient.EXPECT()
computeClientRecorder.GetServer("adopted-fip-bastion-uuid").Return(&server, nil)
- networkClientRecorder := mockScopeFactory.NetworkClient.EXPECT()
- networkClientRecorder.ListPort(gomock.Any()).Return([]ports.Port{{ID: "portID"}}, nil)
- networkClientRecorder.ListFloatingIP(floatingips.ListOpts{PortID: "portID"}).Return([]floatingips.FloatingIP{{FloatingIP: "1.2.3.4"}}, 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{
@@ -324,6 +364,20 @@ var _ = Describe("OpenStackCluster controller", func() {
State: "ACTIVE",
ReferencedResources: infrav1.ReferencedMachineResources{
ImageID: "imageID",
+ PortsOpts: []infrav1.PortOpts{
+ {
+ Network: &infrav1.NetworkFilter{
+ ID: "network-id",
+ },
+ },
+ },
+ },
+ DependentResources: infrav1.DependentMachineResources{
+ PortsStatus: []infrav1.PortStatus{
+ {
+ ID: "portID1",
+ },
+ },
},
}))
Expect(err).To(BeNil())
@@ -343,6 +397,7 @@ var _ = Describe("OpenStackCluster controller", func() {
testCluster.Status = infrav1.OpenStackClusterStatus{
Network: &infrav1.NetworkStatusWithSubnets{
NetworkStatus: infrav1.NetworkStatus{
+ ID: "network-id",
Name: "network-name",
},
},
@@ -350,6 +405,20 @@ var _ = Describe("OpenStackCluster controller", func() {
ID: "requeue-bastion-uuid",
ReferencedResources: infrav1.ReferencedMachineResources{
ImageID: "imageID",
+ PortsOpts: []infrav1.PortOpts{
+ {
+ Network: &infrav1.NetworkFilter{
+ ID: "network-id",
+ },
+ },
+ },
+ },
+ DependentResources: infrav1.DependentMachineResources{
+ PortsStatus: []infrav1.PortStatus{
+ {
+ ID: "portID1",
+ },
+ },
},
},
}
@@ -372,6 +441,20 @@ var _ = Describe("OpenStackCluster controller", func() {
State: "BUILD",
ReferencedResources: infrav1.ReferencedMachineResources{
ImageID: "imageID",
+ PortsOpts: []infrav1.PortOpts{
+ {
+ Network: &infrav1.NetworkFilter{
+ ID: "network-id",
+ },
+ },
+ },
+ },
+ DependentResources: infrav1.DependentMachineResources{
+ PortsStatus: []infrav1.PortStatus{
+ {
+ ID: "portID1",
+ },
+ },
},
}))
Expect(err).To(BeNil())
@@ -392,6 +475,11 @@ var _ = Describe("OpenStackCluster controller", func() {
ImageID: "imageID",
},
},
+ Network: &infrav1.NetworkStatusWithSubnets{
+ NetworkStatus: infrav1.NetworkStatus{
+ ID: "network-id",
+ },
+ },
}
err = k8sClient.Status().Update(ctx, testCluster)
Expect(err).To(BeNil())
@@ -406,14 +494,9 @@ var _ = Describe("OpenStackCluster controller", func() {
computeClientRecorder.ListServers(servers.ListOpts{
Name: "^capi-cluster-bastion$",
}).Return([]clients.ServerExt{server}, nil)
- computeClientRecorder.ListAttachedInterfaces("delete-bastion-uuid").Return([]attachinterfaces.Interface{}, nil)
computeClientRecorder.DeleteServer("delete-bastion-uuid").Return(nil)
computeClientRecorder.GetServer("delete-bastion-uuid").Return(nil, gophercloud.ErrResourceNotFound{})
- networkClientRecorder := mockScopeFactory.NetworkClient.EXPECT()
- networkClientRecorder.ListExtensions().Return([]extensions.Extension{}, nil)
- networkClientRecorder.ListSecGroup(gomock.Any()).Return([]groups.SecGroup{}, nil)
-
err = deleteBastion(scope, capiCluster, testCluster)
Expect(err).To(BeNil())
})
@@ -424,6 +507,9 @@ var _ = Describe("OpenStackCluster controller", func() {
testCluster.SetName("subnet-filtering")
testCluster.Spec = infrav1.OpenStackClusterSpec{
+ Bastion: &infrav1.Bastion{
+ Enabled: true,
+ },
DisableAPIServerFloatingIP: true,
APIServerFixedIP: "10.0.0.1",
ExternalNetwork: infrav1.NetworkFilter{
@@ -433,6 +519,17 @@ var _ = Describe("OpenStackCluster controller", func() {
ID: clusterNetworkID,
},
}
+ testCluster.Status = infrav1.OpenStackClusterStatus{
+ Bastion: &infrav1.BastionStatus{
+ DependentResources: infrav1.DependentMachineResources{
+ PortsStatus: []infrav1.PortStatus{
+ {
+ ID: "port-id",
+ },
+ },
+ },
+ },
+ }
err := k8sClient.Create(ctx, testCluster)
Expect(err).To(BeNil())
err = k8sClient.Create(ctx, capiCluster)
@@ -486,6 +583,9 @@ var _ = Describe("OpenStackCluster controller", func() {
testCluster.SetName("subnet-filtering")
testCluster.Spec = infrav1.OpenStackClusterSpec{
+ Bastion: &infrav1.Bastion{
+ Enabled: true,
+ },
DisableAPIServerFloatingIP: true,
APIServerFixedIP: "10.0.0.1",
ExternalNetwork: infrav1.NetworkFilter{
@@ -499,6 +599,17 @@ var _ = Describe("OpenStackCluster controller", func() {
{ID: clusterSubnets[1]},
},
}
+ testCluster.Status = infrav1.OpenStackClusterStatus{
+ Bastion: &infrav1.BastionStatus{
+ DependentResources: infrav1.DependentMachineResources{
+ PortsStatus: []infrav1.PortStatus{
+ {
+ ID: "port-id",
+ },
+ },
+ },
+ },
+ }
err := k8sClient.Create(ctx, testCluster)
Expect(err).To(BeNil())
err = k8sClient.Create(ctx, capiCluster)
@@ -617,3 +728,40 @@ func Test_ConvertOpenStackNetworkToCAPONetwork(t *testing.T) {
t.Errorf("ConvertOpenStackNetworkToCAPONetwork() = %v, want %v", openStackCluster.Status.Network.NetworkStatus, expected)
}
}
+
+func TestGetBastionSecurityGroups(t *testing.T) {
+ openStackCluster := &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ Bastion: &infrav1.Bastion{
+ Instance: infrav1.OpenStackMachineSpec{
+ SecurityGroups: []infrav1.SecurityGroupFilter{
+ {
+ ID: "sg-123",
+ },
+ },
+ },
+ },
+ ManagedSecurityGroups: &infrav1.ManagedSecurityGroups{},
+ },
+ Status: infrav1.OpenStackClusterStatus{
+ BastionSecurityGroup: &infrav1.SecurityGroupStatus{
+ ID: "sg-456",
+ },
+ },
+ }
+
+ expectedSecurityGroups := []infrav1.SecurityGroupFilter{
+ {
+ ID: "sg-123",
+ },
+ {
+ ID: "sg-456",
+ },
+ }
+
+ securityGroups := getBastionSecurityGroups(openStackCluster)
+
+ if !reflect.DeepEqual(securityGroups, expectedSecurityGroups) {
+ t.Errorf("Expected security groups %v, but got %v", expectedSecurityGroups, securityGroups)
+ }
+}
diff --git a/controllers/openstackmachine_controller.go b/controllers/openstackmachine_controller.go
index 71972fdeff..15171c9f11 100644
--- a/controllers/openstackmachine_controller.go
+++ b/controllers/openstackmachine_controller.go
@@ -148,10 +148,24 @@ func (r *OpenStackMachineReconciler) Reconcile(ctx context.Context, req ctrl.Req
}
// Resolve and store referenced resources
- err = compute.ResolveReferencedMachineResources(scope, &openStackMachine.Spec, &openStackMachine.Status.ReferencedResources)
+ changed, err := compute.ResolveReferencedMachineResources(scope, infraCluster, &openStackMachine.Spec, &openStackMachine.Status.ReferencedResources)
if err != nil {
return reconcile.Result{}, err
}
+ if changed {
+ // If the referenced resources have changed, we need to update the OpenStackMachine status now.
+ return reconcile.Result{}, nil
+ }
+
+ // Resolve and store dependent resources
+ changed, err = compute.ResolveDependentMachineResources(scope, openStackMachine)
+ if err != nil {
+ return reconcile.Result{}, err
+ }
+ if changed {
+ // If the dependent resources have changed, we need to update the OpenStackMachine status now.
+ return reconcile.Result{}, nil
+ }
// Handle deleted machines
if !openStackMachine.DeletionTimestamp.IsZero() {
@@ -288,17 +302,40 @@ func (r *OpenStackMachineReconciler) reconcileDelete(scope scope.Scope, cluster
instanceSpec := machineToInstanceSpec(openStackCluster, machine, openStackMachine, "")
- if err := computeService.DeleteInstance(openStackCluster, openStackMachine, instanceStatus, instanceSpec); err != nil {
+ if err := computeService.DeleteInstance(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)
}
+ trunkSupported, err := networkingService.IsTrunkExtSupported()
+ if err != nil {
+ return ctrl.Result{}, err
+ }
+
+ portsStatus := openStackMachine.Status.DependentResources.PortsStatus
+ 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)
+ }
+ }
+
controllerutil.RemoveFinalizer(openStackMachine, infrav1.MachineFinalizer)
scope.Logger().Info("Reconciled Machine delete successfully")
return ctrl.Result{}, 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
+}
+
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) {
+ 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")
@@ -341,9 +378,15 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope
return ctrl.Result{}, err
}
- instanceStatus, err := r.getOrCreate(scope.Logger(), cluster, openStackCluster, machine, openStackMachine, computeService, userData)
+ err = getOrCreateMachinePorts(scope, openStackCluster, machine, openStackMachine, networkingService, clusterName)
+ if err != nil {
+ return ctrl.Result{}, err
+ }
+ portIDs := GetPortIDs(openStackMachine.Status.DependentResources.PortsStatus)
+
+ instanceStatus, err := r.getOrCreateInstance(scope.Logger(), openStackCluster, machine, openStackMachine, computeService, userData, portIDs)
if err != nil || instanceStatus == nil {
- // Conditions set in getOrCreate
+ // Conditions set in getOrCreateInstance
return ctrl.Result{}, err
}
@@ -446,7 +489,38 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope
return ctrl.Result{}, 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) {
+func getOrCreateMachinePorts(scope scope.Scope, openStackCluster *infrav1.OpenStackCluster, machine *clusterv1.Machine, openStackMachine *infrav1.OpenStackMachine, networkingService *networking.Service, clusterName string) error {
+ scope.Logger().Info("Reconciling ports for machine", "machine", machine.Name)
+ var machinePortsStatus []infrav1.PortStatus
+ var err error
+
+ desiredPorts := openStackMachine.Status.ReferencedResources.PortsOpts
+ portsToCreate := networking.MissingPorts(openStackMachine.Status.DependentResources.PortsStatus, desiredPorts)
+
+ // Sanity check that the number of desired ports is equal to the addition of ports to create and ports that already exist.
+ if len(desiredPorts) != len(portsToCreate)+len(openStackMachine.Status.DependentResources.PortsStatus) {
+ return fmt.Errorf("length of desired ports (%d) is not equal to the length of ports to create (%d) + the length of ports that already exist (%d)", len(desiredPorts), len(portsToCreate), len(openStackMachine.Status.DependentResources.PortsStatus))
+ }
+
+ if len(portsToCreate) > 0 {
+ instanceTags := getInstanceTags(openStackMachine, openStackCluster)
+ managedSecurityGroups := getManagedSecurityGroups(openStackCluster, machine, openStackMachine)
+ machinePortsStatus, err = networkingService.CreatePorts(openStackMachine, clusterName, portsToCreate, managedSecurityGroups, instanceTags, openStackMachine.Name)
+ if err != nil {
+ return fmt.Errorf("create ports: %w", err)
+ }
+ openStackMachine.Status.DependentResources.PortsStatus = append(openStackMachine.Status.DependentResources.PortsStatus, machinePortsStatus...)
+ }
+
+ // Sanity check that the number of ports that have been put into PortsStatus is equal to the number of desired ports now that we have created them all.
+ if len(openStackMachine.Status.DependentResources.PortsStatus) != len(desiredPorts) {
+ return fmt.Errorf("length of ports that already exist (%d) is not equal to the length of desired ports (%d)", len(openStackMachine.Status.DependentResources.PortsStatus), len(desiredPorts))
+ }
+
+ 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.Spec.InstanceID != nil {
@@ -472,7 +546,7 @@ func (r *OpenStackMachineReconciler) getOrCreate(logger logr.Logger, cluster *cl
}
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)
@@ -508,6 +582,17 @@ func machineToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, machine *
instanceSpec.FailureDomain = *machine.Spec.FailureDomain
}
+ instanceSpec.Tags = getInstanceTags(openStackMachine, openStackCluster)
+ instanceSpec.SecurityGroups = getManagedSecurityGroups(openStackCluster, machine, openStackMachine)
+ instanceSpec.Ports = openStackMachine.Spec.Ports
+
+ return &instanceSpec
+}
+
+// getInstanceTags returns the tags that should be applied to the instance.
+// The tags are a combination of the tags specified on the OpenStackMachine and
+// the ones specified on the OpenStackCluster.
+func getInstanceTags(openStackMachine *infrav1.OpenStackMachine, openStackCluster *infrav1.OpenStackCluster) []string {
machineTags := []string{}
// Append machine specific tags
@@ -530,31 +615,36 @@ func machineToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, machine *
}
machineTags = deduplicate(machineTags)
- instanceSpec.Tags = machineTags
+ return machineTags
+}
- instanceSpec.SecurityGroups = openStackMachine.Spec.SecurityGroups
- if openStackCluster.Spec.ManagedSecurityGroups != nil {
- var managedSecurityGroup string
- if util.IsControlPlaneMachine(machine) {
- if openStackCluster.Status.ControlPlaneSecurityGroup != nil {
- managedSecurityGroup = openStackCluster.Status.ControlPlaneSecurityGroup.ID
- }
- } else {
- if openStackCluster.Status.WorkerSecurityGroup != nil {
- managedSecurityGroup = openStackCluster.Status.WorkerSecurityGroup.ID
- }
- }
+// getManagedSecurityGroups returns a combination of OpenStackMachine.Spec.SecurityGroups
+// and the security group managed by the OpenStackCluster whether it's a control plane or a worker machine.
+func getManagedSecurityGroups(openStackCluster *infrav1.OpenStackCluster, machine *clusterv1.Machine, openStackMachine *infrav1.OpenStackMachine) []infrav1.SecurityGroupFilter {
+ machineSpecSecurityGroups := openStackMachine.Spec.SecurityGroups
- if managedSecurityGroup != "" {
- instanceSpec.SecurityGroups = append(instanceSpec.SecurityGroups, infrav1.SecurityGroupFilter{
- ID: managedSecurityGroup,
- })
+ if openStackCluster.Spec.ManagedSecurityGroups == nil {
+ return machineSpecSecurityGroups
+ }
+
+ var managedSecurityGroup string
+ if util.IsControlPlaneMachine(machine) {
+ if openStackCluster.Status.ControlPlaneSecurityGroup != nil {
+ managedSecurityGroup = openStackCluster.Status.ControlPlaneSecurityGroup.ID
+ }
+ } else {
+ if openStackCluster.Status.WorkerSecurityGroup != nil {
+ managedSecurityGroup = openStackCluster.Status.WorkerSecurityGroup.ID
}
}
- instanceSpec.Ports = openStackMachine.Spec.Ports
+ if managedSecurityGroup != "" {
+ machineSpecSecurityGroups = append(machineSpecSecurityGroups, infrav1.SecurityGroupFilter{
+ ID: managedSecurityGroup,
+ })
+ }
- return &instanceSpec
+ return machineSpecSecurityGroups
}
func (r *OpenStackMachineReconciler) reconcileLoadBalancerMember(scope scope.Scope, openStackCluster *infrav1.OpenStackCluster, openStackMachine *infrav1.OpenStackMachine, instanceNS *compute.InstanceNetworkStatus, clusterName string) error {
diff --git a/controllers/openstackmachine_controller_test.go b/controllers/openstackmachine_controller_test.go
index 32db7b92bb..a498ba93a3 100644
--- a/controllers/openstackmachine_controller_test.go
+++ b/controllers/openstackmachine_controller_test.go
@@ -17,6 +17,7 @@ limitations under the License.
package controllers
import (
+ "reflect"
"testing"
. "github.com/onsi/gomega"
@@ -260,3 +261,254 @@ func Test_machineToInstanceSpec(t *testing.T) {
})
}
}
+
+func Test_getInstanceTags(t *testing.T) {
+ tests := []struct {
+ name string
+ openStackMachine func() *infrav1.OpenStackMachine
+ openStackCluster func() *infrav1.OpenStackCluster
+ wantMachineTags []string
+ }{
+ {
+ name: "No tags",
+ openStackMachine: func() *infrav1.OpenStackMachine {
+ return &infrav1.OpenStackMachine{
+ Spec: infrav1.OpenStackMachineSpec{},
+ }
+ },
+ openStackCluster: func() *infrav1.OpenStackCluster {
+ return &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{},
+ }
+ },
+ wantMachineTags: []string{},
+ },
+ {
+ name: "Machine tags only",
+ openStackMachine: func() *infrav1.OpenStackMachine {
+ return &infrav1.OpenStackMachine{
+ Spec: infrav1.OpenStackMachineSpec{
+ Tags: []string{"machine-tag1", "machine-tag2"},
+ },
+ }
+ },
+ openStackCluster: func() *infrav1.OpenStackCluster {
+ return &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{},
+ }
+ },
+ wantMachineTags: []string{"machine-tag1", "machine-tag2"},
+ },
+ {
+ name: "Cluster tags only",
+ openStackMachine: func() *infrav1.OpenStackMachine {
+ return &infrav1.OpenStackMachine{
+ Spec: infrav1.OpenStackMachineSpec{},
+ }
+ },
+ openStackCluster: func() *infrav1.OpenStackCluster {
+ return &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ Tags: []string{"cluster-tag1", "cluster-tag2"},
+ },
+ }
+ },
+ wantMachineTags: []string{"cluster-tag1", "cluster-tag2"},
+ },
+ {
+ name: "Machine and cluster tags",
+ openStackMachine: func() *infrav1.OpenStackMachine {
+ return &infrav1.OpenStackMachine{
+ Spec: infrav1.OpenStackMachineSpec{
+ Tags: []string{"machine-tag1", "machine-tag2"},
+ },
+ }
+ },
+ openStackCluster: func() *infrav1.OpenStackCluster {
+ return &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ Tags: []string{"cluster-tag1", "cluster-tag2"},
+ },
+ }
+ },
+ wantMachineTags: []string{"machine-tag1", "machine-tag2", "cluster-tag1", "cluster-tag2"},
+ },
+ {
+ name: "Duplicate tags",
+ openStackMachine: func() *infrav1.OpenStackMachine {
+ return &infrav1.OpenStackMachine{
+ Spec: infrav1.OpenStackMachineSpec{
+ Tags: []string{"tag1", "tag2", "tag1"},
+ },
+ }
+ },
+ openStackCluster: func() *infrav1.OpenStackCluster {
+ return &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ Tags: []string{"tag2", "tag3", "tag3"},
+ },
+ }
+ },
+ wantMachineTags: []string{"tag1", "tag2", "tag3"},
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ gotMachineTags := getInstanceTags(tt.openStackMachine(), tt.openStackCluster())
+ if !reflect.DeepEqual(gotMachineTags, tt.wantMachineTags) {
+ t.Errorf("getInstanceTags() = %v, want %v", gotMachineTags, tt.wantMachineTags)
+ }
+ })
+ }
+}
+
+func Test_getManagedSecurityGroups(t *testing.T) {
+ tests := []struct {
+ name string
+ openStackCluster func() *infrav1.OpenStackCluster
+ machine func() *clusterv1.Machine
+ openStackMachine func() *infrav1.OpenStackMachine
+ wantSecurityGroups []infrav1.SecurityGroupFilter
+ }{
+ {
+ name: "Defaults",
+ openStackCluster: getDefaultOpenStackCluster,
+ machine: getDefaultMachine,
+ openStackMachine: getDefaultOpenStackMachine,
+ wantSecurityGroups: []infrav1.SecurityGroupFilter{},
+ },
+ {
+ name: "Control plane machine with control plane security group",
+ openStackCluster: func() *infrav1.OpenStackCluster {
+ c := getDefaultOpenStackCluster()
+ c.Spec.ManagedSecurityGroups = &infrav1.ManagedSecurityGroups{}
+ c.Status.ControlPlaneSecurityGroup = &infrav1.SecurityGroupStatus{ID: controlPlaneSecurityGroupUUID}
+ return c
+ },
+ machine: func() *clusterv1.Machine {
+ m := getDefaultMachine()
+ m.Labels = map[string]string{
+ clusterv1.MachineControlPlaneLabel: "true",
+ }
+ return m
+ },
+ openStackMachine: getDefaultOpenStackMachine,
+ wantSecurityGroups: []infrav1.SecurityGroupFilter{
+ {ID: controlPlaneSecurityGroupUUID},
+ },
+ },
+ {
+ name: "Worker machine with worker security group",
+ openStackCluster: func() *infrav1.OpenStackCluster {
+ c := getDefaultOpenStackCluster()
+ c.Spec.ManagedSecurityGroups = &infrav1.ManagedSecurityGroups{}
+ c.Status.WorkerSecurityGroup = &infrav1.SecurityGroupStatus{ID: workerSecurityGroupUUID}
+ return c
+ },
+ machine: getDefaultMachine,
+ openStackMachine: getDefaultOpenStackMachine,
+ wantSecurityGroups: []infrav1.SecurityGroupFilter{
+ {ID: workerSecurityGroupUUID},
+ },
+ },
+ {
+ name: "Control plane machine without control plane security group",
+ openStackCluster: func() *infrav1.OpenStackCluster {
+ c := getDefaultOpenStackCluster()
+ c.Spec.ManagedSecurityGroups = &infrav1.ManagedSecurityGroups{}
+ c.Status.ControlPlaneSecurityGroup = nil
+ return c
+ },
+ machine: func() *clusterv1.Machine {
+ m := getDefaultMachine()
+ m.Labels = map[string]string{
+ clusterv1.MachineControlPlaneLabel: "true",
+ }
+ return m
+ },
+ openStackMachine: getDefaultOpenStackMachine,
+ wantSecurityGroups: []infrav1.SecurityGroupFilter{},
+ },
+ {
+ name: "Worker machine without worker security group",
+ openStackCluster: func() *infrav1.OpenStackCluster {
+ c := getDefaultOpenStackCluster()
+ c.Spec.ManagedSecurityGroups = &infrav1.ManagedSecurityGroups{}
+ c.Status.WorkerSecurityGroup = nil
+ return c
+ },
+ machine: getDefaultMachine,
+ openStackMachine: getDefaultOpenStackMachine,
+ wantSecurityGroups: []infrav1.SecurityGroupFilter{},
+ },
+ {
+ name: "Machine with additional security groups",
+ openStackCluster: func() *infrav1.OpenStackCluster {
+ c := getDefaultOpenStackCluster()
+ c.Spec.ManagedSecurityGroups = &infrav1.ManagedSecurityGroups{}
+ c.Status.ControlPlaneSecurityGroup = &infrav1.SecurityGroupStatus{ID: controlPlaneSecurityGroupUUID}
+ c.Status.WorkerSecurityGroup = &infrav1.SecurityGroupStatus{ID: workerSecurityGroupUUID}
+ return c
+ },
+ machine: getDefaultMachine,
+ openStackMachine: func() *infrav1.OpenStackMachine {
+ m := getDefaultOpenStackMachine()
+ m.Spec.SecurityGroups = []infrav1.SecurityGroupFilter{{ID: extraSecurityGroupUUID}}
+ return m
+ },
+ wantSecurityGroups: []infrav1.SecurityGroupFilter{
+ {ID: extraSecurityGroupUUID},
+ {ID: workerSecurityGroupUUID},
+ },
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ gotMachineSecurity := getManagedSecurityGroups(tt.openStackCluster(), tt.machine(), tt.openStackMachine())
+ if !reflect.DeepEqual(gotMachineSecurity, tt.wantSecurityGroups) {
+ t.Errorf("getManagedSecurityGroups() = %v, want %v", gotMachineSecurity, tt.wantSecurityGroups)
+ }
+ })
+ }
+}
+
+func TestGetPortIDs(t *testing.T) {
+ tests := []struct {
+ name string
+ ports []infrav1.PortStatus
+ want []string
+ }{
+ {
+ name: "Empty ports",
+ ports: []infrav1.PortStatus{},
+ want: []string{},
+ },
+ {
+ name: "Single port",
+ ports: []infrav1.PortStatus{
+ {ID: "port1"},
+ },
+ 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)
+ }
+ })
+ }
+}
diff --git a/controllers/suite_test.go b/controllers/suite_test.go
index fdbda08855..08470ae280 100644
--- a/controllers/suite_test.go
+++ b/controllers/suite_test.go
@@ -147,7 +147,6 @@ var _ = Describe("When calling getOrCreate", func() {
})
It("should return an error if unable to get instance", func() {
- cluster := &clusterv1.Cluster{}
openStackCluster := &infrav1.OpenStackCluster{}
machine := &clusterv1.Machine{}
openStackMachine := &infrav1.OpenStackMachine{
@@ -157,7 +156,7 @@ var _ = Describe("When calling getOrCreate", func() {
}
mockScopeFactory.ComputeClient.EXPECT().GetServer(gomock.Any()).Return(nil, errors.New("Test error when getting server"))
- instanceStatus, err := reconsiler.getOrCreate(logger, cluster, openStackCluster, machine, openStackMachine, computeService, "")
+ instanceStatus, err := reconsiler.getOrCreateInstance(logger, openStackCluster, machine, openStackMachine, computeService, "", []string{})
Expect(err).To(HaveOccurred())
Expect(instanceStatus).To(BeNil())
conditions := openStackMachine.GetConditions()
@@ -171,7 +170,6 @@ var _ = Describe("When calling getOrCreate", func() {
})
It("should retrieve instance by name if no ID is stored", func() {
- cluster := &clusterv1.Cluster{}
openStackCluster := &infrav1.OpenStackCluster{}
machine := &clusterv1.Machine{}
openStackMachine := &infrav1.OpenStackMachine{}
@@ -179,7 +177,7 @@ var _ = Describe("When calling getOrCreate", func() {
servers[0].ID = "machine-uuid"
mockScopeFactory.ComputeClient.EXPECT().ListServers(gomock.Any()).Return(servers, nil)
- instanceStatus, err := reconsiler.getOrCreate(logger, cluster, openStackCluster, machine, openStackMachine, computeService, "")
+ 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/pkg/cloud/services/compute/dependent_resources.go b/pkg/cloud/services/compute/dependent_resources.go
new file mode 100644
index 0000000000..2db2f64bdf
--- /dev/null
+++ b/pkg/cloud/services/compute/dependent_resources.go
@@ -0,0 +1,45 @@
+/*
+Copyright 2024 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 compute
+
+import (
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ "sigs.k8s.io/cluster-api-provider-openstack/pkg/cloud/services/networking"
+ "sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
+)
+
+func ResolveDependentMachineResources(scope scope.Scope, openStackMachine *infrav1.OpenStackMachine) (changed bool, err error) {
+ changed = false
+
+ networkingService, err := networking.NewService(scope)
+ if err != nil {
+ return changed, err
+ }
+
+ return networkingService.AdoptMachinePorts(scope, openStackMachine, openStackMachine.Status.ReferencedResources.PortsOpts)
+}
+
+func ResolveDependentBastionResources(scope scope.Scope, openStackCluster *infrav1.OpenStackCluster, bastionName string) (changed bool, err error) {
+ changed = false
+
+ networkingService, err := networking.NewService(scope)
+ if err != nil {
+ return changed, err
+ }
+
+ return networkingService.AdoptBastionPorts(scope, openStackCluster, bastionName)
+}
diff --git a/pkg/cloud/services/compute/dependent_resources_test.go b/pkg/cloud/services/compute/dependent_resources_test.go
new file mode 100644
index 0000000000..f9567929af
--- /dev/null
+++ b/pkg/cloud/services/compute/dependent_resources_test.go
@@ -0,0 +1,217 @@
+/*
+Copyright 2024 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 compute
+
+import (
+ "testing"
+
+ "github.com/go-logr/logr"
+ "github.com/golang/mock/gomock"
+ "github.com/google/go-cmp/cmp"
+ . "github.com/onsi/gomega"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ "sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
+)
+
+func Test_ResolveDependentMachineResources(t *testing.T) {
+ const networkID = "5e8e0d3b-7f3d-4f3e-8b3f-3e3e3e3e3e3e"
+ const portID = "78e0d3b-7f3d-4f3e-8b3f-3e3e3e3e3e3e"
+
+ tests := []struct {
+ testName string
+ openStackCluster *infrav1.OpenStackCluster
+ openStackMachineStatus infrav1.OpenStackMachineStatus
+ want *infrav1.DependentMachineResources
+ wantErr bool
+ }{
+ {
+ testName: "no Network ID yet and no ports in status",
+ openStackCluster: &infrav1.OpenStackCluster{},
+ want: &infrav1.DependentMachineResources{},
+ wantErr: false,
+ },
+ {
+ testName: "Network ID set but no ports in status",
+ openStackCluster: &infrav1.OpenStackCluster{
+ Status: infrav1.OpenStackClusterStatus{
+ Network: &infrav1.NetworkStatusWithSubnets{
+ NetworkStatus: infrav1.NetworkStatus{
+ ID: networkID,
+ },
+ },
+ },
+ },
+ want: &infrav1.DependentMachineResources{},
+ wantErr: false,
+ },
+ {
+ testName: "Network ID set and ports in status",
+ openStackCluster: &infrav1.OpenStackCluster{
+ Status: infrav1.OpenStackClusterStatus{
+ Network: &infrav1.NetworkStatusWithSubnets{
+ NetworkStatus: infrav1.NetworkStatus{
+ ID: networkID,
+ },
+ },
+ },
+ },
+ openStackMachineStatus: infrav1.OpenStackMachineStatus{
+ DependentResources: infrav1.DependentMachineResources{
+ PortsStatus: []infrav1.PortStatus{
+ {
+ ID: portID,
+ },
+ },
+ },
+ },
+ want: &infrav1.DependentMachineResources{
+ PortsStatus: []infrav1.PortStatus{
+ {
+ ID: portID,
+ },
+ },
+ },
+ wantErr: false,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.testName, func(t *testing.T) {
+ g := NewWithT(t)
+ mockCtrl := gomock.NewController(t)
+ mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "", logr.Discard())
+
+ defaultOpenStackMachine := &infrav1.OpenStackMachine{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "test",
+ },
+ Status: tt.openStackMachineStatus,
+ }
+
+ _, err := ResolveDependentMachineResources(mockScopeFactory, defaultOpenStackMachine)
+ if tt.wantErr {
+ g.Expect(err).Error()
+ return
+ }
+
+ g.Expect(&defaultOpenStackMachine.Status.DependentResources).To(Equal(tt.want), cmp.Diff(&defaultOpenStackMachine.Status.DependentResources, tt.want))
+ })
+ }
+}
+
+func TestResolveDependentBastionResources(t *testing.T) {
+ const networkID = "5e8e0d3b-7f3d-4f3e-8b3f-3e3e3e3e3e3e"
+ const portID = "78e0d3b-7f3d-4f3e-8b3f-3e3e3e3e3e3e"
+ const bastionName = "bastion"
+
+ tests := []struct {
+ testName string
+ openStackCluster *infrav1.OpenStackCluster
+ want *infrav1.DependentMachineResources
+ wantErr bool
+ }{
+ {
+ testName: "no Network ID yet and no ports in status",
+ openStackCluster: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ Bastion: &infrav1.Bastion{
+ Enabled: true,
+ },
+ },
+ },
+ want: &infrav1.DependentMachineResources{},
+ wantErr: false,
+ },
+ {
+ testName: "Network ID set but no ports in status",
+ openStackCluster: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ Bastion: &infrav1.Bastion{
+ Enabled: true,
+ },
+ },
+ Status: infrav1.OpenStackClusterStatus{
+ Network: &infrav1.NetworkStatusWithSubnets{
+ NetworkStatus: infrav1.NetworkStatus{
+ ID: networkID,
+ },
+ },
+ },
+ },
+ want: &infrav1.DependentMachineResources{},
+ },
+ {
+ testName: "Network ID set and ports in status",
+ openStackCluster: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ Bastion: &infrav1.Bastion{
+ Enabled: true,
+ },
+ },
+ Status: infrav1.OpenStackClusterStatus{
+ Bastion: &infrav1.BastionStatus{
+ DependentResources: infrav1.DependentMachineResources{
+ PortsStatus: []infrav1.PortStatus{
+ {
+ ID: portID,
+ },
+ },
+ },
+ },
+ Network: &infrav1.NetworkStatusWithSubnets{
+ NetworkStatus: infrav1.NetworkStatus{
+ ID: networkID,
+ },
+ },
+ },
+ },
+ want: &infrav1.DependentMachineResources{
+ PortsStatus: []infrav1.PortStatus{
+ {
+ ID: portID,
+ },
+ },
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.testName, func(t *testing.T) {
+ g := NewWithT(t)
+ mockCtrl := gomock.NewController(t)
+ mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "", logr.Discard())
+
+ _, err := ResolveDependentBastionResources(mockScopeFactory, tt.openStackCluster, bastionName)
+ if tt.wantErr {
+ g.Expect(err).Error()
+ return
+ }
+
+ defaultOpenStackCluster := &infrav1.OpenStackCluster{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "test",
+ },
+ Spec: tt.openStackCluster.Spec,
+ Status: tt.openStackCluster.Status,
+ }
+
+ if tt.openStackCluster.Status.Bastion != nil {
+ g.Expect(&defaultOpenStackCluster.Status.Bastion.DependentResources).To(Equal(tt.want), cmp.Diff(&defaultOpenStackCluster.Status.Bastion.DependentResources, tt.want))
+ }
+ })
+ }
+}
diff --git a/pkg/cloud/services/compute/instance.go b/pkg/cloud/services/compute/instance.go
index e5648a26f0..147f4f729d 100644
--- a/pkg/cloud/services/compute/instance.go
+++ b/pkg/cloud/services/compute/instance.go
@@ -18,7 +18,6 @@ package compute
import (
"context"
- "errors"
"fmt"
"os"
"strconv"
@@ -36,7 +35,6 @@ import (
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients"
- "sigs.k8s.io/cluster-api-provider-openstack/pkg/cloud/services/networking"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/record"
capoerrors "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/errors"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/hash"
@@ -48,180 +46,8 @@ const (
timeoutInstanceDelete = 5 * time.Minute
)
-// normalizePortTarget ensures that the port has a network ID.
-func (s *Service) normalizePortTarget(port *infrav1.PortOpts, openStackCluster *infrav1.OpenStackCluster, portIdx int) error {
- // Treat no Network and empty Network the same
- noNetwork := port.Network == nil || (*port.Network == infrav1.NetworkFilter{})
-
- // No network or subnets defined: use cluster defaults
- if noNetwork && len(port.FixedIPs) == 0 {
- port.Network = &infrav1.NetworkFilter{
- ID: openStackCluster.Status.Network.ID,
- }
- for _, subnet := range openStackCluster.Status.Network.Subnets {
- port.FixedIPs = append(port.FixedIPs, infrav1.FixedIP{
- Subnet: &infrav1.SubnetFilter{
- ID: subnet.ID,
- },
- })
- }
-
- return nil
- }
-
- // No network, but fixed IPs are defined(we handled the no fixed
- // IPs case above): try to infer network from a subnet
- if noNetwork {
- s.scope.Logger().V(4).Info("No network defined for port, attempting to infer from subnet", "port", portIdx)
-
- // Look for a unique subnet defined in FixedIPs. If we find one
- // we can use it to infer the network ID. We don't need to worry
- // here about the case where different FixedIPs have different
- // networks because that will cause an error later when we try
- // to create the port.
- networkID, err := func() (string, error) {
- networkingService, err := s.getNetworkingService()
- if err != nil {
- return "", err
- }
-
- for i, fixedIP := range port.FixedIPs {
- if fixedIP.Subnet == nil {
- continue
- }
-
- subnet, err := networkingService.GetSubnetByFilter(fixedIP.Subnet)
- if err != nil {
- // Multiple matches might be ok later when we restrict matches to a single network
- if errors.Is(err, networking.ErrMultipleMatches) {
- s.scope.Logger().V(4).Info("Couldn't infer network from subnet", "subnetIndex", i, "err", err)
- continue
- }
-
- return "", err
- }
-
- // Cache the subnet ID in the FixedIP
- fixedIP.Subnet.ID = subnet.ID
- return subnet.NetworkID, nil
- }
-
- // TODO: This is a spec error: it should set the machine to failed
- return "", fmt.Errorf("port %d has no network and unable to infer from fixed IPs", portIdx)
- }()
- if err != nil {
- return err
- }
-
- port.Network = &infrav1.NetworkFilter{
- ID: networkID,
- }
-
- return nil
- }
-
- // Nothing to do if network ID is already set
- if port.Network.ID != "" {
- return nil
- }
-
- // Network is defined by Filter
- networkingService, err := s.getNetworkingService()
- if err != nil {
- return err
- }
-
- netIDs, err := networkingService.GetNetworkIDsByFilter(port.Network.ToListOpt())
- if err != nil {
- return err
- }
-
- // TODO: These are spec errors: they should set the machine to failed
- if len(netIDs) > 1 {
- return fmt.Errorf("network filter for port %d returns more than one result", portIdx)
- } else if len(netIDs) == 0 {
- return fmt.Errorf("network filter for port %d returns no networks", portIdx)
- }
-
- port.Network.ID = netIDs[0]
-
- return nil
-}
-
-// normalizePorts ensures that a user-specified PortOpts has all required fields set. Specifically it:
-// - sets the Trunk field to the instance spec default if not specified
-// - sets the Network ID field if not specified.
-func (s *Service) normalizePorts(ports []infrav1.PortOpts, openStackCluster *infrav1.OpenStackCluster, instanceSpec *InstanceSpec) ([]infrav1.PortOpts, error) {
- normalizedPorts := make([]infrav1.PortOpts, 0, len(ports))
- for i := range ports {
- // Deep copy the port to avoid mutating the original
- port := ports[i].DeepCopy()
-
- // No Trunk field specified for the port, inherit the machine default
- if port.Trunk == nil {
- port.Trunk = &instanceSpec.Trunk
- }
-
- if err := s.normalizePortTarget(port, openStackCluster, i); err != nil {
- return nil, err
- }
-
- normalizedPorts = append(normalizedPorts, *port)
- }
- return normalizedPorts, nil
-}
-
-// constructPorts builds an array of ports from the instance spec.
-// If no ports are in the spec, returns a single port for a network connection to the default cluster network.
-func (s *Service) constructPorts(openStackCluster *infrav1.OpenStackCluster, instanceSpec *InstanceSpec) ([]infrav1.PortOpts, error) {
- // Ensure user-specified ports have all required fields
- ports, err := s.normalizePorts(instanceSpec.Ports, openStackCluster, instanceSpec)
- if err != nil {
- return nil, err
- }
-
- // no networks or ports found in the spec, so create a port on the cluster network
- if len(ports) == 0 {
- port := infrav1.PortOpts{
- Network: &infrav1.NetworkFilter{
- ID: openStackCluster.Status.Network.ID,
- },
- Trunk: &instanceSpec.Trunk,
- }
- for _, subnet := range openStackCluster.Status.Network.Subnets {
- port.FixedIPs = append(port.FixedIPs, infrav1.FixedIP{
- Subnet: &infrav1.SubnetFilter{
- ID: subnet.ID,
- },
- })
- }
- ports = []infrav1.PortOpts{port}
- }
-
- // trunk support is required if any port has trunk enabled
- portUsesTrunk := func() bool {
- for _, port := range ports {
- if port.Trunk != nil && *port.Trunk {
- return true
- }
- }
- return false
- }
- if portUsesTrunk() {
- trunkSupported, err := s.isTrunkExtSupported()
- if err != nil {
- return nil, err
- }
- if !trunkSupported {
- return nil, fmt.Errorf("there is no trunk support. please ensure that the trunk extension is enabled in your OpenStack deployment")
- }
- }
-
- return ports, nil
-}
-
-func (s *Service) CreateInstance(eventObject runtime.Object, openStackCluster *infrav1.OpenStackCluster, instanceSpec *InstanceSpec, clusterName string) (*InstanceStatus, error) {
- return s.createInstanceImpl(eventObject, openStackCluster, instanceSpec, clusterName, retryIntervalInstanceStatus)
+func (s *Service) CreateInstance(eventObject runtime.Object, instanceSpec *InstanceSpec, portIDs []string) (*InstanceStatus, error) {
+ return s.createInstanceImpl(eventObject, instanceSpec, retryIntervalInstanceStatus, portIDs)
}
func (s *Service) getAndValidateFlavor(flavorName string) (*flavors.Flavor, error) {
@@ -233,7 +59,7 @@ func (s *Service) getAndValidateFlavor(flavorName string) (*flavors.Flavor, erro
return f, nil
}
-func (s *Service) createInstanceImpl(eventObject runtime.Object, openStackCluster *infrav1.OpenStackCluster, instanceSpec *InstanceSpec, clusterName string, retryInterval time.Duration) (*InstanceStatus, error) {
+func (s *Service) createInstanceImpl(eventObject runtime.Object, instanceSpec *InstanceSpec, retryInterval time.Duration, portIDs []string) (*InstanceStatus, error) {
var server *clients.ServerExt
portList := []servers.Network{}
@@ -242,46 +68,13 @@ func (s *Service) createInstanceImpl(eventObject runtime.Object, openStackCluste
return nil, err
}
- // Ensure we delete the ports we created if we haven't created the server.
- defer func() {
- if server != nil {
- return
- }
-
- if err := s.deletePorts(eventObject, portList); err != nil {
- s.scope.Logger().V(4).Error(err, "Failed to clean up ports after failure")
- }
- }()
-
- ports, err := s.constructPorts(openStackCluster, instanceSpec)
- if err != nil {
- return nil, err
+ if len(portIDs) == 0 {
+ return nil, fmt.Errorf("portIDs cannot be empty")
}
- networkingService, err := s.getNetworkingService()
- if err != nil {
- return nil, err
- }
-
- securityGroups, err := networkingService.GetSecurityGroups(instanceSpec.SecurityGroups)
- if err != nil {
- return nil, fmt.Errorf("error getting security groups: %v", err)
- }
-
- for i := range ports {
- portOpts := &ports[i]
- iTags := []string{}
- if len(instanceSpec.Tags) > 0 {
- iTags = instanceSpec.Tags
- }
- portName := networking.GetPortName(instanceSpec.Name, portOpts, i)
- port, err := networkingService.GetOrCreatePort(eventObject, clusterName, portName, portOpts, securityGroups, iTags)
- if err != nil {
- return nil, err
- }
-
+ for _, portID := range portIDs {
portList = append(portList, servers.Network{
- Port: port.ID,
+ Port: portID,
})
}
@@ -582,7 +375,7 @@ func (s *Service) GetManagementPort(openStackCluster *infrav1.OpenStackCluster,
return &allPorts[0], nil
}
-func (s *Service) DeleteInstance(openStackCluster *infrav1.OpenStackCluster, eventObject runtime.Object, instanceStatus *InstanceStatus, instanceSpec *InstanceSpec) error {
+func (s *Service) DeleteInstance(eventObject runtime.Object, instanceStatus *InstanceStatus, instanceSpec *InstanceSpec) error {
if instanceStatus == nil {
/*
Attaching volumes to an instance is a two-step process:
@@ -605,49 +398,6 @@ func (s *Service) DeleteInstance(openStackCluster *infrav1.OpenStackCluster, eve
return s.deleteVolumes(instanceSpec)
}
- instanceInterfaces, err := s.getComputeClient().ListAttachedInterfaces(instanceStatus.ID())
- if err != nil {
- return err
- }
-
- trunkSupported, err := s.isTrunkExtSupported()
- if err != nil {
- return fmt.Errorf("obtaining network extensions: %v", err)
- }
-
- networkingService, err := s.getNetworkingService()
- if err != nil {
- return err
- }
-
- // get and delete trunks
- for _, port := range instanceInterfaces {
- if err = s.deleteAttachInterface(eventObject, instanceStatus.InstanceIdentifier(), port.PortID); err != nil {
- return err
- }
-
- if trunkSupported {
- if err = networkingService.DeleteTrunk(eventObject, port.PortID); err != nil {
- return err
- }
- }
- if err = networkingService.DeletePort(eventObject, port.PortID); err != nil {
- return err
- }
- }
-
- // delete port of error instance
- if instanceStatus.State() == infrav1.InstanceStateError {
- portOpts, err := s.constructPorts(openStackCluster, instanceSpec)
- if err != nil {
- return err
- }
-
- if err := networkingService.GarbageCollectErrorInstancesPort(eventObject, instanceSpec.Name, portOpts); err != nil {
- return err
- }
- }
-
return s.deleteInstance(eventObject, instanceStatus.InstanceIdentifier())
}
@@ -679,50 +429,6 @@ func (s *Service) deleteVolume(instanceName string, nameSuffix string) error {
return s.getVolumeClient().DeleteVolume(volume.ID, volumes.DeleteOpts{})
}
-func (s *Service) deletePorts(eventObject runtime.Object, nets []servers.Network) error {
- trunkSupported, err := s.isTrunkExtSupported()
- if err != nil {
- return err
- }
-
- for _, n := range nets {
- networkingService, err := s.getNetworkingService()
- if err != nil {
- return err
- }
-
- if trunkSupported {
- if err = networkingService.DeleteTrunk(eventObject, n.Port); err != nil {
- return err
- }
- }
- if err := networkingService.DeletePort(eventObject, n.Port); err != nil {
- return err
- }
- }
- return nil
-}
-
-func (s *Service) deleteAttachInterface(eventObject runtime.Object, instance *InstanceIdentifier, portID string) error {
- err := s.getComputeClient().DeleteAttachedInterface(instance.ID, portID)
- if err != nil {
- if capoerrors.IsNotFound(err) {
- record.Eventf(eventObject, "SuccessfulDeleteAttachInterface", "Attach interface did not exist: instance %s, port %s", instance.ID, portID)
- return nil
- }
- if capoerrors.IsConflict(err) {
- // we don't want to block deletion because of Conflict
- // due to instance must be paused/active/shutoff in order to detach interface
- return nil
- }
- record.Warnf(eventObject, "FailedDeleteAttachInterface", "Failed to delete attach interface: instance %s, port %s: %v", instance.ID, portID, err)
- return err
- }
-
- record.Eventf(eventObject, "SuccessfulDeleteAttachInterface", "Deleted attach interface: instance %s, port %s", instance.ID, portID)
- return nil
-}
-
func (s *Service) deleteInstance(eventObject runtime.Object, instance *InstanceIdentifier) error {
err := s.getComputeClient().DeleteServer(instance.ID)
if err != nil {
@@ -808,23 +514,6 @@ func getTimeout(name string, timeout int) time.Duration {
return time.Duration(timeout)
}
-// isTrunkExtSupported verifies trunk setup on the OpenStack deployment.
-func (s *Service) isTrunkExtSupported() (trunknSupported bool, err error) {
- networkingService, err := s.getNetworkingService()
- if err != nil {
- return false, err
- }
-
- trunkSupport, err := networkingService.GetTrunkSupport()
- if err != nil {
- return false, fmt.Errorf("there was an issue verifying whether trunk support is available, Please try again later: %v", err)
- }
- if !trunkSupport {
- return false, nil
- }
- return true, nil
-}
-
func HashInstanceSpec(computeInstance *InstanceSpec) (string, error) {
instanceHash, err := hash.ComputeSpewHash(computeInstance)
if err != nil {
diff --git a/pkg/cloud/services/compute/instance_test.go b/pkg/cloud/services/compute/instance_test.go
index d89849f507..345987d510 100644
--- a/pkg/cloud/services/compute/instance_test.go
+++ b/pkg/cloud/services/compute/instance_test.go
@@ -24,100 +24,22 @@ import (
"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/blockstorage/v3/volumes"
- common "github.com/gophercloud/gophercloud/openstack/common/extensions"
- "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/attachinterfaces"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/availabilityzones"
"github.com/gophercloud/gophercloud/openstack/compute/v2/flavors"
"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/attributestags"
- "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/trunks"
- "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/gomega"
- . "github.com/onsi/gomega/gstruct"
- gomegatypes "github.com/onsi/gomega/types"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/utils/pointer"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
"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/networking"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
)
-type gomegaMockMatcher struct {
- matcher gomegatypes.GomegaMatcher
- description string
-}
-
-func newGomegaMockMatcher(matcher gomegatypes.GomegaMatcher) *gomegaMockMatcher {
- return &gomegaMockMatcher{
- matcher: matcher,
- description: "",
- }
-}
-
-func (m *gomegaMockMatcher) String() string {
- return m.description
-}
-
-func (m *gomegaMockMatcher) Matches(x interface{}) bool {
- success, err := m.matcher.Match(x)
- Expect(err).NotTo(HaveOccurred())
- if !success {
- m.description = m.matcher.FailureMessage(x)
- }
- return success
-}
-
-func Test_getPortName(t *testing.T) {
- type args struct {
- instanceName string
- opts *infrav1.PortOpts
- netIndex int
- }
- tests := []struct {
- name string
- args args
- want string
- }{
- {
- name: "with nil PortOpts",
- args: args{"test-1-instance", nil, 2},
- want: "test-1-instance-2",
- },
- {
- name: "with PortOpts name suffix",
- args: args{"test-1-instance", &infrav1.PortOpts{NameSuffix: "foo"}, 4},
- want: "test-1-instance-foo",
- },
- {
- name: "without PortOpts name suffix",
- args: args{"test-1-instance", &infrav1.PortOpts{}, 4},
- want: "test-1-instance-4",
- },
- {
- name: "with PortOpts name suffix",
- args: args{"test-1-instance", &infrav1.PortOpts{NameSuffix: "foo2", Network: &infrav1.NetworkFilter{ID: "bar"}, DisablePortSecurity: pointer.Bool(true)}, 4},
- want: "test-1-instance-foo2",
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- if got := networking.GetPortName(tt.args.instanceName, tt.args.opts, tt.args.netIndex); got != tt.want {
- t.Errorf("getPortName() = %v, want %v", got, tt.want)
- }
- })
- }
-}
-
func TestService_getImageID(t *testing.T) {
const imageID = "ce96e584-7ebc-46d6-9e55-987d72e3806c"
const imageName = "test-image"
@@ -218,6 +140,8 @@ func TestService_getImageID(t *testing.T) {
}
}
+var portUUIDs = []string{"e7b7f3d1-0a81-40b1-bfa6-a22a31b17816"}
+
const (
networkUUID = "d412171b-9fd7-41c1-95a6-c24e5953974d"
subnetUUID = "d2d8d98d-b234-477e-a547-868b7cb5d6a5"
@@ -240,24 +164,6 @@ const (
failureDomain = "test-failure-domain"
)
-func getDefaultOpenStackCluster() *infrav1.OpenStackCluster {
- return &infrav1.OpenStackCluster{
- Spec: infrav1.OpenStackClusterSpec{},
- Status: infrav1.OpenStackClusterStatus{
- Network: &infrav1.NetworkStatusWithSubnets{
- NetworkStatus: infrav1.NetworkStatus{
- ID: networkUUID,
- },
- Subnets: []infrav1.Subnet{
- {ID: subnetUUID},
- },
- },
- ControlPlaneSecurityGroup: &infrav1.SecurityGroupStatus{ID: controlPlaneSecurityGroupUUID},
- WorkerSecurityGroup: &infrav1.SecurityGroupStatus{ID: workerSecurityGroupUUID},
- },
- }
-}
-
func getDefaultInstanceSpec() *InstanceSpec {
return &InstanceSpec{
Name: openStackMachineName,
@@ -327,54 +233,6 @@ func TestService_ReconcileInstance(t *testing.T) {
}
}
- // Expected calls to create a server with a single default port
- expectUseExistingDefaultPort := func(networkRecorder *mock.MockNetworkClientMockRecorder) {
- // Returning a pre-existing port requires fewer mocks
- networkRecorder.ListPort(ports.ListOpts{
- Name: portName,
- NetworkID: networkUUID,
- }).Return([]ports.Port{
- {
- ID: portUUID,
- NetworkID: networkUUID,
- },
- }, nil)
- }
-
- expectCreatePort := func(networkRecorder *mock.MockNetworkClientMockRecorder, name string, networkID string) {
- networkRecorder.ListPort(ports.ListOpts{
- Name: name,
- NetworkID: networkID,
- }).Return([]ports.Port{}, nil)
-
- // gomock won't match a pointer to a nil slice in SecurityGroups, so we do this
- networkRecorder.CreatePort(gomock.Any()).DoAndReturn(func(createOpts ports.CreateOptsBuilder) (*ports.Port, error) {
- createOptsMap, err := createOpts.ToPortCreateMap()
- Expect(err).NotTo(HaveOccurred())
-
- // Match only the fields we're interested in
- portOpts := createOptsMap["port"].(map[string]interface{})
- Expect(portOpts).To(MatchKeys(IgnoreExtras, Keys{
- "network_id": Equal(networkUUID),
- "name": Equal(portName),
- }))
-
- return &ports.Port{
- ID: portUUID,
- NetworkID: networkUUID,
- Name: portName,
- Description: portOpts["description"].(string),
- }, nil
- })
- networkRecorder.ReplaceAllAttributesTags("ports", portUUID, attributestags.ReplaceAllOpts{Tags: []string{"test-tag"}}).Return(nil, nil)
- }
-
- // Expected calls if we delete the network port
- expectCleanupDefaultPort := func(networkRecorder *mock.MockNetworkClientMockRecorder) {
- networkRecorder.ListExtensions()
- networkRecorder.DeletePort(portUUID).Return(nil)
- }
-
// Expected calls when using default flavor
expectDefaultFlavor := func(computeRecorder *mock.MockComputeClientMockRecorder) {
f := flavors.Flavor{
@@ -444,52 +302,12 @@ func TestService_ReconcileInstance(t *testing.T) {
name: "Defaults",
getInstanceSpec: getDefaultInstanceSpec,
expect: func(r *recorders) {
- expectUseExistingDefaultPort(r.network)
expectDefaultFlavor(r.compute)
expectCreateServer(r.compute, getDefaultServerMap(), false)
},
wantErr: false,
},
- {
- name: "Delete ports on server create error",
- getInstanceSpec: getDefaultInstanceSpec,
- expect: func(r *recorders) {
- expectUseExistingDefaultPort(r.network)
- expectDefaultFlavor(r.compute)
-
- expectCreateServer(r.compute, getDefaultServerMap(), true)
-
- // Make sure we delete ports
- expectCleanupDefaultPort(r.network)
- },
- wantErr: true,
- },
- {
- name: "Delete previously created ports on port creation error",
- getInstanceSpec: func() *InstanceSpec {
- s := getDefaultInstanceSpec()
- s.Ports = []infrav1.PortOpts{
- {Description: "Test port 0"},
- {Description: "Test port 1"},
- }
- return s
- },
- expect: func(r *recorders) {
- expectDefaultFlavor(r.compute)
- expectUseExistingDefaultPort(r.network)
-
- // Looking up the second port fails
- r.network.ListPort(ports.ListOpts{
- Name: "test-openstack-machine-1",
- NetworkID: networkUUID,
- }).Return(nil, fmt.Errorf("test error"))
-
- // We should cleanup the first port
- expectCleanupDefaultPort(r.network)
- },
- wantErr: true,
- },
{
name: "Boot from volume success",
getInstanceSpec: func() *InstanceSpec {
@@ -500,7 +318,6 @@ func TestService_ReconcileInstance(t *testing.T) {
return s
},
expect: func(r *recorders) {
- expectUseExistingDefaultPort(r.network)
expectDefaultFlavor(r.compute)
r.volume.ListVolumes(volumes.ListOpts{Name: fmt.Sprintf("%s-root", openStackMachineName)}).
@@ -545,7 +362,6 @@ func TestService_ReconcileInstance(t *testing.T) {
return s
},
expect: func(r *recorders) {
- expectUseExistingDefaultPort(r.network)
expectDefaultFlavor(r.compute)
r.volume.ListVolumes(volumes.ListOpts{Name: fmt.Sprintf("%s-root", openStackMachineName)}).
@@ -589,7 +405,6 @@ func TestService_ReconcileInstance(t *testing.T) {
return s
},
expect: func(r *recorders) {
- expectUseExistingDefaultPort(r.network)
expectDefaultFlavor(r.compute)
r.volume.ListVolumes(volumes.ListOpts{Name: fmt.Sprintf("%s-root", openStackMachineName)}).
@@ -603,8 +418,6 @@ func TestService_ReconcileInstance(t *testing.T) {
Multiattach: false,
}).Return(&volumes.Volume{ID: rootVolumeUUID}, nil)
expectVolumePoll(r.volume, rootVolumeUUID, []string{"creating", "error"})
-
- expectCleanupDefaultPort(r.network)
},
wantErr: true,
},
@@ -637,7 +450,6 @@ func TestService_ReconcileInstance(t *testing.T) {
return s
},
expect: func(r *recorders) {
- expectUseExistingDefaultPort(r.network)
expectDefaultFlavor(r.compute)
r.volume.ListVolumes(volumes.ListOpts{Name: fmt.Sprintf("%s-root", openStackMachineName)}).
@@ -724,7 +536,6 @@ func TestService_ReconcileInstance(t *testing.T) {
return s
},
expect: func(r *recorders) {
- expectUseExistingDefaultPort(r.network)
expectDefaultFlavor(r.compute)
r.volume.ListVolumes(volumes.ListOpts{Name: fmt.Sprintf("%s-etcd", openStackMachineName)}).
@@ -792,7 +603,6 @@ func TestService_ReconcileInstance(t *testing.T) {
return s
},
expect: func(r *recorders) {
- expectUseExistingDefaultPort(r.network)
expectDefaultFlavor(r.compute)
r.volume.ListVolumes(volumes.ListOpts{Name: fmt.Sprintf("%s-etcd", openStackMachineName)}).
@@ -848,68 +658,7 @@ func TestService_ReconcileInstance(t *testing.T) {
return s
},
expect: func(r *recorders) {
- expectUseExistingDefaultPort(r.network)
expectDefaultFlavor(r.compute)
-
- // Make sure we delete ports
- expectCleanupDefaultPort(r.network)
- },
- wantErr: true,
- },
- {
- name: "Delete trunks on port creation error",
- getInstanceSpec: func() *InstanceSpec {
- s := getDefaultInstanceSpec()
- s.Ports = []infrav1.PortOpts{
- {Description: "Test port 0", Trunk: pointer.Bool(true)},
- {Description: "Test port 1"},
- }
- return s
- },
- expect: func(r *recorders) {
- expectDefaultFlavor(r.compute)
- extensions := []extensions.Extension{
- {Extension: common.Extension{Alias: "trunk"}},
- }
- r.network.ListExtensions().Return(extensions, nil)
-
- expectCreatePort(r.network, portName, networkUUID)
-
- // Check for existing trunk
- r.network.ListTrunk(newGomegaMockMatcher(
- MatchFields(IgnoreExtras, Fields{
- "Name": Equal(portName),
- "PortID": Equal(portUUID),
- }),
- )).Return([]trunks.Trunk{}, nil)
-
- // Create new trunk
- r.network.CreateTrunk(newGomegaMockMatcher(MatchFields(IgnoreExtras, Fields{
- "Name": Equal(portName),
- "PortID": Equal(portUUID),
- }))).Return(&trunks.Trunk{
- PortID: portUUID,
- ID: trunkUUID,
- }, nil)
- r.network.ReplaceAllAttributesTags("trunks", trunkUUID, attributestags.ReplaceAllOpts{Tags: []string{"test-tag"}}).Return(nil, nil)
-
- // Looking up the second port fails
- r.network.ListPort(ports.ListOpts{
- Name: "test-openstack-machine-1",
- NetworkID: networkUUID,
- }).Return(nil, fmt.Errorf("test error"))
-
- r.network.ListExtensions().Return(extensions, nil)
-
- r.network.ListTrunk(newGomegaMockMatcher(
- MatchFields(IgnoreExtras, Fields{
- "PortID": Equal(portUUID),
- }),
- )).Return([]trunks.Trunk{{ID: trunkUUID}}, nil)
-
- // We should cleanup the first port and its trunk
- r.network.DeleteTrunk(trunkUUID).Return(nil)
- r.network.DeletePort(portUUID).Return(nil)
},
wantErr: true,
},
@@ -932,7 +681,7 @@ func TestService_ReconcileInstance(t *testing.T) {
}
// Call CreateInstance with a reduced retry interval to speed up the test
- _, err = s.createInstanceImpl(&infrav1.OpenStackMachine{}, getDefaultOpenStackCluster(), tt.getInstanceSpec(), "cluster-name", time.Nanosecond)
+ _, err = s.createInstanceImpl(&infrav1.OpenStackMachine{}, tt.getInstanceSpec(), time.Nanosecond, portUUIDs)
if (err != nil) != tt.wantErr {
t.Errorf("Service.CreateInstance() error = %v, wantErr %v", err, tt.wantErr)
return
@@ -977,21 +726,6 @@ func TestService_DeleteInstance(t *testing.T) {
eventObject: &infrav1.OpenStackMachine{},
instanceStatus: getDefaultInstanceStatus,
expect: func(r *recorders) {
- r.compute.ListAttachedInterfaces(instanceUUID).Return([]attachinterfaces.Interface{
- {
- PortID: portUUID,
- },
- }, nil)
- r.network.ListExtensions().Return([]extensions.Extension{{
- Extension: common.Extension{
- Alias: "trunk",
- },
- }}, nil)
- r.compute.DeleteAttachedInterface(instanceUUID, portUUID).Return(nil)
- // FIXME: Why we are looking for a trunk when we know the port is not trunked?
- r.network.ListTrunk(trunks.ListOpts{PortID: portUUID}).Return([]trunks.Trunk{}, nil)
- r.network.DeletePort(portUUID).Return(nil)
-
r.compute.DeleteServer(instanceUUID).Return(nil)
r.compute.GetServer(instanceUUID).Return(nil, gophercloud.ErrDefault404{})
},
@@ -1043,372 +777,9 @@ func TestService_DeleteInstance(t *testing.T) {
RootVolume: tt.rootVolume,
}
- if err := s.DeleteInstance(&infrav1.OpenStackCluster{}, tt.eventObject, tt.instanceStatus(), instanceSpec); (err != nil) != tt.wantErr {
+ if err := s.DeleteInstance(tt.eventObject, tt.instanceStatus(), instanceSpec); (err != nil) != tt.wantErr {
t.Errorf("Service.DeleteInstance() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
-
-func TestService_normalizePorts(t *testing.T) {
- mockCtrl := gomock.NewController(t)
- defer mockCtrl.Finish()
-
- const (
- defaultNetworkID = "3c66f3ca-2d26-4d9d-ae3b-568f54129773"
- defaultSubnetID = "d8dbba89-8c39-4192-a571-e702fca35bac"
-
- networkID = "afa54944-1443-4132-9ef5-ce37eb4d6ab6"
- subnetID = "d786e715-c299-4a97-911d-640c10fc0392"
- )
-
- openStackCluster := &infrav1.OpenStackCluster{
- Status: infrav1.OpenStackClusterStatus{
- Network: &infrav1.NetworkStatusWithSubnets{
- NetworkStatus: infrav1.NetworkStatus{
- ID: defaultNetworkID,
- },
- Subnets: []infrav1.Subnet{
- {ID: defaultSubnetID},
- },
- },
- },
- }
-
- tests := []struct {
- name string
- ports []infrav1.PortOpts
- instanceTrunk bool
- expectNetwork func(m *mock.MockNetworkClientMockRecorder)
- want []infrav1.PortOpts
- wantErr bool
- }{
- {
- name: "No ports: no ports",
- ports: []infrav1.PortOpts{},
- want: []infrav1.PortOpts{},
- },
- {
- name: "Nil network, no fixed IPs: cluster defaults",
- ports: []infrav1.PortOpts{
- {
- Network: nil,
- FixedIPs: nil,
- },
- },
- want: []infrav1.PortOpts{
- {
- Network: &infrav1.NetworkFilter{
- ID: defaultNetworkID,
- },
- FixedIPs: []infrav1.FixedIP{
- {
- Subnet: &infrav1.SubnetFilter{
- ID: defaultSubnetID,
- },
- },
- },
- Trunk: pointer.Bool(false),
- },
- },
- },
- {
- name: "Empty network, no fixed IPs: cluster defaults",
- ports: []infrav1.PortOpts{
- {
- Network: &infrav1.NetworkFilter{},
- FixedIPs: nil,
- },
- },
- want: []infrav1.PortOpts{
- {
- Network: &infrav1.NetworkFilter{
- ID: defaultNetworkID,
- },
- FixedIPs: []infrav1.FixedIP{
- {
- Subnet: &infrav1.SubnetFilter{
- ID: defaultSubnetID,
- },
- },
- },
- Trunk: pointer.Bool(false),
- },
- },
- },
- {
- name: "Port inherits trunk from instance",
- ports: []infrav1.PortOpts{
- {
- Network: &infrav1.NetworkFilter{},
- FixedIPs: nil,
- },
- },
- instanceTrunk: true,
- want: []infrav1.PortOpts{
- {
- Network: &infrav1.NetworkFilter{
- ID: defaultNetworkID,
- },
- FixedIPs: []infrav1.FixedIP{
- {
- Subnet: &infrav1.SubnetFilter{
- ID: defaultSubnetID,
- },
- },
- },
- Trunk: pointer.Bool(true),
- },
- },
- },
- {
- name: "Port overrides trunk from instance",
- ports: []infrav1.PortOpts{
- {
- Network: &infrav1.NetworkFilter{},
- FixedIPs: nil,
- Trunk: pointer.Bool(true),
- },
- },
- want: []infrav1.PortOpts{
- {
- Network: &infrav1.NetworkFilter{
- ID: defaultNetworkID,
- },
- FixedIPs: []infrav1.FixedIP{
- {
- Subnet: &infrav1.SubnetFilter{
- ID: defaultSubnetID,
- },
- },
- },
- Trunk: pointer.Bool(true),
- },
- },
- },
- {
- name: "Network defined by ID: unchanged",
- ports: []infrav1.PortOpts{
- {
- Network: &infrav1.NetworkFilter{
- ID: networkID,
- },
- },
- },
- want: []infrav1.PortOpts{
- {
- Network: &infrav1.NetworkFilter{
- ID: networkID,
- },
- Trunk: pointer.Bool(false),
- },
- },
- },
- {
- name: "Network defined by filter: add ID from network lookup",
- ports: []infrav1.PortOpts{
- {
- Network: &infrav1.NetworkFilter{
- Name: "test-network",
- },
- },
- },
- expectNetwork: func(m *mock.MockNetworkClientMockRecorder) {
- m.ListNetwork(networks.ListOpts{Name: "test-network"}).Return([]networks.Network{
- {ID: networkID},
- }, nil)
- },
- want: []infrav1.PortOpts{
- {
- Network: &infrav1.NetworkFilter{
- ID: networkID,
- Name: "test-network",
- },
- Trunk: pointer.Bool(false),
- },
- },
- },
- {
- name: "No network, fixed IP has subnet by ID: add ID from subnet",
- ports: []infrav1.PortOpts{
- {
- FixedIPs: []infrav1.FixedIP{
- {
- Subnet: &infrav1.SubnetFilter{
- ID: subnetID,
- },
- },
- },
- },
- },
- expectNetwork: func(m *mock.MockNetworkClientMockRecorder) {
- m.GetSubnet(subnetID).Return(&subnets.Subnet{ID: subnetID, NetworkID: networkID}, nil)
- },
- want: []infrav1.PortOpts{
- {
- Network: &infrav1.NetworkFilter{
- ID: networkID,
- },
- FixedIPs: []infrav1.FixedIP{
- {
- Subnet: &infrav1.SubnetFilter{
- ID: subnetID,
- },
- },
- },
- Trunk: pointer.Bool(false),
- },
- },
- },
- {
- name: "No network, fixed IP has subnet by filter: add ID from subnet",
- ports: []infrav1.PortOpts{
- {
- FixedIPs: []infrav1.FixedIP{
- {
- Subnet: &infrav1.SubnetFilter{
- Name: "test-subnet",
- },
- },
- },
- },
- },
- expectNetwork: func(m *mock.MockNetworkClientMockRecorder) {
- m.ListSubnet(subnets.ListOpts{Name: "test-subnet"}).Return([]subnets.Subnet{
- {ID: subnetID, NetworkID: networkID},
- }, nil)
- },
- want: []infrav1.PortOpts{
- {
- Network: &infrav1.NetworkFilter{
- ID: networkID,
- },
- FixedIPs: []infrav1.FixedIP{
- {
- Subnet: &infrav1.SubnetFilter{
- ID: subnetID,
- Name: "test-subnet",
- },
- },
- },
- Trunk: pointer.Bool(false),
- },
- },
- },
- {
- name: "No network, fixed IP subnet returns no matches: error",
- ports: []infrav1.PortOpts{
- {
- FixedIPs: []infrav1.FixedIP{
- {
- Subnet: &infrav1.SubnetFilter{
- Name: "test-subnet",
- },
- },
- },
- },
- },
- expectNetwork: func(m *mock.MockNetworkClientMockRecorder) {
- m.ListSubnet(subnets.ListOpts{Name: "test-subnet"}).Return([]subnets.Subnet{}, nil)
- },
- wantErr: true,
- },
- {
- name: "No network, only fixed IP subnet returns multiple matches: error",
- ports: []infrav1.PortOpts{
- {
- FixedIPs: []infrav1.FixedIP{
- {
- Subnet: &infrav1.SubnetFilter{
- Name: "test-subnet",
- },
- },
- },
- },
- },
- expectNetwork: func(m *mock.MockNetworkClientMockRecorder) {
- m.ListSubnet(subnets.ListOpts{Name: "test-subnet"}).Return([]subnets.Subnet{
- {ID: subnetID, NetworkID: networkID},
- {ID: "8008494c-301e-4e5c-951b-a8ab568447fd", NetworkID: "5d48bfda-db28-42ee-8374-50e13d1fe5ea"},
- }, nil)
- },
- wantErr: true,
- },
- {
- name: "No network, first fixed IP subnet returns multiple matches: used ID from second fixed IP",
- ports: []infrav1.PortOpts{
- {
- FixedIPs: []infrav1.FixedIP{
- {
- Subnet: &infrav1.SubnetFilter{
- Name: "test-subnet1",
- },
- },
- {
- Subnet: &infrav1.SubnetFilter{
- Name: "test-subnet2",
- },
- },
- },
- },
- },
- expectNetwork: func(m *mock.MockNetworkClientMockRecorder) {
- m.ListSubnet(subnets.ListOpts{Name: "test-subnet1"}).Return([]subnets.Subnet{
- {ID: subnetID, NetworkID: networkID},
- {ID: "8008494c-301e-4e5c-951b-a8ab568447fd", NetworkID: "5d48bfda-db28-42ee-8374-50e13d1fe5ea"},
- }, nil)
- m.ListSubnet(subnets.ListOpts{Name: "test-subnet2"}).Return([]subnets.Subnet{
- {ID: subnetID, NetworkID: networkID},
- }, nil)
- },
- want: []infrav1.PortOpts{
- {
- Network: &infrav1.NetworkFilter{
- ID: networkID,
- },
- FixedIPs: []infrav1.FixedIP{
- {
- Subnet: &infrav1.SubnetFilter{
- Name: "test-subnet1",
- },
- },
- {
- Subnet: &infrav1.SubnetFilter{
- ID: subnetID,
- Name: "test-subnet2",
- },
- },
- },
- Trunk: pointer.Bool(false),
- },
- },
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- g := NewWithT(t)
-
- // MockScopeFactory also implements Scope so no need to create separate Scope from it.
- mockScope := scope.NewMockScopeFactory(mockCtrl, "", logr.Discard())
- if tt.expectNetwork != nil {
- tt.expectNetwork(mockScope.NetworkClient.EXPECT())
- }
-
- s := &Service{
- scope: mockScope,
- }
- instanceSpec := &InstanceSpec{
- Trunk: tt.instanceTrunk,
- }
-
- got, err := s.normalizePorts(tt.ports, openStackCluster, instanceSpec)
- if tt.wantErr {
- g.Expect(err).To(HaveOccurred())
- return
- }
-
- g.Expect(err).NotTo(HaveOccurred())
- g.Expect(got).To(Equal(tt.want), cmp.Diff(got, tt.want))
- })
- }
-}
diff --git a/pkg/cloud/services/compute/referenced_resources.go b/pkg/cloud/services/compute/referenced_resources.go
index b9350f8d06..1d2de809a2 100644
--- a/pkg/cloud/services/compute/referenced_resources.go
+++ b/pkg/cloud/services/compute/referenced_resources.go
@@ -18,35 +18,64 @@ package compute
import (
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ "sigs.k8s.io/cluster-api-provider-openstack/pkg/cloud/services/networking"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
)
// ResolveReferencedMachineResources is responsible for populating ReferencedMachineResources with IDs of
// the resources referenced in the OpenStackMachineSpec by querying the OpenStack APIs. It'll return error
// if resources cannot be found or their filters are ambiguous.
-func ResolveReferencedMachineResources(scope scope.Scope, spec *infrav1.OpenStackMachineSpec, resources *infrav1.ReferencedMachineResources) error {
- compute, err := NewService(scope)
+// Note that we only set the fields in ReferencedMachineResources that are not set yet. This is ok because:
+// - OpenStackMachine is immutable, so we can't change the spec after the machine is created.
+// - the bastion is mutable, but we delete the bastion when the spec changes, so the bastion status will be empty.
+func ResolveReferencedMachineResources(scope scope.Scope, openStackCluster *infrav1.OpenStackCluster, spec *infrav1.OpenStackMachineSpec, resources *infrav1.ReferencedMachineResources) (changed bool, err error) {
+ changed = false
+
+ computeService, err := NewService(scope)
if err != nil {
- return err
+ return changed, err
+ }
+
+ networkingService, err := networking.NewService(scope)
+ if err != nil {
+ return changed, err
}
// ServerGroup is optional, so we only need to resolve it if it's set in the spec and not in ReferencedMachineResources yet.
if spec.ServerGroup != nil && resources.ServerGroupID == "" {
- serverGroupID, err := compute.GetServerGroupID(spec.ServerGroup)
+ serverGroupID, err := computeService.GetServerGroupID(spec.ServerGroup)
if err != nil {
- return err
+ return changed, err
}
resources.ServerGroupID = serverGroupID
+ changed = true
}
// Image is required, so we need to resolve it if it's not set in ReferencedMachineResources yet.
if resources.ImageID == "" {
- imageID, err := compute.GetImageID(spec.Image)
+ imageID, err := computeService.GetImageID(spec.Image)
if err != nil {
- return err
+ return changed, err
}
resources.ImageID = imageID
+ changed = true
+ }
+
+ // Network resources are required in order to get ports options.
+ if len(resources.PortsOpts) == 0 && openStackCluster.Status.Network != nil {
+ // For now we put this here but realistically an OpenStack administrator could enable/disable trunk
+ // support at any time, so we should probably check this on every reconcile.
+ trunkSupported, err := networkingService.IsTrunkExtSupported()
+ if err != nil {
+ return changed, err
+ }
+ portsOpts, err := networkingService.ConstructPorts(openStackCluster, spec.Ports, spec.Trunk, trunkSupported)
+ if err != nil {
+ return changed, err
+ }
+ resources.PortsOpts = portsOpts
+ changed = true
}
- return nil
+ return changed, nil
}
diff --git a/pkg/cloud/services/compute/referenced_resources_test.go b/pkg/cloud/services/compute/referenced_resources_test.go
index 6a976325c4..74dc9d8c63 100644
--- a/pkg/cloud/services/compute/referenced_resources_test.go
+++ b/pkg/cloud/services/compute/referenced_resources_test.go
@@ -24,6 +24,7 @@ import (
"github.com/google/go-cmp/cmp"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/servergroups"
"github.com/gophercloud/gophercloud/openstack/imageservice/v2/images"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions"
. "github.com/onsi/gomega"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
@@ -32,6 +33,7 @@ import (
)
func Test_ResolveReferencedMachineResources(t *testing.T) {
+ constFalse := false
const serverGroupID1 = "ce96e584-7ebc-46d6-9e55-987d72e3806c"
const imageID1 = "de96e584-7ebc-46d6-9e55-987d72e3806c"
@@ -43,8 +45,11 @@ func Test_ResolveReferencedMachineResources(t *testing.T) {
testName string
serverGroupFilter *infrav1.ServerGroupFilter
imageFilter *infrav1.ImageFilter
+ portsOpts *[]infrav1.PortOpts
+ clusterStatus *infrav1.OpenStackClusterStatus
expectComputeMock func(m *mock.MockComputeClientMockRecorder)
expectImageMock func(m *mock.MockImageClientMockRecorder)
+ expectNetworkMock func(m *mock.MockNetworkClientMockRecorder)
want *infrav1.ReferencedMachineResources
wantErr bool
}{
@@ -54,6 +59,7 @@ func Test_ResolveReferencedMachineResources(t *testing.T) {
imageFilter: &infrav1.ImageFilter{ID: imageID1},
expectComputeMock: func(m *mock.MockComputeClientMockRecorder) {},
expectImageMock: func(m *mock.MockImageClientMockRecorder) {},
+ expectNetworkMock: func(m *mock.MockNetworkClientMockRecorder) {},
want: &infrav1.ReferencedMachineResources{ImageID: imageID1, ServerGroupID: serverGroupID1},
wantErr: false,
},
@@ -62,6 +68,7 @@ func Test_ResolveReferencedMachineResources(t *testing.T) {
serverGroupFilter: nil,
expectComputeMock: func(m *mock.MockComputeClientMockRecorder) {},
expectImageMock: func(m *mock.MockImageClientMockRecorder) {},
+ expectNetworkMock: func(m *mock.MockNetworkClientMockRecorder) {},
want: minimumReferences,
wantErr: false,
},
@@ -70,6 +77,7 @@ func Test_ResolveReferencedMachineResources(t *testing.T) {
serverGroupFilter: &infrav1.ServerGroupFilter{},
expectComputeMock: func(m *mock.MockComputeClientMockRecorder) {},
expectImageMock: func(m *mock.MockImageClientMockRecorder) {},
+ expectNetworkMock: func(m *mock.MockNetworkClientMockRecorder) {},
want: minimumReferences,
wantErr: false,
},
@@ -81,9 +89,10 @@ func Test_ResolveReferencedMachineResources(t *testing.T) {
[]servergroups.ServerGroup{},
nil)
},
- expectImageMock: func(m *mock.MockImageClientMockRecorder) {},
- want: &infrav1.ReferencedMachineResources{},
- wantErr: true,
+ expectImageMock: func(m *mock.MockImageClientMockRecorder) {},
+ expectNetworkMock: func(m *mock.MockNetworkClientMockRecorder) {},
+ want: &infrav1.ReferencedMachineResources{},
+ wantErr: true,
},
{
testName: "Image by Name not found",
@@ -94,8 +103,46 @@ func Test_ResolveReferencedMachineResources(t *testing.T) {
[]images.Image{},
nil)
},
- want: &infrav1.ReferencedMachineResources{},
- wantErr: true,
+ expectNetworkMock: func(m *mock.MockNetworkClientMockRecorder) {},
+ want: &infrav1.ReferencedMachineResources{},
+ wantErr: true,
+ },
+ {
+ testName: "PortsOpts set",
+ clusterStatus: &infrav1.OpenStackClusterStatus{
+ Network: &infrav1.NetworkStatusWithSubnets{
+ Subnets: []infrav1.Subnet{
+ {
+ ID: "test-subnet-id",
+ },
+ },
+ },
+ },
+ portsOpts: &[]infrav1.PortOpts{
+ {
+ Network: &infrav1.NetworkFilter{
+ ID: "test-network-id",
+ },
+ Trunk: &constFalse,
+ },
+ },
+ expectComputeMock: func(m *mock.MockComputeClientMockRecorder) {},
+ expectImageMock: func(m *mock.MockImageClientMockRecorder) {},
+ expectNetworkMock: func(m *mock.MockNetworkClientMockRecorder) {
+ m.ListExtensions().Return([]extensions.Extension{}, nil)
+ },
+ want: &infrav1.ReferencedMachineResources{
+ ImageID: imageID1,
+ PortsOpts: []infrav1.PortOpts{
+ {
+ Network: &infrav1.NetworkFilter{
+ ID: "test-network-id",
+ },
+ Trunk: &constFalse,
+ },
+ },
+ },
+ wantErr: false,
},
}
for _, tt := range tests {
@@ -106,21 +153,32 @@ func Test_ResolveReferencedMachineResources(t *testing.T) {
tt.expectComputeMock(mockScopeFactory.ComputeClient.EXPECT())
tt.expectImageMock(mockScopeFactory.ImageClient.EXPECT())
+ tt.expectNetworkMock(mockScopeFactory.NetworkClient.EXPECT())
// Set defaults for required fields
imageFilter := &infrav1.ImageFilter{ID: imageID1}
if tt.imageFilter != nil {
imageFilter = tt.imageFilter
}
+ portsOpts := &[]infrav1.PortOpts{}
+ if tt.portsOpts != nil {
+ portsOpts = tt.portsOpts
+ }
+
+ openStackCluster := &infrav1.OpenStackCluster{}
+ if tt.clusterStatus != nil {
+ openStackCluster.Status = *tt.clusterStatus
+ }
machineSpec := &infrav1.OpenStackMachineSpec{
ServerGroup: tt.serverGroupFilter,
Image: *imageFilter,
+ Ports: *portsOpts,
}
resources := &infrav1.ReferencedMachineResources{}
- err := ResolveReferencedMachineResources(mockScopeFactory, machineSpec, resources)
+ _, err := ResolveReferencedMachineResources(mockScopeFactory, openStackCluster, machineSpec, resources)
if tt.wantErr {
g.Expect(err).Error()
return
diff --git a/pkg/cloud/services/networking/port.go b/pkg/cloud/services/networking/port.go
index 84b9bfc618..6848776358 100644
--- a/pkg/cloud/services/networking/port.go
+++ b/pkg/cloud/services/networking/port.go
@@ -18,6 +18,7 @@ package networking
import (
"context"
+ "errors"
"fmt"
"strings"
"time"
@@ -30,6 +31,7 @@ import (
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/record"
+ "sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
capoerrors "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/errors"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/names"
)
@@ -54,25 +56,10 @@ func (s *Service) GetPortFromInstanceIP(instanceID string, ip string) ([]ports.P
return s.client.ListPort(portOpts)
}
-func (s *Service) GetOrCreatePort(eventObject runtime.Object, clusterName string, portName string, portOpts *infrav1.PortOpts, instanceSecurityGroups []string, instanceTags []string) (*ports.Port, error) {
+func (s *Service) CreatePort(eventObject runtime.Object, clusterName string, portName string, portOpts *infrav1.PortOpts, instanceSecurityGroups []string, instanceTags []string) (*ports.Port, error) {
+ var err error
networkID := portOpts.Network.ID
- existingPorts, err := s.client.ListPort(ports.ListOpts{
- Name: portName,
- NetworkID: networkID,
- })
- if err != nil {
- return nil, fmt.Errorf("searching for existing port for server: %v", err)
- }
-
- if len(existingPorts) == 1 {
- return &existingPorts[0], nil
- }
-
- if len(existingPorts) > 1 {
- return nil, fmt.Errorf("multiple ports found with name \"%s\"", portName)
- }
-
description := portOpts.Description
if description == "" {
description = names.GetDescription(clusterName)
@@ -239,6 +226,7 @@ func getPortProfile(p infrav1.BindingProfile) map[string]interface{} {
return portProfile
}
+// DeletePort deletes the Neutron port with the given ID.
func (s *Service) DeletePort(eventObject runtime.Object, portID string) error {
var err error
err = wait.PollUntilContextTimeout(context.TODO(), retryIntervalPortDelete, timeoutPortDelete, true, func(_ context.Context) (bool, error) {
@@ -265,7 +253,22 @@ func (s *Service) DeletePort(eventObject runtime.Object, portID string) error {
return nil
}
-func (s *Service) DeletePorts(openStackCluster *infrav1.OpenStackCluster) error {
+// DeleteTrunk deletes the Neutron trunk and port with the given ID.
+func (s *Service) DeleteInstanceTrunkAndPort(eventObject runtime.Object, port infrav1.PortStatus, trunkSupported bool) error {
+ if trunkSupported {
+ if err := s.DeleteTrunk(eventObject, port.ID); err != nil {
+ return fmt.Errorf("error deleting trunk of port %s: %v", port.ID, err)
+ }
+ }
+ if err := s.DeletePort(eventObject, port.ID); err != nil {
+ return fmt.Errorf("error deleting port %s: %v", port.ID, err)
+ }
+
+ return nil
+}
+
+// DeleteClusterPorts deletes all ports created for the cluster.
+func (s *Service) DeleteClusterPorts(openStackCluster *infrav1.OpenStackCluster) error {
// If the network is not ready, do nothing
if openStackCluster.Status.Network == nil || openStackCluster.Status.Network.ID == "" {
return nil
@@ -276,6 +279,7 @@ func (s *Service) DeletePorts(openStackCluster *infrav1.OpenStackCluster) error
NetworkID: networkID,
DeviceOwner: "",
})
+ s.scope.Logger().Info("Deleting cluster ports", "networkID", networkID, "portList", portList)
if err != nil {
if capoerrors.IsNotFound(err) {
return nil
@@ -285,9 +289,8 @@ func (s *Service) DeletePorts(openStackCluster *infrav1.OpenStackCluster) error
for _, port := range portList {
if strings.HasPrefix(port.Name, openStackCluster.Name) {
- err := s.DeletePort(openStackCluster, port.ID)
- if err != nil {
- return fmt.Errorf("delete port %s of network %q failed : %v", port.ID, networkID, err)
+ if err := s.DeletePort(openStackCluster, port.ID); err != nil {
+ return fmt.Errorf("error deleting port %s: %v", port.ID, err)
}
}
}
@@ -295,42 +298,349 @@ func (s *Service) DeletePorts(openStackCluster *infrav1.OpenStackCluster) error
return nil
}
-func (s *Service) GarbageCollectErrorInstancesPort(eventObject runtime.Object, instanceName string, portOpts []infrav1.PortOpts) error {
- for i := range portOpts {
- portOpt := &portOpts[i]
+// GetPortName appends a suffix to an instance name in order to try and get a unique name per port.
+func GetPortName(instanceName string, opts *infrav1.PortOpts, netIndex int) string {
+ if opts != nil && opts.NameSuffix != "" {
+ return fmt.Sprintf("%s-%s", instanceName, opts.NameSuffix)
+ }
+ return fmt.Sprintf("%s-%d", instanceName, netIndex)
+}
- portName := GetPortName(instanceName, portOpt, i)
+func (s *Service) CreatePorts(eventObject runtime.Object, clusterName string, ports []infrav1.PortOpts, securityGroups []infrav1.SecurityGroupFilter, instanceTags []string, instanceName string) ([]infrav1.PortStatus, error) {
+ return s.createPortsImpl(eventObject, clusterName, ports, securityGroups, instanceTags, instanceName)
+}
- // TODO: whould be nice if gophercloud could be persuaded to accept multiple
- // names as is allowed by the API in order to reduce API traffic.
- portList, err := s.client.ListPort(ports.ListOpts{Name: portName})
+func (s *Service) createPortsImpl(eventObject runtime.Object, clusterName string, ports []infrav1.PortOpts, securityGroups []infrav1.SecurityGroupFilter, instanceTags []string, instanceName string) ([]infrav1.PortStatus, error) {
+ instanceSecurityGroups, err := s.GetSecurityGroups(securityGroups)
+ if err != nil {
+ return nil, fmt.Errorf("error getting security groups: %v", err)
+ }
+
+ portsStatus := make([]infrav1.PortStatus, 0, len(ports))
+
+ for i := range ports {
+ portOpts := &ports[i]
+ iTags := []string{}
+ if len(instanceTags) > 0 {
+ iTags = instanceTags
+ }
+ portName := GetPortName(instanceName, portOpts, i)
+ // Events are recorded in CreatePort
+ port, err := s.CreatePort(eventObject, clusterName, portName, portOpts, instanceSecurityGroups, iTags)
if err != nil {
- return err
+ return nil, err
}
- // NOTE: https://github.com/kubernetes-sigs/cluster-api-provider-openstack/issues/1476
- // It is up to the end user to specify a UNIQUE cluster name when provisioning in the
- // same project, otherwise things will alias and we could delete more than we should.
- if len(portList) > 1 {
- return fmt.Errorf("garbage collection of port %s failed, found %d ports with the same name", portName, len(portList))
+ portsStatus = append(portsStatus, infrav1.PortStatus{
+ ID: port.ID,
+ })
+ }
+
+ return portsStatus, nil
+}
+
+// ConstructPorts builds an array of ports from the instance spec.
+// If no ports are in the spec, returns a single port for a network connection to the default cluster network.
+func (s *Service) ConstructPorts(openStackCluster *infrav1.OpenStackCluster, ports []infrav1.PortOpts, trunkEnabled bool, trunkSupported bool) ([]infrav1.PortOpts, error) {
+ // If no network is specified, return nil
+ if openStackCluster.Status.Network == nil {
+ return nil, nil
+ }
+
+ // Ensure user-specified ports have all required fields
+ ports, err := s.normalizePorts(ports, openStackCluster, trunkEnabled)
+ if err != nil {
+ return nil, err
+ }
+
+ // no networks or ports found in the spec, so create a port on the cluster network
+ if len(ports) == 0 {
+ port := infrav1.PortOpts{
+ Network: &infrav1.NetworkFilter{
+ ID: openStackCluster.Status.Network.ID,
+ },
+ Trunk: &trunkEnabled,
}
+ for _, subnet := range openStackCluster.Status.Network.Subnets {
+ port.FixedIPs = append(port.FixedIPs, infrav1.FixedIP{
+ Subnet: &infrav1.SubnetFilter{
+ ID: subnet.ID,
+ },
+ })
+ }
+ ports = []infrav1.PortOpts{port}
+ }
- if len(portList) == 0 {
- continue
+ // trunk support is required if any port has trunk enabled
+ portUsesTrunk := func() bool {
+ for _, port := range ports {
+ if port.Trunk != nil && *port.Trunk {
+ return true
+ }
+ }
+ return false
+ }
+ if portUsesTrunk() {
+ if !trunkSupported {
+ return nil, fmt.Errorf("there is no trunk support. please ensure that the trunk extension is enabled in your OpenStack deployment")
}
+ }
- if err := s.DeletePort(eventObject, portList[0].ID); err != nil {
+ return ports, nil
+}
+
+// normalizePorts ensures that a user-specified PortOpts has all required fields set. Specifically it:
+// - sets the Trunk field to the instance spec default if not specified
+// - sets the Network ID field if not specified.
+func (s *Service) normalizePorts(ports []infrav1.PortOpts, openStackCluster *infrav1.OpenStackCluster, trunkEnabled bool) ([]infrav1.PortOpts, error) {
+ normalizedPorts := make([]infrav1.PortOpts, 0, len(ports))
+ for i := range ports {
+ // Deep copy the port to avoid mutating the original
+ port := ports[i].DeepCopy()
+
+ // No Trunk field specified for the port, inherit the machine default
+ if port.Trunk == nil {
+ port.Trunk = &trunkEnabled
+ }
+
+ if err := s.normalizePortTarget(port, openStackCluster, i); err != nil {
+ return nil, err
+ }
+
+ normalizedPorts = append(normalizedPorts, *port)
+ }
+ return normalizedPorts, nil
+}
+
+// normalizePortTarget ensures that the port has a network ID.
+func (s *Service) normalizePortTarget(port *infrav1.PortOpts, openStackCluster *infrav1.OpenStackCluster, portIdx int) error {
+ // Treat no Network and empty Network the same
+ noNetwork := port.Network == nil || (*port.Network == infrav1.NetworkFilter{})
+
+ // No network or subnets defined: use cluster defaults
+ if noNetwork && len(port.FixedIPs) == 0 {
+ port.Network = &infrav1.NetworkFilter{
+ ID: openStackCluster.Status.Network.ID,
+ }
+ for _, subnet := range openStackCluster.Status.Network.Subnets {
+ port.FixedIPs = append(port.FixedIPs, infrav1.FixedIP{
+ Subnet: &infrav1.SubnetFilter{
+ ID: subnet.ID,
+ },
+ })
+ }
+
+ return nil
+ }
+
+ // No network, but fixed IPs are defined(we handled the no fixed
+ // IPs case above): try to infer network from a subnet
+ if noNetwork {
+ s.scope.Logger().V(4).Info("No network defined for port, attempting to infer from subnet", "port", portIdx)
+
+ // Look for a unique subnet defined in FixedIPs. If we find one
+ // we can use it to infer the network ID. We don't need to worry
+ // here about the case where different FixedIPs have different
+ // networks because that will cause an error later when we try
+ // to create the port.
+ networkID, err := func() (string, error) {
+ for i, fixedIP := range port.FixedIPs {
+ if fixedIP.Subnet == nil {
+ continue
+ }
+
+ subnet, err := s.GetSubnetByFilter(fixedIP.Subnet)
+ if err != nil {
+ // Multiple matches might be ok later when we restrict matches to a single network
+ if errors.Is(err, ErrMultipleMatches) {
+ s.scope.Logger().V(4).Info("Couldn't infer network from subnet", "subnetIndex", i, "err", err)
+ continue
+ }
+
+ return "", err
+ }
+
+ // Cache the subnet ID in the FixedIP
+ fixedIP.Subnet.ID = subnet.ID
+ return subnet.NetworkID, nil
+ }
+
+ // TODO: This is a spec error: it should set the machine to failed
+ return "", fmt.Errorf("port %d has no network and unable to infer from fixed IPs", portIdx)
+ }()
+ if err != nil {
return err
}
+
+ port.Network = &infrav1.NetworkFilter{
+ ID: networkID,
+ }
+
+ return nil
}
+ // Nothing to do if network ID is already set
+ if port.Network.ID != "" {
+ return nil
+ }
+
+ // Network is defined by Filter
+ netIDs, err := s.GetNetworkIDsByFilter(port.Network.ToListOpt())
+ if err != nil {
+ return err
+ }
+
+ // TODO: These are spec errors: they should set the machine to failed
+ if len(netIDs) > 1 {
+ return fmt.Errorf("network filter for port %d returns more than one result", portIdx)
+ } else if len(netIDs) == 0 {
+ return fmt.Errorf("network filter for port %d returns no networks", portIdx)
+ }
+
+ port.Network.ID = netIDs[0]
+
return nil
}
-// GetPortName appends a suffix to an instance name in order to try and get a unique name per port.
-func GetPortName(instanceName string, opts *infrav1.PortOpts, netIndex int) string {
- if opts != nil && opts.NameSuffix != "" {
- return fmt.Sprintf("%s-%s", instanceName, opts.NameSuffix)
+// IsTrunkExtSupported verifies trunk setup on the OpenStack deployment.
+func (s *Service) IsTrunkExtSupported() (trunknSupported bool, err error) {
+ trunkSupport, err := s.GetTrunkSupport()
+ if err != nil {
+ return false, fmt.Errorf("there was an issue verifying whether trunk support is available, Please try again later: %v", err)
}
- return fmt.Sprintf("%s-%d", instanceName, netIndex)
+ if !trunkSupport {
+ return false, nil
+ }
+ return true, nil
+}
+
+// AdoptMachinePorts checks if the ports are in ready condition. If not, it'll try to adopt them
+// by checking if they exist and if they do, it'll add them to the OpenStackMachine status.
+// A port is searched by name and network ID and has to be unique.
+// If the port is not found, it'll be ignored because it'll be created after the adoption.
+func (s *Service) AdoptMachinePorts(scope scope.Scope, openStackMachine *infrav1.OpenStackMachine, desiredPorts []infrav1.PortOpts) (changed bool, err error) {
+ changed = false
+
+ // We can skip adoption if the instance is ready because OpenStackMachine is immutable once ready
+ // or if the ports are already in the status
+ if openStackMachine.Status.Ready && len(openStackMachine.Status.DependentResources.PortsStatus) == len(desiredPorts) {
+ scope.Logger().V(5).Info("OpenStackMachine is ready, skipping the adoption of ports")
+ return changed, nil
+ }
+
+ scope.Logger().Info("Adopting ports for OpenStackMachine", "name", openStackMachine.Name)
+
+ // We create ports in order and adopt them in order in PortsStatus.
+ // This means that if port N doesn't exist we know that ports >N don't exist.
+ // We can therefore stop searching for ports once we find one that doesn't exist.
+ for i, port := range desiredPorts {
+ // check if the port is in status first and if it is, skip it
+ if i < len(openStackMachine.Status.DependentResources.PortsStatus) {
+ scope.Logger().V(5).Info("Port already in status, skipping it", "port index", i)
+ continue
+ }
+
+ portOpts := &desiredPorts[i]
+ portName := GetPortName(openStackMachine.Name, portOpts, i)
+ ports, err := s.client.ListPort(ports.ListOpts{
+ Name: portName,
+ NetworkID: port.Network.ID,
+ })
+ if err != nil {
+ return changed, fmt.Errorf("searching for existing port for machine %s: %v", openStackMachine.Name, err)
+ }
+ // if the port is not found, we stop the adoption of ports since the rest of the ports will not be found either
+ // and will be created after the adoption
+ if len(ports) == 0 {
+ scope.Logger().V(5).Info("Port not found, stopping the adoption of ports", "port index", i)
+ return changed, nil
+ }
+ if len(ports) > 1 {
+ return changed, fmt.Errorf("found multiple ports with name %s", portName)
+ }
+
+ // The desired port was found, so we add it to the status
+ scope.Logger().V(5).Info("Port found, adding it to the status", "port index", i)
+ openStackMachine.Status.DependentResources.PortsStatus = append(openStackMachine.Status.DependentResources.PortsStatus, infrav1.PortStatus{ID: ports[0].ID})
+ changed = true
+ }
+
+ return changed, nil
+}
+
+// AdopteBastionPorts tries to adopt the ports for the bastion instance by checking if they exist and if they do,
+// it'll add them to the OpenStackCluster status.
+// A port is searched by name and network ID and has to be unique.
+// If the port is not found, it'll be ignored because it'll be created after the adoption.
+func (s *Service) AdoptBastionPorts(scope scope.Scope, openStackCluster *infrav1.OpenStackCluster, bastionName string) (changed bool, err error) {
+ changed = false
+
+ if openStackCluster.Status.Network == nil {
+ scope.Logger().V(5).Info("Network status is nil, skipping the adoption of ports")
+ return changed, nil
+ }
+
+ if openStackCluster.Status.Bastion == nil {
+ scope.Logger().V(5).Info("Bastion status is nil, initializing it")
+ openStackCluster.Status.Bastion = &infrav1.BastionStatus{}
+ }
+
+ desiredPorts := openStackCluster.Status.Bastion.ReferencedResources.PortsOpts
+
+ // We can skip adoption if the ports are already in the status
+ if len(desiredPorts) == len(openStackCluster.Status.Bastion.DependentResources.PortsStatus) {
+ return changed, nil
+ }
+
+ scope.Logger().Info("Adopting bastion ports for OpenStackCluster", "name", openStackCluster.Name)
+
+ // We create ports in order and adopt them in order in PortsStatus.
+ // This means that if port N doesn't exist we know that ports >N don't exist.
+ // We can therefore stop searching for ports once we find one that doesn't exist.
+ for i, port := range desiredPorts {
+ // check if the port is in status first and if it is, skip it
+ if i < len(openStackCluster.Status.Bastion.DependentResources.PortsStatus) {
+ scope.Logger().V(5).Info("Port already in status, skipping it", "port index", i)
+ continue
+ }
+
+ portOpts := &desiredPorts[i]
+ portName := GetPortName(bastionName, portOpts, i)
+ ports, err := s.client.ListPort(ports.ListOpts{
+ Name: portName,
+ NetworkID: port.Network.ID,
+ })
+ if err != nil {
+ return changed, fmt.Errorf("searching for existing port for bastion %s: %v", bastionName, err)
+ }
+ // if the port is not found, we stop the adoption of ports since the rest of the ports will not be found either
+ // and will be created after the adoption
+ if len(ports) == 0 {
+ scope.Logger().V(5).Info("Port not found, stopping the adoption of ports", "port index", i)
+ return changed, nil
+ }
+ if len(ports) > 1 {
+ return changed, fmt.Errorf("found multiple ports with name %s", portName)
+ }
+
+ // The desired port was found, so we add it to the status
+ scope.Logger().V(5).Info("Port found, adding it to the status", "port index", i)
+ openStackCluster.Status.Bastion.DependentResources.PortsStatus = append(openStackCluster.Status.Bastion.DependentResources.PortsStatus, infrav1.PortStatus{ID: ports[0].ID})
+ changed = true
+ }
+
+ return changed, nil
+}
+
+// MissingPorts returns the ports that are not in the ports status but are desired ports which should be created.
+func MissingPorts(portsStatus []infrav1.PortStatus, desiredPorts []infrav1.PortOpts) []infrav1.PortOpts {
+ // missingPorts is equal to the ports status minus its length
+ missingPortsLength := len(desiredPorts) - len(portsStatus)
+
+ // rebuild desiredPorts to only contain the ports that were not adopted
+ missingPorts := make([]infrav1.PortOpts, missingPortsLength)
+ for i := 0; i < missingPortsLength; i++ {
+ missingPorts[i] = desiredPorts[i+len(portsStatus)]
+ }
+ return missingPorts
}
diff --git a/pkg/cloud/services/networking/port_test.go b/pkg/cloud/services/networking/port_test.go
index a86837778e..4805da89e8 100644
--- a/pkg/cloud/services/networking/port_test.go
+++ b/pkg/cloud/services/networking/port_test.go
@@ -19,20 +19,25 @@ package networking
import (
"testing"
+ "github.com/go-logr/logr"
"github.com/golang/mock/gomock"
+ "github.com/google/go-cmp/cmp"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/attributestags"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/portsbinding"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/portsecurity"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/trunks"
+ "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/gomega"
+ "k8s.io/utils/pointer"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/mock"
+ "sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
)
-func Test_GetOrCreatePort(t *testing.T) {
+func Test_CreatePort(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
@@ -41,7 +46,6 @@ func Test_GetOrCreatePort(t *testing.T) {
subnetID1 := "d9c88a6d-0b8c-48ff-8f0e-8d85a078c194"
subnetID2 := "d9c2346d-05gc-48er-9ut4-ig83ayt8c7h4"
portID1 := "50214c48-c09e-4a54-914f-97b40fd22802"
- portID2 := "4c096384-f0a5-466d-9534-06a7ed281a79"
hostID := "825c1b11-3dca-4bfe-a2d8-a3cc1964c8d5"
trunkID := "eb7541fa-5e2a-4cca-b2c3-dfa409b917ce"
portSecurityGroupID := "f51d1206-fc5a-4f7a-a5c0-2e03e44e4dc0"
@@ -63,65 +67,10 @@ func Test_GetOrCreatePort(t *testing.T) {
tags []string
expect func(m *mock.MockNetworkClientMockRecorder)
// Note the 'wanted' port isn't so important, since it will be whatever we tell ListPort or CreatePort to return.
- // Mostly in this test suite, we're checking that ListPort/CreatePort is called with the expected port opts.
+ // Mostly in this test suite, we're checking that CreatePort is called with the expected port opts.
want *ports.Port
wantErr bool
}{
- {
- "gets and returns existing port if name matches",
- "foo-port-1",
- infrav1.PortOpts{
- Network: &infrav1.NetworkFilter{
- ID: netID,
- },
- },
- nil,
- []string{},
- func(m *mock.MockNetworkClientMockRecorder) {
- m.
- ListPort(ports.ListOpts{
- Name: "foo-port-1",
- NetworkID: netID,
- }).Return([]ports.Port{{
- ID: portID1,
- }}, nil)
- },
- &ports.Port{
- ID: portID1,
- },
- false,
- },
- {
- "errors if multiple matching ports are found",
- "foo-port-1",
- infrav1.PortOpts{
- Network: &infrav1.NetworkFilter{
- ID: netID,
- },
- },
- nil,
- []string{},
- func(m *mock.MockNetworkClientMockRecorder) {
- m.
- ListPort(ports.ListOpts{
- Name: "foo-port-1",
- NetworkID: netID,
- }).Return([]ports.Port{
- {
- ID: portID1,
- NetworkID: netID,
- Name: "foo-port-1",
- },
- {
- ID: portID2,
- NetworkID: netID,
- Name: "foo-port-2",
- },
- }, nil)
- },
- nil,
- true,
- },
{
"creates port with defaults (description and secgroups) if not specified in portOpts",
"foo-port-1",
@@ -133,12 +82,6 @@ func Test_GetOrCreatePort(t *testing.T) {
instanceSecurityGroups,
[]string{},
func(m *mock.MockNetworkClientMockRecorder) {
- // No ports found
- m.
- ListPort(ports.ListOpts{
- Name: "foo-port-1",
- NetworkID: netID,
- }).Return([]ports.Port{}, nil)
m.
CreatePort(portsbinding.CreateOptsExt{
CreateOptsBuilder: ports.CreateOpts{
@@ -222,11 +165,6 @@ func Test_GetOrCreatePort(t *testing.T) {
"trusted": true,
},
}
- m.
- ListPort(ports.ListOpts{
- Name: "foo-port-bar",
- NetworkID: netID,
- }).Return([]ports.Port{}, nil)
m.
CreatePort(portbindingCreateOptsExt).
Return(&ports.Port{
@@ -269,11 +207,6 @@ func Test_GetOrCreatePort(t *testing.T) {
nil,
nil,
func(m *mock.MockNetworkClientMockRecorder) {
- m.
- ListPort(ports.ListOpts{
- Name: "foo-port-bar",
- NetworkID: netID,
- }).Return([]ports.Port{}, nil)
m.
ListSubnet(subnets.ListOpts{
Tags: "Foo",
@@ -306,12 +239,6 @@ func Test_GetOrCreatePort(t *testing.T) {
instanceSecurityGroups,
[]string{},
func(m *mock.MockNetworkClientMockRecorder) {
- // No ports found
- m.
- ListPort(ports.ListOpts{
- Name: "foo-port-1",
- NetworkID: netID,
- }).Return([]ports.Port{}, nil)
m.
CreatePort(portsbinding.CreateOptsExt{
CreateOptsBuilder: ports.CreateOpts{
@@ -338,12 +265,6 @@ func Test_GetOrCreatePort(t *testing.T) {
nil,
[]string{"my-instance-tag"},
func(m *mock.MockNetworkClientMockRecorder) {
- // No ports found
- m.
- ListPort(ports.ListOpts{
- Name: "foo-port-1",
- NetworkID: netID,
- }).Return([]ports.Port{}, nil)
m.CreatePort(portsbinding.CreateOptsExt{
CreateOptsBuilder: ports.CreateOpts{
Name: "foo-port-1",
@@ -369,12 +290,6 @@ func Test_GetOrCreatePort(t *testing.T) {
nil,
[]string{"my-instance-tag"},
func(m *mock.MockNetworkClientMockRecorder) {
- // No ports found
- m.
- ListPort(ports.ListOpts{
- Name: "foo-port-1",
- NetworkID: netID,
- }).Return([]ports.Port{}, nil)
m.CreatePort(portsbinding.CreateOptsExt{
CreateOptsBuilder: ports.CreateOpts{
Name: "foo-port-1",
@@ -402,12 +317,6 @@ func Test_GetOrCreatePort(t *testing.T) {
nil,
[]string{"my-tag"},
func(m *mock.MockNetworkClientMockRecorder) {
- // No ports found
- m.
- ListPort(ports.ListOpts{
- Name: "foo-port-1",
- NetworkID: netID,
- }).Return([]ports.Port{}, nil)
m.
CreatePort(portsbinding.CreateOptsExt{
CreateOptsBuilder: ports.CreateOpts{
@@ -453,12 +362,6 @@ func Test_GetOrCreatePort(t *testing.T) {
nil,
nil,
func(m *mock.MockNetworkClientMockRecorder) {
- // No ports found
- m.
- ListPort(ports.ListOpts{
- Name: "foo-port-1",
- NetworkID: netID,
- }).Return([]ports.Port{}, nil)
m.
CreatePort(portsbinding.CreateOptsExt{
CreateOptsBuilder: ports.CreateOpts{
@@ -485,12 +388,6 @@ func Test_GetOrCreatePort(t *testing.T) {
instanceSecurityGroups,
[]string{},
func(m *mock.MockNetworkClientMockRecorder) {
- // No ports found
- m.
- ListPort(ports.ListOpts{
- Name: "foo-port-1",
- NetworkID: netID,
- }).Return([]ports.Port{}, nil)
m.
CreatePort(portsbinding.CreateOptsExt{
CreateOptsBuilder: ports.CreateOpts{
@@ -518,7 +415,7 @@ func Test_GetOrCreatePort(t *testing.T) {
s := Service{
client: mockClient,
}
- got, err := s.GetOrCreatePort(
+ got, err := s.CreatePort(
eventObject,
"test-cluster",
tt.portName,
@@ -536,98 +433,474 @@ func Test_GetOrCreatePort(t *testing.T) {
}
}
-func Test_GarbageCollectErrorInstancesPort(t *testing.T) {
+func pointerTo(b bool) *bool {
+ return &b
+}
+
+func TestService_normalizePorts(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
- instanceName := "foo"
- portID1 := "dc6e0ae3-dad6-4240-a9cb-e541916f20d3"
- portID2 := "a38ab1cb-c2cc-4c1b-9d1d-696ec73356d2"
- portName1 := GetPortName(instanceName, nil, 0)
- portName2 := GetPortName(instanceName, nil, 1)
+ const (
+ defaultNetworkID = "3c66f3ca-2d26-4d9d-ae3b-568f54129773"
+ defaultSubnetID = "d8dbba89-8c39-4192-a571-e702fca35bac"
+
+ networkID = "afa54944-1443-4132-9ef5-ce37eb4d6ab6"
+ subnetID = "d786e715-c299-4a97-911d-640c10fc0392"
+ )
+
+ openStackCluster := &infrav1.OpenStackCluster{
+ Status: infrav1.OpenStackClusterStatus{
+ Network: &infrav1.NetworkStatusWithSubnets{
+ NetworkStatus: infrav1.NetworkStatus{
+ ID: defaultNetworkID,
+ },
+ Subnets: []infrav1.Subnet{
+ {ID: defaultSubnetID},
+ },
+ },
+ },
+ }
tests := []struct {
- // man is the name of the test.
- name string
- // expect allows definition of any expected calls to the mock.
- expect func(m *mock.MockNetworkClientMockRecorder)
- // portOpts defines the instance ports as defined in the OSM spec.
- portOpts []infrav1.PortOpts
- // wantErr defines whether the test is supposed to fail.
- wantErr bool
+ name string
+ ports []infrav1.PortOpts
+ instanceTrunk bool
+ expectNetwork func(m *mock.MockNetworkClientMockRecorder)
+ want []infrav1.PortOpts
+ wantErr bool
}{
{
- name: "garbage collects all ports for an instance",
- expect: func(m *mock.MockNetworkClientMockRecorder) {
- o1 := ports.ListOpts{
- Name: portName1,
- }
- p1 := []ports.Port{
- {
- ID: portID1,
- Name: portName1,
+ name: "No ports: no ports",
+ ports: []infrav1.PortOpts{},
+ want: []infrav1.PortOpts{},
+ },
+ {
+ name: "Nil network, no fixed IPs: cluster defaults",
+ ports: []infrav1.PortOpts{
+ {
+ Network: nil,
+ FixedIPs: nil,
+ },
+ },
+ want: []infrav1.PortOpts{
+ {
+ Network: &infrav1.NetworkFilter{
+ ID: defaultNetworkID,
},
- }
- m.ListPort(o1).Return(p1, nil)
- m.DeletePort(portID1)
- o2 := ports.ListOpts{
- Name: portName2,
- }
- p2 := []ports.Port{
- {
- ID: portID2,
- Name: portName2,
+ FixedIPs: []infrav1.FixedIP{
+ {
+ Subnet: &infrav1.SubnetFilter{
+ ID: defaultSubnetID,
+ },
+ },
},
- }
-
- m.ListPort(o2).Return(p2, nil)
- m.DeletePort(portID2)
- },
- portOpts: []infrav1.PortOpts{
- {},
- {},
- },
- wantErr: false,
- }, {
- name: "garbage collects no ports in an instance",
- expect: func(m *mock.MockNetworkClientMockRecorder) {
- o1 := ports.ListOpts{
- Name: portName1,
- }
- p1 := []ports.Port{}
- m.ListPort(o1).Return(p1, nil)
+ Trunk: pointer.Bool(false),
+ },
+ },
+ },
+ {
+ name: "Empty network, no fixed IPs: cluster defaults",
+ ports: []infrav1.PortOpts{
+ {
+ Network: &infrav1.NetworkFilter{},
+ FixedIPs: nil,
+ },
+ },
+ want: []infrav1.PortOpts{
+ {
+ Network: &infrav1.NetworkFilter{
+ ID: defaultNetworkID,
+ },
+ FixedIPs: []infrav1.FixedIP{
+ {
+ Subnet: &infrav1.SubnetFilter{
+ ID: defaultSubnetID,
+ },
+ },
+ },
+ Trunk: pointer.Bool(false),
+ },
+ },
+ },
+ {
+ name: "Port inherits trunk from instance",
+ ports: []infrav1.PortOpts{
+ {
+ Network: &infrav1.NetworkFilter{},
+ FixedIPs: nil,
+ },
+ },
+ instanceTrunk: true,
+ want: []infrav1.PortOpts{
+ {
+ Network: &infrav1.NetworkFilter{
+ ID: defaultNetworkID,
+ },
+ FixedIPs: []infrav1.FixedIP{
+ {
+ Subnet: &infrav1.SubnetFilter{
+ ID: defaultSubnetID,
+ },
+ },
+ },
+ Trunk: pointer.Bool(true),
+ },
+ },
+ },
+ {
+ name: "Port overrides trunk from instance",
+ ports: []infrav1.PortOpts{
+ {
+ Network: &infrav1.NetworkFilter{},
+ FixedIPs: nil,
+ Trunk: pointer.Bool(true),
+ },
+ },
+ want: []infrav1.PortOpts{
+ {
+ Network: &infrav1.NetworkFilter{
+ ID: defaultNetworkID,
+ },
+ FixedIPs: []infrav1.FixedIP{
+ {
+ Subnet: &infrav1.SubnetFilter{
+ ID: defaultSubnetID,
+ },
+ },
+ },
+ Trunk: pointer.Bool(true),
+ },
+ },
+ },
+ {
+ name: "Network defined by ID: unchanged",
+ ports: []infrav1.PortOpts{
+ {
+ Network: &infrav1.NetworkFilter{
+ ID: networkID,
+ },
+ },
+ },
+ want: []infrav1.PortOpts{
+ {
+ Network: &infrav1.NetworkFilter{
+ ID: networkID,
+ },
+ Trunk: pointer.Bool(false),
+ },
+ },
+ },
+ {
+ name: "Network defined by filter: add ID from network lookup",
+ ports: []infrav1.PortOpts{
+ {
+ Network: &infrav1.NetworkFilter{
+ Name: "test-network",
+ },
+ },
+ },
+ expectNetwork: func(m *mock.MockNetworkClientMockRecorder) {
+ m.ListNetwork(networks.ListOpts{Name: "test-network"}).Return([]networks.Network{
+ {ID: networkID},
+ }, nil)
},
- portOpts: []infrav1.PortOpts{
- {},
+ want: []infrav1.PortOpts{
+ {
+ Network: &infrav1.NetworkFilter{
+ ID: networkID,
+ Name: "test-network",
+ },
+ Trunk: pointer.Bool(false),
+ },
+ },
+ },
+ {
+ name: "No network, fixed IP has subnet by ID: add ID from subnet",
+ ports: []infrav1.PortOpts{
+ {
+ FixedIPs: []infrav1.FixedIP{
+ {
+ Subnet: &infrav1.SubnetFilter{
+ ID: subnetID,
+ },
+ },
+ },
+ },
+ },
+ expectNetwork: func(m *mock.MockNetworkClientMockRecorder) {
+ m.GetSubnet(subnetID).Return(&subnets.Subnet{ID: subnetID, NetworkID: networkID}, nil)
+ },
+ want: []infrav1.PortOpts{
+ {
+ Network: &infrav1.NetworkFilter{
+ ID: networkID,
+ },
+ FixedIPs: []infrav1.FixedIP{
+ {
+ Subnet: &infrav1.SubnetFilter{
+ ID: subnetID,
+ },
+ },
+ },
+ Trunk: pointer.Bool(false),
+ },
+ },
+ },
+ {
+ name: "No network, fixed IP has subnet by filter: add ID from subnet",
+ ports: []infrav1.PortOpts{
+ {
+ FixedIPs: []infrav1.FixedIP{
+ {
+ Subnet: &infrav1.SubnetFilter{
+ Name: "test-subnet",
+ },
+ },
+ },
+ },
+ },
+ expectNetwork: func(m *mock.MockNetworkClientMockRecorder) {
+ m.ListSubnet(subnets.ListOpts{Name: "test-subnet"}).Return([]subnets.Subnet{
+ {ID: subnetID, NetworkID: networkID},
+ }, nil)
+ },
+ want: []infrav1.PortOpts{
+ {
+ Network: &infrav1.NetworkFilter{
+ ID: networkID,
+ },
+ FixedIPs: []infrav1.FixedIP{
+ {
+ Subnet: &infrav1.SubnetFilter{
+ ID: subnetID,
+ Name: "test-subnet",
+ },
+ },
+ },
+ Trunk: pointer.Bool(false),
+ },
+ },
+ },
+ {
+ name: "No network, fixed IP subnet returns no matches: error",
+ ports: []infrav1.PortOpts{
+ {
+ FixedIPs: []infrav1.FixedIP{
+ {
+ Subnet: &infrav1.SubnetFilter{
+ Name: "test-subnet",
+ },
+ },
+ },
+ },
+ },
+ expectNetwork: func(m *mock.MockNetworkClientMockRecorder) {
+ m.ListSubnet(subnets.ListOpts{Name: "test-subnet"}).Return([]subnets.Subnet{}, nil)
+ },
+ wantErr: true,
+ },
+ {
+ name: "No network, only fixed IP subnet returns multiple matches: error",
+ ports: []infrav1.PortOpts{
+ {
+ FixedIPs: []infrav1.FixedIP{
+ {
+ Subnet: &infrav1.SubnetFilter{
+ Name: "test-subnet",
+ },
+ },
+ },
+ },
+ },
+ expectNetwork: func(m *mock.MockNetworkClientMockRecorder) {
+ m.ListSubnet(subnets.ListOpts{Name: "test-subnet"}).Return([]subnets.Subnet{
+ {ID: subnetID, NetworkID: networkID},
+ {ID: "8008494c-301e-4e5c-951b-a8ab568447fd", NetworkID: "5d48bfda-db28-42ee-8374-50e13d1fe5ea"},
+ }, nil)
+ },
+ wantErr: true,
+ },
+ {
+ name: "No network, first fixed IP subnet returns multiple matches: used ID from second fixed IP",
+ ports: []infrav1.PortOpts{
+ {
+ FixedIPs: []infrav1.FixedIP{
+ {
+ Subnet: &infrav1.SubnetFilter{
+ Name: "test-subnet1",
+ },
+ },
+ {
+ Subnet: &infrav1.SubnetFilter{
+ Name: "test-subnet2",
+ },
+ },
+ },
+ },
+ },
+ expectNetwork: func(m *mock.MockNetworkClientMockRecorder) {
+ m.ListSubnet(subnets.ListOpts{Name: "test-subnet1"}).Return([]subnets.Subnet{
+ {ID: subnetID, NetworkID: networkID},
+ {ID: "8008494c-301e-4e5c-951b-a8ab568447fd", NetworkID: "5d48bfda-db28-42ee-8374-50e13d1fe5ea"},
+ }, nil)
+ m.ListSubnet(subnets.ListOpts{Name: "test-subnet2"}).Return([]subnets.Subnet{
+ {ID: subnetID, NetworkID: networkID},
+ }, nil)
+ },
+ want: []infrav1.PortOpts{
+ {
+ Network: &infrav1.NetworkFilter{
+ ID: networkID,
+ },
+ FixedIPs: []infrav1.FixedIP{
+ {
+ Subnet: &infrav1.SubnetFilter{
+ Name: "test-subnet1",
+ },
+ },
+ {
+ Subnet: &infrav1.SubnetFilter{
+ ID: subnetID,
+ Name: "test-subnet2",
+ },
+ },
+ },
+ Trunk: pointer.Bool(false),
+ },
},
- wantErr: false,
},
}
-
- eventObject := &infrav1.OpenStackMachine{}
-
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
g := NewWithT(t)
+
mockClient := mock.NewMockNetworkClient(mockCtrl)
- tt.expect(mockClient.EXPECT())
+ if tt.expectNetwork != nil {
+ tt.expectNetwork(mockClient.EXPECT())
+ }
s := Service{
client: mockClient,
+ scope: scope.NewMockScopeFactory(mockCtrl, "", logr.Discard()),
}
- err := s.GarbageCollectErrorInstancesPort(
- eventObject,
- instanceName,
- tt.portOpts,
- )
+
+ got, err := s.normalizePorts(tt.ports, openStackCluster, tt.instanceTrunk)
if tt.wantErr {
g.Expect(err).To(HaveOccurred())
- } else {
- g.Expect(err).NotTo(HaveOccurred())
+ return
}
+
+ g.Expect(err).NotTo(HaveOccurred())
+ g.Expect(got).To(Equal(tt.want), cmp.Diff(got, tt.want))
})
}
}
-func pointerTo(b bool) *bool {
- return &b
+func Test_getPortName(t *testing.T) {
+ type args struct {
+ instanceName string
+ opts *infrav1.PortOpts
+ netIndex int
+ }
+ tests := []struct {
+ name string
+ args args
+ want string
+ }{
+ {
+ name: "with nil PortOpts",
+ args: args{"test-1-instance", nil, 2},
+ want: "test-1-instance-2",
+ },
+ {
+ name: "with PortOpts name suffix",
+ args: args{"test-1-instance", &infrav1.PortOpts{NameSuffix: "foo"}, 4},
+ want: "test-1-instance-foo",
+ },
+ {
+ name: "without PortOpts name suffix",
+ args: args{"test-1-instance", &infrav1.PortOpts{}, 4},
+ want: "test-1-instance-4",
+ },
+ {
+ name: "with PortOpts name suffix",
+ args: args{"test-1-instance", &infrav1.PortOpts{NameSuffix: "foo2", Network: &infrav1.NetworkFilter{ID: "bar"}, DisablePortSecurity: pointer.Bool(true)}, 4},
+ want: "test-1-instance-foo2",
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if got := GetPortName(tt.args.instanceName, tt.args.opts, tt.args.netIndex); got != tt.want {
+ t.Errorf("getPortName() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func Test_MissingPorts(t *testing.T) {
+ tests := []struct {
+ name string
+ portsStatus []infrav1.PortStatus
+ desiredPorts []infrav1.PortOpts
+ expectedMissing []infrav1.PortOpts
+ }{
+ {
+ name: "no missing ports",
+ portsStatus: []infrav1.PortStatus{
+ {
+ ID: "06d18afd-a8d2-4c0f-b6be-63fe71d6c16d",
+ },
+ {
+ ID: "7bf62a7e-a969-40cc-b50c-87bd52e97188",
+ },
+ },
+ desiredPorts: []infrav1.PortOpts{
+ {
+ Network: &infrav1.NetworkFilter{
+ ID: "94588d9b-21f1-4583-97ed-c7367327b0ea",
+ },
+ },
+ {
+ Network: &infrav1.NetworkFilter{
+ ID: "9cc0ebba-eaec-4dc7-b5cf-ece51f699f47",
+ },
+ },
+ },
+ expectedMissing: []infrav1.PortOpts{},
+ },
+ {
+ name: "missing ports",
+ portsStatus: []infrav1.PortStatus{
+ {
+ ID: "06d18afd-a8d2-4c0f-b6be-63fe71d6c16d",
+ },
+ },
+ desiredPorts: []infrav1.PortOpts{
+ {
+ Network: &infrav1.NetworkFilter{
+ ID: "94588d9b-21f1-4583-97ed-c7367327b0ea",
+ },
+ },
+ {
+ Network: &infrav1.NetworkFilter{
+ ID: "9cc0ebba-eaec-4dc7-b5cf-ece51f699f47",
+ },
+ },
+ },
+ expectedMissing: []infrav1.PortOpts{
+ {
+ Network: &infrav1.NetworkFilter{
+ ID: "9cc0ebba-eaec-4dc7-b5cf-ece51f699f47",
+ },
+ },
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ g := NewWithT(t)
+ got := MissingPorts(tt.portsStatus, tt.desiredPorts)
+ g.Expect(got).To(Equal(tt.expectedMissing))
+ })
+ }
}
diff --git a/pkg/cloud/services/networking/securitygroups.go b/pkg/cloud/services/networking/securitygroups.go
index 6707b2fbe4..664f9e84b4 100644
--- a/pkg/cloud/services/networking/securitygroups.go
+++ b/pkg/cloud/services/networking/securitygroups.go
@@ -323,6 +323,11 @@ func (s *Service) DeleteSecurityGroups(openStackCluster *infrav1.OpenStackCluste
getSecControlPlaneGroupName(clusterName),
getSecWorkerGroupName(clusterName),
}
+
+ if openStackCluster.Spec.Bastion != nil && openStackCluster.Spec.Bastion.Enabled {
+ secGroupNames = append(secGroupNames, getSecBastionGroupName(clusterName))
+ }
+
for _, secGroupName := range secGroupNames {
if err := s.deleteSecurityGroup(openStackCluster, secGroupName); err != nil {
return err
@@ -332,11 +337,6 @@ func (s *Service) DeleteSecurityGroups(openStackCluster *infrav1.OpenStackCluste
return nil
}
-func (s *Service) DeleteBastionSecurityGroup(openStackCluster *infrav1.OpenStackCluster, clusterName string) error {
- secBastionGroupName := getSecBastionGroupName(clusterName)
- return s.deleteSecurityGroup(openStackCluster, secBastionGroupName)
-}
-
func (s *Service) deleteSecurityGroup(openStackCluster *infrav1.OpenStackCluster, name string) error {
group, err := s.getSecurityGroupByName(name)
if err != nil {
From 3ba8082321ceeffae01cef1b3548a83ee9df5701 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Mon, 26 Feb 2024 22:53:54 +0000
Subject: [PATCH 079/180] Allow running individual generate targets
generate-controller-gen and generate-conversion-gen targets are split
out of generate-go
---
Makefile | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/Makefile b/Makefile
index 4c6837f716..ffcd67b0cf 100644
--- a/Makefile
+++ b/Makefile
@@ -245,16 +245,20 @@ 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: generate-controller-gen generate-conversion-gen generate-go generate-manifests ## 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
+generate-conversion-gen: $(CONVERSION_GEN)
$(CONVERSION_GEN) \
--input-dirs=./api/v1alpha1 \
--input-dirs=./api/v1alpha5 \
@@ -263,7 +267,6 @@ generate-go: $(MOCKGEN)
--input-dirs=./api/v1beta1 \
--output-file-base=zz_generated.conversion \
--go-header-file=./hack/boilerplate/boilerplate.generatego.txt
- go generate ./...
.PHONY: generate-manifests
generate-manifests: $(CONTROLLER_GEN) ## Generate manifests e.g. CRD, RBAC etc.
From 4bb8966639800f145f0539dcaa8738d913ba5ef9 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Tue, 27 Feb 2024 01:51:17 +0000
Subject: [PATCH 080/180] conversion-gen: Fix package name generation
When conversion-gen has to generate a dependency between 2 input
packages it uses the value passed to --input-dirs as the package name in
the generated import. This does not work if that value is a directory
name. If you specify a package name here instead it works correctly.
We also stop trying to generate conversions for versions which don't
need them.
---
Makefile | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/Makefile b/Makefile
index ffcd67b0cf..26d974652f 100644
--- a/Makefile
+++ b/Makefile
@@ -258,14 +258,14 @@ generate-controller-gen: $(CONTROLLER_GEN)
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/v1alpha1 \
- --input-dirs=./api/v1alpha5 \
- --input-dirs=./api/v1alpha6 \
- --input-dirs=./api/v1alpha7 \
- --input-dirs=./api/v1beta1 \
+ --input-dirs=$(capo_module)/api/v1alpha5 \
+ --input-dirs=$(capo_module)/api/v1alpha6 \
+ --input-dirs=$(capo_module)/api/v1alpha7 \
--output-file-base=zz_generated.conversion \
+ --trim-path-prefix=$(capo_module)/ \
--go-header-file=./hack/boilerplate/boilerplate.generatego.txt
.PHONY: generate-manifests
From 5a1e1752b71739d29bf67f6291a48e9047c0ba9c Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Tue, 27 Feb 2024 09:33:08 +0000
Subject: [PATCH 081/180] Remove logger from scope
Scope encapsulates an initialised OpenStack client which can be safely
shared between reconciles which share the same credentials. The logger
is initialised with context specific to an individual reconcile, so it
cannot be shared between reconciles.
To avoid code churn we preserve the previous interface of Scope with the
creation of scope.WithLogger, which changes the initialisation to ensure
that the returned logger always comes from the current reconcile even if
the scope was cached.
While touching logging in tests, we also take the opportunity to replace
uses of logr.Discard with GinkgoLogr or logr/testr as appropriate, so
test logs are now captured.
---
controllers/openstackcluster_controller.go | 15 ++++----
.../openstackcluster_controller_test.go | 38 ++++++++++++++-----
.../openstackfloatingippool_controller.go | 11 +++---
controllers/openstackmachine_controller.go | 11 +++---
controllers/suite_test.go | 9 ++---
.../services/compute/dependent_resources.go | 4 +-
.../compute/dependent_resources_test.go | 12 +++---
pkg/cloud/services/compute/instance_test.go | 17 +++++----
.../services/compute/instance_types_test.go | 8 ++--
.../services/compute/referenced_resources.go | 2 +-
.../compute/referenced_resources_test.go | 8 ++--
.../services/compute/servergroup_test.go | 7 ++--
pkg/cloud/services/compute/service.go | 4 +-
.../loadbalancer/loadbalancer_test.go | 12 +++---
pkg/cloud/services/loadbalancer/service.go | 4 +-
pkg/cloud/services/networking/network_test.go | 16 ++++++--
pkg/cloud/services/networking/port.go | 4 +-
pkg/cloud/services/networking/port_test.go | 6 ++-
.../networking/securitygroups_test.go | 12 +++---
pkg/cloud/services/networking/service.go | 4 +-
pkg/scope/mock.go | 8 +---
pkg/scope/provider.go | 6 ---
pkg/scope/scope.go | 19 +++++++++-
23 files changed, 143 insertions(+), 94 deletions(-)
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index e6712e5257..3abcad6cdc 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -116,10 +116,11 @@ func (r *OpenStackClusterReconciler) Reconcile(ctx context.Context, req ctrl.Req
}
}()
- 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)
// Resolve and store referenced & dependent resources for the bastion
if openStackCluster.Spec.Bastion != nil && openStackCluster.Spec.Bastion.Enabled {
@@ -154,7 +155,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
@@ -232,7 +233,7 @@ func contains(arr []string, target string) bool {
return false
}
-func deleteBastion(scope scope.Scope, cluster *clusterv1.Cluster, openStackCluster *infrav1.OpenStackCluster) error {
+func deleteBastion(scope *scope.WithLogger, cluster *clusterv1.Cluster, openStackCluster *infrav1.OpenStackCluster) error {
scope.Logger().Info("Deleting Bastion")
computeService, err := compute.NewService(scope)
@@ -313,7 +314,7 @@ func deleteBastion(scope scope.Scope, cluster *clusterv1.Cluster, openStackClust
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.
@@ -364,7 +365,7 @@ func reconcileNormal(scope scope.Scope, cluster *clusterv1.Cluster, openStackClu
return reconcile.Result{}, nil
}
-func reconcileBastion(scope scope.Scope, cluster *clusterv1.Cluster, openStackCluster *infrav1.OpenStackCluster) (ctrl.Result, error) {
+func reconcileBastion(scope *scope.WithLogger, cluster *clusterv1.Cluster, openStackCluster *infrav1.OpenStackCluster) (ctrl.Result, error) {
scope.Logger().Info("Reconciling Bastion")
if openStackCluster.Spec.Bastion == nil || !openStackCluster.Spec.Bastion.Enabled {
@@ -542,7 +543,7 @@ func getBastionSecurityGroups(openStackCluster *infrav1.OpenStackCluster) []infr
return instanceSpecSecurityGroups
}
-func getOrCreateBastionPorts(scope scope.Scope, cluster *clusterv1.Cluster, openStackCluster *infrav1.OpenStackCluster, networkingService *networking.Service, clusterName string) error {
+func getOrCreateBastionPorts(scope *scope.WithLogger, cluster *clusterv1.Cluster, openStackCluster *infrav1.OpenStackCluster, networkingService *networking.Service, clusterName string) error {
scope.Logger().Info("Reconciling ports for bastion", "bastion", bastionName(openStackCluster.Name))
if openStackCluster.Status.Bastion == nil {
@@ -584,7 +585,7 @@ func bastionHashHasChanged(computeHash string, clusterAnnotations map[string]str
return latestHash != computeHash
}
-func reconcileNetworkComponents(scope scope.Scope, cluster *clusterv1.Cluster, openStackCluster *infrav1.OpenStackCluster) error {
+func reconcileNetworkComponents(scope *scope.WithLogger, cluster *clusterv1.Cluster, openStackCluster *infrav1.OpenStackCluster) error {
clusterName := fmt.Sprintf("%s-%s", cluster.Namespace, cluster.Name)
networkingService, err := networking.NewService(scope)
diff --git a/controllers/openstackcluster_controller_test.go b/controllers/openstackcluster_controller_test.go
index 8b99f0dc5f..4a19d65f7a 100644
--- a/controllers/openstackcluster_controller_test.go
+++ b/controllers/openstackcluster_controller_test.go
@@ -22,7 +22,6 @@ import (
"reflect"
"testing"
- "github.com/go-logr/logr"
"github.com/golang/mock/gomock"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
@@ -105,7 +104,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,
@@ -207,8 +206,10 @@ var _ = Describe("OpenStackCluster controller", func() {
}
err = k8sClient.Status().Update(ctx, testCluster)
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)
computeClientRecorder := mockScopeFactory.ComputeClient.EXPECT()
computeClientRecorder.GetServer("bastion-uuid").Return(nil, gophercloud.ErrResourceNotFound{})
@@ -258,8 +259,10 @@ var _ = Describe("OpenStackCluster controller", func() {
err = k8sClient.Status().Update(ctx, testCluster)
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)
server := clients.ServerExt{}
server.ID = "adopted-bastion-uuid"
@@ -342,8 +345,10 @@ var _ = Describe("OpenStackCluster controller", func() {
err = k8sClient.Status().Update(ctx, testCluster)
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)
server := clients.ServerExt{}
server.ID = "adopted-fip-bastion-uuid"
@@ -425,8 +430,10 @@ var _ = Describe("OpenStackCluster controller", func() {
err = k8sClient.Status().Update(ctx, testCluster)
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)
server := clients.ServerExt{}
server.ID = "requeue-bastion-uuid"
@@ -484,8 +491,10 @@ var _ = Describe("OpenStackCluster controller", func() {
err = k8sClient.Status().Update(ctx, testCluster)
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)
server := clients.ServerExt{}
server.ID = "delete-bastion-uuid"
@@ -534,8 +543,11 @@ var _ = Describe("OpenStackCluster controller", func() {
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()
@@ -614,8 +626,11 @@ var _ = Describe("OpenStackCluster controller", func() {
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()
@@ -675,8 +690,11 @@ var _ = Describe("OpenStackCluster controller", func() {
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()
diff --git a/controllers/openstackfloatingippool_controller.go b/controllers/openstackfloatingippool_controller.go
index 7c72bc081d..fbcdeb2b63 100644
--- a/controllers/openstackfloatingippool_controller.go
+++ b/controllers/openstackfloatingippool_controller.go
@@ -83,10 +83,11 @@ func (r *OpenStackFloatingIPPoolReconciler) Reconcile(ctx context.Context, req c
return ctrl.Result{}, client.IgnoreNotFound(err)
}
- scope, err := r.ScopeFactory.NewClientScopeFromFloatingIPPool(ctx, r.Client, pool, r.CaCertificates, log)
+ 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 {
@@ -203,7 +204,7 @@ func (r *OpenStackFloatingIPPoolReconciler) Reconcile(ctx context.Context, req c
return ctrl.Result{}, r.Client.Status().Update(ctx, pool)
}
-func (r *OpenStackFloatingIPPoolReconciler) reconcileDelete(ctx context.Context, scope scope.Scope, pool *infrav1alpha1.OpenStackFloatingIPPool) error {
+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 {
@@ -267,7 +268,7 @@ func diff(a []string, b []string) []string {
return result
}
-func (r *OpenStackFloatingIPPoolReconciler) reconcileIPAddresses(ctx context.Context, scope scope.Scope, pool *infrav1alpha1.OpenStackFloatingIPPool) error {
+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
@@ -309,7 +310,7 @@ func (r *OpenStackFloatingIPPoolReconciler) reconcileIPAddresses(ctx context.Con
return nil
}
-func (r *OpenStackFloatingIPPoolReconciler) getIP(ctx context.Context, scope scope.Scope, pool *infrav1alpha1.OpenStackFloatingIPPool) (string, error) {
+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
@@ -388,7 +389,7 @@ func (r *OpenStackFloatingIPPoolReconciler) getIP(ctx context.Context, scope sco
return ip, nil
}
-func (r *OpenStackFloatingIPPoolReconciler) reconcileFloatingIPNetwork(scope scope.Scope, pool *infrav1alpha1.OpenStackFloatingIPPool) error {
+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
diff --git a/controllers/openstackmachine_controller.go b/controllers/openstackmachine_controller.go
index 77d092f268..2a296bcfed 100644
--- a/controllers/openstackmachine_controller.go
+++ b/controllers/openstackmachine_controller.go
@@ -142,10 +142,11 @@ func (r *OpenStackMachineReconciler) Reconcile(ctx context.Context, req ctrl.Req
}
}()
- scope, err := r.ScopeFactory.NewClientScopeFromMachine(ctx, r.Client, openStackMachine, infraCluster, 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)
// Resolve and store referenced resources
changed, err := compute.ResolveReferencedMachineResources(scope, infraCluster, &openStackMachine.Spec, &openStackMachine.Status.ReferencedResources)
@@ -240,7 +241,7 @@ func (r *OpenStackMachineReconciler) SetupWithManager(ctx context.Context, mgr c
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, cluster *clusterv1.Cluster, 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)
@@ -333,7 +334,7 @@ func GetPortIDs(ports []infrav1.PortStatus) []string {
return portIDs
}
-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 (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope *scope.WithLogger, cluster *clusterv1.Cluster, 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.
@@ -489,7 +490,7 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope
return ctrl.Result{}, nil
}
-func getOrCreateMachinePorts(scope scope.Scope, openStackCluster *infrav1.OpenStackCluster, machine *clusterv1.Machine, openStackMachine *infrav1.OpenStackMachine, networkingService *networking.Service, clusterName string) error {
+func getOrCreateMachinePorts(scope *scope.WithLogger, openStackCluster *infrav1.OpenStackCluster, machine *clusterv1.Machine, openStackMachine *infrav1.OpenStackMachine, networkingService *networking.Service, clusterName string) error {
scope.Logger().Info("Reconciling ports for machine", "machine", machine.Name)
var machinePortsStatus []infrav1.PortStatus
var err error
@@ -647,7 +648,7 @@ func getManagedSecurityGroups(openStackCluster *infrav1.OpenStackCluster, machin
return machineSpecSecurityGroups
}
-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, clusterName string) error {
ip := instanceNS.IP(openStackCluster.Status.Network.Name)
loadbalancerService, err := loadbalancer.NewService(scope)
if err != nil {
diff --git a/controllers/suite_test.go b/controllers/suite_test.go
index 2986a4dde6..0a49b42403 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"
@@ -127,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
@@ -138,11 +138,10 @@ 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())
})
diff --git a/pkg/cloud/services/compute/dependent_resources.go b/pkg/cloud/services/compute/dependent_resources.go
index 6e2a5eb270..ab8bf67547 100644
--- a/pkg/cloud/services/compute/dependent_resources.go
+++ b/pkg/cloud/services/compute/dependent_resources.go
@@ -22,7 +22,7 @@ import (
"sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
)
-func ResolveDependentMachineResources(scope scope.Scope, openStackMachine *infrav1.OpenStackMachine) (changed bool, err error) {
+func ResolveDependentMachineResources(scope *scope.WithLogger, openStackMachine *infrav1.OpenStackMachine) (changed bool, err error) {
changed = false
networkingService, err := networking.NewService(scope)
@@ -33,7 +33,7 @@ func ResolveDependentMachineResources(scope scope.Scope, openStackMachine *infra
return networkingService.AdoptMachinePorts(scope, openStackMachine, openStackMachine.Status.ReferencedResources.PortsOpts)
}
-func ResolveDependentBastionResources(scope scope.Scope, openStackCluster *infrav1.OpenStackCluster, bastionName string) (changed bool, err error) {
+func ResolveDependentBastionResources(scope *scope.WithLogger, openStackCluster *infrav1.OpenStackCluster, bastionName string) (changed bool, err error) {
changed = false
networkingService, err := networking.NewService(scope)
diff --git a/pkg/cloud/services/compute/dependent_resources_test.go b/pkg/cloud/services/compute/dependent_resources_test.go
index 1bfb8d5791..e1e91f27f3 100644
--- a/pkg/cloud/services/compute/dependent_resources_test.go
+++ b/pkg/cloud/services/compute/dependent_resources_test.go
@@ -19,7 +19,7 @@ package compute
import (
"testing"
- "github.com/go-logr/logr"
+ "github.com/go-logr/logr/testr"
"github.com/golang/mock/gomock"
"github.com/google/go-cmp/cmp"
. "github.com/onsi/gomega"
@@ -93,8 +93,9 @@ func Test_ResolveDependentMachineResources(t *testing.T) {
for _, tt := range tests {
t.Run(tt.testName, func(t *testing.T) {
g := NewWithT(t)
+ log := testr.New(t)
mockCtrl := gomock.NewController(t)
- mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "", logr.Discard())
+ mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "")
defaultOpenStackMachine := &infrav1.OpenStackMachine{
ObjectMeta: metav1.ObjectMeta{
@@ -103,7 +104,7 @@ func Test_ResolveDependentMachineResources(t *testing.T) {
Status: tt.openStackMachineStatus,
}
- _, err := ResolveDependentMachineResources(mockScopeFactory, defaultOpenStackMachine)
+ _, err := ResolveDependentMachineResources(scope.NewWithLogger(mockScopeFactory, log), defaultOpenStackMachine)
if tt.wantErr {
g.Expect(err).Error()
return
@@ -192,10 +193,11 @@ func TestResolveDependentBastionResources(t *testing.T) {
for _, tt := range tests {
t.Run(tt.testName, func(t *testing.T) {
g := NewWithT(t)
+ log := testr.New(t)
mockCtrl := gomock.NewController(t)
- mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "", logr.Discard())
+ mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "")
- _, err := ResolveDependentBastionResources(mockScopeFactory, tt.openStackCluster, bastionName)
+ _, err := ResolveDependentBastionResources(scope.NewWithLogger(mockScopeFactory, log), tt.openStackCluster, bastionName)
if tt.wantErr {
g.Expect(err).Error()
return
diff --git a/pkg/cloud/services/compute/instance_test.go b/pkg/cloud/services/compute/instance_test.go
index 69b0ac05b8..bc5b01def5 100644
--- a/pkg/cloud/services/compute/instance_test.go
+++ b/pkg/cloud/services/compute/instance_test.go
@@ -22,7 +22,7 @@ import (
"testing"
"time"
- "github.com/go-logr/logr"
+ "github.com/go-logr/logr/testr"
"github.com/golang/mock/gomock"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes"
@@ -120,9 +120,10 @@ func TestService_getImageID(t *testing.T) {
for _, tt := range tests {
t.Run(tt.testName, func(t *testing.T) {
mockCtrl := gomock.NewController(t)
- mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "", logr.Discard())
+ log := testr.New(t)
+ mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "")
- s, err := NewService(mockScopeFactory)
+ s, err := NewService(scope.NewWithLogger(mockScopeFactory, log))
if err != nil {
t.Fatalf("Failed to create service: %v", err)
}
@@ -666,7 +667,8 @@ func TestService_ReconcileInstance(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mockCtrl := gomock.NewController(t)
- mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "", logr.Discard())
+ log := testr.New(t)
+ mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "")
computeRecorder := mockScopeFactory.ComputeClient.EXPECT()
imageRecorder := mockScopeFactory.ImageClient.EXPECT()
@@ -675,7 +677,7 @@ func TestService_ReconcileInstance(t *testing.T) {
tt.expect(&recorders{computeRecorder, imageRecorder, networkRecorder, volumeRecorder})
- s, err := NewService(mockScopeFactory)
+ s, err := NewService(scope.NewWithLogger(mockScopeFactory, log))
if err != nil {
t.Fatalf("Failed to create service: %v", err)
}
@@ -759,7 +761,8 @@ func TestService_DeleteInstance(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mockCtrl := gomock.NewController(t)
- mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "", logr.Discard())
+ log := testr.New(t)
+ mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "")
computeRecorder := mockScopeFactory.ComputeClient.EXPECT()
networkRecorder := mockScopeFactory.NetworkClient.EXPECT()
@@ -767,7 +770,7 @@ func TestService_DeleteInstance(t *testing.T) {
tt.expect(&recorders{computeRecorder, networkRecorder, volumeRecorder})
- s, err := NewService(mockScopeFactory)
+ s, err := NewService(scope.NewWithLogger(mockScopeFactory, log))
if err != nil {
t.Fatalf("Failed to create service: %v", err)
}
diff --git a/pkg/cloud/services/compute/instance_types_test.go b/pkg/cloud/services/compute/instance_types_test.go
index 271af92f60..650fda62ef 100644
--- a/pkg/cloud/services/compute/instance_types_test.go
+++ b/pkg/cloud/services/compute/instance_types_test.go
@@ -19,7 +19,7 @@ package compute
import (
"testing"
- "github.com/go-logr/logr"
+ "github.com/go-logr/logr/testr"
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
@@ -196,10 +196,11 @@ func TestNetworkStatus_Addresses(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
g := NewWithT(t)
+ log := testr.New(t)
is := &InstanceStatus{
server: serverWithAddresses(tt.addresses),
- logger: logr.Discard(),
+ logger: log,
}
instanceNS, err := is.NetworkStatus()
g.Expect(err).NotTo(HaveOccurred())
@@ -411,10 +412,11 @@ func TestInstanceNetworkStatus(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
g := NewWithT(t)
+ log := testr.New(t)
is := &InstanceStatus{
server: serverWithAddresses(tt.addresses),
- logger: logr.Discard(),
+ logger: log,
}
ns, err := is.NetworkStatus()
g.Expect(err).NotTo(HaveOccurred())
diff --git a/pkg/cloud/services/compute/referenced_resources.go b/pkg/cloud/services/compute/referenced_resources.go
index c78298ce16..657a14f93a 100644
--- a/pkg/cloud/services/compute/referenced_resources.go
+++ b/pkg/cloud/services/compute/referenced_resources.go
@@ -28,7 +28,7 @@ import (
// Note that we only set the fields in ReferencedMachineResources that are not set yet. This is ok because:
// - OpenStackMachine is immutable, so we can't change the spec after the machine is created.
// - the bastion is mutable, but we delete the bastion when the spec changes, so the bastion status will be empty.
-func ResolveReferencedMachineResources(scope scope.Scope, openStackCluster *infrav1.OpenStackCluster, spec *infrav1.OpenStackMachineSpec, resources *infrav1.ReferencedMachineResources) (changed bool, err error) {
+func ResolveReferencedMachineResources(scope *scope.WithLogger, openStackCluster *infrav1.OpenStackCluster, spec *infrav1.OpenStackMachineSpec, resources *infrav1.ReferencedMachineResources) (changed bool, err error) {
changed = false
computeService, err := NewService(scope)
diff --git a/pkg/cloud/services/compute/referenced_resources_test.go b/pkg/cloud/services/compute/referenced_resources_test.go
index 06f6a8f5d2..e4107ba302 100644
--- a/pkg/cloud/services/compute/referenced_resources_test.go
+++ b/pkg/cloud/services/compute/referenced_resources_test.go
@@ -19,7 +19,7 @@ package compute
import (
"testing"
- "github.com/go-logr/logr"
+ "github.com/go-logr/logr/testr"
"github.com/golang/mock/gomock"
"github.com/google/go-cmp/cmp"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/servergroups"
@@ -148,8 +148,9 @@ func Test_ResolveReferencedMachineResources(t *testing.T) {
for _, tt := range tests {
t.Run(tt.testName, func(t *testing.T) {
g := NewWithT(t)
+ log := testr.New(t)
mockCtrl := gomock.NewController(t)
- mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "", logr.Discard())
+ mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "")
tt.expectComputeMock(mockScopeFactory.ComputeClient.EXPECT())
tt.expectImageMock(mockScopeFactory.ImageClient.EXPECT())
@@ -178,7 +179,8 @@ func Test_ResolveReferencedMachineResources(t *testing.T) {
resources := &infrav1.ReferencedMachineResources{}
- _, err := ResolveReferencedMachineResources(mockScopeFactory, openStackCluster, machineSpec, resources)
+ scope := scope.NewWithLogger(mockScopeFactory, log)
+ _, err := ResolveReferencedMachineResources(scope, openStackCluster, machineSpec, resources)
if tt.wantErr {
g.Expect(err).Error()
return
diff --git a/pkg/cloud/services/compute/servergroup_test.go b/pkg/cloud/services/compute/servergroup_test.go
index af8ed35f02..2771ccf26a 100644
--- a/pkg/cloud/services/compute/servergroup_test.go
+++ b/pkg/cloud/services/compute/servergroup_test.go
@@ -20,7 +20,7 @@ import (
"fmt"
"testing"
- "github.com/go-logr/logr"
+ "github.com/go-logr/logr/testr"
"github.com/golang/mock/gomock"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/servergroups"
@@ -107,9 +107,10 @@ func TestService_GetServerGroupID(t *testing.T) {
for _, tt := range tests {
t.Run(tt.testName, func(t *testing.T) {
mockCtrl := gomock.NewController(t)
- mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "", logr.Discard())
+ log := testr.New(t)
+ mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "")
- s, err := NewService(mockScopeFactory)
+ s, err := NewService(scope.NewWithLogger(mockScopeFactory, log))
if err != nil {
t.Fatalf("Failed to create service: %v", err)
}
diff --git a/pkg/cloud/services/compute/service.go b/pkg/cloud/services/compute/service.go
index b819d33e31..ac3a9a8022 100644
--- a/pkg/cloud/services/compute/service.go
+++ b/pkg/cloud/services/compute/service.go
@@ -25,7 +25,7 @@ import (
)
type Service struct {
- scope scope.Scope
+ scope *scope.WithLogger
_computeClient clients.ComputeClient
_volumeClient clients.VolumeClient
_imageClient clients.ImageClient
@@ -33,7 +33,7 @@ type Service struct {
}
// NewService returns an instance of the compute service.
-func NewService(scope scope.Scope) (*Service, error) {
+func NewService(scope *scope.WithLogger) (*Service, error) {
return &Service{
scope: scope,
}, nil
diff --git a/pkg/cloud/services/loadbalancer/loadbalancer_test.go b/pkg/cloud/services/loadbalancer/loadbalancer_test.go
index 0c9996ca0f..f264a83415 100644
--- a/pkg/cloud/services/loadbalancer/loadbalancer_test.go
+++ b/pkg/cloud/services/loadbalancer/loadbalancer_test.go
@@ -22,7 +22,7 @@ import (
"net"
"testing"
- "github.com/go-logr/logr"
+ "github.com/go-logr/logr/testr"
"github.com/golang/mock/gomock"
"github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/apiversions"
"github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/listeners"
@@ -139,9 +139,10 @@ func Test_ReconcileLoadBalancer(t *testing.T) {
for _, tt := range lbtests {
t.Run(tt.name, func(t *testing.T) {
g := NewWithT(t)
+ log := testr.New(t)
- mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "", logr.Discard())
- lbs, err := NewService(mockScopeFactory)
+ mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "")
+ lbs, err := NewService(scope.NewWithLogger(mockScopeFactory, log))
g.Expect(err).NotTo(HaveOccurred())
tt.expectNetwork(mockScopeFactory.NetworkClient.EXPECT())
@@ -485,9 +486,10 @@ func Test_getOrCreateAPILoadBalancer(t *testing.T) {
for _, tt := range lbtests {
t.Run(tt.name, func(t *testing.T) {
g := NewWithT(t)
+ log := testr.New(t)
- mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "", logr.Discard())
- lbs, err := NewService(mockScopeFactory)
+ mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "")
+ lbs, err := NewService(scope.NewWithLogger(mockScopeFactory, log))
g.Expect(err).NotTo(HaveOccurred())
tt.expectLoadBalancer(mockScopeFactory.LbClient.EXPECT())
diff --git a/pkg/cloud/services/loadbalancer/service.go b/pkg/cloud/services/loadbalancer/service.go
index 380ebd05d9..58ffc07912 100644
--- a/pkg/cloud/services/loadbalancer/service.go
+++ b/pkg/cloud/services/loadbalancer/service.go
@@ -26,13 +26,13 @@ import (
// Service interfaces with the OpenStack Neutron LBaaS v2 API.
type Service struct {
- scope scope.Scope
+ scope *scope.WithLogger
loadbalancerClient clients.LbClient
networkingService *networking.Service
}
// NewService returns an instance of the loadbalancer service.
-func NewService(scope scope.Scope) (*Service, error) {
+func NewService(scope *scope.WithLogger) (*Service, error) {
loadbalancerClient, err := scope.NewLbClient()
if err != nil {
return nil, err
diff --git a/pkg/cloud/services/networking/network_test.go b/pkg/cloud/services/networking/network_test.go
index 1781ecab67..27a07580ba 100644
--- a/pkg/cloud/services/networking/network_test.go
+++ b/pkg/cloud/services/networking/network_test.go
@@ -19,7 +19,7 @@ package networking
import (
"testing"
- "github.com/go-logr/logr"
+ "github.com/go-logr/logr/testr"
"github.com/golang/mock/gomock"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external"
@@ -188,9 +188,12 @@ func Test_ReconcileNetwork(t *testing.T) {
g := NewWithT(t)
mockClient := mock.NewMockNetworkClient(mockCtrl)
tt.expect(mockClient.EXPECT())
+
+ scopeFactory := scope.NewMockScopeFactory(mockCtrl, "")
+ log := testr.New(t)
s := Service{
client: mockClient,
- scope: scope.NewMockScopeFactory(mockCtrl, "", logr.Discard()),
+ scope: scope.NewWithLogger(scopeFactory, log),
}
err := s.ReconcileNetwork(tt.openStackCluster, clusterName)
g.Expect(err).ShouldNot(HaveOccurred())
@@ -410,9 +413,12 @@ func Test_ReconcileExternalNetwork(t *testing.T) {
g := NewWithT(t)
mockClient := mock.NewMockNetworkClient(mockCtrl)
tt.expect(mockClient.EXPECT())
+
+ scopeFactory := scope.NewMockScopeFactory(mockCtrl, "")
+ log := testr.New(t)
s := Service{
client: mockClient,
- scope: scope.NewMockScopeFactory(mockCtrl, "", logr.Discard()),
+ scope: scope.NewWithLogger(scopeFactory, log),
}
err := s.ReconcileExternalNetwork(tt.openStackCluster)
if (err != nil) != tt.wantErr {
@@ -668,11 +674,13 @@ func Test_ReconcileSubnet(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
g := NewWithT(t)
+ log := testr.New(t)
mockClient := mock.NewMockNetworkClient(mockCtrl)
tt.expect(mockClient.EXPECT())
+ mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "")
s := Service{
client: mockClient,
- scope: scope.NewMockScopeFactory(mockCtrl, "", logr.Discard()),
+ scope: scope.NewWithLogger(mockScopeFactory, log),
}
err := s.ReconcileSubnet(tt.openStackCluster, clusterName)
g.Expect(err).ShouldNot(HaveOccurred())
diff --git a/pkg/cloud/services/networking/port.go b/pkg/cloud/services/networking/port.go
index 5df5002534..1ecf4beaca 100644
--- a/pkg/cloud/services/networking/port.go
+++ b/pkg/cloud/services/networking/port.go
@@ -518,7 +518,7 @@ func (s *Service) IsTrunkExtSupported() (trunknSupported bool, err error) {
// by checking if they exist and if they do, it'll add them to the OpenStackMachine status.
// A port is searched by name and network ID and has to be unique.
// If the port is not found, it'll be ignored because it'll be created after the adoption.
-func (s *Service) AdoptMachinePorts(scope scope.Scope, openStackMachine *infrav1.OpenStackMachine, desiredPorts []infrav1.PortOpts) (changed bool, err error) {
+func (s *Service) AdoptMachinePorts(scope *scope.WithLogger, openStackMachine *infrav1.OpenStackMachine, desiredPorts []infrav1.PortOpts) (changed bool, err error) {
changed = false
// We can skip adoption if the instance is ready because OpenStackMachine is immutable once ready
@@ -572,7 +572,7 @@ func (s *Service) AdoptMachinePorts(scope scope.Scope, openStackMachine *infrav1
// it'll add them to the OpenStackCluster status.
// A port is searched by name and network ID and has to be unique.
// If the port is not found, it'll be ignored because it'll be created after the adoption.
-func (s *Service) AdoptBastionPorts(scope scope.Scope, openStackCluster *infrav1.OpenStackCluster, bastionName string) (changed bool, err error) {
+func (s *Service) AdoptBastionPorts(scope *scope.WithLogger, openStackCluster *infrav1.OpenStackCluster, bastionName string) (changed bool, err error) {
changed = false
if openStackCluster.Status.Network == nil {
diff --git a/pkg/cloud/services/networking/port_test.go b/pkg/cloud/services/networking/port_test.go
index 57103319e0..96d741d992 100644
--- a/pkg/cloud/services/networking/port_test.go
+++ b/pkg/cloud/services/networking/port_test.go
@@ -19,7 +19,7 @@ package networking
import (
"testing"
- "github.com/go-logr/logr"
+ "github.com/go-logr/logr/testr"
"github.com/golang/mock/gomock"
"github.com/google/go-cmp/cmp"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/attributestags"
@@ -774,14 +774,16 @@ func TestService_normalizePorts(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
g := NewWithT(t)
+ log := testr.New(t)
mockClient := mock.NewMockNetworkClient(mockCtrl)
if tt.expectNetwork != nil {
tt.expectNetwork(mockClient.EXPECT())
}
+ mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "")
s := Service{
client: mockClient,
- scope: scope.NewMockScopeFactory(mockCtrl, "", logr.Discard()),
+ scope: scope.NewWithLogger(mockScopeFactory, log),
}
got, err := s.normalizePorts(tt.ports, openStackCluster, tt.instanceTrunk)
diff --git a/pkg/cloud/services/networking/securitygroups_test.go b/pkg/cloud/services/networking/securitygroups_test.go
index e09ba9b7fb..b88a81cd43 100644
--- a/pkg/cloud/services/networking/securitygroups_test.go
+++ b/pkg/cloud/services/networking/securitygroups_test.go
@@ -19,7 +19,7 @@ import (
"reflect"
"testing"
- "github.com/go-logr/logr"
+ "github.com/go-logr/logr/testr"
"github.com/golang/mock/gomock"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules"
@@ -342,9 +342,10 @@ func TestGenerateDesiredSecGroups(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
g := NewWithT(t)
- mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "", logr.Discard())
+ log := testr.New(t)
+ mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "")
- s, err := NewService(mockScopeFactory)
+ s, err := NewService(scope.NewWithLogger(mockScopeFactory, log))
if err != nil {
t.Fatalf("Failed to create service: %v", err)
}
@@ -515,9 +516,10 @@ func TestReconcileGroupRules(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
g := NewWithT(t)
- mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "", logr.Discard())
+ log := testr.New(t)
+ mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "")
- s, err := NewService(mockScopeFactory)
+ s, err := NewService(scope.NewWithLogger(mockScopeFactory, log))
if err != nil {
t.Fatalf("Failed to create service: %v", err)
}
diff --git a/pkg/cloud/services/networking/service.go b/pkg/cloud/services/networking/service.go
index b0a9b8da17..3a01c48b85 100644
--- a/pkg/cloud/services/networking/service.go
+++ b/pkg/cloud/services/networking/service.go
@@ -37,12 +37,12 @@ const (
// Service interfaces with the OpenStack Networking API.
// It will create a network related infrastructure for the cluster, like network, subnet, router, security groups.
type Service struct {
- scope scope.Scope
+ scope *scope.WithLogger
client clients.NetworkClient
}
// NewService returns an instance of the networking service.
-func NewService(scope scope.Scope) (*Service, error) {
+func NewService(scope *scope.WithLogger) (*Service, error) {
networkClient, err := scope.NewNetworkClient()
if err != nil {
return nil, err
diff --git a/pkg/scope/mock.go b/pkg/scope/mock.go
index 4568a66d19..3f3cec13be 100644
--- a/pkg/scope/mock.go
+++ b/pkg/scope/mock.go
@@ -40,12 +40,11 @@ type MockScopeFactory struct {
ImageClient *mock.MockImageClient
LbClient *mock.MockLbClient
- logger logr.Logger
projectID string
clientScopeCreateError error
}
-func NewMockScopeFactory(mockCtrl *gomock.Controller, projectID string, logger logr.Logger) *MockScopeFactory {
+func NewMockScopeFactory(mockCtrl *gomock.Controller, projectID string) *MockScopeFactory {
computeClient := mock.NewMockComputeClient(mockCtrl)
volumeClient := mock.NewMockVolumeClient(mockCtrl)
imageClient := mock.NewMockImageClient(mockCtrl)
@@ -59,7 +58,6 @@ func NewMockScopeFactory(mockCtrl *gomock.Controller, projectID string, logger l
NetworkClient: networkClient,
LbClient: lbClient,
projectID: projectID,
- logger: logger,
}
}
@@ -108,10 +106,6 @@ func (f *MockScopeFactory) NewLbClient() (clients.LbClient, error) {
return f.LbClient, nil
}
-func (f *MockScopeFactory) Logger() logr.Logger {
- return f.logger
-}
-
func (f *MockScopeFactory) ProjectID() string {
return f.projectID
}
diff --git a/pkg/scope/provider.go b/pkg/scope/provider.go
index 2b531f361d..cda179d2e6 100644
--- a/pkg/scope/provider.go
+++ b/pkg/scope/provider.go
@@ -141,7 +141,6 @@ type providerScope struct {
providerClient *gophercloud.ProviderClient
providerClientOpts *clientconfig.ClientOpts
projectID string
- logger logr.Logger
}
func NewProviderScope(cloud clientconfig.Cloud, caCert []byte, logger logr.Logger) (Scope, error) {
@@ -154,7 +153,6 @@ func NewProviderScope(cloud clientconfig.Cloud, caCert []byte, logger logr.Logge
providerClient: providerClient,
providerClientOpts: clientOpts,
projectID: projectID,
- logger: logger,
}, nil
}
@@ -186,10 +184,6 @@ func NewCachedProviderScope(cache *cache.LRUExpireCache, cloud clientconfig.Clou
return scope, nil
}
-func (s *providerScope) Logger() logr.Logger {
- return s.logger
-}
-
func (s *providerScope) ProjectID() string {
return s.projectID
}
diff --git a/pkg/scope/scope.go b/pkg/scope/scope.go
index 6b16e908f1..6792df2fb7 100644
--- a/pkg/scope/scope.go
+++ b/pkg/scope/scope.go
@@ -54,7 +54,24 @@ type Scope interface {
NewImageClient() (clients.ImageClient, error)
NewNetworkClient() (clients.NetworkClient, error)
NewLbClient() (clients.LbClient, error)
- Logger() logr.Logger
ProjectID() string
ExtractToken() (*tokens.Token, error)
}
+
+// WithLogger extends Scope with a logger.
+type WithLogger struct {
+ Scope
+
+ logger logr.Logger
+}
+
+func NewWithLogger(scope Scope, logger logr.Logger) *WithLogger {
+ return &WithLogger{
+ Scope: scope,
+ logger: logger,
+ }
+}
+
+func (s *WithLogger) Logger() logr.Logger {
+ return s.logger
+}
From e9fb53c937de1d668a907d750757eec5630fbc77 Mon Sep 17 00:00:00 2001
From: Emilien Macchi
Date: Wed, 21 Feb 2024 14:23:41 -0500
Subject: [PATCH 082/180] Rename `v1alpha8` to `v1beta1`
---
.golangci.yml | 2 +-
Makefile | 6 +-
PROJECT | 8 +-
README.md | 6 +-
api/v1alpha5/conversion.go | 156 +--
api/v1alpha5/conversion_test.go | 6 +-
api/v1alpha5/doc.go | 2 +-
api/v1alpha5/zz_generated.conversion.go | 876 ++++++-------
api/v1alpha6/conversion.go | 212 ++--
api/v1alpha6/conversion_test.go | 6 +-
api/v1alpha6/doc.go | 2 +-
api/v1alpha6/zz_generated.conversion.go | 914 +++++++-------
api/v1alpha7/conversion.go | 148 +--
api/v1alpha7/conversion_test.go | 6 +-
api/v1alpha7/doc.go | 2 +-
api/v1alpha7/zz_generated.conversion.go | 1084 ++++++++---------
.../conditions_consts.go | 2 +-
api/{v1alpha8 => v1beta1}/conversion.go | 4 +-
api/{v1alpha8 => v1beta1}/doc.go | 2 +-
api/{v1alpha8 => v1beta1}/filter_convert.go | 2 +-
.../groupversion_info.go | 6 +-
api/{v1alpha8 => v1beta1}/identity_types.go | 2 +-
.../openstackcluster_types.go | 2 +-
.../openstackcluster_webhook.go | 6 +-
.../openstackcluster_webhook_test.go | 2 +-
.../openstackclusterlist_webhook.go | 2 +-
.../openstackclustertemplate_types.go | 2 +-
.../openstackclustertemplate_webhook.go | 6 +-
.../openstackmachine_types.go | 2 +-
.../openstackmachine_webhook.go | 6 +-
.../openstackmachinelist_webhook.go | 2 +-
.../openstackmachinetemplate_types.go | 2 +-
.../openstackmachinetemplate_webhook.go | 4 +-
.../openstackmachinetemplate_webhook_test.go | 2 +-
.../openstackmachinetemplatelist_webhook.go | 2 +-
api/{v1alpha8 => v1beta1}/types.go | 2 +-
api/{v1alpha8 => v1beta1}/webhooks.go | 2 +-
.../zz_generated.deepcopy.go | 8 +-
...re.cluster.x-k8s.io_openstackclusters.yaml | 2 +-
...er.x-k8s.io_openstackclustertemplates.yaml | 2 +-
...re.cluster.x-k8s.io_openstackmachines.yaml | 2 +-
...er.x-k8s.io_openstackmachinetemplates.yaml | 2 +-
config/crd/kustomization.yaml | 2 +-
config/webhook/manifests.yaml | 28 +-
controllers/openstackcluster_controller.go | 2 +-
.../openstackcluster_controller_test.go | 2 +-
.../openstackfloatingippool_controller.go | 2 +-
controllers/openstackmachine_controller.go | 2 +-
.../openstackmachine_controller_test.go | 2 +-
controllers/suite_test.go | 2 +-
docs/book/src/SUMMARY.md | 2 +-
.../src/clusteropenstack/configuration.md | 28 +-
docs/book/src/development/development.md | 2 +-
...-to-v1alpha8.md => v1alpha7-to-v1beta1.md} | 22 +-
.../default/cluster-template.yaml | 12 +-
.../default/kustomization.yaml | 0
.../flatcar-sysext/kustomization.yaml | 0
.../flatcar-sysext/patch-flatcar.yaml | 6 +-
.../flatcar/kustomization.yaml | 0
.../flatcar/patch-flatcar.yaml | 6 +-
.../without-lb/kustomization.yaml | 0
.../without-lb/patch-without-lb.yaml | 2 +-
main.go | 2 +-
.../services/compute/dependent_resources.go | 2 +-
.../compute/dependent_resources_test.go | 2 +-
pkg/cloud/services/compute/instance.go | 2 +-
pkg/cloud/services/compute/instance_test.go | 2 +-
pkg/cloud/services/compute/instance_types.go | 2 +-
.../services/compute/referenced_resources.go | 2 +-
.../compute/referenced_resources_test.go | 2 +-
pkg/cloud/services/compute/servergroup.go | 2 +-
.../services/compute/servergroup_test.go | 2 +-
.../services/loadbalancer/loadbalancer.go | 2 +-
.../loadbalancer/loadbalancer_test.go | 2 +-
pkg/cloud/services/networking/floatingip.go | 2 +-
.../services/networking/floatingip_test.go | 2 +-
pkg/cloud/services/networking/network.go | 2 +-
pkg/cloud/services/networking/network_test.go | 2 +-
pkg/cloud/services/networking/port.go | 2 +-
pkg/cloud/services/networking/port_test.go | 2 +-
pkg/cloud/services/networking/router.go | 2 +-
.../services/networking/securitygroups.go | 2 +-
.../networking/securitygroups_test.go | 2 +-
pkg/cloud/services/networking/trunk_test.go | 2 +-
pkg/scope/mock.go | 2 +-
pkg/scope/provider.go | 2 +-
pkg/scope/scope.go | 2 +-
pkg/utils/controllers/controllers.go | 2 +-
pkg/utils/controllers/controllers_test.go | 2 +-
.../cluster-template-flatcar-sysext.yaml | 12 +-
templates/cluster-template-flatcar.yaml | 12 +-
templates/cluster-template-without-lb.yaml | 12 +-
templates/cluster-template.yaml | 12 +-
templates/clusterclass-dev-test.yaml | 16 +-
.../data/kustomize/default/kustomization.yaml | 2 +-
.../flatcar-sysext/kustomization.yaml | 2 +-
.../data/kustomize/flatcar/kustomization.yaml | 2 +-
.../data/kustomize/k8s-upgrade/kcp-patch.yaml | 2 +-
.../data/kustomize/k8s-upgrade/md-patch.yaml | 2 +-
.../k8s-upgrade/upgrade-from-template.yaml | 4 +-
.../k8s-upgrade/upgrade-to-template.yaml | 4 +-
.../kustomize/without-lb/kustomization.yaml | 2 +-
test/e2e/shared/common.go | 2 +-
test/e2e/shared/defaults.go | 2 +-
test/e2e/shared/openstack.go | 2 +-
test/e2e/suites/e2e/e2e_test.go | 2 +-
106 files changed, 1891 insertions(+), 1891 deletions(-)
rename api/{v1alpha8 => v1beta1}/conditions_consts.go (99%)
rename api/{v1alpha8 => v1beta1}/conversion.go (96%)
rename api/{v1alpha8 => v1beta1}/doc.go (97%)
rename api/{v1alpha8 => v1beta1}/filter_convert.go (99%)
rename api/{v1alpha8 => v1beta1}/groupversion_info.go (90%)
rename api/{v1alpha8 => v1beta1}/identity_types.go (98%)
rename api/{v1alpha8 => v1beta1}/openstackcluster_types.go (99%)
rename api/{v1alpha8 => v1beta1}/openstackcluster_webhook.go (91%)
rename api/{v1alpha8 => v1beta1}/openstackcluster_webhook_test.go (99%)
rename api/{v1alpha8 => v1beta1}/openstackclusterlist_webhook.go (98%)
rename api/{v1alpha8 => v1beta1}/openstackclustertemplate_types.go (99%)
rename api/{v1alpha8 => v1beta1}/openstackclustertemplate_webhook.go (80%)
rename api/{v1alpha8 => v1beta1}/openstackmachine_types.go (99%)
rename api/{v1alpha8 => v1beta1}/openstackmachine_webhook.go (86%)
rename api/{v1alpha8 => v1beta1}/openstackmachinelist_webhook.go (98%)
rename api/{v1alpha8 => v1beta1}/openstackmachinetemplate_types.go (98%)
rename api/{v1alpha8 => v1beta1}/openstackmachinetemplate_webhook.go (91%)
rename api/{v1alpha8 => v1beta1}/openstackmachinetemplate_webhook_test.go (99%)
rename api/{v1alpha8 => v1beta1}/openstackmachinetemplatelist_webhook.go (98%)
rename api/{v1alpha8 => v1beta1}/types.go (99%)
rename api/{v1alpha8 => v1beta1}/webhooks.go (98%)
rename api/{v1alpha8 => v1beta1}/zz_generated.deepcopy.go (99%)
rename docs/book/src/topics/crd-changes/{v1alpha7-to-v1alpha8.md => v1alpha7-to-v1beta1.md} (85%)
rename kustomize/{v1alpha8 => v1beta1}/default/cluster-template.yaml (92%)
rename kustomize/{v1alpha8 => v1beta1}/default/kustomization.yaml (100%)
rename kustomize/{v1alpha8 => v1beta1}/flatcar-sysext/kustomization.yaml (100%)
rename kustomize/{v1alpha8 => v1beta1}/flatcar-sysext/patch-flatcar.yaml (98%)
rename kustomize/{v1alpha8 => v1beta1}/flatcar/kustomization.yaml (100%)
rename kustomize/{v1alpha8 => v1beta1}/flatcar/patch-flatcar.yaml (95%)
rename kustomize/{v1alpha8 => v1beta1}/without-lb/kustomization.yaml (100%)
rename kustomize/{v1alpha8 => v1beta1}/without-lb/patch-without-lb.yaml (83%)
diff --git a/.golangci.yml b/.golangci.yml
index 3bc8da3e48..5fc2435fb4 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -102,7 +102,7 @@ linters-settings:
alias: infrav1alpha6
- pkg: sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7
alias: infrav1alpha7
- - pkg: sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8
+ - 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
diff --git a/Makefile b/Makefile
index b66e60a5c6..4c6837f716 100644
--- a/Makefile
+++ b/Makefile
@@ -260,7 +260,7 @@ generate-go: $(MOCKGEN)
--input-dirs=./api/v1alpha5 \
--input-dirs=./api/v1alpha6 \
--input-dirs=./api/v1alpha7 \
- --input-dirs=./api/v1alpha8 \
+ --input-dirs=./api/v1beta1 \
--output-file-base=zz_generated.conversion \
--go-header-file=./hack/boilerplate/boilerplate.generatego.txt
go generate ./...
@@ -410,10 +410,10 @@ templates: templates/cluster-template.yaml \
templates/cluster-template-flatcar.yaml \
templates/cluster-template-flatcar-sysext.yaml
-templates/cluster-template.yaml: kustomize/v1alpha8/default $(KUSTOMIZE) FORCE
+templates/cluster-template.yaml: kustomize/v1beta1/default $(KUSTOMIZE) FORCE
$(KUSTOMIZE) build "$<" > "$@"
-templates/cluster-template-%.yaml: kustomize/v1alpha8/% $(KUSTOMIZE) FORCE
+templates/cluster-template-%.yaml: kustomize/v1beta1/% $(KUSTOMIZE) FORCE
$(KUSTOMIZE) build "$<" > "$@"
.PHONY: release-templates
diff --git a/PROJECT b/PROJECT
index 6514dde9b3..6b397b884f 100644
--- a/PROJECT
+++ b/PROJECT
@@ -42,17 +42,17 @@ resources:
kind: OpenStackClusterTemplate
version: v1alpha7
- group: infrastructure
- version: v1alpha8
+ version: v1beta1
kind: OpenStackCluster
- group: infrastructure
- version: v1alpha8
+ version: v1beta1
kind: OpenStackMachine
- group: infrastructure
- version: v1alpha8
+ version: v1beta1
kind: OpenStackMachineTemplate
- group: infrastructure
kind: OpenStackClusterTemplate
- version: v1alpha8
+ version: v1beta1
- group: infrastructure
kind: OpenStackFloatingIPPool
version: v1alpha1
diff --git a/README.md b/README.md
index 134890bfa9..51b35911b5 100644
--- a/README.md
+++ b/README.md
@@ -44,7 +44,7 @@ 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 (v0.9) | ✓ |
-| OpenStack Provider v1alpha8 | ✓ |
+| OpenStack Provider v1beta1 | ✓ |
This provider's versions are able to install and manage the following versions of Kubernetes:
@@ -54,7 +54,7 @@ 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 (v0.9) | + | ✓ | ✓ | ★ |
-| OpenStack Provider v1alpha8 | + | ✓ | ✓ | ★ |
+| OpenStack Provider v1beta1 | + | ✓ | ✓ | ★ |
This provider's versions are able to install Kubernetes to the following versions of OpenStack:
@@ -63,7 +63,7 @@ This provider's versions are able to install Kubernetes to the following version
| OpenStack Provider v1alpha5 (v0.6) | + | + | + | + | + | ✓ | ✓ | ✓ | ✓ | ★ |
| OpenStack Provider v1alpha6 (v0.7) | + | + | + | + | + | ✓ | ✓ | ✓ | ✓ | ★ |
| OpenStack Provider v1alpha7 (v0.9) | | + | + | + | + | ✓ | ✓ | ✓ | ✓ | ★ |
-| OpenStack Provider v1alpha8 | | + | + | + | + | ✓ | ✓ | ✓ | ✓ | ★ |
+| OpenStack Provider v1beta1 | | + | + | + | + | ✓ | ✓ | ✓ | ✓ | ★ |
Test status:
diff --git a/api/v1alpha5/conversion.go b/api/v1alpha5/conversion.go
index 5fefbc7136..49536451c3 100644
--- a/api/v1alpha5/conversion.go
+++ b/api/v1alpha5/conversion.go
@@ -24,7 +24,7 @@ import (
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/v1alpha8"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
)
var _ ctrlconversion.Convertible = &OpenStackCluster{}
@@ -34,7 +34,7 @@ const trueString = "true"
func (r *OpenStackCluster) ConvertTo(dstRaw ctrlconversion.Hub) error {
dst := dstRaw.(*infrav1.OpenStackCluster)
- if err := Convert_v1alpha5_OpenStackCluster_To_v1alpha8_OpenStackCluster(r, dst, nil); err != nil {
+ if err := Convert_v1alpha5_OpenStackCluster_To_v1beta1_OpenStackCluster(r, dst, nil); err != nil {
return err
}
@@ -50,7 +50,7 @@ func (r *OpenStackCluster) ConvertTo(dstRaw ctrlconversion.Hub) error {
func (r *OpenStackCluster) ConvertFrom(srcRaw ctrlconversion.Hub) error {
src := srcRaw.(*infrav1.OpenStackCluster)
- if err := Convert_v1alpha8_OpenStackCluster_To_v1alpha5_OpenStackCluster(src, r, nil); err != nil {
+ if err := Convert_v1beta1_OpenStackCluster_To_v1alpha5_OpenStackCluster(src, r, nil); err != nil {
return err
}
@@ -63,13 +63,13 @@ var _ ctrlconversion.Convertible = &OpenStackClusterList{}
func (r *OpenStackClusterList) ConvertTo(dstRaw ctrlconversion.Hub) error {
dst := dstRaw.(*infrav1.OpenStackClusterList)
- return Convert_v1alpha5_OpenStackClusterList_To_v1alpha8_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_v1alpha8_OpenStackClusterList_To_v1alpha5_OpenStackClusterList(src, r, nil)
+ return Convert_v1beta1_OpenStackClusterList_To_v1alpha5_OpenStackClusterList(src, r, nil)
}
var _ ctrlconversion.Convertible = &OpenStackClusterTemplate{}
@@ -77,7 +77,7 @@ var _ ctrlconversion.Convertible = &OpenStackClusterTemplate{}
func (r *OpenStackClusterTemplate) ConvertTo(dstRaw ctrlconversion.Hub) error {
dst := dstRaw.(*infrav1.OpenStackClusterTemplate)
- if err := Convert_v1alpha5_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate(r, dst, nil); err != nil {
+ if err := Convert_v1alpha5_OpenStackClusterTemplate_To_v1beta1_OpenStackClusterTemplate(r, dst, nil); err != nil {
return err
}
@@ -93,7 +93,7 @@ func (r *OpenStackClusterTemplate) ConvertTo(dstRaw ctrlconversion.Hub) error {
func (r *OpenStackClusterTemplate) ConvertFrom(srcRaw ctrlconversion.Hub) error {
src := srcRaw.(*infrav1.OpenStackClusterTemplate)
- if err := Convert_v1alpha8_OpenStackClusterTemplate_To_v1alpha5_OpenStackClusterTemplate(src, r, nil); err != nil {
+ if err := Convert_v1beta1_OpenStackClusterTemplate_To_v1alpha5_OpenStackClusterTemplate(src, r, nil); err != nil {
return err
}
@@ -106,7 +106,7 @@ var _ ctrlconversion.Convertible = &OpenStackMachine{}
func (r *OpenStackMachine) ConvertTo(dstRaw ctrlconversion.Hub) error {
dst := dstRaw.(*infrav1.OpenStackMachine)
- if err := Convert_v1alpha5_OpenStackMachine_To_v1alpha8_OpenStackMachine(r, dst, nil); err != nil {
+ if err := Convert_v1alpha5_OpenStackMachine_To_v1beta1_OpenStackMachine(r, dst, nil); err != nil {
return err
}
@@ -122,7 +122,7 @@ func (r *OpenStackMachine) ConvertTo(dstRaw ctrlconversion.Hub) error {
func (r *OpenStackMachine) ConvertFrom(srcRaw ctrlconversion.Hub) error {
src := srcRaw.(*infrav1.OpenStackMachine)
- if err := Convert_v1alpha8_OpenStackMachine_To_v1alpha5_OpenStackMachine(src, r, nil); err != nil {
+ if err := Convert_v1beta1_OpenStackMachine_To_v1alpha5_OpenStackMachine(src, r, nil); err != nil {
return err
}
@@ -135,13 +135,13 @@ var _ ctrlconversion.Convertible = &OpenStackMachineList{}
func (r *OpenStackMachineList) ConvertTo(dstRaw ctrlconversion.Hub) error {
dst := dstRaw.(*infrav1.OpenStackMachineList)
- return Convert_v1alpha5_OpenStackMachineList_To_v1alpha8_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_v1alpha8_OpenStackMachineList_To_v1alpha5_OpenStackMachineList(src, r, nil)
+ return Convert_v1beta1_OpenStackMachineList_To_v1alpha5_OpenStackMachineList(src, r, nil)
}
var _ ctrlconversion.Convertible = &OpenStackMachineTemplate{}
@@ -149,7 +149,7 @@ var _ ctrlconversion.Convertible = &OpenStackMachineTemplate{}
func (r *OpenStackMachineTemplate) ConvertTo(dstRaw ctrlconversion.Hub) error {
dst := dstRaw.(*infrav1.OpenStackMachineTemplate)
- if err := Convert_v1alpha5_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate(r, dst, nil); err != nil {
+ if err := Convert_v1alpha5_OpenStackMachineTemplate_To_v1beta1_OpenStackMachineTemplate(r, dst, nil); err != nil {
return err
}
@@ -165,7 +165,7 @@ func (r *OpenStackMachineTemplate) ConvertTo(dstRaw ctrlconversion.Hub) error {
func (r *OpenStackMachineTemplate) ConvertFrom(srcRaw ctrlconversion.Hub) error {
src := srcRaw.(*infrav1.OpenStackMachineTemplate)
- if err := Convert_v1alpha8_OpenStackMachineTemplate_To_v1alpha5_OpenStackMachineTemplate(src, r, nil); err != nil {
+ if err := Convert_v1beta1_OpenStackMachineTemplate_To_v1alpha5_OpenStackMachineTemplate(src, r, nil); err != nil {
return err
}
@@ -178,17 +178,17 @@ var _ ctrlconversion.Convertible = &OpenStackMachineTemplateList{}
func (r *OpenStackMachineTemplateList) ConvertTo(dstRaw ctrlconversion.Hub) error {
dst := dstRaw.(*infrav1.OpenStackMachineTemplateList)
- return Convert_v1alpha5_OpenStackMachineTemplateList_To_v1alpha8_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_v1alpha8_OpenStackMachineTemplateList_To_v1alpha5_OpenStackMachineTemplateList(src, r, nil)
+ return Convert_v1beta1_OpenStackMachineTemplateList_To_v1alpha5_OpenStackMachineTemplateList(src, r, nil)
}
-func Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(in *infrav1.OpenStackClusterSpec, out *OpenStackClusterSpec, s conversion.Scope) error {
- err := autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(in, out, s)
+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
}
@@ -204,7 +204,7 @@ func Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(in *
if in.Subnets != nil {
if len(in.Subnets) >= 1 {
- if err := Convert_v1alpha8_SubnetFilter_To_v1alpha5_SubnetFilter(&in.Subnets[0], &out.Subnet, s); err != nil {
+ if err := Convert_v1beta1_SubnetFilter_To_v1alpha5_SubnetFilter(&in.Subnets[0], &out.Subnet, s); err != nil {
return err
}
}
@@ -218,8 +218,8 @@ func Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(in *
return nil
}
-func Convert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *OpenStackClusterSpec, out *infrav1.OpenStackClusterSpec, s conversion.Scope) error {
- err := autoConvert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_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
}
@@ -233,7 +233,7 @@ func Convert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *
emptySubnet := SubnetFilter{}
if in.Subnet != emptySubnet {
subnet := infrav1.SubnetFilter{}
- if err := Convert_v1alpha5_SubnetFilter_To_v1alpha8_SubnetFilter(&in.Subnet, &subnet, s); err != nil {
+ if err := Convert_v1alpha5_SubnetFilter_To_v1beta1_SubnetFilter(&in.Subnet, &subnet, s); err != nil {
return err
}
out.Subnets = []infrav1.SubnetFilter{subnet}
@@ -261,13 +261,13 @@ func Convert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *
return nil
}
-func Convert_v1alpha8_LoadBalancer_To_v1alpha5_LoadBalancer(in *infrav1.LoadBalancer, out *LoadBalancer, s conversion.Scope) error {
- return autoConvert_v1alpha8_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_v1alpha8_PortOpts_To_v1alpha5_PortOpts(in *infrav1.PortOpts, out *PortOpts, s conversion.Scope) error {
- // value specs and propagate uplink status have been added in v1alpha8 but have no equivalent in v1alpha5
- err := autoConvert_v1alpha8_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
}
@@ -282,8 +282,8 @@ func Convert_v1alpha8_PortOpts_To_v1alpha5_PortOpts(in *infrav1.PortOpts, out *P
return nil
}
-func Convert_v1alpha5_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(in *OpenStackMachineSpec, out *infrav1.OpenStackMachineSpec, s conversion.Scope) error {
- err := autoConvert_v1alpha5_OpenStackMachineSpec_To_v1alpha8_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
}
@@ -306,19 +306,19 @@ func Convert_v1alpha5_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(in *
return nil
}
-func Convert_v1alpha8_APIServerLoadBalancer_To_v1alpha5_APIServerLoadBalancer(in *infrav1.APIServerLoadBalancer, out *APIServerLoadBalancer, s conversion.Scope) error {
- // Provider was originally added in v1alpha8, but was backported to v1alpha6, but has no equivalent in v1alpha5
- return autoConvert_v1alpha8_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_v1alpha8_PortOpts(in *PortOpts, out *infrav1.PortOpts, s conversion.Scope) error {
- // SecurityGroups have been removed in v1alpha8.
- err := autoConvert_v1alpha5_PortOpts_To_v1alpha8_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 v1alpha8.
+ // Profile is now a struct in v1beta1.
if strings.Contains(in.Profile["capabilities"], "switchdev") {
out.Profile.OVSHWOffload = true
}
@@ -328,7 +328,7 @@ func Convert_v1alpha5_PortOpts_To_v1alpha8_PortOpts(in *PortOpts, out *infrav1.P
return nil
}
-func Convert_v1alpha5_Instance_To_v1alpha8_BastionStatus(in *Instance, out *infrav1.BastionStatus, _ conversion.Scope) error {
+func Convert_v1alpha5_Instance_To_v1beta1_BastionStatus(in *Instance, out *infrav1.BastionStatus, _ conversion.Scope) error {
// BastionStatus is the same as Instance with unused fields removed
out.ID = in.ID
out.Name = in.Name
@@ -340,7 +340,7 @@ func Convert_v1alpha5_Instance_To_v1alpha8_BastionStatus(in *Instance, out *infr
return nil
}
-func Convert_v1alpha8_BastionStatus_To_v1alpha5_Instance(in *infrav1.BastionStatus, out *Instance, _ conversion.Scope) error {
+func Convert_v1beta1_BastionStatus_To_v1alpha5_Instance(in *infrav1.BastionStatus, out *Instance, _ conversion.Scope) error {
// BastionStatus is the same as Instance with unused fields removed
out.ID = in.ID
out.Name = in.Name
@@ -352,9 +352,9 @@ func Convert_v1alpha8_BastionStatus_To_v1alpha5_Instance(in *infrav1.BastionStat
return nil
}
-func Convert_v1alpha5_Network_To_v1alpha8_NetworkStatusWithSubnets(in *Network, out *infrav1.NetworkStatusWithSubnets, s conversion.Scope) error {
- // PortOpts has been removed in v1alpha8
- err := Convert_v1alpha5_Network_To_v1alpha8_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
}
@@ -365,9 +365,9 @@ func Convert_v1alpha5_Network_To_v1alpha8_NetworkStatusWithSubnets(in *Network,
return nil
}
-func Convert_v1alpha8_NetworkStatusWithSubnets_To_v1alpha5_Network(in *infrav1.NetworkStatusWithSubnets, out *Network, s conversion.Scope) error {
- // PortOpts has been removed in v1alpha8
- err := Convert_v1alpha8_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
}
@@ -379,7 +379,7 @@ func Convert_v1alpha8_NetworkStatusWithSubnets_To_v1alpha5_Network(in *infrav1.N
return nil
}
-func Convert_v1alpha5_Network_To_v1alpha8_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
@@ -387,7 +387,7 @@ func Convert_v1alpha5_Network_To_v1alpha8_NetworkStatus(in *Network, out *infrav
return nil
}
-func Convert_v1alpha8_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
@@ -395,13 +395,13 @@ func Convert_v1alpha8_NetworkStatus_To_v1alpha5_Network(in *infrav1.NetworkStatu
return nil
}
-func Convert_v1alpha5_SecurityGroupFilter_To_v1alpha8_SecurityGroupFilter(in *SecurityGroupFilter, out *infrav1.SecurityGroupFilter, s conversion.Scope) error {
- err := autoConvert_v1alpha5_SecurityGroupFilter_To_v1alpha8_SecurityGroupFilter(in, out, s)
+func Convert_v1alpha5_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in *SecurityGroupFilter, out *infrav1.SecurityGroupFilter, s conversion.Scope) error {
+ err := autoConvert_v1alpha5_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in, out, s)
if err != nil {
return err
}
- // TenantID has been removed in v1alpha8. Write it to ProjectID if ProjectID is not already set.
+ // TenantID has been removed in v1beta1. Write it to ProjectID if ProjectID is not already set.
if out.ProjectID == "" {
out.ProjectID = in.TenantID
}
@@ -409,9 +409,9 @@ func Convert_v1alpha5_SecurityGroupFilter_To_v1alpha8_SecurityGroupFilter(in *Se
return nil
}
-func Convert_v1alpha5_SecurityGroupParam_To_v1alpha8_SecurityGroupFilter(in *SecurityGroupParam, out *infrav1.SecurityGroupFilter, s conversion.Scope) error {
- // SecurityGroupParam is replaced by its contained SecurityGroupFilter in v1alpha8
- err := Convert_v1alpha5_SecurityGroupFilter_To_v1alpha8_SecurityGroupFilter(&in.Filter, out, s)
+func Convert_v1alpha5_SecurityGroupParam_To_v1beta1_SecurityGroupFilter(in *SecurityGroupParam, out *infrav1.SecurityGroupFilter, s conversion.Scope) error {
+ // SecurityGroupParam is replaced by its contained SecurityGroupFilter in v1beta1
+ err := Convert_v1alpha5_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(&in.Filter, out, s)
if err != nil {
return err
}
@@ -425,9 +425,9 @@ func Convert_v1alpha5_SecurityGroupParam_To_v1alpha8_SecurityGroupFilter(in *Sec
return nil
}
-func Convert_v1alpha8_SecurityGroupFilter_To_v1alpha5_SecurityGroupParam(in *infrav1.SecurityGroupFilter, out *SecurityGroupParam, s conversion.Scope) error {
- // SecurityGroupParam is replaced by its contained SecurityGroupFilter in v1alpha8
- err := Convert_v1alpha8_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(in, &out.Filter, s)
+func Convert_v1beta1_SecurityGroupFilter_To_v1alpha5_SecurityGroupParam(in *infrav1.SecurityGroupFilter, out *SecurityGroupParam, s conversion.Scope) error {
+ // SecurityGroupParam is replaced by its contained SecurityGroupFilter in v1beta1
+ err := Convert_v1beta1_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(in, &out.Filter, s)
if err != nil {
return err
}
@@ -441,7 +441,7 @@ func Convert_v1alpha8_SecurityGroupFilter_To_v1alpha5_SecurityGroupParam(in *inf
return nil
}
-func Convert_v1alpha5_SubnetParam_To_v1alpha8_SubnetFilter(in *SubnetParam, out *infrav1.SubnetFilter, _ conversion.Scope) error {
+func Convert_v1alpha5_SubnetParam_To_v1beta1_SubnetFilter(in *SubnetParam, out *infrav1.SubnetFilter, _ conversion.Scope) error {
*out = infrav1.SubnetFilter(in.Filter)
if in.UUID != "" {
out.ID = in.UUID
@@ -449,14 +449,14 @@ func Convert_v1alpha5_SubnetParam_To_v1alpha8_SubnetFilter(in *SubnetParam, out
return nil
}
-func Convert_v1alpha8_SubnetFilter_To_v1alpha5_SubnetParam(in *infrav1.SubnetFilter, out *SubnetParam, _ conversion.Scope) error {
+func Convert_v1beta1_SubnetFilter_To_v1alpha5_SubnetParam(in *infrav1.SubnetFilter, out *SubnetParam, _ conversion.Scope) error {
out.Filter = SubnetFilter(*in)
out.UUID = in.ID
return nil
}
-func Convert_Map_string_To_Interface_To_v1alpha8_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") {
@@ -470,7 +470,7 @@ func Convert_Map_string_To_Interface_To_v1alpha8_BindingProfile(in map[string]st
return nil
}
-func Convert_v1alpha8_BindingProfile_To_Map_string_To_Interface(in *infrav1.BindingProfile, out map[string]string, _ conversion.Scope) error {
+func Convert_v1beta1_BindingProfile_To_Map_string_To_Interface(in *infrav1.BindingProfile, out map[string]string, _ conversion.Scope) error {
if in.OVSHWOffload {
(out)["capabilities"] = "[\"switchdev\"]"
}
@@ -480,13 +480,13 @@ func Convert_v1alpha8_BindingProfile_To_Map_string_To_Interface(in *infrav1.Bind
return nil
}
-func Convert_v1alpha8_OpenStackClusterStatus_To_v1alpha5_OpenStackClusterStatus(in *infrav1.OpenStackClusterStatus, out *OpenStackClusterStatus, s conversion.Scope) error {
- err := autoConvert_v1alpha8_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 v1alpha8
+ // 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{}
@@ -495,7 +495,7 @@ func Convert_v1alpha8_OpenStackClusterStatus_To_v1alpha5_OpenStackClusterStatus(
out.Network.Router = (*Router)(in.Router)
if in.APIServerLoadBalancer != nil {
out.Network.APIServerLoadBalancer = &LoadBalancer{}
- err = Convert_v1alpha8_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
}
@@ -505,18 +505,18 @@ func Convert_v1alpha8_OpenStackClusterStatus_To_v1alpha5_OpenStackClusterStatus(
return nil
}
-func Convert_v1alpha5_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterStatus(in *OpenStackClusterStatus, out *infrav1.OpenStackClusterStatus, s conversion.Scope) error {
- err := autoConvert_v1alpha5_OpenStackClusterStatus_To_v1alpha8_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 v1alpha8
+ // 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_v1alpha8_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
}
@@ -526,8 +526,8 @@ func Convert_v1alpha5_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterStatus(
return nil
}
-func Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(in *infrav1.OpenStackMachineSpec, out *OpenStackMachineSpec, s conversion.Scope) error {
- err := autoConvert_v1alpha8_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
}
@@ -547,13 +547,13 @@ func Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(in *
return nil
}
-func Convert_v1alpha8_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineStatus(in *infrav1.OpenStackMachineStatus, out *OpenStackMachineStatus, s conversion.Scope) error {
+func Convert_v1beta1_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineStatus(in *infrav1.OpenStackMachineStatus, out *OpenStackMachineStatus, s conversion.Scope) error {
// ReferencedResources have no equivalent in v1alpha5
- return autoConvert_v1alpha8_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineStatus(in, out, s)
+ return autoConvert_v1beta1_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineStatus(in, out, s)
}
-func Convert_v1alpha8_Bastion_To_v1alpha5_Bastion(in *infrav1.Bastion, out *Bastion, s conversion.Scope) error {
- err := autoConvert_v1alpha8_Bastion_To_v1alpha5_Bastion(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
}
@@ -561,8 +561,8 @@ func Convert_v1alpha8_Bastion_To_v1alpha5_Bastion(in *infrav1.Bastion, out *Bast
return nil
}
-func Convert_v1alpha5_Bastion_To_v1alpha8_Bastion(in *Bastion, out *infrav1.Bastion, s conversion.Scope) error {
- err := autoConvert_v1alpha5_Bastion_To_v1alpha8_Bastion(in, out, s)
+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
}
@@ -570,7 +570,7 @@ func Convert_v1alpha5_Bastion_To_v1alpha8_Bastion(in *Bastion, out *infrav1.Bast
return nil
}
-func Convert_v1alpha8_SecurityGroupStatus_To_v1alpha5_SecurityGroup(in *infrav1.SecurityGroupStatus, out *SecurityGroup, s conversion.Scope) error { //nolint:revive
+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
out.Rules = make([]SecurityGroupRule, len(in.Rules))
@@ -604,7 +604,7 @@ func Convert_v1alpha8_SecurityGroupStatus_To_v1alpha5_SecurityGroup(in *infrav1.
return nil
}
-func Convert_v1alpha5_SecurityGroup_To_v1alpha8_SecurityGroupStatus(in *SecurityGroup, out *infrav1.SecurityGroupStatus, s conversion.Scope) error { //nolint:revive
+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
out.Rules = make([]infrav1.SecurityGroupRuleStatus, len(in.Rules))
@@ -625,6 +625,6 @@ func Convert_v1alpha5_SecurityGroup_To_v1alpha8_SecurityGroupStatus(in *Security
return nil
}
-func Convert_v1alpha5_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(in *OpenStackIdentityReference, out *infrav1.OpenStackIdentityReference, s conversion.Scope) error {
- return autoConvert_v1alpha5_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(in, out, s)
+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)
}
diff --git a/api/v1alpha5/conversion_test.go b/api/v1alpha5/conversion_test.go
index 8848d47379..6e0ab71e74 100644
--- a/api/v1alpha5/conversion_test.go
+++ b/api/v1alpha5/conversion_test.go
@@ -24,7 +24,7 @@ import (
runtime "k8s.io/apimachinery/pkg/runtime"
ctrlconversion "sigs.k8s.io/controller-runtime/pkg/conversion"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
)
func TestConvertFrom(t *testing.T) {
@@ -110,7 +110,7 @@ func TestConvertFrom(t *testing.T) {
}
}
-func TestConvert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(t *testing.T) {
+func TestConvert_v1alpha5_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(t *testing.T) {
tests := []struct {
name string
in *OpenStackClusterSpec
@@ -151,7 +151,7 @@ func TestConvert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(
t.Run(tt.name, func(t *testing.T) {
g := gomega.NewWithT(t)
out := &infrav1.OpenStackClusterSpec{}
- err := Convert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(tt.in, out, nil)
+ 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))
})
diff --git a/api/v1alpha5/doc.go b/api/v1alpha5/doc.go
index ad0e9949b2..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/v1alpha8
+// +k8s:conversion-gen=sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1
package v1alpha5
diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go
index 0e9c9315b8..95c46f3eb3 100644
--- a/api/v1alpha5/zz_generated.conversion.go
+++ b/api/v1alpha5/zz_generated.conversion.go
@@ -27,8 +27,8 @@ import (
v1 "k8s.io/api/core/v1"
conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime"
- v1alpha8 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
- v1beta1 "sigs.k8s.io/cluster-api/api/v1beta1"
+ v1beta1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
+ apiv1beta1 "sigs.k8s.io/cluster-api/api/v1beta1"
errors "sigs.k8s.io/cluster-api/errors"
)
@@ -39,382 +39,382 @@ 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), (*v1alpha8.APIServerLoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalancer(a.(*APIServerLoadBalancer), b.(*v1alpha8.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), (*v1alpha8.AddressPair)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_AddressPair_To_v1alpha8_AddressPair(a.(*AddressPair), b.(*v1alpha8.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((*v1alpha8.AddressPair)(nil), (*AddressPair)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_AddressPair_To_v1alpha5_AddressPair(a.(*v1alpha8.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((*ExternalRouterIPParam)(nil), (*v1alpha8.ExternalRouterIPParam)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_ExternalRouterIPParam_To_v1alpha8_ExternalRouterIPParam(a.(*ExternalRouterIPParam), b.(*v1alpha8.ExternalRouterIPParam), 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((*v1alpha8.ExternalRouterIPParam)(nil), (*ExternalRouterIPParam)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_ExternalRouterIPParam_To_v1alpha5_ExternalRouterIPParam(a.(*v1alpha8.ExternalRouterIPParam), b.(*ExternalRouterIPParam), 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((*FixedIP)(nil), (*v1alpha8.FixedIP)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_FixedIP_To_v1alpha8_FixedIP(a.(*FixedIP), b.(*v1alpha8.FixedIP), 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((*v1alpha8.FixedIP)(nil), (*FixedIP)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_FixedIP_To_v1alpha5_FixedIP(a.(*v1alpha8.FixedIP), b.(*FixedIP), 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((*LoadBalancer)(nil), (*v1alpha8.LoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_LoadBalancer_To_v1alpha8_LoadBalancer(a.(*LoadBalancer), b.(*v1alpha8.LoadBalancer), 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((*NetworkFilter)(nil), (*v1alpha8.NetworkFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_NetworkFilter_To_v1alpha8_NetworkFilter(a.(*NetworkFilter), b.(*v1alpha8.NetworkFilter), scope)
+ if err := s.AddGeneratedConversionFunc((*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((*v1alpha8.NetworkFilter)(nil), (*NetworkFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_NetworkFilter_To_v1alpha5_NetworkFilter(a.(*v1alpha8.NetworkFilter), b.(*NetworkFilter), scope)
+ if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*OpenStackCluster)(nil), (*v1alpha8.OpenStackCluster)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_OpenStackCluster_To_v1alpha8_OpenStackCluster(a.(*OpenStackCluster), b.(*v1alpha8.OpenStackCluster), 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((*v1alpha8.OpenStackCluster)(nil), (*OpenStackCluster)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackCluster_To_v1alpha5_OpenStackCluster(a.(*v1alpha8.OpenStackCluster), b.(*OpenStackCluster), 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((*OpenStackClusterList)(nil), (*v1alpha8.OpenStackClusterList)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_OpenStackClusterList_To_v1alpha8_OpenStackClusterList(a.(*OpenStackClusterList), b.(*v1alpha8.OpenStackClusterList), 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((*v1alpha8.OpenStackClusterList)(nil), (*OpenStackClusterList)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackClusterList_To_v1alpha5_OpenStackClusterList(a.(*v1alpha8.OpenStackClusterList), b.(*OpenStackClusterList), 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((*OpenStackClusterTemplate)(nil), (*v1alpha8.OpenStackClusterTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate(a.(*OpenStackClusterTemplate), b.(*v1alpha8.OpenStackClusterTemplate), 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((*v1alpha8.OpenStackClusterTemplate)(nil), (*OpenStackClusterTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackClusterTemplate_To_v1alpha5_OpenStackClusterTemplate(a.(*v1alpha8.OpenStackClusterTemplate), b.(*OpenStackClusterTemplate), 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((*OpenStackClusterTemplateList)(nil), (*v1alpha8.OpenStackClusterTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_OpenStackClusterTemplateList_To_v1alpha8_OpenStackClusterTemplateList(a.(*OpenStackClusterTemplateList), b.(*v1alpha8.OpenStackClusterTemplateList), 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((*v1alpha8.OpenStackClusterTemplateList)(nil), (*OpenStackClusterTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackClusterTemplateList_To_v1alpha5_OpenStackClusterTemplateList(a.(*v1alpha8.OpenStackClusterTemplateList), b.(*OpenStackClusterTemplateList), 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((*OpenStackClusterTemplateResource)(nil), (*v1alpha8.OpenStackClusterTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_OpenStackClusterTemplateResource_To_v1alpha8_OpenStackClusterTemplateResource(a.(*OpenStackClusterTemplateResource), b.(*v1alpha8.OpenStackClusterTemplateResource), 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((*v1alpha8.OpenStackClusterTemplateResource)(nil), (*OpenStackClusterTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackClusterTemplateResource_To_v1alpha5_OpenStackClusterTemplateResource(a.(*v1alpha8.OpenStackClusterTemplateResource), b.(*OpenStackClusterTemplateResource), 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((*OpenStackClusterTemplateSpec)(nil), (*v1alpha8.OpenStackClusterTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_OpenStackClusterTemplateSpec_To_v1alpha8_OpenStackClusterTemplateSpec(a.(*OpenStackClusterTemplateSpec), b.(*v1alpha8.OpenStackClusterTemplateSpec), 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((*v1alpha8.OpenStackClusterTemplateSpec)(nil), (*OpenStackClusterTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackClusterTemplateSpec_To_v1alpha5_OpenStackClusterTemplateSpec(a.(*v1alpha8.OpenStackClusterTemplateSpec), b.(*OpenStackClusterTemplateSpec), 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((*v1alpha8.OpenStackIdentityReference)(nil), (*OpenStackIdentityReference)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackIdentityReference_To_v1alpha5_OpenStackIdentityReference(a.(*v1alpha8.OpenStackIdentityReference), b.(*OpenStackIdentityReference), scope)
+ if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*OpenStackMachine)(nil), (*v1alpha8.OpenStackMachine)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_OpenStackMachine_To_v1alpha8_OpenStackMachine(a.(*OpenStackMachine), b.(*v1alpha8.OpenStackMachine), 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((*v1alpha8.OpenStackMachine)(nil), (*OpenStackMachine)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackMachine_To_v1alpha5_OpenStackMachine(a.(*v1alpha8.OpenStackMachine), b.(*OpenStackMachine), 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((*OpenStackMachineList)(nil), (*v1alpha8.OpenStackMachineList)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_OpenStackMachineList_To_v1alpha8_OpenStackMachineList(a.(*OpenStackMachineList), b.(*v1alpha8.OpenStackMachineList), 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((*v1alpha8.OpenStackMachineList)(nil), (*OpenStackMachineList)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackMachineList_To_v1alpha5_OpenStackMachineList(a.(*v1alpha8.OpenStackMachineList), b.(*OpenStackMachineList), 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((*OpenStackMachineStatus)(nil), (*v1alpha8.OpenStackMachineStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_OpenStackMachineStatus_To_v1alpha8_OpenStackMachineStatus(a.(*OpenStackMachineStatus), b.(*v1alpha8.OpenStackMachineStatus), 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((*OpenStackMachineTemplate)(nil), (*v1alpha8.OpenStackMachineTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate(a.(*OpenStackMachineTemplate), b.(*v1alpha8.OpenStackMachineTemplate), 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((*v1alpha8.OpenStackMachineTemplate)(nil), (*OpenStackMachineTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackMachineTemplate_To_v1alpha5_OpenStackMachineTemplate(a.(*v1alpha8.OpenStackMachineTemplate), b.(*OpenStackMachineTemplate), 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((*OpenStackMachineTemplateList)(nil), (*v1alpha8.OpenStackMachineTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_OpenStackMachineTemplateList_To_v1alpha8_OpenStackMachineTemplateList(a.(*OpenStackMachineTemplateList), b.(*v1alpha8.OpenStackMachineTemplateList), 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((*v1alpha8.OpenStackMachineTemplateList)(nil), (*OpenStackMachineTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackMachineTemplateList_To_v1alpha5_OpenStackMachineTemplateList(a.(*v1alpha8.OpenStackMachineTemplateList), b.(*OpenStackMachineTemplateList), 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((*OpenStackMachineTemplateResource)(nil), (*v1alpha8.OpenStackMachineTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_OpenStackMachineTemplateResource_To_v1alpha8_OpenStackMachineTemplateResource(a.(*OpenStackMachineTemplateResource), b.(*v1alpha8.OpenStackMachineTemplateResource), 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((*v1alpha8.OpenStackMachineTemplateResource)(nil), (*OpenStackMachineTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackMachineTemplateResource_To_v1alpha5_OpenStackMachineTemplateResource(a.(*v1alpha8.OpenStackMachineTemplateResource), b.(*OpenStackMachineTemplateResource), 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((*OpenStackMachineTemplateSpec)(nil), (*v1alpha8.OpenStackMachineTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_OpenStackMachineTemplateSpec_To_v1alpha8_OpenStackMachineTemplateSpec(a.(*OpenStackMachineTemplateSpec), b.(*v1alpha8.OpenStackMachineTemplateSpec), 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((*v1alpha8.OpenStackMachineTemplateSpec)(nil), (*OpenStackMachineTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackMachineTemplateSpec_To_v1alpha5_OpenStackMachineTemplateSpec(a.(*v1alpha8.OpenStackMachineTemplateSpec), b.(*OpenStackMachineTemplateSpec), 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((*RootVolume)(nil), (*v1alpha8.RootVolume)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_RootVolume_To_v1alpha8_RootVolume(a.(*RootVolume), b.(*v1alpha8.RootVolume), scope)
+ if err := s.AddGeneratedConversionFunc((*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((*v1alpha8.RootVolume)(nil), (*RootVolume)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_RootVolume_To_v1alpha5_RootVolume(a.(*v1alpha8.RootVolume), b.(*RootVolume), scope)
+ if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*Router)(nil), (*v1alpha8.Router)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_Router_To_v1alpha8_Router(a.(*Router), b.(*v1alpha8.Router), 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((*v1alpha8.Router)(nil), (*Router)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_Router_To_v1alpha5_Router(a.(*v1alpha8.Router), b.(*Router), 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((*v1alpha8.SecurityGroupFilter)(nil), (*SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(a.(*v1alpha8.SecurityGroupFilter), b.(*SecurityGroupFilter), scope)
+ if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*Subnet)(nil), (*v1alpha8.Subnet)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_Subnet_To_v1alpha8_Subnet(a.(*Subnet), b.(*v1alpha8.Subnet), 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((*v1alpha8.Subnet)(nil), (*Subnet)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_Subnet_To_v1alpha5_Subnet(a.(*v1alpha8.Subnet), b.(*Subnet), 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((*SubnetFilter)(nil), (*v1alpha8.SubnetFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_SubnetFilter_To_v1alpha8_SubnetFilter(a.(*SubnetFilter), b.(*v1alpha8.SubnetFilter), scope)
+ if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*v1alpha8.SubnetFilter)(nil), (*SubnetFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_SubnetFilter_To_v1alpha5_SubnetFilter(a.(*v1alpha8.SubnetFilter), b.(*SubnetFilter), scope)
+ if err := s.AddGeneratedConversionFunc((*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((*Bastion)(nil), (*v1alpha8.Bastion)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_Bastion_To_v1alpha8_Bastion(a.(*Bastion), b.(*v1alpha8.Bastion), 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.AddConversionFunc((*Instance)(nil), (*v1alpha8.BastionStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_Instance_To_v1alpha8_BastionStatus(a.(*Instance), b.(*v1alpha8.BastionStatus), 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.AddConversionFunc((*Network)(nil), (*v1alpha8.NetworkStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_Network_To_v1alpha8_NetworkStatus(a.(*Network), b.(*v1alpha8.NetworkStatus), 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.AddConversionFunc((*Network)(nil), (*v1alpha8.NetworkStatusWithSubnets)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_Network_To_v1alpha8_NetworkStatusWithSubnets(a.(*Network), b.(*v1alpha8.NetworkStatusWithSubnets), 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.AddConversionFunc((*OpenStackClusterSpec)(nil), (*v1alpha8.OpenStackClusterSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(a.(*OpenStackClusterSpec), b.(*v1alpha8.OpenStackClusterSpec), 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.AddConversionFunc((*OpenStackClusterStatus)(nil), (*v1alpha8.OpenStackClusterStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterStatus(a.(*OpenStackClusterStatus), b.(*v1alpha8.OpenStackClusterStatus), 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.AddConversionFunc((*OpenStackIdentityReference)(nil), (*v1alpha8.OpenStackIdentityReference)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(a.(*OpenStackIdentityReference), b.(*v1alpha8.OpenStackIdentityReference), 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.AddConversionFunc((*OpenStackMachineSpec)(nil), (*v1alpha8.OpenStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(a.(*OpenStackMachineSpec), b.(*v1alpha8.OpenStackMachineSpec), 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.AddConversionFunc((*PortOpts)(nil), (*v1alpha8.PortOpts)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_PortOpts_To_v1alpha8_PortOpts(a.(*PortOpts), b.(*v1alpha8.PortOpts), 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.AddConversionFunc((*SecurityGroupFilter)(nil), (*v1alpha8.SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_SecurityGroupFilter_To_v1alpha8_SecurityGroupFilter(a.(*SecurityGroupFilter), b.(*v1alpha8.SecurityGroupFilter), 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.AddConversionFunc((*SecurityGroupParam)(nil), (*v1alpha8.SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_SecurityGroupParam_To_v1alpha8_SecurityGroupFilter(a.(*SecurityGroupParam), b.(*v1alpha8.SecurityGroupFilter), scope)
+ if err := s.AddConversionFunc((*SecurityGroupParam)(nil), (*v1beta1.SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_SecurityGroupParam_To_v1beta1_SecurityGroupFilter(a.(*SecurityGroupParam), b.(*v1beta1.SecurityGroupFilter), scope)
}); err != nil {
return err
}
- if err := s.AddConversionFunc((*SecurityGroup)(nil), (*v1alpha8.SecurityGroupStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_SecurityGroup_To_v1alpha8_SecurityGroupStatus(a.(*SecurityGroup), b.(*v1alpha8.SecurityGroupStatus), 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.AddConversionFunc((*SubnetParam)(nil), (*v1alpha8.SubnetFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_SubnetParam_To_v1alpha8_SubnetFilter(a.(*SubnetParam), b.(*v1alpha8.SubnetFilter), scope)
+ if err := s.AddConversionFunc((*SubnetParam)(nil), (*v1beta1.SubnetFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha5_SubnetParam_To_v1beta1_SubnetFilter(a.(*SubnetParam), b.(*v1beta1.SubnetFilter), scope)
}); err != nil {
return err
}
- if err := s.AddConversionFunc((*v1alpha8.APIServerLoadBalancer)(nil), (*APIServerLoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_APIServerLoadBalancer_To_v1alpha5_APIServerLoadBalancer(a.(*v1alpha8.APIServerLoadBalancer), b.(*APIServerLoadBalancer), 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((*v1alpha8.BastionStatus)(nil), (*Instance)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_BastionStatus_To_v1alpha5_Instance(a.(*v1alpha8.BastionStatus), b.(*Instance), 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((*v1alpha8.Bastion)(nil), (*Bastion)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_Bastion_To_v1alpha5_Bastion(a.(*v1alpha8.Bastion), b.(*Bastion), 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((*v1alpha8.LoadBalancer)(nil), (*LoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_LoadBalancer_To_v1alpha5_LoadBalancer(a.(*v1alpha8.LoadBalancer), b.(*LoadBalancer), 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((*v1alpha8.NetworkStatusWithSubnets)(nil), (*Network)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_NetworkStatusWithSubnets_To_v1alpha5_Network(a.(*v1alpha8.NetworkStatusWithSubnets), b.(*Network), 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((*v1alpha8.NetworkStatus)(nil), (*Network)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_NetworkStatus_To_v1alpha5_Network(a.(*v1alpha8.NetworkStatus), b.(*Network), 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((*v1alpha8.OpenStackClusterSpec)(nil), (*OpenStackClusterSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(a.(*v1alpha8.OpenStackClusterSpec), b.(*OpenStackClusterSpec), 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((*v1alpha8.OpenStackClusterStatus)(nil), (*OpenStackClusterStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackClusterStatus_To_v1alpha5_OpenStackClusterStatus(a.(*v1alpha8.OpenStackClusterStatus), b.(*OpenStackClusterStatus), 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((*v1alpha8.OpenStackMachineSpec)(nil), (*OpenStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(a.(*v1alpha8.OpenStackMachineSpec), b.(*OpenStackMachineSpec), 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((*v1alpha8.OpenStackMachineStatus)(nil), (*OpenStackMachineStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineStatus(a.(*v1alpha8.OpenStackMachineStatus), b.(*OpenStackMachineStatus), 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((*v1alpha8.PortOpts)(nil), (*PortOpts)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_PortOpts_To_v1alpha5_PortOpts(a.(*v1alpha8.PortOpts), b.(*PortOpts), 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((*v1alpha8.SecurityGroupFilter)(nil), (*SecurityGroupParam)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_SecurityGroupFilter_To_v1alpha5_SecurityGroupParam(a.(*v1alpha8.SecurityGroupFilter), b.(*SecurityGroupParam), scope)
+ if err := s.AddConversionFunc((*v1beta1.SecurityGroupFilter)(nil), (*SecurityGroupParam)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1beta1_SecurityGroupFilter_To_v1alpha5_SecurityGroupParam(a.(*v1beta1.SecurityGroupFilter), b.(*SecurityGroupParam), scope)
}); err != nil {
return err
}
- if err := s.AddConversionFunc((*v1alpha8.SecurityGroupStatus)(nil), (*SecurityGroup)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_SecurityGroupStatus_To_v1alpha5_SecurityGroup(a.(*v1alpha8.SecurityGroupStatus), b.(*SecurityGroup), scope)
+ 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((*v1alpha8.SubnetFilter)(nil), (*SubnetParam)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_SubnetFilter_To_v1alpha5_SubnetParam(a.(*v1alpha8.SubnetFilter), b.(*SubnetParam), scope)
+ if err := s.AddConversionFunc((*v1beta1.SubnetFilter)(nil), (*SubnetParam)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1beta1_SubnetFilter_To_v1alpha5_SubnetParam(a.(*v1beta1.SubnetFilter), b.(*SubnetParam), scope)
}); err != nil {
return err
}
return nil
}
-func autoConvert_v1alpha5_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalancer(in *APIServerLoadBalancer, out *v1alpha8.APIServerLoadBalancer, s conversion.Scope) error {
+func autoConvert_v1alpha5_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer(in *APIServerLoadBalancer, out *v1beta1.APIServerLoadBalancer, s conversion.Scope) error {
out.Enabled = in.Enabled
out.AdditionalPorts = *(*[]int)(unsafe.Pointer(&in.AdditionalPorts))
out.AllowedCIDRs = *(*[]string)(unsafe.Pointer(&in.AllowedCIDRs))
return nil
}
-// Convert_v1alpha5_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalancer is an autogenerated conversion function.
-func Convert_v1alpha5_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalancer(in *APIServerLoadBalancer, out *v1alpha8.APIServerLoadBalancer, s conversion.Scope) error {
- return autoConvert_v1alpha5_APIServerLoadBalancer_To_v1alpha8_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_v1alpha8_APIServerLoadBalancer_To_v1alpha5_APIServerLoadBalancer(in *v1alpha8.APIServerLoadBalancer, out *APIServerLoadBalancer, s conversion.Scope) error {
+func autoConvert_v1beta1_APIServerLoadBalancer_To_v1alpha5_APIServerLoadBalancer(in *v1beta1.APIServerLoadBalancer, out *APIServerLoadBalancer, s conversion.Scope) error {
out.Enabled = in.Enabled
out.AdditionalPorts = *(*[]int)(unsafe.Pointer(&in.AdditionalPorts))
out.AllowedCIDRs = *(*[]string)(unsafe.Pointer(&in.AllowedCIDRs))
@@ -422,40 +422,40 @@ func autoConvert_v1alpha8_APIServerLoadBalancer_To_v1alpha5_APIServerLoadBalance
return nil
}
-func autoConvert_v1alpha5_AddressPair_To_v1alpha8_AddressPair(in *AddressPair, out *v1alpha8.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
return nil
}
-// Convert_v1alpha5_AddressPair_To_v1alpha8_AddressPair is an autogenerated conversion function.
-func Convert_v1alpha5_AddressPair_To_v1alpha8_AddressPair(in *AddressPair, out *v1alpha8.AddressPair, s conversion.Scope) error {
- return autoConvert_v1alpha5_AddressPair_To_v1alpha8_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_v1alpha8_AddressPair_To_v1alpha5_AddressPair(in *v1alpha8.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
return nil
}
-// Convert_v1alpha8_AddressPair_To_v1alpha5_AddressPair is an autogenerated conversion function.
-func Convert_v1alpha8_AddressPair_To_v1alpha5_AddressPair(in *v1alpha8.AddressPair, out *AddressPair, s conversion.Scope) error {
- return autoConvert_v1alpha8_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_v1alpha8_Bastion(in *Bastion, out *v1alpha8.Bastion, s conversion.Scope) error {
+func autoConvert_v1alpha5_Bastion_To_v1beta1_Bastion(in *Bastion, out *v1beta1.Bastion, s conversion.Scope) error {
out.Enabled = in.Enabled
- if err := Convert_v1alpha5_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(&in.Instance, &out.Instance, s); err != nil {
+ if err := Convert_v1alpha5_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(&in.Instance, &out.Instance, s); err != nil {
return err
}
out.AvailabilityZone = in.AvailabilityZone
return nil
}
-func autoConvert_v1alpha8_Bastion_To_v1alpha5_Bastion(in *v1alpha8.Bastion, out *Bastion, s conversion.Scope) error {
+func autoConvert_v1beta1_Bastion_To_v1alpha5_Bastion(in *v1beta1.Bastion, out *Bastion, s conversion.Scope) error {
out.Enabled = in.Enabled
- if err := Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(&in.Instance, &out.Instance, s); err != nil {
+ if err := Convert_v1beta1_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(&in.Instance, &out.Instance, s); err != nil {
return err
}
out.AvailabilityZone = in.AvailabilityZone
@@ -463,55 +463,55 @@ func autoConvert_v1alpha8_Bastion_To_v1alpha5_Bastion(in *v1alpha8.Bastion, out
return nil
}
-func autoConvert_v1alpha5_ExternalRouterIPParam_To_v1alpha8_ExternalRouterIPParam(in *ExternalRouterIPParam, out *v1alpha8.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_v1alpha8_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil {
+ if err := Convert_v1alpha5_SubnetParam_To_v1beta1_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil {
return err
}
return nil
}
-// Convert_v1alpha5_ExternalRouterIPParam_To_v1alpha8_ExternalRouterIPParam is an autogenerated conversion function.
-func Convert_v1alpha5_ExternalRouterIPParam_To_v1alpha8_ExternalRouterIPParam(in *ExternalRouterIPParam, out *v1alpha8.ExternalRouterIPParam, s conversion.Scope) error {
- return autoConvert_v1alpha5_ExternalRouterIPParam_To_v1alpha8_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_v1alpha8_ExternalRouterIPParam_To_v1alpha5_ExternalRouterIPParam(in *v1alpha8.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_v1alpha8_SubnetFilter_To_v1alpha5_SubnetParam(&in.Subnet, &out.Subnet, s); err != nil {
+ if err := Convert_v1beta1_SubnetFilter_To_v1alpha5_SubnetParam(&in.Subnet, &out.Subnet, s); err != nil {
return err
}
return nil
}
-// Convert_v1alpha8_ExternalRouterIPParam_To_v1alpha5_ExternalRouterIPParam is an autogenerated conversion function.
-func Convert_v1alpha8_ExternalRouterIPParam_To_v1alpha5_ExternalRouterIPParam(in *v1alpha8.ExternalRouterIPParam, out *ExternalRouterIPParam, s conversion.Scope) error {
- return autoConvert_v1alpha8_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_v1alpha8_FixedIP(in *FixedIP, out *v1alpha8.FixedIP, s conversion.Scope) error {
- out.Subnet = (*v1alpha8.SubnetFilter)(unsafe.Pointer(in.Subnet))
+func autoConvert_v1alpha5_FixedIP_To_v1beta1_FixedIP(in *FixedIP, out *v1beta1.FixedIP, s conversion.Scope) error {
+ out.Subnet = (*v1beta1.SubnetFilter)(unsafe.Pointer(in.Subnet))
out.IPAddress = in.IPAddress
return nil
}
-// Convert_v1alpha5_FixedIP_To_v1alpha8_FixedIP is an autogenerated conversion function.
-func Convert_v1alpha5_FixedIP_To_v1alpha8_FixedIP(in *FixedIP, out *v1alpha8.FixedIP, s conversion.Scope) error {
- return autoConvert_v1alpha5_FixedIP_To_v1alpha8_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_v1alpha8_FixedIP_To_v1alpha5_FixedIP(in *v1alpha8.FixedIP, out *FixedIP, s conversion.Scope) error {
+func autoConvert_v1beta1_FixedIP_To_v1alpha5_FixedIP(in *v1beta1.FixedIP, out *FixedIP, s conversion.Scope) error {
out.Subnet = (*SubnetFilter)(unsafe.Pointer(in.Subnet))
out.IPAddress = in.IPAddress
return nil
}
-// Convert_v1alpha8_FixedIP_To_v1alpha5_FixedIP is an autogenerated conversion function.
-func Convert_v1alpha8_FixedIP_To_v1alpha5_FixedIP(in *v1alpha8.FixedIP, out *FixedIP, s conversion.Scope) error {
- return autoConvert_v1alpha8_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_v1alpha8_LoadBalancer(in *LoadBalancer, out *v1alpha8.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
@@ -520,12 +520,12 @@ func autoConvert_v1alpha5_LoadBalancer_To_v1alpha8_LoadBalancer(in *LoadBalancer
return nil
}
-// Convert_v1alpha5_LoadBalancer_To_v1alpha8_LoadBalancer is an autogenerated conversion function.
-func Convert_v1alpha5_LoadBalancer_To_v1alpha8_LoadBalancer(in *LoadBalancer, out *v1alpha8.LoadBalancer, s conversion.Scope) error {
- return autoConvert_v1alpha5_LoadBalancer_To_v1alpha8_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_v1alpha8_LoadBalancer_To_v1alpha5_LoadBalancer(in *v1alpha8.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
@@ -535,7 +535,7 @@ func autoConvert_v1alpha8_LoadBalancer_To_v1alpha5_LoadBalancer(in *v1alpha8.Loa
return nil
}
-func autoConvert_v1alpha5_NetworkFilter_To_v1alpha8_NetworkFilter(in *NetworkFilter, out *v1alpha8.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
@@ -547,12 +547,12 @@ func autoConvert_v1alpha5_NetworkFilter_To_v1alpha8_NetworkFilter(in *NetworkFil
return nil
}
-// Convert_v1alpha5_NetworkFilter_To_v1alpha8_NetworkFilter is an autogenerated conversion function.
-func Convert_v1alpha5_NetworkFilter_To_v1alpha8_NetworkFilter(in *NetworkFilter, out *v1alpha8.NetworkFilter, s conversion.Scope) error {
- return autoConvert_v1alpha5_NetworkFilter_To_v1alpha8_NetworkFilter(in, out, s)
+// Convert_v1alpha5_NetworkFilter_To_v1beta1_NetworkFilter is an autogenerated conversion function.
+func Convert_v1alpha5_NetworkFilter_To_v1beta1_NetworkFilter(in *NetworkFilter, out *v1beta1.NetworkFilter, s conversion.Scope) error {
+ return autoConvert_v1alpha5_NetworkFilter_To_v1beta1_NetworkFilter(in, out, s)
}
-func autoConvert_v1alpha8_NetworkFilter_To_v1alpha5_NetworkFilter(in *v1alpha8.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
@@ -564,50 +564,50 @@ func autoConvert_v1alpha8_NetworkFilter_To_v1alpha5_NetworkFilter(in *v1alpha8.N
return nil
}
-// Convert_v1alpha8_NetworkFilter_To_v1alpha5_NetworkFilter is an autogenerated conversion function.
-func Convert_v1alpha8_NetworkFilter_To_v1alpha5_NetworkFilter(in *v1alpha8.NetworkFilter, out *NetworkFilter, s conversion.Scope) error {
- return autoConvert_v1alpha8_NetworkFilter_To_v1alpha5_NetworkFilter(in, out, s)
+// Convert_v1beta1_NetworkFilter_To_v1alpha5_NetworkFilter is an autogenerated conversion function.
+func Convert_v1beta1_NetworkFilter_To_v1alpha5_NetworkFilter(in *v1beta1.NetworkFilter, out *NetworkFilter, s conversion.Scope) error {
+ return autoConvert_v1beta1_NetworkFilter_To_v1alpha5_NetworkFilter(in, out, s)
}
-func autoConvert_v1alpha5_OpenStackCluster_To_v1alpha8_OpenStackCluster(in *OpenStackCluster, out *v1alpha8.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_v1alpha8_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_v1alpha8_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_v1alpha8_OpenStackCluster is an autogenerated conversion function.
-func Convert_v1alpha5_OpenStackCluster_To_v1alpha8_OpenStackCluster(in *OpenStackCluster, out *v1alpha8.OpenStackCluster, s conversion.Scope) error {
- return autoConvert_v1alpha5_OpenStackCluster_To_v1alpha8_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_v1alpha8_OpenStackCluster_To_v1alpha5_OpenStackCluster(in *v1alpha8.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_v1alpha8_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_v1alpha8_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_v1alpha8_OpenStackCluster_To_v1alpha5_OpenStackCluster is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackCluster_To_v1alpha5_OpenStackCluster(in *v1alpha8.OpenStackCluster, out *OpenStackCluster, s conversion.Scope) error {
- return autoConvert_v1alpha8_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_v1alpha8_OpenStackClusterList(in *OpenStackClusterList, out *v1alpha8.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([]v1alpha8.OpenStackCluster, len(*in))
+ *out = make([]v1beta1.OpenStackCluster, len(*in))
for i := range *in {
- if err := Convert_v1alpha5_OpenStackCluster_To_v1alpha8_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
}
}
@@ -617,18 +617,18 @@ func autoConvert_v1alpha5_OpenStackClusterList_To_v1alpha8_OpenStackClusterList(
return nil
}
-// Convert_v1alpha5_OpenStackClusterList_To_v1alpha8_OpenStackClusterList is an autogenerated conversion function.
-func Convert_v1alpha5_OpenStackClusterList_To_v1alpha8_OpenStackClusterList(in *OpenStackClusterList, out *v1alpha8.OpenStackClusterList, s conversion.Scope) error {
- return autoConvert_v1alpha5_OpenStackClusterList_To_v1alpha8_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_v1alpha8_OpenStackClusterList_To_v1alpha5_OpenStackClusterList(in *v1alpha8.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_v1alpha8_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
}
}
@@ -638,24 +638,24 @@ func autoConvert_v1alpha8_OpenStackClusterList_To_v1alpha5_OpenStackClusterList(
return nil
}
-// Convert_v1alpha8_OpenStackClusterList_To_v1alpha5_OpenStackClusterList is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackClusterList_To_v1alpha5_OpenStackClusterList(in *v1alpha8.OpenStackClusterList, out *OpenStackClusterList, s conversion.Scope) error {
- return autoConvert_v1alpha8_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_v1alpha8_OpenStackClusterSpec(in *OpenStackClusterSpec, out *v1alpha8.OpenStackClusterSpec, s conversion.Scope) error {
+func autoConvert_v1alpha5_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *OpenStackClusterSpec, out *v1beta1.OpenStackClusterSpec, s conversion.Scope) error {
out.CloudName = in.CloudName
// WARNING: in.NodeCIDR requires manual conversion: does not exist in peer-type
- if err := Convert_v1alpha5_NetworkFilter_To_v1alpha8_NetworkFilter(&in.Network, &out.Network, s); err != nil {
+ if err := Convert_v1alpha5_NetworkFilter_To_v1beta1_NetworkFilter(&in.Network, &out.Network, s); err != nil {
return err
}
// 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([]v1alpha8.ExternalRouterIPParam, len(*in))
+ *out = make([]v1beta1.ExternalRouterIPParam, len(*in))
for i := range *in {
- if err := Convert_v1alpha5_ExternalRouterIPParam_To_v1alpha8_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
}
}
@@ -663,14 +663,14 @@ func autoConvert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(
out.ExternalRouterIPs = nil
}
// WARNING: in.ExternalNetworkID requires manual conversion: does not exist in peer-type
- if err := Convert_v1alpha5_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil {
+ if err := Convert_v1alpha5_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil {
return err
}
out.DisableAPIServerFloatingIP = in.DisableAPIServerFloatingIP
out.APIServerFloatingIP = in.APIServerFloatingIP
out.APIServerFixedIP = in.APIServerFixedIP
out.APIServerPort = in.APIServerPort
- // WARNING: in.ManagedSecurityGroups requires manual conversion: inconvertible types (bool vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8.ManagedSecurityGroups)
+ // 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
out.DisablePortSecurity = in.DisablePortSecurity
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
@@ -678,8 +678,8 @@ func autoConvert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(
out.ControlPlaneAvailabilityZones = *(*[]string)(unsafe.Pointer(&in.ControlPlaneAvailabilityZones))
if in.Bastion != nil {
in, out := &in.Bastion, &out.Bastion
- *out = new(v1alpha8.Bastion)
- if err := Convert_v1alpha5_Bastion_To_v1alpha8_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 {
@@ -687,8 +687,8 @@ func autoConvert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(
}
if in.IdentityRef != nil {
in, out := &in.IdentityRef, &out.IdentityRef
- *out = new(v1alpha8.OpenStackIdentityReference)
- if err := Convert_v1alpha5_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(*in, *out, s); err != nil {
+ *out = new(v1beta1.OpenStackIdentityReference)
+ if err := Convert_v1alpha5_OpenStackIdentityReference_To_v1beta1_OpenStackIdentityReference(*in, *out, s); err != nil {
return err
}
} else {
@@ -697,11 +697,11 @@ func autoConvert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(
return nil
}
-func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(in *v1alpha8.OpenStackClusterSpec, out *OpenStackClusterSpec, s conversion.Scope) error {
+func autoConvert_v1beta1_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(in *v1beta1.OpenStackClusterSpec, out *OpenStackClusterSpec, s conversion.Scope) error {
out.CloudName = in.CloudName
// 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_v1alpha8_NetworkFilter_To_v1alpha5_NetworkFilter(&in.Network, &out.Network, s); err != nil {
+ if err := Convert_v1beta1_NetworkFilter_To_v1alpha5_NetworkFilter(&in.Network, &out.Network, s); err != nil {
return err
}
// WARNING: in.Subnets requires manual conversion: does not exist in peer-type
@@ -710,7 +710,7 @@ func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(
in, out := &in.ExternalRouterIPs, &out.ExternalRouterIPs
*out = make([]ExternalRouterIPParam, len(*in))
for i := range *in {
- if err := Convert_v1alpha8_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
}
}
@@ -719,14 +719,14 @@ func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(
}
// WARNING: in.ExternalNetwork requires manual conversion: does not exist in peer-type
// WARNING: in.DisableExternalNetwork requires manual conversion: does not exist in peer-type
- if err := Convert_v1alpha8_APIServerLoadBalancer_To_v1alpha5_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil {
+ if err := Convert_v1beta1_APIServerLoadBalancer_To_v1alpha5_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil {
return err
}
out.DisableAPIServerFloatingIP = in.DisableAPIServerFloatingIP
out.APIServerFloatingIP = in.APIServerFloatingIP
out.APIServerFixedIP = in.APIServerFixedIP
out.APIServerPort = in.APIServerPort
- // WARNING: in.ManagedSecurityGroups requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8.ManagedSecurityGroups vs bool)
+ // WARNING: in.ManagedSecurityGroups requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ManagedSecurityGroups vs bool)
out.DisablePortSecurity = in.DisablePortSecurity
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
out.ControlPlaneEndpoint = in.ControlPlaneEndpoint
@@ -735,7 +735,7 @@ func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(
if in.Bastion != nil {
in, out := &in.Bastion, &out.Bastion
*out = new(Bastion)
- if err := Convert_v1alpha8_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 {
@@ -744,7 +744,7 @@ func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(
if in.IdentityRef != nil {
in, out := &in.IdentityRef, &out.IdentityRef
*out = new(OpenStackIdentityReference)
- if err := Convert_v1alpha8_OpenStackIdentityReference_To_v1alpha5_OpenStackIdentityReference(*in, *out, s); err != nil {
+ if err := Convert_v1beta1_OpenStackIdentityReference_To_v1alpha5_OpenStackIdentityReference(*in, *out, s); err != nil {
return err
}
} else {
@@ -753,12 +753,12 @@ func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(
return nil
}
-func autoConvert_v1alpha5_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterStatus(in *OpenStackClusterStatus, out *v1alpha8.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(v1alpha8.NetworkStatusWithSubnets)
- if err := Convert_v1alpha5_Network_To_v1alpha8_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 {
@@ -766,18 +766,18 @@ func autoConvert_v1alpha5_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterSta
}
if in.ExternalNetwork != nil {
in, out := &in.ExternalNetwork, &out.ExternalNetwork
- *out = new(v1alpha8.NetworkStatus)
- if err := Convert_v1alpha5_Network_To_v1alpha8_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.FailureDomains = *(*apiv1beta1.FailureDomains)(unsafe.Pointer(&in.FailureDomains))
if in.ControlPlaneSecurityGroup != nil {
in, out := &in.ControlPlaneSecurityGroup, &out.ControlPlaneSecurityGroup
- *out = new(v1alpha8.SecurityGroupStatus)
- if err := Convert_v1alpha5_SecurityGroup_To_v1alpha8_SecurityGroupStatus(*in, *out, s); err != nil {
+ *out = new(v1beta1.SecurityGroupStatus)
+ if err := Convert_v1alpha5_SecurityGroup_To_v1beta1_SecurityGroupStatus(*in, *out, s); err != nil {
return err
}
} else {
@@ -785,8 +785,8 @@ func autoConvert_v1alpha5_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterSta
}
if in.WorkerSecurityGroup != nil {
in, out := &in.WorkerSecurityGroup, &out.WorkerSecurityGroup
- *out = new(v1alpha8.SecurityGroupStatus)
- if err := Convert_v1alpha5_SecurityGroup_To_v1alpha8_SecurityGroupStatus(*in, *out, s); err != nil {
+ *out = new(v1beta1.SecurityGroupStatus)
+ if err := Convert_v1alpha5_SecurityGroup_To_v1beta1_SecurityGroupStatus(*in, *out, s); err != nil {
return err
}
} else {
@@ -794,8 +794,8 @@ func autoConvert_v1alpha5_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterSta
}
if in.BastionSecurityGroup != nil {
in, out := &in.BastionSecurityGroup, &out.BastionSecurityGroup
- *out = new(v1alpha8.SecurityGroupStatus)
- if err := Convert_v1alpha5_SecurityGroup_To_v1alpha8_SecurityGroupStatus(*in, *out, s); err != nil {
+ *out = new(v1beta1.SecurityGroupStatus)
+ if err := Convert_v1alpha5_SecurityGroup_To_v1beta1_SecurityGroupStatus(*in, *out, s); err != nil {
return err
}
} else {
@@ -803,8 +803,8 @@ func autoConvert_v1alpha5_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterSta
}
if in.Bastion != nil {
in, out := &in.Bastion, &out.Bastion
- *out = new(v1alpha8.BastionStatus)
- if err := Convert_v1alpha5_Instance_To_v1alpha8_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 {
@@ -815,12 +815,12 @@ func autoConvert_v1alpha5_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterSta
return nil
}
-func autoConvert_v1alpha8_OpenStackClusterStatus_To_v1alpha5_OpenStackClusterStatus(in *v1alpha8.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_v1alpha8_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 {
@@ -829,7 +829,7 @@ func autoConvert_v1alpha8_OpenStackClusterStatus_To_v1alpha5_OpenStackClusterSta
if in.ExternalNetwork != nil {
in, out := &in.ExternalNetwork, &out.ExternalNetwork
*out = new(Network)
- if err := Convert_v1alpha8_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 {
@@ -837,11 +837,11 @@ func autoConvert_v1alpha8_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.FailureDomains = *(*apiv1beta1.FailureDomains)(unsafe.Pointer(&in.FailureDomains))
if in.ControlPlaneSecurityGroup != nil {
in, out := &in.ControlPlaneSecurityGroup, &out.ControlPlaneSecurityGroup
*out = new(SecurityGroup)
- if err := Convert_v1alpha8_SecurityGroupStatus_To_v1alpha5_SecurityGroup(*in, *out, s); err != nil {
+ if err := Convert_v1beta1_SecurityGroupStatus_To_v1alpha5_SecurityGroup(*in, *out, s); err != nil {
return err
}
} else {
@@ -850,7 +850,7 @@ func autoConvert_v1alpha8_OpenStackClusterStatus_To_v1alpha5_OpenStackClusterSta
if in.WorkerSecurityGroup != nil {
in, out := &in.WorkerSecurityGroup, &out.WorkerSecurityGroup
*out = new(SecurityGroup)
- if err := Convert_v1alpha8_SecurityGroupStatus_To_v1alpha5_SecurityGroup(*in, *out, s); err != nil {
+ if err := Convert_v1beta1_SecurityGroupStatus_To_v1alpha5_SecurityGroup(*in, *out, s); err != nil {
return err
}
} else {
@@ -859,7 +859,7 @@ func autoConvert_v1alpha8_OpenStackClusterStatus_To_v1alpha5_OpenStackClusterSta
if in.BastionSecurityGroup != nil {
in, out := &in.BastionSecurityGroup, &out.BastionSecurityGroup
*out = new(SecurityGroup)
- if err := Convert_v1alpha8_SecurityGroupStatus_To_v1alpha5_SecurityGroup(*in, *out, s); err != nil {
+ if err := Convert_v1beta1_SecurityGroupStatus_To_v1alpha5_SecurityGroup(*in, *out, s); err != nil {
return err
}
} else {
@@ -868,7 +868,7 @@ func autoConvert_v1alpha8_OpenStackClusterStatus_To_v1alpha5_OpenStackClusterSta
if in.Bastion != nil {
in, out := &in.Bastion, &out.Bastion
*out = new(Instance)
- if err := Convert_v1alpha8_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 {
@@ -879,39 +879,39 @@ func autoConvert_v1alpha8_OpenStackClusterStatus_To_v1alpha5_OpenStackClusterSta
return nil
}
-func autoConvert_v1alpha5_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate(in *OpenStackClusterTemplate, out *v1alpha8.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_v1alpha8_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_v1alpha8_OpenStackClusterTemplate is an autogenerated conversion function.
-func Convert_v1alpha5_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate(in *OpenStackClusterTemplate, out *v1alpha8.OpenStackClusterTemplate, s conversion.Scope) error {
- return autoConvert_v1alpha5_OpenStackClusterTemplate_To_v1alpha8_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_v1alpha8_OpenStackClusterTemplate_To_v1alpha5_OpenStackClusterTemplate(in *v1alpha8.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_v1alpha8_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_v1alpha8_OpenStackClusterTemplate_To_v1alpha5_OpenStackClusterTemplate is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackClusterTemplate_To_v1alpha5_OpenStackClusterTemplate(in *v1alpha8.OpenStackClusterTemplate, out *OpenStackClusterTemplate, s conversion.Scope) error {
- return autoConvert_v1alpha8_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_v1alpha8_OpenStackClusterTemplateList(in *OpenStackClusterTemplateList, out *v1alpha8.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([]v1alpha8.OpenStackClusterTemplate, len(*in))
+ *out = make([]v1beta1.OpenStackClusterTemplate, len(*in))
for i := range *in {
- if err := Convert_v1alpha5_OpenStackClusterTemplate_To_v1alpha8_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
}
}
@@ -921,18 +921,18 @@ func autoConvert_v1alpha5_OpenStackClusterTemplateList_To_v1alpha8_OpenStackClus
return nil
}
-// Convert_v1alpha5_OpenStackClusterTemplateList_To_v1alpha8_OpenStackClusterTemplateList is an autogenerated conversion function.
-func Convert_v1alpha5_OpenStackClusterTemplateList_To_v1alpha8_OpenStackClusterTemplateList(in *OpenStackClusterTemplateList, out *v1alpha8.OpenStackClusterTemplateList, s conversion.Scope) error {
- return autoConvert_v1alpha5_OpenStackClusterTemplateList_To_v1alpha8_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_v1alpha8_OpenStackClusterTemplateList_To_v1alpha5_OpenStackClusterTemplateList(in *v1alpha8.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_v1alpha8_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
}
}
@@ -942,114 +942,114 @@ func autoConvert_v1alpha8_OpenStackClusterTemplateList_To_v1alpha5_OpenStackClus
return nil
}
-// Convert_v1alpha8_OpenStackClusterTemplateList_To_v1alpha5_OpenStackClusterTemplateList is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackClusterTemplateList_To_v1alpha5_OpenStackClusterTemplateList(in *v1alpha8.OpenStackClusterTemplateList, out *OpenStackClusterTemplateList, s conversion.Scope) error {
- return autoConvert_v1alpha8_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_v1alpha8_OpenStackClusterTemplateResource(in *OpenStackClusterTemplateResource, out *v1alpha8.OpenStackClusterTemplateResource, s conversion.Scope) error {
- if err := Convert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_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_v1alpha8_OpenStackClusterTemplateResource is an autogenerated conversion function.
-func Convert_v1alpha5_OpenStackClusterTemplateResource_To_v1alpha8_OpenStackClusterTemplateResource(in *OpenStackClusterTemplateResource, out *v1alpha8.OpenStackClusterTemplateResource, s conversion.Scope) error {
- return autoConvert_v1alpha5_OpenStackClusterTemplateResource_To_v1alpha8_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_v1alpha8_OpenStackClusterTemplateResource_To_v1alpha5_OpenStackClusterTemplateResource(in *v1alpha8.OpenStackClusterTemplateResource, out *OpenStackClusterTemplateResource, s conversion.Scope) error {
- if err := Convert_v1alpha8_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_v1alpha8_OpenStackClusterTemplateResource_To_v1alpha5_OpenStackClusterTemplateResource is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackClusterTemplateResource_To_v1alpha5_OpenStackClusterTemplateResource(in *v1alpha8.OpenStackClusterTemplateResource, out *OpenStackClusterTemplateResource, s conversion.Scope) error {
- return autoConvert_v1alpha8_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_v1alpha8_OpenStackClusterTemplateSpec(in *OpenStackClusterTemplateSpec, out *v1alpha8.OpenStackClusterTemplateSpec, s conversion.Scope) error {
- if err := Convert_v1alpha5_OpenStackClusterTemplateResource_To_v1alpha8_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_v1alpha8_OpenStackClusterTemplateSpec is an autogenerated conversion function.
-func Convert_v1alpha5_OpenStackClusterTemplateSpec_To_v1alpha8_OpenStackClusterTemplateSpec(in *OpenStackClusterTemplateSpec, out *v1alpha8.OpenStackClusterTemplateSpec, s conversion.Scope) error {
- return autoConvert_v1alpha5_OpenStackClusterTemplateSpec_To_v1alpha8_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_v1alpha8_OpenStackClusterTemplateSpec_To_v1alpha5_OpenStackClusterTemplateSpec(in *v1alpha8.OpenStackClusterTemplateSpec, out *OpenStackClusterTemplateSpec, s conversion.Scope) error {
- if err := Convert_v1alpha8_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_v1alpha8_OpenStackClusterTemplateSpec_To_v1alpha5_OpenStackClusterTemplateSpec is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackClusterTemplateSpec_To_v1alpha5_OpenStackClusterTemplateSpec(in *v1alpha8.OpenStackClusterTemplateSpec, out *OpenStackClusterTemplateSpec, s conversion.Scope) error {
- return autoConvert_v1alpha8_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_v1alpha8_OpenStackIdentityReference(in *OpenStackIdentityReference, out *v1alpha8.OpenStackIdentityReference, s conversion.Scope) error {
+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
}
-func autoConvert_v1alpha8_OpenStackIdentityReference_To_v1alpha5_OpenStackIdentityReference(in *v1alpha8.OpenStackIdentityReference, out *OpenStackIdentityReference, s conversion.Scope) error {
+func autoConvert_v1beta1_OpenStackIdentityReference_To_v1alpha5_OpenStackIdentityReference(in *v1beta1.OpenStackIdentityReference, out *OpenStackIdentityReference, s conversion.Scope) error {
out.Name = in.Name
return nil
}
-// Convert_v1alpha8_OpenStackIdentityReference_To_v1alpha5_OpenStackIdentityReference is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackIdentityReference_To_v1alpha5_OpenStackIdentityReference(in *v1alpha8.OpenStackIdentityReference, out *OpenStackIdentityReference, s conversion.Scope) error {
- return autoConvert_v1alpha8_OpenStackIdentityReference_To_v1alpha5_OpenStackIdentityReference(in, out, s)
+// Convert_v1beta1_OpenStackIdentityReference_To_v1alpha5_OpenStackIdentityReference is an autogenerated conversion function.
+func Convert_v1beta1_OpenStackIdentityReference_To_v1alpha5_OpenStackIdentityReference(in *v1beta1.OpenStackIdentityReference, out *OpenStackIdentityReference, s conversion.Scope) error {
+ return autoConvert_v1beta1_OpenStackIdentityReference_To_v1alpha5_OpenStackIdentityReference(in, out, s)
}
-func autoConvert_v1alpha5_OpenStackMachine_To_v1alpha8_OpenStackMachine(in *OpenStackMachine, out *v1alpha8.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_v1alpha8_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_v1alpha8_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_v1alpha8_OpenStackMachine is an autogenerated conversion function.
-func Convert_v1alpha5_OpenStackMachine_To_v1alpha8_OpenStackMachine(in *OpenStackMachine, out *v1alpha8.OpenStackMachine, s conversion.Scope) error {
- return autoConvert_v1alpha5_OpenStackMachine_To_v1alpha8_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_v1alpha8_OpenStackMachine_To_v1alpha5_OpenStackMachine(in *v1alpha8.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_v1alpha8_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_v1alpha8_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_v1alpha8_OpenStackMachine_To_v1alpha5_OpenStackMachine is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackMachine_To_v1alpha5_OpenStackMachine(in *v1alpha8.OpenStackMachine, out *OpenStackMachine, s conversion.Scope) error {
- return autoConvert_v1alpha8_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_v1alpha8_OpenStackMachineList(in *OpenStackMachineList, out *v1alpha8.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([]v1alpha8.OpenStackMachine, len(*in))
+ *out = make([]v1beta1.OpenStackMachine, len(*in))
for i := range *in {
- if err := Convert_v1alpha5_OpenStackMachine_To_v1alpha8_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
}
}
@@ -1059,18 +1059,18 @@ func autoConvert_v1alpha5_OpenStackMachineList_To_v1alpha8_OpenStackMachineList(
return nil
}
-// Convert_v1alpha5_OpenStackMachineList_To_v1alpha8_OpenStackMachineList is an autogenerated conversion function.
-func Convert_v1alpha5_OpenStackMachineList_To_v1alpha8_OpenStackMachineList(in *OpenStackMachineList, out *v1alpha8.OpenStackMachineList, s conversion.Scope) error {
- return autoConvert_v1alpha5_OpenStackMachineList_To_v1alpha8_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_v1alpha8_OpenStackMachineList_To_v1alpha5_OpenStackMachineList(in *v1alpha8.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_v1alpha8_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
}
}
@@ -1080,25 +1080,25 @@ func autoConvert_v1alpha8_OpenStackMachineList_To_v1alpha5_OpenStackMachineList(
return nil
}
-// Convert_v1alpha8_OpenStackMachineList_To_v1alpha5_OpenStackMachineList is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackMachineList_To_v1alpha5_OpenStackMachineList(in *v1alpha8.OpenStackMachineList, out *OpenStackMachineList, s conversion.Scope) error {
- return autoConvert_v1alpha8_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_v1alpha8_OpenStackMachineSpec(in *OpenStackMachineSpec, out *v1alpha8.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
out.Flavor = in.Flavor
- // WARNING: in.Image requires manual conversion: inconvertible types (string vs sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8.ImageFilter)
+ // WARNING: in.Image requires manual conversion: inconvertible types (string vs sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ImageFilter)
// 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([]v1alpha8.PortOpts, len(*in))
+ *out = make([]v1beta1.PortOpts, len(*in))
for i := range *in {
- if err := Convert_v1alpha5_PortOpts_To_v1alpha8_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
}
}
@@ -1109,9 +1109,9 @@ func autoConvert_v1alpha5_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(
// WARNING: in.FloatingIP requires manual conversion: does not exist in peer-type
if in.SecurityGroups != nil {
in, out := &in.SecurityGroups, &out.SecurityGroups
- *out = make([]v1alpha8.SecurityGroupFilter, len(*in))
+ *out = make([]v1beta1.SecurityGroupFilter, len(*in))
for i := range *in {
- if err := Convert_v1alpha5_SecurityGroupParam_To_v1alpha8_SecurityGroupFilter(&(*in)[i], &(*out)[i], s); err != nil {
+ if err := Convert_v1alpha5_SecurityGroupParam_To_v1beta1_SecurityGroupFilter(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -1120,14 +1120,14 @@ func autoConvert_v1alpha5_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(
}
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/v1alpha8.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 = (*v1alpha8.RootVolume)(unsafe.Pointer(in.RootVolume))
+ out.RootVolume = (*v1beta1.RootVolume)(unsafe.Pointer(in.RootVolume))
// WARNING: in.ServerGroupID requires manual conversion: does not exist in peer-type
if in.IdentityRef != nil {
in, out := &in.IdentityRef, &out.IdentityRef
- *out = new(v1alpha8.OpenStackIdentityReference)
- if err := Convert_v1alpha5_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(*in, *out, s); err != nil {
+ *out = new(v1beta1.OpenStackIdentityReference)
+ if err := Convert_v1alpha5_OpenStackIdentityReference_To_v1beta1_OpenStackIdentityReference(*in, *out, s); err != nil {
return err
}
} else {
@@ -1136,18 +1136,18 @@ func autoConvert_v1alpha5_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(
return nil
}
-func autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(in *v1alpha8.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
- // WARNING: in.Image requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8.ImageFilter vs string)
+ // WARNING: in.Image requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ImageFilter 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_v1alpha8_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
}
}
@@ -1158,7 +1158,7 @@ func autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(
in, out := &in.SecurityGroups, &out.SecurityGroups
*out = make([]SecurityGroupParam, len(*in))
for i := range *in {
- if err := Convert_v1alpha8_SecurityGroupFilter_To_v1alpha5_SecurityGroupParam(&(*in)[i], &(*out)[i], s); err != nil {
+ if err := Convert_v1beta1_SecurityGroupFilter_To_v1alpha5_SecurityGroupParam(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -1167,7 +1167,7 @@ func autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(
}
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/v1alpha8.ServerMetadata vs map[string]string)
+ // 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))
// WARNING: in.AdditionalBlockDevices requires manual conversion: does not exist in peer-type
@@ -1175,7 +1175,7 @@ func autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(
if in.IdentityRef != nil {
in, out := &in.IdentityRef, &out.IdentityRef
*out = new(OpenStackIdentityReference)
- if err := Convert_v1alpha8_OpenStackIdentityReference_To_v1alpha5_OpenStackIdentityReference(*in, *out, s); err != nil {
+ if err := Convert_v1beta1_OpenStackIdentityReference_To_v1alpha5_OpenStackIdentityReference(*in, *out, s); err != nil {
return err
}
} else {
@@ -1184,22 +1184,22 @@ func autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(
return nil
}
-func autoConvert_v1alpha5_OpenStackMachineStatus_To_v1alpha8_OpenStackMachineStatus(in *OpenStackMachineStatus, out *v1alpha8.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 = (*v1alpha8.InstanceState)(unsafe.Pointer(in.InstanceState))
+ 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_v1alpha8_OpenStackMachineStatus is an autogenerated conversion function.
-func Convert_v1alpha5_OpenStackMachineStatus_To_v1alpha8_OpenStackMachineStatus(in *OpenStackMachineStatus, out *v1alpha8.OpenStackMachineStatus, s conversion.Scope) error {
- return autoConvert_v1alpha5_OpenStackMachineStatus_To_v1alpha8_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_v1alpha8_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineStatus(in *v1alpha8.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))
out.InstanceState = (*InstanceState)(unsafe.Pointer(in.InstanceState))
@@ -1207,43 +1207,43 @@ func autoConvert_v1alpha8_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineSta
// WARNING: in.DependentResources 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
}
-func autoConvert_v1alpha5_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate(in *OpenStackMachineTemplate, out *v1alpha8.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_v1alpha8_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_v1alpha8_OpenStackMachineTemplate is an autogenerated conversion function.
-func Convert_v1alpha5_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate(in *OpenStackMachineTemplate, out *v1alpha8.OpenStackMachineTemplate, s conversion.Scope) error {
- return autoConvert_v1alpha5_OpenStackMachineTemplate_To_v1alpha8_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_v1alpha8_OpenStackMachineTemplate_To_v1alpha5_OpenStackMachineTemplate(in *v1alpha8.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_v1alpha8_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_v1alpha8_OpenStackMachineTemplate_To_v1alpha5_OpenStackMachineTemplate is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackMachineTemplate_To_v1alpha5_OpenStackMachineTemplate(in *v1alpha8.OpenStackMachineTemplate, out *OpenStackMachineTemplate, s conversion.Scope) error {
- return autoConvert_v1alpha8_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_v1alpha8_OpenStackMachineTemplateList(in *OpenStackMachineTemplateList, out *v1alpha8.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([]v1alpha8.OpenStackMachineTemplate, len(*in))
+ *out = make([]v1beta1.OpenStackMachineTemplate, len(*in))
for i := range *in {
- if err := Convert_v1alpha5_OpenStackMachineTemplate_To_v1alpha8_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
}
}
@@ -1253,18 +1253,18 @@ func autoConvert_v1alpha5_OpenStackMachineTemplateList_To_v1alpha8_OpenStackMach
return nil
}
-// Convert_v1alpha5_OpenStackMachineTemplateList_To_v1alpha8_OpenStackMachineTemplateList is an autogenerated conversion function.
-func Convert_v1alpha5_OpenStackMachineTemplateList_To_v1alpha8_OpenStackMachineTemplateList(in *OpenStackMachineTemplateList, out *v1alpha8.OpenStackMachineTemplateList, s conversion.Scope) error {
- return autoConvert_v1alpha5_OpenStackMachineTemplateList_To_v1alpha8_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_v1alpha8_OpenStackMachineTemplateList_To_v1alpha5_OpenStackMachineTemplateList(in *v1alpha8.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_v1alpha8_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
}
}
@@ -1274,91 +1274,91 @@ func autoConvert_v1alpha8_OpenStackMachineTemplateList_To_v1alpha5_OpenStackMach
return nil
}
-// Convert_v1alpha8_OpenStackMachineTemplateList_To_v1alpha5_OpenStackMachineTemplateList is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackMachineTemplateList_To_v1alpha5_OpenStackMachineTemplateList(in *v1alpha8.OpenStackMachineTemplateList, out *OpenStackMachineTemplateList, s conversion.Scope) error {
- return autoConvert_v1alpha8_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_v1alpha8_OpenStackMachineTemplateResource(in *OpenStackMachineTemplateResource, out *v1alpha8.OpenStackMachineTemplateResource, s conversion.Scope) error {
- if err := Convert_v1alpha5_OpenStackMachineSpec_To_v1alpha8_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_v1alpha8_OpenStackMachineTemplateResource is an autogenerated conversion function.
-func Convert_v1alpha5_OpenStackMachineTemplateResource_To_v1alpha8_OpenStackMachineTemplateResource(in *OpenStackMachineTemplateResource, out *v1alpha8.OpenStackMachineTemplateResource, s conversion.Scope) error {
- return autoConvert_v1alpha5_OpenStackMachineTemplateResource_To_v1alpha8_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_v1alpha8_OpenStackMachineTemplateResource_To_v1alpha5_OpenStackMachineTemplateResource(in *v1alpha8.OpenStackMachineTemplateResource, out *OpenStackMachineTemplateResource, s conversion.Scope) error {
- if err := Convert_v1alpha8_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_v1alpha8_OpenStackMachineTemplateResource_To_v1alpha5_OpenStackMachineTemplateResource is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackMachineTemplateResource_To_v1alpha5_OpenStackMachineTemplateResource(in *v1alpha8.OpenStackMachineTemplateResource, out *OpenStackMachineTemplateResource, s conversion.Scope) error {
- return autoConvert_v1alpha8_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_v1alpha8_OpenStackMachineTemplateSpec(in *OpenStackMachineTemplateSpec, out *v1alpha8.OpenStackMachineTemplateSpec, s conversion.Scope) error {
- if err := Convert_v1alpha5_OpenStackMachineTemplateResource_To_v1alpha8_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_v1alpha8_OpenStackMachineTemplateSpec is an autogenerated conversion function.
-func Convert_v1alpha5_OpenStackMachineTemplateSpec_To_v1alpha8_OpenStackMachineTemplateSpec(in *OpenStackMachineTemplateSpec, out *v1alpha8.OpenStackMachineTemplateSpec, s conversion.Scope) error {
- return autoConvert_v1alpha5_OpenStackMachineTemplateSpec_To_v1alpha8_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_v1alpha8_OpenStackMachineTemplateSpec_To_v1alpha5_OpenStackMachineTemplateSpec(in *v1alpha8.OpenStackMachineTemplateSpec, out *OpenStackMachineTemplateSpec, s conversion.Scope) error {
- if err := Convert_v1alpha8_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_v1alpha8_OpenStackMachineTemplateSpec_To_v1alpha5_OpenStackMachineTemplateSpec is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackMachineTemplateSpec_To_v1alpha5_OpenStackMachineTemplateSpec(in *v1alpha8.OpenStackMachineTemplateSpec, out *OpenStackMachineTemplateSpec, s conversion.Scope) error {
- return autoConvert_v1alpha8_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_v1alpha8_PortOpts(in *PortOpts, out *v1alpha8.PortOpts, s conversion.Scope) error {
- out.Network = (*v1alpha8.NetworkFilter)(unsafe.Pointer(in.Network))
+func autoConvert_v1alpha5_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *v1beta1.PortOpts, s conversion.Scope) error {
+ out.Network = (*v1beta1.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 = *(*[]v1alpha8.FixedIP)(unsafe.Pointer(&in.FixedIPs))
+ out.FixedIPs = *(*[]v1beta1.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([]v1alpha8.SecurityGroupFilter, len(*in))
+ *out = make([]v1beta1.SecurityGroupFilter, len(*in))
for i := range *in {
- if err := Convert_v1alpha5_SecurityGroupParam_To_v1alpha8_SecurityGroupFilter(&(*in)[i], &(*out)[i], s); err != nil {
+ if err := Convert_v1alpha5_SecurityGroupParam_To_v1beta1_SecurityGroupFilter(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.SecurityGroupFilters = nil
}
- out.AllowedAddressPairs = *(*[]v1alpha8.AddressPair)(unsafe.Pointer(&in.AllowedAddressPairs))
+ out.AllowedAddressPairs = *(*[]v1beta1.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 (map[string]string vs sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8.BindingProfile)
+ // WARNING: in.Profile requires manual conversion: inconvertible types (map[string]string vs sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.BindingProfile)
out.DisablePortSecurity = (*bool)(unsafe.Pointer(in.DisablePortSecurity))
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
return nil
}
-func autoConvert_v1alpha8_PortOpts_To_v1alpha5_PortOpts(in *v1alpha8.PortOpts, out *PortOpts, s conversion.Scope) error {
+func autoConvert_v1beta1_PortOpts_To_v1alpha5_PortOpts(in *v1beta1.PortOpts, out *PortOpts, s conversion.Scope) error {
out.Network = (*NetworkFilter)(unsafe.Pointer(in.Network))
out.NameSuffix = in.NameSuffix
out.Description = in.Description
@@ -1369,7 +1369,7 @@ func autoConvert_v1alpha8_PortOpts_To_v1alpha5_PortOpts(in *v1alpha8.PortOpts, o
in, out := &in.SecurityGroupFilters, &out.SecurityGroupFilters
*out = make([]SecurityGroupParam, len(*in))
for i := range *in {
- if err := Convert_v1alpha8_SecurityGroupFilter_To_v1alpha5_SecurityGroupParam(&(*in)[i], &(*out)[i], s); err != nil {
+ if err := Convert_v1beta1_SecurityGroupFilter_To_v1alpha5_SecurityGroupParam(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -1380,7 +1380,7 @@ func autoConvert_v1alpha8_PortOpts_To_v1alpha5_PortOpts(in *v1alpha8.PortOpts, o
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/v1alpha8.BindingProfile vs map[string]string)
+ // WARNING: in.Profile requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.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))
@@ -1388,31 +1388,31 @@ func autoConvert_v1alpha8_PortOpts_To_v1alpha5_PortOpts(in *v1alpha8.PortOpts, o
return nil
}
-func autoConvert_v1alpha5_RootVolume_To_v1alpha8_RootVolume(in *RootVolume, out *v1alpha8.RootVolume, s conversion.Scope) error {
+func autoConvert_v1alpha5_RootVolume_To_v1beta1_RootVolume(in *RootVolume, out *v1beta1.RootVolume, s conversion.Scope) error {
out.Size = in.Size
out.VolumeType = in.VolumeType
out.AvailabilityZone = in.AvailabilityZone
return nil
}
-// Convert_v1alpha5_RootVolume_To_v1alpha8_RootVolume is an autogenerated conversion function.
-func Convert_v1alpha5_RootVolume_To_v1alpha8_RootVolume(in *RootVolume, out *v1alpha8.RootVolume, s conversion.Scope) error {
- return autoConvert_v1alpha5_RootVolume_To_v1alpha8_RootVolume(in, out, s)
+// Convert_v1alpha5_RootVolume_To_v1beta1_RootVolume is an autogenerated conversion function.
+func Convert_v1alpha5_RootVolume_To_v1beta1_RootVolume(in *RootVolume, out *v1beta1.RootVolume, s conversion.Scope) error {
+ return autoConvert_v1alpha5_RootVolume_To_v1beta1_RootVolume(in, out, s)
}
-func autoConvert_v1alpha8_RootVolume_To_v1alpha5_RootVolume(in *v1alpha8.RootVolume, out *RootVolume, s conversion.Scope) error {
+func autoConvert_v1beta1_RootVolume_To_v1alpha5_RootVolume(in *v1beta1.RootVolume, out *RootVolume, s conversion.Scope) error {
out.Size = in.Size
out.VolumeType = in.VolumeType
out.AvailabilityZone = in.AvailabilityZone
return nil
}
-// Convert_v1alpha8_RootVolume_To_v1alpha5_RootVolume is an autogenerated conversion function.
-func Convert_v1alpha8_RootVolume_To_v1alpha5_RootVolume(in *v1alpha8.RootVolume, out *RootVolume, s conversion.Scope) error {
- return autoConvert_v1alpha8_RootVolume_To_v1alpha5_RootVolume(in, out, s)
+// Convert_v1beta1_RootVolume_To_v1alpha5_RootVolume is an autogenerated conversion function.
+func Convert_v1beta1_RootVolume_To_v1alpha5_RootVolume(in *v1beta1.RootVolume, out *RootVolume, s conversion.Scope) error {
+ return autoConvert_v1beta1_RootVolume_To_v1alpha5_RootVolume(in, out, s)
}
-func autoConvert_v1alpha5_Router_To_v1alpha8_Router(in *Router, out *v1alpha8.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))
@@ -1420,12 +1420,12 @@ func autoConvert_v1alpha5_Router_To_v1alpha8_Router(in *Router, out *v1alpha8.Ro
return nil
}
-// Convert_v1alpha5_Router_To_v1alpha8_Router is an autogenerated conversion function.
-func Convert_v1alpha5_Router_To_v1alpha8_Router(in *Router, out *v1alpha8.Router, s conversion.Scope) error {
- return autoConvert_v1alpha5_Router_To_v1alpha8_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_v1alpha8_Router_To_v1alpha5_Router(in *v1alpha8.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))
@@ -1433,12 +1433,12 @@ func autoConvert_v1alpha8_Router_To_v1alpha5_Router(in *v1alpha8.Router, out *Ro
return nil
}
-// Convert_v1alpha8_Router_To_v1alpha5_Router is an autogenerated conversion function.
-func Convert_v1alpha8_Router_To_v1alpha5_Router(in *v1alpha8.Router, out *Router, s conversion.Scope) error {
- return autoConvert_v1alpha8_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_SecurityGroupFilter_To_v1alpha8_SecurityGroupFilter(in *SecurityGroupFilter, out *v1alpha8.SecurityGroupFilter, s conversion.Scope) error {
+func autoConvert_v1alpha5_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in *SecurityGroupFilter, out *v1beta1.SecurityGroupFilter, s conversion.Scope) error {
out.ID = in.ID
out.Name = in.Name
out.Description = in.Description
@@ -1455,7 +1455,7 @@ func autoConvert_v1alpha5_SecurityGroupFilter_To_v1alpha8_SecurityGroupFilter(in
return nil
}
-func autoConvert_v1alpha8_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(in *v1alpha8.SecurityGroupFilter, out *SecurityGroupFilter, s conversion.Scope) error {
+func autoConvert_v1beta1_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(in *v1beta1.SecurityGroupFilter, out *SecurityGroupFilter, s conversion.Scope) error {
out.ID = in.ID
out.Name = in.Name
out.Description = in.Description
@@ -1467,12 +1467,12 @@ func autoConvert_v1alpha8_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(in
return nil
}
-// Convert_v1alpha8_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter is an autogenerated conversion function.
-func Convert_v1alpha8_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(in *v1alpha8.SecurityGroupFilter, out *SecurityGroupFilter, s conversion.Scope) error {
- return autoConvert_v1alpha8_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(in, out, s)
+// Convert_v1beta1_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter is an autogenerated conversion function.
+func Convert_v1beta1_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(in *v1beta1.SecurityGroupFilter, out *SecurityGroupFilter, s conversion.Scope) error {
+ return autoConvert_v1beta1_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(in, out, s)
}
-func autoConvert_v1alpha5_Subnet_To_v1alpha8_Subnet(in *Subnet, out *v1alpha8.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
@@ -1480,12 +1480,12 @@ func autoConvert_v1alpha5_Subnet_To_v1alpha8_Subnet(in *Subnet, out *v1alpha8.Su
return nil
}
-// Convert_v1alpha5_Subnet_To_v1alpha8_Subnet is an autogenerated conversion function.
-func Convert_v1alpha5_Subnet_To_v1alpha8_Subnet(in *Subnet, out *v1alpha8.Subnet, s conversion.Scope) error {
- return autoConvert_v1alpha5_Subnet_To_v1alpha8_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_v1alpha8_Subnet_To_v1alpha5_Subnet(in *v1alpha8.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
@@ -1493,12 +1493,12 @@ func autoConvert_v1alpha8_Subnet_To_v1alpha5_Subnet(in *v1alpha8.Subnet, out *Su
return nil
}
-// Convert_v1alpha8_Subnet_To_v1alpha5_Subnet is an autogenerated conversion function.
-func Convert_v1alpha8_Subnet_To_v1alpha5_Subnet(in *v1alpha8.Subnet, out *Subnet, s conversion.Scope) error {
- return autoConvert_v1alpha8_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_v1alpha8_SubnetFilter(in *SubnetFilter, out *v1alpha8.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
@@ -1515,12 +1515,12 @@ func autoConvert_v1alpha5_SubnetFilter_To_v1alpha8_SubnetFilter(in *SubnetFilter
return nil
}
-// Convert_v1alpha5_SubnetFilter_To_v1alpha8_SubnetFilter is an autogenerated conversion function.
-func Convert_v1alpha5_SubnetFilter_To_v1alpha8_SubnetFilter(in *SubnetFilter, out *v1alpha8.SubnetFilter, s conversion.Scope) error {
- return autoConvert_v1alpha5_SubnetFilter_To_v1alpha8_SubnetFilter(in, out, s)
+// Convert_v1alpha5_SubnetFilter_To_v1beta1_SubnetFilter is an autogenerated conversion function.
+func Convert_v1alpha5_SubnetFilter_To_v1beta1_SubnetFilter(in *SubnetFilter, out *v1beta1.SubnetFilter, s conversion.Scope) error {
+ return autoConvert_v1alpha5_SubnetFilter_To_v1beta1_SubnetFilter(in, out, s)
}
-func autoConvert_v1alpha8_SubnetFilter_To_v1alpha5_SubnetFilter(in *v1alpha8.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
@@ -1537,7 +1537,7 @@ func autoConvert_v1alpha8_SubnetFilter_To_v1alpha5_SubnetFilter(in *v1alpha8.Sub
return nil
}
-// Convert_v1alpha8_SubnetFilter_To_v1alpha5_SubnetFilter is an autogenerated conversion function.
-func Convert_v1alpha8_SubnetFilter_To_v1alpha5_SubnetFilter(in *v1alpha8.SubnetFilter, out *SubnetFilter, s conversion.Scope) error {
- return autoConvert_v1alpha8_SubnetFilter_To_v1alpha5_SubnetFilter(in, out, s)
+// Convert_v1beta1_SubnetFilter_To_v1alpha5_SubnetFilter is an autogenerated conversion function.
+func Convert_v1beta1_SubnetFilter_To_v1alpha5_SubnetFilter(in *v1beta1.SubnetFilter, out *SubnetFilter, s conversion.Scope) error {
+ return autoConvert_v1beta1_SubnetFilter_To_v1alpha5_SubnetFilter(in, out, s)
}
diff --git a/api/v1alpha6/conversion.go b/api/v1alpha6/conversion.go
index 396080e185..bb055369d1 100644
--- a/api/v1alpha6/conversion.go
+++ b/api/v1alpha6/conversion.go
@@ -24,7 +24,7 @@ import (
"k8s.io/utils/pointer"
ctrlconversion "sigs.k8s.io/controller-runtime/pkg/conversion"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/conversion"
)
@@ -41,7 +41,7 @@ func restorev1alpha6SecurityGroup(previous *SecurityGroup, dst *SecurityGroup) {
}
func restorev1alpha6MachineSpec(previous *OpenStackMachineSpec, dst *OpenStackMachineSpec) {
- // Subnet is removed from v1alpha8 with no replacement, so can't be
+ // 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
@@ -56,7 +56,7 @@ func restorev1alpha6MachineSpec(previous *OpenStackMachineSpec, dst *OpenStackMa
// losslessly converted. Restore the previously stored value on down-conversion.
dst.FloatingIP = previous.FloatingIP
- // Conversion to v1alpha8 truncates keys and values to 255 characters
+ // Conversion to v1beta1 truncates keys and values to 255 characters
for k, v := range previous.ServerMetadata {
kd := k
if len(k) > 255 {
@@ -74,12 +74,12 @@ func restorev1alpha6MachineSpec(previous *OpenStackMachineSpec, dst *OpenStackMa
}
}
- // Conversion to v1alpha8 removes the Kind fild
+ // Conversion to v1beta1 removes the Kind fild
dst.IdentityRef = previous.IdentityRef
}
func restorev1alpha6ClusterStatus(previous *OpenStackClusterStatus, dst *OpenStackClusterStatus) {
- // PortOpts.SecurityGroups have been removed in v1alpha8
+ // PortOpts.SecurityGroups have been removed in v1beta1
// We restore the whole PortOpts/Networks since they are anyway immutable.
if previous.ExternalNetwork != nil {
dst.ExternalNetwork.PortOpts = previous.ExternalNetwork.PortOpts
@@ -96,8 +96,8 @@ func restorev1alpha6ClusterStatus(previous *OpenStackClusterStatus, dst *OpenSta
restorev1alpha6SecurityGroup(previous.BastionSecurityGroup, dst.BastionSecurityGroup)
}
-func restorev1alpha8MachineSpec(previous *infrav1.OpenStackMachineSpec, dst *infrav1.OpenStackMachineSpec) {
- // PropagateUplinkStatus has been added in v1alpha8.
+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
@@ -105,20 +105,20 @@ func restorev1alpha8MachineSpec(previous *infrav1.OpenStackMachineSpec, dst *inf
dst.Image = previous.Image
}
-func restorev1alpha8Bastion(previous **infrav1.Bastion, dst **infrav1.Bastion) {
+func restorev1beta1Bastion(previous **infrav1.Bastion, dst **infrav1.Bastion) {
if *previous != nil && *dst != nil {
- restorev1alpha8MachineSpec(&(*previous).Instance, &(*dst).Instance)
+ restorev1beta1MachineSpec(&(*previous).Instance, &(*dst).Instance)
}
}
-func restorev1alpha8Subnets(previous *[]infrav1.SubnetFilter, dst *[]infrav1.SubnetFilter) {
+func restorev1beta1Subnets(previous *[]infrav1.SubnetFilter, dst *[]infrav1.SubnetFilter) {
if len(*previous) > 1 {
*dst = append(*dst, (*previous)[1:]...)
}
}
-func restorev1alpha8ClusterStatus(previous *infrav1.OpenStackClusterStatus, dst *infrav1.OpenStackClusterStatus) {
- // It's (theoretically) possible in v1alpha8 to have Network nil but
+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() {
@@ -169,7 +169,7 @@ func restorev1alpha6ClusterSpec(previous *OpenStackClusterSpec, dst *OpenStackCl
dst.AllowAllInClusterTraffic = true
}
- // Conversion to v1alpha8 removes the Kind field
+ // Conversion to v1beta1 removes the Kind field
dst.IdentityRef = previous.IdentityRef
}
@@ -190,7 +190,7 @@ var v1alpha6OpenStackClusterRestorer = conversion.RestorerFor[*OpenStackCluster]
),
}
-var v1alpha8OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStackCluster]{
+var v1beta1OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStackCluster]{
"externalNetwork": conversion.UnconditionalFieldRestorer(
func(c *infrav1.OpenStackCluster) *infrav1.NetworkFilter {
return &c.Spec.ExternalNetwork
@@ -215,25 +215,25 @@ var v1alpha8OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStack
func(c *infrav1.OpenStackCluster) **infrav1.Bastion {
return &c.Spec.Bastion
},
- restorev1alpha8Bastion,
+ restorev1beta1Bastion,
),
"subnets": conversion.HashedFieldRestorer(
func(c *infrav1.OpenStackCluster) *[]infrav1.SubnetFilter {
return &c.Spec.Subnets
},
- restorev1alpha8Subnets,
+ restorev1beta1Subnets,
),
"allNodesSecurityGroupRules": conversion.HashedFieldRestorer(
func(c *infrav1.OpenStackCluster) *infrav1.ManagedSecurityGroups {
return c.Spec.ManagedSecurityGroups
},
- restorev1alpha8ManagedSecurityGroups,
+ restorev1beta1ManagedSecurityGroups,
),
"status": conversion.HashedFieldRestorer(
func(c *infrav1.OpenStackCluster) *infrav1.OpenStackClusterStatus {
return &c.Status
},
- restorev1alpha8ClusterStatus,
+ restorev1beta1ClusterStatus,
),
"managedSubnets": conversion.UnconditionalFieldRestorer(
func(c *infrav1.OpenStackCluster) *[]infrav1.SubnetSpec {
@@ -247,8 +247,8 @@ func (r *OpenStackCluster) ConvertTo(dstRaw ctrlconversion.Hub) error {
return conversion.ConvertAndRestore(
r, dst,
- Convert_v1alpha6_OpenStackCluster_To_v1alpha8_OpenStackCluster, Convert_v1alpha8_OpenStackCluster_To_v1alpha6_OpenStackCluster,
- v1alpha6OpenStackClusterRestorer, v1alpha8OpenStackClusterRestorer,
+ Convert_v1alpha6_OpenStackCluster_To_v1beta1_OpenStackCluster, Convert_v1beta1_OpenStackCluster_To_v1alpha6_OpenStackCluster,
+ v1alpha6OpenStackClusterRestorer, v1beta1OpenStackClusterRestorer,
)
}
@@ -257,8 +257,8 @@ func (r *OpenStackCluster) ConvertFrom(srcRaw ctrlconversion.Hub) error {
return conversion.ConvertAndRestore(
src, r,
- Convert_v1alpha8_OpenStackCluster_To_v1alpha6_OpenStackCluster, Convert_v1alpha6_OpenStackCluster_To_v1alpha8_OpenStackCluster,
- v1alpha8OpenStackClusterRestorer, v1alpha6OpenStackClusterRestorer,
+ Convert_v1beta1_OpenStackCluster_To_v1alpha6_OpenStackCluster, Convert_v1alpha6_OpenStackCluster_To_v1beta1_OpenStackCluster,
+ v1beta1OpenStackClusterRestorer, v1alpha6OpenStackClusterRestorer,
)
}
@@ -267,13 +267,13 @@ var _ ctrlconversion.Convertible = &OpenStackClusterList{}
func (r *OpenStackClusterList) ConvertTo(dstRaw ctrlconversion.Hub) error {
dst := dstRaw.(*infrav1.OpenStackClusterList)
- return Convert_v1alpha6_OpenStackClusterList_To_v1alpha8_OpenStackClusterList(r, dst, nil)
+ return Convert_v1alpha6_OpenStackClusterList_To_v1beta1_OpenStackClusterList(r, dst, nil)
}
func (r *OpenStackClusterList) ConvertFrom(srcRaw ctrlconversion.Hub) error {
src := srcRaw.(*infrav1.OpenStackClusterList)
- return Convert_v1alpha8_OpenStackClusterList_To_v1alpha6_OpenStackClusterList(src, r, nil)
+ return Convert_v1beta1_OpenStackClusterList_To_v1alpha6_OpenStackClusterList(src, r, nil)
}
var _ ctrlconversion.Convertible = &OpenStackClusterTemplate{}
@@ -287,11 +287,11 @@ var v1alpha6OpenStackClusterTemplateRestorer = conversion.RestorerFor[*OpenStack
),
}
-func restorev1alpha8ManagedSecurityGroups(previous *infrav1.ManagedSecurityGroups, dst *infrav1.ManagedSecurityGroups) {
+func restorev1beta1ManagedSecurityGroups(previous *infrav1.ManagedSecurityGroups, dst *infrav1.ManagedSecurityGroups) {
dst.AllNodesSecurityGroupRules = previous.AllNodesSecurityGroupRules
}
-var v1alpha8OpenStackClusterTemplateRestorer = conversion.RestorerFor[*infrav1.OpenStackClusterTemplate]{
+var v1beta1OpenStackClusterTemplateRestorer = conversion.RestorerFor[*infrav1.OpenStackClusterTemplate]{
"externalNetwork": conversion.UnconditionalFieldRestorer(
func(c *infrav1.OpenStackClusterTemplate) *infrav1.NetworkFilter {
return &c.Spec.Template.Spec.ExternalNetwork
@@ -316,19 +316,19 @@ var v1alpha8OpenStackClusterTemplateRestorer = conversion.RestorerFor[*infrav1.O
func(c *infrav1.OpenStackClusterTemplate) **infrav1.Bastion {
return &c.Spec.Template.Spec.Bastion
},
- restorev1alpha8Bastion,
+ restorev1beta1Bastion,
),
"subnets": conversion.HashedFieldRestorer(
func(c *infrav1.OpenStackClusterTemplate) *[]infrav1.SubnetFilter {
return &c.Spec.Template.Spec.Subnets
},
- restorev1alpha8Subnets,
+ restorev1beta1Subnets,
),
"allNodesSecurityGroupRules": conversion.HashedFieldRestorer(
func(c *infrav1.OpenStackClusterTemplate) *infrav1.ManagedSecurityGroups {
return c.Spec.Template.Spec.ManagedSecurityGroups
},
- restorev1alpha8ManagedSecurityGroups,
+ restorev1beta1ManagedSecurityGroups,
),
"managedSubnets": conversion.UnconditionalFieldRestorer(
func(c *infrav1.OpenStackClusterTemplate) *[]infrav1.SubnetSpec {
@@ -342,8 +342,8 @@ func (r *OpenStackClusterTemplate) ConvertTo(dstRaw ctrlconversion.Hub) error {
return conversion.ConvertAndRestore(
r, dst,
- Convert_v1alpha6_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate, Convert_v1alpha8_OpenStackClusterTemplate_To_v1alpha6_OpenStackClusterTemplate,
- v1alpha6OpenStackClusterTemplateRestorer, v1alpha8OpenStackClusterTemplateRestorer,
+ Convert_v1alpha6_OpenStackClusterTemplate_To_v1beta1_OpenStackClusterTemplate, Convert_v1beta1_OpenStackClusterTemplate_To_v1alpha6_OpenStackClusterTemplate,
+ v1alpha6OpenStackClusterTemplateRestorer, v1beta1OpenStackClusterTemplateRestorer,
)
}
@@ -352,8 +352,8 @@ func (r *OpenStackClusterTemplate) ConvertFrom(srcRaw ctrlconversion.Hub) error
return conversion.ConvertAndRestore(
src, r,
- Convert_v1alpha8_OpenStackClusterTemplate_To_v1alpha6_OpenStackClusterTemplate, Convert_v1alpha6_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate,
- v1alpha8OpenStackClusterTemplateRestorer, v1alpha6OpenStackClusterTemplateRestorer,
+ Convert_v1beta1_OpenStackClusterTemplate_To_v1alpha6_OpenStackClusterTemplate, Convert_v1alpha6_OpenStackClusterTemplate_To_v1beta1_OpenStackClusterTemplate,
+ v1beta1OpenStackClusterTemplateRestorer, v1alpha6OpenStackClusterTemplateRestorer,
)
}
@@ -381,12 +381,12 @@ var v1alpha6OpenStackMachineRestorer = conversion.RestorerFor[*OpenStackMachine]
),
}
-var v1alpha8OpenStackMachineRestorer = conversion.RestorerFor[*infrav1.OpenStackMachine]{
+var v1beta1OpenStackMachineRestorer = conversion.RestorerFor[*infrav1.OpenStackMachine]{
"spec": conversion.HashedFieldRestorer(
func(c *infrav1.OpenStackMachine) *infrav1.OpenStackMachineSpec {
return &c.Spec
},
- restorev1alpha8MachineSpec,
+ restorev1beta1MachineSpec,
),
"depresources": conversion.UnconditionalFieldRestorer(
func(c *infrav1.OpenStackMachine) *infrav1.DependentMachineResources {
@@ -406,8 +406,8 @@ func (r *OpenStackMachine) ConvertTo(dstRaw ctrlconversion.Hub) error {
return conversion.ConvertAndRestore(
r, dst,
- Convert_v1alpha6_OpenStackMachine_To_v1alpha8_OpenStackMachine, Convert_v1alpha8_OpenStackMachine_To_v1alpha6_OpenStackMachine,
- v1alpha6OpenStackMachineRestorer, v1alpha8OpenStackMachineRestorer,
+ Convert_v1alpha6_OpenStackMachine_To_v1beta1_OpenStackMachine, Convert_v1beta1_OpenStackMachine_To_v1alpha6_OpenStackMachine,
+ v1alpha6OpenStackMachineRestorer, v1beta1OpenStackMachineRestorer,
)
}
@@ -416,8 +416,8 @@ func (r *OpenStackMachine) ConvertFrom(srcRaw ctrlconversion.Hub) error {
return conversion.ConvertAndRestore(
src, r,
- Convert_v1alpha8_OpenStackMachine_To_v1alpha6_OpenStackMachine, Convert_v1alpha6_OpenStackMachine_To_v1alpha8_OpenStackMachine,
- v1alpha8OpenStackMachineRestorer, v1alpha6OpenStackMachineRestorer,
+ Convert_v1beta1_OpenStackMachine_To_v1alpha6_OpenStackMachine, Convert_v1alpha6_OpenStackMachine_To_v1beta1_OpenStackMachine,
+ v1beta1OpenStackMachineRestorer, v1alpha6OpenStackMachineRestorer,
)
}
@@ -425,12 +425,12 @@ var _ ctrlconversion.Convertible = &OpenStackMachineList{}
func (r *OpenStackMachineList) ConvertTo(dstRaw ctrlconversion.Hub) error {
dst := dstRaw.(*infrav1.OpenStackMachineList)
- return Convert_v1alpha6_OpenStackMachineList_To_v1alpha8_OpenStackMachineList(r, dst, nil)
+ return Convert_v1alpha6_OpenStackMachineList_To_v1beta1_OpenStackMachineList(r, dst, nil)
}
func (r *OpenStackMachineList) ConvertFrom(srcRaw ctrlconversion.Hub) error {
src := srcRaw.(*infrav1.OpenStackMachineList)
- return Convert_v1alpha8_OpenStackMachineList_To_v1alpha6_OpenStackMachineList(src, r, nil)
+ return Convert_v1beta1_OpenStackMachineList_To_v1alpha6_OpenStackMachineList(src, r, nil)
}
var _ ctrlconversion.Convertible = &OpenStackMachineTemplate{}
@@ -444,12 +444,12 @@ var v1alpha6OpenStackMachineTemplateRestorer = conversion.RestorerFor[*OpenStack
),
}
-var v1alpha8OpenStackMachineTemplateRestorer = conversion.RestorerFor[*infrav1.OpenStackMachineTemplate]{
+var v1beta1OpenStackMachineTemplateRestorer = conversion.RestorerFor[*infrav1.OpenStackMachineTemplate]{
"spec": conversion.HashedFieldRestorer(
func(c *infrav1.OpenStackMachineTemplate) *infrav1.OpenStackMachineSpec {
return &c.Spec.Template.Spec
},
- restorev1alpha8MachineSpec,
+ restorev1beta1MachineSpec,
),
}
@@ -458,8 +458,8 @@ func (r *OpenStackMachineTemplate) ConvertTo(dstRaw ctrlconversion.Hub) error {
return conversion.ConvertAndRestore(
r, dst,
- Convert_v1alpha6_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate, Convert_v1alpha8_OpenStackMachineTemplate_To_v1alpha6_OpenStackMachineTemplate,
- v1alpha6OpenStackMachineTemplateRestorer, v1alpha8OpenStackMachineTemplateRestorer,
+ Convert_v1alpha6_OpenStackMachineTemplate_To_v1beta1_OpenStackMachineTemplate, Convert_v1beta1_OpenStackMachineTemplate_To_v1alpha6_OpenStackMachineTemplate,
+ v1alpha6OpenStackMachineTemplateRestorer, v1beta1OpenStackMachineTemplateRestorer,
)
}
@@ -468,8 +468,8 @@ func (r *OpenStackMachineTemplate) ConvertFrom(srcRaw ctrlconversion.Hub) error
return conversion.ConvertAndRestore(
src, r,
- Convert_v1alpha8_OpenStackMachineTemplate_To_v1alpha6_OpenStackMachineTemplate, Convert_v1alpha6_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate,
- v1alpha8OpenStackMachineTemplateRestorer, v1alpha6OpenStackMachineTemplateRestorer,
+ Convert_v1beta1_OpenStackMachineTemplate_To_v1alpha6_OpenStackMachineTemplate, Convert_v1alpha6_OpenStackMachineTemplate_To_v1beta1_OpenStackMachineTemplate,
+ v1beta1OpenStackMachineTemplateRestorer, v1alpha6OpenStackMachineTemplateRestorer,
)
}
@@ -477,16 +477,16 @@ var _ ctrlconversion.Convertible = &OpenStackMachineTemplateList{}
func (r *OpenStackMachineTemplateList) ConvertTo(dstRaw ctrlconversion.Hub) error {
dst := dstRaw.(*infrav1.OpenStackMachineTemplateList)
- return Convert_v1alpha6_OpenStackMachineTemplateList_To_v1alpha8_OpenStackMachineTemplateList(r, dst, nil)
+ return Convert_v1alpha6_OpenStackMachineTemplateList_To_v1beta1_OpenStackMachineTemplateList(r, dst, nil)
}
func (r *OpenStackMachineTemplateList) ConvertFrom(srcRaw ctrlconversion.Hub) error {
src := srcRaw.(*infrav1.OpenStackMachineTemplateList)
- return Convert_v1alpha8_OpenStackMachineTemplateList_To_v1alpha6_OpenStackMachineTemplateList(src, r, nil)
+ return Convert_v1beta1_OpenStackMachineTemplateList_To_v1alpha6_OpenStackMachineTemplateList(src, r, nil)
}
-func Convert_v1alpha6_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(in *OpenStackMachineSpec, out *infrav1.OpenStackMachineSpec, s apiconversion.Scope) error {
- err := autoConvert_v1alpha6_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(in, out, s)
+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
}
@@ -516,7 +516,7 @@ func Convert_v1alpha6_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(in *
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 v1alpha8
+ // was not validated prior to v1beta1
if len(k) > 255 {
k = k[:255]
}
@@ -598,8 +598,8 @@ func convertNetworksToPorts(networks []NetworkParam) []infrav1.PortOpts {
return ports
}
-func Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(in *infrav1.OpenStackClusterSpec, out *OpenStackClusterSpec, s apiconversion.Scope) error {
- err := autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(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
}
@@ -609,7 +609,7 @@ func Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(in *
}
if len(in.Subnets) >= 1 {
- if err := Convert_v1alpha8_SubnetFilter_To_v1alpha6_SubnetFilter(&in.Subnets[0], &out.Subnet, s); err != nil {
+ if err := Convert_v1beta1_SubnetFilter_To_v1alpha6_SubnetFilter(&in.Subnets[0], &out.Subnet, s); err != nil {
return err
}
}
@@ -627,8 +627,8 @@ func Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(in *
return nil
}
-func Convert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *OpenStackClusterSpec, out *infrav1.OpenStackClusterSpec, s apiconversion.Scope) error {
- err := autoConvert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in, out, s)
+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
}
@@ -642,7 +642,7 @@ func Convert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *
emptySubnet := SubnetFilter{}
if in.Subnet != emptySubnet {
subnet := infrav1.SubnetFilter{}
- if err := Convert_v1alpha6_SubnetFilter_To_v1alpha8_SubnetFilter(&in.Subnet, &subnet, s); err != nil {
+ if err := Convert_v1alpha6_SubnetFilter_To_v1beta1_SubnetFilter(&in.Subnet, &subnet, s); err != nil {
return err
}
out.Subnets = []infrav1.SubnetFilter{subnet}
@@ -670,17 +670,17 @@ func Convert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *
return nil
}
-func Convert_v1alpha6_PortOpts_To_v1alpha8_PortOpts(in *PortOpts, out *infrav1.PortOpts, s apiconversion.Scope) error {
- err := autoConvert_v1alpha6_PortOpts_To_v1alpha8_PortOpts(in, out, s)
+func Convert_v1alpha6_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *infrav1.PortOpts, s apiconversion.Scope) error {
+ err := autoConvert_v1alpha6_PortOpts_To_v1beta1_PortOpts(in, out, s)
if err != nil {
return err
}
- // SecurityGroups are removed in v1alpha8 without replacement. SecurityGroupFilters can be used instead.
+ // SecurityGroups are removed in v1beta1 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 v1alpha8.
+ // Profile is now a struct in v1beta1.
if strings.Contains(in.Profile["capabilities"], "switchdev") {
out.Profile.OVSHWOffload = true
}
@@ -690,9 +690,9 @@ func Convert_v1alpha6_PortOpts_To_v1alpha8_PortOpts(in *PortOpts, out *infrav1.P
return nil
}
-func Convert_v1alpha8_PortOpts_To_v1alpha6_PortOpts(in *infrav1.PortOpts, out *PortOpts, s apiconversion.Scope) error {
- // value specs and propagate uplink status have been added in v1alpha8 but have no equivalent in v1alpha5
- err := autoConvert_v1alpha8_PortOpts_To_v1alpha6_PortOpts(in, out, s)
+func Convert_v1beta1_PortOpts_To_v1alpha6_PortOpts(in *infrav1.PortOpts, out *PortOpts, s apiconversion.Scope) error {
+ // value specs and propagate uplink status have been added in v1beta1 but have no equivalent in v1alpha5
+ err := autoConvert_v1beta1_PortOpts_To_v1alpha6_PortOpts(in, out, s)
if err != nil {
return err
}
@@ -707,7 +707,7 @@ func Convert_v1alpha8_PortOpts_To_v1alpha6_PortOpts(in *infrav1.PortOpts, out *P
return nil
}
-func Convert_v1alpha6_Instance_To_v1alpha8_BastionStatus(in *Instance, out *infrav1.BastionStatus, _ apiconversion.Scope) error {
+func Convert_v1alpha6_Instance_To_v1beta1_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
@@ -718,7 +718,7 @@ func Convert_v1alpha6_Instance_To_v1alpha8_BastionStatus(in *Instance, out *infr
return nil
}
-func Convert_v1alpha8_BastionStatus_To_v1alpha6_Instance(in *infrav1.BastionStatus, out *Instance, _ apiconversion.Scope) error {
+func Convert_v1beta1_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
@@ -729,9 +729,9 @@ func Convert_v1alpha8_BastionStatus_To_v1alpha6_Instance(in *infrav1.BastionStat
return nil
}
-func Convert_v1alpha6_Network_To_v1alpha8_NetworkStatusWithSubnets(in *Network, out *infrav1.NetworkStatusWithSubnets, s apiconversion.Scope) error {
- // PortOpts has been removed in v1alpha8
- err := Convert_v1alpha6_Network_To_v1alpha8_NetworkStatus(in, &out.NetworkStatus, s)
+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
}
@@ -742,9 +742,9 @@ func Convert_v1alpha6_Network_To_v1alpha8_NetworkStatusWithSubnets(in *Network,
return nil
}
-func Convert_v1alpha8_NetworkStatusWithSubnets_To_v1alpha6_Network(in *infrav1.NetworkStatusWithSubnets, out *Network, s apiconversion.Scope) error {
- // PortOpts has been removed in v1alpha8
- err := Convert_v1alpha8_NetworkStatus_To_v1alpha6_Network(&in.NetworkStatus, out, s)
+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
}
@@ -756,7 +756,7 @@ func Convert_v1alpha8_NetworkStatusWithSubnets_To_v1alpha6_Network(in *infrav1.N
return nil
}
-func Convert_v1alpha6_Network_To_v1alpha8_NetworkStatus(in *Network, out *infrav1.NetworkStatus, _ apiconversion.Scope) error {
+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
@@ -764,7 +764,7 @@ func Convert_v1alpha6_Network_To_v1alpha8_NetworkStatus(in *Network, out *infrav
return nil
}
-func Convert_v1alpha8_NetworkStatus_To_v1alpha6_Network(in *infrav1.NetworkStatus, out *Network, _ apiconversion.Scope) error {
+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
@@ -772,13 +772,13 @@ func Convert_v1alpha8_NetworkStatus_To_v1alpha6_Network(in *infrav1.NetworkStatu
return nil
}
-func Convert_v1alpha6_SecurityGroupFilter_To_v1alpha8_SecurityGroupFilter(in *SecurityGroupFilter, out *infrav1.SecurityGroupFilter, s apiconversion.Scope) error {
- err := autoConvert_v1alpha6_SecurityGroupFilter_To_v1alpha8_SecurityGroupFilter(in, out, s)
+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
}
- // TenantID has been removed in v1alpha8. Write it to ProjectID if ProjectID is not already set.
+ // TenantID has been removed in v1beta1. Write it to ProjectID if ProjectID is not already set.
if out.ProjectID == "" {
out.ProjectID = in.TenantID
}
@@ -786,9 +786,9 @@ func Convert_v1alpha6_SecurityGroupFilter_To_v1alpha8_SecurityGroupFilter(in *Se
return nil
}
-func Convert_v1alpha6_SecurityGroupParam_To_v1alpha8_SecurityGroupFilter(in *SecurityGroupParam, out *infrav1.SecurityGroupFilter, s apiconversion.Scope) error {
- // SecurityGroupParam is replaced by its contained SecurityGroupFilter in v1alpha8
- err := Convert_v1alpha6_SecurityGroupFilter_To_v1alpha8_SecurityGroupFilter(&in.Filter, out, s)
+func Convert_v1alpha6_SecurityGroupParam_To_v1beta1_SecurityGroupFilter(in *SecurityGroupParam, out *infrav1.SecurityGroupFilter, s apiconversion.Scope) error {
+ // SecurityGroupParam is replaced by its contained SecurityGroupFilter in v1beta1
+ err := Convert_v1alpha6_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(&in.Filter, out, s)
if err != nil {
return err
}
@@ -802,9 +802,9 @@ func Convert_v1alpha6_SecurityGroupParam_To_v1alpha8_SecurityGroupFilter(in *Sec
return nil
}
-func Convert_v1alpha8_SecurityGroupFilter_To_v1alpha6_SecurityGroupParam(in *infrav1.SecurityGroupFilter, out *SecurityGroupParam, s apiconversion.Scope) error {
- // SecurityGroupParam is replaced by its contained SecurityGroupFilter in v1alpha8
- err := Convert_v1alpha8_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(in, &out.Filter, s)
+func Convert_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupParam(in *infrav1.SecurityGroupFilter, out *SecurityGroupParam, s apiconversion.Scope) error {
+ // SecurityGroupParam is replaced by its contained SecurityGroupFilter in v1beta1
+ err := Convert_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(in, &out.Filter, s)
if err != nil {
return err
}
@@ -818,7 +818,7 @@ func Convert_v1alpha8_SecurityGroupFilter_To_v1alpha6_SecurityGroupParam(in *inf
return nil
}
-func Convert_v1alpha6_SubnetParam_To_v1alpha8_SubnetFilter(in *SubnetParam, out *infrav1.SubnetFilter, _ apiconversion.Scope) error {
+func Convert_v1alpha6_SubnetParam_To_v1beta1_SubnetFilter(in *SubnetParam, out *infrav1.SubnetFilter, _ apiconversion.Scope) error {
*out = infrav1.SubnetFilter(in.Filter)
if in.UUID != "" {
out.ID = in.UUID
@@ -826,14 +826,14 @@ func Convert_v1alpha6_SubnetParam_To_v1alpha8_SubnetFilter(in *SubnetParam, out
return nil
}
-func Convert_v1alpha8_SubnetFilter_To_v1alpha6_SubnetParam(in *infrav1.SubnetFilter, out *SubnetParam, _ apiconversion.Scope) error {
+func Convert_v1beta1_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_v1alpha8_BindingProfile(in map[string]string, out *infrav1.BindingProfile, _ apiconversion.Scope) error {
+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") {
@@ -847,7 +847,7 @@ func Convert_Map_string_To_Interface_To_v1alpha8_BindingProfile(in map[string]st
return nil
}
-func Convert_v1alpha8_BindingProfile_To_Map_string_To_Interface(in *infrav1.BindingProfile, out map[string]string, _ apiconversion.Scope) error {
+func Convert_v1beta1_BindingProfile_To_Map_string_To_Interface(in *infrav1.BindingProfile, out map[string]string, _ apiconversion.Scope) error {
if in.OVSHWOffload {
(out)["capabilities"] = "[\"switchdev\"]"
}
@@ -857,13 +857,13 @@ func Convert_v1alpha8_BindingProfile_To_Map_string_To_Interface(in *infrav1.Bind
return nil
}
-func Convert_v1alpha8_OpenStackClusterStatus_To_v1alpha6_OpenStackClusterStatus(in *infrav1.OpenStackClusterStatus, out *OpenStackClusterStatus, s apiconversion.Scope) error {
- err := autoConvert_v1alpha8_OpenStackClusterStatus_To_v1alpha6_OpenStackClusterStatus(in, out, s)
+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 v1alpha8
+ // 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{}
@@ -876,13 +876,13 @@ func Convert_v1alpha8_OpenStackClusterStatus_To_v1alpha6_OpenStackClusterStatus(
return nil
}
-func Convert_v1alpha6_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterStatus(in *OpenStackClusterStatus, out *infrav1.OpenStackClusterStatus, s apiconversion.Scope) error {
- err := autoConvert_v1alpha6_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterStatus(in, out, s)
+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 v1alpha8
+ // Router and APIServerLoadBalancer have been moved out of Network in v1beta1
if in.Network != nil {
out.Router = (*infrav1.Router)(in.Network.Router)
out.APIServerLoadBalancer = (*infrav1.LoadBalancer)(in.Network.APIServerLoadBalancer)
@@ -891,8 +891,8 @@ func Convert_v1alpha6_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterStatus(
return nil
}
-func Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(in *infrav1.OpenStackMachineSpec, out *OpenStackMachineSpec, s apiconversion.Scope) error {
- err := autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(in, out, s)
+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
}
@@ -922,13 +922,13 @@ func Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(in *
return nil
}
-func Convert_v1alpha8_OpenStackMachineStatus_To_v1alpha6_OpenStackMachineStatus(in *infrav1.OpenStackMachineStatus, out *OpenStackMachineStatus, s apiconversion.Scope) error {
+func Convert_v1beta1_OpenStackMachineStatus_To_v1alpha6_OpenStackMachineStatus(in *infrav1.OpenStackMachineStatus, out *OpenStackMachineStatus, s apiconversion.Scope) error {
// ReferencedResources have no equivalent in v1alpha6
- return autoConvert_v1alpha8_OpenStackMachineStatus_To_v1alpha6_OpenStackMachineStatus(in, out, s)
+ return autoConvert_v1beta1_OpenStackMachineStatus_To_v1alpha6_OpenStackMachineStatus(in, out, s)
}
-func Convert_v1alpha6_Bastion_To_v1alpha8_Bastion(in *Bastion, out *infrav1.Bastion, s apiconversion.Scope) error {
- err := autoConvert_v1alpha6_Bastion_To_v1alpha8_Bastion(in, out, s)
+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
}
@@ -943,8 +943,8 @@ func Convert_v1alpha6_Bastion_To_v1alpha8_Bastion(in *Bastion, out *infrav1.Bast
return nil
}
-func Convert_v1alpha8_Bastion_To_v1alpha6_Bastion(in *infrav1.Bastion, out *Bastion, s apiconversion.Scope) error {
- err := autoConvert_v1alpha8_Bastion_To_v1alpha6_Bastion(in, out, s)
+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
}
@@ -957,7 +957,7 @@ func Convert_v1alpha8_Bastion_To_v1alpha6_Bastion(in *infrav1.Bastion, out *Bast
return nil
}
-func Convert_v1alpha8_SecurityGroupStatus_To_v1alpha6_SecurityGroup(in *infrav1.SecurityGroupStatus, out *SecurityGroup, s apiconversion.Scope) error { //nolint:revive
+func Convert_v1beta1_SecurityGroupStatus_To_v1alpha6_SecurityGroup(in *infrav1.SecurityGroupStatus, out *SecurityGroup, s apiconversion.Scope) error { //nolint:revive
out.ID = in.ID
out.Name = in.Name
out.Rules = make([]SecurityGroupRule, len(in.Rules))
@@ -991,7 +991,7 @@ func Convert_v1alpha8_SecurityGroupStatus_To_v1alpha6_SecurityGroup(in *infrav1.
return nil
}
-func Convert_v1alpha6_SecurityGroup_To_v1alpha8_SecurityGroupStatus(in *SecurityGroup, out *infrav1.SecurityGroupStatus, s apiconversion.Scope) error { //nolint:revive
+func Convert_v1alpha6_SecurityGroup_To_v1beta1_SecurityGroupStatus(in *SecurityGroup, out *infrav1.SecurityGroupStatus, s apiconversion.Scope) error { //nolint:revive
out.ID = in.ID
out.Name = in.Name
out.Rules = make([]infrav1.SecurityGroupRuleStatus, len(in.Rules))
@@ -1012,6 +1012,6 @@ func Convert_v1alpha6_SecurityGroup_To_v1alpha8_SecurityGroupStatus(in *Security
return nil
}
-func Convert_v1alpha6_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(in *OpenStackIdentityReference, out *infrav1.OpenStackIdentityReference, s apiconversion.Scope) error {
- return autoConvert_v1alpha6_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(in, out, s)
+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)
}
diff --git a/api/v1alpha6/conversion_test.go b/api/v1alpha6/conversion_test.go
index d457f48e06..acfb73ce07 100644
--- a/api/v1alpha6/conversion_test.go
+++ b/api/v1alpha6/conversion_test.go
@@ -29,7 +29,7 @@ import (
utilconversion "sigs.k8s.io/cluster-api/util/conversion"
"sigs.k8s.io/controller-runtime/pkg/conversion"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
testhelpers "sigs.k8s.io/cluster-api-provider-openstack/test/helpers"
)
@@ -668,7 +668,7 @@ func TestMachineConversionControllerSpecFields(t *testing.T) {
}
}
-func TestConvert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(t *testing.T) {
+func TestConvert_v1alpha6_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(t *testing.T) {
tests := []struct {
name string
in *OpenStackClusterSpec
@@ -709,7 +709,7 @@ func TestConvert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(
t.Run(tt.name, func(t *testing.T) {
g := gomega.NewWithT(t)
out := &infrav1.OpenStackClusterSpec{}
- err := Convert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(tt.in, out, nil)
+ err := Convert_v1alpha6_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(tt.in, out, nil)
g.Expect(err).NotTo(gomega.HaveOccurred())
g.Expect(out).To(gomega.Equal(tt.expectedOut))
})
diff --git a/api/v1alpha6/doc.go b/api/v1alpha6/doc.go
index e0fde58a62..8b8c08cd51 100644
--- a/api/v1alpha6/doc.go
+++ b/api/v1alpha6/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/v1alpha8
+// +k8s:conversion-gen=sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1
package v1alpha6
diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go
index 2bda83e05c..127d71cd8c 100644
--- a/api/v1alpha6/zz_generated.conversion.go
+++ b/api/v1alpha6/zz_generated.conversion.go
@@ -27,8 +27,8 @@ import (
v1 "k8s.io/api/core/v1"
conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime"
- v1alpha8 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
- v1beta1 "sigs.k8s.io/cluster-api/api/v1beta1"
+ v1beta1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
+ apiv1beta1 "sigs.k8s.io/cluster-api/api/v1beta1"
errors "sigs.k8s.io/cluster-api/errors"
)
@@ -39,380 +39,380 @@ 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), (*v1alpha8.APIServerLoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalancer(a.(*APIServerLoadBalancer), b.(*v1alpha8.APIServerLoadBalancer), scope)
+ if err := s.AddGeneratedConversionFunc((*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((*v1alpha8.APIServerLoadBalancer)(nil), (*APIServerLoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalancer(a.(*v1alpha8.APIServerLoadBalancer), b.(*APIServerLoadBalancer), scope)
+ if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*AddressPair)(nil), (*v1alpha8.AddressPair)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_AddressPair_To_v1alpha8_AddressPair(a.(*AddressPair), b.(*v1alpha8.AddressPair), 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((*v1alpha8.AddressPair)(nil), (*AddressPair)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_AddressPair_To_v1alpha6_AddressPair(a.(*v1alpha8.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_v1alpha6_AddressPair(a.(*v1beta1.AddressPair), b.(*AddressPair), scope)
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*ExternalRouterIPParam)(nil), (*v1alpha8.ExternalRouterIPParam)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_ExternalRouterIPParam_To_v1alpha8_ExternalRouterIPParam(a.(*ExternalRouterIPParam), b.(*v1alpha8.ExternalRouterIPParam), 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((*v1alpha8.ExternalRouterIPParam)(nil), (*ExternalRouterIPParam)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_ExternalRouterIPParam_To_v1alpha6_ExternalRouterIPParam(a.(*v1alpha8.ExternalRouterIPParam), b.(*ExternalRouterIPParam), 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((*FixedIP)(nil), (*v1alpha8.FixedIP)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_FixedIP_To_v1alpha8_FixedIP(a.(*FixedIP), b.(*v1alpha8.FixedIP), 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((*v1alpha8.FixedIP)(nil), (*FixedIP)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_FixedIP_To_v1alpha6_FixedIP(a.(*v1alpha8.FixedIP), b.(*FixedIP), 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((*LoadBalancer)(nil), (*v1alpha8.LoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_LoadBalancer_To_v1alpha8_LoadBalancer(a.(*LoadBalancer), b.(*v1alpha8.LoadBalancer), 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((*v1alpha8.LoadBalancer)(nil), (*LoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_LoadBalancer_To_v1alpha6_LoadBalancer(a.(*v1alpha8.LoadBalancer), b.(*LoadBalancer), scope)
+ if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*NetworkFilter)(nil), (*v1alpha8.NetworkFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_NetworkFilter_To_v1alpha8_NetworkFilter(a.(*NetworkFilter), b.(*v1alpha8.NetworkFilter), scope)
+ if err := s.AddGeneratedConversionFunc((*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((*v1alpha8.NetworkFilter)(nil), (*NetworkFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_NetworkFilter_To_v1alpha6_NetworkFilter(a.(*v1alpha8.NetworkFilter), b.(*NetworkFilter), scope)
+ if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*OpenStackCluster)(nil), (*v1alpha8.OpenStackCluster)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_OpenStackCluster_To_v1alpha8_OpenStackCluster(a.(*OpenStackCluster), b.(*v1alpha8.OpenStackCluster), 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((*v1alpha8.OpenStackCluster)(nil), (*OpenStackCluster)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackCluster_To_v1alpha6_OpenStackCluster(a.(*v1alpha8.OpenStackCluster), b.(*OpenStackCluster), 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((*OpenStackClusterList)(nil), (*v1alpha8.OpenStackClusterList)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_OpenStackClusterList_To_v1alpha8_OpenStackClusterList(a.(*OpenStackClusterList), b.(*v1alpha8.OpenStackClusterList), 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((*v1alpha8.OpenStackClusterList)(nil), (*OpenStackClusterList)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackClusterList_To_v1alpha6_OpenStackClusterList(a.(*v1alpha8.OpenStackClusterList), b.(*OpenStackClusterList), 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((*OpenStackClusterTemplate)(nil), (*v1alpha8.OpenStackClusterTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate(a.(*OpenStackClusterTemplate), b.(*v1alpha8.OpenStackClusterTemplate), 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((*v1alpha8.OpenStackClusterTemplate)(nil), (*OpenStackClusterTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackClusterTemplate_To_v1alpha6_OpenStackClusterTemplate(a.(*v1alpha8.OpenStackClusterTemplate), b.(*OpenStackClusterTemplate), 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((*OpenStackClusterTemplateList)(nil), (*v1alpha8.OpenStackClusterTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_OpenStackClusterTemplateList_To_v1alpha8_OpenStackClusterTemplateList(a.(*OpenStackClusterTemplateList), b.(*v1alpha8.OpenStackClusterTemplateList), 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((*v1alpha8.OpenStackClusterTemplateList)(nil), (*OpenStackClusterTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackClusterTemplateList_To_v1alpha6_OpenStackClusterTemplateList(a.(*v1alpha8.OpenStackClusterTemplateList), b.(*OpenStackClusterTemplateList), 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((*OpenStackClusterTemplateResource)(nil), (*v1alpha8.OpenStackClusterTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_OpenStackClusterTemplateResource_To_v1alpha8_OpenStackClusterTemplateResource(a.(*OpenStackClusterTemplateResource), b.(*v1alpha8.OpenStackClusterTemplateResource), 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((*v1alpha8.OpenStackClusterTemplateResource)(nil), (*OpenStackClusterTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackClusterTemplateResource_To_v1alpha6_OpenStackClusterTemplateResource(a.(*v1alpha8.OpenStackClusterTemplateResource), b.(*OpenStackClusterTemplateResource), 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((*OpenStackClusterTemplateSpec)(nil), (*v1alpha8.OpenStackClusterTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_OpenStackClusterTemplateSpec_To_v1alpha8_OpenStackClusterTemplateSpec(a.(*OpenStackClusterTemplateSpec), b.(*v1alpha8.OpenStackClusterTemplateSpec), 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((*v1alpha8.OpenStackClusterTemplateSpec)(nil), (*OpenStackClusterTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackClusterTemplateSpec_To_v1alpha6_OpenStackClusterTemplateSpec(a.(*v1alpha8.OpenStackClusterTemplateSpec), b.(*OpenStackClusterTemplateSpec), 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((*v1alpha8.OpenStackIdentityReference)(nil), (*OpenStackIdentityReference)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackIdentityReference_To_v1alpha6_OpenStackIdentityReference(a.(*v1alpha8.OpenStackIdentityReference), b.(*OpenStackIdentityReference), scope)
+ if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*OpenStackMachine)(nil), (*v1alpha8.OpenStackMachine)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_OpenStackMachine_To_v1alpha8_OpenStackMachine(a.(*OpenStackMachine), b.(*v1alpha8.OpenStackMachine), scope)
+ if err := s.AddGeneratedConversionFunc((*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((*v1alpha8.OpenStackMachine)(nil), (*OpenStackMachine)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackMachine_To_v1alpha6_OpenStackMachine(a.(*v1alpha8.OpenStackMachine), b.(*OpenStackMachine), scope)
+ if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*OpenStackMachineList)(nil), (*v1alpha8.OpenStackMachineList)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_OpenStackMachineList_To_v1alpha8_OpenStackMachineList(a.(*OpenStackMachineList), b.(*v1alpha8.OpenStackMachineList), 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((*v1alpha8.OpenStackMachineList)(nil), (*OpenStackMachineList)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackMachineList_To_v1alpha6_OpenStackMachineList(a.(*v1alpha8.OpenStackMachineList), b.(*OpenStackMachineList), 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((*OpenStackMachineStatus)(nil), (*v1alpha8.OpenStackMachineStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_OpenStackMachineStatus_To_v1alpha8_OpenStackMachineStatus(a.(*OpenStackMachineStatus), b.(*v1alpha8.OpenStackMachineStatus), 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((*OpenStackMachineTemplate)(nil), (*v1alpha8.OpenStackMachineTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate(a.(*OpenStackMachineTemplate), b.(*v1alpha8.OpenStackMachineTemplate), 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((*v1alpha8.OpenStackMachineTemplate)(nil), (*OpenStackMachineTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackMachineTemplate_To_v1alpha6_OpenStackMachineTemplate(a.(*v1alpha8.OpenStackMachineTemplate), b.(*OpenStackMachineTemplate), 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((*OpenStackMachineTemplateList)(nil), (*v1alpha8.OpenStackMachineTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_OpenStackMachineTemplateList_To_v1alpha8_OpenStackMachineTemplateList(a.(*OpenStackMachineTemplateList), b.(*v1alpha8.OpenStackMachineTemplateList), 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((*v1alpha8.OpenStackMachineTemplateList)(nil), (*OpenStackMachineTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackMachineTemplateList_To_v1alpha6_OpenStackMachineTemplateList(a.(*v1alpha8.OpenStackMachineTemplateList), b.(*OpenStackMachineTemplateList), 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((*OpenStackMachineTemplateResource)(nil), (*v1alpha8.OpenStackMachineTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_OpenStackMachineTemplateResource_To_v1alpha8_OpenStackMachineTemplateResource(a.(*OpenStackMachineTemplateResource), b.(*v1alpha8.OpenStackMachineTemplateResource), 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((*v1alpha8.OpenStackMachineTemplateResource)(nil), (*OpenStackMachineTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackMachineTemplateResource_To_v1alpha6_OpenStackMachineTemplateResource(a.(*v1alpha8.OpenStackMachineTemplateResource), b.(*OpenStackMachineTemplateResource), 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((*OpenStackMachineTemplateSpec)(nil), (*v1alpha8.OpenStackMachineTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_OpenStackMachineTemplateSpec_To_v1alpha8_OpenStackMachineTemplateSpec(a.(*OpenStackMachineTemplateSpec), b.(*v1alpha8.OpenStackMachineTemplateSpec), 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((*v1alpha8.OpenStackMachineTemplateSpec)(nil), (*OpenStackMachineTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackMachineTemplateSpec_To_v1alpha6_OpenStackMachineTemplateSpec(a.(*v1alpha8.OpenStackMachineTemplateSpec), b.(*OpenStackMachineTemplateSpec), 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((*RootVolume)(nil), (*v1alpha8.RootVolume)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_RootVolume_To_v1alpha8_RootVolume(a.(*RootVolume), b.(*v1alpha8.RootVolume), scope)
+ if err := s.AddGeneratedConversionFunc((*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((*v1alpha8.RootVolume)(nil), (*RootVolume)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_RootVolume_To_v1alpha6_RootVolume(a.(*v1alpha8.RootVolume), b.(*RootVolume), scope)
+ if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*Router)(nil), (*v1alpha8.Router)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_Router_To_v1alpha8_Router(a.(*Router), b.(*v1alpha8.Router), 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((*v1alpha8.Router)(nil), (*Router)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_Router_To_v1alpha6_Router(a.(*v1alpha8.Router), b.(*Router), 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((*v1alpha8.SecurityGroupFilter)(nil), (*SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(a.(*v1alpha8.SecurityGroupFilter), b.(*SecurityGroupFilter), scope)
+ if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*Subnet)(nil), (*v1alpha8.Subnet)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_Subnet_To_v1alpha8_Subnet(a.(*Subnet), b.(*v1alpha8.Subnet), 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((*v1alpha8.Subnet)(nil), (*Subnet)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_Subnet_To_v1alpha6_Subnet(a.(*v1alpha8.Subnet), b.(*Subnet), 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((*SubnetFilter)(nil), (*v1alpha8.SubnetFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_SubnetFilter_To_v1alpha8_SubnetFilter(a.(*SubnetFilter), b.(*v1alpha8.SubnetFilter), scope)
+ if err := s.AddGeneratedConversionFunc((*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((*v1alpha8.SubnetFilter)(nil), (*SubnetFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_SubnetFilter_To_v1alpha6_SubnetFilter(a.(*v1alpha8.SubnetFilter), b.(*SubnetFilter), scope)
+ if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*ValueSpec)(nil), (*v1alpha8.ValueSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_ValueSpec_To_v1alpha8_ValueSpec(a.(*ValueSpec), b.(*v1alpha8.ValueSpec), 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((*v1alpha8.ValueSpec)(nil), (*ValueSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_ValueSpec_To_v1alpha6_ValueSpec(a.(*v1alpha8.ValueSpec), b.(*ValueSpec), 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.AddConversionFunc((*Bastion)(nil), (*v1alpha8.Bastion)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_Bastion_To_v1alpha8_Bastion(a.(*Bastion), b.(*v1alpha8.Bastion), 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.AddConversionFunc((*Instance)(nil), (*v1alpha8.BastionStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_Instance_To_v1alpha8_BastionStatus(a.(*Instance), b.(*v1alpha8.BastionStatus), 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.AddConversionFunc((*Network)(nil), (*v1alpha8.NetworkStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_Network_To_v1alpha8_NetworkStatus(a.(*Network), b.(*v1alpha8.NetworkStatus), 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.AddConversionFunc((*Network)(nil), (*v1alpha8.NetworkStatusWithSubnets)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_Network_To_v1alpha8_NetworkStatusWithSubnets(a.(*Network), b.(*v1alpha8.NetworkStatusWithSubnets), 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.AddConversionFunc((*OpenStackClusterSpec)(nil), (*v1alpha8.OpenStackClusterSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(a.(*OpenStackClusterSpec), b.(*v1alpha8.OpenStackClusterSpec), 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.AddConversionFunc((*OpenStackClusterStatus)(nil), (*v1alpha8.OpenStackClusterStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterStatus(a.(*OpenStackClusterStatus), b.(*v1alpha8.OpenStackClusterStatus), 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.AddConversionFunc((*OpenStackIdentityReference)(nil), (*v1alpha8.OpenStackIdentityReference)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(a.(*OpenStackIdentityReference), b.(*v1alpha8.OpenStackIdentityReference), 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.AddConversionFunc((*OpenStackMachineSpec)(nil), (*v1alpha8.OpenStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(a.(*OpenStackMachineSpec), b.(*v1alpha8.OpenStackMachineSpec), 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.AddConversionFunc((*PortOpts)(nil), (*v1alpha8.PortOpts)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_PortOpts_To_v1alpha8_PortOpts(a.(*PortOpts), b.(*v1alpha8.PortOpts), 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.AddConversionFunc((*SecurityGroupFilter)(nil), (*v1alpha8.SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_SecurityGroupFilter_To_v1alpha8_SecurityGroupFilter(a.(*SecurityGroupFilter), b.(*v1alpha8.SecurityGroupFilter), 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.AddConversionFunc((*SecurityGroupParam)(nil), (*v1alpha8.SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_SecurityGroupParam_To_v1alpha8_SecurityGroupFilter(a.(*SecurityGroupParam), b.(*v1alpha8.SecurityGroupFilter), scope)
+ if err := s.AddConversionFunc((*SecurityGroupParam)(nil), (*v1beta1.SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_SecurityGroupParam_To_v1beta1_SecurityGroupFilter(a.(*SecurityGroupParam), b.(*v1beta1.SecurityGroupFilter), scope)
}); err != nil {
return err
}
- if err := s.AddConversionFunc((*SecurityGroup)(nil), (*v1alpha8.SecurityGroupStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_SecurityGroup_To_v1alpha8_SecurityGroupStatus(a.(*SecurityGroup), b.(*v1alpha8.SecurityGroupStatus), 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.AddConversionFunc((*SubnetParam)(nil), (*v1alpha8.SubnetFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_SubnetParam_To_v1alpha8_SubnetFilter(a.(*SubnetParam), b.(*v1alpha8.SubnetFilter), scope)
+ if err := s.AddConversionFunc((*SubnetParam)(nil), (*v1beta1.SubnetFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1alpha6_SubnetParam_To_v1beta1_SubnetFilter(a.(*SubnetParam), b.(*v1beta1.SubnetFilter), scope)
}); err != nil {
return err
}
- if err := s.AddConversionFunc((*v1alpha8.BastionStatus)(nil), (*Instance)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_BastionStatus_To_v1alpha6_Instance(a.(*v1alpha8.BastionStatus), b.(*Instance), 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((*v1alpha8.Bastion)(nil), (*Bastion)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_Bastion_To_v1alpha6_Bastion(a.(*v1alpha8.Bastion), b.(*Bastion), 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((*v1alpha8.NetworkStatusWithSubnets)(nil), (*Network)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_NetworkStatusWithSubnets_To_v1alpha6_Network(a.(*v1alpha8.NetworkStatusWithSubnets), b.(*Network), 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((*v1alpha8.NetworkStatus)(nil), (*Network)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_NetworkStatus_To_v1alpha6_Network(a.(*v1alpha8.NetworkStatus), b.(*Network), 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((*v1alpha8.OpenStackClusterSpec)(nil), (*OpenStackClusterSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(a.(*v1alpha8.OpenStackClusterSpec), b.(*OpenStackClusterSpec), 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((*v1alpha8.OpenStackClusterStatus)(nil), (*OpenStackClusterStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackClusterStatus_To_v1alpha6_OpenStackClusterStatus(a.(*v1alpha8.OpenStackClusterStatus), b.(*OpenStackClusterStatus), 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((*v1alpha8.OpenStackMachineSpec)(nil), (*OpenStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(a.(*v1alpha8.OpenStackMachineSpec), b.(*OpenStackMachineSpec), 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((*v1alpha8.OpenStackMachineStatus)(nil), (*OpenStackMachineStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackMachineStatus_To_v1alpha6_OpenStackMachineStatus(a.(*v1alpha8.OpenStackMachineStatus), b.(*OpenStackMachineStatus), 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((*v1alpha8.PortOpts)(nil), (*PortOpts)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_PortOpts_To_v1alpha6_PortOpts(a.(*v1alpha8.PortOpts), b.(*PortOpts), 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((*v1alpha8.SecurityGroupFilter)(nil), (*SecurityGroupParam)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_SecurityGroupFilter_To_v1alpha6_SecurityGroupParam(a.(*v1alpha8.SecurityGroupFilter), b.(*SecurityGroupParam), scope)
+ if err := s.AddConversionFunc((*v1beta1.SecurityGroupFilter)(nil), (*SecurityGroupParam)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupParam(a.(*v1beta1.SecurityGroupFilter), b.(*SecurityGroupParam), scope)
}); err != nil {
return err
}
- if err := s.AddConversionFunc((*v1alpha8.SecurityGroupStatus)(nil), (*SecurityGroup)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_SecurityGroupStatus_To_v1alpha6_SecurityGroup(a.(*v1alpha8.SecurityGroupStatus), b.(*SecurityGroup), scope)
+ 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((*v1alpha8.SubnetFilter)(nil), (*SubnetParam)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_SubnetFilter_To_v1alpha6_SubnetParam(a.(*v1alpha8.SubnetFilter), b.(*SubnetParam), scope)
+ if err := s.AddConversionFunc((*v1beta1.SubnetFilter)(nil), (*SubnetParam)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1beta1_SubnetFilter_To_v1alpha6_SubnetParam(a.(*v1beta1.SubnetFilter), b.(*SubnetParam), scope)
}); err != nil {
return err
}
return nil
}
-func autoConvert_v1alpha6_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalancer(in *APIServerLoadBalancer, out *v1alpha8.APIServerLoadBalancer, s conversion.Scope) error {
+func autoConvert_v1alpha6_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer(in *APIServerLoadBalancer, out *v1beta1.APIServerLoadBalancer, s conversion.Scope) error {
out.Enabled = in.Enabled
out.AdditionalPorts = *(*[]int)(unsafe.Pointer(&in.AdditionalPorts))
out.AllowedCIDRs = *(*[]string)(unsafe.Pointer(&in.AllowedCIDRs))
@@ -420,12 +420,12 @@ func autoConvert_v1alpha6_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalance
return nil
}
-// Convert_v1alpha6_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalancer is an autogenerated conversion function.
-func Convert_v1alpha6_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalancer(in *APIServerLoadBalancer, out *v1alpha8.APIServerLoadBalancer, s conversion.Scope) error {
- return autoConvert_v1alpha6_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalancer(in, out, s)
+// Convert_v1alpha6_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer is an autogenerated conversion function.
+func Convert_v1alpha6_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer(in *APIServerLoadBalancer, out *v1beta1.APIServerLoadBalancer, s conversion.Scope) error {
+ return autoConvert_v1alpha6_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer(in, out, s)
}
-func autoConvert_v1alpha8_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalancer(in *v1alpha8.APIServerLoadBalancer, out *APIServerLoadBalancer, s conversion.Scope) error {
+func autoConvert_v1beta1_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalancer(in *v1beta1.APIServerLoadBalancer, out *APIServerLoadBalancer, s conversion.Scope) error {
out.Enabled = in.Enabled
out.AdditionalPorts = *(*[]int)(unsafe.Pointer(&in.AdditionalPorts))
out.AllowedCIDRs = *(*[]string)(unsafe.Pointer(&in.AllowedCIDRs))
@@ -433,45 +433,45 @@ func autoConvert_v1alpha8_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalance
return nil
}
-// Convert_v1alpha8_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalancer is an autogenerated conversion function.
-func Convert_v1alpha8_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalancer(in *v1alpha8.APIServerLoadBalancer, out *APIServerLoadBalancer, s conversion.Scope) error {
- return autoConvert_v1alpha8_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalancer(in, out, s)
+// Convert_v1beta1_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalancer is an autogenerated conversion function.
+func Convert_v1beta1_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalancer(in *v1beta1.APIServerLoadBalancer, out *APIServerLoadBalancer, s conversion.Scope) error {
+ return autoConvert_v1beta1_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalancer(in, out, s)
}
-func autoConvert_v1alpha6_AddressPair_To_v1alpha8_AddressPair(in *AddressPair, out *v1alpha8.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
return nil
}
-// Convert_v1alpha6_AddressPair_To_v1alpha8_AddressPair is an autogenerated conversion function.
-func Convert_v1alpha6_AddressPair_To_v1alpha8_AddressPair(in *AddressPair, out *v1alpha8.AddressPair, s conversion.Scope) error {
- return autoConvert_v1alpha6_AddressPair_To_v1alpha8_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_v1alpha8_AddressPair_To_v1alpha6_AddressPair(in *v1alpha8.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
return nil
}
-// Convert_v1alpha8_AddressPair_To_v1alpha6_AddressPair is an autogenerated conversion function.
-func Convert_v1alpha8_AddressPair_To_v1alpha6_AddressPair(in *v1alpha8.AddressPair, out *AddressPair, s conversion.Scope) error {
- return autoConvert_v1alpha8_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_v1alpha8_Bastion(in *Bastion, out *v1alpha8.Bastion, s conversion.Scope) error {
+func autoConvert_v1alpha6_Bastion_To_v1beta1_Bastion(in *Bastion, out *v1beta1.Bastion, s conversion.Scope) error {
out.Enabled = in.Enabled
- if err := Convert_v1alpha6_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(&in.Instance, &out.Instance, s); err != nil {
+ if err := Convert_v1alpha6_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(&in.Instance, &out.Instance, s); err != nil {
return err
}
out.AvailabilityZone = in.AvailabilityZone
return nil
}
-func autoConvert_v1alpha8_Bastion_To_v1alpha6_Bastion(in *v1alpha8.Bastion, out *Bastion, s conversion.Scope) error {
+func autoConvert_v1beta1_Bastion_To_v1alpha6_Bastion(in *v1beta1.Bastion, out *Bastion, s conversion.Scope) error {
out.Enabled = in.Enabled
- if err := Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(&in.Instance, &out.Instance, s); err != nil {
+ if err := Convert_v1beta1_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(&in.Instance, &out.Instance, s); err != nil {
return err
}
out.AvailabilityZone = in.AvailabilityZone
@@ -479,55 +479,55 @@ func autoConvert_v1alpha8_Bastion_To_v1alpha6_Bastion(in *v1alpha8.Bastion, out
return nil
}
-func autoConvert_v1alpha6_ExternalRouterIPParam_To_v1alpha8_ExternalRouterIPParam(in *ExternalRouterIPParam, out *v1alpha8.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_v1alpha8_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil {
+ if err := Convert_v1alpha6_SubnetParam_To_v1beta1_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil {
return err
}
return nil
}
-// Convert_v1alpha6_ExternalRouterIPParam_To_v1alpha8_ExternalRouterIPParam is an autogenerated conversion function.
-func Convert_v1alpha6_ExternalRouterIPParam_To_v1alpha8_ExternalRouterIPParam(in *ExternalRouterIPParam, out *v1alpha8.ExternalRouterIPParam, s conversion.Scope) error {
- return autoConvert_v1alpha6_ExternalRouterIPParam_To_v1alpha8_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_v1alpha8_ExternalRouterIPParam_To_v1alpha6_ExternalRouterIPParam(in *v1alpha8.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_v1alpha8_SubnetFilter_To_v1alpha6_SubnetParam(&in.Subnet, &out.Subnet, s); err != nil {
+ if err := Convert_v1beta1_SubnetFilter_To_v1alpha6_SubnetParam(&in.Subnet, &out.Subnet, s); err != nil {
return err
}
return nil
}
-// Convert_v1alpha8_ExternalRouterIPParam_To_v1alpha6_ExternalRouterIPParam is an autogenerated conversion function.
-func Convert_v1alpha8_ExternalRouterIPParam_To_v1alpha6_ExternalRouterIPParam(in *v1alpha8.ExternalRouterIPParam, out *ExternalRouterIPParam, s conversion.Scope) error {
- return autoConvert_v1alpha8_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_v1alpha8_FixedIP(in *FixedIP, out *v1alpha8.FixedIP, s conversion.Scope) error {
- out.Subnet = (*v1alpha8.SubnetFilter)(unsafe.Pointer(in.Subnet))
+func autoConvert_v1alpha6_FixedIP_To_v1beta1_FixedIP(in *FixedIP, out *v1beta1.FixedIP, s conversion.Scope) error {
+ out.Subnet = (*v1beta1.SubnetFilter)(unsafe.Pointer(in.Subnet))
out.IPAddress = in.IPAddress
return nil
}
-// Convert_v1alpha6_FixedIP_To_v1alpha8_FixedIP is an autogenerated conversion function.
-func Convert_v1alpha6_FixedIP_To_v1alpha8_FixedIP(in *FixedIP, out *v1alpha8.FixedIP, s conversion.Scope) error {
- return autoConvert_v1alpha6_FixedIP_To_v1alpha8_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_v1alpha8_FixedIP_To_v1alpha6_FixedIP(in *v1alpha8.FixedIP, out *FixedIP, s conversion.Scope) error {
+func autoConvert_v1beta1_FixedIP_To_v1alpha6_FixedIP(in *v1beta1.FixedIP, out *FixedIP, s conversion.Scope) error {
out.Subnet = (*SubnetFilter)(unsafe.Pointer(in.Subnet))
out.IPAddress = in.IPAddress
return nil
}
-// Convert_v1alpha8_FixedIP_To_v1alpha6_FixedIP is an autogenerated conversion function.
-func Convert_v1alpha8_FixedIP_To_v1alpha6_FixedIP(in *v1alpha8.FixedIP, out *FixedIP, s conversion.Scope) error {
- return autoConvert_v1alpha8_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_v1alpha8_LoadBalancer(in *LoadBalancer, out *v1alpha8.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
@@ -537,12 +537,12 @@ func autoConvert_v1alpha6_LoadBalancer_To_v1alpha8_LoadBalancer(in *LoadBalancer
return nil
}
-// Convert_v1alpha6_LoadBalancer_To_v1alpha8_LoadBalancer is an autogenerated conversion function.
-func Convert_v1alpha6_LoadBalancer_To_v1alpha8_LoadBalancer(in *LoadBalancer, out *v1alpha8.LoadBalancer, s conversion.Scope) error {
- return autoConvert_v1alpha6_LoadBalancer_To_v1alpha8_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_v1alpha8_LoadBalancer_To_v1alpha6_LoadBalancer(in *v1alpha8.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
@@ -552,12 +552,12 @@ func autoConvert_v1alpha8_LoadBalancer_To_v1alpha6_LoadBalancer(in *v1alpha8.Loa
return nil
}
-// Convert_v1alpha8_LoadBalancer_To_v1alpha6_LoadBalancer is an autogenerated conversion function.
-func Convert_v1alpha8_LoadBalancer_To_v1alpha6_LoadBalancer(in *v1alpha8.LoadBalancer, out *LoadBalancer, s conversion.Scope) error {
- return autoConvert_v1alpha8_LoadBalancer_To_v1alpha6_LoadBalancer(in, out, s)
+// Convert_v1beta1_LoadBalancer_To_v1alpha6_LoadBalancer is an autogenerated conversion function.
+func Convert_v1beta1_LoadBalancer_To_v1alpha6_LoadBalancer(in *v1beta1.LoadBalancer, out *LoadBalancer, s conversion.Scope) error {
+ return autoConvert_v1beta1_LoadBalancer_To_v1alpha6_LoadBalancer(in, out, s)
}
-func autoConvert_v1alpha6_NetworkFilter_To_v1alpha8_NetworkFilter(in *NetworkFilter, out *v1alpha8.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
@@ -569,12 +569,12 @@ func autoConvert_v1alpha6_NetworkFilter_To_v1alpha8_NetworkFilter(in *NetworkFil
return nil
}
-// Convert_v1alpha6_NetworkFilter_To_v1alpha8_NetworkFilter is an autogenerated conversion function.
-func Convert_v1alpha6_NetworkFilter_To_v1alpha8_NetworkFilter(in *NetworkFilter, out *v1alpha8.NetworkFilter, s conversion.Scope) error {
- return autoConvert_v1alpha6_NetworkFilter_To_v1alpha8_NetworkFilter(in, out, s)
+// Convert_v1alpha6_NetworkFilter_To_v1beta1_NetworkFilter is an autogenerated conversion function.
+func Convert_v1alpha6_NetworkFilter_To_v1beta1_NetworkFilter(in *NetworkFilter, out *v1beta1.NetworkFilter, s conversion.Scope) error {
+ return autoConvert_v1alpha6_NetworkFilter_To_v1beta1_NetworkFilter(in, out, s)
}
-func autoConvert_v1alpha8_NetworkFilter_To_v1alpha6_NetworkFilter(in *v1alpha8.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
@@ -586,50 +586,50 @@ func autoConvert_v1alpha8_NetworkFilter_To_v1alpha6_NetworkFilter(in *v1alpha8.N
return nil
}
-// Convert_v1alpha8_NetworkFilter_To_v1alpha6_NetworkFilter is an autogenerated conversion function.
-func Convert_v1alpha8_NetworkFilter_To_v1alpha6_NetworkFilter(in *v1alpha8.NetworkFilter, out *NetworkFilter, s conversion.Scope) error {
- return autoConvert_v1alpha8_NetworkFilter_To_v1alpha6_NetworkFilter(in, out, s)
+// Convert_v1beta1_NetworkFilter_To_v1alpha6_NetworkFilter is an autogenerated conversion function.
+func Convert_v1beta1_NetworkFilter_To_v1alpha6_NetworkFilter(in *v1beta1.NetworkFilter, out *NetworkFilter, s conversion.Scope) error {
+ return autoConvert_v1beta1_NetworkFilter_To_v1alpha6_NetworkFilter(in, out, s)
}
-func autoConvert_v1alpha6_OpenStackCluster_To_v1alpha8_OpenStackCluster(in *OpenStackCluster, out *v1alpha8.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_v1alpha8_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_v1alpha8_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_v1alpha8_OpenStackCluster is an autogenerated conversion function.
-func Convert_v1alpha6_OpenStackCluster_To_v1alpha8_OpenStackCluster(in *OpenStackCluster, out *v1alpha8.OpenStackCluster, s conversion.Scope) error {
- return autoConvert_v1alpha6_OpenStackCluster_To_v1alpha8_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_v1alpha8_OpenStackCluster_To_v1alpha6_OpenStackCluster(in *v1alpha8.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_v1alpha8_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_v1alpha8_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_v1alpha8_OpenStackCluster_To_v1alpha6_OpenStackCluster is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackCluster_To_v1alpha6_OpenStackCluster(in *v1alpha8.OpenStackCluster, out *OpenStackCluster, s conversion.Scope) error {
- return autoConvert_v1alpha8_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_v1alpha8_OpenStackClusterList(in *OpenStackClusterList, out *v1alpha8.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([]v1alpha8.OpenStackCluster, len(*in))
+ *out = make([]v1beta1.OpenStackCluster, len(*in))
for i := range *in {
- if err := Convert_v1alpha6_OpenStackCluster_To_v1alpha8_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
}
}
@@ -639,18 +639,18 @@ func autoConvert_v1alpha6_OpenStackClusterList_To_v1alpha8_OpenStackClusterList(
return nil
}
-// Convert_v1alpha6_OpenStackClusterList_To_v1alpha8_OpenStackClusterList is an autogenerated conversion function.
-func Convert_v1alpha6_OpenStackClusterList_To_v1alpha8_OpenStackClusterList(in *OpenStackClusterList, out *v1alpha8.OpenStackClusterList, s conversion.Scope) error {
- return autoConvert_v1alpha6_OpenStackClusterList_To_v1alpha8_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_v1alpha8_OpenStackClusterList_To_v1alpha6_OpenStackClusterList(in *v1alpha8.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_v1alpha8_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
}
}
@@ -660,24 +660,24 @@ func autoConvert_v1alpha8_OpenStackClusterList_To_v1alpha6_OpenStackClusterList(
return nil
}
-// Convert_v1alpha8_OpenStackClusterList_To_v1alpha6_OpenStackClusterList is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackClusterList_To_v1alpha6_OpenStackClusterList(in *v1alpha8.OpenStackClusterList, out *OpenStackClusterList, s conversion.Scope) error {
- return autoConvert_v1alpha8_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_v1alpha8_OpenStackClusterSpec(in *OpenStackClusterSpec, out *v1alpha8.OpenStackClusterSpec, s conversion.Scope) error {
+func autoConvert_v1alpha6_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *OpenStackClusterSpec, out *v1beta1.OpenStackClusterSpec, s conversion.Scope) error {
out.CloudName = in.CloudName
// WARNING: in.NodeCIDR requires manual conversion: does not exist in peer-type
- if err := Convert_v1alpha6_NetworkFilter_To_v1alpha8_NetworkFilter(&in.Network, &out.Network, s); err != nil {
+ if err := Convert_v1alpha6_NetworkFilter_To_v1beta1_NetworkFilter(&in.Network, &out.Network, s); err != nil {
return err
}
// 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([]v1alpha8.ExternalRouterIPParam, len(*in))
+ *out = make([]v1beta1.ExternalRouterIPParam, len(*in))
for i := range *in {
- if err := Convert_v1alpha6_ExternalRouterIPParam_To_v1alpha8_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
}
}
@@ -685,14 +685,14 @@ func autoConvert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(
out.ExternalRouterIPs = nil
}
// WARNING: in.ExternalNetworkID requires manual conversion: does not exist in peer-type
- if err := Convert_v1alpha6_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil {
+ if err := Convert_v1alpha6_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil {
return err
}
out.DisableAPIServerFloatingIP = in.DisableAPIServerFloatingIP
out.APIServerFloatingIP = in.APIServerFloatingIP
out.APIServerFixedIP = in.APIServerFixedIP
out.APIServerPort = in.APIServerPort
- // WARNING: in.ManagedSecurityGroups requires manual conversion: inconvertible types (bool vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8.ManagedSecurityGroups)
+ // 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
out.DisablePortSecurity = in.DisablePortSecurity
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
@@ -701,8 +701,8 @@ func autoConvert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(
out.ControlPlaneOmitAvailabilityZone = in.ControlPlaneOmitAvailabilityZone
if in.Bastion != nil {
in, out := &in.Bastion, &out.Bastion
- *out = new(v1alpha8.Bastion)
- if err := Convert_v1alpha6_Bastion_To_v1alpha8_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 {
@@ -710,8 +710,8 @@ func autoConvert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(
}
if in.IdentityRef != nil {
in, out := &in.IdentityRef, &out.IdentityRef
- *out = new(v1alpha8.OpenStackIdentityReference)
- if err := Convert_v1alpha6_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(*in, *out, s); err != nil {
+ *out = new(v1beta1.OpenStackIdentityReference)
+ if err := Convert_v1alpha6_OpenStackIdentityReference_To_v1beta1_OpenStackIdentityReference(*in, *out, s); err != nil {
return err
}
} else {
@@ -720,11 +720,11 @@ func autoConvert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(
return nil
}
-func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(in *v1alpha8.OpenStackClusterSpec, out *OpenStackClusterSpec, s conversion.Scope) error {
+func autoConvert_v1beta1_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(in *v1beta1.OpenStackClusterSpec, out *OpenStackClusterSpec, s conversion.Scope) error {
out.CloudName = in.CloudName
// 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_v1alpha8_NetworkFilter_To_v1alpha6_NetworkFilter(&in.Network, &out.Network, s); err != nil {
+ if err := Convert_v1beta1_NetworkFilter_To_v1alpha6_NetworkFilter(&in.Network, &out.Network, s); err != nil {
return err
}
// WARNING: in.Subnets requires manual conversion: does not exist in peer-type
@@ -733,7 +733,7 @@ func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(
in, out := &in.ExternalRouterIPs, &out.ExternalRouterIPs
*out = make([]ExternalRouterIPParam, len(*in))
for i := range *in {
- if err := Convert_v1alpha8_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
}
}
@@ -742,14 +742,14 @@ func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(
}
// WARNING: in.ExternalNetwork requires manual conversion: does not exist in peer-type
// WARNING: in.DisableExternalNetwork requires manual conversion: does not exist in peer-type
- if err := Convert_v1alpha8_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil {
+ if err := Convert_v1beta1_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil {
return err
}
out.DisableAPIServerFloatingIP = in.DisableAPIServerFloatingIP
out.APIServerFloatingIP = in.APIServerFloatingIP
out.APIServerFixedIP = in.APIServerFixedIP
out.APIServerPort = in.APIServerPort
- // WARNING: in.ManagedSecurityGroups requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8.ManagedSecurityGroups vs bool)
+ // WARNING: in.ManagedSecurityGroups requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ManagedSecurityGroups vs bool)
out.DisablePortSecurity = in.DisablePortSecurity
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
out.ControlPlaneEndpoint = in.ControlPlaneEndpoint
@@ -758,7 +758,7 @@ func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(
if in.Bastion != nil {
in, out := &in.Bastion, &out.Bastion
*out = new(Bastion)
- if err := Convert_v1alpha8_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 {
@@ -767,7 +767,7 @@ func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(
if in.IdentityRef != nil {
in, out := &in.IdentityRef, &out.IdentityRef
*out = new(OpenStackIdentityReference)
- if err := Convert_v1alpha8_OpenStackIdentityReference_To_v1alpha6_OpenStackIdentityReference(*in, *out, s); err != nil {
+ if err := Convert_v1beta1_OpenStackIdentityReference_To_v1alpha6_OpenStackIdentityReference(*in, *out, s); err != nil {
return err
}
} else {
@@ -776,12 +776,12 @@ func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(
return nil
}
-func autoConvert_v1alpha6_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterStatus(in *OpenStackClusterStatus, out *v1alpha8.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(v1alpha8.NetworkStatusWithSubnets)
- if err := Convert_v1alpha6_Network_To_v1alpha8_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 {
@@ -789,18 +789,18 @@ func autoConvert_v1alpha6_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterSta
}
if in.ExternalNetwork != nil {
in, out := &in.ExternalNetwork, &out.ExternalNetwork
- *out = new(v1alpha8.NetworkStatus)
- if err := Convert_v1alpha6_Network_To_v1alpha8_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.FailureDomains = *(*apiv1beta1.FailureDomains)(unsafe.Pointer(&in.FailureDomains))
if in.ControlPlaneSecurityGroup != nil {
in, out := &in.ControlPlaneSecurityGroup, &out.ControlPlaneSecurityGroup
- *out = new(v1alpha8.SecurityGroupStatus)
- if err := Convert_v1alpha6_SecurityGroup_To_v1alpha8_SecurityGroupStatus(*in, *out, s); err != nil {
+ *out = new(v1beta1.SecurityGroupStatus)
+ if err := Convert_v1alpha6_SecurityGroup_To_v1beta1_SecurityGroupStatus(*in, *out, s); err != nil {
return err
}
} else {
@@ -808,8 +808,8 @@ func autoConvert_v1alpha6_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterSta
}
if in.WorkerSecurityGroup != nil {
in, out := &in.WorkerSecurityGroup, &out.WorkerSecurityGroup
- *out = new(v1alpha8.SecurityGroupStatus)
- if err := Convert_v1alpha6_SecurityGroup_To_v1alpha8_SecurityGroupStatus(*in, *out, s); err != nil {
+ *out = new(v1beta1.SecurityGroupStatus)
+ if err := Convert_v1alpha6_SecurityGroup_To_v1beta1_SecurityGroupStatus(*in, *out, s); err != nil {
return err
}
} else {
@@ -817,8 +817,8 @@ func autoConvert_v1alpha6_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterSta
}
if in.BastionSecurityGroup != nil {
in, out := &in.BastionSecurityGroup, &out.BastionSecurityGroup
- *out = new(v1alpha8.SecurityGroupStatus)
- if err := Convert_v1alpha6_SecurityGroup_To_v1alpha8_SecurityGroupStatus(*in, *out, s); err != nil {
+ *out = new(v1beta1.SecurityGroupStatus)
+ if err := Convert_v1alpha6_SecurityGroup_To_v1beta1_SecurityGroupStatus(*in, *out, s); err != nil {
return err
}
} else {
@@ -826,8 +826,8 @@ func autoConvert_v1alpha6_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterSta
}
if in.Bastion != nil {
in, out := &in.Bastion, &out.Bastion
- *out = new(v1alpha8.BastionStatus)
- if err := Convert_v1alpha6_Instance_To_v1alpha8_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 {
@@ -838,12 +838,12 @@ func autoConvert_v1alpha6_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterSta
return nil
}
-func autoConvert_v1alpha8_OpenStackClusterStatus_To_v1alpha6_OpenStackClusterStatus(in *v1alpha8.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_v1alpha8_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 {
@@ -852,7 +852,7 @@ func autoConvert_v1alpha8_OpenStackClusterStatus_To_v1alpha6_OpenStackClusterSta
if in.ExternalNetwork != nil {
in, out := &in.ExternalNetwork, &out.ExternalNetwork
*out = new(Network)
- if err := Convert_v1alpha8_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 {
@@ -860,11 +860,11 @@ func autoConvert_v1alpha8_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.FailureDomains = *(*apiv1beta1.FailureDomains)(unsafe.Pointer(&in.FailureDomains))
if in.ControlPlaneSecurityGroup != nil {
in, out := &in.ControlPlaneSecurityGroup, &out.ControlPlaneSecurityGroup
*out = new(SecurityGroup)
- if err := Convert_v1alpha8_SecurityGroupStatus_To_v1alpha6_SecurityGroup(*in, *out, s); err != nil {
+ if err := Convert_v1beta1_SecurityGroupStatus_To_v1alpha6_SecurityGroup(*in, *out, s); err != nil {
return err
}
} else {
@@ -873,7 +873,7 @@ func autoConvert_v1alpha8_OpenStackClusterStatus_To_v1alpha6_OpenStackClusterSta
if in.WorkerSecurityGroup != nil {
in, out := &in.WorkerSecurityGroup, &out.WorkerSecurityGroup
*out = new(SecurityGroup)
- if err := Convert_v1alpha8_SecurityGroupStatus_To_v1alpha6_SecurityGroup(*in, *out, s); err != nil {
+ if err := Convert_v1beta1_SecurityGroupStatus_To_v1alpha6_SecurityGroup(*in, *out, s); err != nil {
return err
}
} else {
@@ -882,7 +882,7 @@ func autoConvert_v1alpha8_OpenStackClusterStatus_To_v1alpha6_OpenStackClusterSta
if in.BastionSecurityGroup != nil {
in, out := &in.BastionSecurityGroup, &out.BastionSecurityGroup
*out = new(SecurityGroup)
- if err := Convert_v1alpha8_SecurityGroupStatus_To_v1alpha6_SecurityGroup(*in, *out, s); err != nil {
+ if err := Convert_v1beta1_SecurityGroupStatus_To_v1alpha6_SecurityGroup(*in, *out, s); err != nil {
return err
}
} else {
@@ -891,7 +891,7 @@ func autoConvert_v1alpha8_OpenStackClusterStatus_To_v1alpha6_OpenStackClusterSta
if in.Bastion != nil {
in, out := &in.Bastion, &out.Bastion
*out = new(Instance)
- if err := Convert_v1alpha8_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 {
@@ -902,39 +902,39 @@ func autoConvert_v1alpha8_OpenStackClusterStatus_To_v1alpha6_OpenStackClusterSta
return nil
}
-func autoConvert_v1alpha6_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate(in *OpenStackClusterTemplate, out *v1alpha8.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_v1alpha8_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_v1alpha8_OpenStackClusterTemplate is an autogenerated conversion function.
-func Convert_v1alpha6_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate(in *OpenStackClusterTemplate, out *v1alpha8.OpenStackClusterTemplate, s conversion.Scope) error {
- return autoConvert_v1alpha6_OpenStackClusterTemplate_To_v1alpha8_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_v1alpha8_OpenStackClusterTemplate_To_v1alpha6_OpenStackClusterTemplate(in *v1alpha8.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_v1alpha8_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_v1alpha8_OpenStackClusterTemplate_To_v1alpha6_OpenStackClusterTemplate is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackClusterTemplate_To_v1alpha6_OpenStackClusterTemplate(in *v1alpha8.OpenStackClusterTemplate, out *OpenStackClusterTemplate, s conversion.Scope) error {
- return autoConvert_v1alpha8_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_v1alpha8_OpenStackClusterTemplateList(in *OpenStackClusterTemplateList, out *v1alpha8.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([]v1alpha8.OpenStackClusterTemplate, len(*in))
+ *out = make([]v1beta1.OpenStackClusterTemplate, len(*in))
for i := range *in {
- if err := Convert_v1alpha6_OpenStackClusterTemplate_To_v1alpha8_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
}
}
@@ -944,18 +944,18 @@ func autoConvert_v1alpha6_OpenStackClusterTemplateList_To_v1alpha8_OpenStackClus
return nil
}
-// Convert_v1alpha6_OpenStackClusterTemplateList_To_v1alpha8_OpenStackClusterTemplateList is an autogenerated conversion function.
-func Convert_v1alpha6_OpenStackClusterTemplateList_To_v1alpha8_OpenStackClusterTemplateList(in *OpenStackClusterTemplateList, out *v1alpha8.OpenStackClusterTemplateList, s conversion.Scope) error {
- return autoConvert_v1alpha6_OpenStackClusterTemplateList_To_v1alpha8_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_v1alpha8_OpenStackClusterTemplateList_To_v1alpha6_OpenStackClusterTemplateList(in *v1alpha8.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_v1alpha8_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
}
}
@@ -965,114 +965,114 @@ func autoConvert_v1alpha8_OpenStackClusterTemplateList_To_v1alpha6_OpenStackClus
return nil
}
-// Convert_v1alpha8_OpenStackClusterTemplateList_To_v1alpha6_OpenStackClusterTemplateList is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackClusterTemplateList_To_v1alpha6_OpenStackClusterTemplateList(in *v1alpha8.OpenStackClusterTemplateList, out *OpenStackClusterTemplateList, s conversion.Scope) error {
- return autoConvert_v1alpha8_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_v1alpha8_OpenStackClusterTemplateResource(in *OpenStackClusterTemplateResource, out *v1alpha8.OpenStackClusterTemplateResource, s conversion.Scope) error {
- if err := Convert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_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_v1alpha8_OpenStackClusterTemplateResource is an autogenerated conversion function.
-func Convert_v1alpha6_OpenStackClusterTemplateResource_To_v1alpha8_OpenStackClusterTemplateResource(in *OpenStackClusterTemplateResource, out *v1alpha8.OpenStackClusterTemplateResource, s conversion.Scope) error {
- return autoConvert_v1alpha6_OpenStackClusterTemplateResource_To_v1alpha8_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_v1alpha8_OpenStackClusterTemplateResource_To_v1alpha6_OpenStackClusterTemplateResource(in *v1alpha8.OpenStackClusterTemplateResource, out *OpenStackClusterTemplateResource, s conversion.Scope) error {
- if err := Convert_v1alpha8_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_v1alpha8_OpenStackClusterTemplateResource_To_v1alpha6_OpenStackClusterTemplateResource is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackClusterTemplateResource_To_v1alpha6_OpenStackClusterTemplateResource(in *v1alpha8.OpenStackClusterTemplateResource, out *OpenStackClusterTemplateResource, s conversion.Scope) error {
- return autoConvert_v1alpha8_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_v1alpha8_OpenStackClusterTemplateSpec(in *OpenStackClusterTemplateSpec, out *v1alpha8.OpenStackClusterTemplateSpec, s conversion.Scope) error {
- if err := Convert_v1alpha6_OpenStackClusterTemplateResource_To_v1alpha8_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_v1alpha8_OpenStackClusterTemplateSpec is an autogenerated conversion function.
-func Convert_v1alpha6_OpenStackClusterTemplateSpec_To_v1alpha8_OpenStackClusterTemplateSpec(in *OpenStackClusterTemplateSpec, out *v1alpha8.OpenStackClusterTemplateSpec, s conversion.Scope) error {
- return autoConvert_v1alpha6_OpenStackClusterTemplateSpec_To_v1alpha8_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_v1alpha8_OpenStackClusterTemplateSpec_To_v1alpha6_OpenStackClusterTemplateSpec(in *v1alpha8.OpenStackClusterTemplateSpec, out *OpenStackClusterTemplateSpec, s conversion.Scope) error {
- if err := Convert_v1alpha8_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_v1alpha8_OpenStackClusterTemplateSpec_To_v1alpha6_OpenStackClusterTemplateSpec is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackClusterTemplateSpec_To_v1alpha6_OpenStackClusterTemplateSpec(in *v1alpha8.OpenStackClusterTemplateSpec, out *OpenStackClusterTemplateSpec, s conversion.Scope) error {
- return autoConvert_v1alpha8_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_v1alpha8_OpenStackIdentityReference(in *OpenStackIdentityReference, out *v1alpha8.OpenStackIdentityReference, s conversion.Scope) error {
+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
}
-func autoConvert_v1alpha8_OpenStackIdentityReference_To_v1alpha6_OpenStackIdentityReference(in *v1alpha8.OpenStackIdentityReference, out *OpenStackIdentityReference, s conversion.Scope) error {
+func autoConvert_v1beta1_OpenStackIdentityReference_To_v1alpha6_OpenStackIdentityReference(in *v1beta1.OpenStackIdentityReference, out *OpenStackIdentityReference, s conversion.Scope) error {
out.Name = in.Name
return nil
}
-// Convert_v1alpha8_OpenStackIdentityReference_To_v1alpha6_OpenStackIdentityReference is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackIdentityReference_To_v1alpha6_OpenStackIdentityReference(in *v1alpha8.OpenStackIdentityReference, out *OpenStackIdentityReference, s conversion.Scope) error {
- return autoConvert_v1alpha8_OpenStackIdentityReference_To_v1alpha6_OpenStackIdentityReference(in, out, s)
+// Convert_v1beta1_OpenStackIdentityReference_To_v1alpha6_OpenStackIdentityReference is an autogenerated conversion function.
+func Convert_v1beta1_OpenStackIdentityReference_To_v1alpha6_OpenStackIdentityReference(in *v1beta1.OpenStackIdentityReference, out *OpenStackIdentityReference, s conversion.Scope) error {
+ return autoConvert_v1beta1_OpenStackIdentityReference_To_v1alpha6_OpenStackIdentityReference(in, out, s)
}
-func autoConvert_v1alpha6_OpenStackMachine_To_v1alpha8_OpenStackMachine(in *OpenStackMachine, out *v1alpha8.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_v1alpha8_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_v1alpha8_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_v1alpha8_OpenStackMachine is an autogenerated conversion function.
-func Convert_v1alpha6_OpenStackMachine_To_v1alpha8_OpenStackMachine(in *OpenStackMachine, out *v1alpha8.OpenStackMachine, s conversion.Scope) error {
- return autoConvert_v1alpha6_OpenStackMachine_To_v1alpha8_OpenStackMachine(in, out, s)
+// Convert_v1alpha6_OpenStackMachine_To_v1beta1_OpenStackMachine is an autogenerated conversion function.
+func Convert_v1alpha6_OpenStackMachine_To_v1beta1_OpenStackMachine(in *OpenStackMachine, out *v1beta1.OpenStackMachine, s conversion.Scope) error {
+ return autoConvert_v1alpha6_OpenStackMachine_To_v1beta1_OpenStackMachine(in, out, s)
}
-func autoConvert_v1alpha8_OpenStackMachine_To_v1alpha6_OpenStackMachine(in *v1alpha8.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_v1alpha8_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_v1alpha8_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_v1alpha8_OpenStackMachine_To_v1alpha6_OpenStackMachine is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackMachine_To_v1alpha6_OpenStackMachine(in *v1alpha8.OpenStackMachine, out *OpenStackMachine, s conversion.Scope) error {
- return autoConvert_v1alpha8_OpenStackMachine_To_v1alpha6_OpenStackMachine(in, out, s)
+// Convert_v1beta1_OpenStackMachine_To_v1alpha6_OpenStackMachine is an autogenerated conversion function.
+func Convert_v1beta1_OpenStackMachine_To_v1alpha6_OpenStackMachine(in *v1beta1.OpenStackMachine, out *OpenStackMachine, s conversion.Scope) error {
+ return autoConvert_v1beta1_OpenStackMachine_To_v1alpha6_OpenStackMachine(in, out, s)
}
-func autoConvert_v1alpha6_OpenStackMachineList_To_v1alpha8_OpenStackMachineList(in *OpenStackMachineList, out *v1alpha8.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([]v1alpha8.OpenStackMachine, len(*in))
+ *out = make([]v1beta1.OpenStackMachine, len(*in))
for i := range *in {
- if err := Convert_v1alpha6_OpenStackMachine_To_v1alpha8_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
}
}
@@ -1082,18 +1082,18 @@ func autoConvert_v1alpha6_OpenStackMachineList_To_v1alpha8_OpenStackMachineList(
return nil
}
-// Convert_v1alpha6_OpenStackMachineList_To_v1alpha8_OpenStackMachineList is an autogenerated conversion function.
-func Convert_v1alpha6_OpenStackMachineList_To_v1alpha8_OpenStackMachineList(in *OpenStackMachineList, out *v1alpha8.OpenStackMachineList, s conversion.Scope) error {
- return autoConvert_v1alpha6_OpenStackMachineList_To_v1alpha8_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_v1alpha8_OpenStackMachineList_To_v1alpha6_OpenStackMachineList(in *v1alpha8.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_v1alpha8_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
}
}
@@ -1103,25 +1103,25 @@ func autoConvert_v1alpha8_OpenStackMachineList_To_v1alpha6_OpenStackMachineList(
return nil
}
-// Convert_v1alpha8_OpenStackMachineList_To_v1alpha6_OpenStackMachineList is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackMachineList_To_v1alpha6_OpenStackMachineList(in *v1alpha8.OpenStackMachineList, out *OpenStackMachineList, s conversion.Scope) error {
- return autoConvert_v1alpha8_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_v1alpha8_OpenStackMachineSpec(in *OpenStackMachineSpec, out *v1alpha8.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
out.Flavor = in.Flavor
- // WARNING: in.Image requires manual conversion: inconvertible types (string vs sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8.ImageFilter)
+ // WARNING: in.Image requires manual conversion: inconvertible types (string vs sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ImageFilter)
// 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([]v1alpha8.PortOpts, len(*in))
+ *out = make([]v1beta1.PortOpts, len(*in))
for i := range *in {
- if err := Convert_v1alpha6_PortOpts_To_v1alpha8_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
}
}
@@ -1132,9 +1132,9 @@ func autoConvert_v1alpha6_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(
// WARNING: in.FloatingIP requires manual conversion: does not exist in peer-type
if in.SecurityGroups != nil {
in, out := &in.SecurityGroups, &out.SecurityGroups
- *out = make([]v1alpha8.SecurityGroupFilter, len(*in))
+ *out = make([]v1beta1.SecurityGroupFilter, len(*in))
for i := range *in {
- if err := Convert_v1alpha6_SecurityGroupParam_To_v1alpha8_SecurityGroupFilter(&(*in)[i], &(*out)[i], s); err != nil {
+ if err := Convert_v1alpha6_SecurityGroupParam_To_v1beta1_SecurityGroupFilter(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -1143,14 +1143,14 @@ func autoConvert_v1alpha6_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(
}
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/v1alpha8.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 = (*v1alpha8.RootVolume)(unsafe.Pointer(in.RootVolume))
+ out.RootVolume = (*v1beta1.RootVolume)(unsafe.Pointer(in.RootVolume))
// WARNING: in.ServerGroupID requires manual conversion: does not exist in peer-type
if in.IdentityRef != nil {
in, out := &in.IdentityRef, &out.IdentityRef
- *out = new(v1alpha8.OpenStackIdentityReference)
- if err := Convert_v1alpha6_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(*in, *out, s); err != nil {
+ *out = new(v1beta1.OpenStackIdentityReference)
+ if err := Convert_v1alpha6_OpenStackIdentityReference_To_v1beta1_OpenStackIdentityReference(*in, *out, s); err != nil {
return err
}
} else {
@@ -1159,18 +1159,18 @@ func autoConvert_v1alpha6_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(
return nil
}
-func autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(in *v1alpha8.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
- // WARNING: in.Image requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8.ImageFilter vs string)
+ // WARNING: in.Image requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ImageFilter 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_v1alpha8_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
}
}
@@ -1181,7 +1181,7 @@ func autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(
in, out := &in.SecurityGroups, &out.SecurityGroups
*out = make([]SecurityGroupParam, len(*in))
for i := range *in {
- if err := Convert_v1alpha8_SecurityGroupFilter_To_v1alpha6_SecurityGroupParam(&(*in)[i], &(*out)[i], s); err != nil {
+ if err := Convert_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupParam(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -1190,7 +1190,7 @@ func autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(
}
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/v1alpha8.ServerMetadata vs map[string]string)
+ // 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))
// WARNING: in.AdditionalBlockDevices requires manual conversion: does not exist in peer-type
@@ -1198,7 +1198,7 @@ func autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(
if in.IdentityRef != nil {
in, out := &in.IdentityRef, &out.IdentityRef
*out = new(OpenStackIdentityReference)
- if err := Convert_v1alpha8_OpenStackIdentityReference_To_v1alpha6_OpenStackIdentityReference(*in, *out, s); err != nil {
+ if err := Convert_v1beta1_OpenStackIdentityReference_To_v1alpha6_OpenStackIdentityReference(*in, *out, s); err != nil {
return err
}
} else {
@@ -1207,22 +1207,22 @@ func autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(
return nil
}
-func autoConvert_v1alpha6_OpenStackMachineStatus_To_v1alpha8_OpenStackMachineStatus(in *OpenStackMachineStatus, out *v1alpha8.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 = (*v1alpha8.InstanceState)(unsafe.Pointer(in.InstanceState))
+ 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_v1alpha8_OpenStackMachineStatus is an autogenerated conversion function.
-func Convert_v1alpha6_OpenStackMachineStatus_To_v1alpha8_OpenStackMachineStatus(in *OpenStackMachineStatus, out *v1alpha8.OpenStackMachineStatus, s conversion.Scope) error {
- return autoConvert_v1alpha6_OpenStackMachineStatus_To_v1alpha8_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_v1alpha8_OpenStackMachineStatus_To_v1alpha6_OpenStackMachineStatus(in *v1alpha8.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))
out.InstanceState = (*InstanceState)(unsafe.Pointer(in.InstanceState))
@@ -1230,43 +1230,43 @@ func autoConvert_v1alpha8_OpenStackMachineStatus_To_v1alpha6_OpenStackMachineSta
// WARNING: in.DependentResources 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
}
-func autoConvert_v1alpha6_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate(in *OpenStackMachineTemplate, out *v1alpha8.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_v1alpha8_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_v1alpha8_OpenStackMachineTemplate is an autogenerated conversion function.
-func Convert_v1alpha6_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate(in *OpenStackMachineTemplate, out *v1alpha8.OpenStackMachineTemplate, s conversion.Scope) error {
- return autoConvert_v1alpha6_OpenStackMachineTemplate_To_v1alpha8_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_v1alpha8_OpenStackMachineTemplate_To_v1alpha6_OpenStackMachineTemplate(in *v1alpha8.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_v1alpha8_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_v1alpha8_OpenStackMachineTemplate_To_v1alpha6_OpenStackMachineTemplate is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackMachineTemplate_To_v1alpha6_OpenStackMachineTemplate(in *v1alpha8.OpenStackMachineTemplate, out *OpenStackMachineTemplate, s conversion.Scope) error {
- return autoConvert_v1alpha8_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_v1alpha8_OpenStackMachineTemplateList(in *OpenStackMachineTemplateList, out *v1alpha8.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([]v1alpha8.OpenStackMachineTemplate, len(*in))
+ *out = make([]v1beta1.OpenStackMachineTemplate, len(*in))
for i := range *in {
- if err := Convert_v1alpha6_OpenStackMachineTemplate_To_v1alpha8_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
}
}
@@ -1276,18 +1276,18 @@ func autoConvert_v1alpha6_OpenStackMachineTemplateList_To_v1alpha8_OpenStackMach
return nil
}
-// Convert_v1alpha6_OpenStackMachineTemplateList_To_v1alpha8_OpenStackMachineTemplateList is an autogenerated conversion function.
-func Convert_v1alpha6_OpenStackMachineTemplateList_To_v1alpha8_OpenStackMachineTemplateList(in *OpenStackMachineTemplateList, out *v1alpha8.OpenStackMachineTemplateList, s conversion.Scope) error {
- return autoConvert_v1alpha6_OpenStackMachineTemplateList_To_v1alpha8_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_v1alpha8_OpenStackMachineTemplateList_To_v1alpha6_OpenStackMachineTemplateList(in *v1alpha8.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_v1alpha8_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
}
}
@@ -1297,92 +1297,92 @@ func autoConvert_v1alpha8_OpenStackMachineTemplateList_To_v1alpha6_OpenStackMach
return nil
}
-// Convert_v1alpha8_OpenStackMachineTemplateList_To_v1alpha6_OpenStackMachineTemplateList is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackMachineTemplateList_To_v1alpha6_OpenStackMachineTemplateList(in *v1alpha8.OpenStackMachineTemplateList, out *OpenStackMachineTemplateList, s conversion.Scope) error {
- return autoConvert_v1alpha8_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_v1alpha8_OpenStackMachineTemplateResource(in *OpenStackMachineTemplateResource, out *v1alpha8.OpenStackMachineTemplateResource, s conversion.Scope) error {
- if err := Convert_v1alpha6_OpenStackMachineSpec_To_v1alpha8_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_v1alpha8_OpenStackMachineTemplateResource is an autogenerated conversion function.
-func Convert_v1alpha6_OpenStackMachineTemplateResource_To_v1alpha8_OpenStackMachineTemplateResource(in *OpenStackMachineTemplateResource, out *v1alpha8.OpenStackMachineTemplateResource, s conversion.Scope) error {
- return autoConvert_v1alpha6_OpenStackMachineTemplateResource_To_v1alpha8_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_v1alpha8_OpenStackMachineTemplateResource_To_v1alpha6_OpenStackMachineTemplateResource(in *v1alpha8.OpenStackMachineTemplateResource, out *OpenStackMachineTemplateResource, s conversion.Scope) error {
- if err := Convert_v1alpha8_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_v1alpha8_OpenStackMachineTemplateResource_To_v1alpha6_OpenStackMachineTemplateResource is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackMachineTemplateResource_To_v1alpha6_OpenStackMachineTemplateResource(in *v1alpha8.OpenStackMachineTemplateResource, out *OpenStackMachineTemplateResource, s conversion.Scope) error {
- return autoConvert_v1alpha8_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_v1alpha8_OpenStackMachineTemplateSpec(in *OpenStackMachineTemplateSpec, out *v1alpha8.OpenStackMachineTemplateSpec, s conversion.Scope) error {
- if err := Convert_v1alpha6_OpenStackMachineTemplateResource_To_v1alpha8_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_v1alpha8_OpenStackMachineTemplateSpec is an autogenerated conversion function.
-func Convert_v1alpha6_OpenStackMachineTemplateSpec_To_v1alpha8_OpenStackMachineTemplateSpec(in *OpenStackMachineTemplateSpec, out *v1alpha8.OpenStackMachineTemplateSpec, s conversion.Scope) error {
- return autoConvert_v1alpha6_OpenStackMachineTemplateSpec_To_v1alpha8_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_v1alpha8_OpenStackMachineTemplateSpec_To_v1alpha6_OpenStackMachineTemplateSpec(in *v1alpha8.OpenStackMachineTemplateSpec, out *OpenStackMachineTemplateSpec, s conversion.Scope) error {
- if err := Convert_v1alpha8_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_v1alpha8_OpenStackMachineTemplateSpec_To_v1alpha6_OpenStackMachineTemplateSpec is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackMachineTemplateSpec_To_v1alpha6_OpenStackMachineTemplateSpec(in *v1alpha8.OpenStackMachineTemplateSpec, out *OpenStackMachineTemplateSpec, s conversion.Scope) error {
- return autoConvert_v1alpha8_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_v1alpha8_PortOpts(in *PortOpts, out *v1alpha8.PortOpts, s conversion.Scope) error {
- out.Network = (*v1alpha8.NetworkFilter)(unsafe.Pointer(in.Network))
+func autoConvert_v1alpha6_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *v1beta1.PortOpts, s conversion.Scope) error {
+ out.Network = (*v1beta1.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 = *(*[]v1alpha8.FixedIP)(unsafe.Pointer(&in.FixedIPs))
+ out.FixedIPs = *(*[]v1beta1.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([]v1alpha8.SecurityGroupFilter, len(*in))
+ *out = make([]v1beta1.SecurityGroupFilter, len(*in))
for i := range *in {
- if err := Convert_v1alpha6_SecurityGroupParam_To_v1alpha8_SecurityGroupFilter(&(*in)[i], &(*out)[i], s); err != nil {
+ if err := Convert_v1alpha6_SecurityGroupParam_To_v1beta1_SecurityGroupFilter(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.SecurityGroupFilters = nil
}
- out.AllowedAddressPairs = *(*[]v1alpha8.AddressPair)(unsafe.Pointer(&in.AllowedAddressPairs))
+ out.AllowedAddressPairs = *(*[]v1beta1.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 (map[string]string vs sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8.BindingProfile)
+ // WARNING: in.Profile requires manual conversion: inconvertible types (map[string]string vs sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.BindingProfile)
out.DisablePortSecurity = (*bool)(unsafe.Pointer(in.DisablePortSecurity))
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
- out.ValueSpecs = *(*[]v1alpha8.ValueSpec)(unsafe.Pointer(&in.ValueSpecs))
+ out.ValueSpecs = *(*[]v1beta1.ValueSpec)(unsafe.Pointer(&in.ValueSpecs))
return nil
}
-func autoConvert_v1alpha8_PortOpts_To_v1alpha6_PortOpts(in *v1alpha8.PortOpts, out *PortOpts, s conversion.Scope) error {
+func autoConvert_v1beta1_PortOpts_To_v1alpha6_PortOpts(in *v1beta1.PortOpts, out *PortOpts, s conversion.Scope) error {
out.Network = (*NetworkFilter)(unsafe.Pointer(in.Network))
out.NameSuffix = in.NameSuffix
out.Description = in.Description
@@ -1393,7 +1393,7 @@ func autoConvert_v1alpha8_PortOpts_To_v1alpha6_PortOpts(in *v1alpha8.PortOpts, o
in, out := &in.SecurityGroupFilters, &out.SecurityGroupFilters
*out = make([]SecurityGroupParam, len(*in))
for i := range *in {
- if err := Convert_v1alpha8_SecurityGroupFilter_To_v1alpha6_SecurityGroupParam(&(*in)[i], &(*out)[i], s); err != nil {
+ if err := Convert_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupParam(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -1404,7 +1404,7 @@ func autoConvert_v1alpha8_PortOpts_To_v1alpha6_PortOpts(in *v1alpha8.PortOpts, o
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/v1alpha8.BindingProfile vs map[string]string)
+ // WARNING: in.Profile requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.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))
@@ -1412,31 +1412,31 @@ func autoConvert_v1alpha8_PortOpts_To_v1alpha6_PortOpts(in *v1alpha8.PortOpts, o
return nil
}
-func autoConvert_v1alpha6_RootVolume_To_v1alpha8_RootVolume(in *RootVolume, out *v1alpha8.RootVolume, s conversion.Scope) error {
+func autoConvert_v1alpha6_RootVolume_To_v1beta1_RootVolume(in *RootVolume, out *v1beta1.RootVolume, s conversion.Scope) error {
out.Size = in.Size
out.VolumeType = in.VolumeType
out.AvailabilityZone = in.AvailabilityZone
return nil
}
-// Convert_v1alpha6_RootVolume_To_v1alpha8_RootVolume is an autogenerated conversion function.
-func Convert_v1alpha6_RootVolume_To_v1alpha8_RootVolume(in *RootVolume, out *v1alpha8.RootVolume, s conversion.Scope) error {
- return autoConvert_v1alpha6_RootVolume_To_v1alpha8_RootVolume(in, out, s)
+// Convert_v1alpha6_RootVolume_To_v1beta1_RootVolume is an autogenerated conversion function.
+func Convert_v1alpha6_RootVolume_To_v1beta1_RootVolume(in *RootVolume, out *v1beta1.RootVolume, s conversion.Scope) error {
+ return autoConvert_v1alpha6_RootVolume_To_v1beta1_RootVolume(in, out, s)
}
-func autoConvert_v1alpha8_RootVolume_To_v1alpha6_RootVolume(in *v1alpha8.RootVolume, out *RootVolume, s conversion.Scope) error {
+func autoConvert_v1beta1_RootVolume_To_v1alpha6_RootVolume(in *v1beta1.RootVolume, out *RootVolume, s conversion.Scope) error {
out.Size = in.Size
out.VolumeType = in.VolumeType
out.AvailabilityZone = in.AvailabilityZone
return nil
}
-// Convert_v1alpha8_RootVolume_To_v1alpha6_RootVolume is an autogenerated conversion function.
-func Convert_v1alpha8_RootVolume_To_v1alpha6_RootVolume(in *v1alpha8.RootVolume, out *RootVolume, s conversion.Scope) error {
- return autoConvert_v1alpha8_RootVolume_To_v1alpha6_RootVolume(in, out, s)
+// Convert_v1beta1_RootVolume_To_v1alpha6_RootVolume is an autogenerated conversion function.
+func Convert_v1beta1_RootVolume_To_v1alpha6_RootVolume(in *v1beta1.RootVolume, out *RootVolume, s conversion.Scope) error {
+ return autoConvert_v1beta1_RootVolume_To_v1alpha6_RootVolume(in, out, s)
}
-func autoConvert_v1alpha6_Router_To_v1alpha8_Router(in *Router, out *v1alpha8.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))
@@ -1444,12 +1444,12 @@ func autoConvert_v1alpha6_Router_To_v1alpha8_Router(in *Router, out *v1alpha8.Ro
return nil
}
-// Convert_v1alpha6_Router_To_v1alpha8_Router is an autogenerated conversion function.
-func Convert_v1alpha6_Router_To_v1alpha8_Router(in *Router, out *v1alpha8.Router, s conversion.Scope) error {
- return autoConvert_v1alpha6_Router_To_v1alpha8_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_v1alpha8_Router_To_v1alpha6_Router(in *v1alpha8.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))
@@ -1457,12 +1457,12 @@ func autoConvert_v1alpha8_Router_To_v1alpha6_Router(in *v1alpha8.Router, out *Ro
return nil
}
-// Convert_v1alpha8_Router_To_v1alpha6_Router is an autogenerated conversion function.
-func Convert_v1alpha8_Router_To_v1alpha6_Router(in *v1alpha8.Router, out *Router, s conversion.Scope) error {
- return autoConvert_v1alpha8_Router_To_v1alpha6_Router(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_v1alpha6_SecurityGroupFilter_To_v1alpha8_SecurityGroupFilter(in *SecurityGroupFilter, out *v1alpha8.SecurityGroupFilter, s conversion.Scope) error {
+func autoConvert_v1alpha6_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in *SecurityGroupFilter, out *v1beta1.SecurityGroupFilter, s conversion.Scope) error {
out.ID = in.ID
out.Name = in.Name
out.Description = in.Description
@@ -1479,7 +1479,7 @@ func autoConvert_v1alpha6_SecurityGroupFilter_To_v1alpha8_SecurityGroupFilter(in
return nil
}
-func autoConvert_v1alpha8_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(in *v1alpha8.SecurityGroupFilter, out *SecurityGroupFilter, s conversion.Scope) error {
+func autoConvert_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(in *v1beta1.SecurityGroupFilter, out *SecurityGroupFilter, s conversion.Scope) error {
out.ID = in.ID
out.Name = in.Name
out.Description = in.Description
@@ -1491,12 +1491,12 @@ func autoConvert_v1alpha8_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(in
return nil
}
-// Convert_v1alpha8_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter is an autogenerated conversion function.
-func Convert_v1alpha8_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(in *v1alpha8.SecurityGroupFilter, out *SecurityGroupFilter, s conversion.Scope) error {
- return autoConvert_v1alpha8_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(in, out, s)
+// Convert_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter is an autogenerated conversion function.
+func Convert_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(in *v1beta1.SecurityGroupFilter, out *SecurityGroupFilter, s conversion.Scope) error {
+ return autoConvert_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(in, out, s)
}
-func autoConvert_v1alpha6_Subnet_To_v1alpha8_Subnet(in *Subnet, out *v1alpha8.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
@@ -1504,12 +1504,12 @@ func autoConvert_v1alpha6_Subnet_To_v1alpha8_Subnet(in *Subnet, out *v1alpha8.Su
return nil
}
-// Convert_v1alpha6_Subnet_To_v1alpha8_Subnet is an autogenerated conversion function.
-func Convert_v1alpha6_Subnet_To_v1alpha8_Subnet(in *Subnet, out *v1alpha8.Subnet, s conversion.Scope) error {
- return autoConvert_v1alpha6_Subnet_To_v1alpha8_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_v1alpha8_Subnet_To_v1alpha6_Subnet(in *v1alpha8.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
@@ -1517,12 +1517,12 @@ func autoConvert_v1alpha8_Subnet_To_v1alpha6_Subnet(in *v1alpha8.Subnet, out *Su
return nil
}
-// Convert_v1alpha8_Subnet_To_v1alpha6_Subnet is an autogenerated conversion function.
-func Convert_v1alpha8_Subnet_To_v1alpha6_Subnet(in *v1alpha8.Subnet, out *Subnet, s conversion.Scope) error {
- return autoConvert_v1alpha8_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_v1alpha8_SubnetFilter(in *SubnetFilter, out *v1alpha8.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
@@ -1539,12 +1539,12 @@ func autoConvert_v1alpha6_SubnetFilter_To_v1alpha8_SubnetFilter(in *SubnetFilter
return nil
}
-// Convert_v1alpha6_SubnetFilter_To_v1alpha8_SubnetFilter is an autogenerated conversion function.
-func Convert_v1alpha6_SubnetFilter_To_v1alpha8_SubnetFilter(in *SubnetFilter, out *v1alpha8.SubnetFilter, s conversion.Scope) error {
- return autoConvert_v1alpha6_SubnetFilter_To_v1alpha8_SubnetFilter(in, out, s)
+// Convert_v1alpha6_SubnetFilter_To_v1beta1_SubnetFilter is an autogenerated conversion function.
+func Convert_v1alpha6_SubnetFilter_To_v1beta1_SubnetFilter(in *SubnetFilter, out *v1beta1.SubnetFilter, s conversion.Scope) error {
+ return autoConvert_v1alpha6_SubnetFilter_To_v1beta1_SubnetFilter(in, out, s)
}
-func autoConvert_v1alpha8_SubnetFilter_To_v1alpha6_SubnetFilter(in *v1alpha8.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
@@ -1561,31 +1561,31 @@ func autoConvert_v1alpha8_SubnetFilter_To_v1alpha6_SubnetFilter(in *v1alpha8.Sub
return nil
}
-// Convert_v1alpha8_SubnetFilter_To_v1alpha6_SubnetFilter is an autogenerated conversion function.
-func Convert_v1alpha8_SubnetFilter_To_v1alpha6_SubnetFilter(in *v1alpha8.SubnetFilter, out *SubnetFilter, s conversion.Scope) error {
- return autoConvert_v1alpha8_SubnetFilter_To_v1alpha6_SubnetFilter(in, out, s)
+// Convert_v1beta1_SubnetFilter_To_v1alpha6_SubnetFilter is an autogenerated conversion function.
+func Convert_v1beta1_SubnetFilter_To_v1alpha6_SubnetFilter(in *v1beta1.SubnetFilter, out *SubnetFilter, s conversion.Scope) error {
+ return autoConvert_v1beta1_SubnetFilter_To_v1alpha6_SubnetFilter(in, out, s)
}
-func autoConvert_v1alpha6_ValueSpec_To_v1alpha8_ValueSpec(in *ValueSpec, out *v1alpha8.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_v1alpha8_ValueSpec is an autogenerated conversion function.
-func Convert_v1alpha6_ValueSpec_To_v1alpha8_ValueSpec(in *ValueSpec, out *v1alpha8.ValueSpec, s conversion.Scope) error {
- return autoConvert_v1alpha6_ValueSpec_To_v1alpha8_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_v1alpha8_ValueSpec_To_v1alpha6_ValueSpec(in *v1alpha8.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_v1alpha8_ValueSpec_To_v1alpha6_ValueSpec is an autogenerated conversion function.
-func Convert_v1alpha8_ValueSpec_To_v1alpha6_ValueSpec(in *v1alpha8.ValueSpec, out *ValueSpec, s conversion.Scope) error {
- return autoConvert_v1alpha8_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/v1alpha7/conversion.go b/api/v1alpha7/conversion.go
index cc0e62756f..ce307ea407 100644
--- a/api/v1alpha7/conversion.go
+++ b/api/v1alpha7/conversion.go
@@ -21,7 +21,7 @@ import (
"k8s.io/utils/pointer"
ctrlconversion "sigs.k8s.io/controller-runtime/pkg/conversion"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/conversion"
)
@@ -82,7 +82,7 @@ func restorev1alpha7ClusterStatus(previous *OpenStackClusterStatus, dst *OpenSta
restorev1alpha7SecurityGroup(previous.BastionSecurityGroup, dst.BastionSecurityGroup)
}
-func restorev1alpha8SecurityGroupStatus(previous *infrav1.SecurityGroupStatus, dst *infrav1.SecurityGroupStatus) {
+func restorev1beta1SecurityGroupStatus(previous *infrav1.SecurityGroupStatus, dst *infrav1.SecurityGroupStatus) {
if previous == nil || dst == nil {
return
}
@@ -115,10 +115,10 @@ func restorev1alpha8SecurityGroupStatus(previous *infrav1.SecurityGroupStatus, d
}
}
-func restorev1alpha8ClusterStatus(previous *infrav1.OpenStackClusterStatus, dst *infrav1.OpenStackClusterStatus) {
- restorev1alpha8SecurityGroupStatus(previous.ControlPlaneSecurityGroup, dst.ControlPlaneSecurityGroup)
- restorev1alpha8SecurityGroupStatus(previous.WorkerSecurityGroup, dst.WorkerSecurityGroup)
- restorev1alpha8SecurityGroupStatus(previous.BastionSecurityGroup, dst.BastionSecurityGroup)
+func restorev1beta1ClusterStatus(previous *infrav1.OpenStackClusterStatus, dst *infrav1.OpenStackClusterStatus) {
+ restorev1beta1SecurityGroupStatus(previous.ControlPlaneSecurityGroup, dst.ControlPlaneSecurityGroup)
+ restorev1beta1SecurityGroupStatus(previous.WorkerSecurityGroup, dst.WorkerSecurityGroup)
+ restorev1beta1SecurityGroupStatus(previous.BastionSecurityGroup, dst.BastionSecurityGroup)
// ReferencedResources have no equivalent in v1alpha7
if previous.Bastion != nil {
@@ -130,18 +130,18 @@ func restorev1alpha8ClusterStatus(previous *infrav1.OpenStackClusterStatus, dst
}
}
-var v1alpha8OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStackCluster]{
+var v1beta1OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStackCluster]{
"bastion": conversion.HashedFieldRestorer(
func(c *infrav1.OpenStackCluster) **infrav1.Bastion {
return &c.Spec.Bastion
},
- restorev1alpha8Bastion,
+ restorev1beta1Bastion,
),
"spec": conversion.HashedFieldRestorer(
func(c *infrav1.OpenStackCluster) *infrav1.OpenStackClusterSpec {
return &c.Spec
},
- restorev1alpha8ClusterSpec,
+ restorev1beta1ClusterSpec,
// Filter out Bastion, which is restored separately
conversion.HashedFilterField[*infrav1.OpenStackCluster, infrav1.OpenStackClusterSpec](
@@ -160,14 +160,14 @@ var v1alpha8OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStack
func(c *infrav1.OpenStackCluster) *infrav1.OpenStackClusterStatus {
return &c.Status
},
- restorev1alpha8ClusterStatus,
+ restorev1beta1ClusterStatus,
),
}
func restorev1alpha7MachineSpec(previous *OpenStackMachineSpec, dst *OpenStackMachineSpec) {
dst.FloatingIP = previous.FloatingIP
- // Conversion to v1alpha8 truncates keys and values to 255 characters
+ // Conversion to v1beta1 truncates keys and values to 255 characters
for k, v := range previous.ServerMetadata {
kd := k
if len(k) > 255 {
@@ -185,18 +185,18 @@ func restorev1alpha7MachineSpec(previous *OpenStackMachineSpec, dst *OpenStackMa
}
}
- // Conversion to v1alpha8 removes the Kind field
+ // Conversion to v1beta1 removes the Kind field
dst.IdentityRef = previous.IdentityRef
}
-func restorev1alpha8MachineSpec(previous *infrav1.OpenStackMachineSpec, dst *infrav1.OpenStackMachineSpec) {
+func restorev1beta1MachineSpec(previous *infrav1.OpenStackMachineSpec, dst *infrav1.OpenStackMachineSpec) {
dst.ServerGroup = previous.ServerGroup
dst.Image = previous.Image
}
-func restorev1alpha8Bastion(previous **infrav1.Bastion, dst **infrav1.Bastion) {
+func restorev1beta1Bastion(previous **infrav1.Bastion, dst **infrav1.Bastion) {
if *previous != nil && *dst != nil {
- restorev1alpha8MachineSpec(&(*previous).Instance, &(*dst).Instance)
+ restorev1beta1MachineSpec(&(*previous).Instance, &(*dst).Instance)
}
}
@@ -218,15 +218,15 @@ func restorev1alpha7ClusterSpec(previous *OpenStackClusterSpec, dst *OpenStackCl
dst.AllowAllInClusterTraffic = true
}
- // Conversion to v1alpha8 removes the Kind field
+ // Conversion to v1beta1 removes the Kind field
dst.IdentityRef = previous.IdentityRef
}
-func restorev1alpha8ClusterSpec(previous *infrav1.OpenStackClusterSpec, dst *infrav1.OpenStackClusterSpec) {
+func restorev1beta1ClusterSpec(previous *infrav1.OpenStackClusterSpec, dst *infrav1.OpenStackClusterSpec) {
prevBastion := previous.Bastion
dstBastion := dst.Bastion
if prevBastion != nil && dstBastion != nil {
- restorev1alpha8MachineSpec(&prevBastion.Instance, &dstBastion.Instance)
+ restorev1beta1MachineSpec(&prevBastion.Instance, &dstBastion.Instance)
}
// Restore all fields except ID, which should have been copied over in conversion
@@ -256,8 +256,8 @@ func (r *OpenStackCluster) ConvertTo(dstRaw ctrlconversion.Hub) error {
return conversion.ConvertAndRestore(
r, dst,
- Convert_v1alpha7_OpenStackCluster_To_v1alpha8_OpenStackCluster, Convert_v1alpha8_OpenStackCluster_To_v1alpha7_OpenStackCluster,
- v1alpha7OpenStackClusterRestorer, v1alpha8OpenStackClusterRestorer,
+ Convert_v1alpha7_OpenStackCluster_To_v1beta1_OpenStackCluster, Convert_v1beta1_OpenStackCluster_To_v1alpha7_OpenStackCluster,
+ v1alpha7OpenStackClusterRestorer, v1beta1OpenStackClusterRestorer,
)
}
@@ -266,8 +266,8 @@ func (r *OpenStackCluster) ConvertFrom(srcRaw ctrlconversion.Hub) error {
return conversion.ConvertAndRestore(
src, r,
- Convert_v1alpha8_OpenStackCluster_To_v1alpha7_OpenStackCluster, Convert_v1alpha7_OpenStackCluster_To_v1alpha8_OpenStackCluster,
- v1alpha8OpenStackClusterRestorer, v1alpha7OpenStackClusterRestorer,
+ Convert_v1beta1_OpenStackCluster_To_v1alpha7_OpenStackCluster, Convert_v1alpha7_OpenStackCluster_To_v1beta1_OpenStackCluster,
+ v1beta1OpenStackClusterRestorer, v1alpha7OpenStackClusterRestorer,
)
}
@@ -276,13 +276,13 @@ var _ ctrlconversion.Convertible = &OpenStackClusterList{}
func (r *OpenStackClusterList) ConvertTo(dstRaw ctrlconversion.Hub) error {
dst := dstRaw.(*infrav1.OpenStackClusterList)
- return Convert_v1alpha7_OpenStackClusterList_To_v1alpha8_OpenStackClusterList(r, dst, nil)
+ return Convert_v1alpha7_OpenStackClusterList_To_v1beta1_OpenStackClusterList(r, dst, nil)
}
func (r *OpenStackClusterList) ConvertFrom(srcRaw ctrlconversion.Hub) error {
src := srcRaw.(*infrav1.OpenStackClusterList)
- return Convert_v1alpha8_OpenStackClusterList_To_v1alpha7_OpenStackClusterList(src, r, nil)
+ return Convert_v1beta1_OpenStackClusterList_To_v1alpha7_OpenStackClusterList(src, r, nil)
}
var _ ctrlconversion.Convertible = &OpenStackClusterTemplate{}
@@ -292,9 +292,9 @@ func restorev1alpha7ClusterTemplateSpec(previous *OpenStackClusterTemplateSpec,
restorev1alpha7Bastion(&previous.Template.Spec.Bastion, &dst.Template.Spec.Bastion)
}
-func restorev1alpha8ClusterTemplateSpec(previous *infrav1.OpenStackClusterTemplateSpec, dst *infrav1.OpenStackClusterTemplateSpec) {
- restorev1alpha8Bastion(&previous.Template.Spec.Bastion, &dst.Template.Spec.Bastion)
- restorev1alpha8ClusterSpec(&previous.Template.Spec, &dst.Template.Spec)
+func restorev1beta1ClusterTemplateSpec(previous *infrav1.OpenStackClusterTemplateSpec, dst *infrav1.OpenStackClusterTemplateSpec) {
+ restorev1beta1Bastion(&previous.Template.Spec.Bastion, &dst.Template.Spec.Bastion)
+ restorev1beta1ClusterSpec(&previous.Template.Spec, &dst.Template.Spec)
}
var v1alpha7OpenStackClusterTemplateRestorer = conversion.RestorerFor[*OpenStackClusterTemplate]{
@@ -306,12 +306,12 @@ var v1alpha7OpenStackClusterTemplateRestorer = conversion.RestorerFor[*OpenStack
),
}
-var v1alpha8OpenStackClusterTemplateRestorer = conversion.RestorerFor[*infrav1.OpenStackClusterTemplate]{
+var v1beta1OpenStackClusterTemplateRestorer = conversion.RestorerFor[*infrav1.OpenStackClusterTemplate]{
"spec": conversion.HashedFieldRestorer(
func(c *infrav1.OpenStackClusterTemplate) *infrav1.OpenStackClusterTemplateSpec {
return &c.Spec
},
- restorev1alpha8ClusterTemplateSpec,
+ restorev1beta1ClusterTemplateSpec,
),
}
@@ -320,8 +320,8 @@ func (r *OpenStackClusterTemplate) ConvertTo(dstRaw ctrlconversion.Hub) error {
return conversion.ConvertAndRestore(
r, dst,
- Convert_v1alpha7_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate, Convert_v1alpha8_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate,
- v1alpha7OpenStackClusterTemplateRestorer, v1alpha8OpenStackClusterTemplateRestorer,
+ Convert_v1alpha7_OpenStackClusterTemplate_To_v1beta1_OpenStackClusterTemplate, Convert_v1beta1_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate,
+ v1alpha7OpenStackClusterTemplateRestorer, v1beta1OpenStackClusterTemplateRestorer,
)
}
@@ -330,8 +330,8 @@ func (r *OpenStackClusterTemplate) ConvertFrom(srcRaw ctrlconversion.Hub) error
return conversion.ConvertAndRestore(
src, r,
- Convert_v1alpha8_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate, Convert_v1alpha7_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate,
- v1alpha8OpenStackClusterTemplateRestorer, v1alpha7OpenStackClusterTemplateRestorer,
+ Convert_v1beta1_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate, Convert_v1alpha7_OpenStackClusterTemplate_To_v1beta1_OpenStackClusterTemplate,
+ v1beta1OpenStackClusterTemplateRestorer, v1alpha7OpenStackClusterTemplateRestorer,
)
}
@@ -346,12 +346,12 @@ var v1alpha7OpenStackMachineRestorer = conversion.RestorerFor[*OpenStackMachine]
),
}
-var v1alpha8OpenStackMachineRestorer = conversion.RestorerFor[*infrav1.OpenStackMachine]{
+var v1beta1OpenStackMachineRestorer = conversion.RestorerFor[*infrav1.OpenStackMachine]{
"spec": conversion.HashedFieldRestorer(
func(c *infrav1.OpenStackMachine) *infrav1.OpenStackMachineSpec {
return &c.Spec
},
- restorev1alpha8MachineSpec,
+ restorev1beta1MachineSpec,
),
"depresources": conversion.UnconditionalFieldRestorer(
func(c *infrav1.OpenStackMachine) *infrav1.DependentMachineResources {
@@ -372,8 +372,8 @@ func (r *OpenStackMachine) ConvertTo(dstRaw ctrlconversion.Hub) error {
return conversion.ConvertAndRestore(
r, dst,
- Convert_v1alpha7_OpenStackMachine_To_v1alpha8_OpenStackMachine, Convert_v1alpha8_OpenStackMachine_To_v1alpha7_OpenStackMachine,
- v1alpha7OpenStackMachineRestorer, v1alpha8OpenStackMachineRestorer,
+ Convert_v1alpha7_OpenStackMachine_To_v1beta1_OpenStackMachine, Convert_v1beta1_OpenStackMachine_To_v1alpha7_OpenStackMachine,
+ v1alpha7OpenStackMachineRestorer, v1beta1OpenStackMachineRestorer,
)
}
@@ -382,8 +382,8 @@ func (r *OpenStackMachine) ConvertFrom(srcRaw ctrlconversion.Hub) error {
return conversion.ConvertAndRestore(
src, r,
- Convert_v1alpha8_OpenStackMachine_To_v1alpha7_OpenStackMachine, Convert_v1alpha7_OpenStackMachine_To_v1alpha8_OpenStackMachine,
- v1alpha8OpenStackMachineRestorer, v1alpha7OpenStackMachineRestorer,
+ Convert_v1beta1_OpenStackMachine_To_v1alpha7_OpenStackMachine, Convert_v1alpha7_OpenStackMachine_To_v1beta1_OpenStackMachine,
+ v1beta1OpenStackMachineRestorer, v1alpha7OpenStackMachineRestorer,
)
}
@@ -391,12 +391,12 @@ var _ ctrlconversion.Convertible = &OpenStackMachineList{}
func (r *OpenStackMachineList) ConvertTo(dstRaw ctrlconversion.Hub) error {
dst := dstRaw.(*infrav1.OpenStackMachineList)
- return Convert_v1alpha7_OpenStackMachineList_To_v1alpha8_OpenStackMachineList(r, dst, nil)
+ return Convert_v1alpha7_OpenStackMachineList_To_v1beta1_OpenStackMachineList(r, dst, nil)
}
func (r *OpenStackMachineList) ConvertFrom(srcRaw ctrlconversion.Hub) error {
src := srcRaw.(*infrav1.OpenStackMachineList)
- return Convert_v1alpha8_OpenStackMachineList_To_v1alpha7_OpenStackMachineList(src, r, nil)
+ return Convert_v1beta1_OpenStackMachineList_To_v1alpha7_OpenStackMachineList(src, r, nil)
}
var _ ctrlconversion.Convertible = &OpenStackMachineTemplate{}
@@ -414,12 +414,12 @@ var v1alpha7OpenStackMachineTemplateRestorer = conversion.RestorerFor[*OpenStack
),
}
-var v1alpha8OpenStackMachineTemplateRestorer = conversion.RestorerFor[*infrav1.OpenStackMachineTemplate]{
+var v1beta1OpenStackMachineTemplateRestorer = conversion.RestorerFor[*infrav1.OpenStackMachineTemplate]{
"spec": conversion.HashedFieldRestorer(
func(c *infrav1.OpenStackMachineTemplate) *infrav1.OpenStackMachineSpec {
return &c.Spec.Template.Spec
},
- restorev1alpha8MachineSpec,
+ restorev1beta1MachineSpec,
),
}
@@ -428,8 +428,8 @@ func (r *OpenStackMachineTemplate) ConvertTo(dstRaw ctrlconversion.Hub) error {
return conversion.ConvertAndRestore(
r, dst,
- Convert_v1alpha7_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate, Convert_v1alpha8_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate,
- v1alpha7OpenStackMachineTemplateRestorer, v1alpha8OpenStackMachineTemplateRestorer,
+ Convert_v1alpha7_OpenStackMachineTemplate_To_v1beta1_OpenStackMachineTemplate, Convert_v1beta1_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate,
+ v1alpha7OpenStackMachineTemplateRestorer, v1beta1OpenStackMachineTemplateRestorer,
)
}
@@ -438,8 +438,8 @@ func (r *OpenStackMachineTemplate) ConvertFrom(srcRaw ctrlconversion.Hub) error
return conversion.ConvertAndRestore(
src, r,
- Convert_v1alpha8_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate, Convert_v1alpha7_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate,
- v1alpha8OpenStackMachineTemplateRestorer, v1alpha7OpenStackMachineTemplateRestorer,
+ Convert_v1beta1_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate, Convert_v1alpha7_OpenStackMachineTemplate_To_v1beta1_OpenStackMachineTemplate,
+ v1beta1OpenStackMachineTemplateRestorer, v1alpha7OpenStackMachineTemplateRestorer,
)
}
@@ -447,16 +447,16 @@ var _ ctrlconversion.Convertible = &OpenStackMachineTemplateList{}
func (r *OpenStackMachineTemplateList) ConvertTo(dstRaw ctrlconversion.Hub) error {
dst := dstRaw.(*infrav1.OpenStackMachineTemplateList)
- return Convert_v1alpha7_OpenStackMachineTemplateList_To_v1alpha8_OpenStackMachineTemplateList(r, dst, nil)
+ return Convert_v1alpha7_OpenStackMachineTemplateList_To_v1beta1_OpenStackMachineTemplateList(r, dst, nil)
}
func (r *OpenStackMachineTemplateList) ConvertFrom(srcRaw ctrlconversion.Hub) error {
src := srcRaw.(*infrav1.OpenStackMachineTemplateList)
- return Convert_v1alpha8_OpenStackMachineTemplateList_To_v1alpha7_OpenStackMachineTemplateList(src, r, nil)
+ return Convert_v1beta1_OpenStackMachineTemplateList_To_v1alpha7_OpenStackMachineTemplateList(src, r, nil)
}
-func Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(in *infrav1.OpenStackMachineSpec, out *OpenStackMachineSpec, s apiconversion.Scope) error {
- err := autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(in, out, s)
+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
}
@@ -486,8 +486,8 @@ func Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(in *
return nil
}
-func Convert_v1alpha7_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(in *OpenStackMachineSpec, out *infrav1.OpenStackMachineSpec, s apiconversion.Scope) error {
- err := autoConvert_v1alpha7_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(in, out, s)
+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
}
@@ -511,7 +511,7 @@ func Convert_v1alpha7_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(in *
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 v1alpha8
+ // was not validated prior to v1beta1
if len(k) > 255 {
k = k[:255]
}
@@ -527,18 +527,18 @@ func Convert_v1alpha7_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(in *
return nil
}
-func Convert_v1alpha8_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus(in *infrav1.OpenStackMachineStatus, out *OpenStackMachineStatus, s apiconversion.Scope) error {
+func Convert_v1beta1_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus(in *infrav1.OpenStackMachineStatus, out *OpenStackMachineStatus, s apiconversion.Scope) error {
// ReferencedResources have no equivalent in v1alpha7
- return autoConvert_v1alpha8_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus(in, out, s)
+ return autoConvert_v1beta1_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus(in, out, s)
}
-func Convert_v1alpha8_BastionStatus_To_v1alpha7_BastionStatus(in *infrav1.BastionStatus, out *BastionStatus, s apiconversion.Scope) error {
+func Convert_v1beta1_BastionStatus_To_v1alpha7_BastionStatus(in *infrav1.BastionStatus, out *BastionStatus, s apiconversion.Scope) error {
// ReferencedResources have no equivalent in v1alpha7
- return autoConvert_v1alpha8_BastionStatus_To_v1alpha7_BastionStatus(in, out, s)
+ return autoConvert_v1beta1_BastionStatus_To_v1alpha7_BastionStatus(in, out, s)
}
-func Convert_v1alpha7_Bastion_To_v1alpha8_Bastion(in *Bastion, out *infrav1.Bastion, s apiconversion.Scope) error {
- err := autoConvert_v1alpha7_Bastion_To_v1alpha8_Bastion(in, out, s)
+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
}
@@ -553,8 +553,8 @@ func Convert_v1alpha7_Bastion_To_v1alpha8_Bastion(in *Bastion, out *infrav1.Bast
return nil
}
-func Convert_v1alpha8_Bastion_To_v1alpha7_Bastion(in *infrav1.Bastion, out *Bastion, s apiconversion.Scope) error {
- err := autoConvert_v1alpha8_Bastion_To_v1alpha7_Bastion(in, out, s)
+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
}
@@ -567,8 +567,8 @@ func Convert_v1alpha8_Bastion_To_v1alpha7_Bastion(in *infrav1.Bastion, out *Bast
return nil
}
-func Convert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *OpenStackClusterSpec, out *infrav1.OpenStackClusterSpec, s apiconversion.Scope) error {
- err := autoConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in, out, s)
+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
}
@@ -582,7 +582,7 @@ func Convert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *
emptySubnet := SubnetFilter{}
if in.Subnet != emptySubnet {
subnet := infrav1.SubnetFilter{}
- if err := Convert_v1alpha7_SubnetFilter_To_v1alpha8_SubnetFilter(&in.Subnet, &subnet, s); err != nil {
+ if err := Convert_v1alpha7_SubnetFilter_To_v1beta1_SubnetFilter(&in.Subnet, &subnet, s); err != nil {
return err
}
out.Subnets = []infrav1.SubnetFilter{subnet}
@@ -610,8 +610,8 @@ func Convert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *
return nil
}
-func Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in *infrav1.OpenStackClusterSpec, out *OpenStackClusterSpec, s apiconversion.Scope) error {
- err := autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(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
}
@@ -621,7 +621,7 @@ func Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in *
}
if len(in.Subnets) >= 1 {
- if err := Convert_v1alpha8_SubnetFilter_To_v1alpha7_SubnetFilter(&in.Subnets[0], &out.Subnet, s); err != nil {
+ if err := Convert_v1beta1_SubnetFilter_To_v1alpha7_SubnetFilter(&in.Subnets[0], &out.Subnet, s); err != nil {
return err
}
}
@@ -639,7 +639,7 @@ func Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in *
return nil
}
-func Convert_v1alpha8_SecurityGroupStatus_To_v1alpha7_SecurityGroup(in *infrav1.SecurityGroupStatus, out *SecurityGroup, s apiconversion.Scope) error { //nolint:revive
+func Convert_v1beta1_SecurityGroupStatus_To_v1alpha7_SecurityGroup(in *infrav1.SecurityGroupStatus, out *SecurityGroup, s apiconversion.Scope) error { //nolint:revive
out.ID = in.ID
out.Name = in.Name
out.Rules = make([]SecurityGroupRule, len(in.Rules))
@@ -673,7 +673,7 @@ func Convert_v1alpha8_SecurityGroupStatus_To_v1alpha7_SecurityGroup(in *infrav1.
return nil
}
-func Convert_v1alpha7_SecurityGroup_To_v1alpha8_SecurityGroupStatus(in *SecurityGroup, out *infrav1.SecurityGroupStatus, s apiconversion.Scope) error { //nolint:revive
+func Convert_v1alpha7_SecurityGroup_To_v1beta1_SecurityGroupStatus(in *SecurityGroup, out *infrav1.SecurityGroupStatus, s apiconversion.Scope) error { //nolint:revive
out.ID = in.ID
out.Name = in.Name
out.Rules = make([]infrav1.SecurityGroupRuleStatus, len(in.Rules))
@@ -694,10 +694,10 @@ func Convert_v1alpha7_SecurityGroup_To_v1alpha8_SecurityGroupStatus(in *Security
return nil
}
-func Convert_v1alpha7_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(in *OpenStackIdentityReference, out *infrav1.OpenStackIdentityReference, s apiconversion.Scope) error {
- return autoConvert_v1alpha7_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(in, out, s)
+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_v1alpha8_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(in *infrav1.OpenStackClusterStatus, out *OpenStackClusterStatus, s apiconversion.Scope) error {
- return autoConvert_v1alpha8_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(in, out, s)
+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)
}
diff --git a/api/v1alpha7/conversion_test.go b/api/v1alpha7/conversion_test.go
index 7487eedaa0..25fcc253fa 100644
--- a/api/v1alpha7/conversion_test.go
+++ b/api/v1alpha7/conversion_test.go
@@ -29,7 +29,7 @@ import (
utilconversion "sigs.k8s.io/cluster-api/util/conversion"
"sigs.k8s.io/controller-runtime/pkg/conversion"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
testhelpers "sigs.k8s.io/cluster-api-provider-openstack/test/helpers"
)
@@ -283,7 +283,7 @@ func TestMachineConversionControllerSpecFields(t *testing.T) {
}
}
-func TestConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(t *testing.T) {
+func TestConvert_v1alpha7_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(t *testing.T) {
tests := []struct {
name string
in *OpenStackClusterSpec
@@ -324,7 +324,7 @@ func TestConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(
t.Run(tt.name, func(t *testing.T) {
g := gomega.NewWithT(t)
out := &infrav1.OpenStackClusterSpec{}
- err := Convert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(tt.in, out, nil)
+ err := Convert_v1alpha7_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(tt.in, out, nil)
g.Expect(err).NotTo(gomega.HaveOccurred())
g.Expect(out).To(gomega.Equal(tt.expectedOut))
})
diff --git a/api/v1alpha7/doc.go b/api/v1alpha7/doc.go
index 91f912911d..84a3ca41b1 100644
--- a/api/v1alpha7/doc.go
+++ b/api/v1alpha7/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/v1alpha8
+// +k8s:conversion-gen=sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1
package v1alpha7
diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go
index 1eae94c731..2e913f05fc 100644
--- a/api/v1alpha7/zz_generated.conversion.go
+++ b/api/v1alpha7/zz_generated.conversion.go
@@ -27,8 +27,8 @@ import (
v1 "k8s.io/api/core/v1"
conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime"
- v1alpha8 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
- v1beta1 "sigs.k8s.io/cluster-api/api/v1beta1"
+ v1beta1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
+ apiv1beta1 "sigs.k8s.io/cluster-api/api/v1beta1"
errors "sigs.k8s.io/cluster-api/errors"
)
@@ -39,410 +39,410 @@ 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), (*v1alpha8.APIServerLoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalancer(a.(*APIServerLoadBalancer), b.(*v1alpha8.APIServerLoadBalancer), scope)
+ if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*v1alpha8.APIServerLoadBalancer)(nil), (*APIServerLoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer(a.(*v1alpha8.APIServerLoadBalancer), b.(*APIServerLoadBalancer), scope)
+ if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*AdditionalBlockDevice)(nil), (*v1alpha8.AdditionalBlockDevice)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_AdditionalBlockDevice_To_v1alpha8_AdditionalBlockDevice(a.(*AdditionalBlockDevice), b.(*v1alpha8.AdditionalBlockDevice), scope)
+ 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((*v1alpha8.AdditionalBlockDevice)(nil), (*AdditionalBlockDevice)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_AdditionalBlockDevice_To_v1alpha7_AdditionalBlockDevice(a.(*v1alpha8.AdditionalBlockDevice), b.(*AdditionalBlockDevice), scope)
+ 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), (*v1alpha8.AddressPair)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_AddressPair_To_v1alpha8_AddressPair(a.(*AddressPair), b.(*v1alpha8.AddressPair), scope)
+ 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((*v1alpha8.AddressPair)(nil), (*AddressPair)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_AddressPair_To_v1alpha7_AddressPair(a.(*v1alpha8.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_v1alpha7_AddressPair(a.(*v1beta1.AddressPair), b.(*AddressPair), scope)
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*BastionStatus)(nil), (*v1alpha8.BastionStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_BastionStatus_To_v1alpha8_BastionStatus(a.(*BastionStatus), b.(*v1alpha8.BastionStatus), scope)
+ 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), (*v1alpha8.BindingProfile)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_BindingProfile_To_v1alpha8_BindingProfile(a.(*BindingProfile), b.(*v1alpha8.BindingProfile), scope)
+ 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((*v1alpha8.BindingProfile)(nil), (*BindingProfile)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_BindingProfile_To_v1alpha7_BindingProfile(a.(*v1alpha8.BindingProfile), b.(*BindingProfile), scope)
+ 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), (*v1alpha8.BlockDeviceStorage)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_BlockDeviceStorage_To_v1alpha8_BlockDeviceStorage(a.(*BlockDeviceStorage), b.(*v1alpha8.BlockDeviceStorage), scope)
+ 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((*v1alpha8.BlockDeviceStorage)(nil), (*BlockDeviceStorage)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_BlockDeviceStorage_To_v1alpha7_BlockDeviceStorage(a.(*v1alpha8.BlockDeviceStorage), b.(*BlockDeviceStorage), scope)
+ 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), (*v1alpha8.BlockDeviceVolume)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_BlockDeviceVolume_To_v1alpha8_BlockDeviceVolume(a.(*BlockDeviceVolume), b.(*v1alpha8.BlockDeviceVolume), scope)
+ 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((*v1alpha8.BlockDeviceVolume)(nil), (*BlockDeviceVolume)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_BlockDeviceVolume_To_v1alpha7_BlockDeviceVolume(a.(*v1alpha8.BlockDeviceVolume), b.(*BlockDeviceVolume), scope)
+ 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), (*v1alpha8.ExternalRouterIPParam)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_ExternalRouterIPParam_To_v1alpha8_ExternalRouterIPParam(a.(*ExternalRouterIPParam), b.(*v1alpha8.ExternalRouterIPParam), scope)
+ 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((*v1alpha8.ExternalRouterIPParam)(nil), (*ExternalRouterIPParam)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_ExternalRouterIPParam_To_v1alpha7_ExternalRouterIPParam(a.(*v1alpha8.ExternalRouterIPParam), b.(*ExternalRouterIPParam), scope)
+ 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), (*v1alpha8.FixedIP)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_FixedIP_To_v1alpha8_FixedIP(a.(*FixedIP), b.(*v1alpha8.FixedIP), scope)
+ 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((*v1alpha8.FixedIP)(nil), (*FixedIP)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_FixedIP_To_v1alpha7_FixedIP(a.(*v1alpha8.FixedIP), b.(*FixedIP), scope)
+ 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), (*v1alpha8.LoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_LoadBalancer_To_v1alpha8_LoadBalancer(a.(*LoadBalancer), b.(*v1alpha8.LoadBalancer), scope)
+ 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((*v1alpha8.LoadBalancer)(nil), (*LoadBalancer)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_LoadBalancer_To_v1alpha7_LoadBalancer(a.(*v1alpha8.LoadBalancer), b.(*LoadBalancer), scope)
+ if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*NetworkFilter)(nil), (*v1alpha8.NetworkFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_NetworkFilter_To_v1alpha8_NetworkFilter(a.(*NetworkFilter), b.(*v1alpha8.NetworkFilter), scope)
+ if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*v1alpha8.NetworkFilter)(nil), (*NetworkFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_NetworkFilter_To_v1alpha7_NetworkFilter(a.(*v1alpha8.NetworkFilter), b.(*NetworkFilter), scope)
+ if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*NetworkStatus)(nil), (*v1alpha8.NetworkStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_NetworkStatus_To_v1alpha8_NetworkStatus(a.(*NetworkStatus), b.(*v1alpha8.NetworkStatus), scope)
+ 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((*v1alpha8.NetworkStatus)(nil), (*NetworkStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_NetworkStatus_To_v1alpha7_NetworkStatus(a.(*v1alpha8.NetworkStatus), b.(*NetworkStatus), scope)
+ 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), (*v1alpha8.NetworkStatusWithSubnets)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_NetworkStatusWithSubnets_To_v1alpha8_NetworkStatusWithSubnets(a.(*NetworkStatusWithSubnets), b.(*v1alpha8.NetworkStatusWithSubnets), scope)
+ 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((*v1alpha8.NetworkStatusWithSubnets)(nil), (*NetworkStatusWithSubnets)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_NetworkStatusWithSubnets_To_v1alpha7_NetworkStatusWithSubnets(a.(*v1alpha8.NetworkStatusWithSubnets), b.(*NetworkStatusWithSubnets), scope)
+ 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), (*v1alpha8.OpenStackCluster)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_OpenStackCluster_To_v1alpha8_OpenStackCluster(a.(*OpenStackCluster), b.(*v1alpha8.OpenStackCluster), scope)
+ 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((*v1alpha8.OpenStackCluster)(nil), (*OpenStackCluster)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackCluster_To_v1alpha7_OpenStackCluster(a.(*v1alpha8.OpenStackCluster), b.(*OpenStackCluster), scope)
+ 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), (*v1alpha8.OpenStackClusterList)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_OpenStackClusterList_To_v1alpha8_OpenStackClusterList(a.(*OpenStackClusterList), b.(*v1alpha8.OpenStackClusterList), scope)
+ 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((*v1alpha8.OpenStackClusterList)(nil), (*OpenStackClusterList)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackClusterList_To_v1alpha7_OpenStackClusterList(a.(*v1alpha8.OpenStackClusterList), b.(*OpenStackClusterList), scope)
+ 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), (*v1alpha8.OpenStackClusterStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterStatus(a.(*OpenStackClusterStatus), b.(*v1alpha8.OpenStackClusterStatus), scope)
+ 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), (*v1alpha8.OpenStackClusterTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate(a.(*OpenStackClusterTemplate), b.(*v1alpha8.OpenStackClusterTemplate), scope)
+ 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((*v1alpha8.OpenStackClusterTemplate)(nil), (*OpenStackClusterTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate(a.(*v1alpha8.OpenStackClusterTemplate), b.(*OpenStackClusterTemplate), scope)
+ 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), (*v1alpha8.OpenStackClusterTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_OpenStackClusterTemplateList_To_v1alpha8_OpenStackClusterTemplateList(a.(*OpenStackClusterTemplateList), b.(*v1alpha8.OpenStackClusterTemplateList), scope)
+ 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((*v1alpha8.OpenStackClusterTemplateList)(nil), (*OpenStackClusterTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackClusterTemplateList_To_v1alpha7_OpenStackClusterTemplateList(a.(*v1alpha8.OpenStackClusterTemplateList), b.(*OpenStackClusterTemplateList), scope)
+ 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), (*v1alpha8.OpenStackClusterTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_OpenStackClusterTemplateResource_To_v1alpha8_OpenStackClusterTemplateResource(a.(*OpenStackClusterTemplateResource), b.(*v1alpha8.OpenStackClusterTemplateResource), scope)
+ 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((*v1alpha8.OpenStackClusterTemplateResource)(nil), (*OpenStackClusterTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackClusterTemplateResource_To_v1alpha7_OpenStackClusterTemplateResource(a.(*v1alpha8.OpenStackClusterTemplateResource), b.(*OpenStackClusterTemplateResource), scope)
+ 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), (*v1alpha8.OpenStackClusterTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_OpenStackClusterTemplateSpec_To_v1alpha8_OpenStackClusterTemplateSpec(a.(*OpenStackClusterTemplateSpec), b.(*v1alpha8.OpenStackClusterTemplateSpec), scope)
+ 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((*v1alpha8.OpenStackClusterTemplateSpec)(nil), (*OpenStackClusterTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackClusterTemplateSpec_To_v1alpha7_OpenStackClusterTemplateSpec(a.(*v1alpha8.OpenStackClusterTemplateSpec), b.(*OpenStackClusterTemplateSpec), scope)
+ 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((*v1alpha8.OpenStackIdentityReference)(nil), (*OpenStackIdentityReference)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference(a.(*v1alpha8.OpenStackIdentityReference), b.(*OpenStackIdentityReference), scope)
+ if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*OpenStackMachine)(nil), (*v1alpha8.OpenStackMachine)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_OpenStackMachine_To_v1alpha8_OpenStackMachine(a.(*OpenStackMachine), b.(*v1alpha8.OpenStackMachine), scope)
+ if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*v1alpha8.OpenStackMachine)(nil), (*OpenStackMachine)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackMachine_To_v1alpha7_OpenStackMachine(a.(*v1alpha8.OpenStackMachine), b.(*OpenStackMachine), scope)
+ if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*OpenStackMachineList)(nil), (*v1alpha8.OpenStackMachineList)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_OpenStackMachineList_To_v1alpha8_OpenStackMachineList(a.(*OpenStackMachineList), b.(*v1alpha8.OpenStackMachineList), scope)
+ 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((*v1alpha8.OpenStackMachineList)(nil), (*OpenStackMachineList)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackMachineList_To_v1alpha7_OpenStackMachineList(a.(*v1alpha8.OpenStackMachineList), b.(*OpenStackMachineList), scope)
+ 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), (*v1alpha8.OpenStackMachineStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_OpenStackMachineStatus_To_v1alpha8_OpenStackMachineStatus(a.(*OpenStackMachineStatus), b.(*v1alpha8.OpenStackMachineStatus), scope)
+ 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), (*v1alpha8.OpenStackMachineTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate(a.(*OpenStackMachineTemplate), b.(*v1alpha8.OpenStackMachineTemplate), scope)
+ 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((*v1alpha8.OpenStackMachineTemplate)(nil), (*OpenStackMachineTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate(a.(*v1alpha8.OpenStackMachineTemplate), b.(*OpenStackMachineTemplate), scope)
+ 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), (*v1alpha8.OpenStackMachineTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_OpenStackMachineTemplateList_To_v1alpha8_OpenStackMachineTemplateList(a.(*OpenStackMachineTemplateList), b.(*v1alpha8.OpenStackMachineTemplateList), scope)
+ 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((*v1alpha8.OpenStackMachineTemplateList)(nil), (*OpenStackMachineTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackMachineTemplateList_To_v1alpha7_OpenStackMachineTemplateList(a.(*v1alpha8.OpenStackMachineTemplateList), b.(*OpenStackMachineTemplateList), scope)
+ 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), (*v1alpha8.OpenStackMachineTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_OpenStackMachineTemplateResource_To_v1alpha8_OpenStackMachineTemplateResource(a.(*OpenStackMachineTemplateResource), b.(*v1alpha8.OpenStackMachineTemplateResource), scope)
+ 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((*v1alpha8.OpenStackMachineTemplateResource)(nil), (*OpenStackMachineTemplateResource)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackMachineTemplateResource_To_v1alpha7_OpenStackMachineTemplateResource(a.(*v1alpha8.OpenStackMachineTemplateResource), b.(*OpenStackMachineTemplateResource), scope)
+ 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), (*v1alpha8.OpenStackMachineTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_OpenStackMachineTemplateSpec_To_v1alpha8_OpenStackMachineTemplateSpec(a.(*OpenStackMachineTemplateSpec), b.(*v1alpha8.OpenStackMachineTemplateSpec), scope)
+ 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((*v1alpha8.OpenStackMachineTemplateSpec)(nil), (*OpenStackMachineTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackMachineTemplateSpec_To_v1alpha7_OpenStackMachineTemplateSpec(a.(*v1alpha8.OpenStackMachineTemplateSpec), b.(*OpenStackMachineTemplateSpec), scope)
+ 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((*PortOpts)(nil), (*v1alpha8.PortOpts)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_PortOpts_To_v1alpha8_PortOpts(a.(*PortOpts), b.(*v1alpha8.PortOpts), scope)
+ if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*v1alpha8.PortOpts)(nil), (*PortOpts)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_PortOpts_To_v1alpha7_PortOpts(a.(*v1alpha8.PortOpts), b.(*PortOpts), scope)
+ if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*RootVolume)(nil), (*v1alpha8.RootVolume)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_RootVolume_To_v1alpha8_RootVolume(a.(*RootVolume), b.(*v1alpha8.RootVolume), scope)
+ if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*v1alpha8.RootVolume)(nil), (*RootVolume)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_RootVolume_To_v1alpha7_RootVolume(a.(*v1alpha8.RootVolume), b.(*RootVolume), scope)
+ if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*Router)(nil), (*v1alpha8.Router)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_Router_To_v1alpha8_Router(a.(*Router), b.(*v1alpha8.Router), scope)
+ 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((*v1alpha8.Router)(nil), (*Router)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_Router_To_v1alpha7_Router(a.(*v1alpha8.Router), b.(*Router), scope)
+ 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((*RouterFilter)(nil), (*v1alpha8.RouterFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_RouterFilter_To_v1alpha8_RouterFilter(a.(*RouterFilter), b.(*v1alpha8.RouterFilter), scope)
+ if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*v1alpha8.RouterFilter)(nil), (*RouterFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_RouterFilter_To_v1alpha7_RouterFilter(a.(*v1alpha8.RouterFilter), b.(*RouterFilter), scope)
+ if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*SecurityGroupFilter)(nil), (*v1alpha8.SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_SecurityGroupFilter_To_v1alpha8_SecurityGroupFilter(a.(*SecurityGroupFilter), b.(*v1alpha8.SecurityGroupFilter), scope)
+ if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*v1alpha8.SecurityGroupFilter)(nil), (*SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(a.(*v1alpha8.SecurityGroupFilter), b.(*SecurityGroupFilter), scope)
+ if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*Subnet)(nil), (*v1alpha8.Subnet)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_Subnet_To_v1alpha8_Subnet(a.(*Subnet), b.(*v1alpha8.Subnet), scope)
+ 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((*v1alpha8.Subnet)(nil), (*Subnet)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_Subnet_To_v1alpha7_Subnet(a.(*v1alpha8.Subnet), b.(*Subnet), scope)
+ 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((*SubnetFilter)(nil), (*v1alpha8.SubnetFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_SubnetFilter_To_v1alpha8_SubnetFilter(a.(*SubnetFilter), b.(*v1alpha8.SubnetFilter), scope)
+ if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*v1alpha8.SubnetFilter)(nil), (*SubnetFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_SubnetFilter_To_v1alpha7_SubnetFilter(a.(*v1alpha8.SubnetFilter), b.(*SubnetFilter), scope)
+ if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*ValueSpec)(nil), (*v1alpha8.ValueSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_ValueSpec_To_v1alpha8_ValueSpec(a.(*ValueSpec), b.(*v1alpha8.ValueSpec), scope)
+ 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((*v1alpha8.ValueSpec)(nil), (*ValueSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_ValueSpec_To_v1alpha7_ValueSpec(a.(*v1alpha8.ValueSpec), b.(*ValueSpec), scope)
+ 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((*Bastion)(nil), (*v1alpha8.Bastion)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_Bastion_To_v1alpha8_Bastion(a.(*Bastion), b.(*v1alpha8.Bastion), scope)
+ 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((*OpenStackClusterSpec)(nil), (*v1alpha8.OpenStackClusterSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(a.(*OpenStackClusterSpec), b.(*v1alpha8.OpenStackClusterSpec), scope)
+ 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), (*v1alpha8.OpenStackIdentityReference)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(a.(*OpenStackIdentityReference), b.(*v1alpha8.OpenStackIdentityReference), scope)
+ 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), (*v1alpha8.OpenStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(a.(*OpenStackMachineSpec), b.(*v1alpha8.OpenStackMachineSpec), scope)
+ 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((*SecurityGroup)(nil), (*v1alpha8.SecurityGroupStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha7_SecurityGroup_To_v1alpha8_SecurityGroupStatus(a.(*SecurityGroup), b.(*v1alpha8.SecurityGroupStatus), scope)
+ 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((*v1alpha8.BastionStatus)(nil), (*BastionStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_BastionStatus_To_v1alpha7_BastionStatus(a.(*v1alpha8.BastionStatus), b.(*BastionStatus), scope)
+ 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((*v1alpha8.Bastion)(nil), (*Bastion)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_Bastion_To_v1alpha7_Bastion(a.(*v1alpha8.Bastion), b.(*Bastion), scope)
+ 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((*v1alpha8.OpenStackClusterSpec)(nil), (*OpenStackClusterSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(a.(*v1alpha8.OpenStackClusterSpec), b.(*OpenStackClusterSpec), scope)
+ 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((*v1alpha8.OpenStackClusterStatus)(nil), (*OpenStackClusterStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(a.(*v1alpha8.OpenStackClusterStatus), b.(*OpenStackClusterStatus), scope)
+ 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((*v1alpha8.OpenStackMachineSpec)(nil), (*OpenStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(a.(*v1alpha8.OpenStackMachineSpec), b.(*OpenStackMachineSpec), scope)
+ 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((*v1alpha8.OpenStackMachineStatus)(nil), (*OpenStackMachineStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus(a.(*v1alpha8.OpenStackMachineStatus), b.(*OpenStackMachineStatus), scope)
+ 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((*v1alpha8.SecurityGroupStatus)(nil), (*SecurityGroup)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha8_SecurityGroupStatus_To_v1alpha7_SecurityGroup(a.(*v1alpha8.SecurityGroupStatus), b.(*SecurityGroup), scope)
+ 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
}
return nil
}
-func autoConvert_v1alpha7_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalancer(in *APIServerLoadBalancer, out *v1alpha8.APIServerLoadBalancer, s conversion.Scope) error {
+func autoConvert_v1alpha7_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer(in *APIServerLoadBalancer, out *v1beta1.APIServerLoadBalancer, s conversion.Scope) error {
out.Enabled = in.Enabled
out.AdditionalPorts = *(*[]int)(unsafe.Pointer(&in.AdditionalPorts))
out.AllowedCIDRs = *(*[]string)(unsafe.Pointer(&in.AllowedCIDRs))
@@ -450,12 +450,12 @@ func autoConvert_v1alpha7_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalance
return nil
}
-// Convert_v1alpha7_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalancer is an autogenerated conversion function.
-func Convert_v1alpha7_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalancer(in *APIServerLoadBalancer, out *v1alpha8.APIServerLoadBalancer, s conversion.Scope) error {
- return autoConvert_v1alpha7_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalancer(in, out, s)
+// Convert_v1alpha7_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer is an autogenerated conversion function.
+func Convert_v1alpha7_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer(in *APIServerLoadBalancer, out *v1beta1.APIServerLoadBalancer, s conversion.Scope) error {
+ return autoConvert_v1alpha7_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer(in, out, s)
}
-func autoConvert_v1alpha8_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer(in *v1alpha8.APIServerLoadBalancer, out *APIServerLoadBalancer, s conversion.Scope) error {
+func autoConvert_v1beta1_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer(in *v1beta1.APIServerLoadBalancer, out *APIServerLoadBalancer, s conversion.Scope) error {
out.Enabled = in.Enabled
out.AdditionalPorts = *(*[]int)(unsafe.Pointer(&in.AdditionalPorts))
out.AllowedCIDRs = *(*[]string)(unsafe.Pointer(&in.AllowedCIDRs))
@@ -463,73 +463,73 @@ func autoConvert_v1alpha8_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalance
return nil
}
-// Convert_v1alpha8_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer is an autogenerated conversion function.
-func Convert_v1alpha8_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer(in *v1alpha8.APIServerLoadBalancer, out *APIServerLoadBalancer, s conversion.Scope) error {
- return autoConvert_v1alpha8_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer(in, out, s)
+// Convert_v1beta1_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer is an autogenerated conversion function.
+func Convert_v1beta1_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer(in *v1beta1.APIServerLoadBalancer, out *APIServerLoadBalancer, s conversion.Scope) error {
+ return autoConvert_v1beta1_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer(in, out, s)
}
-func autoConvert_v1alpha7_AdditionalBlockDevice_To_v1alpha8_AdditionalBlockDevice(in *AdditionalBlockDevice, out *v1alpha8.AdditionalBlockDevice, s conversion.Scope) error {
+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_v1alpha8_BlockDeviceStorage(&in.Storage, &out.Storage, s); err != nil {
+ if err := Convert_v1alpha7_BlockDeviceStorage_To_v1beta1_BlockDeviceStorage(&in.Storage, &out.Storage, s); err != nil {
return err
}
return nil
}
-// Convert_v1alpha7_AdditionalBlockDevice_To_v1alpha8_AdditionalBlockDevice is an autogenerated conversion function.
-func Convert_v1alpha7_AdditionalBlockDevice_To_v1alpha8_AdditionalBlockDevice(in *AdditionalBlockDevice, out *v1alpha8.AdditionalBlockDevice, s conversion.Scope) error {
- return autoConvert_v1alpha7_AdditionalBlockDevice_To_v1alpha8_AdditionalBlockDevice(in, out, s)
+// 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_v1alpha8_AdditionalBlockDevice_To_v1alpha7_AdditionalBlockDevice(in *v1alpha8.AdditionalBlockDevice, out *AdditionalBlockDevice, s conversion.Scope) error {
+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_v1alpha8_BlockDeviceStorage_To_v1alpha7_BlockDeviceStorage(&in.Storage, &out.Storage, s); err != nil {
+ if err := Convert_v1beta1_BlockDeviceStorage_To_v1alpha7_BlockDeviceStorage(&in.Storage, &out.Storage, s); err != nil {
return err
}
return nil
}
-// Convert_v1alpha8_AdditionalBlockDevice_To_v1alpha7_AdditionalBlockDevice is an autogenerated conversion function.
-func Convert_v1alpha8_AdditionalBlockDevice_To_v1alpha7_AdditionalBlockDevice(in *v1alpha8.AdditionalBlockDevice, out *AdditionalBlockDevice, s conversion.Scope) error {
- return autoConvert_v1alpha8_AdditionalBlockDevice_To_v1alpha7_AdditionalBlockDevice(in, out, s)
+// 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_v1alpha8_AddressPair(in *AddressPair, out *v1alpha8.AddressPair, s conversion.Scope) error {
+func autoConvert_v1alpha7_AddressPair_To_v1beta1_AddressPair(in *AddressPair, out *v1beta1.AddressPair, s conversion.Scope) error {
out.IPAddress = in.IPAddress
out.MACAddress = in.MACAddress
return nil
}
-// Convert_v1alpha7_AddressPair_To_v1alpha8_AddressPair is an autogenerated conversion function.
-func Convert_v1alpha7_AddressPair_To_v1alpha8_AddressPair(in *AddressPair, out *v1alpha8.AddressPair, s conversion.Scope) error {
- return autoConvert_v1alpha7_AddressPair_To_v1alpha8_AddressPair(in, out, s)
+// 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_v1alpha8_AddressPair_To_v1alpha7_AddressPair(in *v1alpha8.AddressPair, out *AddressPair, s conversion.Scope) error {
+func autoConvert_v1beta1_AddressPair_To_v1alpha7_AddressPair(in *v1beta1.AddressPair, out *AddressPair, s conversion.Scope) error {
out.IPAddress = in.IPAddress
out.MACAddress = in.MACAddress
return nil
}
-// Convert_v1alpha8_AddressPair_To_v1alpha7_AddressPair is an autogenerated conversion function.
-func Convert_v1alpha8_AddressPair_To_v1alpha7_AddressPair(in *v1alpha8.AddressPair, out *AddressPair, s conversion.Scope) error {
- return autoConvert_v1alpha8_AddressPair_To_v1alpha7_AddressPair(in, out, s)
+// 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_v1alpha8_Bastion(in *Bastion, out *v1alpha8.Bastion, s conversion.Scope) error {
+func autoConvert_v1alpha7_Bastion_To_v1beta1_Bastion(in *Bastion, out *v1beta1.Bastion, s conversion.Scope) error {
out.Enabled = in.Enabled
- if err := Convert_v1alpha7_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(&in.Instance, &out.Instance, s); err != nil {
+ if err := Convert_v1alpha7_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(&in.Instance, &out.Instance, s); err != nil {
return err
}
out.AvailabilityZone = in.AvailabilityZone
return nil
}
-func autoConvert_v1alpha8_Bastion_To_v1alpha7_Bastion(in *v1alpha8.Bastion, out *Bastion, s conversion.Scope) error {
+func autoConvert_v1beta1_Bastion_To_v1alpha7_Bastion(in *v1beta1.Bastion, out *Bastion, s conversion.Scope) error {
out.Enabled = in.Enabled
- if err := Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(&in.Instance, &out.Instance, s); err != nil {
+ if err := Convert_v1beta1_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(&in.Instance, &out.Instance, s); err != nil {
return err
}
out.AvailabilityZone = in.AvailabilityZone
@@ -537,22 +537,22 @@ func autoConvert_v1alpha8_Bastion_To_v1alpha7_Bastion(in *v1alpha8.Bastion, out
return nil
}
-func autoConvert_v1alpha7_BastionStatus_To_v1alpha8_BastionStatus(in *BastionStatus, out *v1alpha8.BastionStatus, s conversion.Scope) error {
+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 = v1alpha8.InstanceState(in.State)
+ out.State = v1beta1.InstanceState(in.State)
out.IP = in.IP
out.FloatingIP = in.FloatingIP
return nil
}
-// Convert_v1alpha7_BastionStatus_To_v1alpha8_BastionStatus is an autogenerated conversion function.
-func Convert_v1alpha7_BastionStatus_To_v1alpha8_BastionStatus(in *BastionStatus, out *v1alpha8.BastionStatus, s conversion.Scope) error {
- return autoConvert_v1alpha7_BastionStatus_To_v1alpha8_BastionStatus(in, out, s)
+// 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_v1alpha8_BastionStatus_To_v1alpha7_BastionStatus(in *v1alpha8.BastionStatus, out *BastionStatus, s conversion.Scope) error {
+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
@@ -564,121 +564,121 @@ func autoConvert_v1alpha8_BastionStatus_To_v1alpha7_BastionStatus(in *v1alpha8.B
return nil
}
-func autoConvert_v1alpha7_BindingProfile_To_v1alpha8_BindingProfile(in *BindingProfile, out *v1alpha8.BindingProfile, s conversion.Scope) error {
+func autoConvert_v1alpha7_BindingProfile_To_v1beta1_BindingProfile(in *BindingProfile, out *v1beta1.BindingProfile, s conversion.Scope) error {
out.OVSHWOffload = in.OVSHWOffload
out.TrustedVF = in.TrustedVF
return nil
}
-// Convert_v1alpha7_BindingProfile_To_v1alpha8_BindingProfile is an autogenerated conversion function.
-func Convert_v1alpha7_BindingProfile_To_v1alpha8_BindingProfile(in *BindingProfile, out *v1alpha8.BindingProfile, s conversion.Scope) error {
- return autoConvert_v1alpha7_BindingProfile_To_v1alpha8_BindingProfile(in, out, s)
+// 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_v1alpha8_BindingProfile_To_v1alpha7_BindingProfile(in *v1alpha8.BindingProfile, out *BindingProfile, s conversion.Scope) error {
+func autoConvert_v1beta1_BindingProfile_To_v1alpha7_BindingProfile(in *v1beta1.BindingProfile, out *BindingProfile, s conversion.Scope) error {
out.OVSHWOffload = in.OVSHWOffload
out.TrustedVF = in.TrustedVF
return nil
}
-// Convert_v1alpha8_BindingProfile_To_v1alpha7_BindingProfile is an autogenerated conversion function.
-func Convert_v1alpha8_BindingProfile_To_v1alpha7_BindingProfile(in *v1alpha8.BindingProfile, out *BindingProfile, s conversion.Scope) error {
- return autoConvert_v1alpha8_BindingProfile_To_v1alpha7_BindingProfile(in, out, s)
+// 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_v1alpha8_BlockDeviceStorage(in *BlockDeviceStorage, out *v1alpha8.BlockDeviceStorage, s conversion.Scope) error {
- out.Type = v1alpha8.BlockDeviceType(in.Type)
- out.Volume = (*v1alpha8.BlockDeviceVolume)(unsafe.Pointer(in.Volume))
+func autoConvert_v1alpha7_BlockDeviceStorage_To_v1beta1_BlockDeviceStorage(in *BlockDeviceStorage, out *v1beta1.BlockDeviceStorage, s conversion.Scope) error {
+ out.Type = v1beta1.BlockDeviceType(in.Type)
+ out.Volume = (*v1beta1.BlockDeviceVolume)(unsafe.Pointer(in.Volume))
return nil
}
-// Convert_v1alpha7_BlockDeviceStorage_To_v1alpha8_BlockDeviceStorage is an autogenerated conversion function.
-func Convert_v1alpha7_BlockDeviceStorage_To_v1alpha8_BlockDeviceStorage(in *BlockDeviceStorage, out *v1alpha8.BlockDeviceStorage, s conversion.Scope) error {
- return autoConvert_v1alpha7_BlockDeviceStorage_To_v1alpha8_BlockDeviceStorage(in, out, s)
+// 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_v1alpha8_BlockDeviceStorage_To_v1alpha7_BlockDeviceStorage(in *v1alpha8.BlockDeviceStorage, out *BlockDeviceStorage, s conversion.Scope) error {
+func autoConvert_v1beta1_BlockDeviceStorage_To_v1alpha7_BlockDeviceStorage(in *v1beta1.BlockDeviceStorage, out *BlockDeviceStorage, s conversion.Scope) error {
out.Type = BlockDeviceType(in.Type)
out.Volume = (*BlockDeviceVolume)(unsafe.Pointer(in.Volume))
return nil
}
-// Convert_v1alpha8_BlockDeviceStorage_To_v1alpha7_BlockDeviceStorage is an autogenerated conversion function.
-func Convert_v1alpha8_BlockDeviceStorage_To_v1alpha7_BlockDeviceStorage(in *v1alpha8.BlockDeviceStorage, out *BlockDeviceStorage, s conversion.Scope) error {
- return autoConvert_v1alpha8_BlockDeviceStorage_To_v1alpha7_BlockDeviceStorage(in, out, s)
+// 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_v1alpha8_BlockDeviceVolume(in *BlockDeviceVolume, out *v1alpha8.BlockDeviceVolume, s conversion.Scope) error {
+func autoConvert_v1alpha7_BlockDeviceVolume_To_v1beta1_BlockDeviceVolume(in *BlockDeviceVolume, out *v1beta1.BlockDeviceVolume, s conversion.Scope) error {
out.Type = in.Type
out.AvailabilityZone = in.AvailabilityZone
return nil
}
-// Convert_v1alpha7_BlockDeviceVolume_To_v1alpha8_BlockDeviceVolume is an autogenerated conversion function.
-func Convert_v1alpha7_BlockDeviceVolume_To_v1alpha8_BlockDeviceVolume(in *BlockDeviceVolume, out *v1alpha8.BlockDeviceVolume, s conversion.Scope) error {
- return autoConvert_v1alpha7_BlockDeviceVolume_To_v1alpha8_BlockDeviceVolume(in, out, s)
+// 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_v1alpha8_BlockDeviceVolume_To_v1alpha7_BlockDeviceVolume(in *v1alpha8.BlockDeviceVolume, out *BlockDeviceVolume, s conversion.Scope) error {
+func autoConvert_v1beta1_BlockDeviceVolume_To_v1alpha7_BlockDeviceVolume(in *v1beta1.BlockDeviceVolume, out *BlockDeviceVolume, s conversion.Scope) error {
out.Type = in.Type
out.AvailabilityZone = in.AvailabilityZone
return nil
}
-// Convert_v1alpha8_BlockDeviceVolume_To_v1alpha7_BlockDeviceVolume is an autogenerated conversion function.
-func Convert_v1alpha8_BlockDeviceVolume_To_v1alpha7_BlockDeviceVolume(in *v1alpha8.BlockDeviceVolume, out *BlockDeviceVolume, s conversion.Scope) error {
- return autoConvert_v1alpha8_BlockDeviceVolume_To_v1alpha7_BlockDeviceVolume(in, out, s)
+// 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_v1alpha8_ExternalRouterIPParam(in *ExternalRouterIPParam, out *v1alpha8.ExternalRouterIPParam, s conversion.Scope) error {
+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_v1alpha8_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil {
+ if err := Convert_v1alpha7_SubnetFilter_To_v1beta1_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil {
return err
}
return nil
}
-// Convert_v1alpha7_ExternalRouterIPParam_To_v1alpha8_ExternalRouterIPParam is an autogenerated conversion function.
-func Convert_v1alpha7_ExternalRouterIPParam_To_v1alpha8_ExternalRouterIPParam(in *ExternalRouterIPParam, out *v1alpha8.ExternalRouterIPParam, s conversion.Scope) error {
- return autoConvert_v1alpha7_ExternalRouterIPParam_To_v1alpha8_ExternalRouterIPParam(in, out, s)
+// 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_v1alpha8_ExternalRouterIPParam_To_v1alpha7_ExternalRouterIPParam(in *v1alpha8.ExternalRouterIPParam, out *ExternalRouterIPParam, s conversion.Scope) error {
+func autoConvert_v1beta1_ExternalRouterIPParam_To_v1alpha7_ExternalRouterIPParam(in *v1beta1.ExternalRouterIPParam, out *ExternalRouterIPParam, s conversion.Scope) error {
out.FixedIP = in.FixedIP
- if err := Convert_v1alpha8_SubnetFilter_To_v1alpha7_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil {
+ if err := Convert_v1beta1_SubnetFilter_To_v1alpha7_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil {
return err
}
return nil
}
-// Convert_v1alpha8_ExternalRouterIPParam_To_v1alpha7_ExternalRouterIPParam is an autogenerated conversion function.
-func Convert_v1alpha8_ExternalRouterIPParam_To_v1alpha7_ExternalRouterIPParam(in *v1alpha8.ExternalRouterIPParam, out *ExternalRouterIPParam, s conversion.Scope) error {
- return autoConvert_v1alpha8_ExternalRouterIPParam_To_v1alpha7_ExternalRouterIPParam(in, out, s)
+// 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_v1alpha8_FixedIP(in *FixedIP, out *v1alpha8.FixedIP, s conversion.Scope) error {
- out.Subnet = (*v1alpha8.SubnetFilter)(unsafe.Pointer(in.Subnet))
+func autoConvert_v1alpha7_FixedIP_To_v1beta1_FixedIP(in *FixedIP, out *v1beta1.FixedIP, s conversion.Scope) error {
+ out.Subnet = (*v1beta1.SubnetFilter)(unsafe.Pointer(in.Subnet))
out.IPAddress = in.IPAddress
return nil
}
-// Convert_v1alpha7_FixedIP_To_v1alpha8_FixedIP is an autogenerated conversion function.
-func Convert_v1alpha7_FixedIP_To_v1alpha8_FixedIP(in *FixedIP, out *v1alpha8.FixedIP, s conversion.Scope) error {
- return autoConvert_v1alpha7_FixedIP_To_v1alpha8_FixedIP(in, out, s)
+// 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_v1alpha8_FixedIP_To_v1alpha7_FixedIP(in *v1alpha8.FixedIP, out *FixedIP, s conversion.Scope) error {
+func autoConvert_v1beta1_FixedIP_To_v1alpha7_FixedIP(in *v1beta1.FixedIP, out *FixedIP, s conversion.Scope) error {
out.Subnet = (*SubnetFilter)(unsafe.Pointer(in.Subnet))
out.IPAddress = in.IPAddress
return nil
}
-// Convert_v1alpha8_FixedIP_To_v1alpha7_FixedIP is an autogenerated conversion function.
-func Convert_v1alpha8_FixedIP_To_v1alpha7_FixedIP(in *v1alpha8.FixedIP, out *FixedIP, s conversion.Scope) error {
- return autoConvert_v1alpha8_FixedIP_To_v1alpha7_FixedIP(in, out, s)
+// 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_v1alpha8_LoadBalancer(in *LoadBalancer, out *v1alpha8.LoadBalancer, s conversion.Scope) error {
+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
@@ -688,12 +688,12 @@ func autoConvert_v1alpha7_LoadBalancer_To_v1alpha8_LoadBalancer(in *LoadBalancer
return nil
}
-// Convert_v1alpha7_LoadBalancer_To_v1alpha8_LoadBalancer is an autogenerated conversion function.
-func Convert_v1alpha7_LoadBalancer_To_v1alpha8_LoadBalancer(in *LoadBalancer, out *v1alpha8.LoadBalancer, s conversion.Scope) error {
- return autoConvert_v1alpha7_LoadBalancer_To_v1alpha8_LoadBalancer(in, out, s)
+// 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_v1alpha8_LoadBalancer_To_v1alpha7_LoadBalancer(in *v1alpha8.LoadBalancer, out *LoadBalancer, s conversion.Scope) error {
+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
@@ -703,12 +703,12 @@ func autoConvert_v1alpha8_LoadBalancer_To_v1alpha7_LoadBalancer(in *v1alpha8.Loa
return nil
}
-// Convert_v1alpha8_LoadBalancer_To_v1alpha7_LoadBalancer is an autogenerated conversion function.
-func Convert_v1alpha8_LoadBalancer_To_v1alpha7_LoadBalancer(in *v1alpha8.LoadBalancer, out *LoadBalancer, s conversion.Scope) error {
- return autoConvert_v1alpha8_LoadBalancer_To_v1alpha7_LoadBalancer(in, out, s)
+// Convert_v1beta1_LoadBalancer_To_v1alpha7_LoadBalancer is an autogenerated conversion function.
+func Convert_v1beta1_LoadBalancer_To_v1alpha7_LoadBalancer(in *v1beta1.LoadBalancer, out *LoadBalancer, s conversion.Scope) error {
+ return autoConvert_v1beta1_LoadBalancer_To_v1alpha7_LoadBalancer(in, out, s)
}
-func autoConvert_v1alpha7_NetworkFilter_To_v1alpha8_NetworkFilter(in *NetworkFilter, out *v1alpha8.NetworkFilter, s conversion.Scope) error {
+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
@@ -720,12 +720,12 @@ func autoConvert_v1alpha7_NetworkFilter_To_v1alpha8_NetworkFilter(in *NetworkFil
return nil
}
-// Convert_v1alpha7_NetworkFilter_To_v1alpha8_NetworkFilter is an autogenerated conversion function.
-func Convert_v1alpha7_NetworkFilter_To_v1alpha8_NetworkFilter(in *NetworkFilter, out *v1alpha8.NetworkFilter, s conversion.Scope) error {
- return autoConvert_v1alpha7_NetworkFilter_To_v1alpha8_NetworkFilter(in, out, s)
+// Convert_v1alpha7_NetworkFilter_To_v1beta1_NetworkFilter is an autogenerated conversion function.
+func Convert_v1alpha7_NetworkFilter_To_v1beta1_NetworkFilter(in *NetworkFilter, out *v1beta1.NetworkFilter, s conversion.Scope) error {
+ return autoConvert_v1alpha7_NetworkFilter_To_v1beta1_NetworkFilter(in, out, s)
}
-func autoConvert_v1alpha8_NetworkFilter_To_v1alpha7_NetworkFilter(in *v1alpha8.NetworkFilter, out *NetworkFilter, s conversion.Scope) error {
+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
@@ -737,100 +737,100 @@ func autoConvert_v1alpha8_NetworkFilter_To_v1alpha7_NetworkFilter(in *v1alpha8.N
return nil
}
-// Convert_v1alpha8_NetworkFilter_To_v1alpha7_NetworkFilter is an autogenerated conversion function.
-func Convert_v1alpha8_NetworkFilter_To_v1alpha7_NetworkFilter(in *v1alpha8.NetworkFilter, out *NetworkFilter, s conversion.Scope) error {
- return autoConvert_v1alpha8_NetworkFilter_To_v1alpha7_NetworkFilter(in, out, s)
+// Convert_v1beta1_NetworkFilter_To_v1alpha7_NetworkFilter is an autogenerated conversion function.
+func Convert_v1beta1_NetworkFilter_To_v1alpha7_NetworkFilter(in *v1beta1.NetworkFilter, out *NetworkFilter, s conversion.Scope) error {
+ return autoConvert_v1beta1_NetworkFilter_To_v1alpha7_NetworkFilter(in, out, s)
}
-func autoConvert_v1alpha7_NetworkStatus_To_v1alpha8_NetworkStatus(in *NetworkStatus, out *v1alpha8.NetworkStatus, s conversion.Scope) error {
+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_v1alpha8_NetworkStatus is an autogenerated conversion function.
-func Convert_v1alpha7_NetworkStatus_To_v1alpha8_NetworkStatus(in *NetworkStatus, out *v1alpha8.NetworkStatus, s conversion.Scope) error {
- return autoConvert_v1alpha7_NetworkStatus_To_v1alpha8_NetworkStatus(in, out, s)
+// 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_v1alpha8_NetworkStatus_To_v1alpha7_NetworkStatus(in *v1alpha8.NetworkStatus, out *NetworkStatus, s conversion.Scope) error {
+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_v1alpha8_NetworkStatus_To_v1alpha7_NetworkStatus is an autogenerated conversion function.
-func Convert_v1alpha8_NetworkStatus_To_v1alpha7_NetworkStatus(in *v1alpha8.NetworkStatus, out *NetworkStatus, s conversion.Scope) error {
- return autoConvert_v1alpha8_NetworkStatus_To_v1alpha7_NetworkStatus(in, out, s)
+// 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_v1alpha8_NetworkStatusWithSubnets(in *NetworkStatusWithSubnets, out *v1alpha8.NetworkStatusWithSubnets, s conversion.Scope) error {
- if err := Convert_v1alpha7_NetworkStatus_To_v1alpha8_NetworkStatus(&in.NetworkStatus, &out.NetworkStatus, s); err != nil {
+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 = *(*[]v1alpha8.Subnet)(unsafe.Pointer(&in.Subnets))
+ out.Subnets = *(*[]v1beta1.Subnet)(unsafe.Pointer(&in.Subnets))
return nil
}
-// Convert_v1alpha7_NetworkStatusWithSubnets_To_v1alpha8_NetworkStatusWithSubnets is an autogenerated conversion function.
-func Convert_v1alpha7_NetworkStatusWithSubnets_To_v1alpha8_NetworkStatusWithSubnets(in *NetworkStatusWithSubnets, out *v1alpha8.NetworkStatusWithSubnets, s conversion.Scope) error {
- return autoConvert_v1alpha7_NetworkStatusWithSubnets_To_v1alpha8_NetworkStatusWithSubnets(in, out, s)
+// 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_v1alpha8_NetworkStatusWithSubnets_To_v1alpha7_NetworkStatusWithSubnets(in *v1alpha8.NetworkStatusWithSubnets, out *NetworkStatusWithSubnets, s conversion.Scope) error {
- if err := Convert_v1alpha8_NetworkStatus_To_v1alpha7_NetworkStatus(&in.NetworkStatus, &out.NetworkStatus, s); err != nil {
+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_v1alpha8_NetworkStatusWithSubnets_To_v1alpha7_NetworkStatusWithSubnets is an autogenerated conversion function.
-func Convert_v1alpha8_NetworkStatusWithSubnets_To_v1alpha7_NetworkStatusWithSubnets(in *v1alpha8.NetworkStatusWithSubnets, out *NetworkStatusWithSubnets, s conversion.Scope) error {
- return autoConvert_v1alpha8_NetworkStatusWithSubnets_To_v1alpha7_NetworkStatusWithSubnets(in, out, s)
+// 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_v1alpha8_OpenStackCluster(in *OpenStackCluster, out *v1alpha8.OpenStackCluster, s conversion.Scope) error {
+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_v1alpha8_OpenStackClusterSpec(&in.Spec, &out.Spec, s); err != nil {
+ if err := Convert_v1alpha7_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(&in.Spec, &out.Spec, s); err != nil {
return err
}
- if err := Convert_v1alpha7_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterStatus(&in.Status, &out.Status, s); err != nil {
+ if err := Convert_v1alpha7_OpenStackClusterStatus_To_v1beta1_OpenStackClusterStatus(&in.Status, &out.Status, s); err != nil {
return err
}
return nil
}
-// Convert_v1alpha7_OpenStackCluster_To_v1alpha8_OpenStackCluster is an autogenerated conversion function.
-func Convert_v1alpha7_OpenStackCluster_To_v1alpha8_OpenStackCluster(in *OpenStackCluster, out *v1alpha8.OpenStackCluster, s conversion.Scope) error {
- return autoConvert_v1alpha7_OpenStackCluster_To_v1alpha8_OpenStackCluster(in, out, s)
+// 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_v1alpha8_OpenStackCluster_To_v1alpha7_OpenStackCluster(in *v1alpha8.OpenStackCluster, out *OpenStackCluster, s conversion.Scope) error {
+func autoConvert_v1beta1_OpenStackCluster_To_v1alpha7_OpenStackCluster(in *v1beta1.OpenStackCluster, out *OpenStackCluster, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
- if err := Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(&in.Spec, &out.Spec, s); err != nil {
+ if err := Convert_v1beta1_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(&in.Spec, &out.Spec, s); err != nil {
return err
}
- if err := Convert_v1alpha8_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(&in.Status, &out.Status, s); err != nil {
+ if err := Convert_v1beta1_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(&in.Status, &out.Status, s); err != nil {
return err
}
return nil
}
-// Convert_v1alpha8_OpenStackCluster_To_v1alpha7_OpenStackCluster is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackCluster_To_v1alpha7_OpenStackCluster(in *v1alpha8.OpenStackCluster, out *OpenStackCluster, s conversion.Scope) error {
- return autoConvert_v1alpha8_OpenStackCluster_To_v1alpha7_OpenStackCluster(in, out, s)
+// 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_v1alpha8_OpenStackClusterList(in *OpenStackClusterList, out *v1alpha8.OpenStackClusterList, s conversion.Scope) error {
+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([]v1alpha8.OpenStackCluster, len(*in))
+ *out = make([]v1beta1.OpenStackCluster, len(*in))
for i := range *in {
- if err := Convert_v1alpha7_OpenStackCluster_To_v1alpha8_OpenStackCluster(&(*in)[i], &(*out)[i], s); err != nil {
+ if err := Convert_v1alpha7_OpenStackCluster_To_v1beta1_OpenStackCluster(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -840,18 +840,18 @@ func autoConvert_v1alpha7_OpenStackClusterList_To_v1alpha8_OpenStackClusterList(
return nil
}
-// Convert_v1alpha7_OpenStackClusterList_To_v1alpha8_OpenStackClusterList is an autogenerated conversion function.
-func Convert_v1alpha7_OpenStackClusterList_To_v1alpha8_OpenStackClusterList(in *OpenStackClusterList, out *v1alpha8.OpenStackClusterList, s conversion.Scope) error {
- return autoConvert_v1alpha7_OpenStackClusterList_To_v1alpha8_OpenStackClusterList(in, out, s)
+// 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_v1alpha8_OpenStackClusterList_To_v1alpha7_OpenStackClusterList(in *v1alpha8.OpenStackClusterList, out *OpenStackClusterList, s conversion.Scope) error {
+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_v1alpha8_OpenStackCluster_To_v1alpha7_OpenStackCluster(&(*in)[i], &(*out)[i], s); err != nil {
+ if err := Convert_v1beta1_OpenStackCluster_To_v1alpha7_OpenStackCluster(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -861,31 +861,31 @@ func autoConvert_v1alpha8_OpenStackClusterList_To_v1alpha7_OpenStackClusterList(
return nil
}
-// Convert_v1alpha8_OpenStackClusterList_To_v1alpha7_OpenStackClusterList is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackClusterList_To_v1alpha7_OpenStackClusterList(in *v1alpha8.OpenStackClusterList, out *OpenStackClusterList, s conversion.Scope) error {
- return autoConvert_v1alpha8_OpenStackClusterList_To_v1alpha7_OpenStackClusterList(in, out, s)
+// 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_v1alpha8_OpenStackClusterSpec(in *OpenStackClusterSpec, out *v1alpha8.OpenStackClusterSpec, s conversion.Scope) error {
+func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *OpenStackClusterSpec, out *v1beta1.OpenStackClusterSpec, s conversion.Scope) error {
out.CloudName = in.CloudName
// WARNING: in.NodeCIDR requires manual conversion: does not exist in peer-type
- out.Router = (*v1alpha8.RouterFilter)(unsafe.Pointer(in.Router))
- if err := Convert_v1alpha7_NetworkFilter_To_v1alpha8_NetworkFilter(&in.Network, &out.Network, s); err != nil {
+ out.Router = (*v1beta1.RouterFilter)(unsafe.Pointer(in.Router))
+ if err := Convert_v1alpha7_NetworkFilter_To_v1beta1_NetworkFilter(&in.Network, &out.Network, s); err != nil {
return err
}
// WARNING: in.Subnet requires manual conversion: does not exist in peer-type
out.NetworkMTU = in.NetworkMTU
// WARNING: in.DNSNameservers requires manual conversion: does not exist in peer-type
- out.ExternalRouterIPs = *(*[]v1alpha8.ExternalRouterIPParam)(unsafe.Pointer(&in.ExternalRouterIPs))
+ out.ExternalRouterIPs = *(*[]v1beta1.ExternalRouterIPParam)(unsafe.Pointer(&in.ExternalRouterIPs))
// WARNING: in.ExternalNetworkID requires manual conversion: does not exist in peer-type
- if err := Convert_v1alpha7_APIServerLoadBalancer_To_v1alpha8_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil {
+ if err := Convert_v1alpha7_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil {
return err
}
out.DisableAPIServerFloatingIP = in.DisableAPIServerFloatingIP
out.APIServerFloatingIP = in.APIServerFloatingIP
out.APIServerFixedIP = in.APIServerFixedIP
out.APIServerPort = in.APIServerPort
- // WARNING: in.ManagedSecurityGroups requires manual conversion: inconvertible types (bool vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8.ManagedSecurityGroups)
+ // 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
out.DisablePortSecurity = in.DisablePortSecurity
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
@@ -894,8 +894,8 @@ func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(
out.ControlPlaneOmitAvailabilityZone = in.ControlPlaneOmitAvailabilityZone
if in.Bastion != nil {
in, out := &in.Bastion, &out.Bastion
- *out = new(v1alpha8.Bastion)
- if err := Convert_v1alpha7_Bastion_To_v1alpha8_Bastion(*in, *out, s); err != nil {
+ *out = new(v1beta1.Bastion)
+ if err := Convert_v1alpha7_Bastion_To_v1beta1_Bastion(*in, *out, s); err != nil {
return err
}
} else {
@@ -903,8 +903,8 @@ func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(
}
if in.IdentityRef != nil {
in, out := &in.IdentityRef, &out.IdentityRef
- *out = new(v1alpha8.OpenStackIdentityReference)
- if err := Convert_v1alpha7_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(*in, *out, s); err != nil {
+ *out = new(v1beta1.OpenStackIdentityReference)
+ if err := Convert_v1alpha7_OpenStackIdentityReference_To_v1beta1_OpenStackIdentityReference(*in, *out, s); err != nil {
return err
}
} else {
@@ -913,11 +913,11 @@ func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(
return nil
}
-func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in *v1alpha8.OpenStackClusterSpec, out *OpenStackClusterSpec, s conversion.Scope) error {
+func autoConvert_v1beta1_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in *v1beta1.OpenStackClusterSpec, out *OpenStackClusterSpec, s conversion.Scope) error {
out.CloudName = in.CloudName
// WARNING: in.ManagedSubnets requires manual conversion: does not exist in peer-type
out.Router = (*RouterFilter)(unsafe.Pointer(in.Router))
- if err := Convert_v1alpha8_NetworkFilter_To_v1alpha7_NetworkFilter(&in.Network, &out.Network, s); err != nil {
+ if err := Convert_v1beta1_NetworkFilter_To_v1alpha7_NetworkFilter(&in.Network, &out.Network, s); err != nil {
return err
}
// WARNING: in.Subnets requires manual conversion: does not exist in peer-type
@@ -925,14 +925,14 @@ func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(
out.ExternalRouterIPs = *(*[]ExternalRouterIPParam)(unsafe.Pointer(&in.ExternalRouterIPs))
// WARNING: in.ExternalNetwork requires manual conversion: does not exist in peer-type
// WARNING: in.DisableExternalNetwork requires manual conversion: does not exist in peer-type
- if err := Convert_v1alpha8_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil {
+ if err := Convert_v1beta1_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil {
return err
}
out.DisableAPIServerFloatingIP = in.DisableAPIServerFloatingIP
out.APIServerFloatingIP = in.APIServerFloatingIP
out.APIServerFixedIP = in.APIServerFixedIP
out.APIServerPort = in.APIServerPort
- // WARNING: in.ManagedSecurityGroups requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8.ManagedSecurityGroups vs bool)
+ // WARNING: in.ManagedSecurityGroups requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ManagedSecurityGroups vs bool)
out.DisablePortSecurity = in.DisablePortSecurity
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
out.ControlPlaneEndpoint = in.ControlPlaneEndpoint
@@ -941,7 +941,7 @@ func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(
if in.Bastion != nil {
in, out := &in.Bastion, &out.Bastion
*out = new(Bastion)
- if err := Convert_v1alpha8_Bastion_To_v1alpha7_Bastion(*in, *out, s); err != nil {
+ if err := Convert_v1beta1_Bastion_To_v1alpha7_Bastion(*in, *out, s); err != nil {
return err
}
} else {
@@ -950,7 +950,7 @@ func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(
if in.IdentityRef != nil {
in, out := &in.IdentityRef, &out.IdentityRef
*out = new(OpenStackIdentityReference)
- if err := Convert_v1alpha8_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference(*in, *out, s); err != nil {
+ if err := Convert_v1beta1_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference(*in, *out, s); err != nil {
return err
}
} else {
@@ -959,17 +959,17 @@ func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(
return nil
}
-func autoConvert_v1alpha7_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterStatus(in *OpenStackClusterStatus, out *v1alpha8.OpenStackClusterStatus, s conversion.Scope) error {
+func autoConvert_v1alpha7_OpenStackClusterStatus_To_v1beta1_OpenStackClusterStatus(in *OpenStackClusterStatus, out *v1beta1.OpenStackClusterStatus, s conversion.Scope) error {
out.Ready = in.Ready
- out.Network = (*v1alpha8.NetworkStatusWithSubnets)(unsafe.Pointer(in.Network))
- out.ExternalNetwork = (*v1alpha8.NetworkStatus)(unsafe.Pointer(in.ExternalNetwork))
- out.Router = (*v1alpha8.Router)(unsafe.Pointer(in.Router))
- out.APIServerLoadBalancer = (*v1alpha8.LoadBalancer)(unsafe.Pointer(in.APIServerLoadBalancer))
- out.FailureDomains = *(*v1beta1.FailureDomains)(unsafe.Pointer(&in.FailureDomains))
+ out.Network = (*v1beta1.NetworkStatusWithSubnets)(unsafe.Pointer(in.Network))
+ out.ExternalNetwork = (*v1beta1.NetworkStatus)(unsafe.Pointer(in.ExternalNetwork))
+ out.Router = (*v1beta1.Router)(unsafe.Pointer(in.Router))
+ out.APIServerLoadBalancer = (*v1beta1.LoadBalancer)(unsafe.Pointer(in.APIServerLoadBalancer))
+ out.FailureDomains = *(*apiv1beta1.FailureDomains)(unsafe.Pointer(&in.FailureDomains))
if in.ControlPlaneSecurityGroup != nil {
in, out := &in.ControlPlaneSecurityGroup, &out.ControlPlaneSecurityGroup
- *out = new(v1alpha8.SecurityGroupStatus)
- if err := Convert_v1alpha7_SecurityGroup_To_v1alpha8_SecurityGroupStatus(*in, *out, s); err != nil {
+ *out = new(v1beta1.SecurityGroupStatus)
+ if err := Convert_v1alpha7_SecurityGroup_To_v1beta1_SecurityGroupStatus(*in, *out, s); err != nil {
return err
}
} else {
@@ -977,8 +977,8 @@ func autoConvert_v1alpha7_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterSta
}
if in.WorkerSecurityGroup != nil {
in, out := &in.WorkerSecurityGroup, &out.WorkerSecurityGroup
- *out = new(v1alpha8.SecurityGroupStatus)
- if err := Convert_v1alpha7_SecurityGroup_To_v1alpha8_SecurityGroupStatus(*in, *out, s); err != nil {
+ *out = new(v1beta1.SecurityGroupStatus)
+ if err := Convert_v1alpha7_SecurityGroup_To_v1beta1_SecurityGroupStatus(*in, *out, s); err != nil {
return err
}
} else {
@@ -986,8 +986,8 @@ func autoConvert_v1alpha7_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterSta
}
if in.BastionSecurityGroup != nil {
in, out := &in.BastionSecurityGroup, &out.BastionSecurityGroup
- *out = new(v1alpha8.SecurityGroupStatus)
- if err := Convert_v1alpha7_SecurityGroup_To_v1alpha8_SecurityGroupStatus(*in, *out, s); err != nil {
+ *out = new(v1beta1.SecurityGroupStatus)
+ if err := Convert_v1alpha7_SecurityGroup_To_v1beta1_SecurityGroupStatus(*in, *out, s); err != nil {
return err
}
} else {
@@ -995,8 +995,8 @@ func autoConvert_v1alpha7_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterSta
}
if in.Bastion != nil {
in, out := &in.Bastion, &out.Bastion
- *out = new(v1alpha8.BastionStatus)
- if err := Convert_v1alpha7_BastionStatus_To_v1alpha8_BastionStatus(*in, *out, s); err != nil {
+ *out = new(v1beta1.BastionStatus)
+ if err := Convert_v1alpha7_BastionStatus_To_v1beta1_BastionStatus(*in, *out, s); err != nil {
return err
}
} else {
@@ -1007,22 +1007,22 @@ func autoConvert_v1alpha7_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterSta
return nil
}
-// Convert_v1alpha7_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterStatus is an autogenerated conversion function.
-func Convert_v1alpha7_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterStatus(in *OpenStackClusterStatus, out *v1alpha8.OpenStackClusterStatus, s conversion.Scope) error {
- return autoConvert_v1alpha7_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterStatus(in, out, s)
+// 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_v1alpha8_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(in *v1alpha8.OpenStackClusterStatus, out *OpenStackClusterStatus, s conversion.Scope) error {
+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))
out.APIServerLoadBalancer = (*LoadBalancer)(unsafe.Pointer(in.APIServerLoadBalancer))
- out.FailureDomains = *(*v1beta1.FailureDomains)(unsafe.Pointer(&in.FailureDomains))
+ out.FailureDomains = *(*apiv1beta1.FailureDomains)(unsafe.Pointer(&in.FailureDomains))
if in.ControlPlaneSecurityGroup != nil {
in, out := &in.ControlPlaneSecurityGroup, &out.ControlPlaneSecurityGroup
*out = new(SecurityGroup)
- if err := Convert_v1alpha8_SecurityGroupStatus_To_v1alpha7_SecurityGroup(*in, *out, s); err != nil {
+ if err := Convert_v1beta1_SecurityGroupStatus_To_v1alpha7_SecurityGroup(*in, *out, s); err != nil {
return err
}
} else {
@@ -1031,7 +1031,7 @@ func autoConvert_v1alpha8_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterSta
if in.WorkerSecurityGroup != nil {
in, out := &in.WorkerSecurityGroup, &out.WorkerSecurityGroup
*out = new(SecurityGroup)
- if err := Convert_v1alpha8_SecurityGroupStatus_To_v1alpha7_SecurityGroup(*in, *out, s); err != nil {
+ if err := Convert_v1beta1_SecurityGroupStatus_To_v1alpha7_SecurityGroup(*in, *out, s); err != nil {
return err
}
} else {
@@ -1040,7 +1040,7 @@ func autoConvert_v1alpha8_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterSta
if in.BastionSecurityGroup != nil {
in, out := &in.BastionSecurityGroup, &out.BastionSecurityGroup
*out = new(SecurityGroup)
- if err := Convert_v1alpha8_SecurityGroupStatus_To_v1alpha7_SecurityGroup(*in, *out, s); err != nil {
+ if err := Convert_v1beta1_SecurityGroupStatus_To_v1alpha7_SecurityGroup(*in, *out, s); err != nil {
return err
}
} else {
@@ -1049,7 +1049,7 @@ func autoConvert_v1alpha8_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterSta
if in.Bastion != nil {
in, out := &in.Bastion, &out.Bastion
*out = new(BastionStatus)
- if err := Convert_v1alpha8_BastionStatus_To_v1alpha7_BastionStatus(*in, *out, s); err != nil {
+ if err := Convert_v1beta1_BastionStatus_To_v1alpha7_BastionStatus(*in, *out, s); err != nil {
return err
}
} else {
@@ -1060,39 +1060,39 @@ func autoConvert_v1alpha8_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterSta
return nil
}
-func autoConvert_v1alpha7_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate(in *OpenStackClusterTemplate, out *v1alpha8.OpenStackClusterTemplate, s conversion.Scope) error {
+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_v1alpha8_OpenStackClusterTemplateSpec(&in.Spec, &out.Spec, s); err != nil {
+ if err := Convert_v1alpha7_OpenStackClusterTemplateSpec_To_v1beta1_OpenStackClusterTemplateSpec(&in.Spec, &out.Spec, s); err != nil {
return err
}
return nil
}
-// Convert_v1alpha7_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate is an autogenerated conversion function.
-func Convert_v1alpha7_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate(in *OpenStackClusterTemplate, out *v1alpha8.OpenStackClusterTemplate, s conversion.Scope) error {
- return autoConvert_v1alpha7_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate(in, out, s)
+// 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_v1alpha8_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate(in *v1alpha8.OpenStackClusterTemplate, out *OpenStackClusterTemplate, s conversion.Scope) error {
+func autoConvert_v1beta1_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate(in *v1beta1.OpenStackClusterTemplate, out *OpenStackClusterTemplate, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
- if err := Convert_v1alpha8_OpenStackClusterTemplateSpec_To_v1alpha7_OpenStackClusterTemplateSpec(&in.Spec, &out.Spec, s); err != nil {
+ if err := Convert_v1beta1_OpenStackClusterTemplateSpec_To_v1alpha7_OpenStackClusterTemplateSpec(&in.Spec, &out.Spec, s); err != nil {
return err
}
return nil
}
-// Convert_v1alpha8_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate(in *v1alpha8.OpenStackClusterTemplate, out *OpenStackClusterTemplate, s conversion.Scope) error {
- return autoConvert_v1alpha8_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate(in, out, s)
+// 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_v1alpha8_OpenStackClusterTemplateList(in *OpenStackClusterTemplateList, out *v1alpha8.OpenStackClusterTemplateList, s conversion.Scope) error {
+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([]v1alpha8.OpenStackClusterTemplate, len(*in))
+ *out = make([]v1beta1.OpenStackClusterTemplate, len(*in))
for i := range *in {
- if err := Convert_v1alpha7_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate(&(*in)[i], &(*out)[i], s); err != nil {
+ if err := Convert_v1alpha7_OpenStackClusterTemplate_To_v1beta1_OpenStackClusterTemplate(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -1102,18 +1102,18 @@ func autoConvert_v1alpha7_OpenStackClusterTemplateList_To_v1alpha8_OpenStackClus
return nil
}
-// Convert_v1alpha7_OpenStackClusterTemplateList_To_v1alpha8_OpenStackClusterTemplateList is an autogenerated conversion function.
-func Convert_v1alpha7_OpenStackClusterTemplateList_To_v1alpha8_OpenStackClusterTemplateList(in *OpenStackClusterTemplateList, out *v1alpha8.OpenStackClusterTemplateList, s conversion.Scope) error {
- return autoConvert_v1alpha7_OpenStackClusterTemplateList_To_v1alpha8_OpenStackClusterTemplateList(in, out, s)
+// 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_v1alpha8_OpenStackClusterTemplateList_To_v1alpha7_OpenStackClusterTemplateList(in *v1alpha8.OpenStackClusterTemplateList, out *OpenStackClusterTemplateList, s conversion.Scope) error {
+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_v1alpha8_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate(&(*in)[i], &(*out)[i], s); err != nil {
+ if err := Convert_v1beta1_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -1123,114 +1123,114 @@ func autoConvert_v1alpha8_OpenStackClusterTemplateList_To_v1alpha7_OpenStackClus
return nil
}
-// Convert_v1alpha8_OpenStackClusterTemplateList_To_v1alpha7_OpenStackClusterTemplateList is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackClusterTemplateList_To_v1alpha7_OpenStackClusterTemplateList(in *v1alpha8.OpenStackClusterTemplateList, out *OpenStackClusterTemplateList, s conversion.Scope) error {
- return autoConvert_v1alpha8_OpenStackClusterTemplateList_To_v1alpha7_OpenStackClusterTemplateList(in, out, s)
+// 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_v1alpha8_OpenStackClusterTemplateResource(in *OpenStackClusterTemplateResource, out *v1alpha8.OpenStackClusterTemplateResource, s conversion.Scope) error {
- if err := Convert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(&in.Spec, &out.Spec, s); err != nil {
+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_v1alpha8_OpenStackClusterTemplateResource is an autogenerated conversion function.
-func Convert_v1alpha7_OpenStackClusterTemplateResource_To_v1alpha8_OpenStackClusterTemplateResource(in *OpenStackClusterTemplateResource, out *v1alpha8.OpenStackClusterTemplateResource, s conversion.Scope) error {
- return autoConvert_v1alpha7_OpenStackClusterTemplateResource_To_v1alpha8_OpenStackClusterTemplateResource(in, out, s)
+// 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_v1alpha8_OpenStackClusterTemplateResource_To_v1alpha7_OpenStackClusterTemplateResource(in *v1alpha8.OpenStackClusterTemplateResource, out *OpenStackClusterTemplateResource, s conversion.Scope) error {
- if err := Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(&in.Spec, &out.Spec, s); err != nil {
+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_v1alpha8_OpenStackClusterTemplateResource_To_v1alpha7_OpenStackClusterTemplateResource is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackClusterTemplateResource_To_v1alpha7_OpenStackClusterTemplateResource(in *v1alpha8.OpenStackClusterTemplateResource, out *OpenStackClusterTemplateResource, s conversion.Scope) error {
- return autoConvert_v1alpha8_OpenStackClusterTemplateResource_To_v1alpha7_OpenStackClusterTemplateResource(in, out, s)
+// 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_v1alpha8_OpenStackClusterTemplateSpec(in *OpenStackClusterTemplateSpec, out *v1alpha8.OpenStackClusterTemplateSpec, s conversion.Scope) error {
- if err := Convert_v1alpha7_OpenStackClusterTemplateResource_To_v1alpha8_OpenStackClusterTemplateResource(&in.Template, &out.Template, s); err != nil {
+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_v1alpha8_OpenStackClusterTemplateSpec is an autogenerated conversion function.
-func Convert_v1alpha7_OpenStackClusterTemplateSpec_To_v1alpha8_OpenStackClusterTemplateSpec(in *OpenStackClusterTemplateSpec, out *v1alpha8.OpenStackClusterTemplateSpec, s conversion.Scope) error {
- return autoConvert_v1alpha7_OpenStackClusterTemplateSpec_To_v1alpha8_OpenStackClusterTemplateSpec(in, out, s)
+// 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_v1alpha8_OpenStackClusterTemplateSpec_To_v1alpha7_OpenStackClusterTemplateSpec(in *v1alpha8.OpenStackClusterTemplateSpec, out *OpenStackClusterTemplateSpec, s conversion.Scope) error {
- if err := Convert_v1alpha8_OpenStackClusterTemplateResource_To_v1alpha7_OpenStackClusterTemplateResource(&in.Template, &out.Template, s); err != nil {
+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_v1alpha8_OpenStackClusterTemplateSpec_To_v1alpha7_OpenStackClusterTemplateSpec is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackClusterTemplateSpec_To_v1alpha7_OpenStackClusterTemplateSpec(in *v1alpha8.OpenStackClusterTemplateSpec, out *OpenStackClusterTemplateSpec, s conversion.Scope) error {
- return autoConvert_v1alpha8_OpenStackClusterTemplateSpec_To_v1alpha7_OpenStackClusterTemplateSpec(in, out, s)
+// 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_v1alpha8_OpenStackIdentityReference(in *OpenStackIdentityReference, out *v1alpha8.OpenStackIdentityReference, s conversion.Scope) error {
+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_v1alpha8_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference(in *v1alpha8.OpenStackIdentityReference, out *OpenStackIdentityReference, s conversion.Scope) error {
+func autoConvert_v1beta1_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference(in *v1beta1.OpenStackIdentityReference, out *OpenStackIdentityReference, s conversion.Scope) error {
out.Name = in.Name
return nil
}
-// Convert_v1alpha8_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference(in *v1alpha8.OpenStackIdentityReference, out *OpenStackIdentityReference, s conversion.Scope) error {
- return autoConvert_v1alpha8_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference(in, out, s)
+// Convert_v1beta1_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference is an autogenerated conversion function.
+func Convert_v1beta1_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference(in *v1beta1.OpenStackIdentityReference, out *OpenStackIdentityReference, s conversion.Scope) error {
+ return autoConvert_v1beta1_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference(in, out, s)
}
-func autoConvert_v1alpha7_OpenStackMachine_To_v1alpha8_OpenStackMachine(in *OpenStackMachine, out *v1alpha8.OpenStackMachine, s conversion.Scope) error {
+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_v1alpha8_OpenStackMachineSpec(&in.Spec, &out.Spec, s); err != nil {
+ if err := Convert_v1alpha7_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(&in.Spec, &out.Spec, s); err != nil {
return err
}
- if err := Convert_v1alpha7_OpenStackMachineStatus_To_v1alpha8_OpenStackMachineStatus(&in.Status, &out.Status, s); err != nil {
+ if err := Convert_v1alpha7_OpenStackMachineStatus_To_v1beta1_OpenStackMachineStatus(&in.Status, &out.Status, s); err != nil {
return err
}
return nil
}
-// Convert_v1alpha7_OpenStackMachine_To_v1alpha8_OpenStackMachine is an autogenerated conversion function.
-func Convert_v1alpha7_OpenStackMachine_To_v1alpha8_OpenStackMachine(in *OpenStackMachine, out *v1alpha8.OpenStackMachine, s conversion.Scope) error {
- return autoConvert_v1alpha7_OpenStackMachine_To_v1alpha8_OpenStackMachine(in, out, s)
+// Convert_v1alpha7_OpenStackMachine_To_v1beta1_OpenStackMachine is an autogenerated conversion function.
+func Convert_v1alpha7_OpenStackMachine_To_v1beta1_OpenStackMachine(in *OpenStackMachine, out *v1beta1.OpenStackMachine, s conversion.Scope) error {
+ return autoConvert_v1alpha7_OpenStackMachine_To_v1beta1_OpenStackMachine(in, out, s)
}
-func autoConvert_v1alpha8_OpenStackMachine_To_v1alpha7_OpenStackMachine(in *v1alpha8.OpenStackMachine, out *OpenStackMachine, s conversion.Scope) error {
+func autoConvert_v1beta1_OpenStackMachine_To_v1alpha7_OpenStackMachine(in *v1beta1.OpenStackMachine, out *OpenStackMachine, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
- if err := Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(&in.Spec, &out.Spec, s); err != nil {
+ if err := Convert_v1beta1_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(&in.Spec, &out.Spec, s); err != nil {
return err
}
- if err := Convert_v1alpha8_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus(&in.Status, &out.Status, s); err != nil {
+ if err := Convert_v1beta1_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus(&in.Status, &out.Status, s); err != nil {
return err
}
return nil
}
-// Convert_v1alpha8_OpenStackMachine_To_v1alpha7_OpenStackMachine is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackMachine_To_v1alpha7_OpenStackMachine(in *v1alpha8.OpenStackMachine, out *OpenStackMachine, s conversion.Scope) error {
- return autoConvert_v1alpha8_OpenStackMachine_To_v1alpha7_OpenStackMachine(in, out, s)
+// Convert_v1beta1_OpenStackMachine_To_v1alpha7_OpenStackMachine is an autogenerated conversion function.
+func Convert_v1beta1_OpenStackMachine_To_v1alpha7_OpenStackMachine(in *v1beta1.OpenStackMachine, out *OpenStackMachine, s conversion.Scope) error {
+ return autoConvert_v1beta1_OpenStackMachine_To_v1alpha7_OpenStackMachine(in, out, s)
}
-func autoConvert_v1alpha7_OpenStackMachineList_To_v1alpha8_OpenStackMachineList(in *OpenStackMachineList, out *v1alpha8.OpenStackMachineList, s conversion.Scope) error {
+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([]v1alpha8.OpenStackMachine, len(*in))
+ *out = make([]v1beta1.OpenStackMachine, len(*in))
for i := range *in {
- if err := Convert_v1alpha7_OpenStackMachine_To_v1alpha8_OpenStackMachine(&(*in)[i], &(*out)[i], s); err != nil {
+ if err := Convert_v1alpha7_OpenStackMachine_To_v1beta1_OpenStackMachine(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -1240,18 +1240,18 @@ func autoConvert_v1alpha7_OpenStackMachineList_To_v1alpha8_OpenStackMachineList(
return nil
}
-// Convert_v1alpha7_OpenStackMachineList_To_v1alpha8_OpenStackMachineList is an autogenerated conversion function.
-func Convert_v1alpha7_OpenStackMachineList_To_v1alpha8_OpenStackMachineList(in *OpenStackMachineList, out *v1alpha8.OpenStackMachineList, s conversion.Scope) error {
- return autoConvert_v1alpha7_OpenStackMachineList_To_v1alpha8_OpenStackMachineList(in, out, s)
+// 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_v1alpha8_OpenStackMachineList_To_v1alpha7_OpenStackMachineList(in *v1alpha8.OpenStackMachineList, out *OpenStackMachineList, s conversion.Scope) error {
+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_v1alpha8_OpenStackMachine_To_v1alpha7_OpenStackMachine(&(*in)[i], &(*out)[i], s); err != nil {
+ if err := Convert_v1beta1_OpenStackMachine_To_v1alpha7_OpenStackMachine(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -1261,33 +1261,33 @@ func autoConvert_v1alpha8_OpenStackMachineList_To_v1alpha7_OpenStackMachineList(
return nil
}
-// Convert_v1alpha8_OpenStackMachineList_To_v1alpha7_OpenStackMachineList is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackMachineList_To_v1alpha7_OpenStackMachineList(in *v1alpha8.OpenStackMachineList, out *OpenStackMachineList, s conversion.Scope) error {
- return autoConvert_v1alpha8_OpenStackMachineList_To_v1alpha7_OpenStackMachineList(in, out, s)
+// 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_v1alpha8_OpenStackMachineSpec(in *OpenStackMachineSpec, out *v1alpha8.OpenStackMachineSpec, s conversion.Scope) error {
+func autoConvert_v1alpha7_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
out.Flavor = in.Flavor
- // WARNING: in.Image requires manual conversion: inconvertible types (string vs sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8.ImageFilter)
+ // WARNING: in.Image requires manual conversion: inconvertible types (string vs sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ImageFilter)
// WARNING: in.ImageUUID requires manual conversion: does not exist in peer-type
out.SSHKeyName = in.SSHKeyName
- out.Ports = *(*[]v1alpha8.PortOpts)(unsafe.Pointer(&in.Ports))
+ out.Ports = *(*[]v1beta1.PortOpts)(unsafe.Pointer(&in.Ports))
// WARNING: in.FloatingIP requires manual conversion: does not exist in peer-type
- out.SecurityGroups = *(*[]v1alpha8.SecurityGroupFilter)(unsafe.Pointer(&in.SecurityGroups))
+ out.SecurityGroups = *(*[]v1beta1.SecurityGroupFilter)(unsafe.Pointer(&in.SecurityGroups))
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/v1alpha8.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 = (*v1alpha8.RootVolume)(unsafe.Pointer(in.RootVolume))
- out.AdditionalBlockDevices = *(*[]v1alpha8.AdditionalBlockDevice)(unsafe.Pointer(&in.AdditionalBlockDevices))
+ out.RootVolume = (*v1beta1.RootVolume)(unsafe.Pointer(in.RootVolume))
+ out.AdditionalBlockDevices = *(*[]v1beta1.AdditionalBlockDevice)(unsafe.Pointer(&in.AdditionalBlockDevices))
// WARNING: in.ServerGroupID requires manual conversion: does not exist in peer-type
if in.IdentityRef != nil {
in, out := &in.IdentityRef, &out.IdentityRef
- *out = new(v1alpha8.OpenStackIdentityReference)
- if err := Convert_v1alpha7_OpenStackIdentityReference_To_v1alpha8_OpenStackIdentityReference(*in, *out, s); err != nil {
+ *out = new(v1beta1.OpenStackIdentityReference)
+ if err := Convert_v1alpha7_OpenStackIdentityReference_To_v1beta1_OpenStackIdentityReference(*in, *out, s); err != nil {
return err
}
} else {
@@ -1296,18 +1296,18 @@ func autoConvert_v1alpha7_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(
return nil
}
-func autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(in *v1alpha8.OpenStackMachineSpec, out *OpenStackMachineSpec, s conversion.Scope) error {
+func autoConvert_v1beta1_OpenStackMachineSpec_To_v1alpha7_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
- // WARNING: in.Image requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8.ImageFilter vs string)
+ // WARNING: in.Image requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ImageFilter vs string)
out.SSHKeyName = in.SSHKeyName
out.Ports = *(*[]PortOpts)(unsafe.Pointer(&in.Ports))
out.SecurityGroups = *(*[]SecurityGroupFilter)(unsafe.Pointer(&in.SecurityGroups))
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/v1alpha8.ServerMetadata vs map[string]string)
+ // 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))
out.AdditionalBlockDevices = *(*[]AdditionalBlockDevice)(unsafe.Pointer(&in.AdditionalBlockDevices))
@@ -1315,7 +1315,7 @@ func autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(
if in.IdentityRef != nil {
in, out := &in.IdentityRef, &out.IdentityRef
*out = new(OpenStackIdentityReference)
- if err := Convert_v1alpha8_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference(*in, *out, s); err != nil {
+ if err := Convert_v1beta1_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference(*in, *out, s); err != nil {
return err
}
} else {
@@ -1324,22 +1324,22 @@ func autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(
return nil
}
-func autoConvert_v1alpha7_OpenStackMachineStatus_To_v1alpha8_OpenStackMachineStatus(in *OpenStackMachineStatus, out *v1alpha8.OpenStackMachineStatus, s conversion.Scope) error {
+func autoConvert_v1alpha7_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 = (*v1alpha8.InstanceState)(unsafe.Pointer(in.InstanceState))
+ 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_v1alpha7_OpenStackMachineStatus_To_v1alpha8_OpenStackMachineStatus is an autogenerated conversion function.
-func Convert_v1alpha7_OpenStackMachineStatus_To_v1alpha8_OpenStackMachineStatus(in *OpenStackMachineStatus, out *v1alpha8.OpenStackMachineStatus, s conversion.Scope) error {
- return autoConvert_v1alpha7_OpenStackMachineStatus_To_v1alpha8_OpenStackMachineStatus(in, out, s)
+// 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_v1alpha8_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus(in *v1alpha8.OpenStackMachineStatus, out *OpenStackMachineStatus, s conversion.Scope) error {
+func autoConvert_v1beta1_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus(in *v1beta1.OpenStackMachineStatus, out *OpenStackMachineStatus, s conversion.Scope) error {
out.Ready = in.Ready
out.Addresses = *(*[]v1.NodeAddress)(unsafe.Pointer(&in.Addresses))
out.InstanceState = (*InstanceState)(unsafe.Pointer(in.InstanceState))
@@ -1347,43 +1347,43 @@ func autoConvert_v1alpha8_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineSta
// WARNING: in.DependentResources 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
}
-func autoConvert_v1alpha7_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate(in *OpenStackMachineTemplate, out *v1alpha8.OpenStackMachineTemplate, s conversion.Scope) error {
+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_v1alpha8_OpenStackMachineTemplateSpec(&in.Spec, &out.Spec, s); err != nil {
+ if err := Convert_v1alpha7_OpenStackMachineTemplateSpec_To_v1beta1_OpenStackMachineTemplateSpec(&in.Spec, &out.Spec, s); err != nil {
return err
}
return nil
}
-// Convert_v1alpha7_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate is an autogenerated conversion function.
-func Convert_v1alpha7_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate(in *OpenStackMachineTemplate, out *v1alpha8.OpenStackMachineTemplate, s conversion.Scope) error {
- return autoConvert_v1alpha7_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate(in, out, s)
+// 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_v1alpha8_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate(in *v1alpha8.OpenStackMachineTemplate, out *OpenStackMachineTemplate, s conversion.Scope) error {
+func autoConvert_v1beta1_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate(in *v1beta1.OpenStackMachineTemplate, out *OpenStackMachineTemplate, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
- if err := Convert_v1alpha8_OpenStackMachineTemplateSpec_To_v1alpha7_OpenStackMachineTemplateSpec(&in.Spec, &out.Spec, s); err != nil {
+ if err := Convert_v1beta1_OpenStackMachineTemplateSpec_To_v1alpha7_OpenStackMachineTemplateSpec(&in.Spec, &out.Spec, s); err != nil {
return err
}
return nil
}
-// Convert_v1alpha8_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate(in *v1alpha8.OpenStackMachineTemplate, out *OpenStackMachineTemplate, s conversion.Scope) error {
- return autoConvert_v1alpha8_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate(in, out, s)
+// 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_v1alpha8_OpenStackMachineTemplateList(in *OpenStackMachineTemplateList, out *v1alpha8.OpenStackMachineTemplateList, s conversion.Scope) error {
+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([]v1alpha8.OpenStackMachineTemplate, len(*in))
+ *out = make([]v1beta1.OpenStackMachineTemplate, len(*in))
for i := range *in {
- if err := Convert_v1alpha7_OpenStackMachineTemplate_To_v1alpha8_OpenStackMachineTemplate(&(*in)[i], &(*out)[i], s); err != nil {
+ if err := Convert_v1alpha7_OpenStackMachineTemplate_To_v1beta1_OpenStackMachineTemplate(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -1393,18 +1393,18 @@ func autoConvert_v1alpha7_OpenStackMachineTemplateList_To_v1alpha8_OpenStackMach
return nil
}
-// Convert_v1alpha7_OpenStackMachineTemplateList_To_v1alpha8_OpenStackMachineTemplateList is an autogenerated conversion function.
-func Convert_v1alpha7_OpenStackMachineTemplateList_To_v1alpha8_OpenStackMachineTemplateList(in *OpenStackMachineTemplateList, out *v1alpha8.OpenStackMachineTemplateList, s conversion.Scope) error {
- return autoConvert_v1alpha7_OpenStackMachineTemplateList_To_v1alpha8_OpenStackMachineTemplateList(in, out, s)
+// 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_v1alpha8_OpenStackMachineTemplateList_To_v1alpha7_OpenStackMachineTemplateList(in *v1alpha8.OpenStackMachineTemplateList, out *OpenStackMachineTemplateList, s conversion.Scope) error {
+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_v1alpha8_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate(&(*in)[i], &(*out)[i], s); err != nil {
+ if err := Convert_v1beta1_OpenStackMachineTemplate_To_v1alpha7_OpenStackMachineTemplate(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -1414,87 +1414,87 @@ func autoConvert_v1alpha8_OpenStackMachineTemplateList_To_v1alpha7_OpenStackMach
return nil
}
-// Convert_v1alpha8_OpenStackMachineTemplateList_To_v1alpha7_OpenStackMachineTemplateList is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackMachineTemplateList_To_v1alpha7_OpenStackMachineTemplateList(in *v1alpha8.OpenStackMachineTemplateList, out *OpenStackMachineTemplateList, s conversion.Scope) error {
- return autoConvert_v1alpha8_OpenStackMachineTemplateList_To_v1alpha7_OpenStackMachineTemplateList(in, out, s)
+// 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_v1alpha8_OpenStackMachineTemplateResource(in *OpenStackMachineTemplateResource, out *v1alpha8.OpenStackMachineTemplateResource, s conversion.Scope) error {
- if err := Convert_v1alpha7_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(&in.Spec, &out.Spec, s); err != nil {
+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_v1alpha8_OpenStackMachineTemplateResource is an autogenerated conversion function.
-func Convert_v1alpha7_OpenStackMachineTemplateResource_To_v1alpha8_OpenStackMachineTemplateResource(in *OpenStackMachineTemplateResource, out *v1alpha8.OpenStackMachineTemplateResource, s conversion.Scope) error {
- return autoConvert_v1alpha7_OpenStackMachineTemplateResource_To_v1alpha8_OpenStackMachineTemplateResource(in, out, s)
+// 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_v1alpha8_OpenStackMachineTemplateResource_To_v1alpha7_OpenStackMachineTemplateResource(in *v1alpha8.OpenStackMachineTemplateResource, out *OpenStackMachineTemplateResource, s conversion.Scope) error {
- if err := Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(&in.Spec, &out.Spec, s); err != nil {
+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_v1alpha8_OpenStackMachineTemplateResource_To_v1alpha7_OpenStackMachineTemplateResource is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackMachineTemplateResource_To_v1alpha7_OpenStackMachineTemplateResource(in *v1alpha8.OpenStackMachineTemplateResource, out *OpenStackMachineTemplateResource, s conversion.Scope) error {
- return autoConvert_v1alpha8_OpenStackMachineTemplateResource_To_v1alpha7_OpenStackMachineTemplateResource(in, out, s)
+// 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_v1alpha8_OpenStackMachineTemplateSpec(in *OpenStackMachineTemplateSpec, out *v1alpha8.OpenStackMachineTemplateSpec, s conversion.Scope) error {
- if err := Convert_v1alpha7_OpenStackMachineTemplateResource_To_v1alpha8_OpenStackMachineTemplateResource(&in.Template, &out.Template, s); err != nil {
+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_v1alpha8_OpenStackMachineTemplateSpec is an autogenerated conversion function.
-func Convert_v1alpha7_OpenStackMachineTemplateSpec_To_v1alpha8_OpenStackMachineTemplateSpec(in *OpenStackMachineTemplateSpec, out *v1alpha8.OpenStackMachineTemplateSpec, s conversion.Scope) error {
- return autoConvert_v1alpha7_OpenStackMachineTemplateSpec_To_v1alpha8_OpenStackMachineTemplateSpec(in, out, s)
+// 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_v1alpha8_OpenStackMachineTemplateSpec_To_v1alpha7_OpenStackMachineTemplateSpec(in *v1alpha8.OpenStackMachineTemplateSpec, out *OpenStackMachineTemplateSpec, s conversion.Scope) error {
- if err := Convert_v1alpha8_OpenStackMachineTemplateResource_To_v1alpha7_OpenStackMachineTemplateResource(&in.Template, &out.Template, s); err != nil {
+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_v1alpha8_OpenStackMachineTemplateSpec_To_v1alpha7_OpenStackMachineTemplateSpec is an autogenerated conversion function.
-func Convert_v1alpha8_OpenStackMachineTemplateSpec_To_v1alpha7_OpenStackMachineTemplateSpec(in *v1alpha8.OpenStackMachineTemplateSpec, out *OpenStackMachineTemplateSpec, s conversion.Scope) error {
- return autoConvert_v1alpha8_OpenStackMachineTemplateSpec_To_v1alpha7_OpenStackMachineTemplateSpec(in, out, s)
+// 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_v1alpha8_PortOpts(in *PortOpts, out *v1alpha8.PortOpts, s conversion.Scope) error {
- out.Network = (*v1alpha8.NetworkFilter)(unsafe.Pointer(in.Network))
+func autoConvert_v1alpha7_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *v1beta1.PortOpts, s conversion.Scope) error {
+ out.Network = (*v1beta1.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 = *(*[]v1alpha8.FixedIP)(unsafe.Pointer(&in.FixedIPs))
- out.SecurityGroupFilters = *(*[]v1alpha8.SecurityGroupFilter)(unsafe.Pointer(&in.SecurityGroupFilters))
- out.AllowedAddressPairs = *(*[]v1alpha8.AddressPair)(unsafe.Pointer(&in.AllowedAddressPairs))
+ out.FixedIPs = *(*[]v1beta1.FixedIP)(unsafe.Pointer(&in.FixedIPs))
+ out.SecurityGroupFilters = *(*[]v1beta1.SecurityGroupFilter)(unsafe.Pointer(&in.SecurityGroupFilters))
+ out.AllowedAddressPairs = *(*[]v1beta1.AddressPair)(unsafe.Pointer(&in.AllowedAddressPairs))
out.Trunk = (*bool)(unsafe.Pointer(in.Trunk))
out.HostID = in.HostID
out.VNICType = in.VNICType
- if err := Convert_v1alpha7_BindingProfile_To_v1alpha8_BindingProfile(&in.Profile, &out.Profile, s); err != nil {
+ if err := Convert_v1alpha7_BindingProfile_To_v1beta1_BindingProfile(&in.Profile, &out.Profile, s); err != nil {
return err
}
out.DisablePortSecurity = (*bool)(unsafe.Pointer(in.DisablePortSecurity))
out.PropagateUplinkStatus = (*bool)(unsafe.Pointer(in.PropagateUplinkStatus))
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
- out.ValueSpecs = *(*[]v1alpha8.ValueSpec)(unsafe.Pointer(&in.ValueSpecs))
+ out.ValueSpecs = *(*[]v1beta1.ValueSpec)(unsafe.Pointer(&in.ValueSpecs))
return nil
}
-// Convert_v1alpha7_PortOpts_To_v1alpha8_PortOpts is an autogenerated conversion function.
-func Convert_v1alpha7_PortOpts_To_v1alpha8_PortOpts(in *PortOpts, out *v1alpha8.PortOpts, s conversion.Scope) error {
- return autoConvert_v1alpha7_PortOpts_To_v1alpha8_PortOpts(in, out, s)
+// Convert_v1alpha7_PortOpts_To_v1beta1_PortOpts is an autogenerated conversion function.
+func Convert_v1alpha7_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *v1beta1.PortOpts, s conversion.Scope) error {
+ return autoConvert_v1alpha7_PortOpts_To_v1beta1_PortOpts(in, out, s)
}
-func autoConvert_v1alpha8_PortOpts_To_v1alpha7_PortOpts(in *v1alpha8.PortOpts, out *PortOpts, s conversion.Scope) error {
+func autoConvert_v1beta1_PortOpts_To_v1alpha7_PortOpts(in *v1beta1.PortOpts, out *PortOpts, s conversion.Scope) error {
out.Network = (*NetworkFilter)(unsafe.Pointer(in.Network))
out.NameSuffix = in.NameSuffix
out.Description = in.Description
@@ -1506,7 +1506,7 @@ func autoConvert_v1alpha8_PortOpts_To_v1alpha7_PortOpts(in *v1alpha8.PortOpts, o
out.Trunk = (*bool)(unsafe.Pointer(in.Trunk))
out.HostID = in.HostID
out.VNICType = in.VNICType
- if err := Convert_v1alpha8_BindingProfile_To_v1alpha7_BindingProfile(&in.Profile, &out.Profile, s); err != nil {
+ if err := Convert_v1beta1_BindingProfile_To_v1alpha7_BindingProfile(&in.Profile, &out.Profile, s); err != nil {
return err
}
out.DisablePortSecurity = (*bool)(unsafe.Pointer(in.DisablePortSecurity))
@@ -1516,36 +1516,36 @@ func autoConvert_v1alpha8_PortOpts_To_v1alpha7_PortOpts(in *v1alpha8.PortOpts, o
return nil
}
-// Convert_v1alpha8_PortOpts_To_v1alpha7_PortOpts is an autogenerated conversion function.
-func Convert_v1alpha8_PortOpts_To_v1alpha7_PortOpts(in *v1alpha8.PortOpts, out *PortOpts, s conversion.Scope) error {
- return autoConvert_v1alpha8_PortOpts_To_v1alpha7_PortOpts(in, out, s)
+// Convert_v1beta1_PortOpts_To_v1alpha7_PortOpts is an autogenerated conversion function.
+func Convert_v1beta1_PortOpts_To_v1alpha7_PortOpts(in *v1beta1.PortOpts, out *PortOpts, s conversion.Scope) error {
+ return autoConvert_v1beta1_PortOpts_To_v1alpha7_PortOpts(in, out, s)
}
-func autoConvert_v1alpha7_RootVolume_To_v1alpha8_RootVolume(in *RootVolume, out *v1alpha8.RootVolume, s conversion.Scope) error {
+func autoConvert_v1alpha7_RootVolume_To_v1beta1_RootVolume(in *RootVolume, out *v1beta1.RootVolume, s conversion.Scope) error {
out.Size = in.Size
out.VolumeType = in.VolumeType
out.AvailabilityZone = in.AvailabilityZone
return nil
}
-// Convert_v1alpha7_RootVolume_To_v1alpha8_RootVolume is an autogenerated conversion function.
-func Convert_v1alpha7_RootVolume_To_v1alpha8_RootVolume(in *RootVolume, out *v1alpha8.RootVolume, s conversion.Scope) error {
- return autoConvert_v1alpha7_RootVolume_To_v1alpha8_RootVolume(in, out, s)
+// Convert_v1alpha7_RootVolume_To_v1beta1_RootVolume is an autogenerated conversion function.
+func Convert_v1alpha7_RootVolume_To_v1beta1_RootVolume(in *RootVolume, out *v1beta1.RootVolume, s conversion.Scope) error {
+ return autoConvert_v1alpha7_RootVolume_To_v1beta1_RootVolume(in, out, s)
}
-func autoConvert_v1alpha8_RootVolume_To_v1alpha7_RootVolume(in *v1alpha8.RootVolume, out *RootVolume, s conversion.Scope) error {
+func autoConvert_v1beta1_RootVolume_To_v1alpha7_RootVolume(in *v1beta1.RootVolume, out *RootVolume, s conversion.Scope) error {
out.Size = in.Size
out.VolumeType = in.VolumeType
out.AvailabilityZone = in.AvailabilityZone
return nil
}
-// Convert_v1alpha8_RootVolume_To_v1alpha7_RootVolume is an autogenerated conversion function.
-func Convert_v1alpha8_RootVolume_To_v1alpha7_RootVolume(in *v1alpha8.RootVolume, out *RootVolume, s conversion.Scope) error {
- return autoConvert_v1alpha8_RootVolume_To_v1alpha7_RootVolume(in, out, s)
+// Convert_v1beta1_RootVolume_To_v1alpha7_RootVolume is an autogenerated conversion function.
+func Convert_v1beta1_RootVolume_To_v1alpha7_RootVolume(in *v1beta1.RootVolume, out *RootVolume, s conversion.Scope) error {
+ return autoConvert_v1beta1_RootVolume_To_v1alpha7_RootVolume(in, out, s)
}
-func autoConvert_v1alpha7_Router_To_v1alpha8_Router(in *Router, out *v1alpha8.Router, s conversion.Scope) error {
+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))
@@ -1553,12 +1553,12 @@ func autoConvert_v1alpha7_Router_To_v1alpha8_Router(in *Router, out *v1alpha8.Ro
return nil
}
-// Convert_v1alpha7_Router_To_v1alpha8_Router is an autogenerated conversion function.
-func Convert_v1alpha7_Router_To_v1alpha8_Router(in *Router, out *v1alpha8.Router, s conversion.Scope) error {
- return autoConvert_v1alpha7_Router_To_v1alpha8_Router(in, out, s)
+// 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_v1alpha8_Router_To_v1alpha7_Router(in *v1alpha8.Router, out *Router, s conversion.Scope) error {
+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))
@@ -1566,12 +1566,12 @@ func autoConvert_v1alpha8_Router_To_v1alpha7_Router(in *v1alpha8.Router, out *Ro
return nil
}
-// Convert_v1alpha8_Router_To_v1alpha7_Router is an autogenerated conversion function.
-func Convert_v1alpha8_Router_To_v1alpha7_Router(in *v1alpha8.Router, out *Router, s conversion.Scope) error {
- return autoConvert_v1alpha8_Router_To_v1alpha7_Router(in, out, s)
+// 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_v1alpha8_RouterFilter(in *RouterFilter, out *v1alpha8.RouterFilter, s conversion.Scope) error {
+func autoConvert_v1alpha7_RouterFilter_To_v1beta1_RouterFilter(in *RouterFilter, out *v1beta1.RouterFilter, s conversion.Scope) error {
out.ID = in.ID
out.Name = in.Name
out.Description = in.Description
@@ -1583,12 +1583,12 @@ func autoConvert_v1alpha7_RouterFilter_To_v1alpha8_RouterFilter(in *RouterFilter
return nil
}
-// Convert_v1alpha7_RouterFilter_To_v1alpha8_RouterFilter is an autogenerated conversion function.
-func Convert_v1alpha7_RouterFilter_To_v1alpha8_RouterFilter(in *RouterFilter, out *v1alpha8.RouterFilter, s conversion.Scope) error {
- return autoConvert_v1alpha7_RouterFilter_To_v1alpha8_RouterFilter(in, out, s)
+// Convert_v1alpha7_RouterFilter_To_v1beta1_RouterFilter is an autogenerated conversion function.
+func Convert_v1alpha7_RouterFilter_To_v1beta1_RouterFilter(in *RouterFilter, out *v1beta1.RouterFilter, s conversion.Scope) error {
+ return autoConvert_v1alpha7_RouterFilter_To_v1beta1_RouterFilter(in, out, s)
}
-func autoConvert_v1alpha8_RouterFilter_To_v1alpha7_RouterFilter(in *v1alpha8.RouterFilter, out *RouterFilter, s conversion.Scope) error {
+func autoConvert_v1beta1_RouterFilter_To_v1alpha7_RouterFilter(in *v1beta1.RouterFilter, out *RouterFilter, s conversion.Scope) error {
out.ID = in.ID
out.Name = in.Name
out.Description = in.Description
@@ -1600,12 +1600,12 @@ func autoConvert_v1alpha8_RouterFilter_To_v1alpha7_RouterFilter(in *v1alpha8.Rou
return nil
}
-// Convert_v1alpha8_RouterFilter_To_v1alpha7_RouterFilter is an autogenerated conversion function.
-func Convert_v1alpha8_RouterFilter_To_v1alpha7_RouterFilter(in *v1alpha8.RouterFilter, out *RouterFilter, s conversion.Scope) error {
- return autoConvert_v1alpha8_RouterFilter_To_v1alpha7_RouterFilter(in, out, s)
+// Convert_v1beta1_RouterFilter_To_v1alpha7_RouterFilter is an autogenerated conversion function.
+func Convert_v1beta1_RouterFilter_To_v1alpha7_RouterFilter(in *v1beta1.RouterFilter, out *RouterFilter, s conversion.Scope) error {
+ return autoConvert_v1beta1_RouterFilter_To_v1alpha7_RouterFilter(in, out, s)
}
-func autoConvert_v1alpha7_SecurityGroupFilter_To_v1alpha8_SecurityGroupFilter(in *SecurityGroupFilter, out *v1alpha8.SecurityGroupFilter, s conversion.Scope) error {
+func autoConvert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in *SecurityGroupFilter, out *v1beta1.SecurityGroupFilter, s conversion.Scope) error {
out.ID = in.ID
out.Name = in.Name
out.Description = in.Description
@@ -1617,12 +1617,12 @@ func autoConvert_v1alpha7_SecurityGroupFilter_To_v1alpha8_SecurityGroupFilter(in
return nil
}
-// Convert_v1alpha7_SecurityGroupFilter_To_v1alpha8_SecurityGroupFilter is an autogenerated conversion function.
-func Convert_v1alpha7_SecurityGroupFilter_To_v1alpha8_SecurityGroupFilter(in *SecurityGroupFilter, out *v1alpha8.SecurityGroupFilter, s conversion.Scope) error {
- return autoConvert_v1alpha7_SecurityGroupFilter_To_v1alpha8_SecurityGroupFilter(in, out, s)
+// Convert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter is an autogenerated conversion function.
+func Convert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in *SecurityGroupFilter, out *v1beta1.SecurityGroupFilter, s conversion.Scope) error {
+ return autoConvert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in, out, s)
}
-func autoConvert_v1alpha8_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in *v1alpha8.SecurityGroupFilter, out *SecurityGroupFilter, s conversion.Scope) error {
+func autoConvert_v1beta1_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in *v1beta1.SecurityGroupFilter, out *SecurityGroupFilter, s conversion.Scope) error {
out.ID = in.ID
out.Name = in.Name
out.Description = in.Description
@@ -1634,12 +1634,12 @@ func autoConvert_v1alpha8_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in
return nil
}
-// Convert_v1alpha8_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter is an autogenerated conversion function.
-func Convert_v1alpha8_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in *v1alpha8.SecurityGroupFilter, out *SecurityGroupFilter, s conversion.Scope) error {
- return autoConvert_v1alpha8_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in, out, s)
+// Convert_v1beta1_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter is an autogenerated conversion function.
+func Convert_v1beta1_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in *v1beta1.SecurityGroupFilter, out *SecurityGroupFilter, s conversion.Scope) error {
+ return autoConvert_v1beta1_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in, out, s)
}
-func autoConvert_v1alpha7_Subnet_To_v1alpha8_Subnet(in *Subnet, out *v1alpha8.Subnet, s conversion.Scope) error {
+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
@@ -1647,12 +1647,12 @@ func autoConvert_v1alpha7_Subnet_To_v1alpha8_Subnet(in *Subnet, out *v1alpha8.Su
return nil
}
-// Convert_v1alpha7_Subnet_To_v1alpha8_Subnet is an autogenerated conversion function.
-func Convert_v1alpha7_Subnet_To_v1alpha8_Subnet(in *Subnet, out *v1alpha8.Subnet, s conversion.Scope) error {
- return autoConvert_v1alpha7_Subnet_To_v1alpha8_Subnet(in, out, s)
+// 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_v1alpha8_Subnet_To_v1alpha7_Subnet(in *v1alpha8.Subnet, out *Subnet, s conversion.Scope) error {
+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
@@ -1660,12 +1660,12 @@ func autoConvert_v1alpha8_Subnet_To_v1alpha7_Subnet(in *v1alpha8.Subnet, out *Su
return nil
}
-// Convert_v1alpha8_Subnet_To_v1alpha7_Subnet is an autogenerated conversion function.
-func Convert_v1alpha8_Subnet_To_v1alpha7_Subnet(in *v1alpha8.Subnet, out *Subnet, s conversion.Scope) error {
- return autoConvert_v1alpha8_Subnet_To_v1alpha7_Subnet(in, out, s)
+// 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_v1alpha8_SubnetFilter(in *SubnetFilter, out *v1alpha8.SubnetFilter, s conversion.Scope) error {
+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
@@ -1682,12 +1682,12 @@ func autoConvert_v1alpha7_SubnetFilter_To_v1alpha8_SubnetFilter(in *SubnetFilter
return nil
}
-// Convert_v1alpha7_SubnetFilter_To_v1alpha8_SubnetFilter is an autogenerated conversion function.
-func Convert_v1alpha7_SubnetFilter_To_v1alpha8_SubnetFilter(in *SubnetFilter, out *v1alpha8.SubnetFilter, s conversion.Scope) error {
- return autoConvert_v1alpha7_SubnetFilter_To_v1alpha8_SubnetFilter(in, out, s)
+// Convert_v1alpha7_SubnetFilter_To_v1beta1_SubnetFilter is an autogenerated conversion function.
+func Convert_v1alpha7_SubnetFilter_To_v1beta1_SubnetFilter(in *SubnetFilter, out *v1beta1.SubnetFilter, s conversion.Scope) error {
+ return autoConvert_v1alpha7_SubnetFilter_To_v1beta1_SubnetFilter(in, out, s)
}
-func autoConvert_v1alpha8_SubnetFilter_To_v1alpha7_SubnetFilter(in *v1alpha8.SubnetFilter, out *SubnetFilter, s conversion.Scope) error {
+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
@@ -1704,31 +1704,31 @@ func autoConvert_v1alpha8_SubnetFilter_To_v1alpha7_SubnetFilter(in *v1alpha8.Sub
return nil
}
-// Convert_v1alpha8_SubnetFilter_To_v1alpha7_SubnetFilter is an autogenerated conversion function.
-func Convert_v1alpha8_SubnetFilter_To_v1alpha7_SubnetFilter(in *v1alpha8.SubnetFilter, out *SubnetFilter, s conversion.Scope) error {
- return autoConvert_v1alpha8_SubnetFilter_To_v1alpha7_SubnetFilter(in, out, s)
+// Convert_v1beta1_SubnetFilter_To_v1alpha7_SubnetFilter is an autogenerated conversion function.
+func Convert_v1beta1_SubnetFilter_To_v1alpha7_SubnetFilter(in *v1beta1.SubnetFilter, out *SubnetFilter, s conversion.Scope) error {
+ return autoConvert_v1beta1_SubnetFilter_To_v1alpha7_SubnetFilter(in, out, s)
}
-func autoConvert_v1alpha7_ValueSpec_To_v1alpha8_ValueSpec(in *ValueSpec, out *v1alpha8.ValueSpec, s conversion.Scope) error {
+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_v1alpha8_ValueSpec is an autogenerated conversion function.
-func Convert_v1alpha7_ValueSpec_To_v1alpha8_ValueSpec(in *ValueSpec, out *v1alpha8.ValueSpec, s conversion.Scope) error {
- return autoConvert_v1alpha7_ValueSpec_To_v1alpha8_ValueSpec(in, out, s)
+// 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_v1alpha8_ValueSpec_To_v1alpha7_ValueSpec(in *v1alpha8.ValueSpec, out *ValueSpec, s conversion.Scope) error {
+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_v1alpha8_ValueSpec_To_v1alpha7_ValueSpec is an autogenerated conversion function.
-func Convert_v1alpha8_ValueSpec_To_v1alpha7_ValueSpec(in *v1alpha8.ValueSpec, out *ValueSpec, s conversion.Scope) error {
- return autoConvert_v1alpha8_ValueSpec_To_v1alpha7_ValueSpec(in, out, s)
+// 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/v1alpha8/conditions_consts.go b/api/v1beta1/conditions_consts.go
similarity index 99%
rename from api/v1alpha8/conditions_consts.go
rename to api/v1beta1/conditions_consts.go
index de16adeb08..288251636d 100644
--- a/api/v1alpha8/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 v1alpha8
+package v1beta1
import clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
diff --git a/api/v1alpha8/conversion.go b/api/v1beta1/conversion.go
similarity index 96%
rename from api/v1alpha8/conversion.go
rename to api/v1beta1/conversion.go
index d59b51d96f..ab9d242d42 100644
--- a/api/v1alpha8/conversion.go
+++ b/api/v1beta1/conversion.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package v1alpha8
+package v1beta1
import "k8s.io/utils/pointer"
@@ -44,7 +44,7 @@ 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 v1alpha8.
+// managed security groups are enabled and upgrading to v1beta1.
func LegacyCalicoSecurityGroupRules() []SecurityGroupRuleSpec {
return []SecurityGroupRuleSpec{
{
diff --git a/api/v1alpha8/doc.go b/api/v1beta1/doc.go
similarity index 97%
rename from api/v1alpha8/doc.go
rename to api/v1beta1/doc.go
index 6e9bd36d84..465e3a377a 100644
--- a/api/v1alpha8/doc.go
+++ b/api/v1beta1/doc.go
@@ -14,4 +14,4 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package v1alpha8
+package v1beta1
diff --git a/api/v1alpha8/filter_convert.go b/api/v1beta1/filter_convert.go
similarity index 99%
rename from api/v1alpha8/filter_convert.go
rename to api/v1beta1/filter_convert.go
index 378642ce5f..e168c63e0a 100644
--- a/api/v1alpha8/filter_convert.go
+++ b/api/v1beta1/filter_convert.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package v1alpha8
+package v1beta1
import (
"github.com/gophercloud/gophercloud/openstack/imageservice/v2/images"
diff --git a/api/v1alpha8/groupversion_info.go b/api/v1beta1/groupversion_info.go
similarity index 90%
rename from api/v1alpha8/groupversion_info.go
rename to api/v1beta1/groupversion_info.go
index b0ab35273c..de2087f709 100644
--- a/api/v1alpha8/groupversion_info.go
+++ b/api/v1beta1/groupversion_info.go
@@ -14,10 +14,10 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-// package v1alpha8 contains API Schema definitions for the infrastructure v1alpha8 API group
+// package v1beta1 contains API Schema definitions for the infrastructure v1beta1 API group
// +kubebuilder:object:generate=true
// +groupName=infrastructure.cluster.x-k8s.io
-package v1alpha8
+package v1beta1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -27,7 +27,7 @@ import (
var (
// GroupVersion is group version used to register these objects.
- GroupVersion = schema.GroupVersion{Group: "infrastructure.cluster.x-k8s.io", Version: "v1alpha8"}
+ 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)
diff --git a/api/v1alpha8/identity_types.go b/api/v1beta1/identity_types.go
similarity index 98%
rename from api/v1alpha8/identity_types.go
rename to api/v1beta1/identity_types.go
index d9bf1f4f92..ff68fceae6 100644
--- a/api/v1alpha8/identity_types.go
+++ b/api/v1beta1/identity_types.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package v1alpha8
+package v1beta1
// OpenStackIdentityReference is a reference to an infrastructure
// provider identity to be used to provision cluster resources.
diff --git a/api/v1alpha8/openstackcluster_types.go b/api/v1beta1/openstackcluster_types.go
similarity index 99%
rename from api/v1alpha8/openstackcluster_types.go
rename to api/v1beta1/openstackcluster_types.go
index a6f9c0b15f..728310a82b 100644
--- a/api/v1alpha8/openstackcluster_types.go
+++ b/api/v1beta1/openstackcluster_types.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package v1alpha8
+package v1beta1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
diff --git a/api/v1alpha8/openstackcluster_webhook.go b/api/v1beta1/openstackcluster_webhook.go
similarity index 91%
rename from api/v1alpha8/openstackcluster_webhook.go
rename to api/v1beta1/openstackcluster_webhook.go
index b9e148f589..68d4c6593e 100644
--- a/api/v1alpha8/openstackcluster_webhook.go
+++ b/api/v1beta1/openstackcluster_webhook.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package v1alpha8
+package v1beta1
import (
"fmt"
@@ -40,8 +40,8 @@ func (r *OpenStackCluster) SetupWebhookWithManager(mgr manager.Manager) error {
Complete()
}
-// +kubebuilder:webhook:verbs=create;update,path=/validate-infrastructure-cluster-x-k8s-io-v1alpha8-openstackcluster,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=openstackclusters,versions=v1alpha8,name=validation.openstackcluster.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1
-// +kubebuilder:webhook:verbs=create;update,path=/mutate-infrastructure-cluster-x-k8s-io-v1alpha8-openstackcluster,mutating=true,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=openstackclusters,versions=v1alpha8,name=default.openstackcluster.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1
+// +kubebuilder:webhook:verbs=create;update,path=/validate-infrastructure-cluster-x-k8s-io-v1beta1-openstackcluster,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=openstackclusters,versions=v1beta1,name=validation.openstackcluster.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1
+// +kubebuilder:webhook:verbs=create;update,path=/mutate-infrastructure-cluster-x-k8s-io-v1beta1-openstackcluster,mutating=true,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=openstackclusters,versions=v1beta1,name=default.openstackcluster.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1
var (
_ webhook.Defaulter = &OpenStackCluster{}
diff --git a/api/v1alpha8/openstackcluster_webhook_test.go b/api/v1beta1/openstackcluster_webhook_test.go
similarity index 99%
rename from api/v1alpha8/openstackcluster_webhook_test.go
rename to api/v1beta1/openstackcluster_webhook_test.go
index 40bfa731f0..27984302e8 100644
--- a/api/v1alpha8/openstackcluster_webhook_test.go
+++ b/api/v1beta1/openstackcluster_webhook_test.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package v1alpha8
+package v1beta1
import (
"testing"
diff --git a/api/v1alpha8/openstackclusterlist_webhook.go b/api/v1beta1/openstackclusterlist_webhook.go
similarity index 98%
rename from api/v1alpha8/openstackclusterlist_webhook.go
rename to api/v1beta1/openstackclusterlist_webhook.go
index e6c3d9d47a..c765ad7cb8 100644
--- a/api/v1alpha8/openstackclusterlist_webhook.go
+++ b/api/v1beta1/openstackclusterlist_webhook.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package v1alpha8
+package v1beta1
import (
"sigs.k8s.io/controller-runtime/pkg/builder"
diff --git a/api/v1alpha8/openstackclustertemplate_types.go b/api/v1beta1/openstackclustertemplate_types.go
similarity index 99%
rename from api/v1alpha8/openstackclustertemplate_types.go
rename to api/v1beta1/openstackclustertemplate_types.go
index 65ea6aeff6..2134595759 100644
--- a/api/v1alpha8/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 v1alpha8
+package v1beta1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
diff --git a/api/v1alpha8/openstackclustertemplate_webhook.go b/api/v1beta1/openstackclustertemplate_webhook.go
similarity index 80%
rename from api/v1alpha8/openstackclustertemplate_webhook.go
rename to api/v1beta1/openstackclustertemplate_webhook.go
index 03aa2b1dff..700dac06e2 100644
--- a/api/v1alpha8/openstackclustertemplate_webhook.go
+++ b/api/v1beta1/openstackclustertemplate_webhook.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package v1alpha8
+package v1beta1
import (
"fmt"
@@ -36,8 +36,8 @@ func (r *OpenStackClusterTemplate) SetupWebhookWithManager(mgr ctrl.Manager) err
Complete()
}
-// +kubebuilder:webhook:verbs=create;update,path=/mutate-infrastructure-cluster-x-k8s-io-v1alpha8-openstackclustertemplate,mutating=true,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=openstackclustertemplates,versions=v1alpha8,name=default.openstackclustertemplate.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1
-// +kubebuilder:webhook:verbs=create;update,path=/validate-infrastructure-cluster-x-k8s-io-v1alpha8-openstackclustertemplate,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=openstackclustertemplates,versions=v1alpha8,name=validation.openstackclustertemplate.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1
+// +kubebuilder:webhook:verbs=create;update,path=/mutate-infrastructure-cluster-x-k8s-io-v1beta1-openstackclustertemplate,mutating=true,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=openstackclustertemplates,versions=v1beta1,name=default.openstackclustertemplate.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1
+// +kubebuilder:webhook:verbs=create;update,path=/validate-infrastructure-cluster-x-k8s-io-v1beta1-openstackclustertemplate,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=openstackclustertemplates,versions=v1beta1,name=validation.openstackclustertemplate.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1
var (
_ webhook.Defaulter = &OpenStackClusterTemplate{}
diff --git a/api/v1alpha8/openstackmachine_types.go b/api/v1beta1/openstackmachine_types.go
similarity index 99%
rename from api/v1alpha8/openstackmachine_types.go
rename to api/v1beta1/openstackmachine_types.go
index b8c03d7b6c..e08cf2ef82 100644
--- a/api/v1alpha8/openstackmachine_types.go
+++ b/api/v1beta1/openstackmachine_types.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package v1alpha8
+package v1beta1
import (
corev1 "k8s.io/api/core/v1"
diff --git a/api/v1alpha8/openstackmachine_webhook.go b/api/v1beta1/openstackmachine_webhook.go
similarity index 86%
rename from api/v1alpha8/openstackmachine_webhook.go
rename to api/v1beta1/openstackmachine_webhook.go
index 8f5e1ee1f3..221dc0c673 100644
--- a/api/v1alpha8/openstackmachine_webhook.go
+++ b/api/v1beta1/openstackmachine_webhook.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package v1alpha8
+package v1beta1
import (
"fmt"
@@ -39,8 +39,8 @@ func (r *OpenStackMachine) SetupWebhookWithManager(mgr manager.Manager) error {
Complete()
}
-// +kubebuilder:webhook:verbs=create;update,path=/validate-infrastructure-cluster-x-k8s-io-v1alpha8-openstackmachine,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=openstackmachines,versions=v1alpha8,name=validation.openstackmachine.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1
-// +kubebuilder:webhook:verbs=create;update,path=/mutate-infrastructure-cluster-x-k8s-io-v1alpha8-openstackmachine,mutating=true,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=openstackmachines,versions=v1alpha8,name=default.openstackmachine.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1
+// +kubebuilder:webhook:verbs=create;update,path=/validate-infrastructure-cluster-x-k8s-io-v1beta1-openstackmachine,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=openstackmachines,versions=v1beta1,name=validation.openstackmachine.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1
+// +kubebuilder:webhook:verbs=create;update,path=/mutate-infrastructure-cluster-x-k8s-io-v1beta1-openstackmachine,mutating=true,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=openstackmachines,versions=v1beta1,name=default.openstackmachine.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1
var (
_ webhook.Defaulter = &OpenStackMachine{}
diff --git a/api/v1alpha8/openstackmachinelist_webhook.go b/api/v1beta1/openstackmachinelist_webhook.go
similarity index 98%
rename from api/v1alpha8/openstackmachinelist_webhook.go
rename to api/v1beta1/openstackmachinelist_webhook.go
index e858ba072d..9e6a551f2d 100644
--- a/api/v1alpha8/openstackmachinelist_webhook.go
+++ b/api/v1beta1/openstackmachinelist_webhook.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package v1alpha8
+package v1beta1
import (
"sigs.k8s.io/controller-runtime/pkg/builder"
diff --git a/api/v1alpha8/openstackmachinetemplate_types.go b/api/v1beta1/openstackmachinetemplate_types.go
similarity index 98%
rename from api/v1alpha8/openstackmachinetemplate_types.go
rename to api/v1beta1/openstackmachinetemplate_types.go
index fa80dc371d..c085f2620d 100644
--- a/api/v1alpha8/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 v1alpha8
+package v1beta1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
diff --git a/api/v1alpha8/openstackmachinetemplate_webhook.go b/api/v1beta1/openstackmachinetemplate_webhook.go
similarity index 91%
rename from api/v1alpha8/openstackmachinetemplate_webhook.go
rename to api/v1beta1/openstackmachinetemplate_webhook.go
index cbb91ebb17..24f27a937e 100644
--- a/api/v1alpha8/openstackmachinetemplate_webhook.go
+++ b/api/v1beta1/openstackmachinetemplate_webhook.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package v1alpha8
+package v1beta1
import (
"context"
@@ -44,7 +44,7 @@ func (r *OpenStackMachineTemplateWebhook) SetupWebhookWithManager(mgr manager.Ma
Complete()
}
-// +kubebuilder:webhook:verbs=create;update,path=/validate-infrastructure-cluster-x-k8s-io-v1alpha8-openstackmachinetemplate,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=openstackmachinetemplates,versions=v1alpha8,name=validation.openstackmachinetemplate.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1
+// +kubebuilder:webhook:verbs=create;update,path=/validate-infrastructure-cluster-x-k8s-io-v1beta1-openstackmachinetemplate,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=openstackmachinetemplates,versions=v1beta1,name=validation.openstackmachinetemplate.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1
var _ webhook.CustomValidator = &OpenStackMachineTemplateWebhook{}
diff --git a/api/v1alpha8/openstackmachinetemplate_webhook_test.go b/api/v1beta1/openstackmachinetemplate_webhook_test.go
similarity index 99%
rename from api/v1alpha8/openstackmachinetemplate_webhook_test.go
rename to api/v1beta1/openstackmachinetemplate_webhook_test.go
index e441ef0583..95fd2c7ccf 100644
--- a/api/v1alpha8/openstackmachinetemplate_webhook_test.go
+++ b/api/v1beta1/openstackmachinetemplate_webhook_test.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package v1alpha8
+package v1beta1
import (
"context"
diff --git a/api/v1alpha8/openstackmachinetemplatelist_webhook.go b/api/v1beta1/openstackmachinetemplatelist_webhook.go
similarity index 98%
rename from api/v1alpha8/openstackmachinetemplatelist_webhook.go
rename to api/v1beta1/openstackmachinetemplatelist_webhook.go
index 01d976b51e..03d438e925 100644
--- a/api/v1alpha8/openstackmachinetemplatelist_webhook.go
+++ b/api/v1beta1/openstackmachinetemplatelist_webhook.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package v1alpha8
+package v1beta1
import (
"sigs.k8s.io/controller-runtime/pkg/builder"
diff --git a/api/v1alpha8/types.go b/api/v1beta1/types.go
similarity index 99%
rename from api/v1alpha8/types.go
rename to api/v1beta1/types.go
index 8d5acf5766..c96995cd31 100644
--- a/api/v1alpha8/types.go
+++ b/api/v1beta1/types.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package v1alpha8
+package v1beta1
// OpenStackMachineTemplateResource describes the data needed to create a OpenStackMachine from a template.
type OpenStackMachineTemplateResource struct {
diff --git a/api/v1alpha8/webhooks.go b/api/v1beta1/webhooks.go
similarity index 98%
rename from api/v1alpha8/webhooks.go
rename to api/v1beta1/webhooks.go
index 87a4a374a0..3df43589ba 100644
--- a/api/v1alpha8/webhooks.go
+++ b/api/v1beta1/webhooks.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package v1alpha8
+package v1beta1
import (
apierrors "k8s.io/apimachinery/pkg/api/errors"
diff --git a/api/v1alpha8/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go
similarity index 99%
rename from api/v1alpha8/zz_generated.deepcopy.go
rename to api/v1beta1/zz_generated.deepcopy.go
index 1aae783e22..f9105944fc 100644
--- a/api/v1alpha8/zz_generated.deepcopy.go
+++ b/api/v1beta1/zz_generated.deepcopy.go
@@ -18,12 +18,12 @@ limitations under the License.
// Code generated by controller-gen. DO NOT EDIT.
-package v1alpha8
+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"
)
@@ -512,7 +512,7 @@ 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()
}
@@ -825,7 +825,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])
}
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 d6b369b9cb..948113c887 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -4820,7 +4820,7 @@ spec:
jsonPath: .metadata.creationTimestamp
name: Age
type: date
- name: v1alpha8
+ name: v1beta1
schema:
openAPIV3Schema:
description: OpenStackCluster is the Schema for the openstackclusters API.
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 629284730c..048769f3ab 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -2234,7 +2234,7 @@ spec:
type: object
served: true
storage: false
- - name: v1alpha8
+ - name: v1beta1
schema:
openAPIV3Schema:
description: OpenStackClusterTemplate is the Schema for the openstackclustertemplates
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 69ae2d52b1..cb7f8edc39 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
@@ -1692,7 +1692,7 @@ spec:
jsonPath: .metadata.creationTimestamp
name: Age
type: date
- name: v1alpha8
+ name: v1beta1
schema:
openAPIV3Schema:
description: OpenStackMachine is the Schema for the openstackmachines API.
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 95d1c52ecf..9a903ee0ad 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
@@ -1354,7 +1354,7 @@ spec:
type: object
served: true
storage: false
- - name: v1alpha8
+ - name: v1beta1
schema:
openAPIV3Schema:
description: OpenStackMachineTemplate is the Schema for the openstackmachinetemplates
diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml
index c153237cc4..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_v1alpha8
+ 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.
diff --git a/config/webhook/manifests.yaml b/config/webhook/manifests.yaml
index d65e84a9f2..260778c5cf 100644
--- a/config/webhook/manifests.yaml
+++ b/config/webhook/manifests.yaml
@@ -10,7 +10,7 @@ webhooks:
service:
name: webhook-service
namespace: system
- path: /mutate-infrastructure-cluster-x-k8s-io-v1alpha8-openstackcluster
+ path: /mutate-infrastructure-cluster-x-k8s-io-v1beta1-openstackcluster
failurePolicy: Fail
matchPolicy: Equivalent
name: default.openstackcluster.infrastructure.cluster.x-k8s.io
@@ -18,7 +18,7 @@ webhooks:
- apiGroups:
- infrastructure.cluster.x-k8s.io
apiVersions:
- - v1alpha8
+ - v1beta1
operations:
- CREATE
- UPDATE
@@ -31,7 +31,7 @@ webhooks:
service:
name: webhook-service
namespace: system
- path: /mutate-infrastructure-cluster-x-k8s-io-v1alpha8-openstackclustertemplate
+ path: /mutate-infrastructure-cluster-x-k8s-io-v1beta1-openstackclustertemplate
failurePolicy: Fail
matchPolicy: Equivalent
name: default.openstackclustertemplate.infrastructure.cluster.x-k8s.io
@@ -39,7 +39,7 @@ webhooks:
- apiGroups:
- infrastructure.cluster.x-k8s.io
apiVersions:
- - v1alpha8
+ - v1beta1
operations:
- CREATE
- UPDATE
@@ -52,7 +52,7 @@ webhooks:
service:
name: webhook-service
namespace: system
- path: /mutate-infrastructure-cluster-x-k8s-io-v1alpha8-openstackmachine
+ path: /mutate-infrastructure-cluster-x-k8s-io-v1beta1-openstackmachine
failurePolicy: Fail
matchPolicy: Equivalent
name: default.openstackmachine.infrastructure.cluster.x-k8s.io
@@ -60,7 +60,7 @@ webhooks:
- apiGroups:
- infrastructure.cluster.x-k8s.io
apiVersions:
- - v1alpha8
+ - v1beta1
operations:
- CREATE
- UPDATE
@@ -79,7 +79,7 @@ webhooks:
service:
name: webhook-service
namespace: system
- path: /validate-infrastructure-cluster-x-k8s-io-v1alpha8-openstackcluster
+ path: /validate-infrastructure-cluster-x-k8s-io-v1beta1-openstackcluster
failurePolicy: Fail
matchPolicy: Equivalent
name: validation.openstackcluster.infrastructure.cluster.x-k8s.io
@@ -87,7 +87,7 @@ webhooks:
- apiGroups:
- infrastructure.cluster.x-k8s.io
apiVersions:
- - v1alpha8
+ - v1beta1
operations:
- CREATE
- UPDATE
@@ -100,7 +100,7 @@ webhooks:
service:
name: webhook-service
namespace: system
- path: /validate-infrastructure-cluster-x-k8s-io-v1alpha8-openstackclustertemplate
+ path: /validate-infrastructure-cluster-x-k8s-io-v1beta1-openstackclustertemplate
failurePolicy: Fail
matchPolicy: Equivalent
name: validation.openstackclustertemplate.infrastructure.cluster.x-k8s.io
@@ -108,7 +108,7 @@ webhooks:
- apiGroups:
- infrastructure.cluster.x-k8s.io
apiVersions:
- - v1alpha8
+ - v1beta1
operations:
- CREATE
- UPDATE
@@ -121,7 +121,7 @@ webhooks:
service:
name: webhook-service
namespace: system
- path: /validate-infrastructure-cluster-x-k8s-io-v1alpha8-openstackmachine
+ path: /validate-infrastructure-cluster-x-k8s-io-v1beta1-openstackmachine
failurePolicy: Fail
matchPolicy: Equivalent
name: validation.openstackmachine.infrastructure.cluster.x-k8s.io
@@ -129,7 +129,7 @@ webhooks:
- apiGroups:
- infrastructure.cluster.x-k8s.io
apiVersions:
- - v1alpha8
+ - v1beta1
operations:
- CREATE
- UPDATE
@@ -142,7 +142,7 @@ webhooks:
service:
name: webhook-service
namespace: system
- path: /validate-infrastructure-cluster-x-k8s-io-v1alpha8-openstackmachinetemplate
+ path: /validate-infrastructure-cluster-x-k8s-io-v1beta1-openstackmachinetemplate
failurePolicy: Fail
matchPolicy: Equivalent
name: validation.openstackmachinetemplate.infrastructure.cluster.x-k8s.io
@@ -150,7 +150,7 @@ webhooks:
- apiGroups:
- infrastructure.cluster.x-k8s.io
apiVersions:
- - v1alpha8
+ - v1beta1
operations:
- CREATE
- UPDATE
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index a06e9e4aa8..e6712e5257 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -47,7 +47,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/predicate"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ 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"
diff --git a/controllers/openstackcluster_controller_test.go b/controllers/openstackcluster_controller_test.go
index 87d63ff7cc..8b99f0dc5f 100644
--- a/controllers/openstackcluster_controller_test.go
+++ b/controllers/openstackcluster_controller_test.go
@@ -42,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/v1alpha8"
+ 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"
)
diff --git a/controllers/openstackfloatingippool_controller.go b/controllers/openstackfloatingippool_controller.go
index c01a5603dd..7c72bc081d 100644
--- a/controllers/openstackfloatingippool_controller.go
+++ b/controllers/openstackfloatingippool_controller.go
@@ -42,7 +42,7 @@ import (
infrav1alpha1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha1"
infrav1alpha7 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ 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"
)
diff --git a/controllers/openstackmachine_controller.go b/controllers/openstackmachine_controller.go
index 15171c9f11..77d092f268 100644
--- a/controllers/openstackmachine_controller.go
+++ b/controllers/openstackmachine_controller.go
@@ -48,7 +48,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/predicate"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ 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"
diff --git a/controllers/openstackmachine_controller_test.go b/controllers/openstackmachine_controller_test.go
index a498ba93a3..a541795528 100644
--- a/controllers/openstackmachine_controller_test.go
+++ b/controllers/openstackmachine_controller_test.go
@@ -25,7 +25,7 @@ import (
"k8s.io/utils/pointer"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/cloud/services/compute"
)
diff --git a/controllers/suite_test.go b/controllers/suite_test.go
index 08470ae280..2986a4dde6 100644
--- a/controllers/suite_test.go
+++ b/controllers/suite_test.go
@@ -38,7 +38,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/envtest"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ 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"
diff --git a/docs/book/src/SUMMARY.md b/docs/book/src/SUMMARY.md
index a03f4c5fc7..476311d1f7 100644
--- a/docs/book/src/SUMMARY.md
+++ b/docs/book/src/SUMMARY.md
@@ -11,6 +11,6 @@
- [v1alpha4 to v1alpha5](./topics/crd-changes/v1alpha4-to-v1alpha5.md)
- [v1alpha5 to v1alpha6](./topics/crd-changes/v1alpha5-to-v1alpha6.md)
- [v1alpha6 to v1alpha7](./topics/crd-changes/v1alpha6-to-v1alpha7.md)
- - [v1alpha7 to v1alpha8](./topics/crd-changes/v1alpha7-to-v1alpha8.md)
+ - [v1alpha7 to v1beta1](./topics/crd-changes/v1alpha7-to-v1beta1.md)
- [Development](./development/development.md)
- [Hacking CI](./development/ci.md)
diff --git a/docs/book/src/clusteropenstack/configuration.md b/docs/book/src/clusteropenstack/configuration.md
index 0a87afcee1..810d33b322 100644
--- a/docs/book/src/clusteropenstack/configuration.md
+++ b/docs/book/src/clusteropenstack/configuration.md
@@ -186,7 +186,7 @@ The recommmend minimum value of control plane flavor's vCPU is 2 and minimum val
Depending on the CNI that will be deployed on the cluster, you may need to add specific security group rules to the control plane and worker nodes. For example, if you are using Calico with BGP, you will need to add the following security group rules to the control plane and worker nodes:
```yaml
- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+ apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackCluster
metadata:
name:
@@ -239,7 +239,7 @@ Note: If your openstack cluster does not already have a public network, you shou
You can use a pre-existing router instead of creating a new one. When deleting a cluster a pre-existing router will not be deleted.
```yaml
- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+ apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackCluster
metadata:
name:
@@ -306,7 +306,7 @@ It is possible to restrict access to the Kubernetes API server on a network leve
the allowed CIDRs by `spec.APIServerLoadBalancer.AllowedCIDRs` of `OpenStackCluster`.
```yaml
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackCluster
metadata:
name:
@@ -324,7 +324,7 @@ All known IPs of the target cluster will be discovered dynamically (e.g. you don
All applied CIDRs (user defined + dynamically discovered) are written back into `status.network.apiServerLoadBalancer.allowedCIDRs`
```yaml
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackCluster
metadata:
name:
@@ -357,7 +357,7 @@ If you have a complex query that you want to use to lookup a network, then you c
By using filters to look up a network, please note that it is possible to get multiple networks as a result. This should not be a problem, however please test your filters with `openstack network list` to be certain that it returns the networks you want. Please refer to the following usage example:
```yaml
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
metadata:
name: -controlplane
@@ -375,7 +375,7 @@ spec:
You can specify multiple networks (or subnets) to connect your server to. To do this, simply add another entry in the networks array. The following example connects the server to 3 different networks:
```yaml
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
metadata:
name: -controlplane
@@ -399,7 +399,7 @@ spec:
Rather than just using a network, you have the option of specifying a specific subnet to connect your server to. The following is an example of how to specify a specific subnet of a network to use for your server.
```yaml
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
metadata:
name: -controlplane
@@ -420,7 +420,7 @@ spec:
A server can also be connected to networks by describing what ports to create. Describing a server's connection with `ports` allows for finer and more advanced configuration. For example, you can specify per-port security groups, fixed IPs, VNIC type or profile.
```yaml
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
metadata:
name: -controlplane
@@ -518,7 +518,7 @@ ports:
`port security` can be applied to specific port to enable/disable the `port security` on that port; When not set, it takes the value of the corresponding field at the network level.
```yaml
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
metadata:
name: -controlplane
@@ -589,7 +589,7 @@ If this is not flexible enough, pre-existing security groups can be added to the
spec of an `OpenStackMachineTemplate`, e.g.:
```yaml
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
metadata:
name: ${CLUSTER_NAME}-control-plane
@@ -605,7 +605,7 @@ spec:
You have the ability to tag all resources created by the cluster in the `OpenStackCluster` spec. Here is an example how to configure tagging:
```yaml
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackCluster
metadata:
name:
@@ -618,7 +618,7 @@ spec:
To tag resources specific to a machine, add a value to the tags field in the `OpenStackMachineTemplate` spec like this:
```yaml
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
metadata:
name: -controlplane
@@ -635,7 +635,7 @@ spec:
You also have the option to add metadata to instances. Here is a usage example:
```yaml
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
metadata:
name: -controlplane
@@ -653,7 +653,7 @@ spec:
For example in `OpenStackMachineTemplate` set `spec.rootVolume.diskSize` to something greater than `0` means boot from volume.
```yaml
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
metadata:
name: -controlplane
diff --git a/docs/book/src/development/development.md b/docs/book/src/development/development.md
index 9f5309fd77..661ac84ec6 100644
--- a/docs/book/src/development/development.md
+++ b/docs/book/src/development/development.md
@@ -500,6 +500,6 @@ This sections goal is to gather various insights into the API design that can se
### `referencedResources`
-Starting from v1alpha8 both `OpenStackMachineStatus` and `BastionsStatus` feature a field named `referencedResources` which aims to include fields that list individual IDs of the resources associated with the machine or bastion. These IDs are calculated on machine or bastion creation and are not intended to be changed during the object lifecycle.
+Starting from v1beta1 both `OpenStackMachineStatus` and `BastionsStatus` feature a field named `referencedResources` which aims to include fields that list individual IDs of the resources associated with the machine or bastion. These IDs are calculated on machine or bastion creation and are not intended to be changed during the object lifecycle.
Having all the IDs of related resources saved in the statuses allows CAPO to make easy decisions about deleting the related resources when deleting the VM corresponding to the machine or bastion.
diff --git a/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md b/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
similarity index 85%
rename from docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md
rename to docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
index 8ea68de168..2cdc4560cd 100644
--- a/docs/book/src/topics/crd-changes/v1alpha7-to-v1alpha8.md
+++ b/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
@@ -2,7 +2,7 @@
**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
-- [v1alpha7 compared to v1alpha8](#v1alpha7-compared-to-v1alpha8)
+- [v1alpha7 compared to v1beta1](#v1alpha7-compared-to-v1beta1)
- [Migration](#migration)
- [API Changes](#api-changes)
- [`OpenStackMachine`](#openstackmachine)
@@ -21,17 +21,17 @@
-# v1alpha7 compared to v1alpha8
+# v1alpha7 compared to v1beta1
-> ⚠️ v1alpha8 has not been released yet.
+> ⚠️ v1beta1 has not been released yet.
## Migration
-All users are encouraged to migrate their usage of the CAPO CRDs from older versions to `v1alpha8`. This includes yaml files and source code. As CAPO implements automatic conversions between the CRD versions, this migration can happen after installing the new CAPO release.
+All users are encouraged to migrate their usage of the CAPO CRDs from older versions to `v1beta1`. This includes yaml files and source code. As CAPO implements automatic conversions between the CRD versions, this migration can happen after installing the new CAPO release.
## API Changes
-This only documents backwards incompatible changes. Fields that were added to v1alpha8 are not listed here.
+This only documents backwards incompatible changes. Fields that were added to v1beta1 are not listed here.
### `OpenStackMachine`
@@ -173,14 +173,14 @@ spec:
#### Change to subnet
-In v1alpha8, `Subnet` of `OpenStackCluster` is modified to `Subnets` to allow specification of two existent subnets for the dual-stack scenario.
+In v1beta1, `Subnet` of `OpenStackCluster` is modified to `Subnets` to allow specification of two existent subnets for the dual-stack scenario.
```yaml
subnet:
id: a532beb0-c73a-4b5d-af66-3ad05b73d063
```
-In v1alpha8, this will be automatically converted to:
+In v1beta1, this will be automatically converted to:
```yaml
subnets:
@@ -193,14 +193,14 @@ When subnets are not specified on `OpenStackCluster` and only the network is, th
#### Change to nodeCidr and dnsNameservers
-In v1alpha8, `OpenStackCluster.Spec.ManagedSubnets` array field is introduced. The `NodeCIDR` and `DNSNameservers` fields of `OpenStackCluster.Spec` are moved into that structure (renaming `NodeCIDR` to `CIDR`). For example:
+In v1beta1, `OpenStackCluster.Spec.ManagedSubnets` array field is introduced. The `NodeCIDR` and `DNSNameservers` fields of `OpenStackCluster.Spec` are moved into that structure (renaming `NodeCIDR` to `CIDR`). For example:
```yaml
nodeCidr: "10.0.0.0/24"
dnsNameservers: "10.0.0.123"
```
-In v1alpha8, this will be automatically converted to:
+In v1beta1, this will be automatically converted to:
```yaml
managedSubnets:
@@ -212,7 +212,7 @@ Please note that currently `managedSubnets` can only hold one element.
#### Addition of allocationPools
-In v1alpha8, an `AllocationPools` property is introduced to `OpenStackCluster.Spec.ManagedSubnets`. When specified, OpenStack subnet created by CAPO will have the given values set as the `allocation_pools` property. This allows users to make sure OpenStack will not allocate some IP ranges in the subnet automatically. If the subnet is precreated and configured, CAPO will ignore `AllocationPools` property.
+In v1beta1, an `AllocationPools` property is introduced to `OpenStackCluster.Spec.ManagedSubnets`. When specified, OpenStack subnet created by CAPO will have the given values set as the `allocation_pools` property. This allows users to make sure OpenStack will not allocate some IP ranges in the subnet automatically. If the subnet is precreated and configured, CAPO will ignore `AllocationPools` property.
#### Change to managedSecurityGroups
@@ -276,4 +276,4 @@ allow backwards compatibility if `allowAllInClusterTraffic` is set to false.
#### Change to network
-In v1alpha8, when the `OpenStackCluster.Spec.Network` is not defined, the `Subnets` are now used to identify the `Network`.
+In v1beta1, when the `OpenStackCluster.Spec.Network` is not defined, the `Subnets` are now used to identify the `Network`.
diff --git a/kustomize/v1alpha8/default/cluster-template.yaml b/kustomize/v1beta1/default/cluster-template.yaml
similarity index 92%
rename from kustomize/v1alpha8/default/cluster-template.yaml
rename to kustomize/v1beta1/default/cluster-template.yaml
index cdee2550fc..f626c0328f 100644
--- a/kustomize/v1alpha8/default/cluster-template.yaml
+++ b/kustomize/v1beta1/default/cluster-template.yaml
@@ -9,7 +9,7 @@ spec:
cidrBlocks: ["192.168.0.0/16"] # CIDR block used by Calico.
serviceDomain: "cluster.local"
infrastructureRef:
- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+ apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackCluster
name: ${CLUSTER_NAME}
controlPlaneRef:
@@ -17,7 +17,7 @@ spec:
apiVersion: controlplane.cluster.x-k8s.io/v1beta1
name: ${CLUSTER_NAME}-control-plane
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackCluster
metadata:
name: ${CLUSTER_NAME}
@@ -63,7 +63,7 @@ spec:
machineTemplate:
infrastructureRef:
kind: OpenStackMachineTemplate
- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+ apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
name: "${CLUSTER_NAME}-control-plane"
kubeadmConfigSpec:
initConfiguration:
@@ -88,7 +88,7 @@ spec:
files: []
version: "${KUBERNETES_VERSION}"
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
metadata:
name: ${CLUSTER_NAME}-control-plane
@@ -124,10 +124,10 @@ spec:
kind: KubeadmConfigTemplate
infrastructureRef:
name: "${CLUSTER_NAME}-md-0"
- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+ apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
metadata:
name: ${CLUSTER_NAME}-md-0
diff --git a/kustomize/v1alpha8/default/kustomization.yaml b/kustomize/v1beta1/default/kustomization.yaml
similarity index 100%
rename from kustomize/v1alpha8/default/kustomization.yaml
rename to kustomize/v1beta1/default/kustomization.yaml
diff --git a/kustomize/v1alpha8/flatcar-sysext/kustomization.yaml b/kustomize/v1beta1/flatcar-sysext/kustomization.yaml
similarity index 100%
rename from kustomize/v1alpha8/flatcar-sysext/kustomization.yaml
rename to kustomize/v1beta1/flatcar-sysext/kustomization.yaml
diff --git a/kustomize/v1alpha8/flatcar-sysext/patch-flatcar.yaml b/kustomize/v1beta1/flatcar-sysext/patch-flatcar.yaml
similarity index 98%
rename from kustomize/v1alpha8/flatcar-sysext/patch-flatcar.yaml
rename to kustomize/v1beta1/flatcar-sysext/patch-flatcar.yaml
index e66245f777..fce635f466 100644
--- a/kustomize/v1alpha8/flatcar-sysext/patch-flatcar.yaml
+++ b/kustomize/v1beta1/flatcar-sysext/patch-flatcar.yaml
@@ -1,5 +1,5 @@
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackCluster
metadata:
name: ${CLUSTER_NAME}
@@ -166,7 +166,7 @@ spec:
[Service]
EnvironmentFile=/run/metadata/flatcar
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
metadata:
name: ${CLUSTER_NAME}-md-0
@@ -176,7 +176,7 @@ spec:
image:
name: ${FLATCAR_IMAGE_NAME}
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
metadata:
name: ${CLUSTER_NAME}-control-plane
diff --git a/kustomize/v1alpha8/flatcar/kustomization.yaml b/kustomize/v1beta1/flatcar/kustomization.yaml
similarity index 100%
rename from kustomize/v1alpha8/flatcar/kustomization.yaml
rename to kustomize/v1beta1/flatcar/kustomization.yaml
diff --git a/kustomize/v1alpha8/flatcar/patch-flatcar.yaml b/kustomize/v1beta1/flatcar/patch-flatcar.yaml
similarity index 95%
rename from kustomize/v1alpha8/flatcar/patch-flatcar.yaml
rename to kustomize/v1beta1/flatcar/patch-flatcar.yaml
index 4fb1c3a8d1..19e7b7fece 100644
--- a/kustomize/v1alpha8/flatcar/patch-flatcar.yaml
+++ b/kustomize/v1beta1/flatcar/patch-flatcar.yaml
@@ -1,5 +1,5 @@
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackCluster
metadata:
name: ${CLUSTER_NAME}
@@ -90,7 +90,7 @@ spec:
[Service]
EnvironmentFile=/run/metadata/flatcar
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
metadata:
name: ${CLUSTER_NAME}-md-0
@@ -100,7 +100,7 @@ spec:
image:
name: ${OPENSTACK_FLATCAR_IMAGE_NAME}
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
metadata:
name: ${CLUSTER_NAME}-control-plane
diff --git a/kustomize/v1alpha8/without-lb/kustomization.yaml b/kustomize/v1beta1/without-lb/kustomization.yaml
similarity index 100%
rename from kustomize/v1alpha8/without-lb/kustomization.yaml
rename to kustomize/v1beta1/without-lb/kustomization.yaml
diff --git a/kustomize/v1alpha8/without-lb/patch-without-lb.yaml b/kustomize/v1beta1/without-lb/patch-without-lb.yaml
similarity index 83%
rename from kustomize/v1alpha8/without-lb/patch-without-lb.yaml
rename to kustomize/v1beta1/without-lb/patch-without-lb.yaml
index 57166c05e2..96932f5a27 100644
--- a/kustomize/v1alpha8/without-lb/patch-without-lb.yaml
+++ b/kustomize/v1beta1/without-lb/patch-without-lb.yaml
@@ -1,5 +1,5 @@
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackCluster
metadata:
name: ${CLUSTER_NAME}
diff --git a/main.go b/main.go
index f9dfdd5d03..9fa9fc5eb0 100644
--- a/main.go
+++ b/main.go
@@ -49,7 +49,7 @@ import (
infrav1alpha5 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha5"
infrav1alpha6 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha6"
infrav1alpha7 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/controllers"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/metrics"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/record"
diff --git a/pkg/cloud/services/compute/dependent_resources.go b/pkg/cloud/services/compute/dependent_resources.go
index 2db2f64bdf..6e2a5eb270 100644
--- a/pkg/cloud/services/compute/dependent_resources.go
+++ b/pkg/cloud/services/compute/dependent_resources.go
@@ -17,7 +17,7 @@ limitations under the License.
package compute
import (
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ 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"
)
diff --git a/pkg/cloud/services/compute/dependent_resources_test.go b/pkg/cloud/services/compute/dependent_resources_test.go
index f9567929af..1bfb8d5791 100644
--- a/pkg/cloud/services/compute/dependent_resources_test.go
+++ b/pkg/cloud/services/compute/dependent_resources_test.go
@@ -25,7 +25,7 @@ import (
. "github.com/onsi/gomega"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
)
diff --git a/pkg/cloud/services/compute/instance.go b/pkg/cloud/services/compute/instance.go
index 147f4f729d..747fbf02bb 100644
--- a/pkg/cloud/services/compute/instance.go
+++ b/pkg/cloud/services/compute/instance.go
@@ -33,7 +33,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/wait"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ 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/record"
capoerrors "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/errors"
diff --git a/pkg/cloud/services/compute/instance_test.go b/pkg/cloud/services/compute/instance_test.go
index 345987d510..69b0ac05b8 100644
--- a/pkg/cloud/services/compute/instance_test.go
+++ b/pkg/cloud/services/compute/instance_test.go
@@ -34,7 +34,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/utils/pointer"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ 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/scope"
diff --git a/pkg/cloud/services/compute/instance_types.go b/pkg/cloud/services/compute/instance_types.go
index 0384e64f89..6c9c211936 100644
--- a/pkg/cloud/services/compute/instance_types.go
+++ b/pkg/cloud/services/compute/instance_types.go
@@ -24,7 +24,7 @@ import (
"github.com/go-logr/logr"
corev1 "k8s.io/api/core/v1"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients"
)
diff --git a/pkg/cloud/services/compute/referenced_resources.go b/pkg/cloud/services/compute/referenced_resources.go
index 1d2de809a2..c78298ce16 100644
--- a/pkg/cloud/services/compute/referenced_resources.go
+++ b/pkg/cloud/services/compute/referenced_resources.go
@@ -17,7 +17,7 @@ limitations under the License.
package compute
import (
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ 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"
)
diff --git a/pkg/cloud/services/compute/referenced_resources_test.go b/pkg/cloud/services/compute/referenced_resources_test.go
index 74dc9d8c63..06f6a8f5d2 100644
--- a/pkg/cloud/services/compute/referenced_resources_test.go
+++ b/pkg/cloud/services/compute/referenced_resources_test.go
@@ -27,7 +27,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions"
. "github.com/onsi/gomega"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/mock"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
)
diff --git a/pkg/cloud/services/compute/servergroup.go b/pkg/cloud/services/compute/servergroup.go
index b084a99634..f4118da73f 100644
--- a/pkg/cloud/services/compute/servergroup.go
+++ b/pkg/cloud/services/compute/servergroup.go
@@ -21,7 +21,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/servergroups"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
)
// GetServerGroupID looks up a server group using the passed filter and returns
diff --git a/pkg/cloud/services/compute/servergroup_test.go b/pkg/cloud/services/compute/servergroup_test.go
index 572e3d78c6..af8ed35f02 100644
--- a/pkg/cloud/services/compute/servergroup_test.go
+++ b/pkg/cloud/services/compute/servergroup_test.go
@@ -24,7 +24,7 @@ import (
"github.com/golang/mock/gomock"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/servergroups"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/mock"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
)
diff --git a/pkg/cloud/services/loadbalancer/loadbalancer.go b/pkg/cloud/services/loadbalancer/loadbalancer.go
index 956e346002..1d0812c353 100644
--- a/pkg/cloud/services/loadbalancer/loadbalancer.go
+++ b/pkg/cloud/services/loadbalancer/loadbalancer.go
@@ -33,7 +33,7 @@ import (
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
"sigs.k8s.io/cluster-api/util"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/record"
capoerrors "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/errors"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/names"
diff --git a/pkg/cloud/services/loadbalancer/loadbalancer_test.go b/pkg/cloud/services/loadbalancer/loadbalancer_test.go
index b4a8960a29..d4a6b69a09 100644
--- a/pkg/cloud/services/loadbalancer/loadbalancer_test.go
+++ b/pkg/cloud/services/loadbalancer/loadbalancer_test.go
@@ -32,7 +32,7 @@ import (
. "github.com/onsi/gomega"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/mock"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
)
diff --git a/pkg/cloud/services/networking/floatingip.go b/pkg/cloud/services/networking/floatingip.go
index 8586ba6223..f7fc8dc308 100644
--- a/pkg/cloud/services/networking/floatingip.go
+++ b/pkg/cloud/services/networking/floatingip.go
@@ -26,7 +26,7 @@ import (
"k8s.io/apimachinery/pkg/util/wait"
"sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha1"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/metrics"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/record"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/names"
diff --git a/pkg/cloud/services/networking/floatingip_test.go b/pkg/cloud/services/networking/floatingip_test.go
index 06c1fdc005..e25a42ab53 100644
--- a/pkg/cloud/services/networking/floatingip_test.go
+++ b/pkg/cloud/services/networking/floatingip_test.go
@@ -23,7 +23,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips"
. "github.com/onsi/gomega"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/mock"
)
diff --git a/pkg/cloud/services/networking/network.go b/pkg/cloud/services/networking/network.go
index 18c79d9433..d1dc15c07f 100644
--- a/pkg/cloud/services/networking/network.go
+++ b/pkg/cloud/services/networking/network.go
@@ -25,7 +25,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
"github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/metrics"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/record"
capoerrors "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/errors"
diff --git a/pkg/cloud/services/networking/network_test.go b/pkg/cloud/services/networking/network_test.go
index f1c351fc8a..1781ecab67 100644
--- a/pkg/cloud/services/networking/network_test.go
+++ b/pkg/cloud/services/networking/network_test.go
@@ -28,7 +28,7 @@ import (
. "github.com/onsi/gomega"
"k8s.io/utils/pointer"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/mock"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/names"
diff --git a/pkg/cloud/services/networking/port.go b/pkg/cloud/services/networking/port.go
index 6848776358..5df5002534 100644
--- a/pkg/cloud/services/networking/port.go
+++ b/pkg/cloud/services/networking/port.go
@@ -29,7 +29,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/wait"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/record"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
capoerrors "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/errors"
diff --git a/pkg/cloud/services/networking/port_test.go b/pkg/cloud/services/networking/port_test.go
index 4805da89e8..57103319e0 100644
--- a/pkg/cloud/services/networking/port_test.go
+++ b/pkg/cloud/services/networking/port_test.go
@@ -32,7 +32,7 @@ import (
. "github.com/onsi/gomega"
"k8s.io/utils/pointer"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/mock"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
)
diff --git a/pkg/cloud/services/networking/router.go b/pkg/cloud/services/networking/router.go
index 021617c060..88fe117f1f 100644
--- a/pkg/cloud/services/networking/router.go
+++ b/pkg/cloud/services/networking/router.go
@@ -24,7 +24,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
"github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/record"
capoerrors "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/errors"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/names"
diff --git a/pkg/cloud/services/networking/securitygroups.go b/pkg/cloud/services/networking/securitygroups.go
index 664f9e84b4..175b46e179 100644
--- a/pkg/cloud/services/networking/securitygroups.go
+++ b/pkg/cloud/services/networking/securitygroups.go
@@ -23,7 +23,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/record"
)
diff --git a/pkg/cloud/services/networking/securitygroups_test.go b/pkg/cloud/services/networking/securitygroups_test.go
index 407f964559..e09ba9b7fb 100644
--- a/pkg/cloud/services/networking/securitygroups_test.go
+++ b/pkg/cloud/services/networking/securitygroups_test.go
@@ -26,7 +26,7 @@ import (
. "github.com/onsi/gomega"
"k8s.io/utils/pointer"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/mock"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
)
diff --git a/pkg/cloud/services/networking/trunk_test.go b/pkg/cloud/services/networking/trunk_test.go
index 24c6bfb719..a75519d8a8 100644
--- a/pkg/cloud/services/networking/trunk_test.go
+++ b/pkg/cloud/services/networking/trunk_test.go
@@ -23,7 +23,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/trunks"
. "github.com/onsi/gomega"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/mock"
)
diff --git a/pkg/scope/mock.go b/pkg/scope/mock.go
index 7dd2364b92..4568a66d19 100644
--- a/pkg/scope/mock.go
+++ b/pkg/scope/mock.go
@@ -26,7 +26,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha1"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ 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"
)
diff --git a/pkg/scope/provider.go b/pkg/scope/provider.go
index 707b08b5b9..2b531f361d 100644
--- a/pkg/scope/provider.go
+++ b/pkg/scope/provider.go
@@ -38,7 +38,7 @@ import (
"sigs.k8s.io/yaml"
"sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha1"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ 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/utils/hash"
"sigs.k8s.io/cluster-api-provider-openstack/version"
diff --git a/pkg/scope/scope.go b/pkg/scope/scope.go
index 5c8f24b968..6b16e908f1 100644
--- a/pkg/scope/scope.go
+++ b/pkg/scope/scope.go
@@ -25,7 +25,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha1"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients"
)
diff --git a/pkg/utils/controllers/controllers.go b/pkg/utils/controllers/controllers.go
index 94dfb11ac4..8c5f8f9fa2 100644
--- a/pkg/utils/controllers/controllers.go
+++ b/pkg/utils/controllers/controllers.go
@@ -20,7 +20,7 @@ import (
"fmt"
"net"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
)
// ValidateSubnets validates if the amount of IPv4 and IPv6 subnets is allowed by OpenStackCluster.
diff --git a/pkg/utils/controllers/controllers_test.go b/pkg/utils/controllers/controllers_test.go
index eadff95b77..eea58d08f4 100644
--- a/pkg/utils/controllers/controllers_test.go
+++ b/pkg/utils/controllers/controllers_test.go
@@ -19,7 +19,7 @@ package controllers
import (
"testing"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
)
func Test_validateSubnets(t *testing.T) {
diff --git a/templates/cluster-template-flatcar-sysext.yaml b/templates/cluster-template-flatcar-sysext.yaml
index 0cdd02dc0e..809f386085 100644
--- a/templates/cluster-template-flatcar-sysext.yaml
+++ b/templates/cluster-template-flatcar-sysext.yaml
@@ -98,7 +98,7 @@ spec:
kind: KubeadmControlPlane
name: ${CLUSTER_NAME}-control-plane
infrastructureRef:
- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+ apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackCluster
name: ${CLUSTER_NAME}
---
@@ -121,7 +121,7 @@ spec:
clusterName: ${CLUSTER_NAME}
failureDomain: ${OPENSTACK_FAILURE_DOMAIN}
infrastructureRef:
- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+ apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
name: ${CLUSTER_NAME}-md-0
version: ${KUBERNETES_VERSION}
@@ -213,13 +213,13 @@ spec:
- mv /etc/kubeadm.yml.tmp /etc/kubeadm.yml
machineTemplate:
infrastructureRef:
- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+ apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
name: ${CLUSTER_NAME}-control-plane
replicas: ${CONTROL_PLANE_MACHINE_COUNT}
version: ${KUBERNETES_VERSION}
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackCluster
metadata:
name: ${CLUSTER_NAME}
@@ -254,7 +254,7 @@ spec:
dnsNameservers:
- ${OPENSTACK_DNS_NAMESERVERS}
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
metadata:
name: ${CLUSTER_NAME}-control-plane
@@ -269,7 +269,7 @@ spec:
name: ${FLATCAR_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
metadata:
name: ${CLUSTER_NAME}-md-0
diff --git a/templates/cluster-template-flatcar.yaml b/templates/cluster-template-flatcar.yaml
index 535a177fcd..a0db85b493 100644
--- a/templates/cluster-template-flatcar.yaml
+++ b/templates/cluster-template-flatcar.yaml
@@ -60,7 +60,7 @@ spec:
kind: KubeadmControlPlane
name: ${CLUSTER_NAME}-control-plane
infrastructureRef:
- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+ apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackCluster
name: ${CLUSTER_NAME}
---
@@ -83,7 +83,7 @@ spec:
clusterName: ${CLUSTER_NAME}
failureDomain: ${OPENSTACK_FAILURE_DOMAIN}
infrastructureRef:
- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+ apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
name: ${CLUSTER_NAME}-md-0
version: ${KUBERNETES_VERSION}
@@ -137,13 +137,13 @@ spec:
- mv /etc/kubeadm.yml.tmp /etc/kubeadm.yml
machineTemplate:
infrastructureRef:
- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+ apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
name: ${CLUSTER_NAME}-control-plane
replicas: ${CONTROL_PLANE_MACHINE_COUNT}
version: ${KUBERNETES_VERSION}
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackCluster
metadata:
name: ${CLUSTER_NAME}
@@ -178,7 +178,7 @@ spec:
dnsNameservers:
- ${OPENSTACK_DNS_NAMESERVERS}
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
metadata:
name: ${CLUSTER_NAME}-control-plane
@@ -193,7 +193,7 @@ spec:
name: ${OPENSTACK_FLATCAR_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
metadata:
name: ${CLUSTER_NAME}-md-0
diff --git a/templates/cluster-template-without-lb.yaml b/templates/cluster-template-without-lb.yaml
index 6b3e402d4f..cc560e5571 100644
--- a/templates/cluster-template-without-lb.yaml
+++ b/templates/cluster-template-without-lb.yaml
@@ -38,7 +38,7 @@ spec:
kind: KubeadmControlPlane
name: ${CLUSTER_NAME}-control-plane
infrastructureRef:
- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+ apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackCluster
name: ${CLUSTER_NAME}
---
@@ -61,7 +61,7 @@ spec:
clusterName: ${CLUSTER_NAME}
failureDomain: ${OPENSTACK_FAILURE_DOMAIN}
infrastructureRef:
- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+ apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
name: ${CLUSTER_NAME}-md-0
version: ${KUBERNETES_VERSION}
@@ -94,13 +94,13 @@ spec:
name: '{{ local_hostname }}'
machineTemplate:
infrastructureRef:
- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+ apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
name: ${CLUSTER_NAME}-control-plane
replicas: 1
version: ${KUBERNETES_VERSION}
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackCluster
metadata:
name: ${CLUSTER_NAME}
@@ -135,7 +135,7 @@ spec:
dnsNameservers:
- ${OPENSTACK_DNS_NAMESERVERS}
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
metadata:
name: ${CLUSTER_NAME}-control-plane
@@ -150,7 +150,7 @@ spec:
name: ${OPENSTACK_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
metadata:
name: ${CLUSTER_NAME}-md-0
diff --git a/templates/cluster-template.yaml b/templates/cluster-template.yaml
index f3886fc8ec..b8cb9db972 100644
--- a/templates/cluster-template.yaml
+++ b/templates/cluster-template.yaml
@@ -38,7 +38,7 @@ spec:
kind: KubeadmControlPlane
name: ${CLUSTER_NAME}-control-plane
infrastructureRef:
- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+ apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackCluster
name: ${CLUSTER_NAME}
---
@@ -61,7 +61,7 @@ spec:
clusterName: ${CLUSTER_NAME}
failureDomain: ${OPENSTACK_FAILURE_DOMAIN}
infrastructureRef:
- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+ apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
name: ${CLUSTER_NAME}-md-0
version: ${KUBERNETES_VERSION}
@@ -94,13 +94,13 @@ spec:
name: '{{ local_hostname }}'
machineTemplate:
infrastructureRef:
- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+ apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
name: ${CLUSTER_NAME}-control-plane
replicas: ${CONTROL_PLANE_MACHINE_COUNT}
version: ${KUBERNETES_VERSION}
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackCluster
metadata:
name: ${CLUSTER_NAME}
@@ -137,7 +137,7 @@ spec:
dnsNameservers:
- ${OPENSTACK_DNS_NAMESERVERS}
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
metadata:
name: ${CLUSTER_NAME}-control-plane
@@ -152,7 +152,7 @@ spec:
name: ${OPENSTACK_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
metadata:
name: ${CLUSTER_NAME}-md-0
diff --git a/templates/clusterclass-dev-test.yaml b/templates/clusterclass-dev-test.yaml
index a73e07dd3b..c329fd5831 100644
--- a/templates/clusterclass-dev-test.yaml
+++ b/templates/clusterclass-dev-test.yaml
@@ -10,12 +10,12 @@ spec:
name: dev-test-control-plane
machineInfrastructure:
ref:
- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+ apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
name: dev-test-control-plane-machine
infrastructure:
ref:
- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+ apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackClusterTemplate
name: dev-test-openstackcluster
workers:
@@ -29,7 +29,7 @@ spec:
name: dev-test-default-worker-bootstraptemplate
infrastructure:
ref:
- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+ apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
name: dev-test-default-worker-machine
patches:
@@ -37,7 +37,7 @@ spec:
description: "Sets the OpenStack image that is used for creating the servers."
definitions:
- selector:
- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+ apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
matchResources:
controlPlane: true
@@ -51,7 +51,7 @@ spec:
description: "Sets the OpenStack image that is used for creating the servers."
definitions:
- selector:
- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+ apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
matchResources:
machineDeploymentClass:
@@ -108,7 +108,7 @@ spec:
provider-id: openstack:///'{{ instance_id }}'
name: '{{ local_hostname }}'
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackClusterTemplate
metadata:
name: dev-test-openstackcluster
@@ -145,7 +145,7 @@ spec:
dnsNameservers:
- 8.8.8.8
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
metadata:
name: dev-test-control-plane-machine
@@ -160,7 +160,7 @@ spec:
name: overridden-by-patch
sshKeyName: ${OPENSTACK_SSH_KEY_NAME:=""}
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
metadata:
name: dev-test-default-worker-machine
diff --git a/test/e2e/data/kustomize/default/kustomization.yaml b/test/e2e/data/kustomize/default/kustomization.yaml
index b648538489..3cd7a6cbb8 100644
--- a/test/e2e/data/kustomize/default/kustomization.yaml
+++ b/test/e2e/data/kustomize/default/kustomization.yaml
@@ -1,7 +1,7 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
-- ../../../../../kustomize/v1alpha8/default
+- ../../../../../kustomize/v1beta1/default
components:
- ../common-patches/cni
- ../upgrade-patches
diff --git a/test/e2e/data/kustomize/flatcar-sysext/kustomization.yaml b/test/e2e/data/kustomize/flatcar-sysext/kustomization.yaml
index c3d83b26c3..8fd5f119f8 100644
--- a/test/e2e/data/kustomize/flatcar-sysext/kustomization.yaml
+++ b/test/e2e/data/kustomize/flatcar-sysext/kustomization.yaml
@@ -1,6 +1,6 @@
---
resources:
-- ../../../../../kustomize/v1alpha8/flatcar-sysext
+- ../../../../../kustomize/v1beta1/flatcar-sysext
components:
- ../common-patches/cni
diff --git a/test/e2e/data/kustomize/flatcar/kustomization.yaml b/test/e2e/data/kustomize/flatcar/kustomization.yaml
index 2d7874e6ac..a85308b72c 100644
--- a/test/e2e/data/kustomize/flatcar/kustomization.yaml
+++ b/test/e2e/data/kustomize/flatcar/kustomization.yaml
@@ -1,7 +1,7 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
-- ../../../../../kustomize/v1alpha8/flatcar
+- ../../../../../kustomize/v1beta1/flatcar
components:
- ../common-patches/cni
diff --git a/test/e2e/data/kustomize/k8s-upgrade/kcp-patch.yaml b/test/e2e/data/kustomize/k8s-upgrade/kcp-patch.yaml
index 0eb4b5f713..859ff0c6fc 100644
--- a/test/e2e/data/kustomize/k8s-upgrade/kcp-patch.yaml
+++ b/test/e2e/data/kustomize/k8s-upgrade/kcp-patch.yaml
@@ -5,6 +5,6 @@ metadata:
spec:
machineTemplate:
infrastructureRef:
- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+ apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
name: ${CLUSTER_NAME}-upgrade-from-control-plane
diff --git a/test/e2e/data/kustomize/k8s-upgrade/md-patch.yaml b/test/e2e/data/kustomize/k8s-upgrade/md-patch.yaml
index fb59a3df2f..a79427f8e3 100644
--- a/test/e2e/data/kustomize/k8s-upgrade/md-patch.yaml
+++ b/test/e2e/data/kustomize/k8s-upgrade/md-patch.yaml
@@ -6,6 +6,6 @@ spec:
template:
spec:
infrastructureRef:
- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+ apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
name: ${CLUSTER_NAME}-upgrade-from-md-0
diff --git a/test/e2e/data/kustomize/k8s-upgrade/upgrade-from-template.yaml b/test/e2e/data/kustomize/k8s-upgrade/upgrade-from-template.yaml
index 60136e0823..73d862f51b 100644
--- a/test/e2e/data/kustomize/k8s-upgrade/upgrade-from-template.yaml
+++ b/test/e2e/data/kustomize/k8s-upgrade/upgrade-from-template.yaml
@@ -1,5 +1,5 @@
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
metadata:
name: ${CLUSTER_NAME}-upgrade-from-control-plane
@@ -16,7 +16,7 @@ spec:
tags:
- control-plane
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
metadata:
name: ${CLUSTER_NAME}-upgrade-from-md-0
diff --git a/test/e2e/data/kustomize/k8s-upgrade/upgrade-to-template.yaml b/test/e2e/data/kustomize/k8s-upgrade/upgrade-to-template.yaml
index b8e499e42c..5b06321073 100644
--- a/test/e2e/data/kustomize/k8s-upgrade/upgrade-to-template.yaml
+++ b/test/e2e/data/kustomize/k8s-upgrade/upgrade-to-template.yaml
@@ -4,7 +4,7 @@
# See CONTROL_PLANE_MACHINE_TEMPLATE_UPGRADE_TO and WORKERS_MACHINE_TEMPLATE_UPGRADE_TO
# in the e2e config.
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
metadata:
name: upgrade-to-control-plane
@@ -23,7 +23,7 @@ spec:
tags:
- control-plane
---
-apiVersion: infrastructure.cluster.x-k8s.io/v1alpha8
+apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
metadata:
name: upgrade-to-md-0
diff --git a/test/e2e/data/kustomize/without-lb/kustomization.yaml b/test/e2e/data/kustomize/without-lb/kustomization.yaml
index dd2efc8c50..c36196f4ac 100644
--- a/test/e2e/data/kustomize/without-lb/kustomization.yaml
+++ b/test/e2e/data/kustomize/without-lb/kustomization.yaml
@@ -1,7 +1,7 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
-- ../../../../../kustomize/v1alpha8/without-lb
+- ../../../../../kustomize/v1beta1/without-lb
components:
- ../common-patches/cni
diff --git a/test/e2e/shared/common.go b/test/e2e/shared/common.go
index 8f1465e23c..b8ad587b90 100644
--- a/test/e2e/shared/common.go
+++ b/test/e2e/shared/common.go
@@ -40,7 +40,7 @@ import (
"sigs.k8s.io/cluster-api/util"
"sigs.k8s.io/controller-runtime/pkg/client"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
)
func SetupSpecNamespace(ctx context.Context, specName string, e2eCtx *E2EContext) *corev1.Namespace {
diff --git a/test/e2e/shared/defaults.go b/test/e2e/shared/defaults.go
index ab2079381f..3c0f32c56e 100644
--- a/test/e2e/shared/defaults.go
+++ b/test/e2e/shared/defaults.go
@@ -26,7 +26,7 @@ import (
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
"sigs.k8s.io/cluster-api/test/framework"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
)
const (
diff --git a/test/e2e/shared/openstack.go b/test/e2e/shared/openstack.go
index b974b01820..2fd5f95d56 100644
--- a/test/e2e/shared/openstack.go
+++ b/test/e2e/shared/openstack.go
@@ -54,7 +54,7 @@ import (
"k8s.io/apimachinery/pkg/util/sets"
"sigs.k8s.io/yaml"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ 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"
diff --git a/test/e2e/suites/e2e/e2e_test.go b/test/e2e/suites/e2e/e2e_test.go
index 41171918c9..5d7098e0dd 100644
--- a/test/e2e/suites/e2e/e2e_test.go
+++ b/test/e2e/suites/e2e/e2e_test.go
@@ -53,7 +53,7 @@ import (
"sigs.k8s.io/cluster-api/test/framework/clusterctl"
crclient "sigs.k8s.io/controller-runtime/pkg/client"
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/test/e2e/shared"
)
From e8ccd212952cebf768171982b2d0cbaf7c59fe6b Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Thu, 22 Feb 2024 02:18:12 +0000
Subject: [PATCH 083/180] Reduce cyclomatic complexity of ReconcileLoadBalancer
This function had become genuinely too complex over time, to the point
that even the linter was starting to complain about it when making
almost any change.
This change refactors ReconcileLoadBalancer into several smaller logical
functions which are much easier to read and reason about. It also
revealed some trivial optimisations:
* Only fetch Octavia providers if we need them to create a new
loadbalancer
* Only calculate allowed CIDRs once
* Don't re-fetch a loadbalancer to check it's active if it's already
active
Co-Authored-By: Emilien Macchi
---
.../services/loadbalancer/loadbalancer.go | 358 ++++++++++-------
.../loadbalancer/loadbalancer_test.go | 360 +++++++++++++++++-
2 files changed, 568 insertions(+), 150 deletions(-)
diff --git a/pkg/cloud/services/loadbalancer/loadbalancer.go b/pkg/cloud/services/loadbalancer/loadbalancer.go
index 1d0812c353..38dda5ecb6 100644
--- a/pkg/cloud/services/loadbalancer/loadbalancer.go
+++ b/pkg/cloud/services/loadbalancer/loadbalancer.go
@@ -76,42 +76,7 @@ func (s *Service) ReconcileLoadBalancer(openStackCluster *infrav1.OpenStackClust
openStackCluster.Status.APIServerLoadBalancer = lbStatus
}
- var fixedIPAddress string
- var err error
-
- switch {
- case lbStatus.InternalIP != "":
- fixedIPAddress = lbStatus.InternalIP
- case openStackCluster.Spec.APIServerFixedIP != "":
- fixedIPAddress = openStackCluster.Spec.APIServerFixedIP
- case openStackCluster.Spec.DisableAPIServerFloatingIP && openStackCluster.Spec.ControlPlaneEndpoint.IsValid():
- fixedIPAddress, err = lookupHost(openStackCluster.Spec.ControlPlaneEndpoint.Host)
- if err != nil {
- return false, fmt.Errorf("lookup host: %w", err)
- }
- }
-
- providers, err := s.loadbalancerClient.ListLoadBalancerProviders()
- if err != nil {
- return false, err
- }
-
- // Choose the selected provider if it is set in cluster spec, if not, omit the field and Octavia will use the default provider.
- lbProvider := ""
- if openStackCluster.Spec.APIServerLoadBalancer.Provider != "" {
- for _, v := range providers {
- if v.Name == openStackCluster.Spec.APIServerLoadBalancer.Provider {
- lbProvider = v.Name
- break
- }
- }
- if lbProvider == "" {
- record.Warnf(openStackCluster, "OctaviaProviderNotFound", "Provider specified for Octavia not found.")
- record.Eventf(openStackCluster, "OctaviaProviderNotFound", "Provider %s specified for Octavia not found, using the default provider.", openStackCluster.Spec.APIServerLoadBalancer.Provider)
- }
- }
-
- lb, err := s.getOrCreateLoadBalancer(openStackCluster, loadBalancerName, openStackCluster.Status.Network.Subnets[0].ID, clusterName, fixedIPAddress, lbProvider)
+ lb, err := s.getOrCreateAPILoadBalancer(openStackCluster, clusterName)
if err != nil {
return false, err
}
@@ -121,23 +86,20 @@ func (s *Service) ReconcileLoadBalancer(openStackCluster *infrav1.OpenStackClust
lbStatus.InternalIP = lb.VipAddress
lbStatus.Tags = lb.Tags
- if err := s.waitForLoadBalancerActive(lb.ID); err != nil {
- return false, fmt.Errorf("load balancer %q with id %s is not active after timeout: %v", loadBalancerName, lb.ID, err)
+ if lb.ProvisioningStatus != loadBalancerProvisioningStatusActive {
+ var err error
+ lb, err = s.waitForLoadBalancerActive(lb.ID)
+ if err != nil {
+ return false, fmt.Errorf("load balancer %q with id %s is not active after timeout: %v", loadBalancerName, lb.ID, err)
+ }
}
if !openStackCluster.Spec.DisableAPIServerFloatingIP {
- var floatingIPAddress string
- switch {
- case lbStatus.IP != "":
- floatingIPAddress = lbStatus.IP
- case openStackCluster.Spec.APIServerFloatingIP != "":
- floatingIPAddress = openStackCluster.Spec.APIServerFloatingIP
- case openStackCluster.Spec.ControlPlaneEndpoint.IsValid():
- floatingIPAddress, err = lookupHost(openStackCluster.Spec.ControlPlaneEndpoint.Host)
- if err != nil {
- return false, fmt.Errorf("lookup host: %w", err)
- }
+ floatingIPAddress, err := getAPIServerFloatingIP(openStackCluster)
+ if err != nil {
+ return false, err
}
+
fp, err := s.networkingService.GetOrCreateFloatingIP(openStackCluster, openStackCluster, clusterName, floatingIPAddress)
if err != nil {
return false, err
@@ -153,71 +115,190 @@ func (s *Service) ReconcileLoadBalancer(openStackCluster *infrav1.OpenStackClust
}
}
- allowedCIDRs := []string{}
- // To reduce API calls towards OpenStack API, let's handle the CIDR support verification for all Ports only once.
- allowedCIDRsSupported := false
- octaviaVersions, err := s.loadbalancerClient.ListOctaviaVersions()
+ allowedCIDRsSupported, err := s.isAllowsCIDRSSupported(lb)
if err != nil {
return false, err
}
- // The current version is always the last one in the list.
- octaviaVersion := octaviaVersions[len(octaviaVersions)-1].ID
- if openstackutil.IsOctaviaFeatureSupported(octaviaVersion, openstackutil.OctaviaFeatureVIPACL, lbProvider) {
- allowedCIDRsSupported = true
+
+ // AllowedCIDRs will be nil if allowed CIDRs is not supported by the Octavia provider
+ if allowedCIDRsSupported {
+ lbStatus.AllowedCIDRs = getCanonicalAllowedCIDRs(openStackCluster)
+ } else {
+ lbStatus.AllowedCIDRs = nil
}
portList := []int{apiServerPort}
portList = append(portList, openStackCluster.Spec.APIServerLoadBalancer.AdditionalPorts...)
for _, port := range portList {
- lbPortObjectsName := fmt.Sprintf("%s-%d", loadBalancerName, port)
+ if err := s.reconcileAPILoadBalancerListener(lb, openStackCluster, clusterName, port); err != nil {
+ return false, err
+ }
+ }
+
+ return false, nil
+}
+
+// getAPIServerVIPAddress gets the VIP address for the API server from wherever it is specified.
+// Returns an empty string if the VIP address is not specified and it should be allocated automatically.
+func getAPIServerVIPAddress(openStackCluster *infrav1.OpenStackCluster) (string, error) {
+ switch {
+ // We only use call this function when creating the loadbalancer, so this case should never be used
+ case openStackCluster.Status.APIServerLoadBalancer != nil && openStackCluster.Status.APIServerLoadBalancer.InternalIP != "":
+ return openStackCluster.Status.APIServerLoadBalancer.InternalIP, nil
+
+ // Explicit fixed IP in the cluster spec
+ case openStackCluster.Spec.APIServerFixedIP != "":
+ return openStackCluster.Spec.APIServerFixedIP, nil
- listener, err := s.getOrCreateListener(openStackCluster, lbPortObjectsName, lb.ID, port)
+ // If we are using the VIP as the control plane endpoint, use any value explicitly set on the control plane endpoint
+ case openStackCluster.Spec.DisableAPIServerFloatingIP && openStackCluster.Spec.ControlPlaneEndpoint.IsValid():
+ fixedIPAddress, err := lookupHost(openStackCluster.Spec.ControlPlaneEndpoint.Host)
if err != nil {
- return false, err
+ return "", fmt.Errorf("lookup host: %w", err)
}
+ return fixedIPAddress, nil
+ }
+
+ return "", nil
+}
+
+// getAPIServerFloatingIP gets the floating IP from wherever it is specified.
+// Returns an empty string if the floating IP is not specified and it should be allocated automatically.
+func getAPIServerFloatingIP(openStackCluster *infrav1.OpenStackCluster) (string, error) {
+ switch {
+ // The floating IP was created previously
+ case openStackCluster.Status.APIServerLoadBalancer != nil && openStackCluster.Status.APIServerLoadBalancer.IP != "":
+ return openStackCluster.Status.APIServerLoadBalancer.IP, nil
- pool, err := s.getOrCreatePool(openStackCluster, lbPortObjectsName, listener.ID, lb.ID, lb.Provider)
+ // Explicit floating IP in the cluster spec
+ case openStackCluster.Spec.APIServerFloatingIP != "":
+ return openStackCluster.Spec.APIServerFloatingIP, nil
+
+ // An IP address is specified explicitly in the control plane endpoint
+ case openStackCluster.Spec.ControlPlaneEndpoint.IsValid():
+ floatingIPAddress, err := lookupHost(openStackCluster.Spec.ControlPlaneEndpoint.Host)
if err != nil {
- return false, err
+ return "", fmt.Errorf("lookup host: %w", err)
}
+ return floatingIPAddress, nil
+ }
- if err := s.getOrCreateMonitor(openStackCluster, lbPortObjectsName, pool.ID, lb.ID); err != nil {
- return false, err
+ return "", nil
+}
+
+// getCanonicalAllowedCIDRs gets a filtered list of CIDRs which should be allowed to access the API server loadbalancer.
+// Invalid CIDRs are filtered from the list and emil a warning event.
+// It returns a canonical representation that can be directly compared with other canonicalized lists.
+func getCanonicalAllowedCIDRs(openStackCluster *infrav1.OpenStackCluster) []string {
+ allowedCIDRs := []string{}
+
+ if len(openStackCluster.Spec.APIServerLoadBalancer.AllowedCIDRs) > 0 {
+ allowedCIDRs = append(allowedCIDRs, openStackCluster.Spec.APIServerLoadBalancer.AllowedCIDRs...)
+
+ // In the first reconciliation loop, only the Ready field is set in openStackCluster.Status
+ // All other fields are empty/nil
+ if openStackCluster.Status.Bastion != nil {
+ if openStackCluster.Status.Bastion.FloatingIP != "" {
+ allowedCIDRs = append(allowedCIDRs, openStackCluster.Status.Bastion.FloatingIP)
+ }
+
+ if openStackCluster.Status.Bastion.IP != "" {
+ allowedCIDRs = append(allowedCIDRs, openStackCluster.Status.Bastion.IP)
+ }
}
- if allowedCIDRsSupported {
- // Skip reconciliation if network status is nil (e.g. during clusterctl move)
- if openStackCluster.Status.Network != nil {
- if err := s.getOrUpdateAllowedCIDRS(openStackCluster, listener); err != nil {
- return false, err
+ if openStackCluster.Status.Network != nil {
+ for _, subnet := range openStackCluster.Status.Network.Subnets {
+ if subnet.CIDR != "" {
+ allowedCIDRs = append(allowedCIDRs, subnet.CIDR)
}
- allowedCIDRs = listener.AllowedCIDRs
+ }
+
+ if openStackCluster.Status.Router != nil && len(openStackCluster.Status.Router.IPs) > 0 {
+ allowedCIDRs = append(allowedCIDRs, openStackCluster.Status.Router.IPs...)
}
}
}
- lbStatus.AllowedCIDRs = allowedCIDRs
- return false, nil
+ // Filter invalid CIDRs and convert any IPs into CIDRs.
+ validCIDRs := []string{}
+ for _, v := range allowedCIDRs {
+ switch {
+ case utilsnet.IsIPv4String(v):
+ validCIDRs = append(validCIDRs, v+"/32")
+ case utilsnet.IsIPv4CIDRString(v):
+ validCIDRs = append(validCIDRs, v)
+ default:
+ record.Warnf(openStackCluster, "FailedIPAddressValidation", "%s is not a valid IPv4 nor CIDR address and will not get applied to allowed_cidrs", v)
+ }
+ }
+
+ // Sort and remove duplicates
+ return capostrings.Canonicalize(validCIDRs)
+}
+
+// isAllowsCIDRSSupported returns true if Octavia supports allowed CIDRs for the loadbalancer provider in use.
+func (s *Service) isAllowsCIDRSSupported(lb *loadbalancers.LoadBalancer) (bool, error) {
+ octaviaVersions, err := s.loadbalancerClient.ListOctaviaVersions()
+ if err != nil {
+ return false, err
+ }
+ // The current version is always the last one in the list.
+ octaviaVersion := octaviaVersions[len(octaviaVersions)-1].ID
+
+ return openstackutil.IsOctaviaFeatureSupported(octaviaVersion, openstackutil.OctaviaFeatureVIPACL, lb.Provider), nil
}
-func (s *Service) getOrCreateLoadBalancer(openStackCluster *infrav1.OpenStackCluster, loadBalancerName, subnetID, clusterName, vipAddress, provider string) (*loadbalancers.LoadBalancer, error) {
+// getOrCreateAPILoadBalancer returns an existing API loadbalancer if it already exists, or creates a new one if it does not.
+func (s *Service) getOrCreateAPILoadBalancer(openStackCluster *infrav1.OpenStackCluster, clusterName string) (*loadbalancers.LoadBalancer, error) {
+ loadBalancerName := getLoadBalancerName(clusterName)
lb, err := s.checkIfLbExists(loadBalancerName)
if err != nil {
return nil, err
}
-
if lb != nil {
return lb, nil
}
+ if openStackCluster.Status.Network == nil {
+ return nil, fmt.Errorf("network is not yet available in OpenStackCluster.Status")
+ }
+
+ // Create the VIP on the first cluster subnet
+ subnetID := openStackCluster.Status.Network.Subnets[0].ID
s.scope.Logger().Info("Creating load balancer in subnet", "subnetID", subnetID, "name", loadBalancerName)
+ providers, err := s.loadbalancerClient.ListLoadBalancerProviders()
+ if err != nil {
+ return nil, err
+ }
+
+ // Choose the selected provider if it is set in cluster spec, if not, omit the field and Octavia will use the default provider.
+ lbProvider := ""
+ if openStackCluster.Spec.APIServerLoadBalancer.Provider != "" {
+ for _, v := range providers {
+ if v.Name == openStackCluster.Spec.APIServerLoadBalancer.Provider {
+ lbProvider = v.Name
+ break
+ }
+ }
+ if lbProvider == "" {
+ record.Warnf(openStackCluster, "OctaviaProviderNotFound", "Provider specified for Octavia not found.")
+ record.Eventf(openStackCluster, "OctaviaProviderNotFound", "Provider %s specified for Octavia not found, using the default provider.", openStackCluster.Spec.APIServerLoadBalancer.Provider)
+ }
+ }
+
+ vipAddress, err := getAPIServerVIPAddress(openStackCluster)
+ if err != nil {
+ return nil, err
+ }
+
lbCreateOpts := loadbalancers.CreateOpts{
Name: loadBalancerName,
VipSubnetID: subnetID,
VipAddress: vipAddress,
Description: names.GetDescription(clusterName),
- Provider: provider,
+ Provider: lbProvider,
Tags: openStackCluster.Spec.Tags,
}
lb, err = s.loadbalancerClient.CreateLoadBalancer(lbCreateOpts)
@@ -230,7 +311,45 @@ func (s *Service) getOrCreateLoadBalancer(openStackCluster *infrav1.OpenStackClu
return lb, nil
}
-func (s *Service) getOrCreateListener(openStackCluster *infrav1.OpenStackCluster, listenerName, lbID string, port int) (*listeners.Listener, error) {
+// reconcileAPILoadBalancerListener ensures that the listener on the given port exists and is configured correctly.
+func (s *Service) reconcileAPILoadBalancerListener(lb *loadbalancers.LoadBalancer, openStackCluster *infrav1.OpenStackCluster, clusterName string, port int) error {
+ loadBalancerName := getLoadBalancerName(clusterName)
+ lbPortObjectsName := fmt.Sprintf("%s-%d", loadBalancerName, port)
+
+ if openStackCluster.Status.APIServerLoadBalancer == nil {
+ return fmt.Errorf("APIServerLoadBalancer is not yet available in OpenStackCluster.Status")
+ }
+
+ allowedCIDRs := openStackCluster.Status.APIServerLoadBalancer.AllowedCIDRs
+
+ listener, err := s.getOrCreateListener(openStackCluster, lbPortObjectsName, lb.ID, allowedCIDRs, port)
+ if err != nil {
+ return err
+ }
+
+ pool, err := s.getOrCreatePool(openStackCluster, lbPortObjectsName, listener.ID, lb.ID, lb.Provider)
+ if err != nil {
+ return err
+ }
+
+ if err := s.getOrCreateMonitor(openStackCluster, lbPortObjectsName, pool.ID, lb.ID); err != nil {
+ return err
+ }
+
+ // allowedCIDRs is nil if allowedCIDRs is not supported by the Octavia provider
+ // A non-nil empty slice is an explicitly empty list
+ if allowedCIDRs != nil {
+ if err := s.getOrUpdateAllowedCIDRs(openStackCluster, listener, allowedCIDRs); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+// getOrCreateListener returns an existing listener for the given loadbalancer
+// and port if it already exists, or creates a new one if it does not.
+func (s *Service) getOrCreateListener(openStackCluster *infrav1.OpenStackCluster, listenerName, lbID string, allowedCIDRs []string, port int) (*listeners.Listener, error) {
listener, err := s.checkIfListenerExists(listenerName)
if err != nil {
return nil, err
@@ -248,6 +367,7 @@ func (s *Service) getOrCreateListener(openStackCluster *infrav1.OpenStackCluster
ProtocolPort: port,
LoadbalancerID: lbID,
Tags: openStackCluster.Spec.Tags,
+ AllowedCIDRs: allowedCIDRs,
}
listener, err = s.loadbalancerClient.CreateListener(listenerCreateOpts)
if err != nil {
@@ -255,7 +375,7 @@ func (s *Service) getOrCreateListener(openStackCluster *infrav1.OpenStackCluster
return nil, err
}
- if err := s.waitForLoadBalancerActive(lbID); err != nil {
+ if _, err := s.waitForLoadBalancerActive(lbID); err != nil {
record.Warnf(openStackCluster, "FailedCreateListener", "Failed to create listener %s with id %s: wait for load balancer active %s: %v", listenerName, listener.ID, lbID, err)
return nil, err
}
@@ -269,42 +389,9 @@ func (s *Service) getOrCreateListener(openStackCluster *infrav1.OpenStackCluster
return listener, nil
}
-func (s *Service) getOrUpdateAllowedCIDRS(openStackCluster *infrav1.OpenStackCluster, listener *listeners.Listener) error {
- allowedCIDRs := []string{}
-
- if len(openStackCluster.Spec.APIServerLoadBalancer.AllowedCIDRs) > 0 {
- allowedCIDRs = append(allowedCIDRs, openStackCluster.Spec.APIServerLoadBalancer.AllowedCIDRs...)
-
- // In the first reconciliation loop, only the Ready field is set in openStackCluster.Status
- // All other fields are empty/nil
- if openStackCluster.Status.Bastion != nil {
- if openStackCluster.Status.Bastion.FloatingIP != "" {
- allowedCIDRs = append(allowedCIDRs, openStackCluster.Status.Bastion.FloatingIP)
- }
-
- if openStackCluster.Status.Bastion.IP != "" {
- allowedCIDRs = append(allowedCIDRs, openStackCluster.Status.Bastion.IP)
- }
- }
-
- if openStackCluster.Status.Network != nil {
- for _, subnet := range openStackCluster.Status.Network.Subnets {
- if subnet.CIDR != "" {
- allowedCIDRs = append(allowedCIDRs, subnet.CIDR)
- }
- }
-
- if len(openStackCluster.Status.Router.IPs) > 0 {
- allowedCIDRs = append(allowedCIDRs, openStackCluster.Status.Router.IPs...)
- }
- }
- }
-
- // Validate CIDRs and convert any given IP into a CIDR.
- allowedCIDRs = validateIPs(openStackCluster, allowedCIDRs)
-
+// getOrUpdateAllowedCIDRs ensures that the allowed CIDRs configured on a listener correspond to the expected list.
+func (s *Service) getOrUpdateAllowedCIDRs(openStackCluster *infrav1.OpenStackCluster, listener *listeners.Listener, allowedCIDRs []string) error {
// Sort and remove duplicates
- allowedCIDRs = capostrings.Canonicalize(allowedCIDRs)
listener.AllowedCIDRs = capostrings.Canonicalize(listener.AllowedCIDRs)
if !slices.Equal(allowedCIDRs, listener.AllowedCIDRs) {
@@ -330,24 +417,6 @@ func (s *Service) getOrUpdateAllowedCIDRS(openStackCluster *infrav1.OpenStackClu
return nil
}
-// validateIPs validates given IPs/CIDRs and removes non valid network objects.
-func validateIPs(openStackCluster *infrav1.OpenStackCluster, definedCIDRs []string) []string {
- marshaledCIDRs := []string{}
-
- for _, v := range definedCIDRs {
- switch {
- case utilsnet.IsIPv4String(v):
- marshaledCIDRs = append(marshaledCIDRs, v+"/32")
- case utilsnet.IsIPv4CIDRString(v):
- marshaledCIDRs = append(marshaledCIDRs, v)
- default:
- record.Warnf(openStackCluster, "FailedIPAddressValidation", "%s is not a valid IPv4 nor CIDR address and will not get applied to allowed_cidrs", v)
- }
- }
-
- return marshaledCIDRs
-}
-
func (s *Service) getOrCreatePool(openStackCluster *infrav1.OpenStackCluster, poolName, listenerID, lbID string, lbProvider string) (*pools.Pool, error) {
pool, err := s.checkIfPoolExists(poolName)
if err != nil {
@@ -379,7 +448,7 @@ func (s *Service) getOrCreatePool(openStackCluster *infrav1.OpenStackCluster, po
return nil, err
}
- if err := s.waitForLoadBalancerActive(lbID); err != nil {
+ if _, err := s.waitForLoadBalancerActive(lbID); err != nil {
record.Warnf(openStackCluster, "FailedCreatePool", "Failed to create pool %s with id %s: wait for load balancer active %s: %v", poolName, pool.ID, lbID, err)
return nil, err
}
@@ -421,7 +490,7 @@ func (s *Service) getOrCreateMonitor(openStackCluster *infrav1.OpenStackCluster,
return err
}
- if err = s.waitForLoadBalancerActive(lbID); err != nil {
+ if _, err = s.waitForLoadBalancerActive(lbID); err != nil {
record.Warnf(openStackCluster, "FailedCreateMonitor", "Failed to create monitor %s with id %s: wait for load balancer active %s: %v", monitorName, monitor.ID, lbID, err)
return err
}
@@ -474,14 +543,14 @@ func (s *Service) ReconcileLoadBalancerMember(openStackCluster *infrav1.OpenStac
s.scope.Logger().Info("Deleting load balancer member because the IP of the machine changed", "name", name)
// lb member changed so let's delete it so we can create it again with the correct IP
- err = s.waitForLoadBalancerActive(lbID)
+ _, err = s.waitForLoadBalancerActive(lbID)
if err != nil {
return err
}
if err := s.loadbalancerClient.DeletePoolMember(pool.ID, lbMember.ID); err != nil {
return err
}
- err = s.waitForLoadBalancerActive(lbID)
+ _, err = s.waitForLoadBalancerActive(lbID)
if err != nil {
return err
}
@@ -497,7 +566,7 @@ func (s *Service) ReconcileLoadBalancerMember(openStackCluster *infrav1.OpenStac
Tags: openStackCluster.Spec.Tags,
}
- if err := s.waitForLoadBalancerActive(lbID); err != nil {
+ if _, err := s.waitForLoadBalancerActive(lbID); err != nil {
return err
}
@@ -505,7 +574,7 @@ func (s *Service) ReconcileLoadBalancerMember(openStackCluster *infrav1.OpenStac
return err
}
- if err := s.waitForLoadBalancerActive(lbID); err != nil {
+ if _, err := s.waitForLoadBalancerActive(lbID); err != nil {
return err
}
}
@@ -598,14 +667,14 @@ func (s *Service) DeleteLoadBalancerMember(openStackCluster *infrav1.OpenStackCl
if lbMember != nil {
// lb member changed so let's delete it so we can create it again with the correct IP
- err = s.waitForLoadBalancerActive(lbID)
+ _, err = s.waitForLoadBalancerActive(lbID)
if err != nil {
return err
}
if err := s.loadbalancerClient.DeletePoolMember(pool.ID, lbMember.ID); err != nil {
return err
}
- err = s.waitForLoadBalancerActive(lbID)
+ _, err = s.waitForLoadBalancerActive(lbID)
if err != nil {
return err
}
@@ -681,15 +750,22 @@ var backoff = wait.Backoff{
}
// Possible LoadBalancer states are documented here: https://docs.openstack.org/api-ref/load-balancer/v2/index.html#prov-status
-func (s *Service) waitForLoadBalancerActive(id string) error {
+func (s *Service) waitForLoadBalancerActive(id string) (*loadbalancers.LoadBalancer, error) {
+ var lb *loadbalancers.LoadBalancer
+
s.scope.Logger().Info("Waiting for load balancer", "id", id, "targetStatus", "ACTIVE")
- return wait.ExponentialBackoff(backoff, func() (bool, error) {
- lb, err := s.loadbalancerClient.GetLoadBalancer(id)
+ err := wait.ExponentialBackoff(backoff, func() (bool, error) {
+ var err error
+ lb, err = s.loadbalancerClient.GetLoadBalancer(id)
if err != nil {
return false, err
}
return lb.ProvisioningStatus == loadBalancerProvisioningStatusActive, nil
})
+ if err != nil {
+ return nil, err
+ }
+ return lb, nil
}
func (s *Service) waitForListener(id, target string) error {
diff --git a/pkg/cloud/services/loadbalancer/loadbalancer_test.go b/pkg/cloud/services/loadbalancer/loadbalancer_test.go
index d4a6b69a09..0c9996ca0f 100644
--- a/pkg/cloud/services/loadbalancer/loadbalancer_test.go
+++ b/pkg/cloud/services/loadbalancer/loadbalancer_test.go
@@ -18,6 +18,7 @@ package loadbalancer
import (
"errors"
+ "fmt"
"net"
"testing"
@@ -37,6 +38,8 @@ import (
"sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
)
+const apiHostname = "api.test-cluster.test"
+
func Test_ReconcileLoadBalancer(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
@@ -45,7 +48,7 @@ func Test_ReconcileLoadBalancer(t *testing.T) {
lookupHost = func(host string) (addrs string, err error) {
if net.ParseIP(host) != nil {
return host, nil
- } else if host == "api.test-cluster.test" {
+ } else if host == apiHostname {
ips := []string{"192.168.100.10"}
return ips[0], nil
}
@@ -56,7 +59,7 @@ func Test_ReconcileLoadBalancer(t *testing.T) {
Spec: infrav1.OpenStackClusterSpec{
DisableAPIServerFloatingIP: true,
ControlPlaneEndpoint: clusterv1.APIEndpoint{
- Host: "api.test-cluster.test",
+ Host: apiHostname,
Port: 6443,
},
},
@@ -83,13 +86,6 @@ func Test_ReconcileLoadBalancer(t *testing.T) {
// add network api call results here
},
expectLoadBalancer: func(m *mock.MockLbClientMockRecorder) {
- // return loadbalancer providers
- providers := []providers.Provider{
- {Name: "amphora", Description: "The Octavia Amphora driver."},
- {Name: "octavia", Description: "Deprecated alias of the Octavia Amphora driver."},
- }
- m.ListLoadBalancerProviders().Return(providers, nil)
-
pendingLB := loadbalancers.LoadBalancer{
ID: "aaaaaaaa-bbbb-cccc-dddd-333333333333",
Name: "k8s-clusterapi-cluster-AAAAA-kubeapi",
@@ -159,3 +155,349 @@ func Test_ReconcileLoadBalancer(t *testing.T) {
})
}
}
+
+func Test_getAPIServerVIPAddress(t *testing.T) {
+ // Stub the call to net.LookupHost
+ lookupHost = func(host string) (addrs string, err error) {
+ if net.ParseIP(host) != nil {
+ return host, nil
+ } else if host == apiHostname {
+ ips := []string{"192.168.100.10"}
+ return ips[0], nil
+ }
+ return "", errors.New("Unknown Host " + host)
+ }
+ tests := []struct {
+ name string
+ openStackCluster *infrav1.OpenStackCluster
+ want string
+ wantError bool
+ }{
+ {
+ name: "empty cluster returns empty VIP",
+ openStackCluster: &infrav1.OpenStackCluster{},
+ want: "",
+ wantError: false,
+ },
+ {
+ name: "API server VIP is InternalIP",
+ openStackCluster: &infrav1.OpenStackCluster{
+ Status: infrav1.OpenStackClusterStatus{
+ APIServerLoadBalancer: &infrav1.LoadBalancer{
+ InternalIP: "1.2.3.4",
+ },
+ },
+ },
+ want: "1.2.3.4",
+ wantError: false,
+ },
+ {
+ name: "API server VIP is API Server Fixed IP",
+ openStackCluster: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ APIServerFixedIP: "1.2.3.4",
+ },
+ },
+ want: "1.2.3.4",
+ wantError: false,
+ },
+ {
+ name: "API server VIP with valid control plane endpoint",
+ openStackCluster: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ DisableAPIServerFloatingIP: true,
+ ControlPlaneEndpoint: clusterv1.APIEndpoint{
+ Host: apiHostname,
+ Port: 6443,
+ },
+ },
+ },
+ want: "192.168.100.10",
+ wantError: false,
+ },
+ {
+ name: "API server VIP with invalid control plane endpoint",
+ openStackCluster: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ DisableAPIServerFloatingIP: true,
+ ControlPlaneEndpoint: clusterv1.APIEndpoint{
+ Host: "invalid-api.test-cluster.test",
+ Port: 6443,
+ },
+ },
+ },
+ wantError: true,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ g := NewWithT(t)
+
+ got, err := getAPIServerVIPAddress(tt.openStackCluster)
+ if tt.wantError {
+ g.Expect(err).To(HaveOccurred())
+ } else {
+ g.Expect(err).NotTo(HaveOccurred())
+ g.Expect(got).To(Equal(tt.want))
+ }
+ })
+ }
+}
+
+func Test_getAPIServerFloatingIP(t *testing.T) {
+ // Stub the call to net.LookupHost
+ lookupHost = func(host string) (addrs string, err error) {
+ if net.ParseIP(host) != nil {
+ return host, nil
+ } else if host == apiHostname {
+ ips := []string{"192.168.100.10"}
+ return ips[0], nil
+ }
+ return "", errors.New("Unknown Host " + host)
+ }
+ tests := []struct {
+ name string
+ openStackCluster *infrav1.OpenStackCluster
+ want string
+ wantError bool
+ }{
+ {
+ name: "empty cluster returns empty FIP",
+ openStackCluster: &infrav1.OpenStackCluster{},
+ want: "",
+ wantError: false,
+ },
+ {
+ name: "API server FIP is API Server LB IP",
+ openStackCluster: &infrav1.OpenStackCluster{
+ Status: infrav1.OpenStackClusterStatus{
+ APIServerLoadBalancer: &infrav1.LoadBalancer{
+ IP: "1.2.3.4",
+ },
+ },
+ },
+ want: "1.2.3.4",
+ wantError: false,
+ },
+ {
+ name: "API server FIP is API Server Floating IP",
+ openStackCluster: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ APIServerFloatingIP: "1.2.3.4",
+ },
+ },
+ want: "1.2.3.4",
+ wantError: false,
+ },
+ {
+ name: "API server FIP with valid control plane endpoint",
+ openStackCluster: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ ControlPlaneEndpoint: clusterv1.APIEndpoint{
+ Host: apiHostname,
+ Port: 6443,
+ },
+ },
+ },
+ want: "192.168.100.10",
+ wantError: false,
+ },
+ {
+ name: "API server FIP with invalid control plane endpoint",
+ openStackCluster: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ ControlPlaneEndpoint: clusterv1.APIEndpoint{
+ Host: "invalid-api.test-cluster.test",
+ Port: 6443,
+ },
+ },
+ },
+ wantError: true,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ g := NewWithT(t)
+
+ got, err := getAPIServerFloatingIP(tt.openStackCluster)
+ if tt.wantError {
+ g.Expect(err).To(HaveOccurred())
+ } else {
+ g.Expect(err).NotTo(HaveOccurred())
+ g.Expect(got).To(Equal(tt.want))
+ }
+ })
+ }
+}
+
+func Test_getCanonicalAllowedCIDRs(t *testing.T) {
+ tests := []struct {
+ name string
+ openStackCluster *infrav1.OpenStackCluster
+ want []string
+ }{
+ {
+ name: "allowed CIDRs are empty",
+ openStackCluster: &infrav1.OpenStackCluster{},
+ want: []string{},
+ },
+ {
+ name: "allowed CIDRs are set",
+ openStackCluster: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ APIServerLoadBalancer: infrav1.APIServerLoadBalancer{
+ AllowedCIDRs: []string{"1.2.3.4/32"},
+ },
+ },
+ },
+ want: []string{"1.2.3.4/32"},
+ },
+ {
+ name: "allowed CIDRs are set with bastion",
+ openStackCluster: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ APIServerLoadBalancer: infrav1.APIServerLoadBalancer{
+ AllowedCIDRs: []string{"1.2.3.4/32"},
+ },
+ },
+ Status: infrav1.OpenStackClusterStatus{
+ Bastion: &infrav1.BastionStatus{
+ FloatingIP: "1.2.3.5",
+ IP: "192.168.0.1",
+ },
+ },
+ },
+ want: []string{"1.2.3.4/32", "1.2.3.5/32", "192.168.0.1/32"},
+ },
+ {
+ name: "allowed CIDRs are set with network status",
+ openStackCluster: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ APIServerLoadBalancer: infrav1.APIServerLoadBalancer{
+ AllowedCIDRs: []string{"1.2.3.4/32"},
+ },
+ },
+ Status: infrav1.OpenStackClusterStatus{
+ Network: &infrav1.NetworkStatusWithSubnets{
+ Subnets: []infrav1.Subnet{
+ {
+ CIDR: "192.168.0.0/24",
+ },
+ },
+ },
+ },
+ },
+ want: []string{"1.2.3.4/32", "192.168.0.0/24"},
+ },
+ {
+ name: "allowed CIDRs are set with network status and router IP",
+ openStackCluster: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ APIServerLoadBalancer: infrav1.APIServerLoadBalancer{
+ AllowedCIDRs: []string{"1.2.3.4/32"},
+ },
+ },
+ Status: infrav1.OpenStackClusterStatus{
+ Network: &infrav1.NetworkStatusWithSubnets{
+ Subnets: []infrav1.Subnet{
+ {
+ CIDR: "192.168.0.0/24",
+ },
+ },
+ },
+ Router: &infrav1.Router{
+ IPs: []string{"1.2.3.5"},
+ },
+ },
+ },
+ want: []string{"1.2.3.4/32", "1.2.3.5/32", "192.168.0.0/24"},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ g := NewWithT(t)
+
+ got := getCanonicalAllowedCIDRs(tt.openStackCluster)
+ g.Expect(got).To(Equal(tt.want))
+ })
+ }
+}
+
+func Test_getOrCreateAPILoadBalancer(t *testing.T) {
+ mockCtrl := gomock.NewController(t)
+ defer mockCtrl.Finish()
+
+ octaviaProviders := []providers.Provider{
+ {
+ Name: "ovn",
+ },
+ }
+ lbtests := []struct {
+ name string
+ openStackCluster *infrav1.OpenStackCluster
+ expectLoadBalancer func(m *mock.MockLbClientMockRecorder)
+ want *loadbalancers.LoadBalancer
+ wantError error
+ }{
+ {
+ name: "nothing exists",
+ openStackCluster: &infrav1.OpenStackCluster{},
+ expectLoadBalancer: func(m *mock.MockLbClientMockRecorder) {
+ m.ListLoadBalancers(gomock.Any()).Return([]loadbalancers.LoadBalancer{}, nil)
+ },
+ want: &loadbalancers.LoadBalancer{},
+ wantError: fmt.Errorf("network is not yet available in OpenStackCluster.Status"),
+ },
+ {
+ name: "loadbalancer already exists",
+ openStackCluster: &infrav1.OpenStackCluster{},
+ expectLoadBalancer: func(m *mock.MockLbClientMockRecorder) {
+ m.ListLoadBalancers(gomock.Any()).Return([]loadbalancers.LoadBalancer{{ID: "AAAAA"}}, nil)
+ },
+ want: &loadbalancers.LoadBalancer{
+ ID: "AAAAA",
+ },
+ },
+ {
+ name: "loadbalancer created",
+ openStackCluster: &infrav1.OpenStackCluster{
+ Status: infrav1.OpenStackClusterStatus{
+ Network: &infrav1.NetworkStatusWithSubnets{
+ Subnets: []infrav1.Subnet{
+ {ID: "aaaaaaaa-bbbb-cccc-dddd-222222222222"},
+ {ID: "aaaaaaaa-bbbb-cccc-dddd-333333333333"},
+ },
+ },
+ },
+ },
+ expectLoadBalancer: func(m *mock.MockLbClientMockRecorder) {
+ m.ListLoadBalancers(gomock.Any()).Return([]loadbalancers.LoadBalancer{}, nil)
+ m.ListLoadBalancerProviders().Return(octaviaProviders, nil)
+ m.CreateLoadBalancer(gomock.Any()).Return(&loadbalancers.LoadBalancer{
+ ID: "AAAAA",
+ }, nil)
+ },
+ want: &loadbalancers.LoadBalancer{
+ ID: "AAAAA",
+ },
+ },
+ }
+ for _, tt := range lbtests {
+ t.Run(tt.name, func(t *testing.T) {
+ g := NewWithT(t)
+
+ mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "", logr.Discard())
+ lbs, err := NewService(mockScopeFactory)
+ g.Expect(err).NotTo(HaveOccurred())
+
+ tt.expectLoadBalancer(mockScopeFactory.LbClient.EXPECT())
+ lb, err := lbs.getOrCreateAPILoadBalancer(tt.openStackCluster, "AAAAA")
+ if tt.wantError != nil {
+ g.Expect(err).To(MatchError(tt.wantError))
+ } else {
+ g.Expect(err).NotTo(HaveOccurred())
+ g.Expect(lb).To(Equal(tt.want))
+ }
+ })
+ }
+}
From 268645a3bee5e88344c78c6965db8f7b099773b9 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Mon, 26 Feb 2024 14:05:17 +0000
Subject: [PATCH 084/180] Reduce cyclomatic complexity of
reconcileNetworkComponents
This change refactors reconcileNetworkComponents into several smaller
logical functions which are easier to read and reason about.
It also makes the gocyclo linter happy when making new changes to this
code.
Co-Authored-By: Emilien Macchi
---
controllers/openstackcluster_controller.go | 299 ++++++++++--------
.../openstackcluster_controller_test.go | 48 ++-
2 files changed, 205 insertions(+), 142 deletions(-)
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index 3abcad6cdc..6fe81d5220 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -602,81 +602,123 @@ func reconcileNetworkComponents(scope *scope.WithLogger, cluster *clusterv1.Clus
}
if len(openStackCluster.Spec.ManagedSubnets) == 0 {
- 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{}
- }
-
- err := getCAPONetwork(openStackCluster, networkingService)
- if err != nil {
+ if err := reconcilePreExistingNetworkComponents(scope, networkingService, openStackCluster); err != nil {
return err
}
-
- filteredSubnets, err := filterSubnets(networkingService, openStackCluster)
- if err != nil {
+ } else if len(openStackCluster.Spec.ManagedSubnets) == 1 {
+ if err := reconcileProvisionedNetworkComponents(networkingService, openStackCluster, clusterName); err != nil {
return err
}
+ } else {
+ return fmt.Errorf("failed to reconcile network: ManagedSubnets only supports one element, %d provided", len(openStackCluster.Spec.ManagedSubnets))
+ }
- var subnets []infrav1.Subnet
- for subnet := range filteredSubnets {
- filterSubnet := &filteredSubnets[subnet]
- subnets = append(subnets, infrav1.Subnet{
- ID: filterSubnet.ID,
- Name: filterSubnet.Name,
- CIDR: filterSubnet.CIDR,
- Tags: filterSubnet.Tags,
- })
- }
+ err = networkingService.ReconcileSecurityGroups(openStackCluster, clusterName)
+ if err != nil {
+ handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to reconcile security groups: %w", err))
+ return fmt.Errorf("failed to reconcile security groups: %w", err)
+ }
- if err := utils.ValidateSubnets(subnets); err != nil {
- return err
- }
- openStackCluster.Status.Network.Subnets = subnets
+ return reconcileControlPlaneEndpoint(scope, networkingService, openStackCluster, clusterName)
+}
- // If network is not yet populated on the Status, use networkID defined in the filtered subnets to get the Network.
- err = populateCAPONetworkFromSubnet(networkingService, filteredSubnets, openStackCluster)
+// 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{}
+ }
+
+ emptyNetwork := infrav1.NetworkFilter{}
+ if openStackCluster.Spec.Network != emptyNetwork {
+ netOpts := openStackCluster.Spec.Network.ToListOpt()
+ networkList, err := networkingService.GetNetworksByFilter(&netOpts)
if err != nil {
- return err
+ handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to find network: %w", err))
+ return fmt.Errorf("error fetching networks: %w", err)
}
- } else if len(openStackCluster.Spec.ManagedSubnets) == 1 {
- err := networkingService.ReconcileNetwork(openStackCluster, clusterName)
- if err != nil {
- handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to reconcile network: %w", err))
- return fmt.Errorf("failed to reconcile network: %w", err)
+ if len(networkList) == 0 {
+ handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to find any network"))
+ return fmt.Errorf("failed to find any network")
}
- 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)
+ if len(networkList) == 1 {
+ setClusterNetwork(openStackCluster, &networkList[0])
+ }
+ }
+
+ 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
}
- } else {
- return fmt.Errorf("failed to reconcile network: ManagedSubnets only supports one element, %d provided", len(openStackCluster.Spec.ManagedSubnets))
+ setClusterNetwork(openStackCluster, network)
}
- err = networkingService.ReconcileSecurityGroups(openStackCluster, clusterName)
+ return nil
+}
+
+func reconcileProvisionedNetworkComponents(networkingService *networking.Service, openStackCluster *infrav1.OpenStackCluster, clusterName string) error {
+ err := networkingService.ReconcileNetwork(openStackCluster, clusterName)
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, clusterName)
+ 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, clusterName)
+ 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, clusterName 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)
- if openStackCluster.Spec.APIServerLoadBalancer.Enabled {
+ // host must be set by a matching control plane endpoint provider below
+ var host string
+
+ 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.Enabled:
loadBalancerService, err := loadbalancer.NewService(scope)
if err != nil {
return err
@@ -690,49 +732,63 @@ func reconcileNetworkComponents(scope *scope.WithLogger, cluster *clusterv1.Clus
}
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.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 !openStackCluster.Spec.DisableAPIServerFloatingIP:
+ 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
+
+ // 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 != "":
+ 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.IsValid():
+ return int(openStackCluster.Spec.ControlPlaneEndpoint.Port)
+ case openStackCluster.Spec.APIServerPort != 0:
+ 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)
@@ -788,9 +844,9 @@ func handleUpdateOSCError(openstackCluster *infrav1.OpenStackCluster, message er
openstackCluster.Status.FailureMessage = pointer.String(message.Error())
}
-// filterSubnets retrieves the subnets based on the Subnet filters specified on OpenstackCluster.
-func filterSubnets(networkingService *networking.Service, openStackCluster *infrav1.OpenStackCluster) ([]subnets.Subnet, error) {
- var filteredSubnets []subnets.Subnet
+// 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 := ""
@@ -800,12 +856,14 @@ func filterSubnets(networkingService *networking.Service, openStackCluster *infr
if len(openStackClusterSubnets) == 0 {
if networkID == "" {
- return nil, nil
+ // This should be a validation error
+ return nil, fmt.Errorf("no network or subnets specified in OpenStackCluster spec")
}
+
empty := &infrav1.SubnetFilter{}
listOpt := empty.ToListOpt()
listOpt.NetworkID = networkID
- filteredSubnets, err = networkingService.GetSubnetsByFilter(listOpt)
+ clusterSubnets, err = networkingService.GetSubnetsByFilter(listOpt)
if err != nil {
err = fmt.Errorf("failed to find subnets: %w", err)
if errors.Is(err, networking.ErrFilterMatch) {
@@ -813,7 +871,7 @@ func filterSubnets(networkingService *networking.Service, openStackCluster *infr
}
return nil, err
}
- if len(filteredSubnets) > 2 {
+ 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 {
@@ -826,55 +884,18 @@ func filterSubnets(networkingService *networking.Service, openStackCluster *infr
}
return nil, err
}
- filteredSubnets = append(filteredSubnets, *filteredSubnet)
+ clusterSubnets = append(clusterSubnets, *filteredSubnet)
+
+ // Constrain the next search to the network of the first subnet
+ networkID = filteredSubnet.NetworkID
}
}
- return filteredSubnets, nil
+ return clusterSubnets, nil
}
-// convertOpenStackNetworkToCAPONetwork converts an OpenStack network to a capo network.
-// It returns the converted subnet.
-func convertOpenStackNetworkToCAPONetwork(openStackCluster *infrav1.OpenStackCluster, network *networks.Network) {
+// 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
}
-
-// populateCAPONetworkFromSubnet gets a network based on the networkID of the subnets and converts it to the CAPO format.
-// It returns an error in case it failed to retrieve the network.
-func populateCAPONetworkFromSubnet(networkingService *networking.Service, subnets []subnets.Subnet, openStackCluster *infrav1.OpenStackCluster) error {
- if openStackCluster.Status.Network.ID == "" && len(subnets) > 0 {
- if len(subnets) > 1 && subnets[0].NetworkID != subnets[1].NetworkID {
- return fmt.Errorf("unable to identify the network to use. NetworkID %s from subnet %s does not match NetworkID %s from subnet %s", subnets[0].NetworkID, subnets[0].ID, subnets[1].NetworkID, subnets[1].ID)
- }
-
- network, err := networkingService.GetNetworkByID(subnets[0].NetworkID)
- if err != nil {
- return err
- }
- convertOpenStackNetworkToCAPONetwork(openStackCluster, network)
- }
- return nil
-}
-
-// getCAPONetwork gets a network based on a filter, if defined, and convert the network to the CAPO format.
-// It returns an error in case it failed to retrieve the network.
-func getCAPONetwork(openStackCluster *infrav1.OpenStackCluster, networkingService *networking.Service) error {
- emptyNetwork := infrav1.NetworkFilter{}
- if openStackCluster.Spec.Network != emptyNetwork {
- 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 {
- convertOpenStackNetworkToCAPONetwork(openStackCluster, &networkList[0])
- }
- }
- return nil
-}
diff --git a/controllers/openstackcluster_controller_test.go b/controllers/openstackcluster_controller_test.go
index 4a19d65f7a..971d0308d2 100644
--- a/controllers/openstackcluster_controller_test.go
+++ b/controllers/openstackcluster_controller_test.go
@@ -725,7 +725,7 @@ func createRequestFromOSCluster(openStackCluster *infrav1.OpenStackCluster) reco
}
}
-func Test_ConvertOpenStackNetworkToCAPONetwork(t *testing.T) {
+func Test_setClusterNetwork(t *testing.T) {
openStackCluster := &infrav1.OpenStackCluster{}
openStackCluster.Status.Network = &infrav1.NetworkStatusWithSubnets{}
@@ -735,7 +735,7 @@ func Test_ConvertOpenStackNetworkToCAPONetwork(t *testing.T) {
Tags: []string{"tag1", "tag2"},
}
- convertOpenStackNetworkToCAPONetwork(openStackCluster, filterednetwork)
+ setClusterNetwork(openStackCluster, filterednetwork)
expected := infrav1.NetworkStatus{
ID: "network1",
Name: "network1",
@@ -743,7 +743,49 @@ func Test_ConvertOpenStackNetworkToCAPONetwork(t *testing.T) {
}
if !reflect.DeepEqual(openStackCluster.Status.Network.NetworkStatus, expected) {
- t.Errorf("ConvertOpenStackNetworkToCAPONetwork() = %v, want %v", 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: 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)
+ }
+ })
}
}
From af5545c5b5a8ee2ac75e9388b36a63bf1157a679 Mon Sep 17 00:00:00 2001
From: "alexandre.vilain"
Date: Mon, 2 Oct 2023 14:46:37 +0200
Subject: [PATCH 085/180] Add API reference documentation generation
Signed-off-by: alexandre.vilain
---
.gitignore | 1 +
Makefile | 21 +-
api/v1alpha6/doc.go | 3 +
api/v1alpha6/groupversion_info.go | 3 -
api/v1alpha6/openstackcluster_types.go | 2 +
.../openstackclustertemplate_types.go | 2 +
api/v1alpha6/openstackmachine_types.go | 2 +
.../openstackmachinetemplate_types.go | 2 +
api/v1alpha7/doc.go | 3 +
api/v1alpha7/groupversion_info.go | 3 -
api/v1alpha7/openstackcluster_types.go | 2 +
.../openstackclustertemplate_types.go | 6 +-
api/v1alpha7/openstackmachine_types.go | 2 +
.../openstackmachinetemplate_types.go | 2 +
api/v1beta1/doc.go | 3 +
api/v1beta1/openstackcluster_types.go | 2 +
api/v1beta1/openstackclustertemplate_types.go | 6 +-
api/v1beta1/openstackmachine_types.go | 2 +
api/v1beta1/openstackmachinetemplate_types.go | 2 +
.../gen-crd-api-reference-docs/config.json | 36 +
.../template/members.tpl | 48 +
.../template/pkg.tpl | 37 +
.../template/type.tpl | 81 +
docs/book/src/SUMMARY.md | 4 +
docs/book/src/api/index.md | 1 +
docs/book/src/api/v1alpha6/api.md | 4218 +++++++++++++++
docs/book/src/api/v1alpha7/api.md | 4235 +++++++++++++++
docs/book/src/api/v1beta1/api.md | 4806 +++++++++++++++++
hack/tools/Makefile | 4 +
hack/tools/go.mod | 3 +
hack/tools/go.sum | 8 +
hack/tools/tools.go | 1 +
32 files changed, 13540 insertions(+), 11 deletions(-)
create mode 100644 docs/book/gen-crd-api-reference-docs/config.json
create mode 100644 docs/book/gen-crd-api-reference-docs/template/members.tpl
create mode 100644 docs/book/gen-crd-api-reference-docs/template/pkg.tpl
create mode 100644 docs/book/gen-crd-api-reference-docs/template/type.tpl
create mode 100644 docs/book/src/api/index.md
create mode 100644 docs/book/src/api/v1alpha6/api.md
create mode 100644 docs/book/src/api/v1alpha7/api.md
create mode 100644 docs/book/src/api/v1beta1/api.md
diff --git a/.gitignore b/.gitignore
index 4d4232cea0..039565c86f 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/Makefile b/Makefile
index 26d974652f..172fb11c2e 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
@@ -245,7 +246,7 @@ modules: ## Runs go mod to ensure proper vendoring.
cd $(TOOLS_DIR); go mod tidy
.PHONY: generate
-generate: generate-controller-gen generate-conversion-gen generate-go generate-manifests ## Generate all generated code
+generate: generate-controller-gen generate-conversion-gen generate-go generate-manifests generate-api-docs ## Generate all generated code
.PHONY: generate-go
generate-go: $(MOCKGEN)
@@ -282,6 +283,24 @@ 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: $(GEN_CRD_API_REFERENCE_DOCS) ## Generate api documentation
+ $(GEN_CRD_API_REFERENCE_DOCS) \
+ -api-dir=./api/v1beta1 \
+ -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/v1beta1/api.md
+ $(GEN_CRD_API_REFERENCE_DOCS) \
+ -api-dir=./api/v1alpha7 \
+ -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/v1alpha7/api.md
+ $(GEN_CRD_API_REFERENCE_DOCS) \
+ -api-dir=./api/v1alpha6 \
+ -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/v1alpha6/api.md
+
## --------------------------------------
##@ Docker
## --------------------------------------
diff --git a/api/v1alpha6/doc.go b/api/v1alpha6/doc.go
index 8b8c08cd51..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.
*/
+// 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/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_types.go b/api/v1alpha6/openstackcluster_types.go
index 3d7ba3d13c..e3a0d82a42 100644
--- a/api/v1alpha6/openstackcluster_types.go
+++ b/api/v1alpha6/openstackcluster_types.go
@@ -212,6 +212,8 @@ 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
diff --git a/api/v1alpha6/openstackclustertemplate_types.go b/api/v1alpha6/openstackclustertemplate_types.go
index c76170dd52..8e5115a793 100644
--- a/api/v1alpha6/openstackclustertemplate_types.go
+++ b/api/v1alpha6/openstackclustertemplate_types.go
@@ -30,6 +30,8 @@ type OpenStackClusterTemplateSpec struct {
Template OpenStackClusterTemplateResource `json:"template"`
}
+// +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
diff --git a/api/v1alpha6/openstackmachine_types.go b/api/v1alpha6/openstackmachine_types.go
index 7dc263f099..9048c181ca 100644
--- a/api/v1alpha6/openstackmachine_types.go
+++ b/api/v1alpha6/openstackmachine_types.go
@@ -136,6 +136,8 @@ 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
diff --git a/api/v1alpha6/openstackmachinetemplate_types.go b/api/v1alpha6/openstackmachinetemplate_types.go
index 6dbddaa85e..d1fd2f0895 100644
--- a/api/v1alpha6/openstackmachinetemplate_types.go
+++ b/api/v1alpha6/openstackmachinetemplate_types.go
@@ -25,6 +25,8 @@ 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
diff --git a/api/v1alpha7/doc.go b/api/v1alpha7/doc.go
index 84a3ca41b1..0c61ce4c18 100644
--- a/api/v1alpha7/doc.go
+++ b/api/v1alpha7/doc.go
@@ -14,5 +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/groupversion_info.go b/api/v1alpha7/groupversion_info.go
index bc23eee49e..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 (
diff --git a/api/v1alpha7/openstackcluster_types.go b/api/v1alpha7/openstackcluster_types.go
index e822e02872..ef0ea51702 100644
--- a/api/v1alpha7/openstackcluster_types.go
+++ b/api/v1alpha7/openstackcluster_types.go
@@ -229,6 +229,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:subresource:status
diff --git a/api/v1alpha7/openstackclustertemplate_types.go b/api/v1alpha7/openstackclustertemplate_types.go
index 0c02a154b3..1c9a41b206 100644
--- a/api/v1alpha7/openstackclustertemplate_types.go
+++ b/api/v1alpha7/openstackclustertemplate_types.go
@@ -30,8 +30,10 @@ 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: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/openstackmachine_types.go b/api/v1alpha7/openstackmachine_types.go
index e70075ecff..1cc5378573 100644
--- a/api/v1alpha7/openstackmachine_types.go
+++ b/api/v1alpha7/openstackmachine_types.go
@@ -136,6 +136,8 @@ type OpenStackMachineStatus struct {
Conditions clusterv1.Conditions `json:"conditions,omitempty"`
}
+// +genclient
+// +genclient:Namespaced
// +kubebuilder:object:root=true
// +kubebuilder:resource:path=openstackmachines,scope=Namespaced,categories=cluster-api,shortName=osm
// +kubebuilder:subresource:status
diff --git a/api/v1alpha7/openstackmachinetemplate_types.go b/api/v1alpha7/openstackmachinetemplate_types.go
index 3eeda6ad7a..dc0eb97c07 100644
--- a/api/v1alpha7/openstackmachinetemplate_types.go
+++ b/api/v1alpha7/openstackmachinetemplate_types.go
@@ -25,6 +25,8 @@ type OpenStackMachineTemplateSpec struct {
Template OpenStackMachineTemplateResource `json:"template"`
}
+// +genclient
+// +genclient:Namespaced
// +kubebuilder:object:root=true
// +kubebuilder:resource:path=openstackmachinetemplates,scope=Namespaced,categories=cluster-api,shortName=osmt
diff --git a/api/v1beta1/doc.go b/api/v1beta1/doc.go
index 465e3a377a..4bd2e99487 100644
--- a/api/v1beta1/doc.go
+++ b/api/v1beta1/doc.go
@@ -14,4 +14,7 @@ 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/openstackcluster_types.go b/api/v1beta1/openstackcluster_types.go
index 728310a82b..ff24c04f5b 100644
--- a/api/v1beta1/openstackcluster_types.go
+++ b/api/v1beta1/openstackcluster_types.go
@@ -235,6 +235,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
diff --git a/api/v1beta1/openstackclustertemplate_types.go b/api/v1beta1/openstackclustertemplate_types.go
index 2134595759..8516831b60 100644
--- a/api/v1beta1/openstackclustertemplate_types.go
+++ b/api/v1beta1/openstackclustertemplate_types.go
@@ -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 {
diff --git a/api/v1beta1/openstackmachine_types.go b/api/v1beta1/openstackmachine_types.go
index e08cf2ef82..c3f5ea367b 100644
--- a/api/v1beta1/openstackmachine_types.go
+++ b/api/v1beta1/openstackmachine_types.go
@@ -146,6 +146,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
diff --git a/api/v1beta1/openstackmachinetemplate_types.go b/api/v1beta1/openstackmachinetemplate_types.go
index c085f2620d..aff1e7060b 100644
--- a/api/v1beta1/openstackmachinetemplate_types.go
+++ b/api/v1beta1/openstackmachinetemplate_types.go
@@ -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
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..5c4e964917
--- /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.5.1"
+ },
+ {
+ "typeMatchPrefix": "^sigs\\.k8s\\.io/cluster-api/api/v1beta1",
+ "docsURLTemplate": "https://doc.crds.dev/github.com/kubernetes-sigs/cluster-api@v1.5.1"
+ },
+ {
+ "typeMatchPrefix": "^sigs\\.k8s\\.io/cluster-api/errors",
+ "docsURLTemplate": "https://pkg.go.dev/sigs.k8s.io/cluster-api@v1.5.1/errors#{{.TypeIdentifier}}"
+ }
+ ],
+ "typeDisplayNamePrefixOverrides": {
+ "k8s.io/api/": "Kubernetes ",
+ "k8s.io/apimachinery/pkg/apis/": "Kubernetes "
+ },
+ "markdownDisabled": false
+ }
\ No newline at end of file
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 . }}
+
+ {{ if linkForType .Type }}
+
+ {{ typeDisplayName .Type }}
+
+ {{ else }}
+ {{ typeDisplayName .Type }}
+ {{ end }}
+
+ |
+
+ {{ if fieldEmbedded . }}
+
+ (Members of {{ fieldName . }} are embedded into this type.)
+
+ {{ end}}
+
+ {{ if isOptionalMember .}}
+ (Optional)
+ {{ end }}
+
+ {{ safe (renderComments .CommentLines) }}
+
+ {{ if and (eq (.Type.Name.Name) "ObjectMeta") }}
+ Refer to the Kubernetes API documentation for the fields of the
+ metadata field.
+ {{ end }}
+
+ {{ if or (eq (fieldName .) "spec") }}
+
+
+
+ {{ template "members" .Type }}
+
+ {{ end }}
+ |
+
+{{ end }}
+{{ end }}
+
+{{ end }}
\ No newline at end of file
diff --git a/docs/book/gen-crd-api-reference-docs/template/pkg.tpl b/docs/book/gen-crd-api-reference-docs/template/pkg.tpl
new file mode 100644
index 0000000000..e9a0697911
--- /dev/null
+++ b/docs/book/gen-crd-api-reference-docs/template/pkg.tpl
@@ -0,0 +1,37 @@
+{{ define "packages" }}
+
+{{ range .packages }}
+
+ {{- packageDisplayName . -}}
+
+
+ {{ with (index .GoPackages 0 )}}
+ {{ with .DocComments }}
+
+ {{ safe (renderComments .) }}
+
+ {{ end }}
+ {{ end }}
+
+ Resource Types:
+
+ {{- range (visibleTypes (sortedTypes .Types)) -}}
+ {{ if isExportedType . -}}
+ -
+ {{ typeDisplayName . }}
+
+ {{- end }}
+ {{- end -}}
+
+
+ {{ range (visibleTypes (sortedTypes .Types))}}
+ {{ template "type" . }}
+ {{ end }}
+
+{{ end }}
+
+
+ Generated with gen-crd-api-reference-docs.
+
+
+{{ end }}
\ No newline at end of file
diff --git a/docs/book/gen-crd-api-reference-docs/template/type.tpl b/docs/book/gen-crd-api-reference-docs/template/type.tpl
new file mode 100644
index 0000000000..7ee5af5ab1
--- /dev/null
+++ b/docs/book/gen-crd-api-reference-docs/template/type.tpl
@@ -0,0 +1,81 @@
+{{ define "type" }}
+
+
+ {{- .Name.Name }}
+ {{ if eq .Kind "Alias" }}({{.Underlying}} alias)
{{ end -}}
+
+{{ with (typeReferences .) }}
+
+ (Appears on:
+ {{- $prev := "" -}}
+ {{- range . -}}
+ {{- if $prev -}}, {{ end -}}
+ {{ $prev = . }}
+ {{ typeDisplayName . }}
+ {{- end -}}
+ )
+
+{{ end }}
+
+
+ {{ safe (renderComments .CommentLines) }}
+
+
+{{ with (constantsOfType .) }}
+
+
+
+ | Value |
+ Description |
+
+
+
+ {{- range . -}}
+
+ {{- /*
+ renderComments implicitly creates a element, so we
+ add one to the display name as well to make the contents
+ of the two cells align evenly.
+ */ -}}
+
{{ typeDisplayName . }} |
+ {{ safe (renderComments .CommentLines) }} |
+
+ {{- end -}}
+
+
+{{ end }}
+
+{{ if .Members }}
+
+
+
+ | Field |
+ Description |
+
+
+
+ {{ if isExportedType . }}
+
+
+ apiVersion
+ string |
+
+
+ {{apiGroup .}}
+
+ |
+
+
+
+ kind
+ string
+ |
+ {{.Name.Name}} |
+
+ {{ end }}
+ {{ template "members" .}}
+
+
+{{ end }}
+
+{{ end }}
\ No newline at end of file
diff --git a/docs/book/src/SUMMARY.md b/docs/book/src/SUMMARY.md
index 476311d1f7..9df5f2f500 100644
--- a/docs/book/src/SUMMARY.md
+++ b/docs/book/src/SUMMARY.md
@@ -12,5 +12,9 @@
- [v1alpha5 to v1alpha6](./topics/crd-changes/v1alpha5-to-v1alpha6.md)
- [v1alpha6 to v1alpha7](./topics/crd-changes/v1alpha6-to-v1alpha7.md)
- [v1alpha7 to v1beta1](./topics/crd-changes/v1alpha7-to-v1beta1.md)
+- [API reference](./api/index.md)
+ - [v1alpha6](./api/v1alpha6/api.md)
+ - [v1alpha7](./api/v1alpha7/api.md)
+ - [v1beta1](./api/v1beta1/api.md)
- [Development](./development/development.md)
- [Hacking CI](./development/ci.md)
diff --git a/docs/book/src/api/index.md b/docs/book/src/api/index.md
new file mode 100644
index 0000000000..4ef12691eb
--- /dev/null
+++ b/docs/book/src/api/index.md
@@ -0,0 +1 @@
+# API reference
\ No newline at end of file
diff --git a/docs/book/src/api/v1alpha6/api.md b/docs/book/src/api/v1alpha6/api.md
new file mode 100644
index 0000000000..16ec7522c5
--- /dev/null
+++ b/docs/book/src/api/v1alpha6/api.md
@@ -0,0 +1,4218 @@
+infrastructure.cluster.x-k8s.io/v1alpha6
+
+
Package v1alpha6 contains API Schema definitions for the infrastructure v1alpha6 API group.
+
+Resource Types:
+
+OpenStackCluster
+
+
+
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
+
+
+ |
+
+
+
+
+
+
+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 enabled: true.
+ |
+
+
+
+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 enabled: false to
+make changes.
+ |
+
+
+
+identityRef
+
+
+OpenStackIdentityReference
+
+
+ |
+
+(Optional)
+ IdentityRef is a reference to a identity to be used when reconciling this cluster
+ |
+
+
+ |
+
+
+
+status
+
+
+OpenStackClusterStatus
+
+
+ |
+
+ |
+
+
+
+OpenStackClusterTemplate
+
+
+
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
+
+
+
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
+
+
+ |
+
+
+
+
+
+
+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
+ |
+
+
+ |
+
+
+
+status
+
+
+OpenStackMachineStatus
+
+
+ |
+
+ |
+
+
+
+OpenStackMachineTemplate
+
+
+
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
+
+
+ |
+
+
+
+
+ |
+
+
+
+APIServerLoadBalancer
+
+
+(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
+ |
+
+
+
+AddressPair
+
+
+(Appears on:
+PortOpts)
+
+
+
+
+
+
+| Field |
+Description |
+
+
+
+
+
+ipAddress
+
+string
+
+ |
+
+ |
+
+
+
+macAddress
+
+string
+
+ |
+
+ |
+
+
+
+Bastion
+
+
+(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)
+ |
+
+
+
+ExternalRouterIPParam
+
+
+(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
+ |
+
+
+
+FixedIP
+
+
+(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
+
+ |
+
+ |
+
+
+
+Instance
+
+
+(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
+
+ |
+
+ |
+
+
+
+InstanceState
+(string alias)
+
+(Appears on:
+Instance,
+OpenStackMachineStatus)
+
+
+
InstanceState describes the state of an OpenStack instance.
+
+LoadBalancer
+
+
+(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)
+ |
+
+
+
+Network
+
+
+(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
+ |
+
+
+
+NetworkFilter
+
+
+(Appears on:
+NetworkParam,
+OpenStackClusterSpec,
+PortOpts)
+
+
+
+
+
+
+| Field |
+Description |
+
+
+
+
+
+name
+
+string
+
+ |
+
+ |
+
+
+
+description
+
+string
+
+ |
+
+ |
+
+
+
+projectId
+
+string
+
+ |
+
+ |
+
+
+
+id
+
+string
+
+ |
+
+ |
+
+
+
+tags
+
+string
+
+ |
+
+ |
+
+
+
+tagsAny
+
+string
+
+ |
+
+ |
+
+
+
+notTags
+
+string
+
+ |
+
+ |
+
+
+
+notTagsAny
+
+string
+
+ |
+
+ |
+
+
+
+NetworkParam
+
+
+(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 Subnets specifies a subnet by UUID.
+ |
+
+
+
+fixedIP
+
+string
+
+ |
+
+ A fixed IPv4 address for the NIC.
+ |
+
+
+
+filter
+
+
+NetworkFilter
+
+
+ |
+
+ Filters for optional network query
+ |
+
+
+
+subnets
+
+
+[]SubnetParam
+
+
+ |
+
+ Subnet within a network to use
+ |
+
+
+
+OpenStackClusterSpec
+
+
+(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 enabled: true.
+ |
+
+
+
+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 enabled: false to
+make changes.
+ |
+
+
+
+identityRef
+
+
+OpenStackIdentityReference
+
+
+ |
+
+(Optional)
+ IdentityRef is a reference to a identity to be used when reconciling this cluster
+ |
+
+
+
+OpenStackClusterStatus
+
+
+(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.
+ |
+
+
+
+OpenStackClusterTemplateResource
+
+
+(Appears on:
+OpenStackClusterTemplateSpec)
+
+
+
OpenStackClusterTemplateResource describes the data needed to create a OpenStackCluster from a template.
+
+
+
+
+| Field |
+Description |
+
+
+
+
+
+spec
+
+
+OpenStackClusterSpec
+
+
+ |
+
+
+
+
+
+
+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 enabled: true.
+ |
+
+
+
+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 enabled: false to
+make changes.
+ |
+
+
+
+identityRef
+
+
+OpenStackIdentityReference
+
+
+ |
+
+(Optional)
+ IdentityRef is a reference to a identity to be used when reconciling this cluster
+ |
+
+
+ |
+
+
+
+OpenStackClusterTemplateSpec
+
+
+(Appears on:
+OpenStackClusterTemplate)
+
+
+
OpenStackClusterTemplateSpec defines the desired state of OpenStackClusterTemplate.
+
+
+OpenStackIdentityReference
+
+
+(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.
+ |
+
+
+
+OpenStackMachineSpec
+
+
+(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
+ |
+
+
+
+OpenStackMachineStatus
+
+
+(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
+
+
+ |
+
+ |
+
+
+
+OpenStackMachineTemplateResource
+
+
+(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.
+
+
+
+
+
+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
+ |
+
+
+ |
+
+
+
+OpenStackMachineTemplateSpec
+
+
+(Appears on:
+OpenStackMachineTemplate)
+
+
+
OpenStackMachineTemplateSpec defines the desired state of OpenStackMachineTemplate.
+
+
+PortOpts
+
+
+(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.
+ |
+
+
+
+RootVolume
+
+
+(Appears on:
+Instance,
+OpenStackMachineSpec)
+
+
+
+
+
+
+| Field |
+Description |
+
+
+
+
+
+diskSize
+
+int
+
+ |
+
+ |
+
+
+
+volumeType
+
+string
+
+ |
+
+ |
+
+
+
+availabilityZone
+
+string
+
+ |
+
+ |
+
+
+
+Router
+
+
+(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)
+ |
+
+
+
+SecurityGroup
+
+
+(Appears on:
+OpenStackClusterStatus)
+
+
+
SecurityGroup represents the basic information of the associated
+OpenStack Neutron Security Group.
+
+
+
+
+| Field |
+Description |
+
+
+
+
+
+name
+
+string
+
+ |
+
+ |
+
+
+
+id
+
+string
+
+ |
+
+ |
+
+
+
+rules
+
+
+[]SecurityGroupRule
+
+
+ |
+
+ |
+
+
+
+SecurityGroupFilter
+
+
+(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
+
+ |
+
+ |
+
+
+
+SecurityGroupParam
+
+
+(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
+ |
+
+
+
+SecurityGroupRule
+
+
+(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
+
+ |
+
+ |
+
+
+
+Subnet
+
+
+(Appears on:
+Network)
+
+
+
Subnet represents basic information about the associated OpenStack Neutron Subnet.
+
+
+
+
+| Field |
+Description |
+
+
+
+
+
+name
+
+string
+
+ |
+
+ |
+
+
+
+id
+
+string
+
+ |
+
+ |
+
+
+
+cidr
+
+string
+
+ |
+
+ |
+
+
+
+tags
+
+[]string
+
+ |
+
+(Optional)
+ |
+
+
+
+SubnetFilter
+
+
+(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
+
+ |
+
+ |
+
+
+
+SubnetParam
+
+
+(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 NetworkParam must also be specified by UUID.
+ |
+
+
+
+filter
+
+
+SubnetFilter
+
+
+ |
+
+ Filters for optional subnet query
+ |
+
+
+
+ValueSpec
+
+
+(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.
+
diff --git a/docs/book/src/api/v1alpha7/api.md b/docs/book/src/api/v1alpha7/api.md
new file mode 100644
index 0000000000..9e4dbbeb16
--- /dev/null
+++ b/docs/book/src/api/v1alpha7/api.md
@@ -0,0 +1,4235 @@
+infrastructure.cluster.x-k8s.io/v1alpha7
+
+
Package v1alpha7 contains API Schema definitions for the infrastructure v1alpha7 API group.
+
+Resource Types:
+
+OpenStackCluster
+
+
+
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
+
+
+ |
+
+
+
+
+
+
+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 enabled: true.
+ |
+
+
+
+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 enabled: false to
+make changes.
+ |
+
+
+
+identityRef
+
+
+OpenStackIdentityReference
+
+
+ |
+
+(Optional)
+ IdentityRef is a reference to a identity to be used when reconciling this cluster
+ |
+
+
+ |
+
+
+
+status
+
+
+OpenStackClusterStatus
+
+
+ |
+
+ |
+
+
+
+OpenStackClusterTemplate
+
+
+
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
+
+
+
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
+
+
+ |
+
+
+
+
+
+
+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.
+ |
+
+
+ |
+
+
+
+status
+
+
+OpenStackMachineStatus
+
+
+ |
+
+ |
+
+
+
+OpenStackMachineTemplate
+
+
+
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
+
+
+ |
+
+
+
+
+ |
+
+
+
+APIServerLoadBalancer
+
+
+(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
+ |
+
+
+
+AdditionalBlockDevice
+
+
+(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.
+ |
+
+
+
+AddressPair
+
+
+(Appears on:
+PortOpts)
+
+
+
+
+
+
+| Field |
+Description |
+
+
+
+
+
+ipAddress
+
+string
+
+ |
+
+ |
+
+
+
+macAddress
+
+string
+
+ |
+
+ |
+
+
+
+Bastion
+
+
+(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)
+ |
+
+
+
+BastionStatus
+
+
+(Appears on:
+OpenStackClusterStatus)
+
+
+
+
+
+
+| Field |
+Description |
+
+
+
+
+
+id
+
+string
+
+ |
+
+ |
+
+
+
+name
+
+string
+
+ |
+
+ |
+
+
+
+sshKeyName
+
+string
+
+ |
+
+ |
+
+
+
+state
+
+
+InstanceState
+
+
+ |
+
+ |
+
+
+
+ip
+
+string
+
+ |
+
+ |
+
+
+
+floatingIP
+
+string
+
+ |
+
+ |
+
+
+
+BindingProfile
+
+
+(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.
+ |
+
+
+
+BlockDeviceStorage
+
+
+(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.
+ |
+
+
+
+BlockDeviceType
+(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.
+ |
+
+
+BlockDeviceVolume
+
+
+(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.
+ |
+
+
+
+ExternalRouterIPParam
+
+
+(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
+ |
+
+
+
+FixedIP
+
+
+(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
+
+ |
+
+ |
+
+
+
+InstanceState
+(string alias)
+
+(Appears on:
+BastionStatus,
+OpenStackMachineStatus)
+
+
+
InstanceState describes the state of an OpenStack instance.
+
+LoadBalancer
+
+
+(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)
+ |
+
+
+
+NetworkFilter
+
+
+(Appears on:
+OpenStackClusterSpec,
+PortOpts)
+
+
+
+
+
+
+| Field |
+Description |
+
+
+
+
+
+name
+
+string
+
+ |
+
+ |
+
+
+
+description
+
+string
+
+ |
+
+ |
+
+
+
+projectId
+
+string
+
+ |
+
+ |
+
+
+
+id
+
+string
+
+ |
+
+ |
+
+
+
+tags
+
+string
+
+ |
+
+ |
+
+
+
+tagsAny
+
+string
+
+ |
+
+ |
+
+
+
+notTags
+
+string
+
+ |
+
+ |
+
+
+
+notTagsAny
+
+string
+
+ |
+
+ |
+
+
+
+NetworkStatus
+
+
+(Appears on:
+NetworkStatusWithSubnets,
+OpenStackClusterStatus)
+
+
+
NetworkStatus contains basic information about an existing neutron network.
+
+
+
+
+| Field |
+Description |
+
+
+
+
+
+name
+
+string
+
+ |
+
+ |
+
+
+
+id
+
+string
+
+ |
+
+ |
+
+
+
+tags
+
+[]string
+
+ |
+
+(Optional)
+ |
+
+
+
+NetworkStatusWithSubnets
+
+
+(Appears on:
+OpenStackClusterStatus)
+
+
+
NetworkStatusWithSubnets represents basic information about an existing neutron network and an associated set of subnets.
+
+
+
+
+| Field |
+Description |
+
+
+
+
+
+NetworkStatus
+
+
+NetworkStatus
+
+
+ |
+
+
+(Members of NetworkStatus are embedded into this type.)
+
+ |
+
+
+
+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.
+ |
+
+
+
+OpenStackClusterSpec
+
+
+(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 enabled: true.
+ |
+
+
+
+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 enabled: false to
+make changes.
+ |
+
+
+
+identityRef
+
+
+OpenStackIdentityReference
+
+
+ |
+
+(Optional)
+ IdentityRef is a reference to a identity to be used when reconciling this cluster
+ |
+
+
+
+OpenStackClusterStatus
+
+
+(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.
+ |
+
+
+
+OpenStackClusterTemplateResource
+
+
+(Appears on:
+OpenStackClusterTemplateSpec)
+
+
+
OpenStackClusterTemplateResource describes the data needed to create a OpenStackCluster from a template.
+
+
+
+
+| Field |
+Description |
+
+
+
+
+
+spec
+
+
+OpenStackClusterSpec
+
+
+ |
+
+
+
+
+
+
+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 enabled: true.
+ |
+
+
+
+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 enabled: false to
+make changes.
+ |
+
+
+
+identityRef
+
+
+OpenStackIdentityReference
+
+
+ |
+
+(Optional)
+ IdentityRef is a reference to a identity to be used when reconciling this cluster
+ |
+
+
+ |
+
+
+
+OpenStackClusterTemplateSpec
+
+
+(Appears on:
+OpenStackClusterTemplate)
+
+
+
OpenStackClusterTemplateSpec defines the desired state of OpenStackClusterTemplate.
+
+
+OpenStackIdentityReference
+
+
+(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.
+ |
+
+
+
+OpenStackMachineSpec
+
+
+(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.
+ |
+
+
+
+OpenStackMachineStatus
+
+
+(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
+
+
+ |
+
+ |
+
+
+
+OpenStackMachineTemplateResource
+
+
+(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.
+
+
+
+
+
+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.
+ |
+
+
+ |
+
+
+
+OpenStackMachineTemplateSpec
+
+
+(Appears on:
+OpenStackMachineTemplate)
+
+
+
OpenStackMachineTemplateSpec defines the desired state of OpenStackMachineTemplate.
+
+
+PortOpts
+
+
+(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.
+ |
+
+
+
+RootVolume
+
+
+(Appears on:
+OpenStackMachineSpec)
+
+
+
+
+
+
+| Field |
+Description |
+
+
+
+
+
+diskSize
+
+int
+
+ |
+
+ |
+
+
+
+volumeType
+
+string
+
+ |
+
+ |
+
+
+
+availabilityZone
+
+string
+
+ |
+
+ |
+
+
+
+Router
+
+
+(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)
+ |
+
+
+
+RouterFilter
+
+
+(Appears on:
+OpenStackClusterSpec)
+
+
+
+
+
+
+| Field |
+Description |
+
+
+
+
+
+id
+
+string
+
+ |
+
+ |
+
+
+
+name
+
+string
+
+ |
+
+ |
+
+
+
+description
+
+string
+
+ |
+
+ |
+
+
+
+projectId
+
+string
+
+ |
+
+ |
+
+
+
+tags
+
+string
+
+ |
+
+ |
+
+
+
+tagsAny
+
+string
+
+ |
+
+ |
+
+
+
+notTags
+
+string
+
+ |
+
+ |
+
+
+
+notTagsAny
+
+string
+
+ |
+
+ |
+
+
+
+SecurityGroup
+
+
+(Appears on:
+OpenStackClusterStatus)
+
+
+
SecurityGroup represents the basic information of the associated
+OpenStack Neutron Security Group.
+
+
+
+
+| Field |
+Description |
+
+
+
+
+
+name
+
+string
+
+ |
+
+ |
+
+
+
+id
+
+string
+
+ |
+
+ |
+
+
+
+rules
+
+
+[]SecurityGroupRule
+
+
+ |
+
+ |
+
+
+
+SecurityGroupFilter
+
+
+(Appears on:
+OpenStackMachineSpec,
+PortOpts)
+
+
+
+
+
+
+| Field |
+Description |
+
+
+
+
+
+id
+
+string
+
+ |
+
+ |
+
+
+
+name
+
+string
+
+ |
+
+ |
+
+
+
+description
+
+string
+
+ |
+
+ |
+
+
+
+projectId
+
+string
+
+ |
+
+ |
+
+
+
+tags
+
+string
+
+ |
+
+ |
+
+
+
+tagsAny
+
+string
+
+ |
+
+ |
+
+
+
+notTags
+
+string
+
+ |
+
+ |
+
+
+
+notTagsAny
+
+string
+
+ |
+
+ |
+
+
+
+SecurityGroupRule
+
+
+(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
+
+ |
+
+ |
+
+
+
+Subnet
+
+
+(Appears on:
+NetworkStatusWithSubnets)
+
+
+
Subnet represents basic information about the associated OpenStack Neutron Subnet.
+
+
+
+
+| Field |
+Description |
+
+
+
+
+
+name
+
+string
+
+ |
+
+ |
+
+
+
+id
+
+string
+
+ |
+
+ |
+
+
+
+cidr
+
+string
+
+ |
+
+ |
+
+
+
+tags
+
+[]string
+
+ |
+
+(Optional)
+ |
+
+
+
+SubnetFilter
+
+
+(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
+
+ |
+
+ |
+
+
+
+ValueSpec
+
+
+(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.
+
diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md
new file mode 100644
index 0000000000..f55c02035e
--- /dev/null
+++ b/docs/book/src/api/v1beta1/api.md
@@ -0,0 +1,4806 @@
+infrastructure.cluster.x-k8s.io/v1beta1
+
+
Package v1beta1 contains API Schema definitions for the infrastructure v1beta1 API group.
+
+Resource Types:
+
+OpenStackCluster
+
+
+
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
+
+
+ |
+
+
+
+
+
+
+cloudName
+
+string
+
+ |
+
+(Optional)
+ The name of the cloud to use from the clouds secret
+ |
+
+
+
+managedSubnets
+
+
+[]SubnetSpec
+
+
+ |
+
+ 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
+
+
+RouterFilter
+
+
+ |
+
+(Optional)
+ Router specifies an existing router to be used if ManagedSubnets are
+specified. If specified, no new router will be created.
+ |
+
+
+
+network
+
+
+NetworkFilter
+
+
+ |
+
+ Network specifies an existing network to use if no ManagedSubnets
+are specified.
+ |
+
+
+
+subnets
+
+
+[]SubnetFilter
+
+
+ |
+
+(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
+
+
+ |
+
+ 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
+
+
+NetworkFilter
+
+
+ |
+
+(Optional)
+ ExternalNetwork is the OpenStack Network to be used to get public internet to the VMs.
+ |
+
+
+
+disableExternalNetwork
+
+bool
+
+ |
+
+(Optional)
+ DisableExternalNetwork determines 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.
+It must be activated by setting enabled: true.
+ |
+
+
+
+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
+
+
+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
+
+ |
+
+ 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. To make changes, it’s required
+to first set enabled: false which will remove the bastion and then changes can be made.
+ |
+
+
+
+identityRef
+
+
+OpenStackIdentityReference
+
+
+ |
+
+(Optional)
+ IdentityRef is a reference to a identity to be used when reconciling this cluster
+ |
+
+
+ |
+
+
+
+status
+
+
+OpenStackClusterStatus
+
+
+ |
+
+ |
+
+
+
+OpenStackClusterTemplate
+
+
+
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
+
+
+
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
+
+
+ |
+
+
+
+
+
+
+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
+
+
+ImageFilter
+
+
+ |
+
+ 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
+
+
+[]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
+
+
+[]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
+
+
+ServerGroupFilter
+
+
+ |
+
+(Optional)
+ 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
+ |
+
+
+ |
+
+
+
+status
+
+
+OpenStackMachineStatus
+
+
+ |
+
+ |
+
+
+
+OpenStackMachineTemplate
+
+
+
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
+
+
+ |
+
+
+
+
+ |
+
+
+
+APIServerLoadBalancer
+
+
+(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
+ |
+
+
+
+AdditionalBlockDevice
+
+
+(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.
+ |
+
+
+
+AddressPair
+
+
+(Appears on:
+PortOpts)
+
+
+
+
+
+
+| Field |
+Description |
+
+
+
+
+
+ipAddress
+
+string
+
+ |
+
+ |
+
+
+
+macAddress
+
+string
+
+ |
+
+ |
+
+
+
+AllocationPool
+
+
+(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.
+ |
+
+
+
+Bastion
+
+
+(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)
+ |
+
+
+
+floatingIP
+
+string
+
+ |
+
+(Optional)
+ FloatingIP which will be associated to the bastion machine.
+The floating IP should already exist and should not be associated with a port.
+ |
+
+
+
+BastionStatus
+
+
+(Appears on:
+OpenStackClusterStatus)
+
+
+
+
+
+
+| Field |
+Description |
+
+
+
+
+
+id
+
+string
+
+ |
+
+ |
+
+
+
+name
+
+string
+
+ |
+
+ |
+
+
+
+sshKeyName
+
+string
+
+ |
+
+ |
+
+
+
+state
+
+
+InstanceState
+
+
+ |
+
+ |
+
+
+
+ip
+
+string
+
+ |
+
+ |
+
+
+
+floatingIP
+
+string
+
+ |
+
+ |
+
+
+
+referencedResources
+
+
+ReferencedMachineResources
+
+
+ |
+
+ |
+
+
+
+dependentResources
+
+
+DependentMachineResources
+
+
+ |
+
+ |
+
+
+
+BindingProfile
+
+
+(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.
+ |
+
+
+
+BlockDeviceStorage
+
+
+(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.
+ |
+
+
+
+BlockDeviceType
+(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.
+ |
+
+
+BlockDeviceVolume
+
+
+(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.
+ |
+
+
+
+DependentMachineResources
+
+
+(Appears on:
+BastionStatus,
+OpenStackMachineStatus)
+
+
+
+
+
+
+| Field |
+Description |
+
+
+
+
+
+portsStatus
+
+
+[]PortStatus
+
+
+ |
+
+(Optional)
+ PortsStatus is the status of the ports created for the machine.
+ |
+
+
+
+ExternalRouterIPParam
+
+
+(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
+ |
+
+
+
+FixedIP
+
+
+(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
+
+ |
+
+ |
+
+
+
+ImageFilter
+
+
+(Appears on:
+OpenStackMachineSpec)
+
+
+
+
+
+
+| Field |
+Description |
+
+
+
+
+
+id
+
+string
+
+ |
+
+ The ID of the desired image. If this is provided, the other filters will be ignored.
+ |
+
+
+
+name
+
+string
+
+ |
+
+ 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
+
+ |
+
+ 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.
+ |
+
+
+
+InstanceState
+(string alias)
+
+(Appears on:
+BastionStatus,
+OpenStackMachineStatus)
+
+
+
InstanceState describes the state of an OpenStack instance.
+
+LoadBalancer
+
+
+(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)
+ |
+
+
+
+ManagedSecurityGroupName
+(string alias)
+
+(Appears on:
+SecurityGroupRuleSpec)
+
+
+
+ManagedSecurityGroups
+
+
+(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.
+ |
+
+
+
+NetworkFilter
+
+
+(Appears on:
+OpenStackClusterSpec,
+PortOpts)
+
+
+
+
+
+
+| Field |
+Description |
+
+
+
+
+
+name
+
+string
+
+ |
+
+ |
+
+
+
+description
+
+string
+
+ |
+
+ |
+
+
+
+projectId
+
+string
+
+ |
+
+ |
+
+
+
+id
+
+string
+
+ |
+
+ |
+
+
+
+tags
+
+string
+
+ |
+
+ |
+
+
+
+tagsAny
+
+string
+
+ |
+
+ |
+
+
+
+notTags
+
+string
+
+ |
+
+ |
+
+
+
+notTagsAny
+
+string
+
+ |
+
+ |
+
+
+
+NetworkStatus
+
+
+(Appears on:
+NetworkStatusWithSubnets,
+OpenStackClusterStatus)
+
+
+
NetworkStatus contains basic information about an existing neutron network.
+
+
+
+
+| Field |
+Description |
+
+
+
+
+
+name
+
+string
+
+ |
+
+ |
+
+
+
+id
+
+string
+
+ |
+
+ |
+
+
+
+tags
+
+[]string
+
+ |
+
+(Optional)
+ |
+
+
+
+NetworkStatusWithSubnets
+
+
+(Appears on:
+OpenStackClusterStatus)
+
+
+
NetworkStatusWithSubnets represents basic information about an existing neutron network and an associated set of subnets.
+
+
+
+
+| Field |
+Description |
+
+
+
+
+
+NetworkStatus
+
+
+NetworkStatus
+
+
+ |
+
+
+(Members of NetworkStatus are embedded into this type.)
+
+ |
+
+
+
+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.
+ |
+
+
+
+OpenStackClusterSpec
+
+
+(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
+ |
+
+
+
+managedSubnets
+
+
+[]SubnetSpec
+
+
+ |
+
+ 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
+
+
+RouterFilter
+
+
+ |
+
+(Optional)
+ Router specifies an existing router to be used if ManagedSubnets are
+specified. If specified, no new router will be created.
+ |
+
+
+
+network
+
+
+NetworkFilter
+
+
+ |
+
+ Network specifies an existing network to use if no ManagedSubnets
+are specified.
+ |
+
+
+
+subnets
+
+
+[]SubnetFilter
+
+
+ |
+
+(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
+
+
+ |
+
+ 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
+
+
+NetworkFilter
+
+
+ |
+
+(Optional)
+ ExternalNetwork is the OpenStack Network to be used to get public internet to the VMs.
+ |
+
+
+
+disableExternalNetwork
+
+bool
+
+ |
+
+(Optional)
+ DisableExternalNetwork determines 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.
+It must be activated by setting enabled: true.
+ |
+
+
+
+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
+
+
+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
+
+ |
+
+ 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. To make changes, it’s required
+to first set enabled: false which will remove the bastion and then changes can be made.
+ |
+
+
+
+identityRef
+
+
+OpenStackIdentityReference
+
+
+ |
+
+(Optional)
+ IdentityRef is a reference to a identity to be used when reconciling this cluster
+ |
+
+
+
+OpenStackClusterStatus
+
+
+(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
+
+
+ |
+
+ 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
+
+
+SecurityGroupStatus
+
+
+ |
+
+ 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
+
+
+SecurityGroupStatus
+
+
+ |
+
+ WorkerSecurityGroup contains all the information about the OpenStack Security
+Group that needs to be applied to worker nodes.
+ |
+
+
+
+bastionSecurityGroup
+
+
+SecurityGroupStatus
+
+
+ |
+
+ |
+
+
+
+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.
+ |
+
+
+
+OpenStackClusterTemplateResource
+
+
+(Appears on:
+OpenStackClusterTemplateSpec)
+
+
+
OpenStackClusterTemplateResource describes the data needed to create a OpenStackCluster from a template.
+
+
+
+
+| Field |
+Description |
+
+
+
+
+
+spec
+
+
+OpenStackClusterSpec
+
+
+ |
+
+
+
+
+
+
+cloudName
+
+string
+
+ |
+
+(Optional)
+ The name of the cloud to use from the clouds secret
+ |
+
+
+
+managedSubnets
+
+
+[]SubnetSpec
+
+
+ |
+
+ 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
+
+
+RouterFilter
+
+
+ |
+
+(Optional)
+ Router specifies an existing router to be used if ManagedSubnets are
+specified. If specified, no new router will be created.
+ |
+
+
+
+network
+
+
+NetworkFilter
+
+
+ |
+
+ Network specifies an existing network to use if no ManagedSubnets
+are specified.
+ |
+
+
+
+subnets
+
+
+[]SubnetFilter
+
+
+ |
+
+(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
+
+
+ |
+
+ 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
+
+
+NetworkFilter
+
+
+ |
+
+(Optional)
+ ExternalNetwork is the OpenStack Network to be used to get public internet to the VMs.
+ |
+
+
+
+disableExternalNetwork
+
+bool
+
+ |
+
+(Optional)
+ DisableExternalNetwork determines 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.
+It must be activated by setting enabled: true.
+ |
+
+
+
+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
+
+
+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
+
+ |
+
+ 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. To make changes, it’s required
+to first set enabled: false which will remove the bastion and then changes can be made.
+ |
+
+
+
+identityRef
+
+
+OpenStackIdentityReference
+
+
+ |
+
+(Optional)
+ IdentityRef is a reference to a identity to be used when reconciling this cluster
+ |
+
+
+ |
+
+
+
+OpenStackClusterTemplateSpec
+
+
+(Appears on:
+OpenStackClusterTemplate)
+
+
+
OpenStackClusterTemplateSpec defines the desired state of OpenStackClusterTemplate.
+
+
+OpenStackIdentityReference
+
+
+(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 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.
+ |
+
+
+
+OpenStackMachineSpec
+
+
+(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
+
+
+ImageFilter
+
+
+ |
+
+ 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
+
+
+[]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
+
+
+[]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
+
+
+ServerGroupFilter
+
+
+ |
+
+(Optional)
+ 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
+ |
+
+
+
+OpenStackMachineStatus
+
+
+(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.
+ |
+
+
+
+referencedResources
+
+
+ReferencedMachineResources
+
+
+ |
+
+ ReferencedResources contains resolved references to resources that the machine depends on.
+ |
+
+
+
+dependentResources
+
+
+DependentMachineResources
+
+
+ |
+
+ DependentResources contains resolved dependent resources that were created by 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
+
+
+ |
+
+ |
+
+
+
+OpenStackMachineTemplateResource
+
+
+(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.
+
+
+
+
+
+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
+
+
+ImageFilter
+
+
+ |
+
+ 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
+
+
+[]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
+
+
+[]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
+
+
+ServerGroupFilter
+
+
+ |
+
+(Optional)
+ 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
+ |
+
+
+ |
+
+
+
+OpenStackMachineTemplateSpec
+
+
+(Appears on:
+OpenStackMachineTemplate)
+
+
+
OpenStackMachineTemplateSpec defines the desired state of OpenStackMachineTemplate.
+
+
+OpenStackMachineTemplateWebhook
+
+
+
+PortOpts
+
+
+(Appears on:
+OpenStackMachineSpec,
+ReferencedMachineResources)
+
+
+
+
+
+
+| 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.
+ |
+
+
+
+PortStatus
+
+
+(Appears on:
+DependentMachineResources)
+
+
+
+
+
+
+| Field |
+Description |
+
+
+
+
+
+id
+
+string
+
+ |
+
+ ID is the unique identifier of the port.
+ |
+
+
+
+ReferencedMachineResources
+
+
+(Appears on:
+BastionStatus,
+OpenStackMachineStatus)
+
+
+
ReferencedMachineResources 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.
+ |
+
+
+
+portsOpts
+
+
+[]PortOpts
+
+
+ |
+
+(Optional)
+ portsOpts is the list of ports options to create for the machine.
+ |
+
+
+
+RootVolume
+
+
+(Appears on:
+OpenStackMachineSpec)
+
+
+
+
+
+
+| Field |
+Description |
+
+
+
+
+
+diskSize
+
+int
+
+ |
+
+ |
+
+
+
+volumeType
+
+string
+
+ |
+
+ |
+
+
+
+availabilityZone
+
+string
+
+ |
+
+ |
+
+
+
+Router
+
+
+(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)
+ |
+
+
+
+RouterFilter
+
+
+(Appears on:
+OpenStackClusterSpec)
+
+
+
+
+
+
+| Field |
+Description |
+
+
+
+
+
+id
+
+string
+
+ |
+
+ |
+
+
+
+name
+
+string
+
+ |
+
+ |
+
+
+
+description
+
+string
+
+ |
+
+ |
+
+
+
+projectId
+
+string
+
+ |
+
+ |
+
+
+
+tags
+
+string
+
+ |
+
+ |
+
+
+
+tagsAny
+
+string
+
+ |
+
+ |
+
+
+
+notTags
+
+string
+
+ |
+
+ |
+
+
+
+notTagsAny
+
+string
+
+ |
+
+ |
+
+
+
+SecurityGroupFilter
+
+
+(Appears on:
+OpenStackMachineSpec,
+PortOpts)
+
+
+
+
+
+
+| Field |
+Description |
+
+
+
+
+
+id
+
+string
+
+ |
+
+ |
+
+
+
+name
+
+string
+
+ |
+
+ |
+
+
+
+description
+
+string
+
+ |
+
+ |
+
+
+
+projectId
+
+string
+
+ |
+
+ |
+
+
+
+tags
+
+string
+
+ |
+
+ |
+
+
+
+tagsAny
+
+string
+
+ |
+
+ |
+
+
+
+notTags
+
+string
+
+ |
+
+ |
+
+
+
+notTagsAny
+
+string
+
+ |
+
+ |
+
+
+
+SecurityGroupRuleSpec
+
+
+(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.
+ |
+
+
+
+SecurityGroupRuleStatus
+
+
+(Appears on:
+SecurityGroupStatus)
+
+
+
+
+
+
+| Field |
+Description |
+
+
+
+
+
+id
+
+string
+
+ |
+
+ id of the security group rule
+ |
+
+
+
+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.
+ |
+
+
+
+SecurityGroupStatus
+
+
+(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
+ |
+
+
+
+rules
+
+
+[]SecurityGroupRuleStatus
+
+
+ |
+
+(Optional)
+ list of security group rules
+ |
+
+
+
+ServerGroupFilter
+
+
+(Appears on:
+OpenStackMachineSpec)
+
+
+
+
+
+
+| Field |
+Description |
+
+
+
+
+
+id
+
+string
+
+ |
+
+ |
+
+
+
+name
+
+string
+
+ |
+
+ |
+
+
+
+
+
+(Appears on:
+OpenStackMachineSpec)
+
+
+
+
+
+
+| Field |
+Description |
+
+
+
+
+
+key
+
+string
+
+ |
+
+ Key is the server metadata key
+kubebuilder:validation:MaxLength:=255
+ |
+
+
+
+value
+
+string
+
+ |
+
+ Value is the server metadata value
+kubebuilder:validation:MaxLength:=255
+ |
+
+
+
+Subnet
+
+
+(Appears on:
+NetworkStatusWithSubnets)
+
+
+
Subnet represents basic information about the associated OpenStack Neutron Subnet.
+
+
+
+
+| Field |
+Description |
+
+
+
+
+
+name
+
+string
+
+ |
+
+ |
+
+
+
+id
+
+string
+
+ |
+
+ |
+
+
+
+cidr
+
+string
+
+ |
+
+ |
+
+
+
+tags
+
+[]string
+
+ |
+
+(Optional)
+ |
+
+
+
+SubnetFilter
+
+
+(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
+
+ |
+
+ |
+
+
+
+SubnetSpec
+
+
+(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.
+ |
+
+
+
+ValueSpec
+
+
+(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.
+
diff --git a/hack/tools/Makefile b/hack/tools/Makefile
index 60f45a9955..f39cfadfd6 100644
--- a/hack/tools/Makefile
+++ b/hack/tools/Makefile
@@ -142,6 +142,10 @@ $(PLANTUML): plantuml.Dockerfile ../../versions.mk | $(BIN_DIR)
docker build --build-arg PLANTUML_VERSION=$(PLANTUML_VERSION) . -f plantuml.Dockerfile -t "plantuml-builder"
touch $@
+GEN_CRD_API_REFERENCE_DOCS := $(BIN_DIR)/gen-crd-api-reference-docs
+$(GEN_CRD_API_REFERENCE_DOCS):
+ go build -tags tools -o $@ github.com/ahmetb/gen-crd-api-reference-docs
+
.PHONY: clean
clean: ## Remove all tools
rm -rf $(BIN_DIR)
diff --git a/hack/tools/go.mod b/hack/tools/go.mod
index 79cbbebe17..5d0c742794 100644
--- a/hack/tools/go.mod
+++ b/hack/tools/go.mod
@@ -4,6 +4,7 @@ go 1.22
require (
github.com/a8m/envsubst v1.2.0
+ github.com/ahmetb/gen-crd-api-reference-docs v0.3.1-0.20220420215017-3f29e6853552
github.com/golang/mock v1.6.0
github.com/itchyny/gojq v0.12.2
github.com/onsi/ginkgo/v2 v2.13.0
@@ -47,6 +48,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
github.com/pkg/errors v0.9.1 // indirect
+ github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/spf13/afero v1.9.2 // indirect
github.com/spf13/cobra v1.8.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
@@ -70,6 +72,7 @@ require (
k8s.io/apiextensions-apiserver v0.29.0 // indirect
k8s.io/apimachinery v0.29.0 // indirect
k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01 // indirect
+ k8s.io/klog v0.2.0 // indirect
k8s.io/klog/v2 v2.110.1 // indirect
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect
k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect
diff --git a/hack/tools/go.sum b/hack/tools/go.sum
index 8d2cb148c6..54f95cff3e 100644
--- a/hack/tools/go.sum
+++ b/hack/tools/go.sum
@@ -40,6 +40,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/a8m/envsubst v1.2.0 h1:yvzAhJD2QKdo35Ut03wIfXQmg+ta3wC/1bskfZynz+Q=
github.com/a8m/envsubst v1.2.0/go.mod h1:PpvLvNWa+Rvu/10qXmFbFiGICIU5hZvFJNPCCkUaObg=
+github.com/ahmetb/gen-crd-api-reference-docs v0.3.1-0.20220420215017-3f29e6853552 h1:ppHFRuYry83Rkj933CxFXAV4F2ciIdVz/uLuELSG1DI=
+github.com/ahmetb/gen-crd-api-reference-docs v0.3.1-0.20220420215017-3f29e6853552/go.mod h1:TdjdkYhlOifCQWPs1UdTma97kQQMozf5h26hTuG70u8=
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
@@ -232,9 +234,12 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
+github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
+github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/spf13/afero v1.9.2 h1:j49Hj62F0n+DaZ1dDCvhABaPNSGNkt32oRFxI33IEMw=
github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
@@ -625,8 +630,11 @@ k8s.io/apimachinery v0.29.0 h1:+ACVktwyicPz0oc6MTMLwa2Pw3ouLAfAon1wPLtG48o=
k8s.io/apimachinery v0.29.0/go.mod h1:eVBxQ/cwiJxH58eK/jd/vAk4mrxmVlnpBH5J2GbMeis=
k8s.io/code-generator v0.29.0 h1:2LQfayGDhaIlaamXjIjEQlCMy4JNCH9lrzas4DNW1GQ=
k8s.io/code-generator v0.29.0/go.mod h1:5bqIZoCxs2zTRKMWNYqyQWW/bajc+ah4rh0tMY8zdGA=
+k8s.io/gengo v0.0.0-20201203183100-97869a43a9d9/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01 h1:pWEwq4Asjm4vjW7vcsmijwBhOr1/shsbSYiWXmNGlks=
k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
+k8s.io/klog v0.2.0 h1:0ElL0OHzF3N+OhoJTL0uca20SxtYt4X4+bzHeqrB83c=
+k8s.io/klog v0.2.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0=
k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo=
diff --git a/hack/tools/tools.go b/hack/tools/tools.go
index a6cbdbe0c5..b43864a9a4 100644
--- a/hack/tools/tools.go
+++ b/hack/tools/tools.go
@@ -22,6 +22,7 @@ package tools
import (
_ "github.com/a8m/envsubst"
+ _ "github.com/ahmetb/gen-crd-api-reference-docs"
_ "github.com/golang/mock/mockgen"
_ "github.com/itchyny/gojq/cmd/gojq"
_ "github.com/onsi/ginkgo/v2/ginkgo"
From 4c01e655f34771ec92455ee35166aa7eedba84fe Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Tue, 27 Feb 2024 12:17:08 +0000
Subject: [PATCH 086/180] API cleanup of PortOpts
Internally, all optional fields become pointers. This change has no
direct effect on the CRD, but means that unset values and zero values
now have different meanings.
SecurityGroupFilters is renamed to SecurityGroups for consistency with
other filter fields used throughout the API. Note that this change
thoroughly confuses conversion-gen. Consequently we explicitly disable
the conversion of these fields in v1alpha6 and v1alpha5 and do the
conversion entirely manually.
---
.golangci.yml | 3 +-
Makefile | 1 +
api/v1alpha5/conversion.go | 78 +++++++-
api/v1alpha5/types.go | 2 +
api/v1alpha5/zz_generated.conversion.go | 122 +++++++++---
api/v1alpha6/conversion.go | 92 +++++++--
api/v1alpha6/conversion_test.go | 83 +++++++-
api/v1alpha6/types.go | 2 +
api/v1alpha6/zz_generated.conversion.go | 126 +++++++++---
api/v1alpha7/conversion.go | 114 +++++++++++
api/v1alpha7/conversion_test.go | 64 +++++-
api/v1alpha7/zz_generated.conversion.go | 186 +++++++++++++-----
api/v1beta1/conversion.go | 4 +-
api/v1beta1/types.go | 118 ++++++++---
api/v1beta1/zz_generated.deepcopy.go | 59 +++++-
...re.cluster.x-k8s.io_openstackclusters.yaml | 164 +++++++++++----
...er.x-k8s.io_openstackclustertemplates.yaml | 87 +++++---
...re.cluster.x-k8s.io_openstackmachines.yaml | 160 +++++++++++----
...er.x-k8s.io_openstackmachinetemplates.yaml | 82 ++++++--
docs/book/src/api/v1beta1/api.md | 71 +++++--
.../topics/crd-changes/v1alpha7-to-v1beta1.md | 17 +-
pkg/cloud/services/networking/port.go | 35 ++--
pkg/cloud/services/networking/port_test.go | 71 ++++---
pkg/utils/optional/conversion.go | 43 ++++
pkg/utils/optional/types.go | 22 +++
test/e2e/suites/e2e/e2e_test.go | 6 +-
26 files changed, 1441 insertions(+), 371 deletions(-)
create mode 100644 pkg/utils/optional/conversion.go
create mode 100644 pkg/utils/optional/types.go
diff --git a/.golangci.yml b/.golangci.yml
index 5fc2435fb4..944b2ad9fc 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -168,11 +168,10 @@ 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$
run:
timeout: 10m
diff --git a/Makefile b/Makefile
index 172fb11c2e..e33ce59c68 100644
--- a/Makefile
+++ b/Makefile
@@ -265,6 +265,7 @@ generate-conversion-gen: $(CONVERSION_GEN)
--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 \
--output-file-base=zz_generated.conversion \
--trim-path-prefix=$(capo_module)/ \
--go-header-file=./hack/boilerplate/boilerplate.generatego.txt
diff --git a/api/v1alpha5/conversion.go b/api/v1alpha5/conversion.go
index 49536451c3..14302a23ea 100644
--- a/api/v1alpha5/conversion.go
+++ b/api/v1alpha5/conversion.go
@@ -272,11 +272,29 @@ func Convert_v1beta1_PortOpts_To_v1alpha5_PortOpts(in *infrav1.PortOpts, out *Po
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 {
+ securityGroupParam := &out.SecurityGroupFilters[i]
+ if in.SecurityGroups[i].ID != "" {
+ securityGroupParam.UUID = in.SecurityGroups[i].ID
+ } else {
+ if err := Convert_v1beta1_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(&in.SecurityGroups[i], &securityGroupParam.Filter, s); err != nil {
+ return err
+ }
+ }
+ }
+ }
+
out.Profile = make(map[string]string)
- if in.Profile.OVSHWOffload {
+ if pointer.BoolDeref(in.Profile.OVSHWOffload, false) {
(out.Profile)["capabilities"] = "[\"switchdev\"]"
}
- if in.Profile.TrustedVF {
+ if pointer.BoolDeref(in.Profile.TrustedVF, false) {
(out.Profile)["trusted"] = trueString
}
return nil
@@ -318,12 +336,56 @@ func Convert_v1alpha5_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *infrav1.Po
return err
}
+ if len(in.SecurityGroups) > 0 || len(in.SecurityGroupFilters) > 0 {
+ out.SecurityGroups = make([]infrav1.SecurityGroupFilter, 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.SecurityGroupFilter{ID: sgParam.UUID})
+ case sgParam.Name != "":
+ out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupFilter{Name: sgParam.Name})
+ case sgParam.Filter != (SecurityGroupFilter{}):
+ out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupFilter{})
+ outSG := &out.SecurityGroups[len(out.SecurityGroups)-1]
+ if err := Convert_v1alpha5_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(&sgParam.Filter, outSG, s); err != nil {
+ return err
+ }
+ }
+ }
+ for _, id := range in.SecurityGroups {
+ out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupFilter{ID: id})
+ }
+ }
+
+ if len(in.SecurityGroups) > 0 || len(in.SecurityGroupFilters) > 0 {
+ out.SecurityGroups = make([]infrav1.SecurityGroupFilter, 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.SecurityGroupFilter{ID: sgParam.UUID})
+ case sgParam.Name != "":
+ out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupFilter{Name: sgParam.Name})
+ case sgParam.Filter != (SecurityGroupFilter{}):
+ out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupFilter{})
+ outSG := &out.SecurityGroups[len(out.SecurityGroups)-1]
+ if err := Convert_v1alpha5_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(&sgParam.Filter, outSG, s); err != nil {
+ return err
+ }
+ }
+ }
+ for _, id := range in.SecurityGroups {
+ out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupFilter{ID: id})
+ }
+ }
+
// Profile is now a struct in v1beta1.
if strings.Contains(in.Profile["capabilities"], "switchdev") {
- out.Profile.OVSHWOffload = true
+ out.Profile.OVSHWOffload = pointer.Bool(true)
}
if in.Profile["trusted"] == trueString {
- out.Profile.TrustedVF = true
+ out.Profile.TrustedVF = pointer.Bool(true)
}
return nil
}
@@ -460,21 +522,21 @@ func Convert_Map_string_To_Interface_To_v1beta1_BindingProfile(in map[string]str
for k, v := range in {
if k == "capabilities" {
if strings.Contains(v, "switchdev") {
- out.OVSHWOffload = true
+ out.OVSHWOffload = pointer.Bool(true)
}
}
if k == "trusted" && v == trueString {
- out.TrustedVF = true
+ out.TrustedVF = pointer.Bool(true)
}
}
return nil
}
func Convert_v1beta1_BindingProfile_To_Map_string_To_Interface(in *infrav1.BindingProfile, out map[string]string, _ conversion.Scope) error {
- if in.OVSHWOffload {
+ if pointer.BoolDeref(in.OVSHWOffload, false) {
(out)["capabilities"] = "[\"switchdev\"]"
}
- if in.TrustedVF {
+ if pointer.BoolDeref(in.TrustedVF, false) {
(out)["trusted"] = trueString
}
return nil
diff --git a/api/v1alpha5/types.go b/api/v1alpha5/types.go
index fd3a58e240..2138b47560 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.
diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go
index 95c46f3eb3..b3f06aaa61 100644
--- a/api/v1alpha5/zz_generated.conversion.go
+++ b/api/v1alpha5/zz_generated.conversion.go
@@ -27,7 +27,9 @@ import (
v1 "k8s.io/api/core/v1"
conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime"
+ 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"
)
@@ -424,7 +426,9 @@ func autoConvert_v1beta1_APIServerLoadBalancer_To_v1alpha5_APIServerLoadBalancer
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
}
@@ -435,7 +439,9 @@ func Convert_v1alpha5_AddressPair_To_v1beta1_AddressPair(in *AddressPair, out *v
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
}
@@ -491,7 +497,9 @@ func Convert_v1beta1_ExternalRouterIPParam_To_v1alpha5_ExternalRouterIPParam(in
func autoConvert_v1alpha5_FixedIP_To_v1beta1_FixedIP(in *FixedIP, out *v1beta1.FixedIP, s conversion.Scope) error {
out.Subnet = (*v1beta1.SubnetFilter)(unsafe.Pointer(in.Subnet))
- out.IPAddress = in.IPAddress
+ if err := optional.Convert_string_To_optional_String(&in.IPAddress, &out.IPAddress, s); err != nil {
+ return err
+ }
return nil
}
@@ -502,7 +510,9 @@ func Convert_v1alpha5_FixedIP_To_v1beta1_FixedIP(in *FixedIP, out *v1beta1.Fixed
func autoConvert_v1beta1_FixedIP_To_v1alpha5_FixedIP(in *v1beta1.FixedIP, out *FixedIP, s conversion.Scope) error {
out.Subnet = (*SubnetFilter)(unsafe.Pointer(in.Subnet))
- out.IPAddress = in.IPAddress
+ if err := optional.Convert_optional_String_To_string(&in.IPAddress, &out.IPAddress, s); err != nil {
+ return err
+ }
return nil
}
@@ -1329,30 +1339,50 @@ func Convert_v1beta1_OpenStackMachineTemplateSpec_To_v1alpha5_OpenStackMachineTe
func autoConvert_v1alpha5_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *v1beta1.PortOpts, s conversion.Scope) error {
out.Network = (*v1beta1.NetworkFilter)(unsafe.Pointer(in.Network))
- out.NameSuffix = in.NameSuffix
- out.Description = in.Description
+ 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
+ }
out.AdminStateUp = (*bool)(unsafe.Pointer(in.AdminStateUp))
- out.MACAddress = in.MACAddress
- out.FixedIPs = *(*[]v1beta1.FixedIP)(unsafe.Pointer(&in.FixedIPs))
+ if err := optional.Convert_string_To_optional_String(&in.MACAddress, &out.MACAddress, s); err != nil {
+ return err
+ }
+ if in.FixedIPs != nil {
+ in, out := &in.FixedIPs, &out.FixedIPs
+ *out = make([]v1beta1.FixedIP, len(*in))
+ for i := range *in {
+ if err := Convert_v1alpha5_FixedIP_To_v1beta1_FixedIP(&(*in)[i], &(*out)[i], s); err != nil {
+ return err
+ }
+ }
+ } else {
+ out.FixedIPs = nil
+ }
// 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([]v1beta1.SecurityGroupFilter, len(*in))
+ // INFO: in.SecurityGroups opted out of conversion generation
+ // INFO: in.SecurityGroupFilters opted out of conversion generation
+ if in.AllowedAddressPairs != nil {
+ in, out := &in.AllowedAddressPairs, &out.AllowedAddressPairs
+ *out = make([]v1beta1.AddressPair, len(*in))
for i := range *in {
- if err := Convert_v1alpha5_SecurityGroupParam_To_v1beta1_SecurityGroupFilter(&(*in)[i], &(*out)[i], s); err != nil {
+ if err := Convert_v1alpha5_AddressPair_To_v1beta1_AddressPair(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
- out.SecurityGroupFilters = nil
+ out.AllowedAddressPairs = nil
}
- out.AllowedAddressPairs = *(*[]v1beta1.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 (map[string]string vs sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.BindingProfile)
+ if err := optional.Convert_string_To_optional_String(&in.HostID, &out.HostID, s); err != nil {
+ return err
+ }
+ if err := optional.Convert_string_To_optional_String(&in.VNICType, &out.VNICType, s); err != nil {
+ return err
+ }
+ // WARNING: in.Profile requires manual conversion: inconvertible types (map[string]string vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.BindingProfile)
out.DisablePortSecurity = (*bool)(unsafe.Pointer(in.DisablePortSecurity))
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
return nil
@@ -1360,27 +1390,57 @@ func autoConvert_v1alpha5_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *v1beta
func autoConvert_v1beta1_PortOpts_To_v1alpha5_PortOpts(in *v1beta1.PortOpts, out *PortOpts, s conversion.Scope) error {
out.Network = (*NetworkFilter)(unsafe.Pointer(in.Network))
- out.NameSuffix = in.NameSuffix
- out.Description = in.Description
+ if err := optional.Convert_optional_String_To_string(&in.NameSuffix, &out.NameSuffix, s); err != nil {
+ return err
+ }
+ if err := optional.Convert_optional_String_To_string(&in.Description, &out.Description, s); err != nil {
+ return err
+ }
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))
+ if err := optional.Convert_optional_String_To_string(&in.MACAddress, &out.MACAddress, 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_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.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_SecurityGroupFilter_To_string(&(*in)[i], &(*out)[i], s); err != nil {
+ return err
+ }
+ }
+ } else {
+ out.SecurityGroups = nil
+ }
+ if in.AllowedAddressPairs != nil {
+ in, out := &in.AllowedAddressPairs, &out.AllowedAddressPairs
+ *out = make([]AddressPair, len(*in))
+ for i := range *in {
+ if err := Convert_v1beta1_AddressPair_To_v1alpha5_AddressPair(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
- out.SecurityGroupFilters = nil
+ out.AllowedAddressPairs = 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/v1beta1.BindingProfile vs map[string]string)
+ if err := optional.Convert_optional_String_To_string(&in.HostID, &out.HostID, s); err != nil {
+ return err
+ }
+ if err := optional.Convert_optional_String_To_string(&in.VNICType, &out.VNICType, s); err != nil {
+ return err
+ }
+ // WARNING: in.Profile requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.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))
diff --git a/api/v1alpha6/conversion.go b/api/v1alpha6/conversion.go
index bb055369d1..13a7c8f98d 100644
--- a/api/v1alpha6/conversion.go
+++ b/api/v1alpha6/conversion.go
@@ -671,39 +671,93 @@ func Convert_v1alpha6_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *O
}
func Convert_v1alpha6_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *infrav1.PortOpts, s apiconversion.Scope) error {
- err := autoConvert_v1alpha6_PortOpts_To_v1beta1_PortOpts(in, out, s)
- if err != nil {
+ if err := autoConvert_v1alpha6_PortOpts_To_v1beta1_PortOpts(in, out, s); err != nil {
return err
}
- // SecurityGroups are removed in v1beta1 without replacement. SecurityGroupFilters can be used instead.
- for i := range in.SecurityGroups {
- out.SecurityGroupFilters = append(out.SecurityGroupFilters, infrav1.SecurityGroupFilter{ID: in.SecurityGroups[i]})
+
+ if len(in.SecurityGroups) > 0 || len(in.SecurityGroupFilters) > 0 {
+ out.SecurityGroups = make([]infrav1.SecurityGroupFilter, 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.SecurityGroupFilter{ID: sgParam.UUID})
+ case sgParam.Name != "":
+ out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupFilter{Name: sgParam.Name})
+ case sgParam.Filter != (SecurityGroupFilter{}):
+ out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupFilter{})
+ outSG := &out.SecurityGroups[len(out.SecurityGroups)-1]
+ if err := Convert_v1alpha6_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(&sgParam.Filter, outSG, s); err != nil {
+ return err
+ }
+ }
+ }
+ for _, id := range in.SecurityGroups {
+ out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupFilter{ID: id})
+ }
}
// Profile is now a struct in v1beta1.
+ var ovsHWOffload, trustedVF bool
if strings.Contains(in.Profile["capabilities"], "switchdev") {
- out.Profile.OVSHWOffload = true
+ ovsHWOffload = true
}
if in.Profile["trusted"] == trueString {
- out.Profile.TrustedVF = true
+ 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_SecurityGroupFilter_To_string(in *infrav1.SecurityGroupFilter, out *string, _ apiconversion.Scope) error {
+ if in.ID != "" {
+ *out = in.ID
}
return nil
}
func Convert_v1beta1_PortOpts_To_v1alpha6_PortOpts(in *infrav1.PortOpts, out *PortOpts, s apiconversion.Scope) error {
- // value specs and propagate uplink status have been added in v1beta1 but have no equivalent in v1alpha5
- err := autoConvert_v1beta1_PortOpts_To_v1alpha6_PortOpts(in, out, s)
- if err != nil {
+ if err := autoConvert_v1beta1_PortOpts_To_v1alpha6_PortOpts(in, out, s); 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 {
+ securityGroupParam := &out.SecurityGroupFilters[i]
+ if in.SecurityGroups[i].ID != "" {
+ securityGroupParam.UUID = in.SecurityGroups[i].ID
+ } else {
+ if err := Convert_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(&in.SecurityGroups[i], &securityGroupParam.Filter, s); err != nil {
+ return err
+ }
+ }
+ }
}
- if in.Profile.TrustedVF {
- (out.Profile)["trusted"] = trueString
+
+ if in.Profile != nil {
+ out.Profile = make(map[string]string)
+ if pointer.BoolDeref(in.Profile.OVSHWOffload, false) {
+ (out.Profile)["capabilities"] = "[\"switchdev\"]"
+ }
+ if pointer.BoolDeref(in.Profile.TrustedVF, false) {
+ (out.Profile)["trusted"] = trueString
+ }
}
+
return nil
}
@@ -837,21 +891,21 @@ func Convert_Map_string_To_Interface_To_v1beta1_BindingProfile(in map[string]str
for k, v := range in {
if k == "capabilities" {
if strings.Contains(v, "switchdev") {
- out.OVSHWOffload = true
+ out.OVSHWOffload = pointer.Bool(true)
}
}
if k == "trusted" && v == trueString {
- out.TrustedVF = true
+ out.TrustedVF = pointer.Bool(true)
}
}
return nil
}
func Convert_v1beta1_BindingProfile_To_Map_string_To_Interface(in *infrav1.BindingProfile, out map[string]string, _ apiconversion.Scope) error {
- if in.OVSHWOffload {
+ if pointer.BoolDeref(in.OVSHWOffload, false) {
(out)["capabilities"] = "[\"switchdev\"]"
}
- if in.TrustedVF {
+ if pointer.BoolDeref(in.TrustedVF, false) {
(out)["trusted"] = trueString
}
return nil
diff --git a/api/v1alpha6/conversion_test.go b/api/v1alpha6/conversion_test.go
index acfb73ce07..e443f5418d 100644
--- a/api/v1alpha6/conversion_test.go
+++ b/api/v1alpha6/conversion_test.go
@@ -19,6 +19,7 @@ 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"
@@ -494,8 +495,8 @@ func TestPortOptsConvertTo(t *testing.T) {
"trusted": "true",
}
convertedPortProfile := infrav1.BindingProfile{
- OVSHWOffload: true,
- TrustedVF: true,
+ OVSHWOffload: pointer.Bool(true),
+ TrustedVF: pointer.Bool(true),
}
tests := []struct {
@@ -513,8 +514,8 @@ func TestPortOptsConvertTo(t *testing.T) {
SecurityGroups: uuids,
}},
hubPortOpts: []infrav1.PortOpts{{
- Profile: convertedPortProfile,
- SecurityGroupFilters: securityGroupsUuids,
+ Profile: &convertedPortProfile,
+ SecurityGroups: securityGroupsUuids,
}},
},
{
@@ -525,10 +526,15 @@ func TestPortOptsConvertTo(t *testing.T) {
SecurityGroupFilters: securityGroupFilter,
}},
hubPortOpts: []infrav1.PortOpts{{
- Profile: convertedPortProfile,
- SecurityGroupFilters: securityGroupFilterMerged,
+ Profile: &convertedPortProfile,
+ SecurityGroups: securityGroupFilterMerged,
}},
},
+ {
+ name: "Empty port",
+ spokePortOpts: []PortOpts{{}},
+ hubPortOpts: []infrav1.PortOpts{{}},
+ },
}
for _, tt := range tests {
@@ -558,7 +564,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))
})
}
}
@@ -709,9 +715,68 @@ func TestConvert_v1alpha6_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(t
t.Run(tt.name, func(t *testing.T) {
g := gomega.NewWithT(t)
out := &infrav1.OpenStackClusterSpec{}
- err := Convert_v1alpha6_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(tt.in, out, nil)
+ 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).To(gomega.Equal(tt.expectedOut))
+ g.Expect(&out.Template.Spec).To(gomega.Equal(tt.expectedOut), cmp.Diff(&out.Template.Spec, tt.expectedOut))
})
}
}
diff --git a/api/v1alpha6/types.go b/api/v1alpha6/types.go
index 0301d8d8cc..d37136490c 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.
diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go
index 127d71cd8c..489889727b 100644
--- a/api/v1alpha6/zz_generated.conversion.go
+++ b/api/v1alpha6/zz_generated.conversion.go
@@ -28,6 +28,7 @@ import (
conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime"
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"
)
@@ -394,6 +395,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
+ if err := s.AddConversionFunc((*v1beta1.SecurityGroupFilter)(nil), (*string)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1beta1_SecurityGroupFilter_To_string(a.(*v1beta1.SecurityGroupFilter), b.(*string), scope)
+ }); err != nil {
+ return err
+ }
if err := s.AddConversionFunc((*v1beta1.SecurityGroupFilter)(nil), (*SecurityGroupParam)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupParam(a.(*v1beta1.SecurityGroupFilter), b.(*SecurityGroupParam), scope)
}); err != nil {
@@ -440,7 +446,9 @@ func Convert_v1beta1_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalancer(in
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
}
@@ -451,7 +459,9 @@ func Convert_v1alpha6_AddressPair_To_v1beta1_AddressPair(in *AddressPair, out *v
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
}
@@ -507,7 +517,9 @@ func Convert_v1beta1_ExternalRouterIPParam_To_v1alpha6_ExternalRouterIPParam(in
func autoConvert_v1alpha6_FixedIP_To_v1beta1_FixedIP(in *FixedIP, out *v1beta1.FixedIP, s conversion.Scope) error {
out.Subnet = (*v1beta1.SubnetFilter)(unsafe.Pointer(in.Subnet))
- out.IPAddress = in.IPAddress
+ if err := optional.Convert_string_To_optional_String(&in.IPAddress, &out.IPAddress, s); err != nil {
+ return err
+ }
return nil
}
@@ -518,7 +530,9 @@ func Convert_v1alpha6_FixedIP_To_v1beta1_FixedIP(in *FixedIP, out *v1beta1.Fixed
func autoConvert_v1beta1_FixedIP_To_v1alpha6_FixedIP(in *v1beta1.FixedIP, out *FixedIP, s conversion.Scope) error {
out.Subnet = (*SubnetFilter)(unsafe.Pointer(in.Subnet))
- out.IPAddress = in.IPAddress
+ if err := optional.Convert_optional_String_To_string(&in.IPAddress, &out.IPAddress, s); err != nil {
+ return err
+ }
return nil
}
@@ -1352,30 +1366,50 @@ func Convert_v1beta1_OpenStackMachineTemplateSpec_To_v1alpha6_OpenStackMachineTe
func autoConvert_v1alpha6_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *v1beta1.PortOpts, s conversion.Scope) error {
out.Network = (*v1beta1.NetworkFilter)(unsafe.Pointer(in.Network))
- out.NameSuffix = in.NameSuffix
- out.Description = in.Description
+ 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
+ }
out.AdminStateUp = (*bool)(unsafe.Pointer(in.AdminStateUp))
- out.MACAddress = in.MACAddress
- out.FixedIPs = *(*[]v1beta1.FixedIP)(unsafe.Pointer(&in.FixedIPs))
+ if err := optional.Convert_string_To_optional_String(&in.MACAddress, &out.MACAddress, s); err != nil {
+ return err
+ }
+ if in.FixedIPs != nil {
+ in, out := &in.FixedIPs, &out.FixedIPs
+ *out = make([]v1beta1.FixedIP, len(*in))
+ for i := range *in {
+ if err := Convert_v1alpha6_FixedIP_To_v1beta1_FixedIP(&(*in)[i], &(*out)[i], s); err != nil {
+ return err
+ }
+ }
+ } else {
+ out.FixedIPs = nil
+ }
// 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([]v1beta1.SecurityGroupFilter, len(*in))
+ // INFO: in.SecurityGroups opted out of conversion generation
+ // INFO: in.SecurityGroupFilters opted out of conversion generation
+ if in.AllowedAddressPairs != nil {
+ in, out := &in.AllowedAddressPairs, &out.AllowedAddressPairs
+ *out = make([]v1beta1.AddressPair, len(*in))
for i := range *in {
- if err := Convert_v1alpha6_SecurityGroupParam_To_v1beta1_SecurityGroupFilter(&(*in)[i], &(*out)[i], s); err != nil {
+ if err := Convert_v1alpha6_AddressPair_To_v1beta1_AddressPair(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
- out.SecurityGroupFilters = nil
+ out.AllowedAddressPairs = nil
}
- out.AllowedAddressPairs = *(*[]v1beta1.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 (map[string]string vs sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.BindingProfile)
+ if err := optional.Convert_string_To_optional_String(&in.HostID, &out.HostID, s); err != nil {
+ return err
+ }
+ if err := optional.Convert_string_To_optional_String(&in.VNICType, &out.VNICType, s); err != nil {
+ return err
+ }
+ // WARNING: in.Profile requires manual conversion: inconvertible types (map[string]string vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.BindingProfile)
out.DisablePortSecurity = (*bool)(unsafe.Pointer(in.DisablePortSecurity))
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
out.ValueSpecs = *(*[]v1beta1.ValueSpec)(unsafe.Pointer(&in.ValueSpecs))
@@ -1384,27 +1418,57 @@ func autoConvert_v1alpha6_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *v1beta
func autoConvert_v1beta1_PortOpts_To_v1alpha6_PortOpts(in *v1beta1.PortOpts, out *PortOpts, s conversion.Scope) error {
out.Network = (*NetworkFilter)(unsafe.Pointer(in.Network))
- out.NameSuffix = in.NameSuffix
- out.Description = in.Description
+ if err := optional.Convert_optional_String_To_string(&in.NameSuffix, &out.NameSuffix, s); err != nil {
+ return err
+ }
+ if err := optional.Convert_optional_String_To_string(&in.Description, &out.Description, s); err != nil {
+ return err
+ }
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))
+ if err := optional.Convert_optional_String_To_string(&in.MACAddress, &out.MACAddress, 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_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.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_SecurityGroupFilter_To_string(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
- out.SecurityGroupFilters = nil
+ out.SecurityGroups = nil
+ }
+ if in.AllowedAddressPairs != nil {
+ in, out := &in.AllowedAddressPairs, &out.AllowedAddressPairs
+ *out = make([]AddressPair, len(*in))
+ for i := range *in {
+ if err := Convert_v1beta1_AddressPair_To_v1alpha6_AddressPair(&(*in)[i], &(*out)[i], s); err != nil {
+ return err
+ }
+ }
+ } else {
+ out.AllowedAddressPairs = 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/v1beta1.BindingProfile vs map[string]string)
+ if err := optional.Convert_optional_String_To_string(&in.HostID, &out.HostID, s); err != nil {
+ return err
+ }
+ if err := optional.Convert_optional_String_To_string(&in.VNICType, &out.VNICType, s); err != nil {
+ return err
+ }
+ // WARNING: in.Profile requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.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))
diff --git a/api/v1alpha7/conversion.go b/api/v1alpha7/conversion.go
index ce307ea407..6c3523a862 100644
--- a/api/v1alpha7/conversion.go
+++ b/api/v1alpha7/conversion.go
@@ -192,6 +192,73 @@ func restorev1alpha7MachineSpec(previous *OpenStackMachineSpec, dst *OpenStackMa
func restorev1beta1MachineSpec(previous *infrav1.OpenStackMachineSpec, dst *infrav1.OpenStackMachineSpec) {
dst.ServerGroup = previous.ServerGroup
dst.Image = previous.Image
+
+ if len(dst.Ports) == len(previous.Ports) {
+ for i := range dst.Ports {
+ restorev1beta1Port(&previous.Ports[i], &dst.Ports[i])
+ }
+ }
+}
+
+func restorev1beta1Port(previous *infrav1.PortOpts, dst *infrav1.PortOpts) {
+ if dst.NameSuffix == nil || *dst.NameSuffix == "" {
+ dst.NameSuffix = previous.NameSuffix
+ }
+
+ if dst.Description == nil || *dst.Description == "" {
+ dst.Description = previous.Description
+ }
+
+ if dst.MACAddress == nil || *dst.MACAddress == "" {
+ dst.MACAddress = previous.MACAddress
+ }
+
+ if len(dst.FixedIPs) == len(previous.FixedIPs) {
+ for j := range dst.FixedIPs {
+ prevFixedIP := &previous.FixedIPs[j]
+ dstFixedIP := &dst.FixedIPs[j]
+
+ if dstFixedIP.IPAddress == nil || *dstFixedIP.IPAddress == "" {
+ dstFixedIP.IPAddress = prevFixedIP.IPAddress
+ }
+ }
+ }
+
+ if len(dst.AllowedAddressPairs) == len(previous.AllowedAddressPairs) {
+ for j := range dst.AllowedAddressPairs {
+ prevAAP := &previous.AllowedAddressPairs[j]
+ dstAAP := &dst.AllowedAddressPairs[j]
+
+ if dstAAP.MACAddress == nil || *dstAAP.MACAddress == "" {
+ dstAAP.MACAddress = prevAAP.MACAddress
+ }
+ }
+ }
+
+ if dst.HostID == nil || *dst.HostID == "" {
+ dst.HostID = previous.HostID
+ }
+
+ if dst.VNICType == nil || *dst.VNICType == "" {
+ dst.VNICType = previous.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
+ }
+ }
}
func restorev1beta1Bastion(previous **infrav1.Bastion, dst **infrav1.Bastion) {
@@ -701,3 +768,50 @@ func Convert_v1alpha7_OpenStackIdentityReference_To_v1beta1_OpenStackIdentityRef
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)
}
+
+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
+ }
+
+ if len(in.SecurityGroupFilters) > 0 {
+ out.SecurityGroups = make([]infrav1.SecurityGroupFilter, len(in.SecurityGroupFilters))
+ for i := range in.SecurityGroupFilters {
+ if err := autoConvert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(&in.SecurityGroupFilters[i], &out.SecurityGroups[i], s); err != nil {
+ return err
+ }
+ }
+ }
+
+ if in.Profile != (BindingProfile{}) {
+ out.Profile = &infrav1.BindingProfile{}
+ if err := autoConvert_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
+ }
+
+ if len(in.SecurityGroups) > 0 {
+ out.SecurityGroupFilters = make([]SecurityGroupFilter, len(in.SecurityGroups))
+ for i := range in.SecurityGroups {
+ if err := autoConvert_v1beta1_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(&in.SecurityGroups[i], &out.SecurityGroupFilters[i], s); err != nil {
+ return err
+ }
+ }
+ }
+
+ if in.Profile != nil {
+ if err := autoConvert_v1beta1_BindingProfile_To_v1alpha7_BindingProfile(in.Profile, &out.Profile, s); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
diff --git a/api/v1alpha7/conversion_test.go b/api/v1alpha7/conversion_test.go
index 25fcc253fa..964b89771b 100644
--- a/api/v1alpha7/conversion_test.go
+++ b/api/v1alpha7/conversion_test.go
@@ -19,6 +19,7 @@ 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"
@@ -324,9 +325,68 @@ func TestConvert_v1alpha7_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(t
t.Run(tt.name, func(t *testing.T) {
g := gomega.NewWithT(t)
out := &infrav1.OpenStackClusterSpec{}
- err := Convert_v1alpha7_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(tt.in, out, nil)
+ 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))
+ 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))
})
}
}
diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go
index 2e913f05fc..e99f7f7557 100644
--- a/api/v1alpha7/zz_generated.conversion.go
+++ b/api/v1alpha7/zz_generated.conversion.go
@@ -24,10 +24,12 @@ package v1alpha7
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"
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"
)
@@ -299,16 +301,6 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*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 {
@@ -399,6 +391,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); 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((*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 {
@@ -434,6 +431,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); 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.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 {
@@ -498,7 +500,9 @@ func Convert_v1beta1_AdditionalBlockDevice_To_v1alpha7_AdditionalBlockDevice(in
func autoConvert_v1alpha7_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
}
@@ -509,7 +513,9 @@ func Convert_v1alpha7_AddressPair_To_v1beta1_AddressPair(in *AddressPair, out *v
func autoConvert_v1beta1_AddressPair_To_v1alpha7_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
}
@@ -565,8 +571,12 @@ func autoConvert_v1beta1_BastionStatus_To_v1alpha7_BastionStatus(in *v1beta1.Bas
}
func autoConvert_v1alpha7_BindingProfile_To_v1beta1_BindingProfile(in *BindingProfile, out *v1beta1.BindingProfile, s conversion.Scope) error {
- out.OVSHWOffload = in.OVSHWOffload
- out.TrustedVF = in.TrustedVF
+ 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
}
@@ -576,8 +586,12 @@ func Convert_v1alpha7_BindingProfile_To_v1beta1_BindingProfile(in *BindingProfil
}
func autoConvert_v1beta1_BindingProfile_To_v1alpha7_BindingProfile(in *v1beta1.BindingProfile, out *BindingProfile, s conversion.Scope) error {
- out.OVSHWOffload = in.OVSHWOffload
- out.TrustedVF = in.TrustedVF
+ 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
}
@@ -658,7 +672,9 @@ func Convert_v1beta1_ExternalRouterIPParam_To_v1alpha7_ExternalRouterIPParam(in
func autoConvert_v1alpha7_FixedIP_To_v1beta1_FixedIP(in *FixedIP, out *v1beta1.FixedIP, s conversion.Scope) error {
out.Subnet = (*v1beta1.SubnetFilter)(unsafe.Pointer(in.Subnet))
- out.IPAddress = in.IPAddress
+ if err := optional.Convert_string_To_optional_String(&in.IPAddress, &out.IPAddress, s); err != nil {
+ return err
+ }
return nil
}
@@ -669,7 +685,9 @@ func Convert_v1alpha7_FixedIP_To_v1beta1_FixedIP(in *FixedIP, out *v1beta1.Fixed
func autoConvert_v1beta1_FixedIP_To_v1alpha7_FixedIP(in *v1beta1.FixedIP, out *FixedIP, s conversion.Scope) error {
out.Subnet = (*SubnetFilter)(unsafe.Pointer(in.Subnet))
- out.IPAddress = in.IPAddress
+ if err := optional.Convert_optional_String_To_string(&in.IPAddress, &out.IPAddress, s); err != nil {
+ return err
+ }
return nil
}
@@ -1274,7 +1292,17 @@ func autoConvert_v1alpha7_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(i
// WARNING: in.Image requires manual conversion: inconvertible types (string vs sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ImageFilter)
// WARNING: in.ImageUUID requires manual conversion: does not exist in peer-type
out.SSHKeyName = in.SSHKeyName
- out.Ports = *(*[]v1beta1.PortOpts)(unsafe.Pointer(&in.Ports))
+ 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
out.SecurityGroups = *(*[]v1beta1.SecurityGroupFilter)(unsafe.Pointer(&in.SecurityGroups))
out.Trunk = in.Trunk
@@ -1303,7 +1331,17 @@ func autoConvert_v1beta1_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(i
out.Flavor = in.Flavor
// WARNING: in.Image requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ImageFilter vs string)
out.SSHKeyName = in.SSHKeyName
- out.Ports = *(*[]PortOpts)(unsafe.Pointer(&in.Ports))
+ 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
+ }
out.SecurityGroups = *(*[]SecurityGroupFilter)(unsafe.Pointer(&in.SecurityGroups))
out.Trunk = in.Trunk
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
@@ -1326,7 +1364,7 @@ func autoConvert_v1beta1_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(i
func autoConvert_v1alpha7_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.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))
@@ -1341,7 +1379,7 @@ func Convert_v1alpha7_OpenStackMachineStatus_To_v1beta1_OpenStackMachineStatus(i
func autoConvert_v1beta1_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStatus(in *v1beta1.OpenStackMachineStatus, out *OpenStackMachineStatus, s conversion.Scope) error {
out.Ready = in.Ready
- out.Addresses = *(*[]v1.NodeAddress)(unsafe.Pointer(&in.Addresses))
+ out.Addresses = *(*[]corev1.NodeAddress)(unsafe.Pointer(&in.Addresses))
out.InstanceState = (*InstanceState)(unsafe.Pointer(in.InstanceState))
// WARNING: in.ReferencedResources requires manual conversion: does not exist in peer-type
// WARNING: in.DependentResources requires manual conversion: does not exist in peer-type
@@ -1469,19 +1507,47 @@ func Convert_v1beta1_OpenStackMachineTemplateSpec_To_v1alpha7_OpenStackMachineTe
func autoConvert_v1alpha7_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *v1beta1.PortOpts, s conversion.Scope) error {
out.Network = (*v1beta1.NetworkFilter)(unsafe.Pointer(in.Network))
- out.NameSuffix = in.NameSuffix
- out.Description = in.Description
+ 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
+ }
out.AdminStateUp = (*bool)(unsafe.Pointer(in.AdminStateUp))
- out.MACAddress = in.MACAddress
- out.FixedIPs = *(*[]v1beta1.FixedIP)(unsafe.Pointer(&in.FixedIPs))
- out.SecurityGroupFilters = *(*[]v1beta1.SecurityGroupFilter)(unsafe.Pointer(&in.SecurityGroupFilters))
- out.AllowedAddressPairs = *(*[]v1beta1.AddressPair)(unsafe.Pointer(&in.AllowedAddressPairs))
+ if err := optional.Convert_string_To_optional_String(&in.MACAddress, &out.MACAddress, s); err != nil {
+ return err
+ }
+ 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
+ if in.AllowedAddressPairs != nil {
+ in, out := &in.AllowedAddressPairs, &out.AllowedAddressPairs
+ *out = make([]v1beta1.AddressPair, len(*in))
+ for i := range *in {
+ if err := Convert_v1alpha7_AddressPair_To_v1beta1_AddressPair(&(*in)[i], &(*out)[i], s); err != nil {
+ return err
+ }
+ }
+ } else {
+ out.AllowedAddressPairs = nil
+ }
out.Trunk = (*bool)(unsafe.Pointer(in.Trunk))
- out.HostID = in.HostID
- out.VNICType = in.VNICType
- if err := Convert_v1alpha7_BindingProfile_To_v1beta1_BindingProfile(&in.Profile, &out.Profile, s); err != nil {
+ if err := optional.Convert_string_To_optional_String(&in.HostID, &out.HostID, s); err != nil {
+ return err
+ }
+ if err := optional.Convert_string_To_optional_String(&in.VNICType, &out.VNICType, s); err != nil {
return err
}
+ // WARNING: in.Profile requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7.BindingProfile vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.BindingProfile)
out.DisablePortSecurity = (*bool)(unsafe.Pointer(in.DisablePortSecurity))
out.PropagateUplinkStatus = (*bool)(unsafe.Pointer(in.PropagateUplinkStatus))
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
@@ -1489,26 +1555,49 @@ func autoConvert_v1alpha7_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *v1beta
return nil
}
-// Convert_v1alpha7_PortOpts_To_v1beta1_PortOpts is an autogenerated conversion function.
-func Convert_v1alpha7_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *v1beta1.PortOpts, s conversion.Scope) error {
- return autoConvert_v1alpha7_PortOpts_To_v1beta1_PortOpts(in, out, s)
-}
-
func autoConvert_v1beta1_PortOpts_To_v1alpha7_PortOpts(in *v1beta1.PortOpts, out *PortOpts, s conversion.Scope) error {
out.Network = (*NetworkFilter)(unsafe.Pointer(in.Network))
- out.NameSuffix = in.NameSuffix
- out.Description = in.Description
+ if err := optional.Convert_optional_String_To_string(&in.NameSuffix, &out.NameSuffix, s); err != nil {
+ return err
+ }
+ if err := optional.Convert_optional_String_To_string(&in.Description, &out.Description, s); err != nil {
+ return err
+ }
out.AdminStateUp = (*bool)(unsafe.Pointer(in.AdminStateUp))
- out.MACAddress = in.MACAddress
- out.FixedIPs = *(*[]FixedIP)(unsafe.Pointer(&in.FixedIPs))
- out.SecurityGroupFilters = *(*[]SecurityGroupFilter)(unsafe.Pointer(&in.SecurityGroupFilters))
- out.AllowedAddressPairs = *(*[]AddressPair)(unsafe.Pointer(&in.AllowedAddressPairs))
+ if err := optional.Convert_optional_String_To_string(&in.MACAddress, &out.MACAddress, 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
+ if in.AllowedAddressPairs != nil {
+ in, out := &in.AllowedAddressPairs, &out.AllowedAddressPairs
+ *out = make([]AddressPair, len(*in))
+ for i := range *in {
+ if err := Convert_v1beta1_AddressPair_To_v1alpha7_AddressPair(&(*in)[i], &(*out)[i], s); err != nil {
+ return err
+ }
+ }
+ } else {
+ out.AllowedAddressPairs = nil
+ }
out.Trunk = (*bool)(unsafe.Pointer(in.Trunk))
- out.HostID = in.HostID
- out.VNICType = in.VNICType
- if err := Convert_v1beta1_BindingProfile_To_v1alpha7_BindingProfile(&in.Profile, &out.Profile, s); err != nil {
+ if err := optional.Convert_optional_String_To_string(&in.HostID, &out.HostID, s); err != nil {
+ return err
+ }
+ if err := optional.Convert_optional_String_To_string(&in.VNICType, &out.VNICType, s); err != nil {
return err
}
+ // WARNING: in.Profile requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.BindingProfile vs sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7.BindingProfile)
out.DisablePortSecurity = (*bool)(unsafe.Pointer(in.DisablePortSecurity))
out.PropagateUplinkStatus = (*bool)(unsafe.Pointer(in.PropagateUplinkStatus))
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
@@ -1516,11 +1605,6 @@ func autoConvert_v1beta1_PortOpts_To_v1alpha7_PortOpts(in *v1beta1.PortOpts, out
return nil
}
-// Convert_v1beta1_PortOpts_To_v1alpha7_PortOpts is an autogenerated conversion function.
-func Convert_v1beta1_PortOpts_To_v1alpha7_PortOpts(in *v1beta1.PortOpts, out *PortOpts, s conversion.Scope) error {
- return autoConvert_v1beta1_PortOpts_To_v1alpha7_PortOpts(in, out, s)
-}
-
func autoConvert_v1alpha7_RootVolume_To_v1beta1_RootVolume(in *RootVolume, out *v1beta1.RootVolume, s conversion.Scope) error {
out.Size = in.Size
out.VolumeType = in.VolumeType
diff --git a/api/v1beta1/conversion.go b/api/v1beta1/conversion.go
index ab9d242d42..49f9f8c03c 100644
--- a/api/v1beta1/conversion.go
+++ b/api/v1beta1/conversion.go
@@ -16,7 +16,9 @@ limitations under the License.
package v1beta1
-import "k8s.io/utils/pointer"
+import (
+ "k8s.io/utils/pointer"
+)
// Hub marks OpenStackCluster as a conversion hub.
func (*OpenStackCluster) Hub() {}
diff --git a/api/v1beta1/types.go b/api/v1beta1/types.go
index c96995cd31..ea290a1656 100644
--- a/api/v1beta1/types.go
+++ b/api/v1beta1/types.go
@@ -16,6 +16,10 @@ limitations under the License.
package v1beta1
+import (
+ "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.
@@ -116,42 +120,87 @@ type AllocationPool struct {
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 *NetworkFilter `json:"network,omitempty"`
- // Used to make the name of the port unique. If unspecified, instead the 0-based index of the port in the list is used.
- NameSuffix string `json:"nameSuffix,omitempty"`
- Description string `json:"description,omitempty"`
- AdminStateUp *bool `json:"adminStateUp,omitempty"`
- MACAddress string `json:"macAddress,omitempty"`
- // Specify pairs of subnet and/or IP address. These should be subnets of the network with the given NetworkID.
+
+ // 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"`
+
+ // Description is a human-readable description for the port.
+ // +optional
+ Description optional.String `json:"description,omitempty"`
+
+ // 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"`
+
+ // 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"`
- // The names, uuids, filters or any combination these of the security groups to assign to the instance
- SecurityGroupFilters []SecurityGroupFilter `json:"securityGroupFilters,omitempty"`
- AllowedAddressPairs []AddressPair `json:"allowedAddressPairs,omitempty"`
- // Enables and disables trunk at port level. If not provided, openStackMachine.Spec.Trunk is inherited.
- Trunk *bool `json:"trunk,omitempty"`
- // The ID of the host where the port is allocated
- HostID string `json:"hostId,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 []SecurityGroupFilter `json:"securityGroups,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"`
- // The virtual network interface card (vNIC) type that is bound to the neutron port.
- VNICType string `json:"vnicType,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"`
- // 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
- Profile BindingProfile `json:"profile,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"`
// 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"`
// Value specs are extra parameters to include in the API request with OpenStack.
@@ -171,22 +220,39 @@ type PortStatus struct {
type BindingProfile struct {
// OVSHWOffload enables or disables the OVS hardware offload feature.
- OVSHWOffload bool `json:"ovsHWOffload,omitempty"`
+ // +optional
+ OVSHWOffload *bool `json:"ovsHWOffload,omitempty"`
// TrustedVF enables or disables the “trusted mode” for the VF.
- TrustedVF bool `json:"trustedVF,omitempty"`
+ // +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.
- Subnet *SubnetFilter `json:"subnet"`
- IPAddress string `json:"ipAddress,omitempty"`
+ // +optional
+ Subnet *SubnetFilter `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"`
}
type AddressPair struct {
- IPAddress string `json:"ipAddress,omitempty"`
- MACAddress string `json:"macAddress,omitempty"`
+ // 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 {
diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go
index f9105944fc..4a1265d991 100644
--- a/api/v1beta1/zz_generated.deepcopy.go
+++ b/api/v1beta1/zz_generated.deepcopy.go
@@ -71,6 +71,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.
@@ -134,6 +139,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.
@@ -225,6 +240,11 @@ func (in *FixedIP) DeepCopyInto(out *FixedIP) {
*out = new(SubnetFilter)
**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 FixedIP.
@@ -940,11 +960,26 @@ func (in *PortOpts) DeepCopyInto(out *PortOpts) {
*out = new(NetworkFilter)
**out = **in
}
+ if in.NameSuffix != nil {
+ in, out := &in.NameSuffix, &out.NameSuffix
+ *out = new(string)
+ **out = **in
+ }
+ 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)
**out = **in
}
+ if in.MACAddress != nil {
+ in, out := &in.MACAddress, &out.MACAddress
+ *out = new(string)
+ **out = **in
+ }
if in.FixedIPs != nil {
in, out := &in.FixedIPs, &out.FixedIPs
*out = make([]FixedIP, len(*in))
@@ -952,22 +987,38 @@ func (in *PortOpts) DeepCopyInto(out *PortOpts) {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
- if in.SecurityGroupFilters != nil {
- in, out := &in.SecurityGroupFilters, &out.SecurityGroupFilters
+ if in.SecurityGroups != nil {
+ in, out := &in.SecurityGroups, &out.SecurityGroups
*out = make([]SecurityGroupFilter, len(*in))
copy(*out, *in)
}
if in.AllowedAddressPairs != nil {
in, out := &in.AllowedAddressPairs, &out.AllowedAddressPairs
*out = make([]AddressPair, len(*in))
- copy(*out, *in)
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
}
if in.Trunk != nil {
in, out := &in.Trunk, &out.Trunk
*out = new(bool)
**out = **in
}
- out.Profile = in.Profile
+ 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)
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 948113c887..a6b962ee77 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -5032,17 +5032,37 @@ spec:
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: |-
@@ -5050,12 +5070,17 @@ spec:
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 should be subnets of the network with the given
- NetworkID.
+ 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: |-
@@ -5089,19 +5114,22 @@ spec:
tagsAny:
type: string
type: object
- required:
- - subnet
type: object
type: array
+ x-kubernetes-list-type: atomic
hostId:
- description: The ID of the host where the port is allocated
+ 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: 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: 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: |-
@@ -5127,10 +5155,13 @@ spec:
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
+ 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
@@ -5145,9 +5176,10 @@ spec:
description: PropageteUplinkStatus enables or disables
the propagate uplink status on the port.
type: boolean
- securityGroupFilters:
- description: The names, uuids, filters or any combination
- these of the security groups to assign to the instance
+ 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:
properties:
description:
@@ -5168,6 +5200,7 @@ spec:
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.)
@@ -5177,8 +5210,10 @@ spec:
type: array
x-kubernetes-list-type: set
trunk:
- description: Enables and disables trunk at port level.
- If not provided, openStackMachine.Spec.Trunk is inherited.
+ 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: |-
@@ -5211,8 +5246,15 @@ spec:
- name
x-kubernetes-list-type: map
vnicType:
- description: The virtual network interface card (vNIC)
- type that is bound to the neutron port.
+ 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
@@ -5738,17 +5780,37 @@ spec:
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: |-
@@ -5756,12 +5818,17 @@ spec:
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 should be subnets of the network with the given
- NetworkID.
+ 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: |-
@@ -5795,19 +5862,22 @@ spec:
tagsAny:
type: string
type: object
- required:
- - subnet
type: object
type: array
+ x-kubernetes-list-type: atomic
hostId:
- description: The ID of the host where the port is allocated
+ 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: 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: 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: |-
@@ -5833,10 +5903,13 @@ spec:
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
+ 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
@@ -5851,9 +5924,10 @@ spec:
description: PropageteUplinkStatus enables or disables
the propagate uplink status on the port.
type: boolean
- securityGroupFilters:
- description: The names, uuids, filters or any combination
- these of the security groups to assign to the instance
+ 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:
properties:
description:
@@ -5874,6 +5948,7 @@ spec:
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.)
@@ -5883,8 +5958,10 @@ spec:
type: array
x-kubernetes-list-type: set
trunk:
- description: Enables and disables trunk at port level.
- If not provided, openStackMachine.Spec.Trunk is inherited.
+ 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: |-
@@ -5917,8 +5994,15 @@ spec:
- name
x-kubernetes-list-type: map
vnicType:
- description: The virtual network interface card (vNIC)
- type that is bound to the neutron port.
+ 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
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 048769f3ab..09775b2e75 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -2459,17 +2459,37 @@ spec:
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: |-
@@ -2477,12 +2497,18 @@ spec:
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 should be subnets of the
- network with the given NetworkID.
+ 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: |-
@@ -2516,20 +2542,23 @@ spec:
tagsAny:
type: string
type: object
- required:
- - subnet
type: object
type: array
+ x-kubernetes-list-type: atomic
hostId:
- description: The ID of the host where the port
- is allocated
+ 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: 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: 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: |-
@@ -2555,10 +2584,13 @@ spec:
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
+ 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
@@ -2574,10 +2606,10 @@ spec:
disables the propagate uplink status on the
port.
type: boolean
- securityGroupFilters:
- description: The names, uuids, filters or any
- combination these of the security groups to
- assign to the instance
+ 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:
properties:
description:
@@ -2598,6 +2630,7 @@ spec:
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.)
@@ -2607,9 +2640,10 @@ spec:
type: array
x-kubernetes-list-type: set
trunk:
- description: Enables and disables trunk at port
- level. If not provided, openStackMachine.Spec.Trunk
- is inherited.
+ 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: |-
@@ -2643,8 +2677,15 @@ spec:
- name
x-kubernetes-list-type: map
vnicType:
- description: The virtual network interface card
- (vNIC) type that is bound to the neutron port.
+ 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
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 cb7f8edc39..0270d47c6c 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
@@ -1832,17 +1832,37 @@ spec:
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: |-
@@ -1850,11 +1870,17 @@ spec:
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
- should be subnets of the network with the given NetworkID.
+ 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: |-
@@ -1888,18 +1914,21 @@ spec:
tagsAny:
type: string
type: object
- required:
- - subnet
type: object
type: array
+ x-kubernetes-list-type: atomic
hostId:
- description: The ID of the host where the port is allocated
+ 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: 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: 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: |-
@@ -1925,10 +1954,13 @@ spec:
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
+ 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
@@ -1943,9 +1975,10 @@ spec:
description: PropageteUplinkStatus enables or disables the propagate
uplink status on the port.
type: boolean
- securityGroupFilters:
- description: The names, uuids, filters or any combination these
- of the security groups to assign to the instance
+ 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:
properties:
description:
@@ -1966,6 +1999,7 @@ spec:
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.)
@@ -1975,8 +2009,10 @@ spec:
type: array
x-kubernetes-list-type: set
trunk:
- description: Enables and disables trunk at port level. If not
- provided, openStackMachine.Spec.Trunk is inherited.
+ 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: |-
@@ -2008,8 +2044,15 @@ spec:
- name
x-kubernetes-list-type: map
vnicType:
- description: The virtual network interface card (vNIC) type
- that is bound to the neutron port.
+ 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
@@ -2228,17 +2271,37 @@ spec:
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: |-
@@ -2246,12 +2309,17 @@ spec:
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 should be subnets of the network with the given
- NetworkID.
+ 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: |-
@@ -2285,19 +2353,21 @@ spec:
tagsAny:
type: string
type: object
- required:
- - subnet
type: object
type: array
+ x-kubernetes-list-type: atomic
hostId:
- description: The ID of the host where the port is allocated
+ 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: 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: 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: |-
@@ -2323,10 +2393,13 @@ spec:
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
+ 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
@@ -2341,9 +2414,10 @@ spec:
description: PropageteUplinkStatus enables or disables the
propagate uplink status on the port.
type: boolean
- securityGroupFilters:
- description: The names, uuids, filters or any combination
- these of the security groups to assign to the instance
+ 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:
properties:
description:
@@ -2364,6 +2438,7 @@ spec:
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.)
@@ -2373,8 +2448,10 @@ spec:
type: array
x-kubernetes-list-type: set
trunk:
- description: Enables and disables trunk at port level. If
- not provided, openStackMachine.Spec.Trunk is inherited.
+ 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: |-
@@ -2406,8 +2483,15 @@ spec:
- name
x-kubernetes-list-type: map
vnicType:
- description: The virtual network interface card (vNIC) type
- that is bound to the neutron port.
+ 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
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 9a903ee0ad..d3d7f9d9fc 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
@@ -1507,17 +1507,37 @@ spec:
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: |-
@@ -1525,12 +1545,17 @@ spec:
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 should be subnets of the network with the given
- NetworkID.
+ 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: |-
@@ -1564,19 +1589,22 @@ spec:
tagsAny:
type: string
type: object
- required:
- - subnet
type: object
type: array
+ x-kubernetes-list-type: atomic
hostId:
- description: The ID of the host where the port is allocated
+ 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: 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: 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: |-
@@ -1602,10 +1630,13 @@ spec:
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
+ 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
@@ -1620,9 +1651,10 @@ spec:
description: PropageteUplinkStatus enables or disables
the propagate uplink status on the port.
type: boolean
- securityGroupFilters:
- description: The names, uuids, filters or any combination
- these of the security groups to assign to the instance
+ 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:
properties:
description:
@@ -1643,6 +1675,7 @@ spec:
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.)
@@ -1652,8 +1685,10 @@ spec:
type: array
x-kubernetes-list-type: set
trunk:
- description: Enables and disables trunk at port level.
- If not provided, openStackMachine.Spec.Trunk is inherited.
+ 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: |-
@@ -1686,8 +1721,15 @@ spec:
- name
x-kubernetes-list-type: map
vnicType:
- description: The virtual network interface card (vNIC)
- type that is bound to the neutron port.
+ 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
diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md
index f55c02035e..ac6b13a425 100644
--- a/docs/book/src/api/v1beta1/api.md
+++ b/docs/book/src/api/v1beta1/api.md
@@ -969,6 +969,9 @@ 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.
|
@@ -979,6 +982,9 @@ 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.
|
@@ -1218,6 +1224,7 @@ bool
+(Optional)
OVSHWOffload enables or disables the OVS hardware offload feature.
|
@@ -1229,6 +1236,7 @@ bool
+(Optional)
TrustedVF enables or disables the “trusted mode” for the VF.
|
@@ -1456,6 +1464,7 @@ SubnetFilter
+(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.
|
@@ -1468,6 +1477,11 @@ 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.
|
@@ -3479,6 +3493,7 @@ NetworkFilter
+(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.
|
@@ -3491,7 +3506,8 @@ 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.
+(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.
|
@@ -3502,6 +3518,8 @@ string
|
+(Optional)
+ Description is a human-readable description for the port.
|
@@ -3512,6 +3530,8 @@ bool
|
+(Optional)
+ AdminStateUp specifies whether the port should be created in the up (true) or down (false) state. The default is up.
|
@@ -3522,6 +3542,8 @@ string
|
+(Optional)
+ MACAddress specifies the MAC address of the port. If not specified, the MAC address will be generated.
|
@@ -3534,12 +3556,13 @@ string
|
- Specify pairs of subnet and/or IP address. These should be subnets of the network with the given NetworkID.
+(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.
|
-securityGroupFilters
+securityGroups
[]SecurityGroupFilter
@@ -3547,7 +3570,8 @@ string
|
- The names, uuids, filters or any combination these of the security groups to assign to the instance
+(Optional)
+SecurityGroups is a list of the names, uuids, filters or any combination these of the security groups to assign to the instance.
|
@@ -3560,6 +3584,12 @@ string
|
+(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.
|
@@ -3570,7 +3600,10 @@ bool
|
- Enables and disables trunk at port level. If not provided, openStackMachine.Spec.Trunk is inherited.
+(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.
|
@@ -3581,7 +3614,8 @@ string
|
- The ID of the host where the port is allocated
+(Optional)
+HostID specifies the ID of the host where the port resides.
|
@@ -3592,7 +3626,15 @@ string
|
- The virtual network interface card (vNIC) type that is bound to the neutron port.
+(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.
|
@@ -3605,10 +3647,14 @@ 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
+(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
|
@@ -3619,6 +3665,7 @@ 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.
|
@@ -3631,6 +3678,7 @@ bool
+(Optional)
PropageteUplinkStatus enables or disables the propagate uplink status on the port.
|
@@ -3642,6 +3690,7 @@ bool
+(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.
|
diff --git a/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md b/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
index 2cdc4560cd..6028c9de31 100644
--- a/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
+++ b/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
@@ -8,16 +8,19 @@
- [`OpenStackMachine`](#openstackmachine)
- [Removal of machine identityRef.kind](#removal-of-machine-identityrefkind)
- [Change to serverGroupID](#change-to-servergroupid)
+ - [Changes to ports](#changes-to-ports)
- [`OpenStackCluster`](#openstackcluster)
- [Removal of cluster identityRef.kind](#removal-of-cluster-identityrefkind)
- [Change to externalNetworkID](#change-to-externalnetworkid)
- - [Changes to image](#change-to-image)
+ - [Change to image](#change-to-image)
- [Removal of imageUUID](#removal-of-imageuuid)
- [Change to floatingIP](#change-to-floatingip)
- [Change to subnet](#change-to-subnet)
- [Change to nodeCidr and dnsNameservers](#change-to-nodecidr-and-dnsnameservers)
+ - [Addition of allocationPools](#addition-of-allocationpools)
- [Change to managedSecurityGroups](#change-to-managedsecuritygroups)
- [Calico CNI](#calico-cni)
+ - [Change to network](#change-to-network)
@@ -66,6 +69,18 @@ serverGroup:
If a server group is provided and found, it'll be added to `OpenStackMachine.Status.ReferencedResources.ServerGroupID`. If the server group can't be found or filter matches multiple server groups, an error will be returned.
If empty object or null is provided, Machine will not be added to any server group and `OpenStackMachine.Status.ReferencedResources.ServerGroupID` will be empty.
+#### Changes to ports
+
+These changes apply to ports specified in both OpenStackMachines and the Bastion.
+
+The `securityGroupFilters` field is renamed to `securityGroups` to be consistent with other similar fields throughout the API.
+
+When specifying `allowedAddressPairs`, `ipAddress` is now required. Neutron has already required this parameter, so while the API previously allowed it to be unset it would not have resulted in a working VM.
+
+Setting either of the following fields explicitly to the empty string would previously have caused the default behaviour to be used. In v1beta1 it will result in an empty string being used instead. To retain the default behaviour in v1beta1, do not set the value at all. When objects are upgraded automatically by the controller, empty values will become unset values by default, so this applies only to newly created objects.
+* nameSuffix
+* description
+
### `OpenStackCluster`
#### Removal of cluster identityRef.kind
diff --git a/pkg/cloud/services/networking/port.go b/pkg/cloud/services/networking/port.go
index 1ecf4beaca..a4f4488008 100644
--- a/pkg/cloud/services/networking/port.go
+++ b/pkg/cloud/services/networking/port.go
@@ -28,6 +28,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/wait"
+ "k8s.io/utils/pointer"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/record"
@@ -60,8 +61,10 @@ func (s *Service) CreatePort(eventObject runtime.Object, clusterName string, por
var err error
networkID := portOpts.Network.ID
- description := portOpts.Description
- if description == "" {
+ var description string
+ if portOpts.Description != nil {
+ description = *portOpts.Description
+ } else {
description = names.GetDescription(clusterName)
}
@@ -71,11 +74,11 @@ func (s *Service) CreatePort(eventObject runtime.Object, clusterName string, por
for _, ap := range portOpts.AllowedAddressPairs {
addressPairs = append(addressPairs, ports.AddressPair{
IPAddress: ap.IPAddress,
- MACAddress: ap.MACAddress,
+ MACAddress: pointer.StringDeref(ap.MACAddress, ""),
})
}
- if portOpts.SecurityGroupFilters != nil {
- securityGroups, err = s.GetSecurityGroups(portOpts.SecurityGroupFilters)
+ if portOpts.SecurityGroups != nil {
+ securityGroups, err = s.GetSecurityGroups(portOpts.SecurityGroups)
if err != nil {
return nil, fmt.Errorf("error getting security groups: %v", err)
}
@@ -96,7 +99,7 @@ func (s *Service) CreatePort(eventObject runtime.Object, clusterName string, por
}
fips = append(fips, ports.IP{
SubnetID: subnetID,
- IPAddress: fixedIP.IPAddress,
+ IPAddress: pointer.StringDeref(fixedIP.IPAddress, ""),
})
}
fixedIPs = fips
@@ -124,7 +127,7 @@ func (s *Service) CreatePort(eventObject runtime.Object, clusterName string, por
NetworkID: networkID,
Description: description,
AdminStateUp: portOpts.AdminStateUp,
- MACAddress: portOpts.MACAddress,
+ MACAddress: pointer.StringDeref(portOpts.MACAddress, ""),
SecurityGroups: securityGroupsPtr,
AllowedAddressPairs: addressPairs,
FixedIPs: fixedIPs,
@@ -142,8 +145,8 @@ func (s *Service) CreatePort(eventObject runtime.Object, clusterName string, por
createOpts = portsbinding.CreateOptsExt{
CreateOptsBuilder: createOpts,
- HostID: portOpts.HostID,
- VNICType: portOpts.VNICType,
+ HostID: pointer.StringDeref(portOpts.HostID, ""),
+ VNICType: pointer.StringDeref(portOpts.VNICType, ""),
Profile: getPortProfile(portOpts.Profile),
}
@@ -204,15 +207,19 @@ func (s *Service) getSubnetIDForFixedIP(subnet *infrav1.SubnetFilter, networkID
}
}
-func getPortProfile(p infrav1.BindingProfile) map[string]interface{} {
+func getPortProfile(p *infrav1.BindingProfile) map[string]interface{} {
+ if p == nil {
+ return nil
+ }
+
portProfile := make(map[string]interface{})
// if p.OVSHWOffload is true, we need to set the profile
// to enable hardware offload for the port
- if p.OVSHWOffload {
+ if pointer.BoolDeref(p.OVSHWOffload, false) {
portProfile["capabilities"] = []string{"switchdev"}
}
- if p.TrustedVF {
+ if pointer.BoolDeref(p.TrustedVF, false) {
portProfile["trusted"] = true
}
@@ -300,8 +307,8 @@ func (s *Service) DeleteClusterPorts(openStackCluster *infrav1.OpenStackCluster)
// GetPortName appends a suffix to an instance name in order to try and get a unique name per port.
func GetPortName(instanceName string, opts *infrav1.PortOpts, netIndex int) string {
- if opts != nil && opts.NameSuffix != "" {
- return fmt.Sprintf("%s-%s", instanceName, opts.NameSuffix)
+ if opts != nil && opts.NameSuffix != nil {
+ return fmt.Sprintf("%s-%s", instanceName, *opts.NameSuffix)
}
return fmt.Sprintf("%s-%d", instanceName, netIndex)
}
diff --git a/pkg/cloud/services/networking/port_test.go b/pkg/cloud/services/networking/port_test.go
index 96d741d992..9fd0c50a6c 100644
--- a/pkg/cloud/services/networking/port_test.go
+++ b/pkg/cloud/services/networking/port_test.go
@@ -56,9 +56,6 @@ func Test_CreatePort(t *testing.T) {
portSecurityGroupFilters := []infrav1.SecurityGroupFilter{{ID: portSecurityGroupID, Name: "port-secgroup"}}
valueSpecs := map[string]string{"key": "value"}
- pointerToTrue := pointerTo(true)
- pointerToFalse := pointerTo(false)
-
tests := []struct {
name string
portName string
@@ -103,28 +100,32 @@ func Test_CreatePort(t *testing.T) {
Network: &infrav1.NetworkFilter{
ID: netID,
},
- NameSuffix: "bar",
- Description: "this is a test port",
- MACAddress: "fe:fe:fe:fe:fe:fe",
- AdminStateUp: pointerToTrue,
- FixedIPs: []infrav1.FixedIP{{
- Subnet: &infrav1.SubnetFilter{
- Name: "subnetFoo",
+ NameSuffix: pointer.String("bar"),
+ Description: pointer.String("this is a test port"),
+ MACAddress: pointer.String("fe:fe:fe:fe:fe:fe"),
+ AdminStateUp: pointer.Bool(true),
+ FixedIPs: []infrav1.FixedIP{
+ {
+ Subnet: &infrav1.SubnetFilter{
+ Name: "subnetFoo",
+ },
+ IPAddress: pointer.String("192.168.0.50"),
+ }, {
+ IPAddress: pointer.String("192.168.1.50"),
},
- IPAddress: "192.168.0.50",
- }, {IPAddress: "192.168.1.50"}},
- SecurityGroupFilters: portSecurityGroupFilters,
+ },
+ SecurityGroups: portSecurityGroupFilters,
AllowedAddressPairs: []infrav1.AddressPair{{
IPAddress: "10.10.10.10",
- MACAddress: "f1:f1:f1:f1:f1:f1",
+ MACAddress: pointer.String("f1:f1:f1:f1:f1:f1"),
}},
- HostID: hostID,
- VNICType: "direct",
- Profile: infrav1.BindingProfile{
- OVSHWOffload: true,
- TrustedVF: true,
+ HostID: pointer.String(hostID),
+ VNICType: pointer.String("direct"),
+ Profile: &infrav1.BindingProfile{
+ OVSHWOffload: pointer.Bool(true),
+ TrustedVF: pointer.Bool(true),
},
- DisablePortSecurity: pointerToFalse,
+ DisablePortSecurity: pointer.Bool(false),
Tags: []string{"my-port-tag"},
},
nil,
@@ -134,7 +135,7 @@ func Test_CreatePort(t *testing.T) {
NetworkID: netID,
Name: "foo-port-bar",
Description: "this is a test port",
- AdminStateUp: pointerToTrue,
+ AdminStateUp: pointer.Bool(true),
MACAddress: "fe:fe:fe:fe:fe:fe",
FixedIPs: []ports.IP{
{
@@ -152,7 +153,7 @@ func Test_CreatePort(t *testing.T) {
}
portsecurityCreateOptsExt := portsecurity.PortCreateOptsExt{
CreateOptsBuilder: portCreateOpts,
- PortSecurityEnabled: pointerToTrue,
+ PortSecurityEnabled: pointer.Bool(true),
}
portbindingCreateOptsExt := portsbinding.CreateOptsExt{
// Note for the test matching, the order in which the builders are composed
@@ -195,13 +196,13 @@ func Test_CreatePort(t *testing.T) {
Network: &infrav1.NetworkFilter{
ID: netID,
},
- NameSuffix: "foo-port-bar",
- Description: "this is a test port",
+ NameSuffix: pointer.String("foo-port-bar"),
+ Description: pointer.String("this is a test port"),
FixedIPs: []infrav1.FixedIP{{
Subnet: &infrav1.SubnetFilter{
Tags: "Foo",
},
- IPAddress: "192.168.0.50",
+ IPAddress: pointer.String("192.168.0.50"),
}},
},
nil,
@@ -234,7 +235,7 @@ func Test_CreatePort(t *testing.T) {
Network: &infrav1.NetworkFilter{
ID: netID,
},
- SecurityGroupFilters: portSecurityGroupFilters,
+ SecurityGroups: portSecurityGroupFilters,
},
instanceSecurityGroups,
[]string{},
@@ -312,7 +313,7 @@ func Test_CreatePort(t *testing.T) {
Network: &infrav1.NetworkFilter{
ID: netID,
},
- Trunk: pointerToTrue,
+ Trunk: pointer.Bool(true),
},
nil,
[]string{"my-tag"},
@@ -383,7 +384,7 @@ func Test_CreatePort(t *testing.T) {
Network: &infrav1.NetworkFilter{
ID: netID,
},
- PropagateUplinkStatus: pointerToTrue,
+ PropagateUplinkStatus: pointer.Bool(true),
},
instanceSecurityGroups,
[]string{},
@@ -396,11 +397,11 @@ func Test_CreatePort(t *testing.T) {
SecurityGroups: &instanceSecurityGroups,
NetworkID: netID,
AllowedAddressPairs: []ports.AddressPair{},
- PropagateUplinkStatus: pointerToTrue,
+ PropagateUplinkStatus: pointer.Bool(true),
},
- }).Return(&ports.Port{ID: portID1, PropagateUplinkStatus: *pointerToTrue}, nil)
+ }).Return(&ports.Port{ID: portID1, PropagateUplinkStatus: true}, nil)
},
- &ports.Port{ID: portID1, PropagateUplinkStatus: *pointerToTrue},
+ &ports.Port{ID: portID1, PropagateUplinkStatus: true},
false,
},
}
@@ -433,10 +434,6 @@ func Test_CreatePort(t *testing.T) {
}
}
-func pointerTo(b bool) *bool {
- return &b
-}
-
func TestService_normalizePorts(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
@@ -816,7 +813,7 @@ func Test_getPortName(t *testing.T) {
},
{
name: "with PortOpts name suffix",
- args: args{"test-1-instance", &infrav1.PortOpts{NameSuffix: "foo"}, 4},
+ args: args{"test-1-instance", &infrav1.PortOpts{NameSuffix: pointer.String("foo")}, 4},
want: "test-1-instance-foo",
},
{
@@ -826,7 +823,7 @@ func Test_getPortName(t *testing.T) {
},
{
name: "with PortOpts name suffix",
- args: args{"test-1-instance", &infrav1.PortOpts{NameSuffix: "foo2", Network: &infrav1.NetworkFilter{ID: "bar"}, DisablePortSecurity: pointer.Bool(true)}, 4},
+ args: args{"test-1-instance", &infrav1.PortOpts{NameSuffix: pointer.String("foo2"), Network: &infrav1.NetworkFilter{ID: "bar"}, DisablePortSecurity: pointer.Bool(true)}, 4},
want: "test-1-instance-foo2",
},
}
diff --git a/pkg/utils/optional/conversion.go b/pkg/utils/optional/conversion.go
new file mode 100644
index 0000000000..1876927b7a
--- /dev/null
+++ b/pkg/utils/optional/conversion.go
@@ -0,0 +1,43 @@
+/*
+Copyright 2024 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 optional
+
+import (
+ "k8s.io/apimachinery/pkg/conversion"
+)
+
+func Convert_string_To_optional_String(in *string, out *String, _ conversion.Scope) error {
+ // NOTE: This function has the opposite defaulting behaviour to
+ // Convert_string_to_Pointer_string defined in apimachinery: it converts
+ // empty strings to nil instead of a pointer to an empty string.
+
+ if *in == "" {
+ *out = nil
+ } else {
+ *out = in
+ }
+ return nil
+}
+
+func Convert_optional_String_To_string(in *String, out *string, _ conversion.Scope) error {
+ if *in == nil {
+ *out = ""
+ } else {
+ *out = **in
+ }
+ return nil
+}
diff --git a/pkg/utils/optional/types.go b/pkg/utils/optional/types.go
new file mode 100644
index 0000000000..c9d05ec91b
--- /dev/null
+++ b/pkg/utils/optional/types.go
@@ -0,0 +1,22 @@
+/*
+Copyright 2024 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 optional
+
+// String is a string that can be unspecified. strings which are converted to
+// optional.String during API conversion will be converted to nil if the value
+// was previously the empty string.
+type String *string
diff --git a/test/e2e/suites/e2e/e2e_test.go b/test/e2e/suites/e2e/e2e_test.go
index 5d7098e0dd..4443c500dd 100644
--- a/test/e2e/suites/e2e/e2e_test.go
+++ b/test/e2e/suites/e2e/e2e_test.go
@@ -373,14 +373,14 @@ var _ = Describe("e2e tests [PR-Blocking]", func() {
customPortOptions := &[]infrav1.PortOpts{
{
- Description: "primary",
+ Description: pointer.String("primary"),
},
{
- Description: "trunked",
+ Description: pointer.String("trunked"),
Trunk: pointer.Bool(true),
},
{
- SecurityGroupFilters: []infrav1.SecurityGroupFilter{{Name: testSecurityGroupName}},
+ SecurityGroups: []infrav1.SecurityGroupFilter{{Name: testSecurityGroupName}},
},
}
From 564b6bd899062bf4fc06ac4a6a10ddfbe7f7a082 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Mon, 19 Feb 2024 15:11:21 +0000
Subject: [PATCH 087/180] Move CloudName into IdentityRef and make cluster
IdentityRef required
This change came from attempting to write validation markers for
CloudName and IdentityRef in both the machine and cluster specs.
Firstly I noticed that IdentityRef was marked optional in the cluster
spec, but it is certainly required: the cluster cannot be provisioned
without cloud credentials. I made IdentityRef required in the cluster
spec.
In contrast, IdentityRef is genuinely optional in the machine spec
because, if not specified, we will use the credentials defined in the
cluster spec.
CloudName on the machine spec is also marked optional. However, it is
required if IdentityRef was specified. This is because it refers to the
same object as IdentityRef. The most sensible way to to represent this
in the API is to put it in the IdentityRef. This means that if
IdentityRef is provided, it must be provided completely, including
CloudName.
---
api/v1alpha5/conversion.go | 28 +++
api/v1alpha5/conversion_test.go | 20 +-
api/v1alpha5/zz_generated.conversion.go | 42 +---
api/v1alpha6/conversion.go | 28 +++
api/v1alpha6/zz_generated.conversion.go | 42 +---
api/v1alpha7/conversion.go | 24 +++
api/v1alpha7/zz_generated.conversion.go | 42 +---
api/v1beta1/identity_types.go | 11 +-
api/v1beta1/openstackcluster_types.go | 12 +-
api/v1beta1/openstackcluster_webhook.go | 21 +-
api/v1beta1/openstackcluster_webhook_test.go | 204 +++++++++++++-----
api/v1beta1/openstackmachine_types.go | 8 +-
api/v1beta1/openstackmachine_webhook.go | 4 +
api/v1beta1/zz_generated.deepcopy.go | 6 +-
...re.cluster.x-k8s.io_openstackclusters.yaml | 43 ++--
...er.x-k8s.io_openstackclustertemplates.yaml | 44 ++--
...re.cluster.x-k8s.io_openstackmachines.yaml | 20 +-
...er.x-k8s.io_openstackmachinetemplates.yaml | 21 +-
.../openstackmachine_controller_test.go | 1 -
docs/book/src/api/v1beta1/api.md | 116 +++-------
.../topics/crd-changes/v1alpha7-to-v1beta1.md | 32 ++-
.../v1beta1/default/cluster-template.yaml | 8 +-
pkg/scope/provider.go | 34 +--
.../cluster-template-flatcar-sysext.yaml | 8 +-
templates/cluster-template-flatcar.yaml | 8 +-
templates/cluster-template-without-lb.yaml | 8 +-
templates/cluster-template.yaml | 8 +-
templates/clusterclass-dev-test.yaml | 8 +-
test/e2e/suites/e2e/e2e_test.go | 8 +-
29 files changed, 458 insertions(+), 401 deletions(-)
diff --git a/api/v1alpha5/conversion.go b/api/v1alpha5/conversion.go
index 14302a23ea..39901bfd2e 100644
--- a/api/v1alpha5/conversion.go
+++ b/api/v1alpha5/conversion.go
@@ -215,6 +215,9 @@ func Convert_v1beta1_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(in *i
out.AllowAllInClusterTraffic = in.ManagedSecurityGroups.AllowAllInClusterTraffic
}
+ out.CloudName = in.IdentityRef.CloudName
+ out.IdentityRef = &OpenStackIdentityReference{Name: in.IdentityRef.Name}
+
return nil
}
@@ -258,6 +261,11 @@ func Convert_v1alpha5_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *O
}
}
+ out.IdentityRef.CloudName = in.CloudName
+ if in.IdentityRef != nil {
+ out.IdentityRef.Name = in.IdentityRef.Name
+ }
+
return nil
}
@@ -321,6 +329,16 @@ func Convert_v1alpha5_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(in *O
}
out.Image = imageFilter
+ 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
}
@@ -606,6 +624,11 @@ func Convert_v1beta1_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(in *i
out.ImageUUID = in.Image.ID
}
+ if in.IdentityRef != nil {
+ out.IdentityRef = &OpenStackIdentityReference{Name: in.IdentityRef.Name}
+ out.CloudName = in.IdentityRef.CloudName
+ }
+
return nil
}
@@ -690,3 +713,8 @@ func Convert_v1alpha5_SecurityGroup_To_v1beta1_SecurityGroupStatus(in *SecurityG
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
+}
diff --git a/api/v1alpha5/conversion_test.go b/api/v1alpha5/conversion_test.go
index 6e0ab71e74..3aa5f57d43 100644
--- a/api/v1alpha5/conversion_test.go
+++ b/api/v1alpha5/conversion_test.go
@@ -46,10 +46,12 @@ func TestConvertFrom(t *testing.T) {
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\":{\"apiServerLoadBalancer\":{},\"cloudName\":\"\",\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"disableExternalNetwork\":false,\"externalNetwork\":{},\"managedSecurityGroups\":null,\"network\":{}},\"status\":{\"ready\":false}}",
+ "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"apiServerLoadBalancer\":{},\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"disableExternalNetwork\":false,\"externalNetwork\":{},\"identityRef\":{\"cloudName\":\"\",\"name\":\"\"},\"managedSecurityGroups\":null,\"network\":{}},\"status\":{\"ready\":false}}",
},
},
},
@@ -61,10 +63,16 @@ func TestConvertFrom(t *testing.T) {
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\":{\"apiServerLoadBalancer\":{},\"cloudName\":\"\",\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"disableExternalNetwork\":false,\"externalNetwork\":{},\"managedSecurityGroups\":null,\"network\":{}}}}}",
+ "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"template\":{\"spec\":{\"apiServerLoadBalancer\":{},\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"disableExternalNetwork\":false,\"externalNetwork\":{},\"identityRef\":{\"cloudName\":\"\",\"name\":\"\"},\"managedSecurityGroups\":null,\"network\":{}}}}}",
},
},
},
@@ -79,7 +87,7 @@ func TestConvertFrom(t *testing.T) {
Spec: OpenStackMachineSpec{},
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
- "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"cloudName\":\"\",\"flavor\":\"\",\"image\":{}},\"status\":{\"dependentResources\":{},\"ready\":false,\"referencedResources\":{}}}",
+ "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"flavor\":\"\",\"image\":{}},\"status\":{\"dependentResources\":{},\"ready\":false,\"referencedResources\":{}}}",
},
},
},
@@ -94,7 +102,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\":\"\",\"image\":{}}}}}",
+ "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"template\":{\"spec\":{\"flavor\":\"\",\"image\":{}}}}}",
},
},
},
diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go
index b3f06aaa61..c6d7dc4e49 100644
--- a/api/v1alpha5/zz_generated.conversion.go
+++ b/api/v1alpha5/zz_generated.conversion.go
@@ -151,11 +151,6 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*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.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 {
@@ -371,6 +366,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); 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_v1alpha5_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_v1alpha5_OpenStackMachineSpec(a.(*v1beta1.OpenStackMachineSpec), b.(*OpenStackMachineSpec), scope)
}); err != nil {
@@ -654,7 +654,7 @@ func Convert_v1beta1_OpenStackClusterList_To_v1alpha5_OpenStackClusterList(in *v
}
func autoConvert_v1alpha5_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *OpenStackClusterSpec, out *v1beta1.OpenStackClusterSpec, s conversion.Scope) error {
- out.CloudName = in.CloudName
+ // 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 err := Convert_v1alpha5_NetworkFilter_To_v1beta1_NetworkFilter(&in.Network, &out.Network, s); err != nil {
return err
@@ -695,20 +695,11 @@ func autoConvert_v1alpha5_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(i
} else {
out.Bastion = nil
}
- 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
- }
+ // 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
}
func autoConvert_v1beta1_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(in *v1beta1.OpenStackClusterSpec, out *OpenStackClusterSpec, s conversion.Scope) error {
- out.CloudName = in.CloudName
// 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_v1beta1_NetworkFilter_To_v1alpha5_NetworkFilter(&in.Network, &out.Network, s); err != nil {
@@ -751,15 +742,7 @@ func autoConvert_v1beta1_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(i
} else {
out.Bastion = nil
}
- 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.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
}
@@ -1013,14 +996,10 @@ func autoConvert_v1alpha5_OpenStackIdentityReference_To_v1beta1_OpenStackIdentit
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_v1beta1_OpenStackIdentityReference_To_v1alpha5_OpenStackIdentityReference is an autogenerated conversion function.
-func Convert_v1beta1_OpenStackIdentityReference_To_v1alpha5_OpenStackIdentityReference(in *v1beta1.OpenStackIdentityReference, out *OpenStackIdentityReference, s conversion.Scope) error {
- return autoConvert_v1beta1_OpenStackIdentityReference_To_v1alpha5_OpenStackIdentityReference(in, out, s)
-}
-
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_v1beta1_OpenStackMachineSpec(&in.Spec, &out.Spec, s); err != nil {
@@ -1098,7 +1077,7 @@ func Convert_v1beta1_OpenStackMachineList_To_v1alpha5_OpenStackMachineList(in *v
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.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.ImageFilter)
// WARNING: in.ImageUUID requires manual conversion: does not exist in peer-type
@@ -1149,7 +1128,6 @@ func autoConvert_v1alpha5_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(i
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
// WARNING: in.Image requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ImageFilter vs string)
out.SSHKeyName = in.SSHKeyName
diff --git a/api/v1alpha6/conversion.go b/api/v1alpha6/conversion.go
index 13a7c8f98d..5526561dbe 100644
--- a/api/v1alpha6/conversion.go
+++ b/api/v1alpha6/conversion.go
@@ -529,6 +529,16 @@ func Convert_v1alpha6_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(in *O
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
}
@@ -624,6 +634,9 @@ func Convert_v1beta1_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(in *i
out.AllowAllInClusterTraffic = in.ManagedSecurityGroups.AllowAllInClusterTraffic
}
+ out.CloudName = in.IdentityRef.CloudName
+ out.IdentityRef = &OpenStackIdentityReference{Name: in.IdentityRef.Name}
+
return nil
}
@@ -667,6 +680,11 @@ func Convert_v1alpha6_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *O
}
}
+ out.IdentityRef.CloudName = in.CloudName
+ if in.IdentityRef != nil {
+ out.IdentityRef.Name = in.IdentityRef.Name
+ }
+
return nil
}
@@ -973,6 +991,11 @@ func Convert_v1beta1_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(in *i
out.ServerMetadata = serverMetadata
}
+ if in.IdentityRef != nil {
+ out.IdentityRef = &OpenStackIdentityReference{Name: in.IdentityRef.Name}
+ out.CloudName = in.IdentityRef.CloudName
+ }
+
return nil
}
@@ -1069,3 +1092,8 @@ func Convert_v1alpha6_SecurityGroup_To_v1beta1_SecurityGroupStatus(in *SecurityG
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
+}
diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go
index 489889727b..f27f605f86 100644
--- a/api/v1alpha6/zz_generated.conversion.go
+++ b/api/v1alpha6/zz_generated.conversion.go
@@ -160,11 +160,6 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*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 {
@@ -380,6 +375,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); 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_v1alpha6_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_v1alpha6_OpenStackMachineSpec(a.(*v1beta1.OpenStackMachineSpec), b.(*OpenStackMachineSpec), scope)
}); err != nil {
@@ -680,7 +680,7 @@ func Convert_v1beta1_OpenStackClusterList_To_v1alpha6_OpenStackClusterList(in *v
}
func autoConvert_v1alpha6_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *OpenStackClusterSpec, out *v1beta1.OpenStackClusterSpec, s conversion.Scope) error {
- out.CloudName = in.CloudName
+ // 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 err := Convert_v1alpha6_NetworkFilter_To_v1beta1_NetworkFilter(&in.Network, &out.Network, s); err != nil {
return err
@@ -722,20 +722,11 @@ func autoConvert_v1alpha6_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(i
} else {
out.Bastion = nil
}
- 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
- }
+ // 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
}
func autoConvert_v1beta1_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(in *v1beta1.OpenStackClusterSpec, out *OpenStackClusterSpec, s conversion.Scope) error {
- out.CloudName = in.CloudName
// 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_v1beta1_NetworkFilter_To_v1alpha6_NetworkFilter(&in.Network, &out.Network, s); err != nil {
@@ -778,15 +769,7 @@ func autoConvert_v1beta1_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(i
} else {
out.Bastion = nil
}
- 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.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
}
@@ -1040,14 +1023,10 @@ func autoConvert_v1alpha6_OpenStackIdentityReference_To_v1beta1_OpenStackIdentit
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_v1beta1_OpenStackIdentityReference_To_v1alpha6_OpenStackIdentityReference is an autogenerated conversion function.
-func Convert_v1beta1_OpenStackIdentityReference_To_v1alpha6_OpenStackIdentityReference(in *v1beta1.OpenStackIdentityReference, out *OpenStackIdentityReference, s conversion.Scope) error {
- return autoConvert_v1beta1_OpenStackIdentityReference_To_v1alpha6_OpenStackIdentityReference(in, out, s)
-}
-
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_v1beta1_OpenStackMachineSpec(&in.Spec, &out.Spec, s); err != nil {
@@ -1125,7 +1104,7 @@ func Convert_v1beta1_OpenStackMachineList_To_v1alpha6_OpenStackMachineList(in *v
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.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.ImageFilter)
// WARNING: in.ImageUUID requires manual conversion: does not exist in peer-type
@@ -1176,7 +1155,6 @@ func autoConvert_v1alpha6_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(i
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
// WARNING: in.Image requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ImageFilter vs string)
out.SSHKeyName = in.SSHKeyName
diff --git a/api/v1alpha7/conversion.go b/api/v1alpha7/conversion.go
index 6c3523a862..ff38380bf4 100644
--- a/api/v1alpha7/conversion.go
+++ b/api/v1alpha7/conversion.go
@@ -550,6 +550,10 @@ func Convert_v1beta1_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(in *i
out.ServerMetadata = serverMetadata
}
+ if in.IdentityRef != nil {
+ out.CloudName = in.IdentityRef.CloudName
+ }
+
return nil
}
@@ -591,6 +595,13 @@ func Convert_v1alpha7_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(in *O
out.ServerMetadata = serverMetadata
}
+ if in.CloudName != "" {
+ if out.IdentityRef == nil {
+ out.IdentityRef = &infrav1.OpenStackIdentityReference{}
+ }
+ out.IdentityRef.CloudName = in.CloudName
+ }
+
return nil
}
@@ -674,6 +685,11 @@ func Convert_v1alpha7_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *O
}
}
+ out.IdentityRef.CloudName = in.CloudName
+ if in.IdentityRef != nil {
+ out.IdentityRef.Name = in.IdentityRef.Name
+ }
+
return nil
}
@@ -703,6 +719,9 @@ func Convert_v1beta1_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in *i
out.AllowAllInClusterTraffic = in.ManagedSecurityGroups.AllowAllInClusterTraffic
}
+ out.CloudName = in.IdentityRef.CloudName
+ out.IdentityRef = &OpenStackIdentityReference{Name: in.IdentityRef.Name}
+
return nil
}
@@ -815,3 +834,8 @@ func Convert_v1beta1_PortOpts_To_v1alpha7_PortOpts(in *infrav1.PortOpts, out *Po
return nil
}
+
+func Convert_v1beta1_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference(in *infrav1.OpenStackIdentityReference, out *OpenStackIdentityReference, _ apiconversion.Scope) error {
+ out.Name = in.Name
+ return nil
+}
diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go
index e99f7f7557..69cbeb55f3 100644
--- a/api/v1alpha7/zz_generated.conversion.go
+++ b/api/v1alpha7/zz_generated.conversion.go
@@ -231,11 +231,6 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*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 {
@@ -421,6 +416,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); 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 {
@@ -885,7 +885,7 @@ func Convert_v1beta1_OpenStackClusterList_To_v1alpha7_OpenStackClusterList(in *v
}
func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *OpenStackClusterSpec, out *v1beta1.OpenStackClusterSpec, s conversion.Scope) error {
- out.CloudName = in.CloudName
+ // WARNING: in.CloudName requires manual conversion: does not exist in peer-type
// WARNING: in.NodeCIDR requires manual conversion: does not exist in peer-type
out.Router = (*v1beta1.RouterFilter)(unsafe.Pointer(in.Router))
if err := Convert_v1alpha7_NetworkFilter_To_v1beta1_NetworkFilter(&in.Network, &out.Network, s); err != nil {
@@ -919,20 +919,11 @@ func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(i
} else {
out.Bastion = nil
}
- 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
- }
+ // 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 {
- out.CloudName = in.CloudName
// WARNING: in.ManagedSubnets requires manual conversion: does not exist in peer-type
out.Router = (*RouterFilter)(unsafe.Pointer(in.Router))
if err := Convert_v1beta1_NetworkFilter_To_v1alpha7_NetworkFilter(&in.Network, &out.Network, s); err != nil {
@@ -965,15 +956,7 @@ func autoConvert_v1beta1_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(i
} else {
out.Bastion = nil
}
- 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.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
}
@@ -1202,14 +1185,10 @@ func autoConvert_v1alpha7_OpenStackIdentityReference_To_v1beta1_OpenStackIdentit
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
}
-// Convert_v1beta1_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference is an autogenerated conversion function.
-func Convert_v1beta1_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference(in *v1beta1.OpenStackIdentityReference, out *OpenStackIdentityReference, s conversion.Scope) error {
- return autoConvert_v1beta1_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference(in, out, s)
-}
-
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 {
@@ -1287,7 +1266,7 @@ func Convert_v1beta1_OpenStackMachineList_To_v1alpha7_OpenStackMachineList(in *v
func autoConvert_v1alpha7_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.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.ImageFilter)
// WARNING: in.ImageUUID requires manual conversion: does not exist in peer-type
@@ -1327,7 +1306,6 @@ func autoConvert_v1alpha7_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(i
func autoConvert_v1beta1_OpenStackMachineSpec_To_v1alpha7_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
// WARNING: in.Image requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ImageFilter vs string)
out.SSHKeyName = in.SSHKeyName
diff --git a/api/v1beta1/identity_types.go b/api/v1beta1/identity_types.go
index ff68fceae6..d54ed749e4 100644
--- a/api/v1beta1/identity_types.go
+++ b/api/v1beta1/identity_types.go
@@ -19,8 +19,13 @@ package v1beta1
// OpenStackIdentityReference is a reference to an infrastructure
// provider identity to be used to provision cluster resources.
type OpenStackIdentityReference struct {
- // 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/api/v1beta1/openstackcluster_types.go b/api/v1beta1/openstackcluster_types.go
index ff24c04f5b..d5cda0ec1a 100644
--- a/api/v1beta1/openstackcluster_types.go
+++ b/api/v1beta1/openstackcluster_types.go
@@ -30,10 +30,6 @@ const (
// OpenStackClusterSpec defines the desired state of OpenStackCluster.
type OpenStackClusterSpec struct {
- // The name of the cloud to use from the clouds secret
- // +optional
- CloudName string `json:"cloudName"`
-
// 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.
@@ -157,9 +153,11 @@ type OpenStackClusterSpec struct {
//+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.
diff --git a/api/v1beta1/openstackcluster_webhook.go b/api/v1beta1/openstackcluster_webhook.go
index 68d4c6593e..97781ea2c6 100644
--- a/api/v1beta1/openstackcluster_webhook.go
+++ b/api/v1beta1/openstackcluster_webhook.go
@@ -81,24 +81,9 @@ func (r *OpenStackCluster) ValidateUpdate(oldRaw runtime.Object) (admission.Warn
return nil, apierrors.NewBadRequest(fmt.Sprintf("expected an OpenStackCluster but got a %T", oldRaw))
}
- // 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 changes to Spec.IdentityRef
+ old.Spec.IdentityRef = OpenStackIdentityReference{}
+ r.Spec.IdentityRef = OpenStackIdentityReference{}
// Allow change only for the first time.
if old.Spec.ControlPlaneEndpoint.Host == "" {
diff --git a/api/v1beta1/openstackcluster_webhook_test.go b/api/v1beta1/openstackcluster_webhook_test.go
index 27984302e8..4a0213dd90 100644
--- a/api/v1beta1/openstackcluster_webhook_test.go
+++ b/api/v1beta1/openstackcluster_webhook_test.go
@@ -36,66 +36,54 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
name: "Changing OpenStackCluster.Spec.IdentityRef.Name is allowed",
oldTemplate: &OpenStackCluster{
Spec: OpenStackClusterSpec{
- CloudName: "foobar",
- IdentityRef: &OpenStackIdentityReference{
- Name: "foobar",
+ IdentityRef: OpenStackIdentityReference{
+ Name: "foobar",
+ CloudName: "foobar",
},
},
},
newTemplate: &OpenStackCluster{
Spec: OpenStackClusterSpec{
- CloudName: "foobar",
- IdentityRef: &OpenStackIdentityReference{
- Name: "foobarbaz",
+ IdentityRef: OpenStackIdentityReference{
+ Name: "foobarbaz",
+ CloudName: "foobar",
},
},
},
wantErr: false,
},
{
- name: "OpenStackCluster.Spec.IdentityRef can be changed if it was unset",
+ name: "Changing OpenStackCluster.Spec.IdentityRef.CloudName is allowed",
oldTemplate: &OpenStackCluster{
Spec: OpenStackClusterSpec{
- CloudName: "foobar",
+ IdentityRef: OpenStackIdentityReference{
+ Name: "foobar",
+ CloudName: "foobar",
+ },
},
},
newTemplate: &OpenStackCluster{
Spec: OpenStackClusterSpec{
- CloudName: "foobar",
- IdentityRef: &OpenStackIdentityReference{
- Name: "foobar",
+ IdentityRef: OpenStackIdentityReference{
+ Name: "foobar",
+ CloudName: "foobarbaz",
},
},
},
wantErr: false,
},
- {
- name: "OpenStackCluster.Spec.IdentityRef must not be removed",
- oldTemplate: &OpenStackCluster{
- Spec: OpenStackClusterSpec{
- CloudName: "foobar",
- IdentityRef: &OpenStackIdentityReference{
- Name: "foobar",
- },
- },
- },
- newTemplate: &OpenStackCluster{
- Spec: OpenStackClusterSpec{
- CloudName: "foobar",
- },
- },
- wantErr: true,
- },
{
name: "Changing OpenStackCluster.Spec.Bastion is allowed",
oldTemplate: &OpenStackCluster{
Spec: OpenStackClusterSpec{
- CloudName: "foobar",
+ IdentityRef: OpenStackIdentityReference{
+ Name: "foobar",
+ CloudName: "foobar",
+ },
Bastion: &Bastion{
Instance: OpenStackMachineSpec{
- CloudName: "foobar",
- Image: ImageFilter{Name: "foobar"},
- Flavor: "minimal",
+ Image: ImageFilter{Name: "foobar"},
+ Flavor: "minimal",
},
Enabled: true,
},
@@ -108,12 +96,14 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
newTemplate: &OpenStackCluster{
Spec: OpenStackClusterSpec{
- CloudName: "foobar",
+ IdentityRef: OpenStackIdentityReference{
+ Name: "foobar",
+ CloudName: "foobar",
+ },
Bastion: &Bastion{
Instance: OpenStackMachineSpec{
- CloudName: "foobarbaz",
- Image: ImageFilter{Name: "foobarbaz"},
- Flavor: "medium",
+ Image: ImageFilter{Name: "foobarbaz"},
+ Flavor: "medium",
},
Enabled: true,
},
@@ -125,7 +115,10 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
name: "Changing security group rules on the OpenStackCluster.Spec.ManagedSecurityGroups.AllNodesSecurityGroupRules is allowed",
oldTemplate: &OpenStackCluster{
Spec: OpenStackClusterSpec{
- CloudName: "foobar",
+ IdentityRef: OpenStackIdentityReference{
+ Name: "foobar",
+ CloudName: "foobar",
+ },
ManagedSecurityGroups: &ManagedSecurityGroups{
AllNodesSecurityGroupRules: []SecurityGroupRuleSpec{
{
@@ -142,7 +135,10 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
newTemplate: &OpenStackCluster{
Spec: OpenStackClusterSpec{
- CloudName: "foobar",
+ IdentityRef: OpenStackIdentityReference{
+ Name: "foobar",
+ CloudName: "foobar",
+ },
ManagedSecurityGroups: &ManagedSecurityGroups{
AllNodesSecurityGroupRules: []SecurityGroupRuleSpec{
{
@@ -163,7 +159,10 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
name: "Changing CIDRs on the OpenStackCluster.Spec.APIServerLoadBalancer.AllowedCIDRs is allowed",
oldTemplate: &OpenStackCluster{
Spec: OpenStackClusterSpec{
- CloudName: "foobar",
+ IdentityRef: OpenStackIdentityReference{
+ Name: "foobar",
+ CloudName: "foobar",
+ },
APIServerLoadBalancer: APIServerLoadBalancer{
Enabled: true,
AllowedCIDRs: []string{
@@ -175,7 +174,10 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
newTemplate: &OpenStackCluster{
Spec: OpenStackClusterSpec{
- CloudName: "foobar",
+ IdentityRef: OpenStackIdentityReference{
+ Name: "foobar",
+ CloudName: "foobar",
+ },
APIServerLoadBalancer: APIServerLoadBalancer{
Enabled: true,
AllowedCIDRs: []string{
@@ -192,12 +194,18 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
name: "Adding OpenStackCluster.Spec.ControlPlaneAvailabilityZones is allowed",
oldTemplate: &OpenStackCluster{
Spec: OpenStackClusterSpec{
- CloudName: "foobar",
+ IdentityRef: OpenStackIdentityReference{
+ Name: "foobar",
+ CloudName: "foobar",
+ },
},
},
newTemplate: &OpenStackCluster{
Spec: OpenStackClusterSpec{
- CloudName: "foobar",
+ IdentityRef: OpenStackIdentityReference{
+ Name: "foobar",
+ CloudName: "foobar",
+ },
ControlPlaneAvailabilityZones: []string{
"alice",
"bob",
@@ -210,7 +218,10 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
name: "Modifying OpenStackCluster.Spec.ControlPlaneAvailabilityZones is allowed",
oldTemplate: &OpenStackCluster{
Spec: OpenStackClusterSpec{
- CloudName: "foobar",
+ IdentityRef: OpenStackIdentityReference{
+ Name: "foobar",
+ CloudName: "foobar",
+ },
ControlPlaneAvailabilityZones: []string{
"alice",
"bob",
@@ -219,7 +230,10 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
newTemplate: &OpenStackCluster{
Spec: OpenStackClusterSpec{
- CloudName: "foobar",
+ IdentityRef: OpenStackIdentityReference{
+ Name: "foobar",
+ CloudName: "foobar",
+ },
ControlPlaneAvailabilityZones: []string{
"alice",
"bob",
@@ -233,7 +247,10 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
name: "Removing OpenStackCluster.Spec.ControlPlaneAvailabilityZones is allowed",
oldTemplate: &OpenStackCluster{
Spec: OpenStackClusterSpec{
- CloudName: "foobar",
+ IdentityRef: OpenStackIdentityReference{
+ Name: "foobar",
+ CloudName: "foobar",
+ },
ControlPlaneAvailabilityZones: []string{
"alice",
"bob",
@@ -242,7 +259,10 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
newTemplate: &OpenStackCluster{
Spec: OpenStackClusterSpec{
- CloudName: "foobar",
+ IdentityRef: OpenStackIdentityReference{
+ Name: "foobar",
+ CloudName: "foobar",
+ },
},
},
wantErr: false,
@@ -251,12 +271,18 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
name: "Modifying OpenstackCluster.Spec.ControlPlaneOmitAvailabilityZone is allowed",
oldTemplate: &OpenStackCluster{
Spec: OpenStackClusterSpec{
- CloudName: "foobar",
+ IdentityRef: OpenStackIdentityReference{
+ Name: "foobar",
+ CloudName: "foobar",
+ },
},
},
newTemplate: &OpenStackCluster{
Spec: OpenStackClusterSpec{
- CloudName: "foobar",
+ IdentityRef: OpenStackIdentityReference{
+ Name: "foobar",
+ CloudName: "foobar",
+ },
ControlPlaneOmitAvailabilityZone: true,
},
},
@@ -266,11 +292,19 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
name: "Changing OpenStackCluster.Spec.APIServerFixedIP is allowed when API Server Floating IP is disabled",
oldTemplate: &OpenStackCluster{
Spec: OpenStackClusterSpec{
+ IdentityRef: OpenStackIdentityReference{
+ Name: "foobar",
+ CloudName: "foobar",
+ },
DisableAPIServerFloatingIP: true,
},
},
newTemplate: &OpenStackCluster{
Spec: OpenStackClusterSpec{
+ IdentityRef: OpenStackIdentityReference{
+ Name: "foobar",
+ CloudName: "foobar",
+ },
DisableAPIServerFloatingIP: true,
APIServerFixedIP: "20.1.56.1",
},
@@ -281,11 +315,19 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
name: "Changing OpenStackCluster.Spec.APIServerFixedIP is not allowed",
oldTemplate: &OpenStackCluster{
Spec: OpenStackClusterSpec{
+ IdentityRef: OpenStackIdentityReference{
+ Name: "foobar",
+ CloudName: "foobar",
+ },
DisableAPIServerFloatingIP: false,
},
},
newTemplate: &OpenStackCluster{
Spec: OpenStackClusterSpec{
+ IdentityRef: OpenStackIdentityReference{
+ Name: "foobar",
+ CloudName: "foobar",
+ },
DisableAPIServerFloatingIP: false,
APIServerFixedIP: "20.1.56.1",
},
@@ -297,6 +339,10 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
name: "Changing OpenStackCluster.Spec.APIServerPort is allowed when API Server Floating IP is disabled",
oldTemplate: &OpenStackCluster{
Spec: OpenStackClusterSpec{
+ IdentityRef: OpenStackIdentityReference{
+ Name: "foobar",
+ CloudName: "foobar",
+ },
DisableAPIServerFloatingIP: true,
},
},
@@ -312,11 +358,19 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
name: "Changing OpenStackCluster.Spec.APIServerPort is not allowed",
oldTemplate: &OpenStackCluster{
Spec: OpenStackClusterSpec{
+ IdentityRef: OpenStackIdentityReference{
+ Name: "foobar",
+ CloudName: "foobar",
+ },
DisableAPIServerFloatingIP: false,
},
},
newTemplate: &OpenStackCluster{
Spec: OpenStackClusterSpec{
+ IdentityRef: OpenStackIdentityReference{
+ Name: "foobar",
+ CloudName: "foobar",
+ },
DisableAPIServerFloatingIP: false,
APIServerPort: 8443,
},
@@ -327,6 +381,10 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
name: "Changing OpenStackCluster.Spec.APIServerFloatingIP is allowed when it matches the current api server loadbalancer IP",
oldTemplate: &OpenStackCluster{
Spec: OpenStackClusterSpec{
+ IdentityRef: OpenStackIdentityReference{
+ Name: "foobar",
+ CloudName: "foobar",
+ },
APIServerFloatingIP: "",
},
Status: OpenStackClusterStatus{
@@ -337,6 +395,10 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
newTemplate: &OpenStackCluster{
Spec: OpenStackClusterSpec{
+ IdentityRef: OpenStackIdentityReference{
+ Name: "foobar",
+ CloudName: "foobar",
+ },
APIServerFloatingIP: "1.2.3.4",
},
Status: OpenStackClusterStatus{
@@ -351,6 +413,10 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
name: "Changing OpenStackCluster.Spec.APIServerFloatingIP is not allowed when it doesn't matches the current api server loadbalancer IP",
oldTemplate: &OpenStackCluster{
Spec: OpenStackClusterSpec{
+ IdentityRef: OpenStackIdentityReference{
+ Name: "foobar",
+ CloudName: "foobar",
+ },
APIServerFloatingIP: "",
},
Status: OpenStackClusterStatus{
@@ -361,6 +427,10 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
newTemplate: &OpenStackCluster{
Spec: OpenStackClusterSpec{
+ IdentityRef: OpenStackIdentityReference{
+ Name: "foobar",
+ CloudName: "foobar",
+ },
APIServerFloatingIP: "5.6.7.8",
},
Status: OpenStackClusterStatus{
@@ -375,6 +445,10 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
name: "Removing OpenStackCluster.Spec.Bastion when it is enabled is not allowed",
oldTemplate: &OpenStackCluster{
Spec: OpenStackClusterSpec{
+ IdentityRef: OpenStackIdentityReference{
+ Name: "foobar",
+ CloudName: "foobar",
+ },
Bastion: &Bastion{
Enabled: true,
Instance: OpenStackMachineSpec{
@@ -385,7 +459,12 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
},
newTemplate: &OpenStackCluster{
- Spec: OpenStackClusterSpec{},
+ Spec: OpenStackClusterSpec{
+ IdentityRef: OpenStackIdentityReference{
+ Name: "foobar",
+ CloudName: "foobar",
+ },
+ },
},
wantErr: true,
},
@@ -393,6 +472,10 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
name: "Removing OpenStackCluster.Spec.Bastion when it is disabled is allowed",
oldTemplate: &OpenStackCluster{
Spec: OpenStackClusterSpec{
+ IdentityRef: OpenStackIdentityReference{
+ Name: "foobar",
+ CloudName: "foobar",
+ },
Bastion: &Bastion{
Enabled: false,
Instance: OpenStackMachineSpec{
@@ -403,7 +486,12 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
},
newTemplate: &OpenStackCluster{
- Spec: OpenStackClusterSpec{},
+ Spec: OpenStackClusterSpec{
+ IdentityRef: OpenStackIdentityReference{
+ Name: "foobar",
+ CloudName: "foobar",
+ },
+ },
},
wantErr: false,
},
@@ -434,9 +522,9 @@ func TestOpenStackCluster_ValidateCreate(t *testing.T) {
name: "OpenStackCluster.Spec.IdentityRef with correct spec on create",
template: &OpenStackCluster{
Spec: OpenStackClusterSpec{
- CloudName: "foobar",
- IdentityRef: &OpenStackIdentityReference{
- Name: "foobar",
+ IdentityRef: OpenStackIdentityReference{
+ Name: "foobar",
+ CloudName: "foobar",
},
},
},
@@ -446,7 +534,10 @@ func TestOpenStackCluster_ValidateCreate(t *testing.T) {
name: "OpenStackCluster.Spec.ManagedSecurityGroups.AllNodesSecurityGroupRules with correct spec on create",
template: &OpenStackCluster{
Spec: OpenStackClusterSpec{
- CloudName: "foobar",
+ IdentityRef: OpenStackIdentityReference{
+ Name: "foobar",
+ CloudName: "foobar",
+ },
ManagedSecurityGroups: &ManagedSecurityGroups{
AllNodesSecurityGroupRules: []SecurityGroupRuleSpec{
{
@@ -466,7 +557,10 @@ func TestOpenStackCluster_ValidateCreate(t *testing.T) {
name: "OpenStackCluster.Spec.ManagedSecurityGroups.AllNodesSecurityGroupRules with mutually exclusive fields on create",
template: &OpenStackCluster{
Spec: OpenStackClusterSpec{
- CloudName: "foobar",
+ IdentityRef: OpenStackIdentityReference{
+ Name: "foobar",
+ CloudName: "foobar",
+ },
ManagedSecurityGroups: &ManagedSecurityGroups{
AllNodesSecurityGroupRules: []SecurityGroupRuleSpec{
{
diff --git a/api/v1beta1/openstackmachine_types.go b/api/v1beta1/openstackmachine_types.go
index c3f5ea367b..9e36fa9dd8 100644
--- a/api/v1beta1/openstackmachine_types.go
+++ b/api/v1beta1/openstackmachine_types.go
@@ -38,10 +38,6 @@ type OpenStackMachineSpec struct {
// 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"`
@@ -88,7 +84,9 @@ type OpenStackMachineSpec struct {
// +optional
ServerGroup *ServerGroupFilter `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"`
}
diff --git a/api/v1beta1/openstackmachine_webhook.go b/api/v1beta1/openstackmachine_webhook.go
index 221dc0c673..93c91c5ffa 100644
--- a/api/v1beta1/openstackmachine_webhook.go
+++ b/api/v1beta1/openstackmachine_webhook.go
@@ -98,6 +98,10 @@ func (r *OpenStackMachine) ValidateUpdate(old runtime.Object) (admission.Warning
delete(newOpenStackMachineSpec, "instanceID")
}
+ // allow changes to identifyRef
+ delete(oldOpenStackMachineSpec, "identityRef")
+ delete(newOpenStackMachineSpec, "identityRef")
+
if !reflect.DeepEqual(oldOpenStackMachineSpec, newOpenStackMachineSpec) {
allErrs = append(allErrs, field.Forbidden(field.NewPath("spec"), "cannot be modified"))
}
diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go
index 4a1265d991..b66e1869c8 100644
--- a/api/v1beta1/zz_generated.deepcopy.go
+++ b/api/v1beta1/zz_generated.deepcopy.go
@@ -490,11 +490,7 @@ func (in *OpenStackClusterSpec) DeepCopyInto(out *OpenStackClusterSpec) {
*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.
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 a6b962ee77..195071619b 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -4975,10 +4975,6 @@ spec:
x-kubernetes-list-map-keys:
- name
x-kubernetes-list-type: map
- cloudName:
- description: The name of the cloud to use from the clouds
- secret
- type: string
configDrive:
description: Config Drive support
type: boolean
@@ -4987,16 +4983,23 @@ spec:
server instance.
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 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 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.
type: string
required:
+ - cloudName
- name
type: object
image:
@@ -5345,9 +5348,6 @@ spec:
- flavor
type: object
type: object
- cloudName:
- description: The name of the cloud to use from the clouds secret
- type: string
controlPlaneAvailabilityZones:
description: ControlPlaneAvailabilityZones is the az to deploy control
plane to
@@ -5467,16 +5467,23 @@ spec:
type: object
type: array
identityRef:
- description: IdentityRef is a reference to a identity to be used when
- reconciling this cluster
+ 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 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.
type: string
required:
+ - cloudName
- name
type: object
managedSecurityGroups:
@@ -5711,6 +5718,8 @@ spec:
type: string
type: array
x-kubernetes-list-type: set
+ required:
+ - identityRef
type: object
status:
description: OpenStackClusterStatus defines the observed state of OpenStackCluster.
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 09775b2e75..ff668645be 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -2400,10 +2400,6 @@ spec:
x-kubernetes-list-map-keys:
- name
x-kubernetes-list-type: map
- cloudName:
- description: The name of the cloud to use from the
- clouds secret
- type: string
configDrive:
description: Config Drive support
type: boolean
@@ -2412,16 +2408,23 @@ spec:
your server instance.
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 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 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.
type: string
required:
+ - cloudName
- name
type: object
image:
@@ -2777,10 +2780,6 @@ spec:
- flavor
type: object
type: object
- cloudName:
- description: The name of the cloud to use from the clouds
- secret
- type: string
controlPlaneAvailabilityZones:
description: ControlPlaneAvailabilityZones is the az to deploy
control plane to
@@ -2900,16 +2899,23 @@ spec:
type: object
type: array
identityRef:
- description: IdentityRef is a reference to a identity to be
- used when reconciling this cluster
+ 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 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.
type: string
required:
+ - cloudName
- name
type: object
managedSecurityGroups:
@@ -3146,6 +3152,8 @@ spec:
type: string
type: array
x-kubernetes-list-type: set
+ required:
+ - identityRef
type: object
required:
- spec
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 0270d47c6c..7fbeee04e3 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
@@ -1778,9 +1778,6 @@ spec:
x-kubernetes-list-map-keys:
- name
x-kubernetes-list-type: map
- cloudName:
- description: The name of the cloud to use from the clouds secret
- type: string
configDrive:
description: Config Drive support
type: boolean
@@ -1788,16 +1785,23 @@ spec:
description: The flavor reference for the flavor for your server instance.
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 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 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.
type: string
required:
+ - cloudName
- name
type: object
image:
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 d3d7f9d9fc..ca42ad199f 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
@@ -1450,10 +1450,6 @@ spec:
x-kubernetes-list-map-keys:
- name
x-kubernetes-list-type: map
- cloudName:
- description: The name of the cloud to use from the clouds
- secret
- type: string
configDrive:
description: Config Drive support
type: boolean
@@ -1462,16 +1458,23 @@ spec:
server instance.
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 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 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.
type: string
required:
+ - cloudName
- name
type: object
image:
diff --git a/controllers/openstackmachine_controller_test.go b/controllers/openstackmachine_controller_test.go
index a541795528..a03120ce5e 100644
--- a/controllers/openstackmachine_controller_test.go
+++ b/controllers/openstackmachine_controller_test.go
@@ -82,7 +82,6 @@ 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: infrav1.ImageFilter{ID: imageUUID},
SSHKeyName: sshKeyName,
diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md
index ac6b13a425..48c293c608 100644
--- a/docs/book/src/api/v1beta1/api.md
+++ b/docs/book/src/api/v1beta1/api.md
@@ -69,18 +69,6 @@ OpenStackClusterSpec
-cloudName
-
-string
-
- |
-
-(Optional)
- The name of the cloud to use from the clouds secret
- |
-
-
-
managedSubnets
@@ -387,8 +375,9 @@ OpenStackIdentityReference
|
-(Optional)
- 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 cluster. It is also to reconcile
+machines unless overridden in the machine spec.
|
@@ -559,18 +548,6 @@ string
-cloudName
-
-string
-
- |
-
-(Optional)
- The name of the cloud to use from the clouds secret
- |
-
-
-
flavor
string
@@ -731,7 +708,9 @@ OpenStackIdentityReference
|
(Optional)
- 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.
|
@@ -1897,18 +1876,6 @@ NetworkStatus
-cloudName
-
-string
-
- |
-
-(Optional)
- The name of the cloud to use from the clouds secret
- |
-
-
-
managedSubnets
@@ -2215,8 +2182,9 @@ OpenStackIdentityReference
|
-(Optional)
- 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 cluster. It is also to reconcile
+machines unless overridden in the machine spec.
|
@@ -2453,18 +2421,6 @@ OpenStackClusterSpec
-cloudName
-
-string
-
- |
-
-(Optional)
- The name of the cloud to use from the clouds secret
- |
-
-
-
managedSubnets
@@ -2771,8 +2727,9 @@ OpenStackIdentityReference
|
-(Optional)
- 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 cluster. It is also to reconcile
+machines unless overridden in the machine spec.
|
@@ -2838,9 +2795,20 @@ 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.
+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.
+ |
+
+
+
+cloudName
+
+string
+
+ |
+
+ CloudName specifies the name of the entry in the clouds.yaml file to use.
|
@@ -2888,18 +2856,6 @@ string
-cloudName
-
-string
-
- |
-
-(Optional)
- The name of the cloud to use from the clouds secret
- |
-
-
-
flavor
string
@@ -3060,7 +3016,9 @@ OpenStackIdentityReference
|
(Optional)
- 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.
|
@@ -3251,18 +3209,6 @@ string
-cloudName
-
-string
-
- |
-
-(Optional)
- The name of the cloud to use from the clouds secret
- |
-
-
-
flavor
string
@@ -3423,7 +3369,9 @@ OpenStackIdentityReference
|
(Optional)
- 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.
|
diff --git a/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md b/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
index 6028c9de31..3087e41929 100644
--- a/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
+++ b/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
@@ -5,12 +5,16 @@
- [v1alpha7 compared to v1beta1](#v1alpha7-compared-to-v1beta1)
- [Migration](#migration)
- [API Changes](#api-changes)
- - [`OpenStackMachine`](#openstackmachine)
+ - [Changes to `identityRef` in both `OpenStackMachine` and `OpenStackCluster`](#changes-to-identityref-in-both-openstackmachine-and-openstackcluster)
- [Removal of machine identityRef.kind](#removal-of-machine-identityrefkind)
+ - [Addition of cloudName](#addition-of-cloudname)
+ - [`OpenStackMachine`](#openstackmachine)
+ - [Removal of cloudName](#removal-of-cloudname)
- [Change to serverGroupID](#change-to-servergroupid)
- [Changes to ports](#changes-to-ports)
- [`OpenStackCluster`](#openstackcluster)
- - [Removal of cluster identityRef.kind](#removal-of-cluster-identityrefkind)
+ - [Removal of cloudName](#removal-of-cloudname-1)
+ - [identityRef is now required](#identityref-is-now-required)
- [Change to externalNetworkID](#change-to-externalnetworkid)
- [Change to image](#change-to-image)
- [Removal of imageUUID](#removal-of-imageuuid)
@@ -36,11 +40,21 @@ All users are encouraged to migrate their usage of the CAPO CRDs from older vers
This only documents backwards incompatible changes. Fields that were added to v1beta1 are not listed here.
-### `OpenStackMachine`
+### Changes to `identityRef` in both `OpenStackMachine` and `OpenStackCluster`
#### Removal of machine identityRef.kind
-The `identityRef.Kind` field has been removed. It was used to specify the kind of the identity provider to use but was actually ignored.
+The `identityRef.Kind` field has been removed. It was used to specify the kind of the identity provider to use but was actually ignored. The referenced resource must always be a Secret.
+
+#### Addition of cloudName
+
+The `cloudName` field has been removed from both `OpenStackMachine` and `OpenStackCluster` and added to `identityRef`. It is now a required field when `identityRef` is specified.
+
+### `OpenStackMachine`
+
+#### Removal of cloudName
+
+This has moved to `identityRef.cloudName`.
#### Change to serverGroupID
@@ -83,9 +97,15 @@ Setting either of the following fields explicitly to the empty string would prev
### `OpenStackCluster`
-#### Removal of cluster identityRef.kind
+#### Removal of cloudName
+
+This has moved to `identityRef.cloudName`.
+
+#### identityRef is now required
+
+The API server would previously accept an `OpenStackCluster` without an `identityRef`, although the controller would generate an error. In v1beta1 the API server will no longer accept an `OpenStackCluster` without an `identityRef`.
-The `identityRef.Kind` field has been removed. It was used to specify the kind of the identity provider to use but was actually ignored.
+Note that this is in contrast `identityRef` in `OpenStackMachine`, which remains optional: `OpenStackMachine` will default to the credentials in `OpenStackCluster` if not specified.
#### Change to externalNetworkID
diff --git a/kustomize/v1beta1/default/cluster-template.yaml b/kustomize/v1beta1/default/cluster-template.yaml
index f626c0328f..52ab6c2f88 100644
--- a/kustomize/v1beta1/default/cluster-template.yaml
+++ b/kustomize/v1beta1/default/cluster-template.yaml
@@ -22,9 +22,9 @@ kind: OpenStackCluster
metadata:
name: ${CLUSTER_NAME}
spec:
- cloudName: ${OPENSTACK_CLOUD}
identityRef:
name: ${CLUSTER_NAME}-cloud-config
+ cloudName: ${OPENSTACK_CLOUD}
apiServerLoadBalancer:
enabled: true
managedSubnets:
@@ -99,9 +99,6 @@ spec:
image:
name: ${OPENSTACK_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
- cloudName: ${OPENSTACK_CLOUD}
- identityRef:
- name: ${CLUSTER_NAME}-cloud-config
---
apiVersion: cluster.x-k8s.io/v1beta1
kind: MachineDeployment
@@ -134,9 +131,6 @@ metadata:
spec:
template:
spec:
- cloudName: ${OPENSTACK_CLOUD}
- identityRef:
- name: ${CLUSTER_NAME}-cloud-config
flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR}
image:
name: ${OPENSTACK_IMAGE_NAME}
diff --git a/pkg/scope/provider.go b/pkg/scope/provider.go
index cda179d2e6..d20cee5bc2 100644
--- a/pkg/scope/provider.go
+++ b/pkg/scope/provider.go
@@ -57,18 +57,20 @@ func (f *providerScopeFactory) NewClientScopeFromMachine(ctx context.Context, ct
var cloud clientconfig.Cloud
var caCert []byte
+ var identityRef *infrav1.OpenStackIdentityReference
+ var namespace string
if openStackMachine.Spec.IdentityRef != nil {
- var err error
- cloud, caCert, err = getCloudFromSecret(ctx, ctrlClient, openStackMachine.Namespace, openStackMachine.Spec.IdentityRef.Name, openStackMachine.Spec.CloudName)
- if err != nil {
- return nil, err
- }
- } else if openStackCluster.Spec.IdentityRef != nil {
- var err error
- cloud, caCert, err = getCloudFromSecret(ctx, ctrlClient, openStackCluster.Namespace, openStackCluster.Spec.IdentityRef.Name, openStackCluster.Spec.CloudName)
- if err != nil {
- return nil, err
- }
+ identityRef = openStackMachine.Spec.IdentityRef
+ namespace = openStackMachine.Namespace
+ } else {
+ identityRef = &openStackCluster.Spec.IdentityRef
+ namespace = openStackCluster.Namespace
+ }
+
+ var err error
+ cloud, caCert, err = getCloudFromSecret(ctx, ctrlClient, namespace, identityRef.Name, identityRef.CloudName)
+ if err != nil {
+ return nil, err
}
if caCert == nil {
@@ -86,12 +88,10 @@ func (f *providerScopeFactory) NewClientScopeFromCluster(ctx context.Context, ct
var cloud clientconfig.Cloud
var caCert []byte
- if openStackCluster.Spec.IdentityRef != nil {
- var err error
- cloud, caCert, err = getCloudFromSecret(ctx, ctrlClient, openStackCluster.Namespace, openStackCluster.Spec.IdentityRef.Name, openStackCluster.Spec.CloudName)
- if err != nil {
- return nil, err
- }
+ var err error
+ cloud, caCert, err = getCloudFromSecret(ctx, ctrlClient, openStackCluster.Namespace, openStackCluster.Spec.IdentityRef.Name, openStackCluster.Spec.IdentityRef.CloudName)
+ if err != nil {
+ return nil, err
}
if caCert == nil {
diff --git a/templates/cluster-template-flatcar-sysext.yaml b/templates/cluster-template-flatcar-sysext.yaml
index 809f386085..360ff1c005 100644
--- a/templates/cluster-template-flatcar-sysext.yaml
+++ b/templates/cluster-template-flatcar-sysext.yaml
@@ -224,10 +224,10 @@ kind: OpenStackCluster
metadata:
name: ${CLUSTER_NAME}
spec:
- cloudName: ${OPENSTACK_CLOUD}
externalNetwork:
id: ${OPENSTACK_EXTERNAL_NETWORK_ID}
identityRef:
+ cloudName: ${OPENSTACK_CLOUD}
name: ${CLUSTER_NAME}-cloud-config
managedSecurityGroups:
allNodesSecurityGroupRules:
@@ -261,10 +261,7 @@ metadata:
spec:
template:
spec:
- cloudName: ${OPENSTACK_CLOUD}
flavor: ${OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR}
- identityRef:
- name: ${CLUSTER_NAME}-cloud-config
image:
name: ${FLATCAR_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
@@ -276,10 +273,7 @@ metadata:
spec:
template:
spec:
- cloudName: ${OPENSTACK_CLOUD}
flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR}
- identityRef:
- name: ${CLUSTER_NAME}-cloud-config
image:
name: ${FLATCAR_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
diff --git a/templates/cluster-template-flatcar.yaml b/templates/cluster-template-flatcar.yaml
index a0db85b493..691a98daee 100644
--- a/templates/cluster-template-flatcar.yaml
+++ b/templates/cluster-template-flatcar.yaml
@@ -148,10 +148,10 @@ kind: OpenStackCluster
metadata:
name: ${CLUSTER_NAME}
spec:
- cloudName: ${OPENSTACK_CLOUD}
externalNetwork:
id: ${OPENSTACK_EXTERNAL_NETWORK_ID}
identityRef:
+ cloudName: ${OPENSTACK_CLOUD}
name: ${CLUSTER_NAME}-cloud-config
managedSecurityGroups:
allNodesSecurityGroupRules:
@@ -185,10 +185,7 @@ metadata:
spec:
template:
spec:
- cloudName: ${OPENSTACK_CLOUD}
flavor: ${OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR}
- identityRef:
- name: ${CLUSTER_NAME}-cloud-config
image:
name: ${OPENSTACK_FLATCAR_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
@@ -200,10 +197,7 @@ metadata:
spec:
template:
spec:
- cloudName: ${OPENSTACK_CLOUD}
flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR}
- identityRef:
- name: ${CLUSTER_NAME}-cloud-config
image:
name: ${OPENSTACK_FLATCAR_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
diff --git a/templates/cluster-template-without-lb.yaml b/templates/cluster-template-without-lb.yaml
index cc560e5571..35acfdbdf1 100644
--- a/templates/cluster-template-without-lb.yaml
+++ b/templates/cluster-template-without-lb.yaml
@@ -105,10 +105,10 @@ kind: OpenStackCluster
metadata:
name: ${CLUSTER_NAME}
spec:
- cloudName: ${OPENSTACK_CLOUD}
externalNetwork:
id: ${OPENSTACK_EXTERNAL_NETWORK_ID}
identityRef:
+ cloudName: ${OPENSTACK_CLOUD}
name: ${CLUSTER_NAME}-cloud-config
managedSecurityGroups:
allNodesSecurityGroupRules:
@@ -142,10 +142,7 @@ metadata:
spec:
template:
spec:
- cloudName: ${OPENSTACK_CLOUD}
flavor: ${OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR}
- identityRef:
- name: ${CLUSTER_NAME}-cloud-config
image:
name: ${OPENSTACK_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
@@ -157,10 +154,7 @@ metadata:
spec:
template:
spec:
- cloudName: ${OPENSTACK_CLOUD}
flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR}
- identityRef:
- name: ${CLUSTER_NAME}-cloud-config
image:
name: ${OPENSTACK_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
diff --git a/templates/cluster-template.yaml b/templates/cluster-template.yaml
index b8cb9db972..bc8c8aab8c 100644
--- a/templates/cluster-template.yaml
+++ b/templates/cluster-template.yaml
@@ -107,10 +107,10 @@ metadata:
spec:
apiServerLoadBalancer:
enabled: true
- cloudName: ${OPENSTACK_CLOUD}
externalNetwork:
id: ${OPENSTACK_EXTERNAL_NETWORK_ID}
identityRef:
+ cloudName: ${OPENSTACK_CLOUD}
name: ${CLUSTER_NAME}-cloud-config
managedSecurityGroups:
allNodesSecurityGroupRules:
@@ -144,10 +144,7 @@ metadata:
spec:
template:
spec:
- cloudName: ${OPENSTACK_CLOUD}
flavor: ${OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR}
- identityRef:
- name: ${CLUSTER_NAME}-cloud-config
image:
name: ${OPENSTACK_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
@@ -159,10 +156,7 @@ metadata:
spec:
template:
spec:
- cloudName: ${OPENSTACK_CLOUD}
flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR}
- identityRef:
- name: ${CLUSTER_NAME}-cloud-config
image:
name: ${OPENSTACK_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
diff --git a/templates/clusterclass-dev-test.yaml b/templates/clusterclass-dev-test.yaml
index c329fd5831..2cd3a38531 100644
--- a/templates/clusterclass-dev-test.yaml
+++ b/templates/clusterclass-dev-test.yaml
@@ -117,9 +117,9 @@ spec:
spec:
apiServerLoadBalancer:
enabled: true
- cloudName: ${OPENSTACK_CLOUD:=capo-e2e}
identityRef:
name: dev-test-cloud-config
+ cloudName: ${OPENSTACK_CLOUD:=capo-e2e}
managedSecurityGroups:
allNodesSecurityGroupRules:
- description: Created by cluster-api-provider-openstack - BGP (calico)
@@ -152,10 +152,7 @@ metadata:
spec:
template:
spec:
- cloudName: ${OPENSTACK_CLOUD:=capo-e2e}
flavor: ${OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR:=m1.medium}
- identityRef:
- name: dev-test-cloud-config
image:
name: overridden-by-patch
sshKeyName: ${OPENSTACK_SSH_KEY_NAME:=""}
@@ -167,10 +164,7 @@ metadata:
spec:
template:
spec:
- cloudName: ${OPENSTACK_CLOUD:=capo-e2e}
flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR:=m1.small}
- identityRef:
- name: dev-test-cloud-config
image:
name: overridden-by-patch
sshKeyName: ${OPENSTACK_SSH_KEY_NAME:=""}
diff --git a/test/e2e/suites/e2e/e2e_test.go b/test/e2e/suites/e2e/e2e_test.go
index 4443c500dd..c184f96011 100644
--- a/test/e2e/suites/e2e/e2e_test.go
+++ b/test/e2e/suites/e2e/e2e_test.go
@@ -864,9 +864,9 @@ func makeOpenStackMachineTemplate(namespace, clusterName, name string) *infrav1.
Name: e2eCtx.E2EConfig.GetVariable(shared.OpenStackImageName),
},
SSHKeyName: shared.DefaultSSHKeyPairName,
- CloudName: e2eCtx.E2EConfig.GetVariable(shared.OpenStackCloud),
IdentityRef: &infrav1.OpenStackIdentityReference{
- Name: fmt.Sprintf("%s-cloud-config", clusterName),
+ Name: fmt.Sprintf("%s-cloud-config", clusterName),
+ CloudName: e2eCtx.E2EConfig.GetVariable(shared.OpenStackCloud),
},
},
},
@@ -888,9 +888,9 @@ func makeOpenStackMachineTemplateWithPortOptions(namespace, clusterName, name st
Name: e2eCtx.E2EConfig.GetVariable(shared.OpenStackImageName),
},
SSHKeyName: shared.DefaultSSHKeyPairName,
- CloudName: e2eCtx.E2EConfig.GetVariable(shared.OpenStackCloud),
IdentityRef: &infrav1.OpenStackIdentityReference{
- Name: fmt.Sprintf("%s-cloud-config", clusterName),
+ Name: fmt.Sprintf("%s-cloud-config", clusterName),
+ CloudName: e2eCtx.E2EConfig.GetVariable(shared.OpenStackCloud),
},
Ports: *portOpts,
Tags: machineTags,
From 7927f657fe9c2633babfafbcf6dffa6a7d07728a Mon Sep 17 00:00:00 2001
From: Emilien Macchi
Date: Mon, 26 Feb 2024 15:13:48 -0500
Subject: [PATCH 088/180] Transform neutron filter tags into slices
Co-Authored-By: Matthew Booth
---
api/v1alpha5/conversion.go | 79 ++-
api/v1alpha5/zz_generated.conversion.go | 154 +++--
api/v1alpha6/conversion.go | 171 ++++-
api/v1alpha6/conversion_test.go | 82 ++-
api/v1alpha6/zz_generated.conversion.go | 154 +++--
api/v1alpha7/conversion.go | 157 ++++-
api/v1alpha7/conversion_test.go | 70 ++
api/v1alpha7/zz_generated.conversion.go | 280 ++++----
api/v1beta1/filter_convert.go | 99 ++-
api/v1beta1/types.go | 57 +-
api/v1beta1/zz_generated.deepcopy.go | 67 +-
...re.cluster.x-k8s.io_openstackclusters.yaml | 636 ++++++++++++++++--
...er.x-k8s.io_openstackclustertemplates.yaml | 477 ++++++++++++-
...re.cluster.x-k8s.io_openstackmachines.yaml | 371 +++++++++-
...er.x-k8s.io_openstackmachinetemplates.yaml | 212 +++++-
controllers/openstackcluster_controller.go | 3 +-
docs/book/src/api/v1beta1/api.md | 248 ++++---
.../topics/crd-changes/v1alpha7-to-v1beta1.md | 31 +
pkg/cloud/services/networking/network.go | 2 +-
pkg/cloud/services/networking/port.go | 2 +-
pkg/cloud/services/networking/port_test.go | 4 +-
21 files changed, 2712 insertions(+), 644 deletions(-)
diff --git a/api/v1alpha5/conversion.go b/api/v1alpha5/conversion.go
index 39901bfd2e..8b31518c2e 100644
--- a/api/v1alpha5/conversion.go
+++ b/api/v1alpha5/conversion.go
@@ -475,20 +475,6 @@ func Convert_v1beta1_NetworkStatus_To_v1alpha5_Network(in *infrav1.NetworkStatus
return nil
}
-func Convert_v1alpha5_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in *SecurityGroupFilter, out *infrav1.SecurityGroupFilter, s conversion.Scope) error {
- err := autoConvert_v1alpha5_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in, out, s)
- if err != nil {
- return err
- }
-
- // 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_v1alpha5_SecurityGroupParam_To_v1beta1_SecurityGroupFilter(in *SecurityGroupParam, out *infrav1.SecurityGroupFilter, s conversion.Scope) error {
// SecurityGroupParam is replaced by its contained SecurityGroupFilter in v1beta1
err := Convert_v1alpha5_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(&in.Filter, out, s)
@@ -521,16 +507,20 @@ func Convert_v1beta1_SecurityGroupFilter_To_v1alpha5_SecurityGroupParam(in *infr
return nil
}
-func Convert_v1alpha5_SubnetParam_To_v1beta1_SubnetFilter(in *SubnetParam, out *infrav1.SubnetFilter, _ conversion.Scope) error {
- *out = infrav1.SubnetFilter(in.Filter)
+func Convert_v1alpha5_SubnetParam_To_v1beta1_SubnetFilter(in *SubnetParam, out *infrav1.SubnetFilter, s conversion.Scope) error {
+ if err := Convert_v1alpha5_SubnetFilter_To_v1beta1_SubnetFilter(&in.Filter, out, s); err != nil {
+ return err
+ }
if in.UUID != "" {
out.ID = in.UUID
}
return nil
}
-func Convert_v1beta1_SubnetFilter_To_v1alpha5_SubnetParam(in *infrav1.SubnetFilter, out *SubnetParam, _ conversion.Scope) error {
- out.Filter = SubnetFilter(*in)
+func Convert_v1beta1_SubnetFilter_To_v1alpha5_SubnetParam(in *infrav1.SubnetFilter, out *SubnetParam, s conversion.Scope) error {
+ if err := Convert_v1beta1_SubnetFilter_To_v1alpha5_SubnetFilter(in, &out.Filter, s); err != nil {
+ return err
+ }
out.UUID = in.ID
return nil
@@ -718,3 +708,56 @@ func Convert_v1beta1_OpenStackIdentityReference_To_v1alpha5_OpenStackIdentityRef
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_NetworkFilter(in *NetworkFilter, out *infrav1.NetworkFilter, s conversion.Scope) error {
+ if err := autoConvert_v1alpha5_NetworkFilter_To_v1beta1_NetworkFilter(in, out, s); err != nil {
+ return err
+ }
+ infrav1.ConvertAllTagsTo(in.Tags, in.TagsAny, in.NotTags, in.NotTagsAny, &out.FilterByNeutronTags)
+ return nil
+}
+
+func Convert_v1beta1_NetworkFilter_To_v1alpha5_NetworkFilter(in *infrav1.NetworkFilter, out *NetworkFilter, s conversion.Scope) error {
+ if err := autoConvert_v1beta1_NetworkFilter_To_v1alpha5_NetworkFilter(in, out, s); err != nil {
+ return err
+ }
+ infrav1.ConvertAllTagsFrom(&in.FilterByNeutronTags, &out.Tags, &out.TagsAny, &out.NotTags, &out.NotTagsAny)
+ return nil
+}
diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go
index c6d7dc4e49..646ce0a938 100644
--- a/api/v1alpha5/zz_generated.conversion.go
+++ b/api/v1alpha5/zz_generated.conversion.go
@@ -81,16 +81,6 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*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((*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.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 {
@@ -236,11 +226,6 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*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.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 {
@@ -251,16 +236,6 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*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((*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 {
@@ -271,6 +246,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
+ 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.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 {
@@ -321,6 +301,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
+ 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((*SubnetParam)(nil), (*v1beta1.SubnetFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha5_SubnetParam_To_v1beta1_SubnetFilter(a.(*SubnetParam), b.(*v1beta1.SubnetFilter), scope)
}); err != nil {
@@ -346,6 +331,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); 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_v1alpha5_NetworkFilter(a.(*v1beta1.NetworkFilter), b.(*NetworkFilter), scope)
+ }); err != nil {
+ return err
+ }
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 {
@@ -386,6 +376,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); 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_v1alpha5_SecurityGroupFilter(a.(*v1beta1.SecurityGroupFilter), b.(*SecurityGroupFilter), scope)
+ }); err != nil {
+ return err
+ }
if err := s.AddConversionFunc((*v1beta1.SecurityGroupFilter)(nil), (*SecurityGroupParam)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_SecurityGroupFilter_To_v1alpha5_SecurityGroupParam(a.(*v1beta1.SecurityGroupFilter), b.(*SecurityGroupParam), scope)
}); err != nil {
@@ -396,6 +391,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); 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.SubnetFilter)(nil), (*SubnetParam)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_SubnetFilter_To_v1alpha5_SubnetParam(a.(*v1beta1.SubnetFilter), b.(*SubnetParam), scope)
}); err != nil {
@@ -496,7 +496,15 @@ func Convert_v1beta1_ExternalRouterIPParam_To_v1alpha5_ExternalRouterIPParam(in
}
func autoConvert_v1alpha5_FixedIP_To_v1beta1_FixedIP(in *FixedIP, out *v1beta1.FixedIP, s conversion.Scope) error {
- out.Subnet = (*v1beta1.SubnetFilter)(unsafe.Pointer(in.Subnet))
+ if in.Subnet != nil {
+ in, out := &in.Subnet, &out.Subnet
+ *out = new(v1beta1.SubnetFilter)
+ if err := Convert_v1alpha5_SubnetFilter_To_v1beta1_SubnetFilter(*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
}
@@ -509,7 +517,15 @@ func Convert_v1alpha5_FixedIP_To_v1beta1_FixedIP(in *FixedIP, out *v1beta1.Fixed
}
func autoConvert_v1beta1_FixedIP_To_v1alpha5_FixedIP(in *v1beta1.FixedIP, out *FixedIP, s conversion.Scope) error {
- out.Subnet = (*SubnetFilter)(unsafe.Pointer(in.Subnet))
+ if in.Subnet != nil {
+ in, out := &in.Subnet, &out.Subnet
+ *out = new(SubnetFilter)
+ if err := Convert_v1beta1_SubnetFilter_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
}
@@ -550,35 +566,22 @@ func autoConvert_v1alpha5_NetworkFilter_To_v1beta1_NetworkFilter(in *NetworkFilt
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.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_v1beta1_NetworkFilter is an autogenerated conversion function.
-func Convert_v1alpha5_NetworkFilter_To_v1beta1_NetworkFilter(in *NetworkFilter, out *v1beta1.NetworkFilter, s conversion.Scope) error {
- return autoConvert_v1alpha5_NetworkFilter_To_v1beta1_NetworkFilter(in, out, s)
-}
-
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
}
-// Convert_v1beta1_NetworkFilter_To_v1alpha5_NetworkFilter is an autogenerated conversion function.
-func Convert_v1beta1_NetworkFilter_To_v1alpha5_NetworkFilter(in *v1beta1.NetworkFilter, out *NetworkFilter, s conversion.Scope) error {
- return autoConvert_v1beta1_NetworkFilter_To_v1alpha5_NetworkFilter(in, out, s)
-}
-
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_v1beta1_OpenStackClusterSpec(&in.Spec, &out.Spec, s); err != nil {
@@ -1316,7 +1319,15 @@ func Convert_v1beta1_OpenStackMachineTemplateSpec_To_v1alpha5_OpenStackMachineTe
}
func autoConvert_v1alpha5_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *v1beta1.PortOpts, s conversion.Scope) error {
- out.Network = (*v1beta1.NetworkFilter)(unsafe.Pointer(in.Network))
+ if in.Network != nil {
+ in, out := &in.Network, &out.Network
+ *out = new(v1beta1.NetworkFilter)
+ if err := Convert_v1alpha5_NetworkFilter_To_v1beta1_NetworkFilter(*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
}
@@ -1367,7 +1378,15 @@ func autoConvert_v1alpha5_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *v1beta
}
func autoConvert_v1beta1_PortOpts_To_v1alpha5_PortOpts(in *v1beta1.PortOpts, out *PortOpts, s conversion.Scope) error {
- out.Network = (*NetworkFilter)(unsafe.Pointer(in.Network))
+ if in.Network != nil {
+ in, out := &in.Network, &out.Network
+ *out = new(NetworkFilter)
+ if err := Convert_v1beta1_NetworkFilter_To_v1alpha5_NetworkFilter(*in, *out, s); err != nil {
+ return err
+ }
+ } else {
+ out.Network = nil
+ }
if err := optional.Convert_optional_String_To_string(&in.NameSuffix, &out.NameSuffix, s); err != nil {
return err
}
@@ -1486,10 +1505,10 @@ func autoConvert_v1alpha5_SecurityGroupFilter_To_v1beta1_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
}
@@ -1498,18 +1517,10 @@ func autoConvert_v1beta1_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(in
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_v1beta1_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter is an autogenerated conversion function.
-func Convert_v1beta1_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(in *v1beta1.SecurityGroupFilter, out *SecurityGroupFilter, s conversion.Scope) error {
- return autoConvert_v1beta1_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(in, out, s)
-}
-
func autoConvert_v1alpha5_Subnet_To_v1beta1_Subnet(in *Subnet, out *v1beta1.Subnet, s conversion.Scope) error {
out.Name = in.Name
out.ID = in.ID
@@ -1546,18 +1557,13 @@ func autoConvert_v1alpha5_SubnetFilter_To_v1beta1_SubnetFilter(in *SubnetFilter,
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.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_v1beta1_SubnetFilter is an autogenerated conversion function.
-func Convert_v1alpha5_SubnetFilter_To_v1beta1_SubnetFilter(in *SubnetFilter, out *v1beta1.SubnetFilter, s conversion.Scope) error {
- return autoConvert_v1alpha5_SubnetFilter_To_v1beta1_SubnetFilter(in, out, s)
-}
-
func autoConvert_v1beta1_SubnetFilter_To_v1alpha5_SubnetFilter(in *v1beta1.SubnetFilter, out *SubnetFilter, s conversion.Scope) error {
out.Name = in.Name
out.Description = in.Description
@@ -1568,14 +1574,6 @@ func autoConvert_v1beta1_SubnetFilter_To_v1alpha5_SubnetFilter(in *v1beta1.Subne
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
}
-
-// Convert_v1beta1_SubnetFilter_To_v1alpha5_SubnetFilter is an autogenerated conversion function.
-func Convert_v1beta1_SubnetFilter_To_v1alpha5_SubnetFilter(in *v1beta1.SubnetFilter, out *SubnetFilter, s conversion.Scope) error {
- return autoConvert_v1beta1_SubnetFilter_To_v1alpha5_SubnetFilter(in, out, s)
-}
diff --git a/api/v1alpha6/conversion.go b/api/v1alpha6/conversion.go
index 5526561dbe..dbdcde2687 100644
--- a/api/v1alpha6/conversion.go
+++ b/api/v1alpha6/conversion.go
@@ -30,6 +30,33 @@ import (
const trueString = "true"
+func restorev1alpha6SubnetFilter(previous *SubnetFilter, dst *SubnetFilter) {
+ // 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 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 restorev1alpha6NetworkFilter(previous *NetworkFilter, dst *NetworkFilter) {
+ // 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 restorev1alpha6SecurityGroup(previous *SecurityGroup, dst *SecurityGroup) {
if previous == nil || dst == nil {
return
@@ -40,6 +67,29 @@ func restorev1alpha6SecurityGroup(previous *SecurityGroup, dst *SecurityGroup) {
}
}
+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)
+ }
+ }
+
+ if dst.Network != nil && previous.Network != nil {
+ 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 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.
@@ -76,6 +126,18 @@ func restorev1alpha6MachineSpec(previous *OpenStackMachineSpec, dst *OpenStackMa
// 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)
+ }
+ }
}
func restorev1alpha6ClusterStatus(previous *OpenStackClusterStatus, dst *OpenStackClusterStatus) {
@@ -171,6 +233,16 @@ func restorev1alpha6ClusterSpec(previous *OpenStackClusterSpec, dst *OpenStackCl
// Conversion to v1beta1 removes the Kind field
dst.IdentityRef = previous.IdentityRef
+
+ if len(dst.ExternalRouterIPs) == len(previous.ExternalRouterIPs) {
+ for i := range dst.ExternalRouterIPs {
+ restorev1alpha6SubnetFilter(&previous.ExternalRouterIPs[i].Subnet.Filter, &dst.ExternalRouterIPs[i].Subnet.Filter)
+ }
+ }
+
+ restorev1alpha6SubnetFilter(&previous.Subnet, &dst.Subnet)
+
+ restorev1alpha6NetworkFilter(&previous.Network, &dst.Network)
}
var _ ctrlconversion.Convertible = &OpenStackCluster{}
@@ -492,7 +564,10 @@ func Convert_v1alpha6_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(in *O
}
if len(in.Networks) > 0 {
- ports := convertNetworksToPorts(in.Networks)
+ 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...)
}
@@ -542,7 +617,7 @@ func Convert_v1alpha6_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(in *O
return nil
}
-func convertNetworksToPorts(networks []NetworkParam) []infrav1.PortOpts {
+func convertNetworksToPorts(networks []NetworkParam, s apiconversion.Scope) ([]infrav1.PortOpts, error) {
var ports []infrav1.PortOpts
for i := range networks {
@@ -563,7 +638,10 @@ func convertNetworksToPorts(networks []NetworkParam) []infrav1.PortOpts {
ID: network.UUID,
}
case network.Filter != (NetworkFilter{}):
- networkFilter = (*infrav1.NetworkFilter)(&network.Filter)
+ networkFilter = &infrav1.NetworkFilter{}
+ if err := Convert_v1alpha6_NetworkFilter_To_v1beta1_NetworkFilter(&network.Filter, networkFilter, s); err != nil {
+ return nil, err
+ }
}
// Note that network.FixedIP was unused in v1alpha6 so we also ignore it here.
@@ -594,10 +672,14 @@ func convertNetworksToPorts(networks []NetworkParam) []infrav1.PortOpts {
},
})
} else {
+ subnetFilter := &infrav1.SubnetFilter{}
+ if err := Convert_v1alpha6_SubnetFilter_To_v1beta1_SubnetFilter(&subnet.Filter, subnetFilter, s); err != nil {
+ return nil, err
+ }
ports = append(ports, infrav1.PortOpts{
Network: networkFilter,
FixedIPs: []infrav1.FixedIP{
- {Subnet: (*infrav1.SubnetFilter)(&subnet.Filter)},
+ {Subnet: subnetFilter},
},
})
}
@@ -605,7 +687,7 @@ func convertNetworksToPorts(networks []NetworkParam) []infrav1.PortOpts {
}
}
- return ports
+ return ports, nil
}
func Convert_v1beta1_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(in *infrav1.OpenStackClusterSpec, out *OpenStackClusterSpec, s apiconversion.Scope) error {
@@ -844,20 +926,6 @@ func Convert_v1beta1_NetworkStatus_To_v1alpha6_Network(in *infrav1.NetworkStatus
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
- }
-
- // 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_v1alpha6_SecurityGroupParam_To_v1beta1_SecurityGroupFilter(in *SecurityGroupParam, out *infrav1.SecurityGroupFilter, s apiconversion.Scope) error {
// SecurityGroupParam is replaced by its contained SecurityGroupFilter in v1beta1
err := Convert_v1alpha6_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(&in.Filter, out, s)
@@ -890,16 +958,20 @@ func Convert_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupParam(in *infr
return nil
}
-func Convert_v1alpha6_SubnetParam_To_v1beta1_SubnetFilter(in *SubnetParam, out *infrav1.SubnetFilter, _ apiconversion.Scope) error {
- *out = infrav1.SubnetFilter(in.Filter)
+func Convert_v1alpha6_SubnetParam_To_v1beta1_SubnetFilter(in *SubnetParam, out *infrav1.SubnetFilter, s apiconversion.Scope) error {
+ if err := Convert_v1alpha6_SubnetFilter_To_v1beta1_SubnetFilter(&in.Filter, out, s); err != nil {
+ return err
+ }
if in.UUID != "" {
out.ID = in.UUID
}
return nil
}
-func Convert_v1beta1_SubnetFilter_To_v1alpha6_SubnetParam(in *infrav1.SubnetFilter, out *SubnetParam, _ apiconversion.Scope) error {
- out.Filter = SubnetFilter(*in)
+func Convert_v1beta1_SubnetFilter_To_v1alpha6_SubnetParam(in *infrav1.SubnetFilter, out *SubnetParam, s apiconversion.Scope) error {
+ if err := Convert_v1beta1_SubnetFilter_To_v1alpha6_SubnetFilter(in, &out.Filter, s); err != nil {
+ return err
+ }
out.UUID = in.ID
return nil
@@ -1097,3 +1169,56 @@ func Convert_v1beta1_OpenStackIdentityReference_To_v1alpha6_OpenStackIdentityRef
out.Name = in.Name
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_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in *SecurityGroupFilter, out *infrav1.SecurityGroupFilter, s apiconversion.Scope) error {
+ if err := autoConvert_v1alpha6_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_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
+}
+
+func Convert_v1alpha6_NetworkFilter_To_v1beta1_NetworkFilter(in *NetworkFilter, out *infrav1.NetworkFilter, s apiconversion.Scope) error {
+ if err := autoConvert_v1alpha6_NetworkFilter_To_v1beta1_NetworkFilter(in, out, s); err != nil {
+ return err
+ }
+ infrav1.ConvertAllTagsTo(in.Tags, in.TagsAny, in.NotTags, in.NotTagsAny, &out.FilterByNeutronTags)
+ return nil
+}
+
+func Convert_v1beta1_NetworkFilter_To_v1alpha6_NetworkFilter(in *infrav1.NetworkFilter, out *NetworkFilter, s apiconversion.Scope) error {
+ if err := autoConvert_v1beta1_NetworkFilter_To_v1alpha6_NetworkFilter(in, out, s); err != nil {
+ return err
+ }
+ infrav1.ConvertAllTagsFrom(&in.FilterByNeutronTags, &out.Tags, &out.TagsAny, &out.NotTags, &out.NotTagsAny)
+ return nil
+}
diff --git a/api/v1alpha6/conversion_test.go b/api/v1alpha6/conversion_test.go
index e443f5418d..984d7ffb46 100644
--- a/api/v1alpha6/conversion_test.go
+++ b/api/v1alpha6/conversion_test.go
@@ -17,6 +17,7 @@ limitations under the License.
package v1alpha6
import (
+ "strings"
"testing"
"github.com/google/go-cmp/cmp"
@@ -56,6 +57,17 @@ func TestFuzzyConversion(t *testing.T) {
delete(obj.GetAnnotations(), utilconversion.DataAnnotation)
}
+ filterInvalidTags := func(tags []infrav1.NeutronTag) []infrav1.NeutronTag {
+ var ret []infrav1.NeutronTag
+ for i := range tags {
+ s := string(tags[i])
+ if len(s) > 0 && !strings.Contains(s, ",") {
+ ret = append(ret, tags[i])
+ }
+ }
+ return ret
+ }
+
fuzzerFuncs := func(_ runtimeserializer.CodecFactory) []interface{} {
return []interface{}{
func(instance *Instance, c fuzz.Continue) {
@@ -156,6 +168,44 @@ func TestFuzzyConversion(t *testing.T) {
pool.End = c.RandString()
}
},
+
+ // v1beta1 filter tags cannot contain commas and can't be empty.
+
+ func(filter *infrav1.SubnetFilter, c fuzz.Continue) {
+ c.FuzzNoCustom(filter)
+
+ filter.Tags = filterInvalidTags(filter.Tags)
+ filter.TagsAny = filterInvalidTags(filter.TagsAny)
+ filter.NotTags = filterInvalidTags(filter.NotTags)
+ filter.NotTagsAny = filterInvalidTags(filter.NotTagsAny)
+ },
+
+ func(filter *infrav1.NetworkFilter, c fuzz.Continue) {
+ c.FuzzNoCustom(filter)
+
+ filter.Tags = filterInvalidTags(filter.Tags)
+ filter.TagsAny = filterInvalidTags(filter.TagsAny)
+ filter.NotTags = filterInvalidTags(filter.NotTags)
+ filter.NotTagsAny = filterInvalidTags(filter.NotTagsAny)
+ },
+
+ func(filter *infrav1.RouterFilter, c fuzz.Continue) {
+ c.FuzzNoCustom(filter)
+
+ filter.Tags = filterInvalidTags(filter.Tags)
+ filter.TagsAny = filterInvalidTags(filter.TagsAny)
+ filter.NotTags = filterInvalidTags(filter.NotTags)
+ filter.NotTagsAny = filterInvalidTags(filter.NotTagsAny)
+ },
+
+ func(filter *infrav1.SecurityGroupFilter, c fuzz.Continue) {
+ c.FuzzNoCustom(filter)
+
+ filter.Tags = filterInvalidTags(filter.Tags)
+ filter.TagsAny = filterInvalidTags(filter.TagsAny)
+ filter.NotTags = filterInvalidTags(filter.NotTags)
+ filter.NotTagsAny = filterInvalidTags(filter.NotTagsAny)
+ },
}
}
@@ -284,10 +334,12 @@ func TestNetworksToPorts(t *testing.T) {
Name: "network-name",
Description: "network-description",
ProjectID: "project-id",
- Tags: "tags",
- TagsAny: "tags-any",
- NotTags: "not-tags",
- NotTagsAny: "not-tags-any",
+ FilterByNeutronTags: infrav1.FilterByNeutronTags{
+ Tags: []infrav1.NeutronTag{"tags"},
+ TagsAny: []infrav1.NeutronTag{"tags-any"},
+ NotTags: []infrav1.NeutronTag{"not-tags"},
+ NotTagsAny: []infrav1.NeutronTag{"not-tags-any"},
+ },
},
},
},
@@ -368,10 +420,12 @@ func TestNetworksToPorts(t *testing.T) {
CIDR: "y.y.y.y",
IPv6AddressMode: "address-mode",
IPv6RAMode: "ra-mode",
- Tags: "tags",
- TagsAny: "tags-any",
- NotTags: "not-tags",
- NotTagsAny: "not-tags-any",
+ FilterByNeutronTags: infrav1.FilterByNeutronTags{
+ Tags: []infrav1.NeutronTag{"tags"},
+ TagsAny: []infrav1.NeutronTag{"tags-any"},
+ NotTags: []infrav1.NeutronTag{"not-tags"},
+ NotTagsAny: []infrav1.NeutronTag{"not-tags-any"},
+ },
},
},
},
@@ -438,10 +492,12 @@ func TestNetworksToPorts(t *testing.T) {
CIDR: "y.y.y.y",
IPv6AddressMode: "address-mode",
IPv6RAMode: "ra-mode",
- Tags: "tags",
- TagsAny: "tags-any",
- NotTags: "not-tags",
- NotTagsAny: "not-tags-any",
+ FilterByNeutronTags: infrav1.FilterByNeutronTags{
+ Tags: []infrav1.NeutronTag{"tags"},
+ TagsAny: []infrav1.NeutronTag{"tags-any"},
+ NotTags: []infrav1.NeutronTag{"not-tags"},
+ NotTagsAny: []infrav1.NeutronTag{"not-tags-any"},
+ },
},
},
},
@@ -459,7 +515,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))
})
}
}
diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go
index f27f605f86..dafa54171b 100644
--- a/api/v1alpha6/zz_generated.conversion.go
+++ b/api/v1alpha6/zz_generated.conversion.go
@@ -90,16 +90,6 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*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((*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.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 {
@@ -245,11 +235,6 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*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.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 {
@@ -260,16 +245,6 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*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((*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.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 {
@@ -290,6 +265,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
+ 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.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 {
@@ -340,6 +320,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
+ 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.AddConversionFunc((*SubnetParam)(nil), (*v1beta1.SubnetFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha6_SubnetParam_To_v1beta1_SubnetFilter(a.(*SubnetParam), b.(*v1beta1.SubnetFilter), scope)
}); err != nil {
@@ -355,6 +340,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); 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_v1alpha6_NetworkFilter(a.(*v1beta1.NetworkFilter), b.(*NetworkFilter), scope)
+ }); err != nil {
+ return err
+ }
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 {
@@ -400,6 +390,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); 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_v1alpha6_SecurityGroupFilter(a.(*v1beta1.SecurityGroupFilter), b.(*SecurityGroupFilter), scope)
+ }); err != nil {
+ return err
+ }
if err := s.AddConversionFunc((*v1beta1.SecurityGroupFilter)(nil), (*SecurityGroupParam)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupParam(a.(*v1beta1.SecurityGroupFilter), b.(*SecurityGroupParam), scope)
}); err != nil {
@@ -410,6 +405,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); 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.SubnetFilter)(nil), (*SubnetParam)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_SubnetFilter_To_v1alpha6_SubnetParam(a.(*v1beta1.SubnetFilter), b.(*SubnetParam), scope)
}); err != nil {
@@ -516,7 +516,15 @@ func Convert_v1beta1_ExternalRouterIPParam_To_v1alpha6_ExternalRouterIPParam(in
}
func autoConvert_v1alpha6_FixedIP_To_v1beta1_FixedIP(in *FixedIP, out *v1beta1.FixedIP, s conversion.Scope) error {
- out.Subnet = (*v1beta1.SubnetFilter)(unsafe.Pointer(in.Subnet))
+ if in.Subnet != nil {
+ in, out := &in.Subnet, &out.Subnet
+ *out = new(v1beta1.SubnetFilter)
+ if err := Convert_v1alpha6_SubnetFilter_To_v1beta1_SubnetFilter(*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
}
@@ -529,7 +537,15 @@ func Convert_v1alpha6_FixedIP_To_v1beta1_FixedIP(in *FixedIP, out *v1beta1.Fixed
}
func autoConvert_v1beta1_FixedIP_To_v1alpha6_FixedIP(in *v1beta1.FixedIP, out *FixedIP, s conversion.Scope) error {
- out.Subnet = (*SubnetFilter)(unsafe.Pointer(in.Subnet))
+ if in.Subnet != nil {
+ in, out := &in.Subnet, &out.Subnet
+ *out = new(SubnetFilter)
+ if err := Convert_v1beta1_SubnetFilter_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
}
@@ -576,35 +592,22 @@ func autoConvert_v1alpha6_NetworkFilter_To_v1beta1_NetworkFilter(in *NetworkFilt
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.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_v1beta1_NetworkFilter is an autogenerated conversion function.
-func Convert_v1alpha6_NetworkFilter_To_v1beta1_NetworkFilter(in *NetworkFilter, out *v1beta1.NetworkFilter, s conversion.Scope) error {
- return autoConvert_v1alpha6_NetworkFilter_To_v1beta1_NetworkFilter(in, out, s)
-}
-
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_v1beta1_NetworkFilter_To_v1alpha6_NetworkFilter is an autogenerated conversion function.
-func Convert_v1beta1_NetworkFilter_To_v1alpha6_NetworkFilter(in *v1beta1.NetworkFilter, out *NetworkFilter, s conversion.Scope) error {
- return autoConvert_v1beta1_NetworkFilter_To_v1alpha6_NetworkFilter(in, out, s)
-}
-
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_v1beta1_OpenStackClusterSpec(&in.Spec, &out.Spec, s); err != nil {
@@ -1343,7 +1346,15 @@ func Convert_v1beta1_OpenStackMachineTemplateSpec_To_v1alpha6_OpenStackMachineTe
}
func autoConvert_v1alpha6_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *v1beta1.PortOpts, s conversion.Scope) error {
- out.Network = (*v1beta1.NetworkFilter)(unsafe.Pointer(in.Network))
+ if in.Network != nil {
+ in, out := &in.Network, &out.Network
+ *out = new(v1beta1.NetworkFilter)
+ if err := Convert_v1alpha6_NetworkFilter_To_v1beta1_NetworkFilter(*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
}
@@ -1395,7 +1406,15 @@ func autoConvert_v1alpha6_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *v1beta
}
func autoConvert_v1beta1_PortOpts_To_v1alpha6_PortOpts(in *v1beta1.PortOpts, out *PortOpts, s conversion.Scope) error {
- out.Network = (*NetworkFilter)(unsafe.Pointer(in.Network))
+ if in.Network != nil {
+ in, out := &in.Network, &out.Network
+ *out = new(NetworkFilter)
+ if err := Convert_v1beta1_NetworkFilter_To_v1alpha6_NetworkFilter(*in, *out, s); err != nil {
+ return err
+ }
+ } else {
+ out.Network = nil
+ }
if err := optional.Convert_optional_String_To_string(&in.NameSuffix, &out.NameSuffix, s); err != nil {
return err
}
@@ -1514,10 +1533,10 @@ func autoConvert_v1alpha6_SecurityGroupFilter_To_v1beta1_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
}
@@ -1526,18 +1545,10 @@ func autoConvert_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(in
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_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter is an autogenerated conversion function.
-func Convert_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(in *v1beta1.SecurityGroupFilter, out *SecurityGroupFilter, s conversion.Scope) error {
- return autoConvert_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(in, out, s)
-}
-
func autoConvert_v1alpha6_Subnet_To_v1beta1_Subnet(in *Subnet, out *v1beta1.Subnet, s conversion.Scope) error {
out.Name = in.Name
out.ID = in.ID
@@ -1574,18 +1585,13 @@ func autoConvert_v1alpha6_SubnetFilter_To_v1beta1_SubnetFilter(in *SubnetFilter,
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.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_v1beta1_SubnetFilter is an autogenerated conversion function.
-func Convert_v1alpha6_SubnetFilter_To_v1beta1_SubnetFilter(in *SubnetFilter, out *v1beta1.SubnetFilter, s conversion.Scope) error {
- return autoConvert_v1alpha6_SubnetFilter_To_v1beta1_SubnetFilter(in, out, s)
-}
-
func autoConvert_v1beta1_SubnetFilter_To_v1alpha6_SubnetFilter(in *v1beta1.SubnetFilter, out *SubnetFilter, s conversion.Scope) error {
out.Name = in.Name
out.Description = in.Description
@@ -1596,18 +1602,10 @@ func autoConvert_v1beta1_SubnetFilter_To_v1alpha6_SubnetFilter(in *v1beta1.Subne
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
}
-// Convert_v1beta1_SubnetFilter_To_v1alpha6_SubnetFilter is an autogenerated conversion function.
-func Convert_v1beta1_SubnetFilter_To_v1alpha6_SubnetFilter(in *v1beta1.SubnetFilter, out *SubnetFilter, s conversion.Scope) error {
- return autoConvert_v1beta1_SubnetFilter_To_v1alpha6_SubnetFilter(in, out, s)
-}
-
func autoConvert_v1alpha6_ValueSpec_To_v1beta1_ValueSpec(in *ValueSpec, out *v1beta1.ValueSpec, s conversion.Scope) error {
out.Name = in.Name
out.Key = in.Key
diff --git a/api/v1alpha7/conversion.go b/api/v1alpha7/conversion.go
index ff38380bf4..ed6c3f487f 100644
--- a/api/v1alpha7/conversion.go
+++ b/api/v1alpha7/conversion.go
@@ -164,6 +164,65 @@ var v1beta1OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStackC
),
}
+func restorev1alpha7SubnetFilter(previous *SubnetFilter, dst *SubnetFilter) {
+ // 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 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
+}
+
+func restorev1alpha7NetworkFilter(previous *NetworkFilter, dst *NetworkFilter) {
+ // 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 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
+}
+
+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 restorev1alpha7MachineSpec(previous *OpenStackMachineSpec, dst *OpenStackMachineSpec) {
dst.FloatingIP = previous.FloatingIP
@@ -187,6 +246,18 @@ func restorev1alpha7MachineSpec(previous *OpenStackMachineSpec, dst *OpenStackMa
// 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])
+ }
+ }
}
func restorev1beta1MachineSpec(previous *infrav1.OpenStackMachineSpec, dst *infrav1.OpenStackMachineSpec) {
@@ -287,6 +358,20 @@ func restorev1alpha7ClusterSpec(previous *OpenStackClusterSpec, dst *OpenStackCl
// 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) {
@@ -796,7 +881,7 @@ func Convert_v1alpha7_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *infrav1.Po
if len(in.SecurityGroupFilters) > 0 {
out.SecurityGroups = make([]infrav1.SecurityGroupFilter, len(in.SecurityGroupFilters))
for i := range in.SecurityGroupFilters {
- if err := autoConvert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(&in.SecurityGroupFilters[i], &out.SecurityGroups[i], s); err != nil {
+ if err := Convert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(&in.SecurityGroupFilters[i], &out.SecurityGroups[i], s); err != nil {
return err
}
}
@@ -804,7 +889,7 @@ func Convert_v1alpha7_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *infrav1.Po
if in.Profile != (BindingProfile{}) {
out.Profile = &infrav1.BindingProfile{}
- if err := autoConvert_v1alpha7_BindingProfile_To_v1beta1_BindingProfile(&in.Profile, out.Profile, s); err != nil {
+ if err := Convert_v1alpha7_BindingProfile_To_v1beta1_BindingProfile(&in.Profile, out.Profile, s); err != nil {
return err
}
}
@@ -820,14 +905,14 @@ func Convert_v1beta1_PortOpts_To_v1alpha7_PortOpts(in *infrav1.PortOpts, out *Po
if len(in.SecurityGroups) > 0 {
out.SecurityGroupFilters = make([]SecurityGroupFilter, len(in.SecurityGroups))
for i := range in.SecurityGroups {
- if err := autoConvert_v1beta1_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(&in.SecurityGroups[i], &out.SecurityGroupFilters[i], s); err != nil {
+ if err := Convert_v1beta1_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(&in.SecurityGroups[i], &out.SecurityGroupFilters[i], s); err != nil {
return err
}
}
}
if in.Profile != nil {
- if err := autoConvert_v1beta1_BindingProfile_To_v1alpha7_BindingProfile(in.Profile, &out.Profile, s); err != nil {
+ if err := Convert_v1beta1_BindingProfile_To_v1alpha7_BindingProfile(in.Profile, &out.Profile, s); err != nil {
return err
}
}
@@ -839,3 +924,67 @@ func Convert_v1beta1_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityRef
out.Name = in.Name
return nil
}
+
+func Convert_v1alpha7_SubnetFilter_To_v1beta1_SubnetFilter(in *SubnetFilter, out *infrav1.SubnetFilter, s apiconversion.Scope) error {
+ if err := autoConvert_v1alpha7_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_v1alpha7_SubnetFilter(in *infrav1.SubnetFilter, out *SubnetFilter, s apiconversion.Scope) error {
+ if err := autoConvert_v1beta1_SubnetFilter_To_v1alpha7_SubnetFilter(in, out, s); err != nil {
+ return err
+ }
+ infrav1.ConvertAllTagsFrom(&in.FilterByNeutronTags, &out.Tags, &out.TagsAny, &out.NotTags, &out.NotTagsAny)
+ return nil
+}
+
+func Convert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in *SecurityGroupFilter, out *infrav1.SecurityGroupFilter, s apiconversion.Scope) error {
+ if err := autoConvert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in, out, s); err != nil {
+ return err
+ }
+ infrav1.ConvertAllTagsTo(in.Tags, in.TagsAny, in.NotTags, in.NotTagsAny, &out.FilterByNeutronTags)
+ return nil
+}
+
+func Convert_v1beta1_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in *infrav1.SecurityGroupFilter, out *SecurityGroupFilter, s apiconversion.Scope) error {
+ if err := autoConvert_v1beta1_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in, out, s); err != nil {
+ return err
+ }
+ infrav1.ConvertAllTagsFrom(&in.FilterByNeutronTags, &out.Tags, &out.TagsAny, &out.NotTags, &out.NotTagsAny)
+ return nil
+}
+
+func Convert_v1alpha7_RouterFilter_To_v1beta1_RouterFilter(in *RouterFilter, out *infrav1.RouterFilter, s apiconversion.Scope) error {
+ if err := autoConvert_v1alpha7_RouterFilter_To_v1beta1_RouterFilter(in, out, s); err != nil {
+ return err
+ }
+ infrav1.ConvertAllTagsTo(in.Tags, in.TagsAny, in.NotTags, in.NotTagsAny, &out.FilterByNeutronTags)
+ return nil
+}
+
+func Convert_v1beta1_RouterFilter_To_v1alpha7_RouterFilter(in *infrav1.RouterFilter, out *RouterFilter, s apiconversion.Scope) error {
+ if err := autoConvert_v1beta1_RouterFilter_To_v1alpha7_RouterFilter(in, out, s); err != nil {
+ return err
+ }
+ infrav1.ConvertAllTagsFrom(&in.FilterByNeutronTags, &out.Tags, &out.TagsAny, &out.NotTags, &out.NotTagsAny)
+ return nil
+}
+
+func Convert_v1alpha7_NetworkFilter_To_v1beta1_NetworkFilter(in *NetworkFilter, out *infrav1.NetworkFilter, s apiconversion.Scope) error {
+ if err := autoConvert_v1alpha7_NetworkFilter_To_v1beta1_NetworkFilter(in, out, s); err != nil {
+ return err
+ }
+ infrav1.ConvertAllTagsTo(in.Tags, in.TagsAny, in.NotTags, in.NotTagsAny, &out.FilterByNeutronTags)
+ return nil
+}
+
+func Convert_v1beta1_NetworkFilter_To_v1alpha7_NetworkFilter(in *infrav1.NetworkFilter, out *NetworkFilter, s apiconversion.Scope) error {
+ if err := autoConvert_v1beta1_NetworkFilter_To_v1alpha7_NetworkFilter(in, out, s); err != nil {
+ return err
+ }
+ infrav1.ConvertAllTagsFrom(&in.FilterByNeutronTags, &out.Tags, &out.TagsAny, &out.NotTags, &out.NotTagsAny)
+ return nil
+}
diff --git a/api/v1alpha7/conversion_test.go b/api/v1alpha7/conversion_test.go
index 964b89771b..a2c770984f 100644
--- a/api/v1alpha7/conversion_test.go
+++ b/api/v1alpha7/conversion_test.go
@@ -17,6 +17,7 @@ limitations under the License.
package v1alpha7
import (
+ "strings"
"testing"
"github.com/google/go-cmp/cmp"
@@ -56,6 +57,17 @@ func TestFuzzyConversion(t *testing.T) {
delete(obj.GetAnnotations(), utilconversion.DataAnnotation)
}
+ filterInvalidTags := func(tags []infrav1.NeutronTag) []infrav1.NeutronTag {
+ var ret []infrav1.NeutronTag
+ for i := range tags {
+ s := string(tags[i])
+ if len(s) > 0 && !strings.Contains(s, ",") {
+ ret = append(ret, tags[i])
+ }
+ }
+ return ret
+ }
+
fuzzerFuncs := func(_ runtimeserializer.CodecFactory) []interface{} {
return []interface{}{
func(spec *infrav1.OpenStackClusterSpec, c fuzz.Continue) {
@@ -124,6 +136,64 @@ func TestFuzzyConversion(t *testing.T) {
pool.End = c.RandString()
}
},
+
+ // v1beta1 filter tags cannot contain commas and can't be empty.
+
+ func(filter *infrav1.SubnetFilter, c fuzz.Continue) {
+ c.FuzzNoCustom(filter)
+
+ // Sometimes add an additional tag to ensure we get test coverage of multiple tags
+ if c.RandBool() {
+ filter.Tags = append(filter.Tags, infrav1.NeutronTag(c.RandString()))
+ }
+
+ filter.Tags = filterInvalidTags(filter.Tags)
+ filter.TagsAny = filterInvalidTags(filter.TagsAny)
+ filter.NotTags = filterInvalidTags(filter.NotTags)
+ filter.NotTagsAny = filterInvalidTags(filter.NotTagsAny)
+ },
+
+ func(filter *infrav1.NetworkFilter, c fuzz.Continue) {
+ c.FuzzNoCustom(filter)
+
+ // Sometimes add an additional tag to ensure we get test coverage of multiple tags
+ if c.RandBool() {
+ filter.Tags = append(filter.Tags, infrav1.NeutronTag(c.RandString()))
+ }
+
+ filter.Tags = filterInvalidTags(filter.Tags)
+ filter.TagsAny = filterInvalidTags(filter.TagsAny)
+ filter.NotTags = filterInvalidTags(filter.NotTags)
+ filter.NotTagsAny = filterInvalidTags(filter.NotTagsAny)
+ },
+
+ func(filter *infrav1.RouterFilter, c fuzz.Continue) {
+ c.FuzzNoCustom(filter)
+
+ // Sometimes add an additional tag to ensure we get test coverage of multiple tags
+ if c.RandBool() {
+ filter.Tags = append(filter.Tags, infrav1.NeutronTag(c.RandString()))
+ }
+
+ filter.Tags = filterInvalidTags(filter.Tags)
+ filter.TagsAny = filterInvalidTags(filter.TagsAny)
+ filter.NotTags = filterInvalidTags(filter.NotTags)
+ filter.NotTagsAny = filterInvalidTags(filter.NotTagsAny)
+ },
+
+ func(filter *infrav1.SecurityGroupFilter, c fuzz.Continue) {
+ c.FuzzNoCustom(filter)
+
+ // Sometimes add an additional tag to ensure we get test coverage of multiple tags
+ if c.RandBool() {
+ filter.Tags = append(filter.Tags, infrav1.NeutronTag(c.RandString()))
+ }
+
+ filter.Tags = filterInvalidTags(filter.Tags)
+ filter.TagsAny = filterInvalidTags(filter.TagsAny)
+ filter.NotTags = filterInvalidTags(filter.NotTags)
+ filter.NotTagsAny = filterInvalidTags(filter.NotTagsAny)
+ },
}
}
diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go
index 69cbeb55f3..2cbd5b0184 100644
--- a/api/v1alpha7/zz_generated.conversion.go
+++ b/api/v1alpha7/zz_generated.conversion.go
@@ -136,16 +136,6 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*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.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 {
@@ -316,26 +306,6 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*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.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 {
@@ -346,16 +316,6 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*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.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 {
@@ -371,6 +331,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); 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((*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 {
@@ -391,11 +356,26 @@ func RegisterConversions(s *runtime.Scheme) error {
}); 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((*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((*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((*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 {
@@ -406,6 +386,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); 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.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 {
@@ -436,11 +421,26 @@ func RegisterConversions(s *runtime.Scheme) error {
}); 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.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.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
+ }
return nil
}
@@ -671,7 +671,15 @@ func Convert_v1beta1_ExternalRouterIPParam_To_v1alpha7_ExternalRouterIPParam(in
}
func autoConvert_v1alpha7_FixedIP_To_v1beta1_FixedIP(in *FixedIP, out *v1beta1.FixedIP, s conversion.Scope) error {
- out.Subnet = (*v1beta1.SubnetFilter)(unsafe.Pointer(in.Subnet))
+ if in.Subnet != nil {
+ in, out := &in.Subnet, &out.Subnet
+ *out = new(v1beta1.SubnetFilter)
+ if err := Convert_v1alpha7_SubnetFilter_To_v1beta1_SubnetFilter(*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
}
@@ -684,7 +692,15 @@ func Convert_v1alpha7_FixedIP_To_v1beta1_FixedIP(in *FixedIP, out *v1beta1.Fixed
}
func autoConvert_v1beta1_FixedIP_To_v1alpha7_FixedIP(in *v1beta1.FixedIP, out *FixedIP, s conversion.Scope) error {
- out.Subnet = (*SubnetFilter)(unsafe.Pointer(in.Subnet))
+ if in.Subnet != nil {
+ in, out := &in.Subnet, &out.Subnet
+ *out = new(SubnetFilter)
+ if err := Convert_v1beta1_SubnetFilter_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
}
@@ -731,35 +747,22 @@ func autoConvert_v1alpha7_NetworkFilter_To_v1beta1_NetworkFilter(in *NetworkFilt
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.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_v1alpha7_NetworkFilter_To_v1beta1_NetworkFilter is an autogenerated conversion function.
-func Convert_v1alpha7_NetworkFilter_To_v1beta1_NetworkFilter(in *NetworkFilter, out *v1beta1.NetworkFilter, s conversion.Scope) error {
- return autoConvert_v1alpha7_NetworkFilter_To_v1beta1_NetworkFilter(in, out, s)
-}
-
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
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_v1beta1_NetworkFilter_To_v1alpha7_NetworkFilter is an autogenerated conversion function.
-func Convert_v1beta1_NetworkFilter_To_v1alpha7_NetworkFilter(in *v1beta1.NetworkFilter, out *NetworkFilter, s conversion.Scope) error {
- return autoConvert_v1beta1_NetworkFilter_To_v1alpha7_NetworkFilter(in, out, s)
-}
-
func autoConvert_v1alpha7_NetworkStatus_To_v1beta1_NetworkStatus(in *NetworkStatus, out *v1beta1.NetworkStatus, s conversion.Scope) error {
out.Name = in.Name
out.ID = in.ID
@@ -887,14 +890,32 @@ func Convert_v1beta1_OpenStackClusterList_To_v1alpha7_OpenStackClusterList(in *v
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
- out.Router = (*v1beta1.RouterFilter)(unsafe.Pointer(in.Router))
+ if in.Router != nil {
+ in, out := &in.Router, &out.Router
+ *out = new(v1beta1.RouterFilter)
+ if err := Convert_v1alpha7_RouterFilter_To_v1beta1_RouterFilter(*in, *out, s); err != nil {
+ return err
+ }
+ } else {
+ out.Router = nil
+ }
if err := Convert_v1alpha7_NetworkFilter_To_v1beta1_NetworkFilter(&in.Network, &out.Network, s); err != nil {
return err
}
// WARNING: in.Subnet requires manual conversion: does not exist in peer-type
out.NetworkMTU = in.NetworkMTU
// WARNING: in.DNSNameservers requires manual conversion: does not exist in peer-type
- out.ExternalRouterIPs = *(*[]v1beta1.ExternalRouterIPParam)(unsafe.Pointer(&in.ExternalRouterIPs))
+ 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
if err := Convert_v1alpha7_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil {
return err
@@ -925,13 +946,31 @@ func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(i
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
- out.Router = (*RouterFilter)(unsafe.Pointer(in.Router))
+ if in.Router != nil {
+ in, out := &in.Router, &out.Router
+ *out = new(RouterFilter)
+ if err := Convert_v1beta1_RouterFilter_To_v1alpha7_RouterFilter(*in, *out, s); err != nil {
+ return err
+ }
+ } else {
+ out.Router = nil
+ }
if err := Convert_v1beta1_NetworkFilter_To_v1alpha7_NetworkFilter(&in.Network, &out.Network, s); err != nil {
return err
}
// WARNING: in.Subnets requires manual conversion: does not exist in peer-type
out.NetworkMTU = in.NetworkMTU
- out.ExternalRouterIPs = *(*[]ExternalRouterIPParam)(unsafe.Pointer(&in.ExternalRouterIPs))
+ 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
if err := Convert_v1beta1_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil {
@@ -1283,7 +1322,17 @@ func autoConvert_v1alpha7_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(i
out.Ports = nil
}
// WARNING: in.FloatingIP requires manual conversion: does not exist in peer-type
- out.SecurityGroups = *(*[]v1beta1.SecurityGroupFilter)(unsafe.Pointer(&in.SecurityGroups))
+ if in.SecurityGroups != nil {
+ in, out := &in.SecurityGroups, &out.SecurityGroups
+ *out = make([]v1beta1.SecurityGroupFilter, len(*in))
+ for i := range *in {
+ if err := Convert_v1alpha7_SecurityGroupFilter_To_v1beta1_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 (map[string]string vs []sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ServerMetadata)
@@ -1320,7 +1369,17 @@ func autoConvert_v1beta1_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(i
} else {
out.Ports = nil
}
- out.SecurityGroups = *(*[]SecurityGroupFilter)(unsafe.Pointer(&in.SecurityGroups))
+ if in.SecurityGroups != nil {
+ in, out := &in.SecurityGroups, &out.SecurityGroups
+ *out = make([]SecurityGroupFilter, len(*in))
+ for i := range *in {
+ if err := Convert_v1beta1_SecurityGroupFilter_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)
@@ -1484,7 +1543,15 @@ func Convert_v1beta1_OpenStackMachineTemplateSpec_To_v1alpha7_OpenStackMachineTe
}
func autoConvert_v1alpha7_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *v1beta1.PortOpts, s conversion.Scope) error {
- out.Network = (*v1beta1.NetworkFilter)(unsafe.Pointer(in.Network))
+ if in.Network != nil {
+ in, out := &in.Network, &out.Network
+ *out = new(v1beta1.NetworkFilter)
+ if err := Convert_v1alpha7_NetworkFilter_To_v1beta1_NetworkFilter(*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
}
@@ -1534,7 +1601,15 @@ func autoConvert_v1alpha7_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *v1beta
}
func autoConvert_v1beta1_PortOpts_To_v1alpha7_PortOpts(in *v1beta1.PortOpts, out *PortOpts, s conversion.Scope) error {
- out.Network = (*NetworkFilter)(unsafe.Pointer(in.Network))
+ if in.Network != nil {
+ in, out := &in.Network, &out.Network
+ *out = new(NetworkFilter)
+ if err := Convert_v1beta1_NetworkFilter_To_v1alpha7_NetworkFilter(*in, *out, s); err != nil {
+ return err
+ }
+ } else {
+ out.Network = nil
+ }
if err := optional.Convert_optional_String_To_string(&in.NameSuffix, &out.NameSuffix, s); err != nil {
return err
}
@@ -1638,69 +1713,43 @@ func autoConvert_v1alpha7_RouterFilter_To_v1beta1_RouterFilter(in *RouterFilter,
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.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_v1alpha7_RouterFilter_To_v1beta1_RouterFilter is an autogenerated conversion function.
-func Convert_v1alpha7_RouterFilter_To_v1beta1_RouterFilter(in *RouterFilter, out *v1beta1.RouterFilter, s conversion.Scope) error {
- return autoConvert_v1alpha7_RouterFilter_To_v1beta1_RouterFilter(in, out, s)
-}
-
func autoConvert_v1beta1_RouterFilter_To_v1alpha7_RouterFilter(in *v1beta1.RouterFilter, out *RouterFilter, s conversion.Scope) error {
out.ID = in.ID
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_v1beta1_RouterFilter_To_v1alpha7_RouterFilter is an autogenerated conversion function.
-func Convert_v1beta1_RouterFilter_To_v1alpha7_RouterFilter(in *v1beta1.RouterFilter, out *RouterFilter, s conversion.Scope) error {
- return autoConvert_v1beta1_RouterFilter_To_v1alpha7_RouterFilter(in, out, s)
-}
-
func autoConvert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in *SecurityGroupFilter, out *v1beta1.SecurityGroupFilter, s conversion.Scope) error {
out.ID = in.ID
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.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_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter is an autogenerated conversion function.
-func Convert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in *SecurityGroupFilter, out *v1beta1.SecurityGroupFilter, s conversion.Scope) error {
- return autoConvert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in, out, s)
-}
-
func autoConvert_v1beta1_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in *v1beta1.SecurityGroupFilter, out *SecurityGroupFilter, s conversion.Scope) error {
out.ID = in.ID
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_v1beta1_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter is an autogenerated conversion function.
-func Convert_v1beta1_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in *v1beta1.SecurityGroupFilter, out *SecurityGroupFilter, s conversion.Scope) error {
- return autoConvert_v1beta1_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in, out, s)
-}
-
func autoConvert_v1alpha7_Subnet_To_v1beta1_Subnet(in *Subnet, out *v1beta1.Subnet, s conversion.Scope) error {
out.Name = in.Name
out.ID = in.ID
@@ -1737,18 +1786,13 @@ func autoConvert_v1alpha7_SubnetFilter_To_v1beta1_SubnetFilter(in *SubnetFilter,
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.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_v1alpha7_SubnetFilter_To_v1beta1_SubnetFilter is an autogenerated conversion function.
-func Convert_v1alpha7_SubnetFilter_To_v1beta1_SubnetFilter(in *SubnetFilter, out *v1beta1.SubnetFilter, s conversion.Scope) error {
- return autoConvert_v1alpha7_SubnetFilter_To_v1beta1_SubnetFilter(in, out, s)
-}
-
func autoConvert_v1beta1_SubnetFilter_To_v1alpha7_SubnetFilter(in *v1beta1.SubnetFilter, out *SubnetFilter, s conversion.Scope) error {
out.Name = in.Name
out.Description = in.Description
@@ -1759,18 +1803,10 @@ func autoConvert_v1beta1_SubnetFilter_To_v1alpha7_SubnetFilter(in *v1beta1.Subne
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
}
-// Convert_v1beta1_SubnetFilter_To_v1alpha7_SubnetFilter is an autogenerated conversion function.
-func Convert_v1beta1_SubnetFilter_To_v1alpha7_SubnetFilter(in *v1beta1.SubnetFilter, out *SubnetFilter, s conversion.Scope) error {
- return autoConvert_v1beta1_SubnetFilter_To_v1alpha7_SubnetFilter(in, out, s)
-}
-
func autoConvert_v1alpha7_ValueSpec_To_v1beta1_ValueSpec(in *ValueSpec, out *v1beta1.ValueSpec, s conversion.Scope) error {
out.Name = in.Name
out.Key = in.Key
diff --git a/api/v1beta1/filter_convert.go b/api/v1beta1/filter_convert.go
index e168c63e0a..23f7f3c348 100644
--- a/api/v1beta1/filter_convert.go
+++ b/api/v1beta1/filter_convert.go
@@ -17,6 +17,8 @@ limitations under the License.
package v1beta1
import (
+ "strings"
+
"github.com/gophercloud/gophercloud/openstack/imageservice/v2/images"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers"
securitygroups "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups"
@@ -24,20 +26,20 @@ import (
"github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
)
-func (securityGroupFilter SecurityGroupFilter) ToListOpt() securitygroups.ListOpts {
+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,
+ Tags: joinTags(securityGroupFilter.Tags),
+ TagsAny: joinTags(securityGroupFilter.TagsAny),
+ NotTags: joinTags(securityGroupFilter.NotTags),
+ NotTagsAny: joinTags(securityGroupFilter.NotTagsAny),
}
}
-func (subnetFilter SubnetFilter) ToListOpt() subnets.ListOpts {
+func (subnetFilter *SubnetFilter) ToListOpt() subnets.ListOpts {
return subnets.ListOpts{
Name: subnetFilter.Name,
Description: subnetFilter.Description,
@@ -48,43 +50,98 @@ func (subnetFilter SubnetFilter) ToListOpt() subnets.ListOpts {
IPv6AddressMode: subnetFilter.IPv6AddressMode,
IPv6RAMode: subnetFilter.IPv6RAMode,
ID: subnetFilter.ID,
- Tags: subnetFilter.Tags,
- TagsAny: subnetFilter.TagsAny,
- NotTags: subnetFilter.NotTags,
- NotTagsAny: subnetFilter.NotTagsAny,
+ Tags: joinTags(subnetFilter.Tags),
+ TagsAny: joinTags(subnetFilter.TagsAny),
+ NotTags: joinTags(subnetFilter.NotTags),
+ NotTagsAny: joinTags(subnetFilter.NotTagsAny),
}
}
-func (networkFilter NetworkFilter) ToListOpt() networks.ListOpts {
+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,
+ Tags: joinTags(networkFilter.Tags),
+ TagsAny: joinTags(networkFilter.TagsAny),
+ NotTags: joinTags(networkFilter.NotTags),
+ NotTagsAny: joinTags(networkFilter.NotTagsAny),
}
}
-func (routerFilter RouterFilter) ToListOpt() routers.ListOpts {
+func (networkFilter *NetworkFilter) IsEmpty() bool {
+ return networkFilter.Name == "" &&
+ networkFilter.Description == "" &&
+ networkFilter.ProjectID == "" &&
+ networkFilter.ID == "" &&
+ len(networkFilter.Tags) == 0 &&
+ len(networkFilter.TagsAny) == 0 &&
+ len(networkFilter.NotTags) == 0 &&
+ len(networkFilter.NotTagsAny) == 0
+}
+
+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,
+ Tags: joinTags(routerFilter.Tags),
+ TagsAny: joinTags(routerFilter.TagsAny),
+ NotTags: joinTags(routerFilter.NotTags),
+ NotTagsAny: joinTags(routerFilter.NotTagsAny),
}
}
-func (imageFilter ImageFilter) ToListOpt() images.ListOpts {
+func (imageFilter *ImageFilter) ToListOpt() images.ListOpts {
return images.ListOpts{
ID: imageFilter.ID,
Name: imageFilter.Name,
Tags: imageFilter.Tags,
}
}
+
+// 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/types.go b/api/v1beta1/types.go
index ea290a1656..8be6ecc5e4 100644
--- a/api/v1beta1/types.go
+++ b/api/v1beta1/types.go
@@ -42,15 +42,46 @@ type ExternalRouterIPParam struct {
Subnet SubnetFilter `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"`
+}
+
type SecurityGroupFilter struct {
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
ProjectID string `json:"projectId,omitempty"`
- Tags string `json:"tags,omitempty"`
- TagsAny string `json:"tagsAny,omitempty"`
- NotTags string `json:"notTags,omitempty"`
- NotTagsAny string `json:"notTagsAny,omitempty"`
+
+ FilterByNeutronTags `json:",inline"`
}
type NetworkFilter struct {
@@ -58,10 +89,8 @@ type NetworkFilter struct {
Description string `json:"description,omitempty"`
ProjectID string `json:"projectId,omitempty"`
ID string `json:"id,omitempty"`
- Tags string `json:"tags,omitempty"`
- TagsAny string `json:"tagsAny,omitempty"`
- NotTags string `json:"notTags,omitempty"`
- NotTagsAny string `json:"notTagsAny,omitempty"`
+
+ FilterByNeutronTags `json:",inline"`
}
type SubnetFilter struct {
@@ -74,10 +103,8 @@ type SubnetFilter struct {
IPv6AddressMode string `json:"ipv6AddressMode,omitempty"`
IPv6RAMode string `json:"ipv6RaMode,omitempty"`
ID string `json:"id,omitempty"`
- Tags string `json:"tags,omitempty"`
- TagsAny string `json:"tagsAny,omitempty"`
- NotTags string `json:"notTags,omitempty"`
- NotTagsAny string `json:"notTagsAny,omitempty"`
+
+ FilterByNeutronTags `json:",inline"`
}
type RouterFilter struct {
@@ -85,10 +112,8 @@ type RouterFilter struct {
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
ProjectID string `json:"projectId,omitempty"`
- Tags string `json:"tags,omitempty"`
- TagsAny string `json:"tagsAny,omitempty"`
- NotTags string `json:"notTags,omitempty"`
- NotTagsAny string `json:"notTagsAny,omitempty"`
+
+ FilterByNeutronTags `json:",inline"`
}
type SubnetSpec struct {
diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go
index b66e1869c8..cd5c538ffa 100644
--- a/api/v1beta1/zz_generated.deepcopy.go
+++ b/api/v1beta1/zz_generated.deepcopy.go
@@ -219,7 +219,7 @@ func (in *DependentMachineResources) DeepCopy() *DependentMachineResources {
// 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.
@@ -232,13 +232,48 @@ 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 = **in
+ (*in).DeepCopyInto(*out)
}
if in.IPAddress != nil {
in, out := &in.IPAddress, &out.IPAddress
@@ -327,6 +362,7 @@ func (in *ManagedSecurityGroups) DeepCopy() *ManagedSecurityGroups {
// 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.
@@ -454,20 +490,24 @@ func (in *OpenStackClusterSpec) DeepCopyInto(out *OpenStackClusterSpec) {
if in.Router != nil {
in, out := &in.Router, &out.Router
*out = new(RouterFilter)
- **out = **in
+ (*in).DeepCopyInto(*out)
}
- out.Network = in.Network
+ in.Network.DeepCopyInto(&out.Network)
if in.Subnets != nil {
in, out := &in.Subnets, &out.Subnets
*out = make([]SubnetFilter, len(*in))
- copy(*out, *in)
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
}
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])
+ }
}
- out.ExternalNetwork = in.ExternalNetwork
+ in.ExternalNetwork.DeepCopyInto(&out.ExternalNetwork)
in.APIServerLoadBalancer.DeepCopyInto(&out.APIServerLoadBalancer)
if in.ManagedSecurityGroups != nil {
in, out := &in.ManagedSecurityGroups, &out.ManagedSecurityGroups
@@ -763,7 +803,9 @@ func (in *OpenStackMachineSpec) DeepCopyInto(out *OpenStackMachineSpec) {
if in.SecurityGroups != nil {
in, out := &in.SecurityGroups, &out.SecurityGroups
*out = make([]SecurityGroupFilter, len(*in))
- copy(*out, *in)
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
}
if in.Tags != nil {
in, out := &in.Tags, &out.Tags
@@ -954,7 +996,7 @@ func (in *PortOpts) DeepCopyInto(out *PortOpts) {
if in.Network != nil {
in, out := &in.Network, &out.Network
*out = new(NetworkFilter)
- **out = **in
+ (*in).DeepCopyInto(*out)
}
if in.NameSuffix != nil {
in, out := &in.NameSuffix, &out.NameSuffix
@@ -986,7 +1028,9 @@ func (in *PortOpts) DeepCopyInto(out *PortOpts) {
if in.SecurityGroups != nil {
in, out := &in.SecurityGroups, &out.SecurityGroups
*out = make([]SecurityGroupFilter, len(*in))
- copy(*out, *in)
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
}
if in.AllowedAddressPairs != nil {
in, out := &in.AllowedAddressPairs, &out.AllowedAddressPairs
@@ -1127,6 +1171,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.
@@ -1142,6 +1187,7 @@ func (in *RouterFilter) DeepCopy() *RouterFilter {
// 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.
@@ -1334,6 +1380,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.
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 195071619b..85b3b178e4 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -5107,15 +5107,60 @@ spec:
name:
type: string
notTags:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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
type: object
type: array
@@ -5146,15 +5191,60 @@ spec:
name:
type: string
notTags:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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
profile:
description: |-
@@ -5192,15 +5282,60 @@ spec:
name:
type: string
notTags:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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
type: array
x-kubernetes-list-type: atomic
@@ -5287,15 +5422,60 @@ spec:
name:
type: string
notTags:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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
type: array
serverGroup:
@@ -5412,15 +5592,60 @@ spec:
name:
type: string
notTags:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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
externalRouterIPs:
description: |-
@@ -5452,15 +5677,60 @@ spec:
name:
type: string
notTags:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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
required:
- subnet
@@ -5635,15 +5905,60 @@ spec:
name:
type: string
notTags:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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
networkMtu:
description: |-
@@ -5664,15 +5979,60 @@ spec:
name:
type: string
notTags:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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
subnets:
description: |-
@@ -5700,15 +6060,60 @@ spec:
name:
type: string
notTags:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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
maxItems: 2
type: array
@@ -5861,15 +6266,60 @@ spec:
name:
type: string
notTags:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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
type: object
type: array
@@ -5900,15 +6350,60 @@ spec:
name:
type: string
notTags:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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
profile:
description: |-
@@ -5946,15 +6441,60 @@ spec:
name:
type: string
notTags:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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
type: array
x-kubernetes-list-type: atomic
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 ff668645be..d4c396ef94 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -2535,15 +2535,60 @@ spec:
name:
type: string
notTags:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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
type: object
type: array
@@ -2575,15 +2620,60 @@ spec:
name:
type: string
notTags:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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
profile:
description: |-
@@ -2622,15 +2712,60 @@ spec:
name:
type: string
notTags:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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
type: array
x-kubernetes-list-type: atomic
@@ -2718,15 +2853,60 @@ spec:
name:
type: string
notTags:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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
type: array
serverGroup:
@@ -2844,15 +3024,60 @@ spec:
name:
type: string
notTags:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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
externalRouterIPs:
description: |-
@@ -2884,15 +3109,60 @@ spec:
name:
type: string
notTags:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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
required:
- subnet
@@ -3069,15 +3339,60 @@ spec:
name:
type: string
notTags:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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
networkMtu:
description: |-
@@ -3098,15 +3413,60 @@ spec:
name:
type: string
notTags:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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
subnets:
description: |-
@@ -3134,15 +3494,60 @@ spec:
name:
type: string
notTags:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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
maxItems: 2
type: array
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 7fbeee04e3..a58649e400 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
@@ -1908,15 +1908,60 @@ spec:
name:
type: string
notTags:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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
type: object
type: array
@@ -1946,15 +1991,60 @@ spec:
name:
type: string
notTags:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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
profile:
description: |-
@@ -1992,15 +2082,60 @@ spec:
name:
type: string
notTags:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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
type: array
x-kubernetes-list-type: atomic
@@ -2085,15 +2220,60 @@ spec:
name:
type: string
notTags:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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
type: array
serverGroup:
@@ -2347,15 +2527,60 @@ spec:
name:
type: string
notTags:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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
type: object
type: array
@@ -2385,15 +2610,60 @@ spec:
name:
type: string
notTags:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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
profile:
description: |-
@@ -2431,15 +2701,60 @@ spec:
name:
type: string
notTags:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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
type: array
x-kubernetes-list-type: atomic
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 ca42ad199f..5a4838e274 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
@@ -1582,15 +1582,60 @@ spec:
name:
type: string
notTags:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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
type: object
type: array
@@ -1621,15 +1666,60 @@ spec:
name:
type: string
notTags:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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
profile:
description: |-
@@ -1667,15 +1757,60 @@ spec:
name:
type: string
notTags:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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
type: array
x-kubernetes-list-type: atomic
@@ -1762,15 +1897,60 @@ spec:
name:
type: string
notTags:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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:
- type: string
+ 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
type: array
serverGroup:
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index 6fe81d5220..944155f100 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -632,8 +632,7 @@ func reconcilePreExistingNetworkComponents(scope *scope.WithLogger, networkingSe
openStackCluster.Status.Network = &infrav1.NetworkStatusWithSubnets{}
}
- emptyNetwork := infrav1.NetworkFilter{}
- if openStackCluster.Spec.Network != emptyNetwork {
+ if !openStackCluster.Spec.Network.IsEmpty() {
netOpts := openStackCluster.Spec.Network.ToListOpt()
networkList, err := networkingService.GetNetworksByFilter(&netOpts)
if err != nil {
diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md
index 48c293c608..9dc7667830 100644
--- a/docs/book/src/api/v1beta1/api.md
+++ b/docs/book/src/api/v1beta1/api.md
@@ -1417,6 +1417,88 @@ SubnetFilter
+
+
+(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.
+ |
+
+
+
FixedIP
@@ -1718,42 +1800,17 @@ string
-tags
-
-string
-
- |
-
- |
-
-
-
-tagsAny
+FilterByNeutronTags
-string
-
- |
-
- |
-
-
-
-notTags
-
-string
-
- |
-
- |
-
-
-
-notTagsAny
-
-string
+
+FilterByNeutronTags
+
|
+
+(Members of FilterByNeutronTags are embedded into this type.)
+
|
@@ -1856,6 +1913,16 @@ NetworkStatus
+NeutronTag
+(string alias)
+
+(Appears on:
+FilterByNeutronTags)
+
+
+
NeutronTag represents a tag on a Neutron resource.
+It may not be empty and may not contain commas.
+
OpenStackClusterSpec
@@ -3915,42 +3982,17 @@ string
-tags
-
-string
-
- |
-
- |
-
-
-
-tagsAny
-
-string
-
- |
-
- |
-
-
-
-notTags
-
-string
-
- |
-
- |
-
-
-
-notTagsAny
+FilterByNeutronTags
-string
+
+FilterByNeutronTags
+
|
+
+(Members of FilterByNeutronTags are embedded into this type.)
+
|
@@ -4014,42 +4056,17 @@ string
-tags
-
-string
-
- |
-
- |
-
-
-
-tagsAny
+FilterByNeutronTags
-string
-
- |
-
- |
-
-
-
-notTags
-
-string
-
- |
-
- |
-
-
-
-notTagsAny
-
-string
+
+FilterByNeutronTags
+
|
+
+(Members of FilterByNeutronTags are embedded into this type.)
+
|
@@ -4647,42 +4664,17 @@ string
-tags
+FilterByNeutronTags
-string
-
- |
-
- |
-
-
-
-tagsAny
-
-string
-
- |
-
- |
-
-
-
-notTags
-
-string
-
- |
-
- |
-
-
-
-notTagsAny
-
-string
+
+FilterByNeutronTags
+
|
+
+(Members of FilterByNeutronTags are embedded into this type.)
+
|
diff --git a/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md b/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
index 3087e41929..126b09b391 100644
--- a/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
+++ b/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
@@ -25,6 +25,7 @@
- [Change to managedSecurityGroups](#change-to-managedsecuritygroups)
- [Calico CNI](#calico-cni)
- [Change to network](#change-to-network)
+ - [Changes to filter tags](#changes-to-filter-tags)
@@ -312,3 +313,33 @@ allow backwards compatibility if `allowAllInClusterTraffic` is set to false.
#### Change to network
In v1beta1, when the `OpenStackCluster.Spec.Network` is not defined, the `Subnets` are now used to identify the `Network`.
+
+### Changes to filter tags
+
+We currently define filters on 4 different Neutron resources which are used throughout the API:
+* Networks
+* Subnets
+* Security Groups
+* Routers
+
+Each of these filters provide the following fields which filter by tag:
+* tags
+* tagsAny
+* notTags
+* notTagsAny
+
+We previously passed this value to Neutron without change, which treated it as a comma-separated list. In v1beta1 each of the tags fields becomes a list of tags. e.g.:
+
+```yaml
+subnet:
+ tags: "foo,bar"
+```
+becomes
+```yaml
+subnet:
+ tags:
+ - foo
+ - bar
+```
+
+Due to the limitations of the encoding of tag queries in Neutron, tags must be non-empty and may not contain commas. Tags will be automatically converted to a list of tags during conversion.
\ No newline at end of file
diff --git a/pkg/cloud/services/networking/network.go b/pkg/cloud/services/networking/network.go
index d1dc15c07f..20df7b96bb 100644
--- a/pkg/cloud/services/networking/network.go
+++ b/pkg/cloud/services/networking/network.go
@@ -86,7 +86,7 @@ func (s *Service) ReconcileExternalNetwork(openStackCluster *infrav1.OpenStackCl
return nil
}
- if openStackCluster.Spec.ExternalNetwork != emptyExternalnetwork {
+ if openStackCluster.Spec.ExternalNetwork.ToListOpt() != emptyExternalnetwork.ToListOpt() {
listOpts = external.ListOptsExt{
ListOptsBuilder: openStackCluster.Spec.ExternalNetwork.ToListOpt(),
}
diff --git a/pkg/cloud/services/networking/port.go b/pkg/cloud/services/networking/port.go
index a4f4488008..e9e8c6df3a 100644
--- a/pkg/cloud/services/networking/port.go
+++ b/pkg/cloud/services/networking/port.go
@@ -422,7 +422,7 @@ func (s *Service) normalizePorts(ports []infrav1.PortOpts, openStackCluster *inf
// normalizePortTarget ensures that the port has a network ID.
func (s *Service) normalizePortTarget(port *infrav1.PortOpts, openStackCluster *infrav1.OpenStackCluster, portIdx int) error {
// Treat no Network and empty Network the same
- noNetwork := port.Network == nil || (*port.Network == infrav1.NetworkFilter{})
+ noNetwork := port.Network == nil || port.Network.IsEmpty()
// No network or subnets defined: use cluster defaults
if noNetwork && len(port.FixedIPs) == 0 {
diff --git a/pkg/cloud/services/networking/port_test.go b/pkg/cloud/services/networking/port_test.go
index 9fd0c50a6c..5219886060 100644
--- a/pkg/cloud/services/networking/port_test.go
+++ b/pkg/cloud/services/networking/port_test.go
@@ -200,7 +200,9 @@ func Test_CreatePort(t *testing.T) {
Description: pointer.String("this is a test port"),
FixedIPs: []infrav1.FixedIP{{
Subnet: &infrav1.SubnetFilter{
- Tags: "Foo",
+ FilterByNeutronTags: infrav1.FilterByNeutronTags{
+ Tags: []infrav1.NeutronTag{"Foo"},
+ },
},
IPAddress: pointer.String("192.168.0.50"),
}},
From 412cae39d71babab9f5eab7ecbc06c5bdf92accb Mon Sep 17 00:00:00 2001
From: Emilien Macchi
Date: Thu, 29 Feb 2024 19:29:48 -0500
Subject: [PATCH 089/180] ci: fix upgrades by dropping cloudName
---
.../data/kustomize/k8s-upgrade/upgrade-from-template.yaml | 6 ------
.../e2e/data/kustomize/k8s-upgrade/upgrade-to-template.yaml | 6 ------
2 files changed, 12 deletions(-)
diff --git a/test/e2e/data/kustomize/k8s-upgrade/upgrade-from-template.yaml b/test/e2e/data/kustomize/k8s-upgrade/upgrade-from-template.yaml
index 73d862f51b..6e9098977b 100644
--- a/test/e2e/data/kustomize/k8s-upgrade/upgrade-from-template.yaml
+++ b/test/e2e/data/kustomize/k8s-upgrade/upgrade-from-template.yaml
@@ -6,10 +6,7 @@ metadata:
spec:
template:
spec:
- cloudName: ${OPENSTACK_CLOUD}
flavor: ${OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR}
- identityRef:
- name: ${CLUSTER_NAME}-cloud-config
image:
name: ${OPENSTACK_IMAGE_NAME_UPGRADE_FROM}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
@@ -23,10 +20,7 @@ metadata:
spec:
template:
spec:
- cloudName: ${OPENSTACK_CLOUD}
flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR}
- identityRef:
- name: ${CLUSTER_NAME}-cloud-config
image:
name: ${OPENSTACK_IMAGE_NAME_UPGRADE_FROM}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
diff --git a/test/e2e/data/kustomize/k8s-upgrade/upgrade-to-template.yaml b/test/e2e/data/kustomize/k8s-upgrade/upgrade-to-template.yaml
index 5b06321073..39272254fd 100644
--- a/test/e2e/data/kustomize/k8s-upgrade/upgrade-to-template.yaml
+++ b/test/e2e/data/kustomize/k8s-upgrade/upgrade-to-template.yaml
@@ -13,10 +13,7 @@ metadata:
spec:
template:
spec:
- cloudName: ${OPENSTACK_CLOUD}
flavor: ${OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR}
- identityRef:
- name: ${CLUSTER_NAME}-cloud-config
image:
name: ${OPENSTACK_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
@@ -32,10 +29,7 @@ metadata:
spec:
template:
spec:
- cloudName: ${OPENSTACK_CLOUD}
flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR}
- identityRef:
- name: ${CLUSTER_NAME}-cloud-config
image:
name: ${OPENSTACK_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
From c2e8b4908382da3a836447f710640c84433145c2 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Thu, 29 Feb 2024 23:30:56 +0000
Subject: [PATCH 090/180] Update ginkgo to 2.15.0
---
go.mod | 16 ++++++++--------
go.sum | 32 ++++++++++++++++----------------
hack/tools/go.mod | 2 +-
hack/tools/go.sum | 4 ++--
4 files changed, 27 insertions(+), 27 deletions(-)
diff --git a/go.mod b/go.mod
index 565999d219..50ebe0a6a8 100644
--- a/go.mod
+++ b/go.mod
@@ -11,11 +11,11 @@ require (
github.com/gophercloud/gophercloud v1.7.0
github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56
github.com/hashicorp/go-version v1.4.0
- github.com/onsi/ginkgo/v2 v2.13.1
+ github.com/onsi/ginkgo/v2 v2.15.0
github.com/onsi/gomega v1.30.0
github.com/prometheus/client_golang v1.17.0
github.com/spf13/pflag v1.0.5
- golang.org/x/crypto v0.15.0
+ golang.org/x/crypto v0.16.0
golang.org/x/text v0.14.0
gopkg.in/ini.v1 v1.67.0
k8s.io/api v0.28.4
@@ -135,14 +135,14 @@ require (
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.25.0 // indirect
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
- golang.org/x/mod v0.13.0 // indirect
- golang.org/x/net v0.18.0 // indirect
+ golang.org/x/mod v0.14.0 // indirect
+ golang.org/x/net v0.19.0 // indirect
golang.org/x/oauth2 v0.14.0 // indirect
- golang.org/x/sync v0.4.0 // indirect
- golang.org/x/sys v0.14.0 // indirect
- golang.org/x/term v0.14.0 // indirect
+ golang.org/x/sync v0.5.0 // indirect
+ golang.org/x/sys v0.15.0 // indirect
+ golang.org/x/term v0.15.0 // indirect
golang.org/x/time v0.3.0 // indirect
- golang.org/x/tools v0.14.0 // indirect
+ golang.org/x/tools v0.16.1 // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb // indirect
diff --git a/go.sum b/go.sum
index c5f22dace3..3da2fa64fd 100644
--- a/go.sum
+++ b/go.sum
@@ -343,8 +343,8 @@ github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7P
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
-github.com/onsi/ginkgo/v2 v2.13.1 h1:LNGfMbR2OVGBfXjvRZIZ2YCTQdGKtPLvuI1rMCCj3OU=
-github.com/onsi/ginkgo/v2 v2.13.1/go.mod h1:XStQ8QcGwLyF4HdfcZB8SFOS/MWCgDuXMSBe6zrvLgM=
+github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY=
+github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM=
github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8=
github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
@@ -491,8 +491,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
-golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA=
-golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
+golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY=
+golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -530,8 +530,8 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
-golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
-golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
+golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -567,8 +567,8 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
-golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
-golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
+golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
+golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -592,8 +592,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
-golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
+golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
+golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -640,13 +640,13 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
-golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
+golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
-golang.org/x/term v0.14.0 h1:LGK9IlZ8T9jvdy6cTdfKUCltatMFOehAQo9SRC46UQ8=
-golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww=
+golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
+golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -715,8 +715,8 @@ golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
-golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc=
-golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
+golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA=
+golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/hack/tools/go.mod b/hack/tools/go.mod
index 5d0c742794..32f7f0856e 100644
--- a/hack/tools/go.mod
+++ b/hack/tools/go.mod
@@ -7,7 +7,7 @@ require (
github.com/ahmetb/gen-crd-api-reference-docs v0.3.1-0.20220420215017-3f29e6853552
github.com/golang/mock v1.6.0
github.com/itchyny/gojq v0.12.2
- github.com/onsi/ginkgo/v2 v2.13.0
+ github.com/onsi/ginkgo/v2 v2.15.0
k8s.io/code-generator v0.29.0
sigs.k8s.io/cluster-api/hack/tools v0.0.0-20221129083400-679ae3e9e6b6
sigs.k8s.io/controller-runtime/tools/setup-envtest v0.0.0-20230926180527-c93e2abcb28e
diff --git a/hack/tools/go.sum b/hack/tools/go.sum
index 54f95cff3e..abac2117f7 100644
--- a/hack/tools/go.sum
+++ b/hack/tools/go.sum
@@ -220,8 +220,8 @@ github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
-github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4=
-github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o=
+github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY=
+github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM=
github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8=
github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
From 120bc682203a8b8651cbddb0b09853d2ea83d10d Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Fri, 1 Mar 2024 00:52:29 +0000
Subject: [PATCH 091/180] ManagedSecurityGroups: fix missing omitemptys on
optional fields
---
api/v1alpha5/conversion_test.go | 4 ++--
api/v1beta1/openstackcluster_types.go | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/api/v1alpha5/conversion_test.go b/api/v1alpha5/conversion_test.go
index 3aa5f57d43..1ecbf00a13 100644
--- a/api/v1alpha5/conversion_test.go
+++ b/api/v1alpha5/conversion_test.go
@@ -51,7 +51,7 @@ func TestConvertFrom(t *testing.T) {
},
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
- "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"apiServerLoadBalancer\":{},\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"disableExternalNetwork\":false,\"externalNetwork\":{},\"identityRef\":{\"cloudName\":\"\",\"name\":\"\"},\"managedSecurityGroups\":null,\"network\":{}},\"status\":{\"ready\":false}}",
+ "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"apiServerLoadBalancer\":{},\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"disableExternalNetwork\":false,\"externalNetwork\":{},\"identityRef\":{\"cloudName\":\"\",\"name\":\"\"},\"network\":{}},\"status\":{\"ready\":false}}",
},
},
},
@@ -72,7 +72,7 @@ func TestConvertFrom(t *testing.T) {
},
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
- "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"template\":{\"spec\":{\"apiServerLoadBalancer\":{},\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"disableExternalNetwork\":false,\"externalNetwork\":{},\"identityRef\":{\"cloudName\":\"\",\"name\":\"\"},\"managedSecurityGroups\":null,\"network\":{}}}}}",
+ "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"template\":{\"spec\":{\"apiServerLoadBalancer\":{},\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"disableExternalNetwork\":false,\"externalNetwork\":{},\"identityRef\":{\"cloudName\":\"\",\"name\":\"\"},\"network\":{}}}}}",
},
},
},
diff --git a/api/v1beta1/openstackcluster_types.go b/api/v1beta1/openstackcluster_types.go
index d5cda0ec1a..7ca146ef70 100644
--- a/api/v1beta1/openstackcluster_types.go
+++ b/api/v1beta1/openstackcluster_types.go
@@ -123,7 +123,7 @@ type OpenStackClusterSpec struct {
// 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
- ManagedSecurityGroups *ManagedSecurityGroups `json:"managedSecurityGroups"`
+ ManagedSecurityGroups *ManagedSecurityGroups `json:"managedSecurityGroups,omitempty"`
// DisablePortSecurity disables the port security of the network created for the
// Kubernetes cluster, which also disables SecurityGroups
@@ -272,7 +272,7 @@ type ManagedSecurityGroups struct {
// +listType=map
// +listMapKey=name
// +optional
- AllNodesSecurityGroupRules []SecurityGroupRuleSpec `json:"allNodesSecurityGroupRules" patchStrategy:"merge" patchMergeKey:"name"`
+ 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
From a4e207974a4884449898d83aa1fe0283dd3905ed Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Fri, 1 Mar 2024 00:59:15 +0000
Subject: [PATCH 092/180] tests: Add TEST_PATHS target for make test
TEST_PATHS defaults to the previous hardcoded value of './...', but can
now be overridden. e.g. To run just the controller tests:
make test TEST_PATHS=./controllers/...
---
Makefile | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
index e33ce59c68..4eb9f5d757 100644
--- a/Makefile
+++ b/Makefile
@@ -134,12 +134,13 @@ ifdef KUBEBUILDER_ASSETS_DIR
endif
.PHONY: test
+TEST_PATHS ?= ./...
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)
+ 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
From 8533ef501d8d90774b9f98726a5db1e5f870f9c8 Mon Sep 17 00:00:00 2001
From: Hugo Blom <6117705+huxcrux@users.noreply.github.com>
Date: Fri, 1 Mar 2024 14:02:14 +0100
Subject: [PATCH 093/180] Make sure that additional ports security groups are
dynamic and cannot go out of range
---
pkg/cloud/services/networking/securitygroups_rules.go | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/pkg/cloud/services/networking/securitygroups_rules.go b/pkg/cloud/services/networking/securitygroups_rules.go
index e7dcdd1d3b..5bea83c1a4 100644
--- a/pkg/cloud/services/networking/securitygroups_rules.go
+++ b/pkg/cloud/services/networking/securitygroups_rules.go
@@ -223,11 +223,9 @@ func getSGControlPlaneAdditionalPorts(ports []int) []resolvedSecurityGroupRuleSp
Protocol: "tcp",
},
}
- for _, p := range ports {
- r[0].PortRangeMin = p
- r[0].PortRangeMax = p
- r[1].PortRangeMin = p
- r[1].PortRangeMax = p
+ for i, p := range ports {
+ r[i].PortRangeMin = p
+ r[i].PortRangeMax = p
controlPlaneRules = append(controlPlaneRules, r...)
}
return controlPlaneRules
From 4d3e79c8cc23dc4d8bab0f77bec8b44e45e5319e Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Fri, 1 Mar 2024 01:01:08 +0000
Subject: [PATCH 094/180] Add framework for api validation tests using envtest
---
.../apivalidations/neutronfilters_test.go | 176 ++++++++++++++++++
.../apivalidations/openstackcluster_test.go | 62 ++++++
.../apivalidations/openstackmachine_test.go | 57 ++++++
test/e2e/suites/apivalidations/suite_test.go | 159 ++++++++++++++++
4 files changed, 454 insertions(+)
create mode 100644 test/e2e/suites/apivalidations/neutronfilters_test.go
create mode 100644 test/e2e/suites/apivalidations/openstackcluster_test.go
create mode 100644 test/e2e/suites/apivalidations/openstackmachine_test.go
create mode 100644 test/e2e/suites/apivalidations/suite_test.go
diff --git a/test/e2e/suites/apivalidations/neutronfilters_test.go b/test/e2e/suites/apivalidations/neutronfilters_test.go
new file mode 100644
index 0000000000..540cb815c0
--- /dev/null
+++ b/test/e2e/suites/apivalidations/neutronfilters_test.go
@@ -0,0 +1,176 @@
+/*
+Copyright 2024 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 apivalidations
+
+import (
+ . "github.com/onsi/ginkgo/v2"
+ . "github.com/onsi/gomega"
+ corev1 "k8s.io/api/core/v1"
+
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
+)
+
+var _ = Describe("Neutron filter API validations", func() {
+ var (
+ namespace *corev1.Namespace
+ cluster *infrav1.OpenStackCluster
+ machine *infrav1.OpenStackMachine
+ )
+
+ BeforeEach(func() {
+ namespace = createNamespace()
+
+ // Initialise a basic machine object in the correct namespace
+ machine = &infrav1.OpenStackMachine{}
+ machine.Namespace = namespace.Name
+ machine.GenerateName = "machine-"
+
+ // Initialise a basic cluster object in the correct namespace
+ cluster = &infrav1.OpenStackCluster{}
+ cluster.Namespace = namespace.Name
+ cluster.GenerateName = "cluster-"
+ })
+
+ DescribeTable("Allow valid neutron filter tags", func(tags []infrav1.FilterByNeutronTags) {
+ // Specify the given neutron tags in every filter it is
+ // possible to specify them in, then create the
+ // resulting object. It should be valid.
+
+ securityGroups := make([]infrav1.SecurityGroupFilter, len(tags))
+ for i := range tags {
+ securityGroups[i].FilterByNeutronTags = tags[i]
+ }
+ machine.Spec.SecurityGroups = securityGroups
+
+ ports := make([]infrav1.PortOpts, len(tags))
+ for i := range tags {
+ port := &ports[i]
+ port.Network = &infrav1.NetworkFilter{FilterByNeutronTags: tags[i]}
+ port.FixedIPs = []infrav1.FixedIP{{Subnet: &infrav1.SubnetFilter{FilterByNeutronTags: tags[i]}}}
+ port.SecurityGroups = []infrav1.SecurityGroupFilter{{FilterByNeutronTags: tags[i]}}
+ }
+ Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "OpenStackMachine creation should succeed")
+
+ // Maximum of 2 subnets are supported
+ nSubnets := min(len(tags), 2)
+ subnets := make([]infrav1.SubnetFilter, nSubnets)
+ for i := 0; i < nSubnets; i++ {
+ subnets[i].FilterByNeutronTags = tags[i]
+ }
+ cluster.Spec.Subnets = subnets
+ if len(tags) > 0 {
+ cluster.Spec.Network = infrav1.NetworkFilter{FilterByNeutronTags: tags[0]}
+ cluster.Spec.ExternalNetwork = infrav1.NetworkFilter{FilterByNeutronTags: tags[0]}
+ cluster.Spec.Router = &infrav1.RouterFilter{FilterByNeutronTags: tags[0]}
+ }
+ Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
+ },
+ Entry("empty list", nil),
+ Entry("single tag", []infrav1.FilterByNeutronTags{
+ {Tags: []infrav1.NeutronTag{"foo"}},
+ }),
+ Entry("multiple filters, multiple tags", []infrav1.FilterByNeutronTags{
+ {Tags: []infrav1.NeutronTag{"foo", "bar"}},
+ {TagsAny: []infrav1.NeutronTag{"foo", "bar"}},
+ {NotTags: []infrav1.NeutronTag{"foo", "bar"}},
+ {NotTagsAny: []infrav1.NeutronTag{"foo", "bar"}},
+ }),
+ )
+
+ DescribeTable("Disallow invalid neutron filter tags", func(tags []infrav1.FilterByNeutronTags) {
+ {
+ machine := machine.DeepCopy()
+ securityGroups := make([]infrav1.SecurityGroupFilter, len(tags))
+ for i := range tags {
+ securityGroups[i].FilterByNeutronTags = tags[i]
+ }
+ machine.Spec.SecurityGroups = securityGroups
+ Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail with invalid security group neutron tags")
+ }
+
+ for i := range tags {
+ {
+ machine := machine.DeepCopy()
+ machine.Spec.Ports = []infrav1.PortOpts{
+ {Network: &infrav1.NetworkFilter{FilterByNeutronTags: tags[i]}},
+ }
+ Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail with invalid port network neutron tags")
+ }
+ {
+ machine := machine.DeepCopy()
+ machine.Spec.Ports = []infrav1.PortOpts{
+ {FixedIPs: []infrav1.FixedIP{{Subnet: &infrav1.SubnetFilter{FilterByNeutronTags: tags[i]}}}},
+ }
+ Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail with invalid port subnet neutron tags")
+ }
+ {
+ machine := machine.DeepCopy()
+ machine.Spec.Ports = []infrav1.PortOpts{
+ {SecurityGroups: []infrav1.SecurityGroupFilter{{FilterByNeutronTags: tags[i]}}},
+ }
+ Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail with invalid port security group neutron tags")
+ }
+ }
+
+ if len(tags) > 0 {
+ tag := tags[0]
+
+ {
+ cluster := cluster.DeepCopy()
+ cluster.Spec.Subnets = []infrav1.SubnetFilter{{FilterByNeutronTags: tag}}
+ Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should fail with invalid subnet neutron tags")
+ }
+
+ {
+ cluster := cluster.DeepCopy()
+ cluster.Spec.Network = infrav1.NetworkFilter{FilterByNeutronTags: tag}
+ Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should fail with invalid network neutron tags")
+ }
+
+ {
+ cluster := cluster.DeepCopy()
+ cluster.Spec.ExternalNetwork = infrav1.NetworkFilter{FilterByNeutronTags: tag}
+ Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should fail with invalid external network neutron tags")
+ }
+
+ {
+ cluster := cluster.DeepCopy()
+ cluster.Spec.Router = &infrav1.RouterFilter{FilterByNeutronTags: tag}
+ Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should fail with invalid router neutron tags")
+ }
+ }
+ },
+ Entry("contains leading comma", []infrav1.FilterByNeutronTags{
+ {Tags: []infrav1.NeutronTag{",foo"}},
+ }),
+ Entry("contains trailing comma", []infrav1.FilterByNeutronTags{
+ {Tags: []infrav1.NeutronTag{"foo,"}},
+ }),
+ Entry("contains comma in middle", []infrav1.FilterByNeutronTags{
+ {Tags: []infrav1.NeutronTag{"foo,bar"}},
+ }),
+ Entry("contains multiple commas", []infrav1.FilterByNeutronTags{
+ {Tags: []infrav1.NeutronTag{"foo,,bar"}},
+ }),
+ Entry("empty tag", []infrav1.FilterByNeutronTags{
+ {Tags: []infrav1.NeutronTag{""}},
+ }),
+ Entry("second tag is invalid", []infrav1.FilterByNeutronTags{
+ {Tags: []infrav1.NeutronTag{"foo", ""}},
+ }),
+ )
+})
diff --git a/test/e2e/suites/apivalidations/openstackcluster_test.go b/test/e2e/suites/apivalidations/openstackcluster_test.go
new file mode 100644
index 0000000000..00fd97197b
--- /dev/null
+++ b/test/e2e/suites/apivalidations/openstackcluster_test.go
@@ -0,0 +1,62 @@
+/*
+Copyright 2024 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 apivalidations
+
+import (
+ . "github.com/onsi/ginkgo/v2"
+ . "github.com/onsi/gomega"
+ corev1 "k8s.io/api/core/v1"
+
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
+)
+
+var _ = Describe("OpenStackCluster API validations", func() {
+ var cluster *infrav1.OpenStackCluster
+ var namespace *corev1.Namespace
+
+ BeforeEach(func() {
+ namespace = createNamespace()
+
+ // Initialise a basic cluster object in the correct namespace
+ cluster = &infrav1.OpenStackCluster{}
+ cluster.Namespace = namespace.Name
+ cluster.GenerateName = "cluster-"
+ })
+
+ It("should allow the smallest permissible cluster spec", func() {
+ Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
+ })
+
+ It("should only allow controlPlaneEndpoint to be set once", func() {
+ By("Creating a bare cluster")
+ Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
+
+ By("Setting the control plane endpoint")
+ cluster.Spec.ControlPlaneEndpoint.Host = "foo"
+ cluster.Spec.ControlPlaneEndpoint.Port = 1234
+ Expect(k8sClient.Update(ctx, cluster)).To(Succeed(), "Setting control plane endpoint should succeed")
+
+ By("Modifying the control plane endpoint")
+ cluster.Spec.ControlPlaneEndpoint.Host = "bar"
+ Expect(k8sClient.Update(ctx, cluster)).NotTo(Succeed(), "Updating control plane endpoint should fail")
+ })
+
+ It("should allow an empty managed security groups definition", func() {
+ cluster.Spec.ManagedSecurityGroups = &infrav1.ManagedSecurityGroups{}
+ Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
+ })
+})
diff --git a/test/e2e/suites/apivalidations/openstackmachine_test.go b/test/e2e/suites/apivalidations/openstackmachine_test.go
new file mode 100644
index 0000000000..00f262cc0b
--- /dev/null
+++ b/test/e2e/suites/apivalidations/openstackmachine_test.go
@@ -0,0 +1,57 @@
+/*
+Copyright 2024 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 apivalidations
+
+import (
+ . "github.com/onsi/ginkgo/v2"
+ . "github.com/onsi/gomega"
+ corev1 "k8s.io/api/core/v1"
+ "k8s.io/utils/pointer"
+
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
+)
+
+var _ = Describe("OpenStackMachine API validations", func() {
+ var namespace *corev1.Namespace
+ var machine *infrav1.OpenStackMachine
+
+ BeforeEach(func() {
+ namespace = createNamespace()
+
+ // Initialise a basic machine object in the correct namespace
+ machine = &infrav1.OpenStackMachine{}
+ machine.Namespace = namespace.Name
+ machine.GenerateName = "machine-"
+ })
+
+ It("should allow the smallest permissible machine spec", func() {
+ Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "OpenStackMachine creation should succeed")
+ })
+
+ It("should only allow the providerID to be set once", func() {
+ By("Creating a bare machine")
+ Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "OpenStackMachine creation should succeed")
+
+ By("Setting the providerID")
+ machine.Spec.ProviderID = pointer.String("foo")
+ Expect(k8sClient.Update(ctx, machine)).To(Succeed(), "Setting providerID should succeed")
+
+ By("Modifying the providerID")
+ machine.Spec.ProviderID = pointer.String("bar")
+ Expect(k8sClient.Update(ctx, machine)).NotTo(Succeed(), "Updating providerID should fail")
+ })
+})
diff --git a/test/e2e/suites/apivalidations/suite_test.go b/test/e2e/suites/apivalidations/suite_test.go
new file mode 100644
index 0000000000..65a8e69136
--- /dev/null
+++ b/test/e2e/suites/apivalidations/suite_test.go
@@ -0,0 +1,159 @@
+/*
+Copyright 2024 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 apivalidations
+
+import (
+ "context"
+ "fmt"
+ "path/filepath"
+ "strconv"
+ "testing"
+
+ . "github.com/onsi/ginkgo/v2"
+ . "github.com/onsi/gomega"
+ corev1 "k8s.io/api/core/v1"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/runtime"
+ "k8s.io/client-go/discovery"
+ "k8s.io/client-go/kubernetes/scheme"
+ "k8s.io/client-go/rest"
+ ctrl "sigs.k8s.io/controller-runtime"
+ "sigs.k8s.io/controller-runtime/pkg/client"
+ "sigs.k8s.io/controller-runtime/pkg/envtest"
+ "sigs.k8s.io/controller-runtime/pkg/envtest/komega"
+ "sigs.k8s.io/controller-runtime/pkg/metrics/server"
+ "sigs.k8s.io/controller-runtime/pkg/webhook"
+
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
+)
+
+var (
+ cfg *rest.Config
+ k8sClient client.Client
+ testEnv *envtest.Environment
+ testScheme *runtime.Scheme
+ ctx = context.Background()
+ mgrCancel context.CancelFunc
+ mgrDone chan struct{}
+)
+
+func TestAPIs(t *testing.T) {
+ RegisterFailHandler(Fail)
+
+ RunSpecs(t, "API Validation Suite")
+}
+
+var _ = BeforeSuite(func() {
+ By("bootstrapping test environment")
+ testEnv = &envtest.Environment{
+ CRDDirectoryPaths: []string{
+ // NOTE: These are the bare CRDs without conversion webhooks
+ filepath.Join("..", "..", "..", "..", "config", "crd", "bases"),
+ },
+ ErrorIfCRDPathMissing: true,
+ WebhookInstallOptions: envtest.WebhookInstallOptions{
+ Paths: []string{
+ filepath.Join("..", "..", "..", "..", "config", "webhook"),
+ },
+ },
+ }
+
+ var err error
+ cfg, err = testEnv.Start()
+ Expect(err).NotTo(HaveOccurred(), "test environment should start")
+ Expect(cfg).NotTo(BeNil(), "test environment should return a configuration")
+ DeferCleanup(func() error {
+ By("tearing down the test environment")
+ return testEnv.Stop()
+ })
+
+ testScheme = scheme.Scheme
+ Expect(infrav1.AddToScheme(testScheme)).To(Succeed())
+
+ //+kubebuilder:scaffold:scheme
+
+ k8sClient, err = client.New(cfg, client.Options{Scheme: testScheme})
+ Expect(err).NotTo(HaveOccurred())
+ Expect(k8sClient).NotTo(BeNil())
+
+ // CEL requires Kube 1.25 and above, so check for the minimum server version.
+ discoveryClient, err := discovery.NewDiscoveryClientForConfig(cfg)
+ Expect(err).ToNot(HaveOccurred())
+
+ serverVersion, err := discoveryClient.ServerVersion()
+ Expect(err).ToNot(HaveOccurred())
+
+ Expect(serverVersion.Major).To(Equal("1"))
+
+ minorInt, err := strconv.Atoi(serverVersion.Minor)
+ Expect(err).ToNot(HaveOccurred())
+ Expect(minorInt).To(BeNumerically(">=", 25), fmt.Sprintf("This test suite requires a Kube API server of at least version 1.25, current version is 1.%s", serverVersion.Minor))
+
+ komega.SetClient(k8sClient)
+ komega.SetContext(ctx)
+
+ By("Setting up manager and webhooks")
+ mgr, err := ctrl.NewManager(cfg, ctrl.Options{
+ Scheme: testScheme,
+ Metrics: server.Options{
+ BindAddress: "0",
+ },
+ WebhookServer: webhook.NewServer(webhook.Options{
+ Port: testEnv.WebhookInstallOptions.LocalServingPort,
+ Host: testEnv.WebhookInstallOptions.LocalServingHost,
+ CertDir: testEnv.WebhookInstallOptions.LocalServingCertDir,
+ }),
+ })
+ Expect(err).ToNot(HaveOccurred(), "Manager setup should succeed")
+
+ Expect((&infrav1.OpenStackMachineTemplateWebhook{}).SetupWebhookWithManager(mgr)).To(Succeed(), "OpenStackMachineTemplate webhook should be registered with manager")
+ Expect((&infrav1.OpenStackMachineTemplateList{}).SetupWebhookWithManager(mgr)).To(Succeed(), "OpenStackMachineTemplateList webhook should be registered with manager")
+ Expect((&infrav1.OpenStackCluster{}).SetupWebhookWithManager(mgr)).To(Succeed(), "OpenStackCluster webhook should be registered with manager")
+ Expect((&infrav1.OpenStackClusterTemplate{}).SetupWebhookWithManager(mgr)).To(Succeed(), "OpenStackClusterTemplate webhook should be registered with manager")
+ Expect((&infrav1.OpenStackMachine{}).SetupWebhookWithManager(mgr)).To(Succeed(), "OpenStackMachine webhook should be registered with manager")
+ Expect((&infrav1.OpenStackMachineList{}).SetupWebhookWithManager(mgr)).To(Succeed(), "OpenStackMachineList webhook should be registered with manager")
+ Expect((&infrav1.OpenStackClusterList{}).SetupWebhookWithManager(mgr)).To(Succeed(), "OpenStackClusterList webhook should be registered with manager")
+
+ By("Starting manager")
+ var mgrCtx context.Context
+ mgrDone = make(chan struct{})
+ mgrCtx, mgrCancel = context.WithCancel(context.Background())
+
+ go func() {
+ defer GinkgoRecover()
+ defer close(mgrDone)
+ Expect(mgr.Start(mgrCtx)).To(Succeed(), "Manager should start")
+ }()
+ DeferCleanup(func() {
+ By("Tearing down manager")
+ mgrCancel()
+ Eventually(mgrDone).Should(BeClosed(), "Manager should stop")
+ })
+})
+
+func createNamespace() *corev1.Namespace {
+ By("Creating namespace")
+ namespace := corev1.Namespace{}
+ namespace.GenerateName = "test-"
+ Expect(k8sClient.Create(ctx, &namespace)).To(Succeed(), "Namespace creation should succeed")
+ DeferCleanup(func() {
+ By("Deleting namespace")
+ Expect(k8sClient.Delete(ctx, &namespace, client.PropagationPolicy(metav1.DeletePropagationForeground))).To(Succeed(), "Namespace deletion should succeed")
+ })
+ By(fmt.Sprintf("Using namespace %s", namespace.Name))
+ return &namespace
+}
From 750b84de45c2e884daa690143a56091e2b79a3f8 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Fri, 1 Mar 2024 18:14:07 +0000
Subject: [PATCH 095/180] Move webhooks into pkg/webhooks
Moves webhooks from api to pkg/webhooks making only mechanical code
changes except for the removal of the defaulting webhooks, because they
weren't used. This results in there now being no mutating webhook
configured.
---
Makefile | 2 +-
api/v1beta1/openstackcluster_webhook.go | 156 ---------
api/v1beta1/openstackclusterlist_webhook.go | 32 --
.../openstackclustertemplate_webhook.go | 78 -----
api/v1beta1/openstackmachinelist_webhook.go | 32 --
.../openstackmachinetemplatelist_webhook.go | 32 --
config/webhook/manifests.yaml | 69 ----
docs/book/src/api/v1beta1/api.md | 4 -
main.go | 32 +-
.../webhooks.go => pkg/webhooks/errors.go | 2 +-
pkg/webhooks/openstackcluster_webhook.go | 167 ++++++++++
.../openstackcluster_webhook_test.go | 309 +++++++++---------
.../openstackclustertemplate_webhook.go | 90 +++++
.../webhooks}/openstackmachine_webhook.go | 72 ++--
.../openstackmachinetemplate_webhook.go | 61 ++--
.../openstackmachinetemplate_webhook_test.go | 90 ++---
pkg/webhooks/register.go | 63 ++++
test/e2e/suites/apivalidations/suite_test.go | 10 +-
18 files changed, 610 insertions(+), 691 deletions(-)
delete mode 100644 api/v1beta1/openstackcluster_webhook.go
delete mode 100644 api/v1beta1/openstackclusterlist_webhook.go
delete mode 100644 api/v1beta1/openstackclustertemplate_webhook.go
delete mode 100644 api/v1beta1/openstackmachinelist_webhook.go
delete mode 100644 api/v1beta1/openstackmachinetemplatelist_webhook.go
rename api/v1beta1/webhooks.go => pkg/webhooks/errors.go (98%)
create mode 100644 pkg/webhooks/openstackcluster_webhook.go
rename {api/v1beta1 => pkg/webhooks}/openstackcluster_webhook_test.go (56%)
create mode 100644 pkg/webhooks/openstackclustertemplate_webhook.go
rename {api/v1beta1 => pkg/webhooks}/openstackmachine_webhook.go (57%)
rename {api/v1beta1 => pkg/webhooks}/openstackmachinetemplate_webhook.go (55%)
rename {api/v1beta1 => pkg/webhooks}/openstackmachinetemplate_webhook_test.go (55%)
create mode 100644 pkg/webhooks/register.go
diff --git a/Makefile b/Makefile
index 4eb9f5d757..7a0b864d05 100644
--- a/Makefile
+++ b/Makefile
@@ -274,7 +274,7 @@ generate-conversion-gen: $(CONVERSION_GEN)
.PHONY: generate-manifests
generate-manifests: $(CONTROLLER_GEN) ## Generate manifests e.g. CRD, RBAC etc.
$(CONTROLLER_GEN) \
- paths=./api/... \
+ paths=./pkg/webhooks/... \
crd:crdVersions=v1 \
output:crd:dir=$(CRD_ROOT) \
output:webhook:dir=$(WEBHOOK_ROOT) \
diff --git a/api/v1beta1/openstackcluster_webhook.go b/api/v1beta1/openstackcluster_webhook.go
deleted file mode 100644
index 97781ea2c6..0000000000
--- a/api/v1beta1/openstackcluster_webhook.go
+++ /dev/null
@@ -1,156 +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 v1beta1
-
-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-v1beta1-openstackcluster,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=openstackclusters,versions=v1beta1,name=validation.openstackcluster.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1
-// +kubebuilder:webhook:verbs=create;update,path=/mutate-infrastructure-cluster-x-k8s-io-v1beta1-openstackcluster,mutating=true,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=openstackclusters,versions=v1beta1,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() {
-}
-
-// 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.ManagedSecurityGroups != nil {
- for _, rule := range r.Spec.ManagedSecurityGroups.AllNodesSecurityGroupRules {
- if rule.RemoteManagedGroups != nil && (rule.RemoteGroupID != nil || rule.RemoteIPPrefix != nil) {
- allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "managedSecurityGroups", "allNodesSecurityGroupRules"), "remoteManagedGroups cannot be used with remoteGroupID or remoteIPPrefix"))
- }
- if rule.RemoteGroupID != nil && (rule.RemoteManagedGroups != nil || rule.RemoteIPPrefix != nil) {
- allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "managedSecurityGroups", "allNodesSecurityGroupRules"), "remoteGroupID cannot be used with remoteManagedGroups or remoteIPPrefix"))
- }
- if rule.RemoteIPPrefix != nil && (rule.RemoteManagedGroups != nil || rule.RemoteGroupID != nil) {
- allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "managedSecurityGroups", "allNodesSecurityGroupRules"), "remoteIPPrefix cannot be used with remoteManagedGroups or remoteGroupID"))
- }
- }
- }
-
- 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))
- }
-
- // Allow changes to Spec.IdentityRef
- old.Spec.IdentityRef = OpenStackIdentityReference{}
- r.Spec.IdentityRef = OpenStackIdentityReference{}
-
- // 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 to remove the bastion spec only if it was disabled before.
- if r.Spec.Bastion == nil {
- if old.Spec.Bastion != nil && old.Spec.Bastion.Enabled {
- allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "bastion"), "cannot be removed before disabling it"))
- }
- }
-
- // Allow changes to the bastion spec.
- old.Spec.Bastion = &Bastion{}
- r.Spec.Bastion = &Bastion{}
-
- // Allow changes to the managed allNodesSecurityGroupRules.
- if r.Spec.ManagedSecurityGroups != nil {
- old.Spec.ManagedSecurityGroups.AllNodesSecurityGroupRules = []SecurityGroupRuleSpec{}
- r.Spec.ManagedSecurityGroups.AllNodesSecurityGroupRules = []SecurityGroupRuleSpec{}
-
- // Allow change to the allowAllInClusterTraffic.
- old.Spec.ManagedSecurityGroups.AllowAllInClusterTraffic = false
- r.Spec.ManagedSecurityGroups.AllowAllInClusterTraffic = false
- }
-
- // 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 the scheduling to be changed from CAPI managed to Nova and
- // vice versa.
- old.Spec.ControlPlaneOmitAvailabilityZone = false
- r.Spec.ControlPlaneOmitAvailabilityZone = 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/v1beta1/openstackclusterlist_webhook.go b/api/v1beta1/openstackclusterlist_webhook.go
deleted file mode 100644
index c765ad7cb8..0000000000
--- a/api/v1beta1/openstackclusterlist_webhook.go
+++ /dev/null
@@ -1,32 +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 v1beta1
-
-import (
- "sigs.k8s.io/controller-runtime/pkg/builder"
- logf "sigs.k8s.io/controller-runtime/pkg/log"
- "sigs.k8s.io/controller-runtime/pkg/manager"
-)
-
-// log is for logging in this package.
-var _ = logf.Log.WithName("openstackclusterlist-resource")
-
-func (r *OpenStackClusterList) SetupWebhookWithManager(mgr manager.Manager) error {
- return builder.WebhookManagedBy(mgr).
- For(r).
- Complete()
-}
diff --git a/api/v1beta1/openstackclustertemplate_webhook.go b/api/v1beta1/openstackclustertemplate_webhook.go
deleted file mode 100644
index 700dac06e2..0000000000
--- a/api/v1beta1/openstackclustertemplate_webhook.go
+++ /dev/null
@@ -1,78 +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 v1beta1
-
-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-v1beta1-openstackclustertemplate,mutating=true,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=openstackclustertemplates,versions=v1beta1,name=default.openstackclustertemplate.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1
-// +kubebuilder:webhook:verbs=create;update,path=/validate-infrastructure-cluster-x-k8s-io-v1beta1-openstackclustertemplate,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=openstackclustertemplates,versions=v1beta1,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() {
-}
-
-// ValidateCreate implements webhook.Validator so a webhook will be registered for the type.
-func (r *OpenStackClusterTemplate) ValidateCreate() (admission.Warnings, error) {
- var allErrs field.ErrorList
-
- 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/v1beta1/openstackmachinelist_webhook.go b/api/v1beta1/openstackmachinelist_webhook.go
deleted file mode 100644
index 9e6a551f2d..0000000000
--- a/api/v1beta1/openstackmachinelist_webhook.go
+++ /dev/null
@@ -1,32 +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 v1beta1
-
-import (
- "sigs.k8s.io/controller-runtime/pkg/builder"
- logf "sigs.k8s.io/controller-runtime/pkg/log"
- "sigs.k8s.io/controller-runtime/pkg/manager"
-)
-
-// log is for logging in this package.
-var _ = logf.Log.WithName("openstackmachinelist-resource")
-
-func (r *OpenStackMachineList) SetupWebhookWithManager(mgr manager.Manager) error {
- return builder.WebhookManagedBy(mgr).
- For(r).
- Complete()
-}
diff --git a/api/v1beta1/openstackmachinetemplatelist_webhook.go b/api/v1beta1/openstackmachinetemplatelist_webhook.go
deleted file mode 100644
index 03d438e925..0000000000
--- a/api/v1beta1/openstackmachinetemplatelist_webhook.go
+++ /dev/null
@@ -1,32 +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 v1beta1
-
-import (
- "sigs.k8s.io/controller-runtime/pkg/builder"
- logf "sigs.k8s.io/controller-runtime/pkg/log"
- "sigs.k8s.io/controller-runtime/pkg/manager"
-)
-
-// log is for logging in this package.
-var _ = logf.Log.WithName("openstackmachinetemplatelist-resource")
-
-func (r *OpenStackMachineTemplateList) SetupWebhookWithManager(mgr manager.Manager) error {
- return builder.WebhookManagedBy(mgr).
- For(r).
- Complete()
-}
diff --git a/config/webhook/manifests.yaml b/config/webhook/manifests.yaml
index 260778c5cf..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-v1beta1-openstackcluster
- failurePolicy: Fail
- matchPolicy: Equivalent
- name: default.openstackcluster.infrastructure.cluster.x-k8s.io
- rules:
- - apiGroups:
- - infrastructure.cluster.x-k8s.io
- apiVersions:
- - v1beta1
- operations:
- - CREATE
- - UPDATE
- resources:
- - openstackclusters
- sideEffects: None
-- admissionReviewVersions:
- - v1beta1
- clientConfig:
- service:
- name: webhook-service
- namespace: system
- path: /mutate-infrastructure-cluster-x-k8s-io-v1beta1-openstackclustertemplate
- failurePolicy: Fail
- matchPolicy: Equivalent
- name: default.openstackclustertemplate.infrastructure.cluster.x-k8s.io
- rules:
- - apiGroups:
- - infrastructure.cluster.x-k8s.io
- apiVersions:
- - v1beta1
- operations:
- - CREATE
- - UPDATE
- resources:
- - openstackclustertemplates
- sideEffects: None
-- admissionReviewVersions:
- - v1beta1
- clientConfig:
- service:
- name: webhook-service
- namespace: system
- path: /mutate-infrastructure-cluster-x-k8s-io-v1beta1-openstackmachine
- failurePolicy: Fail
- matchPolicy: Equivalent
- name: default.openstackmachine.infrastructure.cluster.x-k8s.io
- rules:
- - apiGroups:
- - infrastructure.cluster.x-k8s.io
- apiVersions:
- - v1beta1
- operations:
- - CREATE
- - UPDATE
- resources:
- - openstackmachines
- sideEffects: None
----
-apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: validating-webhook-configuration
diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md
index 9dc7667830..a0f4caf74b 100644
--- a/docs/book/src/api/v1beta1/api.md
+++ b/docs/book/src/api/v1beta1/api.md
@@ -3477,10 +3477,6 @@ OpenStackMachineTemplateResource
-OpenStackMachineTemplateWebhook
-
-
-
PortOpts
diff --git a/main.go b/main.go
index 9fa9fc5eb0..c170553eeb 100644
--- a/main.go
+++ b/main.go
@@ -54,6 +54,7 @@ import (
"sigs.k8s.io/cluster-api-provider-openstack/pkg/metrics"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/record"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
+ "sigs.k8s.io/cluster-api-provider-openstack/pkg/webhooks"
"sigs.k8s.io/cluster-api-provider-openstack/version"
)
@@ -353,32 +354,11 @@ func setupReconcilers(ctx context.Context, mgr ctrl.Manager, caCerts []byte, sco
}
func setupWebhooks(mgr ctrl.Manager) {
- if err := (&infrav1.OpenStackMachineTemplateWebhook{}).SetupWebhookWithManager(mgr); err != nil {
- setupLog.Error(err, "unable to create webhook", "webhook", "OpenStackMachineTemplate")
- os.Exit(1)
- }
- if err := (&infrav1.OpenStackMachineTemplateList{}).SetupWebhookWithManager(mgr); err != nil {
- setupLog.Error(err, "unable to create webhook", "webhook", "OpenStackMachineTemplateList")
- os.Exit(1)
- }
- if err := (&infrav1.OpenStackCluster{}).SetupWebhookWithManager(mgr); err != nil {
- setupLog.Error(err, "unable to create webhook", "webhook", "OpenStackCluster")
- os.Exit(1)
- }
- if err := (&infrav1.OpenStackClusterTemplate{}).SetupWebhookWithManager(mgr); err != nil {
- setupLog.Error(err, "unable to create webhook", "webhook", "OpenStackClusterTemplate")
- os.Exit(1)
- }
- if err := (&infrav1.OpenStackMachine{}).SetupWebhookWithManager(mgr); err != nil {
- setupLog.Error(err, "unable to create webhook", "webhook", "OpenStackMachine")
- os.Exit(1)
- }
- if err := (&infrav1.OpenStackMachineList{}).SetupWebhookWithManager(mgr); err != nil {
- setupLog.Error(err, "unable to create webhook", "webhook", "OpenStackMachineList")
- os.Exit(1)
- }
- if err := (&infrav1.OpenStackClusterList{}).SetupWebhookWithManager(mgr); err != nil {
- setupLog.Error(err, "unable to create webhook", "webhook", "OpenStackClusterList")
+ errs := webhooks.RegisterAllWithManager(mgr)
+ if len(errs) > 0 {
+ for i := range errs {
+ setupLog.Error(errs[i], "unable to register webhook")
+ }
os.Exit(1)
}
}
diff --git a/api/v1beta1/webhooks.go b/pkg/webhooks/errors.go
similarity index 98%
rename from api/v1beta1/webhooks.go
rename to pkg/webhooks/errors.go
index 3df43589ba..ad2c53aae4 100644
--- a/api/v1beta1/webhooks.go
+++ b/pkg/webhooks/errors.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package v1beta1
+package webhooks
import (
apierrors "k8s.io/apimachinery/pkg/api/errors"
diff --git a/pkg/webhooks/openstackcluster_webhook.go b/pkg/webhooks/openstackcluster_webhook.go
new file mode 100644
index 0000000000..6541e93681
--- /dev/null
+++ b/pkg/webhooks/openstackcluster_webhook.go
@@ -0,0 +1,167 @@
+/*
+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 webhooks
+
+import (
+ "context"
+ "fmt"
+ "reflect"
+
+ "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"
+ "sigs.k8s.io/controller-runtime/pkg/manager"
+ "sigs.k8s.io/controller-runtime/pkg/webhook"
+ "sigs.k8s.io/controller-runtime/pkg/webhook/admission"
+
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
+)
+
+// +kubebuilder:webhook:verbs=create;update,path=/validate-infrastructure-cluster-x-k8s-io-v1beta1-openstackcluster,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=openstackclusters,versions=v1beta1,name=validation.openstackcluster.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1
+
+func SetupOpenStackClusterWebhook(mgr manager.Manager) error {
+ return builder.WebhookManagedBy(mgr).
+ For(&infrav1.OpenStackCluster{}).
+ WithValidator(&openStackClusterWebhook{}).
+ Complete()
+}
+
+type openStackClusterWebhook struct{}
+
+// Compile-time assertion that openStackClusterWebhook implements webhook.CustomValidator.
+var _ webhook.CustomValidator = &openStackClusterWebhook{}
+
+// ValidateCreate implements webhook.CustomValidator so a webhook will be registered for the type.
+func (*openStackClusterWebhook) ValidateCreate(_ context.Context, objRaw runtime.Object) (admission.Warnings, error) {
+ var allErrs field.ErrorList
+
+ newObj, err := castToOpenStackCluster(objRaw)
+ if err != nil {
+ return nil, err
+ }
+
+ if newObj.Spec.ManagedSecurityGroups != nil {
+ for _, rule := range newObj.Spec.ManagedSecurityGroups.AllNodesSecurityGroupRules {
+ if rule.RemoteManagedGroups != nil && (rule.RemoteGroupID != nil || rule.RemoteIPPrefix != nil) {
+ allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "managedSecurityGroups", "allNodesSecurityGroupRules"), "remoteManagedGroups cannot be used with remoteGroupID or remoteIPPrefix"))
+ }
+ if rule.RemoteGroupID != nil && (rule.RemoteManagedGroups != nil || rule.RemoteIPPrefix != nil) {
+ allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "managedSecurityGroups", "allNodesSecurityGroupRules"), "remoteGroupID cannot be used with remoteManagedGroups or remoteIPPrefix"))
+ }
+ if rule.RemoteIPPrefix != nil && (rule.RemoteManagedGroups != nil || rule.RemoteGroupID != nil) {
+ allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "managedSecurityGroups", "allNodesSecurityGroupRules"), "remoteIPPrefix cannot be used with remoteManagedGroups or remoteGroupID"))
+ }
+ }
+ }
+
+ return aggregateObjErrors(newObj.GroupVersionKind().GroupKind(), newObj.Name, allErrs)
+}
+
+// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type.
+func (*openStackClusterWebhook) ValidateUpdate(_ context.Context, oldObjRaw, newObjRaw runtime.Object) (admission.Warnings, error) {
+ var allErrs field.ErrorList
+ oldObj, err := castToOpenStackCluster(oldObjRaw)
+ if err != nil {
+ return nil, err
+ }
+ newObj, err := castToOpenStackCluster(newObjRaw)
+ if err != nil {
+ return nil, err
+ }
+
+ // Allow changes to Spec.IdentityRef
+ oldObj.Spec.IdentityRef = infrav1.OpenStackIdentityReference{}
+ newObj.Spec.IdentityRef = infrav1.OpenStackIdentityReference{}
+
+ // Allow change only for the first time.
+ if oldObj.Spec.ControlPlaneEndpoint.Host == "" {
+ oldObj.Spec.ControlPlaneEndpoint = clusterv1.APIEndpoint{}
+ newObj.Spec.ControlPlaneEndpoint = clusterv1.APIEndpoint{}
+ }
+
+ // Allow change only for the first time.
+ if oldObj.Spec.DisableAPIServerFloatingIP && oldObj.Spec.APIServerFixedIP == "" {
+ newObj.Spec.APIServerFixedIP = ""
+ }
+
+ // If API Server floating IP is disabled, allow the change of the API Server port only for the first time.
+ if oldObj.Spec.DisableAPIServerFloatingIP && oldObj.Spec.APIServerPort == 0 && newObj.Spec.APIServerPort > 0 {
+ newObj.Spec.APIServerPort = 0
+ }
+
+ // Allow to remove the bastion spec only if it was disabled before.
+ if newObj.Spec.Bastion == nil {
+ if oldObj.Spec.Bastion != nil && oldObj.Spec.Bastion.Enabled {
+ allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "bastion"), "cannot be removed before disabling it"))
+ }
+ }
+
+ // Allow changes to the bastion spec.
+ oldObj.Spec.Bastion = &infrav1.Bastion{}
+ newObj.Spec.Bastion = &infrav1.Bastion{}
+
+ // Allow changes to the managed allNodesSecurityGroupRules.
+ if newObj.Spec.ManagedSecurityGroups != nil {
+ oldObj.Spec.ManagedSecurityGroups.AllNodesSecurityGroupRules = []infrav1.SecurityGroupRuleSpec{}
+ newObj.Spec.ManagedSecurityGroups.AllNodesSecurityGroupRules = []infrav1.SecurityGroupRuleSpec{}
+
+ // Allow change to the allowAllInClusterTraffic.
+ oldObj.Spec.ManagedSecurityGroups.AllowAllInClusterTraffic = false
+ newObj.Spec.ManagedSecurityGroups.AllowAllInClusterTraffic = false
+ }
+
+ // Allow changes on AllowedCIDRs
+ if newObj.Spec.APIServerLoadBalancer.Enabled {
+ oldObj.Spec.APIServerLoadBalancer.AllowedCIDRs = []string{}
+ newObj.Spec.APIServerLoadBalancer.AllowedCIDRs = []string{}
+ }
+
+ // Allow changes to the availability zones.
+ oldObj.Spec.ControlPlaneAvailabilityZones = []string{}
+ newObj.Spec.ControlPlaneAvailabilityZones = []string{}
+
+ // Allow the scheduling to be changed from CAPI managed to Nova and
+ // vice versa.
+ oldObj.Spec.ControlPlaneOmitAvailabilityZone = false
+ newObj.Spec.ControlPlaneOmitAvailabilityZone = false
+
+ // Allow change on the spec.APIServerFloatingIP only if it matches the current api server loadbalancer IP.
+ if oldObj.Status.APIServerLoadBalancer != nil && newObj.Spec.APIServerFloatingIP == oldObj.Status.APIServerLoadBalancer.IP {
+ newObj.Spec.APIServerFloatingIP = ""
+ oldObj.Spec.APIServerFloatingIP = ""
+ }
+
+ if !reflect.DeepEqual(oldObj.Spec, newObj.Spec) {
+ allErrs = append(allErrs, field.Forbidden(field.NewPath("spec"), "cannot be modified"))
+ }
+
+ return aggregateObjErrors(newObj.GroupVersionKind().GroupKind(), newObj.Name, allErrs)
+}
+
+// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type.
+func (*openStackClusterWebhook) ValidateDelete(_ context.Context, _ runtime.Object) (admission.Warnings, error) {
+ return nil, nil
+}
+
+func castToOpenStackCluster(obj runtime.Object) (*infrav1.OpenStackCluster, error) {
+ cast, ok := obj.(*infrav1.OpenStackCluster)
+ if !ok {
+ return nil, fmt.Errorf("expected an OpenStackCluster but got a %T", obj)
+ }
+ return cast, nil
+}
diff --git a/api/v1beta1/openstackcluster_webhook_test.go b/pkg/webhooks/openstackcluster_webhook_test.go
similarity index 56%
rename from api/v1beta1/openstackcluster_webhook_test.go
rename to pkg/webhooks/openstackcluster_webhook_test.go
index 4a0213dd90..5a4c44269c 100644
--- a/api/v1beta1/openstackcluster_webhook_test.go
+++ b/pkg/webhooks/openstackcluster_webhook_test.go
@@ -14,13 +14,16 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package v1beta1
+package webhooks
import (
+ "context"
"testing"
. "github.com/onsi/gomega"
"k8s.io/utils/pointer"
+
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
)
func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
@@ -28,23 +31,23 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
tests := []struct {
name string
- oldTemplate *OpenStackCluster
- newTemplate *OpenStackCluster
+ oldTemplate *infrav1.OpenStackCluster
+ newTemplate *infrav1.OpenStackCluster
wantErr bool
}{
{
name: "Changing OpenStackCluster.Spec.IdentityRef.Name is allowed",
- oldTemplate: &OpenStackCluster{
- Spec: OpenStackClusterSpec{
- IdentityRef: OpenStackIdentityReference{
+ oldTemplate: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ IdentityRef: infrav1.OpenStackIdentityReference{
Name: "foobar",
CloudName: "foobar",
},
},
},
- newTemplate: &OpenStackCluster{
- Spec: OpenStackClusterSpec{
- IdentityRef: OpenStackIdentityReference{
+ newTemplate: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ IdentityRef: infrav1.OpenStackIdentityReference{
Name: "foobarbaz",
CloudName: "foobar",
},
@@ -54,17 +57,17 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
{
name: "Changing OpenStackCluster.Spec.IdentityRef.CloudName is allowed",
- oldTemplate: &OpenStackCluster{
- Spec: OpenStackClusterSpec{
- IdentityRef: OpenStackIdentityReference{
+ oldTemplate: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ IdentityRef: infrav1.OpenStackIdentityReference{
Name: "foobar",
CloudName: "foobar",
},
},
},
- newTemplate: &OpenStackCluster{
- Spec: OpenStackClusterSpec{
- IdentityRef: OpenStackIdentityReference{
+ newTemplate: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ IdentityRef: infrav1.OpenStackIdentityReference{
Name: "foobar",
CloudName: "foobarbaz",
},
@@ -74,35 +77,35 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
{
name: "Changing OpenStackCluster.Spec.Bastion is allowed",
- oldTemplate: &OpenStackCluster{
- Spec: OpenStackClusterSpec{
- IdentityRef: OpenStackIdentityReference{
+ oldTemplate: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ IdentityRef: infrav1.OpenStackIdentityReference{
Name: "foobar",
CloudName: "foobar",
},
- Bastion: &Bastion{
- Instance: OpenStackMachineSpec{
- Image: ImageFilter{Name: "foobar"},
+ Bastion: &infrav1.Bastion{
+ Instance: infrav1.OpenStackMachineSpec{
+ Image: infrav1.ImageFilter{Name: "foobar"},
Flavor: "minimal",
},
Enabled: true,
},
},
- Status: OpenStackClusterStatus{
- Bastion: &BastionStatus{
+ Status: infrav1.OpenStackClusterStatus{
+ Bastion: &infrav1.BastionStatus{
Name: "foobar",
},
},
},
- newTemplate: &OpenStackCluster{
- Spec: OpenStackClusterSpec{
- IdentityRef: OpenStackIdentityReference{
+ newTemplate: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ IdentityRef: infrav1.OpenStackIdentityReference{
Name: "foobar",
CloudName: "foobar",
},
- Bastion: &Bastion{
- Instance: OpenStackMachineSpec{
- Image: ImageFilter{Name: "foobarbaz"},
+ Bastion: &infrav1.Bastion{
+ Instance: infrav1.OpenStackMachineSpec{
+ Image: infrav1.ImageFilter{Name: "foobarbaz"},
Flavor: "medium",
},
Enabled: true,
@@ -113,41 +116,41 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
{
name: "Changing security group rules on the OpenStackCluster.Spec.ManagedSecurityGroups.AllNodesSecurityGroupRules is allowed",
- oldTemplate: &OpenStackCluster{
- Spec: OpenStackClusterSpec{
- IdentityRef: OpenStackIdentityReference{
+ oldTemplate: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ IdentityRef: infrav1.OpenStackIdentityReference{
Name: "foobar",
CloudName: "foobar",
},
- ManagedSecurityGroups: &ManagedSecurityGroups{
- AllNodesSecurityGroupRules: []SecurityGroupRuleSpec{
+ ManagedSecurityGroups: &infrav1.ManagedSecurityGroups{
+ AllNodesSecurityGroupRules: []infrav1.SecurityGroupRuleSpec{
{
Name: "foobar",
Description: pointer.String("foobar"),
PortRangeMin: pointer.Int(80),
PortRangeMax: pointer.Int(80),
Protocol: pointer.String("tcp"),
- RemoteManagedGroups: []ManagedSecurityGroupName{"controlplane"},
+ RemoteManagedGroups: []infrav1.ManagedSecurityGroupName{"controlplane"},
},
},
},
},
},
- newTemplate: &OpenStackCluster{
- Spec: OpenStackClusterSpec{
- IdentityRef: OpenStackIdentityReference{
+ newTemplate: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ IdentityRef: infrav1.OpenStackIdentityReference{
Name: "foobar",
CloudName: "foobar",
},
- ManagedSecurityGroups: &ManagedSecurityGroups{
- AllNodesSecurityGroupRules: []SecurityGroupRuleSpec{
+ ManagedSecurityGroups: &infrav1.ManagedSecurityGroups{
+ AllNodesSecurityGroupRules: []infrav1.SecurityGroupRuleSpec{
{
Name: "foobar",
Description: pointer.String("foobar"),
PortRangeMin: pointer.Int(80),
PortRangeMax: pointer.Int(80),
Protocol: pointer.String("tcp"),
- RemoteManagedGroups: []ManagedSecurityGroupName{"controlplane", "worker"},
+ RemoteManagedGroups: []infrav1.ManagedSecurityGroupName{"controlplane", "worker"},
},
},
},
@@ -157,13 +160,13 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
{
name: "Changing CIDRs on the OpenStackCluster.Spec.APIServerLoadBalancer.AllowedCIDRs is allowed",
- oldTemplate: &OpenStackCluster{
- Spec: OpenStackClusterSpec{
- IdentityRef: OpenStackIdentityReference{
+ oldTemplate: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ IdentityRef: infrav1.OpenStackIdentityReference{
Name: "foobar",
CloudName: "foobar",
},
- APIServerLoadBalancer: APIServerLoadBalancer{
+ APIServerLoadBalancer: infrav1.APIServerLoadBalancer{
Enabled: true,
AllowedCIDRs: []string{
"0.0.0.0/0",
@@ -172,13 +175,13 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
},
},
- newTemplate: &OpenStackCluster{
- Spec: OpenStackClusterSpec{
- IdentityRef: OpenStackIdentityReference{
+ newTemplate: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ IdentityRef: infrav1.OpenStackIdentityReference{
Name: "foobar",
CloudName: "foobar",
},
- APIServerLoadBalancer: APIServerLoadBalancer{
+ APIServerLoadBalancer: infrav1.APIServerLoadBalancer{
Enabled: true,
AllowedCIDRs: []string{
"0.0.0.0/0",
@@ -192,17 +195,17 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
{
name: "Adding OpenStackCluster.Spec.ControlPlaneAvailabilityZones is allowed",
- oldTemplate: &OpenStackCluster{
- Spec: OpenStackClusterSpec{
- IdentityRef: OpenStackIdentityReference{
+ oldTemplate: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ IdentityRef: infrav1.OpenStackIdentityReference{
Name: "foobar",
CloudName: "foobar",
},
},
},
- newTemplate: &OpenStackCluster{
- Spec: OpenStackClusterSpec{
- IdentityRef: OpenStackIdentityReference{
+ newTemplate: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ IdentityRef: infrav1.OpenStackIdentityReference{
Name: "foobar",
CloudName: "foobar",
},
@@ -216,9 +219,9 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
{
name: "Modifying OpenStackCluster.Spec.ControlPlaneAvailabilityZones is allowed",
- oldTemplate: &OpenStackCluster{
- Spec: OpenStackClusterSpec{
- IdentityRef: OpenStackIdentityReference{
+ oldTemplate: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ IdentityRef: infrav1.OpenStackIdentityReference{
Name: "foobar",
CloudName: "foobar",
},
@@ -228,9 +231,9 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
},
},
- newTemplate: &OpenStackCluster{
- Spec: OpenStackClusterSpec{
- IdentityRef: OpenStackIdentityReference{
+ newTemplate: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ IdentityRef: infrav1.OpenStackIdentityReference{
Name: "foobar",
CloudName: "foobar",
},
@@ -245,9 +248,9 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
{
name: "Removing OpenStackCluster.Spec.ControlPlaneAvailabilityZones is allowed",
- oldTemplate: &OpenStackCluster{
- Spec: OpenStackClusterSpec{
- IdentityRef: OpenStackIdentityReference{
+ oldTemplate: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ IdentityRef: infrav1.OpenStackIdentityReference{
Name: "foobar",
CloudName: "foobar",
},
@@ -257,9 +260,9 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
},
},
- newTemplate: &OpenStackCluster{
- Spec: OpenStackClusterSpec{
- IdentityRef: OpenStackIdentityReference{
+ newTemplate: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ IdentityRef: infrav1.OpenStackIdentityReference{
Name: "foobar",
CloudName: "foobar",
},
@@ -269,17 +272,17 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
{
name: "Modifying OpenstackCluster.Spec.ControlPlaneOmitAvailabilityZone is allowed",
- oldTemplate: &OpenStackCluster{
- Spec: OpenStackClusterSpec{
- IdentityRef: OpenStackIdentityReference{
+ oldTemplate: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ IdentityRef: infrav1.OpenStackIdentityReference{
Name: "foobar",
CloudName: "foobar",
},
},
},
- newTemplate: &OpenStackCluster{
- Spec: OpenStackClusterSpec{
- IdentityRef: OpenStackIdentityReference{
+ newTemplate: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ IdentityRef: infrav1.OpenStackIdentityReference{
Name: "foobar",
CloudName: "foobar",
},
@@ -290,18 +293,18 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
{
name: "Changing OpenStackCluster.Spec.APIServerFixedIP is allowed when API Server Floating IP is disabled",
- oldTemplate: &OpenStackCluster{
- Spec: OpenStackClusterSpec{
- IdentityRef: OpenStackIdentityReference{
+ oldTemplate: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ IdentityRef: infrav1.OpenStackIdentityReference{
Name: "foobar",
CloudName: "foobar",
},
DisableAPIServerFloatingIP: true,
},
},
- newTemplate: &OpenStackCluster{
- Spec: OpenStackClusterSpec{
- IdentityRef: OpenStackIdentityReference{
+ newTemplate: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ IdentityRef: infrav1.OpenStackIdentityReference{
Name: "foobar",
CloudName: "foobar",
},
@@ -313,18 +316,18 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
{
name: "Changing OpenStackCluster.Spec.APIServerFixedIP is not allowed",
- oldTemplate: &OpenStackCluster{
- Spec: OpenStackClusterSpec{
- IdentityRef: OpenStackIdentityReference{
+ oldTemplate: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ IdentityRef: infrav1.OpenStackIdentityReference{
Name: "foobar",
CloudName: "foobar",
},
DisableAPIServerFloatingIP: false,
},
},
- newTemplate: &OpenStackCluster{
- Spec: OpenStackClusterSpec{
- IdentityRef: OpenStackIdentityReference{
+ newTemplate: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ IdentityRef: infrav1.OpenStackIdentityReference{
Name: "foobar",
CloudName: "foobar",
},
@@ -337,17 +340,17 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
{
name: "Changing OpenStackCluster.Spec.APIServerPort is allowed when API Server Floating IP is disabled",
- oldTemplate: &OpenStackCluster{
- Spec: OpenStackClusterSpec{
- IdentityRef: OpenStackIdentityReference{
+ oldTemplate: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ IdentityRef: infrav1.OpenStackIdentityReference{
Name: "foobar",
CloudName: "foobar",
},
DisableAPIServerFloatingIP: true,
},
},
- newTemplate: &OpenStackCluster{
- Spec: OpenStackClusterSpec{
+ newTemplate: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
DisableAPIServerFloatingIP: true,
APIServerPort: 8443,
},
@@ -356,18 +359,18 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
{
name: "Changing OpenStackCluster.Spec.APIServerPort is not allowed",
- oldTemplate: &OpenStackCluster{
- Spec: OpenStackClusterSpec{
- IdentityRef: OpenStackIdentityReference{
+ oldTemplate: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ IdentityRef: infrav1.OpenStackIdentityReference{
Name: "foobar",
CloudName: "foobar",
},
DisableAPIServerFloatingIP: false,
},
},
- newTemplate: &OpenStackCluster{
- Spec: OpenStackClusterSpec{
- IdentityRef: OpenStackIdentityReference{
+ newTemplate: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ IdentityRef: infrav1.OpenStackIdentityReference{
Name: "foobar",
CloudName: "foobar",
},
@@ -379,30 +382,30 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
{
name: "Changing OpenStackCluster.Spec.APIServerFloatingIP is allowed when it matches the current api server loadbalancer IP",
- oldTemplate: &OpenStackCluster{
- Spec: OpenStackClusterSpec{
- IdentityRef: OpenStackIdentityReference{
+ oldTemplate: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ IdentityRef: infrav1.OpenStackIdentityReference{
Name: "foobar",
CloudName: "foobar",
},
APIServerFloatingIP: "",
},
- Status: OpenStackClusterStatus{
- APIServerLoadBalancer: &LoadBalancer{
+ Status: infrav1.OpenStackClusterStatus{
+ APIServerLoadBalancer: &infrav1.LoadBalancer{
IP: "1.2.3.4",
},
},
},
- newTemplate: &OpenStackCluster{
- Spec: OpenStackClusterSpec{
- IdentityRef: OpenStackIdentityReference{
+ newTemplate: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ IdentityRef: infrav1.OpenStackIdentityReference{
Name: "foobar",
CloudName: "foobar",
},
APIServerFloatingIP: "1.2.3.4",
},
- Status: OpenStackClusterStatus{
- APIServerLoadBalancer: &LoadBalancer{
+ Status: infrav1.OpenStackClusterStatus{
+ APIServerLoadBalancer: &infrav1.LoadBalancer{
IP: "1.2.3.4",
},
},
@@ -411,30 +414,30 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
{
name: "Changing OpenStackCluster.Spec.APIServerFloatingIP is not allowed when it doesn't matches the current api server loadbalancer IP",
- oldTemplate: &OpenStackCluster{
- Spec: OpenStackClusterSpec{
- IdentityRef: OpenStackIdentityReference{
+ oldTemplate: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ IdentityRef: infrav1.OpenStackIdentityReference{
Name: "foobar",
CloudName: "foobar",
},
APIServerFloatingIP: "",
},
- Status: OpenStackClusterStatus{
- APIServerLoadBalancer: &LoadBalancer{
+ Status: infrav1.OpenStackClusterStatus{
+ APIServerLoadBalancer: &infrav1.LoadBalancer{
IP: "1.2.3.4",
},
},
},
- newTemplate: &OpenStackCluster{
- Spec: OpenStackClusterSpec{
- IdentityRef: OpenStackIdentityReference{
+ newTemplate: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ IdentityRef: infrav1.OpenStackIdentityReference{
Name: "foobar",
CloudName: "foobar",
},
APIServerFloatingIP: "5.6.7.8",
},
- Status: OpenStackClusterStatus{
- APIServerLoadBalancer: &LoadBalancer{
+ Status: infrav1.OpenStackClusterStatus{
+ APIServerLoadBalancer: &infrav1.LoadBalancer{
IP: "1.2.3.4",
},
},
@@ -443,24 +446,24 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
{
name: "Removing OpenStackCluster.Spec.Bastion when it is enabled is not allowed",
- oldTemplate: &OpenStackCluster{
- Spec: OpenStackClusterSpec{
- IdentityRef: OpenStackIdentityReference{
+ oldTemplate: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ IdentityRef: infrav1.OpenStackIdentityReference{
Name: "foobar",
CloudName: "foobar",
},
- Bastion: &Bastion{
+ Bastion: &infrav1.Bastion{
Enabled: true,
- Instance: OpenStackMachineSpec{
+ Instance: infrav1.OpenStackMachineSpec{
Flavor: "m1.small",
- Image: ImageFilter{Name: "ubuntu"},
+ Image: infrav1.ImageFilter{Name: "ubuntu"},
},
},
},
},
- newTemplate: &OpenStackCluster{
- Spec: OpenStackClusterSpec{
- IdentityRef: OpenStackIdentityReference{
+ newTemplate: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ IdentityRef: infrav1.OpenStackIdentityReference{
Name: "foobar",
CloudName: "foobar",
},
@@ -470,24 +473,24 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
{
name: "Removing OpenStackCluster.Spec.Bastion when it is disabled is allowed",
- oldTemplate: &OpenStackCluster{
- Spec: OpenStackClusterSpec{
- IdentityRef: OpenStackIdentityReference{
+ oldTemplate: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ IdentityRef: infrav1.OpenStackIdentityReference{
Name: "foobar",
CloudName: "foobar",
},
- Bastion: &Bastion{
+ Bastion: &infrav1.Bastion{
Enabled: false,
- Instance: OpenStackMachineSpec{
+ Instance: infrav1.OpenStackMachineSpec{
Flavor: "m1.small",
- Image: ImageFilter{Name: "ubuntu"},
+ Image: infrav1.ImageFilter{Name: "ubuntu"},
},
},
},
},
- newTemplate: &OpenStackCluster{
- Spec: OpenStackClusterSpec{
- IdentityRef: OpenStackIdentityReference{
+ newTemplate: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ IdentityRef: infrav1.OpenStackIdentityReference{
Name: "foobar",
CloudName: "foobar",
},
@@ -498,7 +501,9 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- warn, err := tt.newTemplate.ValidateUpdate(tt.oldTemplate)
+ ctx := context.TODO()
+ webhook := &openStackClusterWebhook{}
+ warn, err := webhook.ValidateUpdate(ctx, tt.oldTemplate, tt.newTemplate)
if tt.wantErr {
g.Expect(err).To(HaveOccurred())
} else {
@@ -515,14 +520,14 @@ func TestOpenStackCluster_ValidateCreate(t *testing.T) {
tests := []struct {
name string
- template *OpenStackCluster
+ template *infrav1.OpenStackCluster
wantErr bool
}{
{
name: "OpenStackCluster.Spec.IdentityRef with correct spec on create",
- template: &OpenStackCluster{
- Spec: OpenStackClusterSpec{
- IdentityRef: OpenStackIdentityReference{
+ template: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ IdentityRef: infrav1.OpenStackIdentityReference{
Name: "foobar",
CloudName: "foobar",
},
@@ -532,14 +537,14 @@ func TestOpenStackCluster_ValidateCreate(t *testing.T) {
},
{
name: "OpenStackCluster.Spec.ManagedSecurityGroups.AllNodesSecurityGroupRules with correct spec on create",
- template: &OpenStackCluster{
- Spec: OpenStackClusterSpec{
- IdentityRef: OpenStackIdentityReference{
+ template: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ IdentityRef: infrav1.OpenStackIdentityReference{
Name: "foobar",
CloudName: "foobar",
},
- ManagedSecurityGroups: &ManagedSecurityGroups{
- AllNodesSecurityGroupRules: []SecurityGroupRuleSpec{
+ ManagedSecurityGroups: &infrav1.ManagedSecurityGroups{
+ AllNodesSecurityGroupRules: []infrav1.SecurityGroupRuleSpec{
{
Name: "foobar",
Description: pointer.String("foobar"),
@@ -555,21 +560,21 @@ func TestOpenStackCluster_ValidateCreate(t *testing.T) {
},
{
name: "OpenStackCluster.Spec.ManagedSecurityGroups.AllNodesSecurityGroupRules with mutually exclusive fields on create",
- template: &OpenStackCluster{
- Spec: OpenStackClusterSpec{
- IdentityRef: OpenStackIdentityReference{
+ template: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ IdentityRef: infrav1.OpenStackIdentityReference{
Name: "foobar",
CloudName: "foobar",
},
- ManagedSecurityGroups: &ManagedSecurityGroups{
- AllNodesSecurityGroupRules: []SecurityGroupRuleSpec{
+ ManagedSecurityGroups: &infrav1.ManagedSecurityGroups{
+ AllNodesSecurityGroupRules: []infrav1.SecurityGroupRuleSpec{
{
Name: "foobar",
Description: pointer.String("foobar"),
PortRangeMin: pointer.Int(80),
PortRangeMax: pointer.Int(80),
Protocol: pointer.String("tcp"),
- RemoteManagedGroups: []ManagedSecurityGroupName{"controlplane"},
+ RemoteManagedGroups: []infrav1.ManagedSecurityGroupName{"controlplane"},
RemoteGroupID: pointer.String("foobar"),
},
},
@@ -581,7 +586,9 @@ func TestOpenStackCluster_ValidateCreate(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- warn, err := tt.template.ValidateCreate()
+ ctx := context.TODO()
+ webhook := &openStackClusterWebhook{}
+ warn, err := webhook.ValidateCreate(ctx, tt.template)
if tt.wantErr {
g.Expect(err).To(HaveOccurred())
} else {
diff --git a/pkg/webhooks/openstackclustertemplate_webhook.go b/pkg/webhooks/openstackclustertemplate_webhook.go
new file mode 100644
index 0000000000..b82f510ca8
--- /dev/null
+++ b/pkg/webhooks/openstackclustertemplate_webhook.go
@@ -0,0 +1,90 @@
+/*
+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 webhooks
+
+import (
+ "context"
+ "fmt"
+ "reflect"
+
+ "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"
+
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
+)
+
+// +kubebuilder:webhook:verbs=create;update,path=/validate-infrastructure-cluster-x-k8s-io-v1beta1-openstackclustertemplate,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=openstackclustertemplates,versions=v1beta1,name=validation.openstackclustertemplate.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1
+
+func SetupOpenStackClusterTemplateWebhook(mgr ctrl.Manager) error {
+ return ctrl.NewWebhookManagedBy(mgr).
+ For(&infrav1.OpenStackClusterTemplate{}).
+ WithValidator(&openStackClusterTemplateWebhook{}).
+ Complete()
+}
+
+type openStackClusterTemplateWebhook struct{}
+
+// Compile-time assertion that openStackClusterTemplateWebhook implements webhook.CustomValidator.
+var _ webhook.CustomValidator = &openStackClusterTemplateWebhook{}
+
+// ValidateCreate implements webhook.CustomValidator so a webhook will be registered for the type.
+func (*openStackClusterTemplateWebhook) ValidateCreate(_ context.Context, objRaw runtime.Object) (admission.Warnings, error) {
+ var allErrs field.ErrorList
+ newObj, err := castToOpenStackClusterTemplate(objRaw)
+ if err != nil {
+ return nil, err
+ }
+
+ return aggregateObjErrors(newObj.GroupVersionKind().GroupKind(), newObj.Name, allErrs)
+}
+
+// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type.
+func (*openStackClusterTemplateWebhook) ValidateUpdate(_ context.Context, oldObjRaw, newObjRaw runtime.Object) (admission.Warnings, error) {
+ var allErrs field.ErrorList
+ oldObj, err := castToOpenStackClusterTemplate(oldObjRaw)
+ if err != nil {
+ return nil, err
+ }
+ newObj, err := castToOpenStackClusterTemplate(newObjRaw)
+ if err != nil {
+ return nil, err
+ }
+
+ if !reflect.DeepEqual(newObj.Spec.Template.Spec, oldObj.Spec.Template.Spec) {
+ allErrs = append(allErrs,
+ field.Invalid(field.NewPath("OpenStackClusterTemplate", "spec", "template", "spec"), newObj, "OpenStackClusterTemplate spec.template.spec field is immutable. Please create new resource instead."),
+ )
+ }
+
+ return aggregateObjErrors(newObj.GroupVersionKind().GroupKind(), newObj.Name, allErrs)
+}
+
+// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type.
+func (*openStackClusterTemplateWebhook) ValidateDelete(_ context.Context, _ runtime.Object) (admission.Warnings, error) {
+ return nil, nil
+}
+
+func castToOpenStackClusterTemplate(obj runtime.Object) (*infrav1.OpenStackClusterTemplate, error) {
+ cast, ok := obj.(*infrav1.OpenStackClusterTemplate)
+ if !ok {
+ return nil, fmt.Errorf("expected an OpenStackClusterTemplate but got a %T", obj)
+ }
+ return cast, nil
+}
diff --git a/api/v1beta1/openstackmachine_webhook.go b/pkg/webhooks/openstackmachine_webhook.go
similarity index 57%
rename from api/v1beta1/openstackmachine_webhook.go
rename to pkg/webhooks/openstackmachine_webhook.go
index 93c91c5ffa..cfee9e5c74 100644
--- a/api/v1beta1/openstackmachine_webhook.go
+++ b/pkg/webhooks/openstackmachine_webhook.go
@@ -14,9 +14,10 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package v1beta1
+package webhooks
import (
+ "context"
"fmt"
"reflect"
@@ -24,59 +25,62 @@ import (
"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"
+
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
)
-// log is for logging in this package.
-var _ = logf.Log.WithName("openstackmachine-resource")
+// +kubebuilder:webhook:verbs=create;update,path=/validate-infrastructure-cluster-x-k8s-io-v1beta1-openstackmachine,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=openstackmachines,versions=v1beta1,name=validation.openstackmachine.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1
-func (r *OpenStackMachine) SetupWebhookWithManager(mgr manager.Manager) error {
+func SetupOpenStackMachineWebhook(mgr manager.Manager) error {
return builder.WebhookManagedBy(mgr).
- For(r).
+ For(&infrav1.OpenStackMachine{}).
+ WithValidator(&openStackMachineWebhook{}).
Complete()
}
-// +kubebuilder:webhook:verbs=create;update,path=/validate-infrastructure-cluster-x-k8s-io-v1beta1-openstackmachine,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=openstackmachines,versions=v1beta1,name=validation.openstackmachine.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1
-// +kubebuilder:webhook:verbs=create;update,path=/mutate-infrastructure-cluster-x-k8s-io-v1beta1-openstackmachine,mutating=true,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=openstackmachines,versions=v1beta1,name=default.openstackmachine.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1
+type openStackMachineWebhook struct{}
-var (
- _ webhook.Defaulter = &OpenStackMachine{}
- _ webhook.Validator = &OpenStackMachine{}
-)
+// Compile-time assertion that openStackMachineWebhook implements webhook.CustomValidator.
+var _ webhook.CustomValidator = &openStackMachineWebhook{}
-// Default satisfies the defaulting webhook interface.
-func (r *OpenStackMachine) Default() {
-}
-
-// ValidateCreate implements webhook.Validator so a webhook will be registered for the type.
-func (r *OpenStackMachine) ValidateCreate() (admission.Warnings, error) {
+// ValidateCreate implements webhook.CustomValidator so a webhook will be registered for the type.
+func (*openStackMachineWebhook) ValidateCreate(_ context.Context, objRaw runtime.Object) (admission.Warnings, error) {
var allErrs field.ErrorList
+ newObj, err := castToOpenStackMachine(objRaw)
+ if err != nil {
+ return nil, err
+ }
- if r.Spec.RootVolume != nil && r.Spec.AdditionalBlockDevices != nil {
- for _, device := range r.Spec.AdditionalBlockDevices {
+ if newObj.Spec.RootVolume != nil && newObj.Spec.AdditionalBlockDevices != nil {
+ for _, device := range newObj.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)
+ return aggregateObjErrors(newObj.GroupVersionKind().GroupKind(), newObj.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)
+// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type.
+func (*openStackMachineWebhook) ValidateUpdate(_ context.Context, oldObjRaw, newObjRaw runtime.Object) (admission.Warnings, error) {
+ newObj, err := castToOpenStackMachine(newObjRaw)
+ if err != nil {
+ return nil, err
+ }
+
+ newOpenStackMachine, err := runtime.DefaultUnstructuredConverter.ToUnstructured(newObj)
if err != nil {
- return nil, apierrors.NewInvalid(GroupVersion.WithKind("OpenStackMachine").GroupKind(), r.Name, field.ErrorList{
+ return nil, apierrors.NewInvalid(infrav1.GroupVersion.WithKind("OpenStackMachine").GroupKind(), newObj.Name, field.ErrorList{
field.InternalError(nil, fmt.Errorf("failed to convert new OpenStackMachine to unstructured object: %w", err)),
})
}
- oldOpenStackMachine, err := runtime.DefaultUnstructuredConverter.ToUnstructured(old)
+ oldOpenStackMachine, err := runtime.DefaultUnstructuredConverter.ToUnstructured(oldObjRaw)
if err != nil {
- return nil, apierrors.NewInvalid(GroupVersion.WithKind("OpenStackMachine").GroupKind(), r.Name, field.ErrorList{
+ return nil, apierrors.NewInvalid(infrav1.GroupVersion.WithKind("OpenStackMachine").GroupKind(), newObj.Name, field.ErrorList{
field.InternalError(nil, fmt.Errorf("failed to convert old OpenStackMachine to unstructured object: %w", err)),
})
}
@@ -106,10 +110,18 @@ func (r *OpenStackMachine) ValidateUpdate(old runtime.Object) (admission.Warning
allErrs = append(allErrs, field.Forbidden(field.NewPath("spec"), "cannot be modified"))
}
- return aggregateObjErrors(r.GroupVersionKind().GroupKind(), r.Name, allErrs)
+ return aggregateObjErrors(newObj.GroupVersionKind().GroupKind(), newObj.Name, allErrs)
}
-// ValidateDelete implements webhook.Validator so a webhook will be registered for the type.
-func (r *OpenStackMachine) ValidateDelete() (admission.Warnings, error) {
+// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type.
+func (*openStackMachineWebhook) ValidateDelete(_ context.Context, _ runtime.Object) (admission.Warnings, error) {
return nil, nil
}
+
+func castToOpenStackMachine(obj runtime.Object) (*infrav1.OpenStackMachine, error) {
+ cast, ok := obj.(*infrav1.OpenStackMachine)
+ if !ok {
+ return nil, fmt.Errorf("expected an OpenStackMachine but got a %T", obj)
+ }
+ return cast, nil
+}
diff --git a/api/v1beta1/openstackmachinetemplate_webhook.go b/pkg/webhooks/openstackmachinetemplate_webhook.go
similarity index 55%
rename from api/v1beta1/openstackmachinetemplate_webhook.go
rename to pkg/webhooks/openstackmachinetemplate_webhook.go
index 24f27a937e..4d11008836 100644
--- a/api/v1beta1/openstackmachinetemplate_webhook.go
+++ b/pkg/webhooks/openstackmachinetemplate_webhook.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package v1beta1
+package webhooks
import (
"context"
@@ -29,52 +29,51 @@ import (
"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"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
+)
-// +kubebuilder:object:generate=false
-type OpenStackMachineTemplateWebhook struct{}
+// +kubebuilder:webhook:verbs=create;update,path=/validate-infrastructure-cluster-x-k8s-io-v1beta1-openstackmachinetemplate,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=openstackmachinetemplates,versions=v1beta1,name=validation.openstackmachinetemplate.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1
-func (r *OpenStackMachineTemplateWebhook) SetupWebhookWithManager(mgr manager.Manager) error {
+func SetupOpenStackMachineTemplateWebhook(mgr manager.Manager) error {
return builder.WebhookManagedBy(mgr).
- For(&OpenStackMachineTemplate{}).
- WithValidator(r).
+ For(&infrav1.OpenStackMachineTemplate{}).
+ WithValidator(&openStackMachineTemplateWebhook{}).
Complete()
}
-// +kubebuilder:webhook:verbs=create;update,path=/validate-infrastructure-cluster-x-k8s-io-v1beta1-openstackmachinetemplate,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=openstackmachinetemplates,versions=v1beta1,name=validation.openstackmachinetemplate.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1
+type openStackMachineTemplateWebhook struct{}
-var _ webhook.CustomValidator = &OpenStackMachineTemplateWebhook{}
+// Compile-time assertion that openStackMachineTemplateWebhook implements webhook.CustomValidator.
+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))
+func (*openStackMachineTemplateWebhook) ValidateCreate(_ context.Context, objRaw runtime.Object) (admission.Warnings, error) {
+ newObj, err := castToOpenStackMachineTemplate(objRaw)
+ if err != nil {
+ return nil, err
}
var allErrs field.ErrorList
- if openStackMachineTemplate.Spec.Template.Spec.ProviderID != nil {
+ if newObj.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)
+ return aggregateObjErrors(newObj.GroupVersionKind().GroupKind(), newObj.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) {
+func (*openStackMachineTemplateWebhook) ValidateUpdate(ctx context.Context, oldObjRaw, newObjRaw 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))
+ oldObj, err := castToOpenStackMachineTemplate(oldObjRaw)
+ if err != nil {
+ return nil, err
}
- newObj, ok := newRaw.(*OpenStackMachineTemplate)
- if !ok {
- return nil, apierrors.NewBadRequest(fmt.Sprintf("expected an OpenStackMachineTemplate but got a %T", oldRaw))
+ newObj, err := castToOpenStackMachineTemplate(newObjRaw)
+ if err != nil {
+ return nil, err
}
req, err := admission.RequestFromContext(ctx)
@@ -83,9 +82,9 @@ func (r *OpenStackMachineTemplateWebhook) ValidateUpdate(ctx context.Context, ol
}
if !topology.ShouldSkipImmutabilityChecks(req, newObj) &&
- !reflect.DeepEqual(newObj.Spec.Template.Spec, old.Spec.Template.Spec) {
+ !reflect.DeepEqual(newObj.Spec.Template.Spec, oldObj.Spec.Template.Spec) {
allErrs = append(allErrs,
- field.Invalid(field.NewPath("spec", "template", "spec"), r, OpenStackMachineTemplateImmutableMsg),
+ field.Invalid(field.NewPath("spec", "template", "spec"), newObj.Spec.Template.Spec, "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"),
)
}
@@ -93,6 +92,14 @@ func (r *OpenStackMachineTemplateWebhook) ValidateUpdate(ctx context.Context, ol
}
// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type.
-func (r *OpenStackMachineTemplateWebhook) ValidateDelete(_ context.Context, _ runtime.Object) (admission.Warnings, error) {
+func (*openStackMachineTemplateWebhook) ValidateDelete(_ context.Context, _ runtime.Object) (admission.Warnings, error) {
return nil, nil
}
+
+func castToOpenStackMachineTemplate(obj runtime.Object) (*infrav1.OpenStackMachineTemplate, error) {
+ cast, ok := obj.(*infrav1.OpenStackMachineTemplate)
+ if !ok {
+ return nil, fmt.Errorf("expected an OpenStackMachineTemplate but got a %T", obj)
+ }
+ return cast, nil
+}
diff --git a/api/v1beta1/openstackmachinetemplate_webhook_test.go b/pkg/webhooks/openstackmachinetemplate_webhook_test.go
similarity index 55%
rename from api/v1beta1/openstackmachinetemplate_webhook_test.go
rename to pkg/webhooks/openstackmachinetemplate_webhook_test.go
index 95fd2c7ccf..b6d30791c6 100644
--- a/api/v1beta1/openstackmachinetemplate_webhook_test.go
+++ b/pkg/webhooks/openstackmachinetemplate_webhook_test.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package v1beta1
+package webhooks
import (
"context"
@@ -26,6 +26,8 @@ import (
"k8s.io/utils/pointer"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
+
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
)
func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) {
@@ -33,29 +35,29 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) {
tests := []struct {
name string
- oldTemplate *OpenStackMachineTemplate
- newTemplate *OpenStackMachineTemplate
+ oldTemplate *infrav1.OpenStackMachineTemplate
+ newTemplate *infrav1.OpenStackMachineTemplate
req *admission.Request
wantErr bool
}{
{
name: "OpenStackMachineTemplate with immutable spec",
- oldTemplate: &OpenStackMachineTemplate{
- Spec: OpenStackMachineTemplateSpec{
- Template: OpenStackMachineTemplateResource{
- Spec: OpenStackMachineSpec{
+ oldTemplate: &infrav1.OpenStackMachineTemplate{
+ Spec: infrav1.OpenStackMachineTemplateSpec{
+ Template: infrav1.OpenStackMachineTemplateResource{
+ Spec: infrav1.OpenStackMachineSpec{
Flavor: "foo",
- Image: ImageFilter{Name: "bar"},
+ Image: infrav1.ImageFilter{Name: "bar"},
},
},
},
},
- newTemplate: &OpenStackMachineTemplate{
- Spec: OpenStackMachineTemplateSpec{
- Template: OpenStackMachineTemplateResource{
- Spec: OpenStackMachineSpec{
+ newTemplate: &infrav1.OpenStackMachineTemplate{
+ Spec: infrav1.OpenStackMachineTemplateSpec{
+ Template: infrav1.OpenStackMachineTemplateResource{
+ Spec: infrav1.OpenStackMachineSpec{
Flavor: "foo",
- Image: ImageFilter{Name: "NewImage"},
+ Image: infrav1.ImageFilter{Name: "NewImage"},
},
},
},
@@ -65,12 +67,12 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) {
},
{
name: "OpenStackMachineTemplate with mutable metadata",
- oldTemplate: &OpenStackMachineTemplate{
- Spec: OpenStackMachineTemplateSpec{
- Template: OpenStackMachineTemplateResource{
- Spec: OpenStackMachineSpec{
+ oldTemplate: &infrav1.OpenStackMachineTemplate{
+ Spec: infrav1.OpenStackMachineTemplateSpec{
+ Template: infrav1.OpenStackMachineTemplateResource{
+ Spec: infrav1.OpenStackMachineSpec{
Flavor: "foo",
- Image: ImageFilter{Name: "bar"},
+ Image: infrav1.ImageFilter{Name: "bar"},
},
},
},
@@ -78,12 +80,12 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) {
Name: "foo",
},
},
- newTemplate: &OpenStackMachineTemplate{
- Spec: OpenStackMachineTemplateSpec{
- Template: OpenStackMachineTemplateResource{
- Spec: OpenStackMachineSpec{
+ newTemplate: &infrav1.OpenStackMachineTemplate{
+ Spec: infrav1.OpenStackMachineTemplateSpec{
+ Template: infrav1.OpenStackMachineTemplateResource{
+ Spec: infrav1.OpenStackMachineSpec{
Flavor: "foo",
- Image: ImageFilter{Name: "bar"},
+ Image: infrav1.ImageFilter{Name: "bar"},
},
},
},
@@ -95,22 +97,22 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) {
},
{
name: "don't allow modification, dry run, no skip immutability annotation set",
- oldTemplate: &OpenStackMachineTemplate{
- Spec: OpenStackMachineTemplateSpec{
- Template: OpenStackMachineTemplateResource{
- Spec: OpenStackMachineSpec{
+ oldTemplate: &infrav1.OpenStackMachineTemplate{
+ Spec: infrav1.OpenStackMachineTemplateSpec{
+ Template: infrav1.OpenStackMachineTemplateResource{
+ Spec: infrav1.OpenStackMachineSpec{
Flavor: "foo",
- Image: ImageFilter{Name: "bar"},
+ Image: infrav1.ImageFilter{Name: "bar"},
},
},
},
},
- newTemplate: &OpenStackMachineTemplate{
- Spec: OpenStackMachineTemplateSpec{
- Template: OpenStackMachineTemplateResource{
- Spec: OpenStackMachineSpec{
+ newTemplate: &infrav1.OpenStackMachineTemplate{
+ Spec: infrav1.OpenStackMachineTemplateSpec{
+ Template: infrav1.OpenStackMachineTemplateResource{
+ Spec: infrav1.OpenStackMachineSpec{
Flavor: "foo",
- Image: ImageFilter{Name: "NewImage"},
+ Image: infrav1.ImageFilter{Name: "NewImage"},
},
},
},
@@ -120,27 +122,27 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) {
},
{
name: "allow modification, dry run, skip immutability annotation set",
- oldTemplate: &OpenStackMachineTemplate{
- Spec: OpenStackMachineTemplateSpec{
- Template: OpenStackMachineTemplateResource{
- Spec: OpenStackMachineSpec{
+ oldTemplate: &infrav1.OpenStackMachineTemplate{
+ Spec: infrav1.OpenStackMachineTemplateSpec{
+ Template: infrav1.OpenStackMachineTemplateResource{
+ Spec: infrav1.OpenStackMachineSpec{
Flavor: "foo",
- Image: ImageFilter{Name: "bar"},
+ Image: infrav1.ImageFilter{Name: "bar"},
},
},
},
},
- newTemplate: &OpenStackMachineTemplate{
+ newTemplate: &infrav1.OpenStackMachineTemplate{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
clusterv1.TopologyDryRunAnnotation: "",
},
},
- Spec: OpenStackMachineTemplateSpec{
- Template: OpenStackMachineTemplateResource{
- Spec: OpenStackMachineSpec{
+ Spec: infrav1.OpenStackMachineTemplateSpec{
+ Template: infrav1.OpenStackMachineTemplateResource{
+ Spec: infrav1.OpenStackMachineSpec{
Flavor: "foo",
- Image: ImageFilter{Name: "NewImage"},
+ Image: infrav1.ImageFilter{Name: "NewImage"},
},
},
},
@@ -154,7 +156,7 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
- webhook := &OpenStackMachineTemplateWebhook{}
+ webhook := &openStackMachineTemplateWebhook{}
ctx := admission.NewContextWithRequest(context.Background(), *tt.req)
warn, err := webhook.ValidateUpdate(ctx, tt.oldTemplate, tt.newTemplate)
diff --git a/pkg/webhooks/register.go b/pkg/webhooks/register.go
new file mode 100644
index 0000000000..02ad4608ed
--- /dev/null
+++ b/pkg/webhooks/register.go
@@ -0,0 +1,63 @@
+/*
+Copyright 2024 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 webhooks
+
+import (
+ "fmt"
+
+ ctrl "sigs.k8s.io/controller-runtime"
+ "sigs.k8s.io/controller-runtime/pkg/builder"
+ "sigs.k8s.io/controller-runtime/pkg/conversion"
+ "sigs.k8s.io/controller-runtime/pkg/manager"
+
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
+)
+
+func RegisterAllWithManager(mgr manager.Manager) []error {
+ var errs []error
+
+ // Register webhooks for all types with custom validators.
+ for _, webhook := range []struct {
+ name string
+ setup func(ctrl.Manager) error
+ }{
+ {"OpenStackCluster", SetupOpenStackClusterWebhook},
+ {"OpenStackClusterTemplate", SetupOpenStackClusterTemplateWebhook},
+ {"OpenStackMachine", SetupOpenStackMachineWebhook},
+ {"OpenStackMachineTemplate", SetupOpenStackMachineTemplateWebhook},
+ } {
+ if err := webhook.setup(mgr); err != nil {
+ errs = append(errs, fmt.Errorf("creating webhook for %s: %v", webhook.name, err))
+ }
+ }
+
+ // Additionally register webhooks for other types so they get conversion webhooks.
+ for _, conversionOnlyType := range []conversion.Hub{
+ &infrav1.OpenStackClusterList{},
+ &infrav1.OpenStackClusterTemplateList{},
+ &infrav1.OpenStackMachineList{},
+ &infrav1.OpenStackMachineTemplateList{},
+ } {
+ if err := builder.WebhookManagedBy(mgr).
+ For(conversionOnlyType).
+ Complete(); err != nil {
+ errs = append(errs, fmt.Errorf("creating webhook for %T: %v", conversionOnlyType, err))
+ }
+ }
+
+ return errs
+}
diff --git a/test/e2e/suites/apivalidations/suite_test.go b/test/e2e/suites/apivalidations/suite_test.go
index 65a8e69136..70eef5e7ec 100644
--- a/test/e2e/suites/apivalidations/suite_test.go
+++ b/test/e2e/suites/apivalidations/suite_test.go
@@ -39,6 +39,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/webhook"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
+ "sigs.k8s.io/cluster-api-provider-openstack/pkg/webhooks"
)
var (
@@ -119,14 +120,7 @@ var _ = BeforeSuite(func() {
}),
})
Expect(err).ToNot(HaveOccurred(), "Manager setup should succeed")
-
- Expect((&infrav1.OpenStackMachineTemplateWebhook{}).SetupWebhookWithManager(mgr)).To(Succeed(), "OpenStackMachineTemplate webhook should be registered with manager")
- Expect((&infrav1.OpenStackMachineTemplateList{}).SetupWebhookWithManager(mgr)).To(Succeed(), "OpenStackMachineTemplateList webhook should be registered with manager")
- Expect((&infrav1.OpenStackCluster{}).SetupWebhookWithManager(mgr)).To(Succeed(), "OpenStackCluster webhook should be registered with manager")
- Expect((&infrav1.OpenStackClusterTemplate{}).SetupWebhookWithManager(mgr)).To(Succeed(), "OpenStackClusterTemplate webhook should be registered with manager")
- Expect((&infrav1.OpenStackMachine{}).SetupWebhookWithManager(mgr)).To(Succeed(), "OpenStackMachine webhook should be registered with manager")
- Expect((&infrav1.OpenStackMachineList{}).SetupWebhookWithManager(mgr)).To(Succeed(), "OpenStackMachineList webhook should be registered with manager")
- Expect((&infrav1.OpenStackClusterList{}).SetupWebhookWithManager(mgr)).To(Succeed(), "OpenStackClusterList webhook should be registered with manager")
+ Expect(webhooks.RegisterAllWithManager(mgr)).To(BeEmpty(), "Failed to register webhooks")
By("Starting manager")
var mgrCtx context.Context
From 13e95db525b8e5aafca141ac2df90d5cb960188f Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Sat, 2 Mar 2024 00:22:15 +0000
Subject: [PATCH 096/180] Register API versions with test scheme in validation
tests
The conversion webhook does not try to register conversions for versions
which are not present in the scheme.
---
test/e2e/suites/apivalidations/suite_test.go | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/test/e2e/suites/apivalidations/suite_test.go b/test/e2e/suites/apivalidations/suite_test.go
index 70eef5e7ec..6705a96aa5 100644
--- a/test/e2e/suites/apivalidations/suite_test.go
+++ b/test/e2e/suites/apivalidations/suite_test.go
@@ -38,6 +38,10 @@ import (
"sigs.k8s.io/controller-runtime/pkg/metrics/server"
"sigs.k8s.io/controller-runtime/pkg/webhook"
+ infrav1alpha1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha1"
+ infrav1alpha5 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha5"
+ infrav1alpha6 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha6"
+ infrav1alpha7 "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/webhooks"
)
@@ -83,9 +87,15 @@ var _ = BeforeSuite(func() {
})
testScheme = scheme.Scheme
- Expect(infrav1.AddToScheme(testScheme)).To(Succeed())
-
- //+kubebuilder:scaffold:scheme
+ for _, f := range []func(*runtime.Scheme) error{
+ infrav1alpha1.AddToScheme,
+ infrav1alpha5.AddToScheme,
+ infrav1alpha6.AddToScheme,
+ infrav1alpha7.AddToScheme,
+ infrav1.AddToScheme,
+ } {
+ Expect(f(testScheme)).To(Succeed())
+ }
k8sClient, err = client.New(cfg, client.Options{Scheme: testScheme})
Expect(err).NotTo(HaveOccurred())
From cb09d5fe452bd6c2b24dfa1b10c35b8c65b92164 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Sat, 2 Mar 2024 00:24:41 +0000
Subject: [PATCH 097/180] Implement convertible for
OpenStackClusterTemplateList
The conversion webhook fails to register without this.
---
api/v1alpha5/conversion.go | 12 ++++++++++++
api/v1alpha6/conversion.go | 12 ++++++++++++
api/v1alpha7/conversion.go | 12 ++++++++++++
3 files changed, 36 insertions(+)
diff --git a/api/v1alpha5/conversion.go b/api/v1alpha5/conversion.go
index 8b31518c2e..9fb404b9e7 100644
--- a/api/v1alpha5/conversion.go
+++ b/api/v1alpha5/conversion.go
@@ -101,6 +101,18 @@ 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 {
diff --git a/api/v1alpha6/conversion.go b/api/v1alpha6/conversion.go
index dbdcde2687..6cc668deac 100644
--- a/api/v1alpha6/conversion.go
+++ b/api/v1alpha6/conversion.go
@@ -429,6 +429,18 @@ func (r *OpenStackClusterTemplate) ConvertFrom(srcRaw ctrlconversion.Hub) error
)
}
+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)
+}
+
var _ ctrlconversion.Convertible = &OpenStackMachine{}
var v1alpha6OpenStackMachineRestorer = conversion.RestorerFor[*OpenStackMachine]{
diff --git a/api/v1alpha7/conversion.go b/api/v1alpha7/conversion.go
index ed6c3f487f..9048c3e5ef 100644
--- a/api/v1alpha7/conversion.go
+++ b/api/v1alpha7/conversion.go
@@ -487,6 +487,18 @@ func (r *OpenStackClusterTemplate) ConvertFrom(srcRaw ctrlconversion.Hub) error
)
}
+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)
+}
+
var _ ctrlconversion.Convertible = &OpenStackMachine{}
var v1alpha7OpenStackMachineRestorer = conversion.RestorerFor[*OpenStackMachine]{
From 1eca0903b4b47f7852b0982430ae9d4ec670ce40 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Tue, 5 Mar 2024 11:11:30 +0000
Subject: [PATCH 098/180] Split v1alpha6&v1alpha7 conversion into multiple
files
This is 100% code motion with no code changes whatsoever.
conversion.go has become unwieldy, making changes to it harder to
understand. This simply splits it into several files based on the
corresponding _types.go.
We don't touch v1alpha5 as it's about to be deleted. It can stay a mess.
---
api/v1alpha6/conversion.go | 1236 -----------------
api/v1alpha6/openstackcluster_conversion.go | 400 ++++++
.../openstackclustertemplate_conversion.go | 115 ++
api/v1alpha6/openstackmachine_conversion.go | 340 +++++
.../openstackmachinetemplate_conversion.go | 78 ++
api/v1alpha6/types_conversion.go | 445 ++++++
api/v1alpha7/conversion.go | 1002 -------------
api/v1alpha7/openstackcluster_conversion.go | 352 +++++
.../openstackclustertemplate_conversion.go | 88 ++
api/v1alpha7/openstackmachine_conversion.go | 231 +++
.../openstackmachinetemplate_conversion.go | 82 ++
api/v1alpha7/types_conversion.go | 376 +++++
12 files changed, 2507 insertions(+), 2238 deletions(-)
delete mode 100644 api/v1alpha6/conversion.go
create mode 100644 api/v1alpha6/openstackcluster_conversion.go
create mode 100644 api/v1alpha6/openstackclustertemplate_conversion.go
create mode 100644 api/v1alpha6/openstackmachine_conversion.go
create mode 100644 api/v1alpha6/openstackmachinetemplate_conversion.go
create mode 100644 api/v1alpha6/types_conversion.go
delete mode 100644 api/v1alpha7/conversion.go
create mode 100644 api/v1alpha7/openstackcluster_conversion.go
create mode 100644 api/v1alpha7/openstackclustertemplate_conversion.go
create mode 100644 api/v1alpha7/openstackmachine_conversion.go
create mode 100644 api/v1alpha7/openstackmachinetemplate_conversion.go
create mode 100644 api/v1alpha7/types_conversion.go
diff --git a/api/v1alpha6/conversion.go b/api/v1alpha6/conversion.go
deleted file mode 100644
index 6cc668deac..0000000000
--- a/api/v1alpha6/conversion.go
+++ /dev/null
@@ -1,1236 +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"
- "k8s.io/utils/pointer"
- 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"
-)
-
-const trueString = "true"
-
-func restorev1alpha6SubnetFilter(previous *SubnetFilter, dst *SubnetFilter) {
- // 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 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 restorev1alpha6NetworkFilter(previous *NetworkFilter, dst *NetworkFilter) {
- // 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 restorev1alpha6SecurityGroup(previous *SecurityGroup, dst *SecurityGroup) {
- if previous == nil || dst == nil {
- return
- }
-
- for i, rule := range previous.Rules {
- dst.Rules[i].SecurityGroupID = rule.SecurityGroupID
- }
-}
-
-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)
- }
- }
-
- if dst.Network != nil && previous.Network != nil {
- 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 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 {
- 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)
- }
- }
-}
-
-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.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
- }
-
- restorev1alpha6SecurityGroup(previous.ControlPlaneSecurityGroup, dst.ControlPlaneSecurityGroup)
- restorev1alpha6SecurityGroup(previous.WorkerSecurityGroup, dst.WorkerSecurityGroup)
- restorev1alpha6SecurityGroup(previous.BastionSecurityGroup, dst.BastionSecurityGroup)
-}
-
-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
-}
-
-func restorev1beta1Bastion(previous **infrav1.Bastion, dst **infrav1.Bastion) {
- if *previous != nil && *dst != nil {
- restorev1beta1MachineSpec(&(*previous).Instance, &(*dst).Instance)
- }
-}
-
-func restorev1beta1Subnets(previous *[]infrav1.SubnetFilter, dst *[]infrav1.SubnetFilter) {
- if len(*previous) > 1 {
- *dst = append(*dst, (*previous)[1:]...)
- }
-}
-
-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
-
- if previous.Bastion != nil {
- dst.Bastion.ReferencedResources = previous.Bastion.ReferencedResources
- }
- if previous.Bastion != nil && previous.Bastion.DependentResources.PortsStatus != nil {
- dst.Bastion.DependentResources.PortsStatus = previous.Bastion.DependentResources.PortsStatus
- }
-}
-
-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 = ""
- }
- }
-
- // 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)
- }
-
- // 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 {
- restorev1alpha6SubnetFilter(&previous.ExternalRouterIPs[i].Subnet.Filter, &dst.ExternalRouterIPs[i].Subnet.Filter)
- }
- }
-
- restorev1alpha6SubnetFilter(&previous.Subnet, &dst.Subnet)
-
- restorev1alpha6NetworkFilter(&previous.Network, &dst.Network)
-}
-
-var _ ctrlconversion.Convertible = &OpenStackCluster{}
-
-var v1alpha6OpenStackClusterRestorer = conversion.RestorerFor[*OpenStackCluster]{
- "spec": conversion.HashedFieldRestorer(
- func(c *OpenStackCluster) *OpenStackClusterSpec {
- return &c.Spec
- },
- restorev1alpha6ClusterSpec,
- ),
- "status": conversion.HashedFieldRestorer(
- func(c *OpenStackCluster) *OpenStackClusterStatus {
- return &c.Status
- },
- restorev1alpha6ClusterStatus,
- ),
-}
-
-var v1beta1OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStackCluster]{
- "externalNetwork": conversion.UnconditionalFieldRestorer(
- func(c *infrav1.OpenStackCluster) *infrav1.NetworkFilter {
- return &c.Spec.ExternalNetwork
- },
- ),
- "disableExternalNetwork": conversion.UnconditionalFieldRestorer(
- func(c *infrav1.OpenStackCluster) *bool {
- return &c.Spec.DisableExternalNetwork
- },
- ),
- "router": conversion.UnconditionalFieldRestorer(
- func(c *infrav1.OpenStackCluster) **infrav1.RouterFilter {
- return &c.Spec.Router
- },
- ),
- "networkMtu": conversion.UnconditionalFieldRestorer(
- func(c *infrav1.OpenStackCluster) *int {
- return &c.Spec.NetworkMTU
- },
- ),
- "bastion": conversion.HashedFieldRestorer(
- func(c *infrav1.OpenStackCluster) **infrav1.Bastion {
- return &c.Spec.Bastion
- },
- restorev1beta1Bastion,
- ),
- "subnets": conversion.HashedFieldRestorer(
- func(c *infrav1.OpenStackCluster) *[]infrav1.SubnetFilter {
- return &c.Spec.Subnets
- },
- restorev1beta1Subnets,
- ),
- "allNodesSecurityGroupRules": conversion.HashedFieldRestorer(
- func(c *infrav1.OpenStackCluster) *infrav1.ManagedSecurityGroups {
- return c.Spec.ManagedSecurityGroups
- },
- restorev1beta1ManagedSecurityGroups,
- ),
- "status": conversion.HashedFieldRestorer(
- func(c *infrav1.OpenStackCluster) *infrav1.OpenStackClusterStatus {
- return &c.Status
- },
- restorev1beta1ClusterStatus,
- ),
- "managedSubnets": conversion.UnconditionalFieldRestorer(
- func(c *infrav1.OpenStackCluster) *[]infrav1.SubnetSpec {
- return &c.Spec.ManagedSubnets
- },
- ),
-}
-
-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)
-}
-
-var _ ctrlconversion.Convertible = &OpenStackClusterTemplate{}
-
-var v1alpha6OpenStackClusterTemplateRestorer = conversion.RestorerFor[*OpenStackClusterTemplate]{
- "spec": conversion.HashedFieldRestorer(
- func(c *OpenStackClusterTemplate) *OpenStackClusterSpec {
- return &c.Spec.Template.Spec
- },
- restorev1alpha6ClusterSpec,
- ),
-}
-
-func restorev1beta1ManagedSecurityGroups(previous *infrav1.ManagedSecurityGroups, dst *infrav1.ManagedSecurityGroups) {
- dst.AllNodesSecurityGroupRules = previous.AllNodesSecurityGroupRules
-}
-
-var v1beta1OpenStackClusterTemplateRestorer = conversion.RestorerFor[*infrav1.OpenStackClusterTemplate]{
- "externalNetwork": conversion.UnconditionalFieldRestorer(
- func(c *infrav1.OpenStackClusterTemplate) *infrav1.NetworkFilter {
- return &c.Spec.Template.Spec.ExternalNetwork
- },
- ),
- "disableExternalNetwork": conversion.UnconditionalFieldRestorer(
- func(c *infrav1.OpenStackClusterTemplate) *bool {
- return &c.Spec.Template.Spec.DisableExternalNetwork
- },
- ),
- "router": conversion.UnconditionalFieldRestorer(
- func(c *infrav1.OpenStackClusterTemplate) **infrav1.RouterFilter {
- return &c.Spec.Template.Spec.Router
- },
- ),
- "networkMtu": conversion.UnconditionalFieldRestorer(
- func(c *infrav1.OpenStackClusterTemplate) *int {
- return &c.Spec.Template.Spec.NetworkMTU
- },
- ),
- "bastion": conversion.HashedFieldRestorer(
- func(c *infrav1.OpenStackClusterTemplate) **infrav1.Bastion {
- return &c.Spec.Template.Spec.Bastion
- },
- restorev1beta1Bastion,
- ),
- "subnets": conversion.HashedFieldRestorer(
- func(c *infrav1.OpenStackClusterTemplate) *[]infrav1.SubnetFilter {
- return &c.Spec.Template.Spec.Subnets
- },
- restorev1beta1Subnets,
- ),
- "allNodesSecurityGroupRules": conversion.HashedFieldRestorer(
- func(c *infrav1.OpenStackClusterTemplate) *infrav1.ManagedSecurityGroups {
- return c.Spec.Template.Spec.ManagedSecurityGroups
- },
- restorev1beta1ManagedSecurityGroups,
- ),
- "managedSubnets": conversion.UnconditionalFieldRestorer(
- func(c *infrav1.OpenStackClusterTemplate) *[]infrav1.SubnetSpec {
- return &c.Spec.Template.Spec.ManagedSubnets
- },
- ),
-}
-
-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)
-}
-
-var _ ctrlconversion.Convertible = &OpenStackMachine{}
-
-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.DependentMachineResources {
- return &c.Status.DependentResources
- },
- ),
- // No equivalent in v1alpha6
- "refresources": conversion.UnconditionalFieldRestorer(
- func(c *infrav1.OpenStackMachine) *infrav1.ReferencedMachineResources {
- return &c.Status.ReferencedResources
- },
- ),
-}
-
-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)
-}
-
-var _ ctrlconversion.Convertible = &OpenStackMachineTemplate{}
-
-var v1alpha6OpenStackMachineTemplateRestorer = conversion.RestorerFor[*OpenStackMachineTemplate]{
- "spec": conversion.HashedFieldRestorer(
- func(c *OpenStackMachineTemplate) *OpenStackMachineSpec {
- return &c.Spec.Template.Spec
- },
- restorev1alpha6MachineSpec,
- ),
-}
-
-var v1beta1OpenStackMachineTemplateRestorer = conversion.RestorerFor[*infrav1.OpenStackMachineTemplate]{
- "spec": conversion.HashedFieldRestorer(
- func(c *infrav1.OpenStackMachineTemplate) *infrav1.OpenStackMachineSpec {
- return &c.Spec.Template.Spec
- },
- restorev1beta1MachineSpec,
- ),
-}
-
-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)
-}
-
-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.ServerGroupFilter{ID: in.ServerGroupID}
- } else {
- out.ServerGroup = nil
- }
-
- imageFilter := infrav1.ImageFilter{}
- if in.Image != "" {
- imageFilter.Name = in.Image
- }
- if in.ImageUUID != "" {
- imageFilter.ID = in.ImageUUID
- }
- out.Image = imageFilter
-
- 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 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.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{}
- if err := Convert_v1alpha6_NetworkFilter_To_v1beta1_NetworkFilter(&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.SubnetFilter{ID: subnet.UUID}},
- },
- })
- } else {
- subnetFilter := &infrav1.SubnetFilter{}
- if err := Convert_v1alpha6_SubnetFilter_To_v1beta1_SubnetFilter(&subnet.Filter, subnetFilter, s); err != nil {
- return nil, err
- }
- ports = append(ports, infrav1.PortOpts{
- Network: networkFilter,
- FixedIPs: []infrav1.FixedIP{
- {Subnet: subnetFilter},
- },
- })
- }
- }
- }
- }
-
- return ports, nil
-}
-
-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.ExternalNetwork.ID != "" {
- out.ExternalNetworkID = in.ExternalNetwork.ID
- }
-
- if len(in.Subnets) >= 1 {
- if err := Convert_v1beta1_SubnetFilter_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
- }
-
- out.CloudName = in.IdentityRef.CloudName
- out.IdentityRef = &OpenStackIdentityReference{Name: in.IdentityRef.Name}
-
- return nil
-}
-
-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.ExternalNetworkID != "" {
- out.ExternalNetwork = infrav1.NetworkFilter{
- ID: in.ExternalNetworkID,
- }
- }
-
- emptySubnet := SubnetFilter{}
- if in.Subnet != emptySubnet {
- subnet := infrav1.SubnetFilter{}
- if err := Convert_v1alpha6_SubnetFilter_To_v1beta1_SubnetFilter(&in.Subnet, &subnet, s); err != nil {
- return err
- }
- out.Subnets = []infrav1.SubnetFilter{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
- }
- }
-
- out.IdentityRef.CloudName = in.CloudName
- if in.IdentityRef != nil {
- out.IdentityRef.Name = in.IdentityRef.Name
- }
-
- return nil
-}
-
-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.SecurityGroupFilter, 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.SecurityGroupFilter{ID: sgParam.UUID})
- case sgParam.Name != "":
- out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupFilter{Name: sgParam.Name})
- case sgParam.Filter != (SecurityGroupFilter{}):
- out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupFilter{})
- outSG := &out.SecurityGroups[len(out.SecurityGroups)-1]
- if err := Convert_v1alpha6_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(&sgParam.Filter, outSG, s); err != nil {
- return err
- }
- }
- }
- for _, id := range in.SecurityGroups {
- out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupFilter{ID: id})
- }
- }
-
- // 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_SecurityGroupFilter_To_string(in *infrav1.SecurityGroupFilter, out *string, _ apiconversion.Scope) error {
- if in.ID != "" {
- *out = in.ID
- }
- 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 {
- securityGroupParam := &out.SecurityGroupFilters[i]
- if in.SecurityGroups[i].ID != "" {
- securityGroupParam.UUID = in.SecurityGroups[i].ID
- } else {
- if err := Convert_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(&in.SecurityGroups[i], &securityGroupParam.Filter, s); err != nil {
- return err
- }
- }
- }
- }
-
- if in.Profile != nil {
- out.Profile = make(map[string]string)
- if pointer.BoolDeref(in.Profile.OVSHWOffload, false) {
- (out.Profile)["capabilities"] = "[\"switchdev\"]"
- }
- if pointer.BoolDeref(in.Profile.TrustedVF, false) {
- (out.Profile)["trusted"] = trueString
- }
- }
-
- return nil
-}
-
-func Convert_v1alpha6_Instance_To_v1beta1_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_v1beta1_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_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
-}
-
-func Convert_v1alpha6_SecurityGroupParam_To_v1beta1_SecurityGroupFilter(in *SecurityGroupParam, out *infrav1.SecurityGroupFilter, s apiconversion.Scope) error {
- // SecurityGroupParam is replaced by its contained SecurityGroupFilter in v1beta1
- err := Convert_v1alpha6_SecurityGroupFilter_To_v1beta1_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_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupParam(in *infrav1.SecurityGroupFilter, out *SecurityGroupParam, s apiconversion.Scope) error {
- // SecurityGroupParam is replaced by its contained SecurityGroupFilter in v1beta1
- err := Convert_v1beta1_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_v1beta1_SubnetFilter(in *SubnetParam, out *infrav1.SubnetFilter, s apiconversion.Scope) error {
- if err := Convert_v1alpha6_SubnetFilter_To_v1beta1_SubnetFilter(&in.Filter, out, s); err != nil {
- return err
- }
- if in.UUID != "" {
- out.ID = in.UUID
- }
- return nil
-}
-
-func Convert_v1beta1_SubnetFilter_To_v1alpha6_SubnetParam(in *infrav1.SubnetFilter, out *SubnetParam, s apiconversion.Scope) error {
- if err := Convert_v1beta1_SubnetFilter_To_v1alpha6_SubnetFilter(in, &out.Filter, s); err != nil {
- return err
- }
- out.UUID = in.ID
-
- 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 = pointer.Bool(true)
- }
- }
- if k == "trusted" && v == trueString {
- out.TrustedVF = pointer.Bool(true)
- }
- }
- return nil
-}
-
-func Convert_v1beta1_BindingProfile_To_Map_string_To_Interface(in *infrav1.BindingProfile, out map[string]string, _ apiconversion.Scope) error {
- if pointer.BoolDeref(in.OVSHWOffload, false) {
- (out)["capabilities"] = "[\"switchdev\"]"
- }
- if pointer.BoolDeref(in.TrustedVF, false) {
- (out)["trusted"] = trueString
- }
- return nil
-}
-
-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)
- out.Network.APIServerLoadBalancer = (*LoadBalancer)(in.APIServerLoadBalancer)
- }
-
- 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)
- out.APIServerLoadBalancer = (*infrav1.LoadBalancer)(in.Network.APIServerLoadBalancer)
- }
-
- 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 {
- out.ServerGroupID = in.ServerGroup.ID
- }
-
- if in.Image.Name != "" {
- out.Image = in.Image.Name
- }
-
- if in.Image.ID != "" {
- out.ImageUUID = in.Image.ID
- }
-
- 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
-}
-
-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)
-}
-
-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 in.Instance.ServerGroupID != "" {
- out.Instance.ServerGroup = &infrav1.ServerGroupFilter{ID: in.Instance.ServerGroupID}
- } else {
- out.Instance.ServerGroup = nil
- }
-
- out.FloatingIP = in.Instance.FloatingIP
- 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.Instance.ServerGroup != nil && in.Instance.ServerGroup.ID != "" {
- out.Instance.ServerGroupID = in.Instance.ServerGroup.ID
- }
-
- out.Instance.FloatingIP = in.FloatingIP
- return nil
-}
-
-func Convert_v1beta1_SecurityGroupStatus_To_v1alpha6_SecurityGroup(in *infrav1.SecurityGroupStatus, out *SecurityGroup, s apiconversion.Scope) error { //nolint:revive
- out.ID = in.ID
- out.Name = in.Name
- out.Rules = make([]SecurityGroupRule, len(in.Rules))
- for i, rule := range in.Rules {
- out.Rules[i] = SecurityGroupRule{
- ID: rule.ID,
- Direction: rule.Direction,
- }
- if rule.Description != nil {
- out.Rules[i].Description = *rule.Description
- }
- if rule.EtherType != nil {
- out.Rules[i].EtherType = *rule.EtherType
- }
- if rule.PortRangeMin != nil {
- out.Rules[i].PortRangeMin = *rule.PortRangeMin
- }
- if rule.PortRangeMax != nil {
- out.Rules[i].PortRangeMax = *rule.PortRangeMax
- }
- if rule.Protocol != nil {
- out.Rules[i].Protocol = *rule.Protocol
- }
- if rule.RemoteGroupID != nil {
- out.Rules[i].RemoteGroupID = *rule.RemoteGroupID
- }
- if rule.RemoteIPPrefix != nil {
- out.Rules[i].RemoteIPPrefix = *rule.RemoteIPPrefix
- }
- }
- return nil
-}
-
-func Convert_v1alpha6_SecurityGroup_To_v1beta1_SecurityGroupStatus(in *SecurityGroup, out *infrav1.SecurityGroupStatus, s apiconversion.Scope) error { //nolint:revive
- out.ID = in.ID
- out.Name = in.Name
- out.Rules = make([]infrav1.SecurityGroupRuleStatus, len(in.Rules))
- for i, rule := range in.Rules {
- out.Rules[i] = infrav1.SecurityGroupRuleStatus{
- ID: rule.ID,
- Description: pointer.String(rule.Description),
- Direction: rule.Direction,
- EtherType: pointer.String(rule.EtherType),
- PortRangeMin: pointer.Int(rule.PortRangeMin),
- PortRangeMax: pointer.Int(rule.PortRangeMax),
- Protocol: pointer.String(rule.Protocol),
- RemoteGroupID: pointer.String(rule.RemoteGroupID),
- RemoteIPPrefix: pointer.String(rule.RemoteIPPrefix),
- }
- }
-
- return nil
-}
-
-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
-}
-
-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_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in *SecurityGroupFilter, out *infrav1.SecurityGroupFilter, s apiconversion.Scope) error {
- if err := autoConvert_v1alpha6_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_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
-}
-
-func Convert_v1alpha6_NetworkFilter_To_v1beta1_NetworkFilter(in *NetworkFilter, out *infrav1.NetworkFilter, s apiconversion.Scope) error {
- if err := autoConvert_v1alpha6_NetworkFilter_To_v1beta1_NetworkFilter(in, out, s); err != nil {
- return err
- }
- infrav1.ConvertAllTagsTo(in.Tags, in.TagsAny, in.NotTags, in.NotTagsAny, &out.FilterByNeutronTags)
- return nil
-}
-
-func Convert_v1beta1_NetworkFilter_To_v1alpha6_NetworkFilter(in *infrav1.NetworkFilter, out *NetworkFilter, s apiconversion.Scope) error {
- if err := autoConvert_v1beta1_NetworkFilter_To_v1alpha6_NetworkFilter(in, out, s); err != nil {
- return err
- }
- infrav1.ConvertAllTagsFrom(&in.FilterByNeutronTags, &out.Tags, &out.TagsAny, &out.NotTags, &out.NotTagsAny)
- return nil
-}
diff --git a/api/v1alpha6/openstackcluster_conversion.go b/api/v1alpha6/openstackcluster_conversion.go
new file mode 100644
index 0000000000..57499183a9
--- /dev/null
+++ b/api/v1alpha6/openstackcluster_conversion.go
@@ -0,0 +1,400 @@
+/*
+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"
+ 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 = &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,
+ ),
+ "status": conversion.HashedFieldRestorer(
+ func(c *OpenStackCluster) *OpenStackClusterStatus {
+ return &c.Status
+ },
+ restorev1alpha6ClusterStatus,
+ ),
+}
+
+var v1beta1OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStackCluster]{
+ "externalNetwork": conversion.UnconditionalFieldRestorer(
+ func(c *infrav1.OpenStackCluster) *infrav1.NetworkFilter {
+ return &c.Spec.ExternalNetwork
+ },
+ ),
+ "disableExternalNetwork": conversion.UnconditionalFieldRestorer(
+ func(c *infrav1.OpenStackCluster) *bool {
+ return &c.Spec.DisableExternalNetwork
+ },
+ ),
+ "router": conversion.UnconditionalFieldRestorer(
+ func(c *infrav1.OpenStackCluster) **infrav1.RouterFilter {
+ return &c.Spec.Router
+ },
+ ),
+ "networkMtu": conversion.UnconditionalFieldRestorer(
+ func(c *infrav1.OpenStackCluster) *int {
+ return &c.Spec.NetworkMTU
+ },
+ ),
+ "bastion": conversion.HashedFieldRestorer(
+ func(c *infrav1.OpenStackCluster) **infrav1.Bastion {
+ return &c.Spec.Bastion
+ },
+ restorev1beta1Bastion,
+ ),
+ "subnets": conversion.HashedFieldRestorer(
+ func(c *infrav1.OpenStackCluster) *[]infrav1.SubnetFilter {
+ return &c.Spec.Subnets
+ },
+ restorev1beta1Subnets,
+ ),
+ "allNodesSecurityGroupRules": conversion.HashedFieldRestorer(
+ func(c *infrav1.OpenStackCluster) *infrav1.ManagedSecurityGroups {
+ return c.Spec.ManagedSecurityGroups
+ },
+ restorev1beta1ManagedSecurityGroups,
+ ),
+ "status": conversion.HashedFieldRestorer(
+ func(c *infrav1.OpenStackCluster) *infrav1.OpenStackClusterStatus {
+ return &c.Status
+ },
+ restorev1beta1ClusterStatus,
+ ),
+ "managedSubnets": conversion.UnconditionalFieldRestorer(
+ func(c *infrav1.OpenStackCluster) *[]infrav1.SubnetSpec {
+ return &c.Spec.ManagedSubnets
+ },
+ ),
+}
+
+/* OpenStackClusterSpec */
+
+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 = ""
+ }
+ }
+
+ // 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)
+ }
+
+ // 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 {
+ restorev1alpha6SubnetFilter(&previous.ExternalRouterIPs[i].Subnet.Filter, &dst.ExternalRouterIPs[i].Subnet.Filter)
+ }
+ }
+
+ restorev1alpha6SubnetFilter(&previous.Subnet, &dst.Subnet)
+
+ restorev1alpha6NetworkFilter(&previous.Network, &dst.Network)
+}
+
+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.ExternalNetworkID != "" {
+ out.ExternalNetwork = infrav1.NetworkFilter{
+ ID: in.ExternalNetworkID,
+ }
+ }
+
+ emptySubnet := SubnetFilter{}
+ if in.Subnet != emptySubnet {
+ subnet := infrav1.SubnetFilter{}
+ if err := Convert_v1alpha6_SubnetFilter_To_v1beta1_SubnetFilter(&in.Subnet, &subnet, s); err != nil {
+ return err
+ }
+ out.Subnets = []infrav1.SubnetFilter{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
+ }
+ }
+
+ out.IdentityRef.CloudName = in.CloudName
+ if in.IdentityRef != nil {
+ out.IdentityRef.Name = in.IdentityRef.Name
+ }
+
+ return nil
+}
+
+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.ExternalNetwork.ID != "" {
+ out.ExternalNetworkID = in.ExternalNetwork.ID
+ }
+
+ if len(in.Subnets) >= 1 {
+ if err := Convert_v1beta1_SubnetFilter_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
+ }
+
+ out.CloudName = in.IdentityRef.CloudName
+ out.IdentityRef = &OpenStackIdentityReference{Name: in.IdentityRef.Name}
+
+ 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.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
+ }
+
+ 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
+
+ if previous.Bastion != nil {
+ dst.Bastion.ReferencedResources = previous.Bastion.ReferencedResources
+ }
+ if previous.Bastion != nil && previous.Bastion.DependentResources.PortsStatus != nil {
+ dst.Bastion.DependentResources.PortsStatus = previous.Bastion.DependentResources.PortsStatus
+ }
+}
+
+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)
+ out.Network.APIServerLoadBalancer = (*LoadBalancer)(in.APIServerLoadBalancer)
+ }
+
+ 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)
+ out.APIServerLoadBalancer = (*infrav1.LoadBalancer)(in.Network.APIServerLoadBalancer)
+ }
+
+ return nil
+}
+
+/* Bastion */
+
+func restorev1beta1Bastion(previous **infrav1.Bastion, dst **infrav1.Bastion) {
+ if *previous != nil && *dst != nil {
+ restorev1beta1MachineSpec(&(*previous).Instance, &(*dst).Instance)
+ }
+}
+
+func Convert_v1alpha6_Instance_To_v1beta1_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_v1beta1_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_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 in.Instance.ServerGroupID != "" {
+ out.Instance.ServerGroup = &infrav1.ServerGroupFilter{ID: in.Instance.ServerGroupID}
+ } else {
+ out.Instance.ServerGroup = nil
+ }
+
+ out.FloatingIP = in.Instance.FloatingIP
+ 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.Instance.ServerGroup != nil && in.Instance.ServerGroup.ID != "" {
+ out.Instance.ServerGroupID = in.Instance.ServerGroup.ID
+ }
+
+ out.Instance.FloatingIP = in.FloatingIP
+ return nil
+}
+
+/* ManagedSecurityGroups */
+
+func restorev1beta1ManagedSecurityGroups(previous *infrav1.ManagedSecurityGroups, dst *infrav1.ManagedSecurityGroups) {
+ dst.AllNodesSecurityGroupRules = previous.AllNodesSecurityGroupRules
+}
diff --git a/api/v1alpha6/openstackclustertemplate_conversion.go b/api/v1alpha6/openstackclustertemplate_conversion.go
new file mode 100644
index 0000000000..cf7a3ffead
--- /dev/null
+++ b/api/v1alpha6/openstackclustertemplate_conversion.go
@@ -0,0 +1,115 @@
+/*
+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]{
+ "externalNetwork": conversion.UnconditionalFieldRestorer(
+ func(c *infrav1.OpenStackClusterTemplate) *infrav1.NetworkFilter {
+ return &c.Spec.Template.Spec.ExternalNetwork
+ },
+ ),
+ "disableExternalNetwork": conversion.UnconditionalFieldRestorer(
+ func(c *infrav1.OpenStackClusterTemplate) *bool {
+ return &c.Spec.Template.Spec.DisableExternalNetwork
+ },
+ ),
+ "router": conversion.UnconditionalFieldRestorer(
+ func(c *infrav1.OpenStackClusterTemplate) **infrav1.RouterFilter {
+ return &c.Spec.Template.Spec.Router
+ },
+ ),
+ "networkMtu": conversion.UnconditionalFieldRestorer(
+ func(c *infrav1.OpenStackClusterTemplate) *int {
+ return &c.Spec.Template.Spec.NetworkMTU
+ },
+ ),
+ "bastion": conversion.HashedFieldRestorer(
+ func(c *infrav1.OpenStackClusterTemplate) **infrav1.Bastion {
+ return &c.Spec.Template.Spec.Bastion
+ },
+ restorev1beta1Bastion,
+ ),
+ "subnets": conversion.HashedFieldRestorer(
+ func(c *infrav1.OpenStackClusterTemplate) *[]infrav1.SubnetFilter {
+ return &c.Spec.Template.Spec.Subnets
+ },
+ restorev1beta1Subnets,
+ ),
+ "allNodesSecurityGroupRules": conversion.HashedFieldRestorer(
+ func(c *infrav1.OpenStackClusterTemplate) *infrav1.ManagedSecurityGroups {
+ return c.Spec.Template.Spec.ManagedSecurityGroups
+ },
+ restorev1beta1ManagedSecurityGroups,
+ ),
+ "managedSubnets": conversion.UnconditionalFieldRestorer(
+ func(c *infrav1.OpenStackClusterTemplate) *[]infrav1.SubnetSpec {
+ return &c.Spec.Template.Spec.ManagedSubnets
+ },
+ ),
+}
diff --git a/api/v1alpha6/openstackmachine_conversion.go b/api/v1alpha6/openstackmachine_conversion.go
new file mode 100644
index 0000000000..6720f99f90
--- /dev/null
+++ b/api/v1alpha6/openstackmachine_conversion.go
@@ -0,0 +1,340 @@
+/*
+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.DependentMachineResources {
+ return &c.Status.DependentResources
+ },
+ ),
+ // No equivalent in v1alpha6
+ "refresources": conversion.UnconditionalFieldRestorer(
+ func(c *infrav1.OpenStackMachine) *infrav1.ReferencedMachineResources {
+ return &c.Status.ReferencedResources
+ },
+ ),
+}
+
+/* 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 {
+ 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)
+ }
+ }
+}
+
+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
+}
+
+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.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{}
+ if err := Convert_v1alpha6_NetworkFilter_To_v1beta1_NetworkFilter(&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.SubnetFilter{ID: subnet.UUID}},
+ },
+ })
+ } else {
+ subnetFilter := &infrav1.SubnetFilter{}
+ if err := Convert_v1alpha6_SubnetFilter_To_v1beta1_SubnetFilter(&subnet.Filter, subnetFilter, s); err != nil {
+ return nil, err
+ }
+ ports = append(ports, infrav1.PortOpts{
+ Network: networkFilter,
+ FixedIPs: []infrav1.FixedIP{
+ {Subnet: subnetFilter},
+ },
+ })
+ }
+ }
+ }
+ }
+
+ 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.ServerGroupFilter{ID: in.ServerGroupID}
+ } else {
+ out.ServerGroup = nil
+ }
+
+ imageFilter := infrav1.ImageFilter{}
+ if in.Image != "" {
+ imageFilter.Name = in.Image
+ }
+ if in.ImageUUID != "" {
+ imageFilter.ID = in.ImageUUID
+ }
+ out.Image = imageFilter
+
+ 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 {
+ out.ServerGroupID = in.ServerGroup.ID
+ }
+
+ if in.Image.Name != "" {
+ out.Image = in.Image.Name
+ }
+
+ if in.Image.ID != "" {
+ out.ImageUUID = in.Image.ID
+ }
+
+ 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/openstackmachinetemplate_conversion.go b/api/v1alpha6/openstackmachinetemplate_conversion.go
new file mode 100644
index 0000000000..0851e5f6b1
--- /dev/null
+++ b/api/v1alpha6/openstackmachinetemplate_conversion.go
@@ -0,0 +1,78 @@
+/*
+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
+ },
+ restorev1alpha6MachineSpec,
+ ),
+}
+
+var v1beta1OpenStackMachineTemplateRestorer = conversion.RestorerFor[*infrav1.OpenStackMachineTemplate]{
+ "spec": conversion.HashedFieldRestorer(
+ func(c *infrav1.OpenStackMachineTemplate) *infrav1.OpenStackMachineSpec {
+ return &c.Spec.Template.Spec
+ },
+ restorev1beta1MachineSpec,
+ ),
+}
diff --git a/api/v1alpha6/types_conversion.go b/api/v1alpha6/types_conversion.go
new file mode 100644
index 0000000000..f4cd0d2724
--- /dev/null
+++ b/api/v1alpha6/types_conversion.go
@@ -0,0 +1,445 @@
+/*
+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 (
+ "strings"
+
+ apiconversion "k8s.io/apimachinery/pkg/conversion"
+ "k8s.io/utils/pointer"
+
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
+)
+
+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 Convert_v1beta1_SecurityGroupFilter_To_string(in *infrav1.SecurityGroupFilter, out *string, _ apiconversion.Scope) error {
+ if in.ID != "" {
+ *out = in.ID
+ }
+ return nil
+}
+
+func Convert_v1alpha6_SecurityGroupParam_To_v1beta1_SecurityGroupFilter(in *SecurityGroupParam, out *infrav1.SecurityGroupFilter, s apiconversion.Scope) error {
+ // SecurityGroupParam is replaced by its contained SecurityGroupFilter in v1beta1
+ err := Convert_v1alpha6_SecurityGroupFilter_To_v1beta1_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_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupParam(in *infrav1.SecurityGroupFilter, out *SecurityGroupParam, s apiconversion.Scope) error {
+ // SecurityGroupParam is replaced by its contained SecurityGroupFilter in v1beta1
+ err := Convert_v1beta1_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_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in *SecurityGroupFilter, out *infrav1.SecurityGroupFilter, s apiconversion.Scope) error {
+ if err := autoConvert_v1alpha6_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_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) {
+ // 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 Convert_v1alpha6_NetworkFilter_To_v1beta1_NetworkFilter(in *NetworkFilter, out *infrav1.NetworkFilter, s apiconversion.Scope) error {
+ if err := autoConvert_v1alpha6_NetworkFilter_To_v1beta1_NetworkFilter(in, out, s); err != nil {
+ return err
+ }
+ infrav1.ConvertAllTagsTo(in.Tags, in.TagsAny, in.NotTags, in.NotTagsAny, &out.FilterByNeutronTags)
+ return nil
+}
+
+func Convert_v1beta1_NetworkFilter_To_v1alpha6_NetworkFilter(in *infrav1.NetworkFilter, out *NetworkFilter, s apiconversion.Scope) error {
+ if err := autoConvert_v1beta1_NetworkFilter_To_v1alpha6_NetworkFilter(in, out, s); err != nil {
+ return err
+ }
+ infrav1.ConvertAllTagsFrom(&in.FilterByNeutronTags, &out.Tags, &out.TagsAny, &out.NotTags, &out.NotTagsAny)
+ return nil
+}
+
+/* SubnetParam, SubnetFilter */
+
+func restorev1alpha6SubnetFilter(previous *SubnetFilter, dst *SubnetFilter) {
+ // 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 restorev1beta1Subnets(previous *[]infrav1.SubnetFilter, dst *[]infrav1.SubnetFilter) {
+ if len(*previous) > 1 {
+ *dst = append(*dst, (*previous)[1:]...)
+ }
+}
+
+func Convert_v1alpha6_SubnetParam_To_v1beta1_SubnetFilter(in *SubnetParam, out *infrav1.SubnetFilter, s apiconversion.Scope) error {
+ if err := Convert_v1alpha6_SubnetFilter_To_v1beta1_SubnetFilter(&in.Filter, out, s); err != nil {
+ return err
+ }
+ if in.UUID != "" {
+ out.ID = in.UUID
+ }
+ return nil
+}
+
+func Convert_v1beta1_SubnetFilter_To_v1alpha6_SubnetParam(in *infrav1.SubnetFilter, out *SubnetParam, s apiconversion.Scope) error {
+ if err := Convert_v1beta1_SubnetFilter_To_v1alpha6_SubnetFilter(in, &out.Filter, s); err != nil {
+ return err
+ }
+ out.UUID = in.ID
+
+ 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
+}
+
+/* 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)
+ }
+ }
+
+ if dst.Network != nil && previous.Network != nil {
+ 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.SecurityGroupFilter, 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.SecurityGroupFilter{ID: sgParam.UUID})
+ case sgParam.Name != "":
+ out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupFilter{Name: sgParam.Name})
+ case sgParam.Filter != (SecurityGroupFilter{}):
+ out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupFilter{})
+ outSG := &out.SecurityGroups[len(out.SecurityGroups)-1]
+ if err := Convert_v1alpha6_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(&sgParam.Filter, outSG, s); err != nil {
+ return err
+ }
+ }
+ }
+ for _, id := range in.SecurityGroups {
+ out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupFilter{ID: id})
+ }
+ }
+
+ // 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 {
+ securityGroupParam := &out.SecurityGroupFilters[i]
+ if in.SecurityGroups[i].ID != "" {
+ securityGroupParam.UUID = in.SecurityGroups[i].ID
+ } else {
+ if err := Convert_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(&in.SecurityGroups[i], &securityGroupParam.Filter, s); err != nil {
+ return err
+ }
+ }
+ }
+ }
+
+ if in.Profile != nil {
+ out.Profile = make(map[string]string)
+ if pointer.BoolDeref(in.Profile.OVSHWOffload, false) {
+ (out.Profile)["capabilities"] = "[\"switchdev\"]"
+ }
+ if pointer.BoolDeref(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 = pointer.Bool(true)
+ }
+ }
+ if k == "trusted" && v == trueString {
+ out.TrustedVF = pointer.Bool(true)
+ }
+ }
+ return nil
+}
+
+func Convert_v1beta1_BindingProfile_To_Map_string_To_Interface(in *infrav1.BindingProfile, out map[string]string, _ apiconversion.Scope) error {
+ if pointer.BoolDeref(in.OVSHWOffload, false) {
+ (out)["capabilities"] = "[\"switchdev\"]"
+ }
+ if pointer.BoolDeref(in.TrustedVF, false) {
+ (out)["trusted"] = trueString
+ }
+ return nil
+}
+
+/* FixedIP */
+/* AddressPair */
+/* Instance */
+/* RootVolume */
+/* 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
+ }
+
+ for i, rule := range previous.Rules {
+ dst.Rules[i].SecurityGroupID = rule.SecurityGroupID
+ }
+}
+
+func Convert_v1beta1_SecurityGroupStatus_To_v1alpha6_SecurityGroup(in *infrav1.SecurityGroupStatus, out *SecurityGroup, _ apiconversion.Scope) error {
+ out.ID = in.ID
+ out.Name = in.Name
+ out.Rules = make([]SecurityGroupRule, len(in.Rules))
+ for i, rule := range in.Rules {
+ out.Rules[i] = SecurityGroupRule{
+ ID: rule.ID,
+ Direction: rule.Direction,
+ }
+ if rule.Description != nil {
+ out.Rules[i].Description = *rule.Description
+ }
+ if rule.EtherType != nil {
+ out.Rules[i].EtherType = *rule.EtherType
+ }
+ if rule.PortRangeMin != nil {
+ out.Rules[i].PortRangeMin = *rule.PortRangeMin
+ }
+ if rule.PortRangeMax != nil {
+ out.Rules[i].PortRangeMax = *rule.PortRangeMax
+ }
+ if rule.Protocol != nil {
+ out.Rules[i].Protocol = *rule.Protocol
+ }
+ if rule.RemoteGroupID != nil {
+ out.Rules[i].RemoteGroupID = *rule.RemoteGroupID
+ }
+ if rule.RemoteIPPrefix != nil {
+ out.Rules[i].RemoteIPPrefix = *rule.RemoteIPPrefix
+ }
+ }
+ 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
+ out.Rules = make([]infrav1.SecurityGroupRuleStatus, len(in.Rules))
+ for i, rule := range in.Rules {
+ out.Rules[i] = infrav1.SecurityGroupRuleStatus{
+ ID: rule.ID,
+ Description: pointer.String(rule.Description),
+ Direction: rule.Direction,
+ EtherType: pointer.String(rule.EtherType),
+ PortRangeMin: pointer.Int(rule.PortRangeMin),
+ PortRangeMax: pointer.Int(rule.PortRangeMax),
+ Protocol: pointer.String(rule.Protocol),
+ RemoteGroupID: pointer.String(rule.RemoteGroupID),
+ RemoteIPPrefix: pointer.String(rule.RemoteIPPrefix),
+ }
+ }
+
+ return nil
+}
+
+/* SecurityGroupRule */
+/* APIServerLoadBalancer */
+/* 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
+}
diff --git a/api/v1alpha7/conversion.go b/api/v1alpha7/conversion.go
deleted file mode 100644
index 9048c3e5ef..0000000000
--- a/api/v1alpha7/conversion.go
+++ /dev/null
@@ -1,1002 +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 (
- apiconversion "k8s.io/apimachinery/pkg/conversion"
- "k8s.io/utils/pointer"
- 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 = &OpenStackCluster{}
-
-func restorev1alpha7Bastion(previous **Bastion, dst **Bastion) {
- if *previous != nil && *dst != nil {
- restorev1alpha7MachineSpec(&(*previous).Instance, &(*dst).Instance)
- }
-}
-
-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
- conversion.HashedFilterField[*OpenStackCluster, OpenStackClusterSpec](
- func(s *OpenStackClusterSpec) *OpenStackClusterSpec {
- if s.Bastion != nil {
- f := *s
- f.Bastion = nil
- return &f
- }
- return s
- },
- ),
- ),
- "status": conversion.HashedFieldRestorer(
- func(c *OpenStackCluster) *OpenStackClusterStatus {
- return &c.Status
- },
- restorev1alpha7ClusterStatus,
- ),
-}
-
-func restorev1alpha7SecurityGroup(previous *SecurityGroup, dst *SecurityGroup) {
- if previous == nil || dst == nil {
- return
- }
-
- for i, rule := range previous.Rules {
- dst.Rules[i].SecurityGroupID = rule.SecurityGroupID
- }
-}
-
-func restorev1alpha7ClusterStatus(previous *OpenStackClusterStatus, dst *OpenStackClusterStatus) {
- restorev1alpha7SecurityGroup(previous.ControlPlaneSecurityGroup, dst.ControlPlaneSecurityGroup)
- restorev1alpha7SecurityGroup(previous.WorkerSecurityGroup, dst.WorkerSecurityGroup)
- restorev1alpha7SecurityGroup(previous.BastionSecurityGroup, dst.BastionSecurityGroup)
-}
-
-func restorev1beta1SecurityGroupStatus(previous *infrav1.SecurityGroupStatus, dst *infrav1.SecurityGroupStatus) {
- if previous == nil || dst == nil {
- return
- }
-
- for i := range dst.Rules {
- dstRule := &dst.Rules[i]
-
- // Conversion from scalar to *scalar is lossy for zero values. We need to restore only nil values.
- if dstRule.Description != nil && *dstRule.Description == "" {
- dstRule.Description = previous.Rules[i].Description
- }
- if dstRule.EtherType != nil && *dstRule.EtherType == "" {
- dstRule.EtherType = previous.Rules[i].EtherType
- }
- if dstRule.PortRangeMin != nil && *dstRule.PortRangeMin == 0 {
- dstRule.PortRangeMin = previous.Rules[i].PortRangeMin
- }
- if dstRule.PortRangeMax != nil && *dstRule.PortRangeMax == 0 {
- dstRule.PortRangeMax = previous.Rules[i].PortRangeMax
- }
- if dstRule.Protocol != nil && *dstRule.Protocol == "" {
- dstRule.Protocol = previous.Rules[i].Protocol
- }
- if dstRule.RemoteGroupID != nil && *dstRule.RemoteGroupID == "" {
- dstRule.RemoteGroupID = previous.Rules[i].RemoteGroupID
- }
- if dstRule.RemoteIPPrefix != nil && *dstRule.RemoteIPPrefix == "" {
- dstRule.RemoteIPPrefix = previous.Rules[i].RemoteIPPrefix
- }
- }
-}
-
-func restorev1beta1ClusterStatus(previous *infrav1.OpenStackClusterStatus, dst *infrav1.OpenStackClusterStatus) {
- restorev1beta1SecurityGroupStatus(previous.ControlPlaneSecurityGroup, dst.ControlPlaneSecurityGroup)
- restorev1beta1SecurityGroupStatus(previous.WorkerSecurityGroup, dst.WorkerSecurityGroup)
- restorev1beta1SecurityGroupStatus(previous.BastionSecurityGroup, dst.BastionSecurityGroup)
-
- // ReferencedResources have no equivalent in v1alpha7
- if previous.Bastion != nil {
- dst.Bastion.ReferencedResources = previous.Bastion.ReferencedResources
- }
-
- if previous.Bastion != nil && previous.Bastion.DependentResources.PortsStatus != nil {
- dst.Bastion.DependentResources.PortsStatus = previous.Bastion.DependentResources.PortsStatus
- }
-}
-
-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,
- ),
-}
-
-func restorev1alpha7SubnetFilter(previous *SubnetFilter, dst *SubnetFilter) {
- // 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 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
-}
-
-func restorev1alpha7NetworkFilter(previous *NetworkFilter, dst *NetworkFilter) {
- // 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 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
-}
-
-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 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 {
- 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])
- }
- }
-}
-
-func restorev1beta1MachineSpec(previous *infrav1.OpenStackMachineSpec, dst *infrav1.OpenStackMachineSpec) {
- dst.ServerGroup = previous.ServerGroup
- dst.Image = previous.Image
-
- if len(dst.Ports) == len(previous.Ports) {
- for i := range dst.Ports {
- restorev1beta1Port(&previous.Ports[i], &dst.Ports[i])
- }
- }
-}
-
-func restorev1beta1Port(previous *infrav1.PortOpts, dst *infrav1.PortOpts) {
- if dst.NameSuffix == nil || *dst.NameSuffix == "" {
- dst.NameSuffix = previous.NameSuffix
- }
-
- if dst.Description == nil || *dst.Description == "" {
- dst.Description = previous.Description
- }
-
- if dst.MACAddress == nil || *dst.MACAddress == "" {
- dst.MACAddress = previous.MACAddress
- }
-
- if len(dst.FixedIPs) == len(previous.FixedIPs) {
- for j := range dst.FixedIPs {
- prevFixedIP := &previous.FixedIPs[j]
- dstFixedIP := &dst.FixedIPs[j]
-
- if dstFixedIP.IPAddress == nil || *dstFixedIP.IPAddress == "" {
- dstFixedIP.IPAddress = prevFixedIP.IPAddress
- }
- }
- }
-
- if len(dst.AllowedAddressPairs) == len(previous.AllowedAddressPairs) {
- for j := range dst.AllowedAddressPairs {
- prevAAP := &previous.AllowedAddressPairs[j]
- dstAAP := &dst.AllowedAddressPairs[j]
-
- if dstAAP.MACAddress == nil || *dstAAP.MACAddress == "" {
- dstAAP.MACAddress = prevAAP.MACAddress
- }
- }
- }
-
- if dst.HostID == nil || *dst.HostID == "" {
- dst.HostID = previous.HostID
- }
-
- if dst.VNICType == nil || *dst.VNICType == "" {
- dst.VNICType = previous.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
- }
- }
-}
-
-func restorev1beta1Bastion(previous **infrav1.Bastion, dst **infrav1.Bastion) {
- if *previous != nil && *dst != nil {
- restorev1beta1MachineSpec(&(*previous).Instance, &(*dst).Instance)
- }
-}
-
-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) {
- prevBastion := previous.Bastion
- dstBastion := dst.Bastion
- if prevBastion != nil && dstBastion != nil {
- restorev1beta1MachineSpec(&prevBastion.Instance, &dstBastion.Instance)
- }
-
- // Restore all fields except ID, which should have been copied over in conversion
- dst.ExternalNetwork.Name = previous.ExternalNetwork.Name
- dst.ExternalNetwork.Description = previous.ExternalNetwork.Description
- dst.ExternalNetwork.ProjectID = previous.ExternalNetwork.ProjectID
- dst.ExternalNetwork.Tags = previous.ExternalNetwork.Tags
- dst.ExternalNetwork.TagsAny = previous.ExternalNetwork.TagsAny
- dst.ExternalNetwork.NotTags = previous.ExternalNetwork.NotTags
- dst.ExternalNetwork.NotTagsAny = previous.ExternalNetwork.NotTagsAny
-
- dst.DisableExternalNetwork = previous.DisableExternalNetwork
-
- if len(previous.Subnets) > 1 {
- dst.Subnets = append(dst.Subnets, previous.Subnets[1:]...)
- }
-
- dst.ManagedSubnets = previous.ManagedSubnets
-
- if previous.ManagedSecurityGroups != nil {
- dst.ManagedSecurityGroups.AllNodesSecurityGroupRules = previous.ManagedSecurityGroups.AllNodesSecurityGroupRules
- }
-}
-
-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)
-}
-
-var _ ctrlconversion.Convertible = &OpenStackClusterTemplate{}
-
-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)
-}
-
-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 (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)
-}
-
-var _ ctrlconversion.Convertible = &OpenStackMachine{}
-
-var v1alpha7OpenStackMachineRestorer = conversion.RestorerFor[*OpenStackMachine]{
- "spec": conversion.HashedFieldRestorer(
- func(c *OpenStackMachine) *OpenStackMachineSpec {
- return &c.Spec
- },
- restorev1alpha7MachineSpec,
- ),
-}
-
-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.DependentMachineResources {
- return &c.Status.DependentResources
- },
- ),
-
- // No equivalent in v1alpha7
- "refresources": conversion.UnconditionalFieldRestorer(
- func(c *infrav1.OpenStackMachine) *infrav1.ReferencedMachineResources {
- return &c.Status.ReferencedResources
- },
- ),
-}
-
-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)
-}
-
-var _ ctrlconversion.Convertible = &OpenStackMachineTemplate{}
-
-func restorev1alpha7MachineTemplateSpec(previous *OpenStackMachineTemplateSpec, dst *OpenStackMachineTemplateSpec) {
- restorev1alpha7MachineSpec(&previous.Template.Spec, &dst.Template.Spec)
-}
-
-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 (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)
-}
-
-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 {
- out.ServerGroupID = in.ServerGroup.ID
- }
-
- if in.Image.Name != "" {
- out.Image = in.Image.Name
- }
-
- if in.Image.ID != "" {
- out.ImageUUID = in.Image.ID
- }
-
- 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
-}
-
-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.ServerGroupFilter{ID: in.ServerGroupID}
- } else {
- out.ServerGroup = nil
- }
-
- imageFilter := infrav1.ImageFilter{}
- if in.Image != "" {
- imageFilter.Name = in.Image
- }
- if in.ImageUUID != "" {
- imageFilter.ID = in.ImageUUID
- }
- out.Image = imageFilter
-
- 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_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)
-}
-
-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)
-}
-
-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 in.Instance.ServerGroupID != "" {
- out.Instance.ServerGroup = &infrav1.ServerGroupFilter{ID: in.Instance.ServerGroupID}
- } else {
- out.Instance.ServerGroup = nil
- }
-
- out.FloatingIP = in.Instance.FloatingIP
- 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.Instance.ServerGroup != nil && in.Instance.ServerGroup.ID != "" {
- out.Instance.ServerGroupID = in.Instance.ServerGroup.ID
- }
-
- out.Instance.FloatingIP = in.FloatingIP
- return nil
-}
-
-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.ExternalNetworkID != "" {
- out.ExternalNetwork = infrav1.NetworkFilter{
- ID: in.ExternalNetworkID,
- }
- }
-
- emptySubnet := SubnetFilter{}
- if in.Subnet != emptySubnet {
- subnet := infrav1.SubnetFilter{}
- if err := Convert_v1alpha7_SubnetFilter_To_v1beta1_SubnetFilter(&in.Subnet, &subnet, s); err != nil {
- return err
- }
- out.Subnets = []infrav1.SubnetFilter{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
- }
- }
-
- out.IdentityRef.CloudName = in.CloudName
- if in.IdentityRef != nil {
- out.IdentityRef.Name = in.IdentityRef.Name
- }
-
- return nil
-}
-
-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.ExternalNetwork.ID != "" {
- out.ExternalNetworkID = in.ExternalNetwork.ID
- }
-
- if len(in.Subnets) >= 1 {
- if err := Convert_v1beta1_SubnetFilter_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
- }
-
- out.CloudName = in.IdentityRef.CloudName
- out.IdentityRef = &OpenStackIdentityReference{Name: in.IdentityRef.Name}
-
- return nil
-}
-
-func Convert_v1beta1_SecurityGroupStatus_To_v1alpha7_SecurityGroup(in *infrav1.SecurityGroupStatus, out *SecurityGroup, s apiconversion.Scope) error { //nolint:revive
- out.ID = in.ID
- out.Name = in.Name
- out.Rules = make([]SecurityGroupRule, len(in.Rules))
- for i, rule := range in.Rules {
- out.Rules[i] = SecurityGroupRule{
- ID: rule.ID,
- Direction: rule.Direction,
- }
- if rule.Description != nil {
- out.Rules[i].Description = *rule.Description
- }
- if rule.EtherType != nil {
- out.Rules[i].EtherType = *rule.EtherType
- }
- if rule.PortRangeMin != nil {
- out.Rules[i].PortRangeMin = *rule.PortRangeMin
- }
- if rule.PortRangeMax != nil {
- out.Rules[i].PortRangeMax = *rule.PortRangeMax
- }
- if rule.Protocol != nil {
- out.Rules[i].Protocol = *rule.Protocol
- }
- if rule.RemoteGroupID != nil {
- out.Rules[i].RemoteGroupID = *rule.RemoteGroupID
- }
- if rule.RemoteIPPrefix != nil {
- out.Rules[i].RemoteIPPrefix = *rule.RemoteIPPrefix
- }
- }
- return nil
-}
-
-func Convert_v1alpha7_SecurityGroup_To_v1beta1_SecurityGroupStatus(in *SecurityGroup, out *infrav1.SecurityGroupStatus, s apiconversion.Scope) error { //nolint:revive
- out.ID = in.ID
- out.Name = in.Name
- out.Rules = make([]infrav1.SecurityGroupRuleStatus, len(in.Rules))
- for i, rule := range in.Rules {
- out.Rules[i] = infrav1.SecurityGroupRuleStatus{
- ID: rule.ID,
- Description: pointer.String(rule.Description),
- Direction: rule.Direction,
- EtherType: pointer.String(rule.EtherType),
- PortRangeMin: pointer.Int(rule.PortRangeMin),
- PortRangeMax: pointer.Int(rule.PortRangeMax),
- Protocol: pointer.String(rule.Protocol),
- RemoteGroupID: pointer.String(rule.RemoteGroupID),
- RemoteIPPrefix: pointer.String(rule.RemoteIPPrefix),
- }
- }
-
- return nil
-}
-
-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_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(in *infrav1.OpenStackClusterStatus, out *OpenStackClusterStatus, s apiconversion.Scope) error {
- return autoConvert_v1beta1_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(in, out, s)
-}
-
-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
- }
-
- if len(in.SecurityGroupFilters) > 0 {
- out.SecurityGroups = make([]infrav1.SecurityGroupFilter, len(in.SecurityGroupFilters))
- for i := range in.SecurityGroupFilters {
- if err := Convert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(&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
- }
-
- if len(in.SecurityGroups) > 0 {
- out.SecurityGroupFilters = make([]SecurityGroupFilter, len(in.SecurityGroups))
- for i := range in.SecurityGroups {
- if err := Convert_v1beta1_SecurityGroupFilter_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
-}
-
-func Convert_v1beta1_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityReference(in *infrav1.OpenStackIdentityReference, out *OpenStackIdentityReference, _ apiconversion.Scope) error {
- out.Name = in.Name
- return nil
-}
-
-func Convert_v1alpha7_SubnetFilter_To_v1beta1_SubnetFilter(in *SubnetFilter, out *infrav1.SubnetFilter, s apiconversion.Scope) error {
- if err := autoConvert_v1alpha7_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_v1alpha7_SubnetFilter(in *infrav1.SubnetFilter, out *SubnetFilter, s apiconversion.Scope) error {
- if err := autoConvert_v1beta1_SubnetFilter_To_v1alpha7_SubnetFilter(in, out, s); err != nil {
- return err
- }
- infrav1.ConvertAllTagsFrom(&in.FilterByNeutronTags, &out.Tags, &out.TagsAny, &out.NotTags, &out.NotTagsAny)
- return nil
-}
-
-func Convert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in *SecurityGroupFilter, out *infrav1.SecurityGroupFilter, s apiconversion.Scope) error {
- if err := autoConvert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in, out, s); err != nil {
- return err
- }
- infrav1.ConvertAllTagsTo(in.Tags, in.TagsAny, in.NotTags, in.NotTagsAny, &out.FilterByNeutronTags)
- return nil
-}
-
-func Convert_v1beta1_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in *infrav1.SecurityGroupFilter, out *SecurityGroupFilter, s apiconversion.Scope) error {
- if err := autoConvert_v1beta1_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in, out, s); err != nil {
- return err
- }
- infrav1.ConvertAllTagsFrom(&in.FilterByNeutronTags, &out.Tags, &out.TagsAny, &out.NotTags, &out.NotTagsAny)
- return nil
-}
-
-func Convert_v1alpha7_RouterFilter_To_v1beta1_RouterFilter(in *RouterFilter, out *infrav1.RouterFilter, s apiconversion.Scope) error {
- if err := autoConvert_v1alpha7_RouterFilter_To_v1beta1_RouterFilter(in, out, s); err != nil {
- return err
- }
- infrav1.ConvertAllTagsTo(in.Tags, in.TagsAny, in.NotTags, in.NotTagsAny, &out.FilterByNeutronTags)
- return nil
-}
-
-func Convert_v1beta1_RouterFilter_To_v1alpha7_RouterFilter(in *infrav1.RouterFilter, out *RouterFilter, s apiconversion.Scope) error {
- if err := autoConvert_v1beta1_RouterFilter_To_v1alpha7_RouterFilter(in, out, s); err != nil {
- return err
- }
- infrav1.ConvertAllTagsFrom(&in.FilterByNeutronTags, &out.Tags, &out.TagsAny, &out.NotTags, &out.NotTagsAny)
- return nil
-}
-
-func Convert_v1alpha7_NetworkFilter_To_v1beta1_NetworkFilter(in *NetworkFilter, out *infrav1.NetworkFilter, s apiconversion.Scope) error {
- if err := autoConvert_v1alpha7_NetworkFilter_To_v1beta1_NetworkFilter(in, out, s); err != nil {
- return err
- }
- infrav1.ConvertAllTagsTo(in.Tags, in.TagsAny, in.NotTags, in.NotTagsAny, &out.FilterByNeutronTags)
- return nil
-}
-
-func Convert_v1beta1_NetworkFilter_To_v1alpha7_NetworkFilter(in *infrav1.NetworkFilter, out *NetworkFilter, s apiconversion.Scope) error {
- if err := autoConvert_v1beta1_NetworkFilter_To_v1alpha7_NetworkFilter(in, out, s); err != nil {
- return err
- }
- infrav1.ConvertAllTagsFrom(&in.FilterByNeutronTags, &out.Tags, &out.TagsAny, &out.NotTags, &out.NotTagsAny)
- return nil
-}
diff --git a/api/v1alpha7/openstackcluster_conversion.go b/api/v1alpha7/openstackcluster_conversion.go
new file mode 100644
index 0000000000..16a13aa601
--- /dev/null
+++ b/api/v1alpha7/openstackcluster_conversion.go
@@ -0,0 +1,352 @@
+/*
+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 = &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
+ conversion.HashedFilterField[*OpenStackCluster, OpenStackClusterSpec](
+ func(s *OpenStackClusterSpec) *OpenStackClusterSpec {
+ if s.Bastion != nil {
+ f := *s
+ f.Bastion = nil
+ 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) {
+ prevBastion := previous.Bastion
+ dstBastion := dst.Bastion
+ if prevBastion != nil && dstBastion != nil {
+ restorev1beta1MachineSpec(&prevBastion.Instance, &dstBastion.Instance)
+ }
+
+ // Restore all fields except ID, which should have been copied over in conversion
+ dst.ExternalNetwork.Name = previous.ExternalNetwork.Name
+ dst.ExternalNetwork.Description = previous.ExternalNetwork.Description
+ dst.ExternalNetwork.ProjectID = previous.ExternalNetwork.ProjectID
+ dst.ExternalNetwork.Tags = previous.ExternalNetwork.Tags
+ dst.ExternalNetwork.TagsAny = previous.ExternalNetwork.TagsAny
+ dst.ExternalNetwork.NotTags = previous.ExternalNetwork.NotTags
+ dst.ExternalNetwork.NotTagsAny = previous.ExternalNetwork.NotTagsAny
+
+ dst.DisableExternalNetwork = previous.DisableExternalNetwork
+
+ if len(previous.Subnets) > 1 {
+ dst.Subnets = append(dst.Subnets, previous.Subnets[1:]...)
+ }
+
+ dst.ManagedSubnets = previous.ManagedSubnets
+
+ if previous.ManagedSecurityGroups != nil {
+ dst.ManagedSecurityGroups.AllNodesSecurityGroupRules = previous.ManagedSecurityGroups.AllNodesSecurityGroupRules
+ }
+}
+
+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.ExternalNetworkID != "" {
+ out.ExternalNetwork = infrav1.NetworkFilter{
+ ID: in.ExternalNetworkID,
+ }
+ }
+
+ emptySubnet := SubnetFilter{}
+ if in.Subnet != emptySubnet {
+ subnet := infrav1.SubnetFilter{}
+ if err := Convert_v1alpha7_SubnetFilter_To_v1beta1_SubnetFilter(&in.Subnet, &subnet, s); err != nil {
+ return err
+ }
+ out.Subnets = []infrav1.SubnetFilter{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
+ }
+ }
+
+ out.IdentityRef.CloudName = in.CloudName
+ if in.IdentityRef != nil {
+ out.IdentityRef.Name = in.IdentityRef.Name
+ }
+
+ return nil
+}
+
+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.ExternalNetwork.ID != "" {
+ out.ExternalNetworkID = in.ExternalNetwork.ID
+ }
+
+ if len(in.Subnets) >= 1 {
+ if err := Convert_v1beta1_SubnetFilter_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
+ }
+
+ out.CloudName = in.IdentityRef.CloudName
+ out.IdentityRef = &OpenStackIdentityReference{Name: in.IdentityRef.Name}
+
+ 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) {
+ restorev1beta1SecurityGroupStatus(previous.ControlPlaneSecurityGroup, dst.ControlPlaneSecurityGroup)
+ restorev1beta1SecurityGroupStatus(previous.WorkerSecurityGroup, dst.WorkerSecurityGroup)
+ restorev1beta1SecurityGroupStatus(previous.BastionSecurityGroup, dst.BastionSecurityGroup)
+
+ // ReferencedResources have no equivalent in v1alpha7
+ if previous.Bastion != nil {
+ dst.Bastion.ReferencedResources = previous.Bastion.ReferencedResources
+ }
+
+ if previous.Bastion != nil && previous.Bastion.DependentResources.PortsStatus != nil {
+ dst.Bastion.DependentResources.PortsStatus = previous.Bastion.DependentResources.PortsStatus
+ }
+}
+
+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 {
+ restorev1alpha7MachineSpec(&(*previous).Instance, &(*dst).Instance)
+ }
+}
+
+func restorev1beta1Bastion(previous **infrav1.Bastion, dst **infrav1.Bastion) {
+ if *previous != nil && *dst != nil {
+ restorev1beta1MachineSpec(&(*previous).Instance, &(*dst).Instance)
+ }
+}
+
+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 in.Instance.ServerGroupID != "" {
+ out.Instance.ServerGroup = &infrav1.ServerGroupFilter{ID: in.Instance.ServerGroupID}
+ } else {
+ out.Instance.ServerGroup = nil
+ }
+
+ out.FloatingIP = in.Instance.FloatingIP
+ 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.Instance.ServerGroup != nil && in.Instance.ServerGroup.ID != "" {
+ out.Instance.ServerGroupID = in.Instance.ServerGroup.ID
+ }
+
+ out.Instance.FloatingIP = in.FloatingIP
+ return nil
+}
+
+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/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/openstackmachine_conversion.go b/api/v1alpha7/openstackmachine_conversion.go
new file mode 100644
index 0000000000..90242c6596
--- /dev/null
+++ b/api/v1alpha7/openstackmachine_conversion.go
@@ -0,0 +1,231 @@
+/*
+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,
+ ),
+}
+
+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.DependentMachineResources {
+ return &c.Status.DependentResources
+ },
+ ),
+
+ // No equivalent in v1alpha7
+ "refresources": conversion.UnconditionalFieldRestorer(
+ func(c *infrav1.OpenStackMachine) *infrav1.ReferencedMachineResources {
+ return &c.Status.ReferencedResources
+ },
+ ),
+}
+
+/* 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 {
+ 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])
+ }
+ }
+}
+
+func restorev1beta1MachineSpec(previous *infrav1.OpenStackMachineSpec, dst *infrav1.OpenStackMachineSpec) {
+ dst.ServerGroup = previous.ServerGroup
+ dst.Image = previous.Image
+
+ if len(dst.Ports) == len(previous.Ports) {
+ for i := range dst.Ports {
+ restorev1beta1Port(&previous.Ports[i], &dst.Ports[i])
+ }
+ }
+}
+
+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.ServerGroupFilter{ID: in.ServerGroupID}
+ } else {
+ out.ServerGroup = nil
+ }
+
+ imageFilter := infrav1.ImageFilter{}
+ if in.Image != "" {
+ imageFilter.Name = in.Image
+ }
+ if in.ImageUUID != "" {
+ imageFilter.ID = in.ImageUUID
+ }
+ out.Image = imageFilter
+
+ 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 {
+ out.ServerGroupID = in.ServerGroup.ID
+ }
+
+ if in.Image.Name != "" {
+ out.Image = in.Image.Name
+ }
+
+ if in.Image.ID != "" {
+ out.ImageUUID = in.Image.ID
+ }
+
+ 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/openstackmachinetemplate_conversion.go b/api/v1alpha7/openstackmachinetemplate_conversion.go
new file mode 100644
index 0000000000..f110066467
--- /dev/null
+++ b/api/v1alpha7/openstackmachinetemplate_conversion.go
@@ -0,0 +1,82 @@
+/*
+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) {
+ restorev1alpha7MachineSpec(&previous.Template.Spec, &dst.Template.Spec)
+}
diff --git a/api/v1alpha7/types_conversion.go b/api/v1alpha7/types_conversion.go
new file mode 100644
index 0000000000..f18f77269d
--- /dev/null
+++ b/api/v1alpha7/types_conversion.go
@@ -0,0 +1,376 @@
+/*
+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"
+ "k8s.io/utils/pointer"
+
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
+)
+
+/* 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
+}
+
+func restorev1alpha7SecurityGroup(previous *SecurityGroup, dst *SecurityGroup) {
+ if previous == nil || dst == nil {
+ return
+ }
+
+ for i, rule := range previous.Rules {
+ dst.Rules[i].SecurityGroupID = rule.SecurityGroupID
+ }
+}
+
+func Convert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in *SecurityGroupFilter, out *infrav1.SecurityGroupFilter, s apiconversion.Scope) error {
+ if err := autoConvert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in, out, s); err != nil {
+ return err
+ }
+ infrav1.ConvertAllTagsTo(in.Tags, in.TagsAny, in.NotTags, in.NotTagsAny, &out.FilterByNeutronTags)
+ return nil
+}
+
+func Convert_v1beta1_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in *infrav1.SecurityGroupFilter, out *SecurityGroupFilter, s apiconversion.Scope) error {
+ if err := autoConvert_v1beta1_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in, out, s); err != nil {
+ return err
+ }
+ infrav1.ConvertAllTagsFrom(&in.FilterByNeutronTags, &out.Tags, &out.TagsAny, &out.NotTags, &out.NotTagsAny)
+ return nil
+}
+
+/* NetworkFilter */
+
+func restorev1alpha7NetworkFilter(previous *NetworkFilter, dst *NetworkFilter) {
+ // 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 Convert_v1alpha7_NetworkFilter_To_v1beta1_NetworkFilter(in *NetworkFilter, out *infrav1.NetworkFilter, s apiconversion.Scope) error {
+ if err := autoConvert_v1alpha7_NetworkFilter_To_v1beta1_NetworkFilter(in, out, s); err != nil {
+ return err
+ }
+ infrav1.ConvertAllTagsTo(in.Tags, in.TagsAny, in.NotTags, in.NotTagsAny, &out.FilterByNeutronTags)
+ return nil
+}
+
+func Convert_v1beta1_NetworkFilter_To_v1alpha7_NetworkFilter(in *infrav1.NetworkFilter, out *NetworkFilter, s apiconversion.Scope) error {
+ if err := autoConvert_v1beta1_NetworkFilter_To_v1alpha7_NetworkFilter(in, out, s); err != nil {
+ return err
+ }
+ infrav1.ConvertAllTagsFrom(&in.FilterByNeutronTags, &out.Tags, &out.TagsAny, &out.NotTags, &out.NotTagsAny)
+ return nil
+}
+
+/* SubnetFilter */
+
+func restorev1alpha7SubnetFilter(previous *SubnetFilter, dst *SubnetFilter) {
+ // 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 Convert_v1alpha7_SubnetFilter_To_v1beta1_SubnetFilter(in *SubnetFilter, out *infrav1.SubnetFilter, s apiconversion.Scope) error {
+ if err := autoConvert_v1alpha7_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_v1alpha7_SubnetFilter(in *infrav1.SubnetFilter, out *SubnetFilter, s apiconversion.Scope) error {
+ if err := autoConvert_v1beta1_SubnetFilter_To_v1alpha7_SubnetFilter(in, out, s); err != nil {
+ return err
+ }
+ infrav1.ConvertAllTagsFrom(&in.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
+}
+
+func Convert_v1alpha7_RouterFilter_To_v1beta1_RouterFilter(in *RouterFilter, out *infrav1.RouterFilter, s apiconversion.Scope) error {
+ if err := autoConvert_v1alpha7_RouterFilter_To_v1beta1_RouterFilter(in, out, s); err != nil {
+ return err
+ }
+ infrav1.ConvertAllTagsTo(in.Tags, in.TagsAny, in.NotTags, in.NotTagsAny, &out.FilterByNeutronTags)
+ return nil
+}
+
+func Convert_v1beta1_RouterFilter_To_v1alpha7_RouterFilter(in *infrav1.RouterFilter, out *RouterFilter, s apiconversion.Scope) error {
+ if err := autoConvert_v1beta1_RouterFilter_To_v1alpha7_RouterFilter(in, out, s); err != nil {
+ return err
+ }
+ infrav1.ConvertAllTagsFrom(&in.FilterByNeutronTags, &out.Tags, &out.TagsAny, &out.NotTags, &out.NotTagsAny)
+ return nil
+}
+
+func restorev1beta1SecurityGroupStatus(previous *infrav1.SecurityGroupStatus, dst *infrav1.SecurityGroupStatus) {
+ if previous == nil || dst == nil {
+ return
+ }
+
+ for i := range dst.Rules {
+ dstRule := &dst.Rules[i]
+
+ // Conversion from scalar to *scalar is lossy for zero values. We need to restore only nil values.
+ if dstRule.Description != nil && *dstRule.Description == "" {
+ dstRule.Description = previous.Rules[i].Description
+ }
+ if dstRule.EtherType != nil && *dstRule.EtherType == "" {
+ dstRule.EtherType = previous.Rules[i].EtherType
+ }
+ if dstRule.PortRangeMin != nil && *dstRule.PortRangeMin == 0 {
+ dstRule.PortRangeMin = previous.Rules[i].PortRangeMin
+ }
+ if dstRule.PortRangeMax != nil && *dstRule.PortRangeMax == 0 {
+ dstRule.PortRangeMax = previous.Rules[i].PortRangeMax
+ }
+ if dstRule.Protocol != nil && *dstRule.Protocol == "" {
+ dstRule.Protocol = previous.Rules[i].Protocol
+ }
+ if dstRule.RemoteGroupID != nil && *dstRule.RemoteGroupID == "" {
+ dstRule.RemoteGroupID = previous.Rules[i].RemoteGroupID
+ }
+ if dstRule.RemoteIPPrefix != nil && *dstRule.RemoteIPPrefix == "" {
+ dstRule.RemoteIPPrefix = previous.Rules[i].RemoteIPPrefix
+ }
+ }
+}
+
+/* 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) {
+ if dst.NameSuffix == nil || *dst.NameSuffix == "" {
+ dst.NameSuffix = previous.NameSuffix
+ }
+
+ if dst.Description == nil || *dst.Description == "" {
+ dst.Description = previous.Description
+ }
+
+ if dst.MACAddress == nil || *dst.MACAddress == "" {
+ dst.MACAddress = previous.MACAddress
+ }
+
+ if len(dst.FixedIPs) == len(previous.FixedIPs) {
+ for j := range dst.FixedIPs {
+ prevFixedIP := &previous.FixedIPs[j]
+ dstFixedIP := &dst.FixedIPs[j]
+
+ if dstFixedIP.IPAddress == nil || *dstFixedIP.IPAddress == "" {
+ dstFixedIP.IPAddress = prevFixedIP.IPAddress
+ }
+ }
+ }
+
+ if len(dst.AllowedAddressPairs) == len(previous.AllowedAddressPairs) {
+ for j := range dst.AllowedAddressPairs {
+ prevAAP := &previous.AllowedAddressPairs[j]
+ dstAAP := &dst.AllowedAddressPairs[j]
+
+ if dstAAP.MACAddress == nil || *dstAAP.MACAddress == "" {
+ dstAAP.MACAddress = prevAAP.MACAddress
+ }
+ }
+ }
+
+ if dst.HostID == nil || *dst.HostID == "" {
+ dst.HostID = previous.HostID
+ }
+
+ if dst.VNICType == nil || *dst.VNICType == "" {
+ dst.VNICType = previous.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
+ }
+ }
+}
+
+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
+ }
+
+ if len(in.SecurityGroupFilters) > 0 {
+ out.SecurityGroups = make([]infrav1.SecurityGroupFilter, len(in.SecurityGroupFilters))
+ for i := range in.SecurityGroupFilters {
+ if err := Convert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(&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
+ }
+
+ if len(in.SecurityGroups) > 0 {
+ out.SecurityGroupFilters = make([]SecurityGroupFilter, len(in.SecurityGroups))
+ for i := range in.SecurityGroups {
+ if err := Convert_v1beta1_SecurityGroupFilter_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
+}
+
+/* SecurityGroup */
+
+func Convert_v1alpha7_SecurityGroup_To_v1beta1_SecurityGroupStatus(in *SecurityGroup, out *infrav1.SecurityGroupStatus, _ apiconversion.Scope) error {
+ out.ID = in.ID
+ out.Name = in.Name
+ out.Rules = make([]infrav1.SecurityGroupRuleStatus, len(in.Rules))
+ for i, rule := range in.Rules {
+ out.Rules[i] = infrav1.SecurityGroupRuleStatus{
+ ID: rule.ID,
+ Description: pointer.String(rule.Description),
+ Direction: rule.Direction,
+ EtherType: pointer.String(rule.EtherType),
+ PortRangeMin: pointer.Int(rule.PortRangeMin),
+ PortRangeMax: pointer.Int(rule.PortRangeMax),
+ Protocol: pointer.String(rule.Protocol),
+ RemoteGroupID: pointer.String(rule.RemoteGroupID),
+ RemoteIPPrefix: pointer.String(rule.RemoteIPPrefix),
+ }
+ }
+
+ 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
+ out.Rules = make([]SecurityGroupRule, len(in.Rules))
+ for i, rule := range in.Rules {
+ out.Rules[i] = SecurityGroupRule{
+ ID: rule.ID,
+ Direction: rule.Direction,
+ }
+ if rule.Description != nil {
+ out.Rules[i].Description = *rule.Description
+ }
+ if rule.EtherType != nil {
+ out.Rules[i].EtherType = *rule.EtherType
+ }
+ if rule.PortRangeMin != nil {
+ out.Rules[i].PortRangeMin = *rule.PortRangeMin
+ }
+ if rule.PortRangeMax != nil {
+ out.Rules[i].PortRangeMax = *rule.PortRangeMax
+ }
+ if rule.Protocol != nil {
+ out.Rules[i].Protocol = *rule.Protocol
+ }
+ if rule.RemoteGroupID != nil {
+ out.Rules[i].RemoteGroupID = *rule.RemoteGroupID
+ }
+ if rule.RemoteIPPrefix != nil {
+ out.Rules[i].RemoteIPPrefix = *rule.RemoteIPPrefix
+ }
+ }
+ 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
+}
From 392edfddc9d96ce2aba5fe5b66edd01fbeeb45a2 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Tue, 5 Mar 2024 13:28:21 +0000
Subject: [PATCH 099/180] v1alpha7 restorev1beta1ClusterSpec should not restore
Bastion
The bastion has a separate restorer.
---
api/v1alpha7/openstackcluster_conversion.go | 8 +-------
api/v1alpha7/openstackmachine_conversion.go | 1 -
2 files changed, 1 insertion(+), 8 deletions(-)
diff --git a/api/v1alpha7/openstackcluster_conversion.go b/api/v1alpha7/openstackcluster_conversion.go
index 16a13aa601..5761f11f8c 100644
--- a/api/v1alpha7/openstackcluster_conversion.go
+++ b/api/v1alpha7/openstackcluster_conversion.go
@@ -74,7 +74,6 @@ var v1alpha7OpenStackClusterRestorer = conversion.RestorerFor[*OpenStackCluster]
return &c.Spec
},
restorev1alpha7ClusterSpec,
-
// Filter out Bastion, which is restored separately
conversion.HashedFilterField[*OpenStackCluster, OpenStackClusterSpec](
func(s *OpenStackClusterSpec) *OpenStackClusterSpec {
@@ -107,7 +106,6 @@ var v1beta1OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStackC
return &c.Spec
},
restorev1beta1ClusterSpec,
-
// Filter out Bastion, which is restored separately
conversion.HashedFilterField[*infrav1.OpenStackCluster, infrav1.OpenStackClusterSpec](
func(s *infrav1.OpenStackClusterSpec) *infrav1.OpenStackClusterSpec {
@@ -167,11 +165,7 @@ func restorev1alpha7ClusterSpec(previous *OpenStackClusterSpec, dst *OpenStackCl
}
func restorev1beta1ClusterSpec(previous *infrav1.OpenStackClusterSpec, dst *infrav1.OpenStackClusterSpec) {
- prevBastion := previous.Bastion
- dstBastion := dst.Bastion
- if prevBastion != nil && dstBastion != nil {
- restorev1beta1MachineSpec(&prevBastion.Instance, &dstBastion.Instance)
- }
+ // Bastion is restored separately
// Restore all fields except ID, which should have been copied over in conversion
dst.ExternalNetwork.Name = previous.ExternalNetwork.Name
diff --git a/api/v1alpha7/openstackmachine_conversion.go b/api/v1alpha7/openstackmachine_conversion.go
index 90242c6596..575f8ad40b 100644
--- a/api/v1alpha7/openstackmachine_conversion.go
+++ b/api/v1alpha7/openstackmachine_conversion.go
@@ -81,7 +81,6 @@ var v1beta1OpenStackMachineRestorer = conversion.RestorerFor[*infrav1.OpenStackM
return &c.Status.DependentResources
},
),
-
// No equivalent in v1alpha7
"refresources": conversion.UnconditionalFieldRestorer(
func(c *infrav1.OpenStackMachine) *infrav1.ReferencedMachineResources {
From a81ef96d6da8e0554f563591c932dbc6d48636b3 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Tue, 5 Mar 2024 13:29:15 +0000
Subject: [PATCH 100/180] v1alpha6: Simplify v1alpha6 cluster restorer
This is a breaking change, although it should not have any negative
effects in practise.
The v1alpha6 cluster restorer had become too complex with too many
individual fields. This change reduces the number of fields to be
consistent with the v1alpha7 restorer.
With this change, an object stored as v1alpha6 with previous v1beta1
annotations could have fields in its spec restored to a semantically
equivalent but slightly different serialisation when converted to
v1beta1. Differences in the bastion and status are not affected.
In practise this should not matter for 2 reasons:
* The storage version is v1beta1, so the annotation should have been
freshly generated in the new format anyway.
* Even if it were not, and the v1alpha6 were under external control, the
external controller would observe a difference and restore it to the
previous version. It would then converted again with the new
annotation.
Note that if the object is not under external control these differences
don't matter anyway.
---
api/v1alpha6/openstackcluster_conversion.go | 84 ++++++++++---------
.../openstackclustertemplate_conversion.go | 50 ++---------
api/v1alpha6/types_conversion.go | 6 --
3 files changed, 52 insertions(+), 88 deletions(-)
diff --git a/api/v1alpha6/openstackcluster_conversion.go b/api/v1alpha6/openstackcluster_conversion.go
index 57499183a9..b8aac5aa5a 100644
--- a/api/v1alpha6/openstackcluster_conversion.go
+++ b/api/v1alpha6/openstackcluster_conversion.go
@@ -80,43 +80,28 @@ var v1alpha6OpenStackClusterRestorer = conversion.RestorerFor[*OpenStackCluster]
}
var v1beta1OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStackCluster]{
- "externalNetwork": conversion.UnconditionalFieldRestorer(
- func(c *infrav1.OpenStackCluster) *infrav1.NetworkFilter {
- return &c.Spec.ExternalNetwork
- },
- ),
- "disableExternalNetwork": conversion.UnconditionalFieldRestorer(
- func(c *infrav1.OpenStackCluster) *bool {
- return &c.Spec.DisableExternalNetwork
- },
- ),
- "router": conversion.UnconditionalFieldRestorer(
- func(c *infrav1.OpenStackCluster) **infrav1.RouterFilter {
- return &c.Spec.Router
- },
- ),
- "networkMtu": conversion.UnconditionalFieldRestorer(
- func(c *infrav1.OpenStackCluster) *int {
- return &c.Spec.NetworkMTU
- },
- ),
"bastion": conversion.HashedFieldRestorer(
func(c *infrav1.OpenStackCluster) **infrav1.Bastion {
return &c.Spec.Bastion
},
restorev1beta1Bastion,
),
- "subnets": conversion.HashedFieldRestorer(
- func(c *infrav1.OpenStackCluster) *[]infrav1.SubnetFilter {
- return &c.Spec.Subnets
- },
- restorev1beta1Subnets,
- ),
- "allNodesSecurityGroupRules": conversion.HashedFieldRestorer(
- func(c *infrav1.OpenStackCluster) *infrav1.ManagedSecurityGroups {
- return c.Spec.ManagedSecurityGroups
+ "spec": conversion.HashedFieldRestorer(
+ func(c *infrav1.OpenStackCluster) *infrav1.OpenStackClusterSpec {
+ return &c.Spec
},
- restorev1beta1ManagedSecurityGroups,
+ 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 {
@@ -124,11 +109,6 @@ var v1beta1OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStackC
},
restorev1beta1ClusterStatus,
),
- "managedSubnets": conversion.UnconditionalFieldRestorer(
- func(c *infrav1.OpenStackCluster) *[]infrav1.SubnetSpec {
- return &c.Spec.ManagedSubnets
- },
- ),
}
/* OpenStackClusterSpec */
@@ -179,6 +159,34 @@ func restorev1alpha6ClusterSpec(previous *OpenStackClusterSpec, dst *OpenStackCl
restorev1alpha6NetworkFilter(&previous.Network, &dst.Network)
}
+func restorev1beta1ClusterSpec(previous *infrav1.OpenStackClusterSpec, dst *infrav1.OpenStackClusterSpec) {
+ // Bastion is restored separately
+
+ // Restore all fields except ID, which should have been copied over in conversion
+ dst.ExternalNetwork.Name = previous.ExternalNetwork.Name
+ dst.ExternalNetwork.Description = previous.ExternalNetwork.Description
+ dst.ExternalNetwork.ProjectID = previous.ExternalNetwork.ProjectID
+ dst.ExternalNetwork.Tags = previous.ExternalNetwork.Tags
+ dst.ExternalNetwork.TagsAny = previous.ExternalNetwork.TagsAny
+ dst.ExternalNetwork.NotTags = previous.ExternalNetwork.NotTags
+ dst.ExternalNetwork.NotTagsAny = previous.ExternalNetwork.NotTagsAny
+
+ // Restore fields not present in v1alpha6
+ dst.Router = previous.Router
+ dst.NetworkMTU = previous.NetworkMTU
+ dst.DisableExternalNetwork = previous.DisableExternalNetwork
+
+ if len(previous.Subnets) > 1 {
+ dst.Subnets = append(dst.Subnets, previous.Subnets[1:]...)
+ }
+
+ dst.ManagedSubnets = previous.ManagedSubnets
+
+ if previous.ManagedSecurityGroups != nil {
+ dst.ManagedSecurityGroups.AllNodesSecurityGroupRules = previous.ManagedSecurityGroups.AllNodesSecurityGroupRules
+ }
+}
+
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 {
@@ -392,9 +400,3 @@ func Convert_v1beta1_Bastion_To_v1alpha6_Bastion(in *infrav1.Bastion, out *Basti
out.Instance.FloatingIP = in.FloatingIP
return nil
}
-
-/* ManagedSecurityGroups */
-
-func restorev1beta1ManagedSecurityGroups(previous *infrav1.ManagedSecurityGroups, dst *infrav1.ManagedSecurityGroups) {
- dst.AllNodesSecurityGroupRules = previous.AllNodesSecurityGroupRules
-}
diff --git a/api/v1alpha6/openstackclustertemplate_conversion.go b/api/v1alpha6/openstackclustertemplate_conversion.go
index cf7a3ffead..7ded0fc0de 100644
--- a/api/v1alpha6/openstackclustertemplate_conversion.go
+++ b/api/v1alpha6/openstackclustertemplate_conversion.go
@@ -69,47 +69,15 @@ var v1alpha6OpenStackClusterTemplateRestorer = conversion.RestorerFor[*OpenStack
}
var v1beta1OpenStackClusterTemplateRestorer = conversion.RestorerFor[*infrav1.OpenStackClusterTemplate]{
- "externalNetwork": conversion.UnconditionalFieldRestorer(
- func(c *infrav1.OpenStackClusterTemplate) *infrav1.NetworkFilter {
- return &c.Spec.Template.Spec.ExternalNetwork
- },
- ),
- "disableExternalNetwork": conversion.UnconditionalFieldRestorer(
- func(c *infrav1.OpenStackClusterTemplate) *bool {
- return &c.Spec.Template.Spec.DisableExternalNetwork
- },
- ),
- "router": conversion.UnconditionalFieldRestorer(
- func(c *infrav1.OpenStackClusterTemplate) **infrav1.RouterFilter {
- return &c.Spec.Template.Spec.Router
- },
- ),
- "networkMtu": conversion.UnconditionalFieldRestorer(
- func(c *infrav1.OpenStackClusterTemplate) *int {
- return &c.Spec.Template.Spec.NetworkMTU
- },
- ),
- "bastion": conversion.HashedFieldRestorer(
- func(c *infrav1.OpenStackClusterTemplate) **infrav1.Bastion {
- return &c.Spec.Template.Spec.Bastion
- },
- restorev1beta1Bastion,
- ),
- "subnets": conversion.HashedFieldRestorer(
- func(c *infrav1.OpenStackClusterTemplate) *[]infrav1.SubnetFilter {
- return &c.Spec.Template.Spec.Subnets
- },
- restorev1beta1Subnets,
- ),
- "allNodesSecurityGroupRules": conversion.HashedFieldRestorer(
- func(c *infrav1.OpenStackClusterTemplate) *infrav1.ManagedSecurityGroups {
- return c.Spec.Template.Spec.ManagedSecurityGroups
- },
- restorev1beta1ManagedSecurityGroups,
- ),
- "managedSubnets": conversion.UnconditionalFieldRestorer(
- func(c *infrav1.OpenStackClusterTemplate) *[]infrav1.SubnetSpec {
- return &c.Spec.Template.Spec.ManagedSubnets
+ "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/types_conversion.go b/api/v1alpha6/types_conversion.go
index f4cd0d2724..c43f8a23ac 100644
--- a/api/v1alpha6/types_conversion.go
+++ b/api/v1alpha6/types_conversion.go
@@ -137,12 +137,6 @@ func restorev1alpha6SubnetFilter(previous *SubnetFilter, dst *SubnetFilter) {
dst.NotTagsAny = previous.NotTagsAny
}
-func restorev1beta1Subnets(previous *[]infrav1.SubnetFilter, dst *[]infrav1.SubnetFilter) {
- if len(*previous) > 1 {
- *dst = append(*dst, (*previous)[1:]...)
- }
-}
-
func Convert_v1alpha6_SubnetParam_To_v1beta1_SubnetFilter(in *SubnetParam, out *infrav1.SubnetFilter, s apiconversion.Scope) error {
if err := Convert_v1alpha6_SubnetFilter_To_v1beta1_SubnetFilter(&in.Filter, out, s); err != nil {
return err
From 30ba121d773b5665798500828e4ffcc467afbc15 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Wed, 6 Mar 2024 13:24:22 +0000
Subject: [PATCH 101/180] Fix CRD generation
When moving the webhooks we didn't separate CRD generation from webhook
generation, meaning controller-gen was looking for CRDs to generate in
pkg/webhook. This resulted in CRDs not being generated.
---
Makefile | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/Makefile b/Makefile
index 7a0b864d05..08bd30002e 100644
--- a/Makefile
+++ b/Makefile
@@ -274,9 +274,11 @@ generate-conversion-gen: $(CONVERSION_GEN)
.PHONY: generate-manifests
generate-manifests: $(CONTROLLER_GEN) ## Generate manifests e.g. CRD, RBAC etc.
$(CONTROLLER_GEN) \
- paths=./pkg/webhooks/... \
+ 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) \
From d33fee8e4789e7a72ad7688602a41810555820eb Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Fri, 1 Mar 2024 22:19:09 +0000
Subject: [PATCH 102/180] Move filter conversions out of /api
Removes a gophercloud dependency for consumers of the API.
---
api/v1alpha6/filter_convert.go | 53 -------
api/v1beta1/conversion.go | 46 ++++++
api/v1beta1/filter_convert.go | 147 ------------------
api/v1beta1/types.go | 11 ++
controllers/openstackcluster_controller.go | 11 +-
.../openstackfloatingippool_controller.go | 3 +-
pkg/cloud/services/compute/instance.go | 4 +-
pkg/cloud/services/networking/network.go | 16 +-
pkg/cloud/services/networking/port.go | 6 +-
pkg/cloud/services/networking/router.go | 5 +-
.../services/networking/securitygroups.go | 7 +-
.../utils/filterconvert/convert.go | 55 ++++---
.../utils/filterconvert/v1alpha7/convert.go | 29 +---
13 files changed, 129 insertions(+), 264 deletions(-)
delete mode 100644 api/v1alpha6/filter_convert.go
delete mode 100644 api/v1beta1/filter_convert.go
rename api/v1alpha7/filter_convert.go => pkg/utils/filterconvert/convert.go (52%)
rename api/v1alpha5/filter_convert.go => pkg/utils/filterconvert/v1alpha7/convert.go (53%)
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/v1beta1/conversion.go b/api/v1beta1/conversion.go
index 49f9f8c03c..250483a0f0 100644
--- a/api/v1beta1/conversion.go
+++ b/api/v1beta1/conversion.go
@@ -17,6 +17,8 @@ limitations under the License.
package v1beta1
import (
+ "strings"
+
"k8s.io/utils/pointer"
)
@@ -69,3 +71,47 @@ func LegacyCalicoSecurityGroupRules() []SecurityGroupRuleSpec {
},
}
}
+
+// 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/filter_convert.go b/api/v1beta1/filter_convert.go
deleted file mode 100644
index 23f7f3c348..0000000000
--- a/api/v1beta1/filter_convert.go
+++ /dev/null
@@ -1,147 +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 v1beta1
-
-import (
- "strings"
-
- "github.com/gophercloud/gophercloud/openstack/imageservice/v2/images"
- "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: joinTags(securityGroupFilter.Tags),
- TagsAny: joinTags(securityGroupFilter.TagsAny),
- NotTags: joinTags(securityGroupFilter.NotTags),
- NotTagsAny: joinTags(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: joinTags(subnetFilter.Tags),
- TagsAny: joinTags(subnetFilter.TagsAny),
- NotTags: joinTags(subnetFilter.NotTags),
- NotTagsAny: joinTags(subnetFilter.NotTagsAny),
- }
-}
-
-func (networkFilter *NetworkFilter) ToListOpt() networks.ListOpts {
- return networks.ListOpts{
- Name: networkFilter.Name,
- Description: networkFilter.Description,
- ProjectID: networkFilter.ProjectID,
- ID: networkFilter.ID,
- Tags: joinTags(networkFilter.Tags),
- TagsAny: joinTags(networkFilter.TagsAny),
- NotTags: joinTags(networkFilter.NotTags),
- NotTagsAny: joinTags(networkFilter.NotTagsAny),
- }
-}
-
-func (networkFilter *NetworkFilter) IsEmpty() bool {
- return networkFilter.Name == "" &&
- networkFilter.Description == "" &&
- networkFilter.ProjectID == "" &&
- networkFilter.ID == "" &&
- len(networkFilter.Tags) == 0 &&
- len(networkFilter.TagsAny) == 0 &&
- len(networkFilter.NotTags) == 0 &&
- len(networkFilter.NotTagsAny) == 0
-}
-
-func (routerFilter *RouterFilter) ToListOpt() routers.ListOpts {
- return routers.ListOpts{
- ID: routerFilter.ID,
- Name: routerFilter.Name,
- Description: routerFilter.Description,
- ProjectID: routerFilter.ProjectID,
- Tags: joinTags(routerFilter.Tags),
- TagsAny: joinTags(routerFilter.TagsAny),
- NotTags: joinTags(routerFilter.NotTags),
- NotTagsAny: joinTags(routerFilter.NotTagsAny),
- }
-}
-
-func (imageFilter *ImageFilter) ToListOpt() images.ListOpts {
- return images.ListOpts{
- ID: imageFilter.ID,
- Name: imageFilter.Name,
- Tags: imageFilter.Tags,
- }
-}
-
-// 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/types.go b/api/v1beta1/types.go
index 8be6ecc5e4..6d64c4a0cf 100644
--- a/api/v1beta1/types.go
+++ b/api/v1beta1/types.go
@@ -93,6 +93,17 @@ type NetworkFilter struct {
FilterByNeutronTags `json:",inline"`
}
+func (networkFilter *NetworkFilter) IsEmpty() bool {
+ return networkFilter.Name == "" &&
+ networkFilter.Description == "" &&
+ networkFilter.ProjectID == "" &&
+ networkFilter.ID == "" &&
+ len(networkFilter.Tags) == 0 &&
+ len(networkFilter.TagsAny) == 0 &&
+ len(networkFilter.NotTags) == 0 &&
+ len(networkFilter.NotTagsAny) == 0
+}
+
type SubnetFilter struct {
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index 944155f100..eea38455f2 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -53,6 +53,7 @@ import (
"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/filterconvert"
)
const (
@@ -633,7 +634,7 @@ func reconcilePreExistingNetworkComponents(scope *scope.WithLogger, networkingSe
}
if !openStackCluster.Spec.Network.IsEmpty() {
- netOpts := openStackCluster.Spec.Network.ToListOpt()
+ netOpts := filterconvert.NetworkFilterToListOpts(&openStackCluster.Spec.Network)
networkList, err := networkingService.GetNetworksByFilter(&netOpts)
if err != nil {
handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to find network: %w", err))
@@ -859,10 +860,10 @@ func getClusterSubnets(networkingService *networking.Service, openStackCluster *
return nil, fmt.Errorf("no network or subnets specified in OpenStackCluster spec")
}
- empty := &infrav1.SubnetFilter{}
- listOpt := empty.ToListOpt()
- listOpt.NetworkID = networkID
- clusterSubnets, err = networkingService.GetSubnetsByFilter(listOpt)
+ 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) {
diff --git a/controllers/openstackfloatingippool_controller.go b/controllers/openstackfloatingippool_controller.go
index fbcdeb2b63..ac08dc9185 100644
--- a/controllers/openstackfloatingippool_controller.go
+++ b/controllers/openstackfloatingippool_controller.go
@@ -45,6 +45,7 @@ import (
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"
+ filterconvert "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/filterconvert/v1alpha7"
)
const (
@@ -401,7 +402,7 @@ func (r *OpenStackFloatingIPPoolReconciler) reconcileFloatingIPNetwork(scope *sc
}
netListOpts := external.ListOptsExt{
- ListOptsBuilder: pool.Spec.FloatingIPNetwork.ToListOpt(),
+ ListOptsBuilder: filterconvert.NetworkFilterToListOpt(&pool.Spec.FloatingIPNetwork),
External: pointer.Bool(true),
}
diff --git a/pkg/cloud/services/compute/instance.go b/pkg/cloud/services/compute/instance.go
index 747fbf02bb..9981ebeabb 100644
--- a/pkg/cloud/services/compute/instance.go
+++ b/pkg/cloud/services/compute/instance.go
@@ -37,6 +37,7 @@ import (
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/record"
capoerrors "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/errors"
+ "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/filterconvert"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/hash"
)
@@ -336,7 +337,8 @@ func (s *Service) GetImageID(image infrav1.ImageFilter) (string, error) {
return image.ID, nil
}
- allImages, err := s.getImageClient().ListImages(image.ToListOpt())
+ listOpts := filterconvert.ImageFilterToListOpts(&image)
+ allImages, err := s.getImageClient().ListImages(listOpts)
if err != nil {
return "", err
}
diff --git a/pkg/cloud/services/networking/network.go b/pkg/cloud/services/networking/network.go
index 20df7b96bb..1904b3823c 100644
--- a/pkg/cloud/services/networking/network.go
+++ b/pkg/cloud/services/networking/network.go
@@ -29,6 +29,7 @@ import (
"sigs.k8s.io/cluster-api-provider-openstack/pkg/metrics"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/record"
capoerrors "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/errors"
+ "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/filterconvert"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/names"
)
@@ -77,7 +78,6 @@ func (c createOpts) ToNetworkCreateMap() (map[string]interface{}, error) {
// - the user has set OpenStackCluster.Spec.DisableExternalNetwork to true.
func (s *Service) ReconcileExternalNetwork(openStackCluster *infrav1.OpenStackCluster) error {
var listOpts external.ListOptsExt
- var emptyExternalnetwork infrav1.NetworkFilter
var isAutoDetecting bool
if openStackCluster.Spec.DisableExternalNetwork {
@@ -86,9 +86,10 @@ func (s *Service) ReconcileExternalNetwork(openStackCluster *infrav1.OpenStackCl
return nil
}
- if openStackCluster.Spec.ExternalNetwork.ToListOpt() != emptyExternalnetwork.ToListOpt() {
+ externalNetworkListOpts := filterconvert.NetworkFilterToListOpts(&openStackCluster.Spec.ExternalNetwork)
+ if externalNetworkListOpts != (networks.ListOpts{}) {
listOpts = external.ListOptsExt{
- ListOptsBuilder: openStackCluster.Spec.ExternalNetwork.ToListOpt(),
+ ListOptsBuilder: externalNetworkListOpts,
}
} else {
// ExternalNetwork is not given so we'll list all networks and filter for external networks
@@ -345,16 +346,17 @@ func (s *Service) GetSubnetsByFilter(opts subnets.ListOptsBuilder) ([]subnets.Su
// GetSubnetByFilter gets a single subnet specified by the given SubnetFilter.
// It returns an ErrFilterMatch if no or multiple subnets are found.
func (s *Service) GetSubnetByFilter(filter *infrav1.SubnetFilter) (*subnets.Subnet, error) {
- return s.getSubnetByFilter(filter.ToListOpt())
+ listOpts := filterconvert.SubnetFilterToListOpts(filter)
+ return s.getSubnetByFilter(listOpts)
}
// GetNetworkSubnetByFilter gets a single subnet of the given network, specified by the given SubnetFilter.
// It returns an ErrFilterMatch if no or multiple subnets are found.
func (s *Service) GetNetworkSubnetByFilter(networkID string, filter *infrav1.SubnetFilter) (*subnets.Subnet, error) {
- listOpt := filter.ToListOpt()
- listOpt.NetworkID = networkID
+ listOpts := filterconvert.SubnetFilterToListOpts(filter)
+ listOpts.NetworkID = networkID
- return s.getSubnetByFilter(listOpt)
+ return s.getSubnetByFilter(listOpts)
}
// getSubnetByFilter gets a single subnet specified by the given gophercloud ListOpts.
diff --git a/pkg/cloud/services/networking/port.go b/pkg/cloud/services/networking/port.go
index e9e8c6df3a..305c58d71a 100644
--- a/pkg/cloud/services/networking/port.go
+++ b/pkg/cloud/services/networking/port.go
@@ -34,6 +34,7 @@ import (
"sigs.k8s.io/cluster-api-provider-openstack/pkg/record"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
capoerrors "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/errors"
+ "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/filterconvert"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/names"
)
@@ -190,7 +191,7 @@ func (s *Service) getSubnetIDForFixedIP(subnet *infrav1.SubnetFilter, networkID
return subnet.ID, nil
}
- opts := subnet.ToListOpt()
+ opts := filterconvert.SubnetFilterToListOpts(subnet)
opts.NetworkID = networkID
subnets, err := s.client.ListSubnet(opts)
if err != nil {
@@ -492,7 +493,8 @@ func (s *Service) normalizePortTarget(port *infrav1.PortOpts, openStackCluster *
}
// Network is defined by Filter
- netIDs, err := s.GetNetworkIDsByFilter(port.Network.ToListOpt())
+ networkListOpts := filterconvert.NetworkFilterToListOpts(port.Network)
+ netIDs, err := s.GetNetworkIDsByFilter(networkListOpts)
if err != nil {
return err
}
diff --git a/pkg/cloud/services/networking/router.go b/pkg/cloud/services/networking/router.go
index 88fe117f1f..749d5c3be9 100644
--- a/pkg/cloud/services/networking/router.go
+++ b/pkg/cloud/services/networking/router.go
@@ -27,6 +27,7 @@ import (
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/record"
capoerrors "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/errors"
+ "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/filterconvert"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/names"
)
@@ -49,7 +50,7 @@ func (s *Service) ReconcileRouter(openStackCluster *infrav1.OpenStackCluster, cl
routerListOpts := routers.ListOpts{Name: routerName}
existingRouter := false
if openStackCluster.Spec.Router != nil {
- routerListOpts = openStackCluster.Spec.Router.ToListOpt()
+ routerListOpts = filterconvert.RouterFilterToListOpts(openStackCluster.Spec.Router)
existingRouter = true
}
@@ -196,7 +197,7 @@ func (s *Service) DeleteRouter(openStackCluster *infrav1.OpenStackCluster, clust
listOpts := routers.ListOpts{Name: routerName}
existingRouter := false
if openStackCluster.Spec.Router != nil {
- listOpts = openStackCluster.Spec.Router.ToListOpt()
+ listOpts = filterconvert.RouterFilterToListOpts(openStackCluster.Spec.Router)
existingRouter = true
}
diff --git a/pkg/cloud/services/networking/securitygroups.go b/pkg/cloud/services/networking/securitygroups.go
index 175b46e179..cd1f64360b 100644
--- a/pkg/cloud/services/networking/securitygroups.go
+++ b/pkg/cloud/services/networking/securitygroups.go
@@ -25,6 +25,7 @@ import (
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/record"
+ "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/filterconvert"
)
const (
@@ -285,7 +286,9 @@ func validateRemoteManagedGroups(remoteManagedGroups map[string]string, ruleRemo
func (s *Service) GetSecurityGroups(securityGroupParams []infrav1.SecurityGroupFilter) ([]string, error) {
var sgIDs []string
- for _, sg := range securityGroupParams {
+ for i := range securityGroupParams {
+ sg := &securityGroupParams[i]
+
// Don't validate an explicit UUID if we were given one
if sg.ID != "" {
if isDuplicate(sgIDs, sg.ID) {
@@ -295,7 +298,7 @@ func (s *Service) GetSecurityGroups(securityGroupParams []infrav1.SecurityGroupF
continue
}
- listOpts := sg.ToListOpt()
+ listOpts := filterconvert.SecurityGroupFilterToListOpts(sg)
if listOpts.ProjectID == "" {
listOpts.ProjectID = s.scope.ProjectID()
}
diff --git a/api/v1alpha7/filter_convert.go b/pkg/utils/filterconvert/convert.go
similarity index 52%
rename from api/v1alpha7/filter_convert.go
rename to pkg/utils/filterconvert/convert.go
index 236c91fcd7..3dedad67ac 100644
--- a/api/v1alpha7/filter_convert.go
+++ b/pkg/utils/filterconvert/convert.go
@@ -1,5 +1,5 @@
/*
-Copyright 2023 The Kubernetes Authors.
+Copyright 2024 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.
@@ -14,29 +14,32 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package v1alpha7
+package filterconvert
import (
+ "github.com/gophercloud/gophercloud/openstack/imageservice/v2/images"
"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"
+
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
)
-func (securityGroupFilter SecurityGroupFilter) ToListOpt() securitygroups.ListOpts {
+func SecurityGroupFilterToListOpts(securityGroupFilter *infrav1.SecurityGroupFilter) 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,
+ Tags: infrav1.JoinTags(securityGroupFilter.Tags),
+ TagsAny: infrav1.JoinTags(securityGroupFilter.TagsAny),
+ NotTags: infrav1.JoinTags(securityGroupFilter.NotTags),
+ NotTagsAny: infrav1.JoinTags(securityGroupFilter.NotTagsAny),
}
}
-func (subnetFilter SubnetFilter) ToListOpt() subnets.ListOpts {
+func SubnetFilterToListOpts(subnetFilter *infrav1.SubnetFilter) subnets.ListOpts {
return subnets.ListOpts{
Name: subnetFilter.Name,
Description: subnetFilter.Description,
@@ -47,35 +50,43 @@ func (subnetFilter SubnetFilter) ToListOpt() subnets.ListOpts {
IPv6AddressMode: subnetFilter.IPv6AddressMode,
IPv6RAMode: subnetFilter.IPv6RAMode,
ID: subnetFilter.ID,
- Tags: subnetFilter.Tags,
- TagsAny: subnetFilter.TagsAny,
- NotTags: subnetFilter.NotTags,
- NotTagsAny: subnetFilter.NotTagsAny,
+ Tags: infrav1.JoinTags(subnetFilter.Tags),
+ TagsAny: infrav1.JoinTags(subnetFilter.TagsAny),
+ NotTags: infrav1.JoinTags(subnetFilter.NotTags),
+ NotTagsAny: infrav1.JoinTags(subnetFilter.NotTagsAny),
}
}
-func (networkFilter NetworkFilter) ToListOpt() networks.ListOpts {
+func NetworkFilterToListOpts(networkFilter *infrav1.NetworkFilter) 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,
+ Tags: infrav1.JoinTags(networkFilter.Tags),
+ TagsAny: infrav1.JoinTags(networkFilter.TagsAny),
+ NotTags: infrav1.JoinTags(networkFilter.NotTags),
+ NotTagsAny: infrav1.JoinTags(networkFilter.NotTagsAny),
}
}
-func (routerFilter RouterFilter) ToListOpt() routers.ListOpts {
+func RouterFilterToListOpts(routerFilter *infrav1.RouterFilter) 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,
+ Tags: infrav1.JoinTags(routerFilter.Tags),
+ TagsAny: infrav1.JoinTags(routerFilter.TagsAny),
+ NotTags: infrav1.JoinTags(routerFilter.NotTags),
+ NotTagsAny: infrav1.JoinTags(routerFilter.NotTagsAny),
+ }
+}
+
+func ImageFilterToListOpts(imageFilter *infrav1.ImageFilter) images.ListOpts {
+ return images.ListOpts{
+ ID: imageFilter.ID,
+ Name: imageFilter.Name,
+ Tags: imageFilter.Tags,
}
}
diff --git a/api/v1alpha5/filter_convert.go b/pkg/utils/filterconvert/v1alpha7/convert.go
similarity index 53%
rename from api/v1alpha5/filter_convert.go
rename to pkg/utils/filterconvert/v1alpha7/convert.go
index ab89bdca75..545811d5fb 100644
--- a/api/v1alpha5/filter_convert.go
+++ b/pkg/utils/filterconvert/v1alpha7/convert.go
@@ -1,5 +1,5 @@
/*
-Copyright 2021 The Kubernetes Authors.
+Copyright 2024 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.
@@ -14,32 +14,17 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package v1alpha5
+package convert
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,
- }
-}
+ infrav1alpha7 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
+)
-func (networkFilter NetworkFilter) ToListOpt() networks.ListOpts {
+// NetworkFilterToListOpt converts a v1alpha7.NetworkFilter to a networks.ListOpts
+// Still used by the Floating IP IPAM controller until we bump it to v1beta1.
+func NetworkFilterToListOpt(networkFilter *infrav1alpha7.NetworkFilter) networks.ListOpts {
return networks.ListOpts{
Name: networkFilter.Name,
Description: networkFilter.Description,
From 1734ebbc188dd64cb4f98eb921d4e5dfa231d8ec Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Wed, 6 Mar 2024 19:06:12 +0000
Subject: [PATCH 103/180] Allow generating api-docs for individual versions
This change creates separate targets for individual API targets when
generating api documentation. The generate-api-docs target continues to
execute all of them as before.
---
Makefile | 17 ++++-------------
1 file changed, 4 insertions(+), 13 deletions(-)
diff --git a/Makefile b/Makefile
index 08bd30002e..1a967b0f2f 100644
--- a/Makefile
+++ b/Makefile
@@ -288,22 +288,13 @@ generate-manifests: $(CONTROLLER_GEN) ## Generate manifests e.g. CRD, RBAC etc.
rbac:roleName=manager-role
.PHONY: generate-api-docs
-generate-api-docs: $(GEN_CRD_API_REFERENCE_DOCS) ## Generate api documentation
+generate-api-docs: generate-api-docs-v1beta1 generate-api-docs-v1alpha7 generate-api-docs-v1alpha6
+generate-api-docs-%: $(GEN_CRD_API_REFERENCE_DOCS) FORCE
$(GEN_CRD_API_REFERENCE_DOCS) \
- -api-dir=./api/v1beta1 \
+ -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/v1beta1/api.md
- $(GEN_CRD_API_REFERENCE_DOCS) \
- -api-dir=./api/v1alpha7 \
- -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/v1alpha7/api.md
- $(GEN_CRD_API_REFERENCE_DOCS) \
- -api-dir=./api/v1alpha6 \
- -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/v1alpha6/api.md
+ -out-file=./docs/book/src/api/$*/api.md
## --------------------------------------
##@ Docker
From c7c5baf2e61260ae17b855b3f4768cc1209d0be0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20Dulko?=
Date: Thu, 7 Mar 2024 17:16:00 +0100
Subject: [PATCH 104/180] Rename fields to correctly do uppercase acronyms
K8s API conventions require the acronyms in the field names to be
uppercase if not being the first word in the name. We aren't following
this in several places and this commit fixes these occurrences:
* `projectId` becomes `projectID`
* `gateway_ip` becomes `gatewayIP`
* `ipv6RaMode` becomes `ipv6RAMode`
* `networkMtu` becomes `networkMTU`
* `hostId` becomes `hostID`
* `allowedCidrs` becomes `allowedCIDRs`
---
api/v1beta1/openstackcluster_types.go | 2 +-
api/v1beta1/types.go | 16 +++----
...re.cluster.x-k8s.io_openstackclusters.yaml | 48 +++++++++----------
...er.x-k8s.io_openstackclustertemplates.yaml | 36 +++++++-------
...re.cluster.x-k8s.io_openstackmachines.yaml | 26 +++++-----
...er.x-k8s.io_openstackmachinetemplates.yaml | 14 +++---
docs/book/src/api/v1beta1/api.md | 22 ++++-----
.../src/clusteropenstack/configuration.md | 2 +-
.../topics/crd-changes/v1alpha7-to-v1beta1.md | 35 ++++++++++++--
9 files changed, 115 insertions(+), 86 deletions(-)
diff --git a/api/v1beta1/openstackcluster_types.go b/api/v1beta1/openstackcluster_types.go
index 7ca146ef70..3a3fe803c0 100644
--- a/api/v1beta1/openstackcluster_types.go
+++ b/api/v1beta1/openstackcluster_types.go
@@ -59,7 +59,7 @@ type OpenStackClusterSpec struct {
// 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 int `json:"networkMTU,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.
diff --git a/api/v1beta1/types.go b/api/v1beta1/types.go
index 8be6ecc5e4..63236db1bf 100644
--- a/api/v1beta1/types.go
+++ b/api/v1beta1/types.go
@@ -79,7 +79,7 @@ type SecurityGroupFilter struct {
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
- ProjectID string `json:"projectId,omitempty"`
+ ProjectID string `json:"projectID,omitempty"`
FilterByNeutronTags `json:",inline"`
}
@@ -87,7 +87,7 @@ type SecurityGroupFilter struct {
type NetworkFilter struct {
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
- ProjectID string `json:"projectId,omitempty"`
+ ProjectID string `json:"projectID,omitempty"`
ID string `json:"id,omitempty"`
FilterByNeutronTags `json:",inline"`
@@ -96,12 +96,12 @@ type NetworkFilter struct {
type SubnetFilter struct {
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
- ProjectID string `json:"projectId,omitempty"`
+ ProjectID string `json:"projectID,omitempty"`
IPVersion int `json:"ipVersion,omitempty"`
- GatewayIP string `json:"gateway_ip,omitempty"`
+ GatewayIP string `json:"gatewayIP,omitempty"`
CIDR string `json:"cidr,omitempty"`
IPv6AddressMode string `json:"ipv6AddressMode,omitempty"`
- IPv6RAMode string `json:"ipv6RaMode,omitempty"`
+ IPv6RAMode string `json:"ipv6RAMode,omitempty"`
ID string `json:"id,omitempty"`
FilterByNeutronTags `json:",inline"`
@@ -111,7 +111,7 @@ type RouterFilter struct {
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
- ProjectID string `json:"projectId,omitempty"`
+ ProjectID string `json:"projectID,omitempty"`
FilterByNeutronTags `json:",inline"`
}
@@ -190,7 +190,7 @@ type PortOpts struct {
// HostID specifies the ID of the host where the port resides.
// +optional
- HostID optional.String `json:"hostId,omitempty"`
+ 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
@@ -596,7 +596,7 @@ type APIServerLoadBalancer struct {
// AdditionalPorts adds additional tcp ports to the load balancer.
AdditionalPorts []int `json:"additionalPorts,omitempty"`
// AllowedCIDRs restrict access to all API-Server listeners to the given address CIDRs.
- AllowedCIDRs []string `json:"allowedCidrs,omitempty"`
+ AllowedCIDRs []string `json:"allowedCIDRs,omitempty"`
// Octavia Provider Used to create load balancer
Provider string `json:"provider,omitempty"`
}
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 85b3b178e4..afe2b5c726 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -4874,7 +4874,7 @@ spec:
items:
type: integer
type: array
- allowedCidrs:
+ allowedCIDRs:
description: AllowedCIDRs restrict access to all API-Server listeners
to the given address CIDRs.
items:
@@ -5094,7 +5094,7 @@ spec:
type: string
description:
type: string
- gateway_ip:
+ gatewayIP:
type: string
id:
type: string
@@ -5102,7 +5102,7 @@ spec:
type: integer
ipv6AddressMode:
type: string
- ipv6RaMode:
+ ipv6RAMode:
type: string
name:
type: string
@@ -5132,7 +5132,7 @@ spec:
type: string
type: array
x-kubernetes-list-type: set
- projectId:
+ projectID:
type: string
tags:
description: |-
@@ -5165,7 +5165,7 @@ spec:
type: object
type: array
x-kubernetes-list-type: atomic
- hostId:
+ hostID:
description: HostID specifies the ID of the host where
the port resides.
type: string
@@ -5216,7 +5216,7 @@ spec:
type: string
type: array
x-kubernetes-list-type: set
- projectId:
+ projectID:
type: string
tags:
description: |-
@@ -5307,7 +5307,7 @@ spec:
type: string
type: array
x-kubernetes-list-type: set
- projectId:
+ projectID:
type: string
tags:
description: |-
@@ -5447,7 +5447,7 @@ spec:
type: string
type: array
x-kubernetes-list-type: set
- projectId:
+ projectID:
type: string
tags:
description: |-
@@ -5617,7 +5617,7 @@ spec:
type: string
type: array
x-kubernetes-list-type: set
- projectId:
+ projectID:
type: string
tags:
description: |-
@@ -5664,7 +5664,7 @@ spec:
type: string
description:
type: string
- gateway_ip:
+ gatewayIP:
type: string
id:
type: string
@@ -5672,7 +5672,7 @@ spec:
type: integer
ipv6AddressMode:
type: string
- ipv6RaMode:
+ ipv6RAMode:
type: string
name:
type: string
@@ -5702,7 +5702,7 @@ spec:
type: string
type: array
x-kubernetes-list-type: set
- projectId:
+ projectID:
type: string
tags:
description: |-
@@ -5930,7 +5930,7 @@ spec:
type: string
type: array
x-kubernetes-list-type: set
- projectId:
+ projectID:
type: string
tags:
description: |-
@@ -5960,7 +5960,7 @@ spec:
type: array
x-kubernetes-list-type: set
type: object
- networkMtu:
+ 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.
@@ -6004,7 +6004,7 @@ spec:
type: string
type: array
x-kubernetes-list-type: set
- projectId:
+ projectID:
type: string
tags:
description: |-
@@ -6047,7 +6047,7 @@ spec:
type: string
description:
type: string
- gateway_ip:
+ gatewayIP:
type: string
id:
type: string
@@ -6055,7 +6055,7 @@ spec:
type: integer
ipv6AddressMode:
type: string
- ipv6RaMode:
+ ipv6RAMode:
type: string
name:
type: string
@@ -6085,7 +6085,7 @@ spec:
type: string
type: array
x-kubernetes-list-type: set
- projectId:
+ projectID:
type: string
tags:
description: |-
@@ -6253,7 +6253,7 @@ spec:
type: string
description:
type: string
- gateway_ip:
+ gatewayIP:
type: string
id:
type: string
@@ -6261,7 +6261,7 @@ spec:
type: integer
ipv6AddressMode:
type: string
- ipv6RaMode:
+ ipv6RAMode:
type: string
name:
type: string
@@ -6291,7 +6291,7 @@ spec:
type: string
type: array
x-kubernetes-list-type: set
- projectId:
+ projectID:
type: string
tags:
description: |-
@@ -6324,7 +6324,7 @@ spec:
type: object
type: array
x-kubernetes-list-type: atomic
- hostId:
+ hostID:
description: HostID specifies the ID of the host where
the port resides.
type: string
@@ -6375,7 +6375,7 @@ spec:
type: string
type: array
x-kubernetes-list-type: set
- projectId:
+ projectID:
type: string
tags:
description: |-
@@ -6466,7 +6466,7 @@ spec:
type: string
type: array
x-kubernetes-list-type: set
- projectId:
+ projectID:
type: string
tags:
description: |-
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 d4c396ef94..550887a8a6 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -2298,7 +2298,7 @@ spec:
items:
type: integer
type: array
- allowedCidrs:
+ allowedCIDRs:
description: AllowedCIDRs restrict access to all API-Server
listeners to the given address CIDRs.
items:
@@ -2522,7 +2522,7 @@ spec:
type: string
description:
type: string
- gateway_ip:
+ gatewayIP:
type: string
id:
type: string
@@ -2530,7 +2530,7 @@ spec:
type: integer
ipv6AddressMode:
type: string
- ipv6RaMode:
+ ipv6RAMode:
type: string
name:
type: string
@@ -2560,7 +2560,7 @@ spec:
type: string
type: array
x-kubernetes-list-type: set
- projectId:
+ projectID:
type: string
tags:
description: |-
@@ -2593,7 +2593,7 @@ spec:
type: object
type: array
x-kubernetes-list-type: atomic
- hostId:
+ hostID:
description: HostID specifies the ID of the
host where the port resides.
type: string
@@ -2645,7 +2645,7 @@ spec:
type: string
type: array
x-kubernetes-list-type: set
- projectId:
+ projectID:
type: string
tags:
description: |-
@@ -2737,7 +2737,7 @@ spec:
type: string
type: array
x-kubernetes-list-type: set
- projectId:
+ projectID:
type: string
tags:
description: |-
@@ -2878,7 +2878,7 @@ spec:
type: string
type: array
x-kubernetes-list-type: set
- projectId:
+ projectID:
type: string
tags:
description: |-
@@ -3049,7 +3049,7 @@ spec:
type: string
type: array
x-kubernetes-list-type: set
- projectId:
+ projectID:
type: string
tags:
description: |-
@@ -3096,7 +3096,7 @@ spec:
type: string
description:
type: string
- gateway_ip:
+ gatewayIP:
type: string
id:
type: string
@@ -3104,7 +3104,7 @@ spec:
type: integer
ipv6AddressMode:
type: string
- ipv6RaMode:
+ ipv6RAMode:
type: string
name:
type: string
@@ -3134,7 +3134,7 @@ spec:
type: string
type: array
x-kubernetes-list-type: set
- projectId:
+ projectID:
type: string
tags:
description: |-
@@ -3364,7 +3364,7 @@ spec:
type: string
type: array
x-kubernetes-list-type: set
- projectId:
+ projectID:
type: string
tags:
description: |-
@@ -3394,7 +3394,7 @@ spec:
type: array
x-kubernetes-list-type: set
type: object
- networkMtu:
+ 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.
@@ -3438,7 +3438,7 @@ spec:
type: string
type: array
x-kubernetes-list-type: set
- projectId:
+ projectID:
type: string
tags:
description: |-
@@ -3481,7 +3481,7 @@ spec:
type: string
description:
type: string
- gateway_ip:
+ gatewayIP:
type: string
id:
type: string
@@ -3489,7 +3489,7 @@ spec:
type: integer
ipv6AddressMode:
type: string
- ipv6RaMode:
+ ipv6RAMode:
type: string
name:
type: string
@@ -3519,7 +3519,7 @@ spec:
type: string
type: array
x-kubernetes-list-type: set
- projectId:
+ projectID:
type: string
tags:
description: |-
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 a58649e400..3bb1c4a4df 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
@@ -1895,7 +1895,7 @@ spec:
type: string
description:
type: string
- gateway_ip:
+ gatewayIP:
type: string
id:
type: string
@@ -1903,7 +1903,7 @@ spec:
type: integer
ipv6AddressMode:
type: string
- ipv6RaMode:
+ ipv6RAMode:
type: string
name:
type: string
@@ -1933,7 +1933,7 @@ spec:
type: string
type: array
x-kubernetes-list-type: set
- projectId:
+ projectID:
type: string
tags:
description: |-
@@ -1966,7 +1966,7 @@ spec:
type: object
type: array
x-kubernetes-list-type: atomic
- hostId:
+ hostID:
description: HostID specifies the ID of the host where the port
resides.
type: string
@@ -2016,7 +2016,7 @@ spec:
type: string
type: array
x-kubernetes-list-type: set
- projectId:
+ projectID:
type: string
tags:
description: |-
@@ -2107,7 +2107,7 @@ spec:
type: string
type: array
x-kubernetes-list-type: set
- projectId:
+ projectID:
type: string
tags:
description: |-
@@ -2245,7 +2245,7 @@ spec:
type: string
type: array
x-kubernetes-list-type: set
- projectId:
+ projectID:
type: string
tags:
description: |-
@@ -2514,7 +2514,7 @@ spec:
type: string
description:
type: string
- gateway_ip:
+ gatewayIP:
type: string
id:
type: string
@@ -2522,7 +2522,7 @@ spec:
type: integer
ipv6AddressMode:
type: string
- ipv6RaMode:
+ ipv6RAMode:
type: string
name:
type: string
@@ -2552,7 +2552,7 @@ spec:
type: string
type: array
x-kubernetes-list-type: set
- projectId:
+ projectID:
type: string
tags:
description: |-
@@ -2585,7 +2585,7 @@ spec:
type: object
type: array
x-kubernetes-list-type: atomic
- hostId:
+ hostID:
description: HostID specifies the ID of the host where the
port resides.
type: string
@@ -2635,7 +2635,7 @@ spec:
type: string
type: array
x-kubernetes-list-type: set
- projectId:
+ projectID:
type: string
tags:
description: |-
@@ -2726,7 +2726,7 @@ spec:
type: string
type: array
x-kubernetes-list-type: set
- projectId:
+ projectID:
type: string
tags:
description: |-
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 5a4838e274..975c907650 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
@@ -1569,7 +1569,7 @@ spec:
type: string
description:
type: string
- gateway_ip:
+ gatewayIP:
type: string
id:
type: string
@@ -1577,7 +1577,7 @@ spec:
type: integer
ipv6AddressMode:
type: string
- ipv6RaMode:
+ ipv6RAMode:
type: string
name:
type: string
@@ -1607,7 +1607,7 @@ spec:
type: string
type: array
x-kubernetes-list-type: set
- projectId:
+ projectID:
type: string
tags:
description: |-
@@ -1640,7 +1640,7 @@ spec:
type: object
type: array
x-kubernetes-list-type: atomic
- hostId:
+ hostID:
description: HostID specifies the ID of the host where
the port resides.
type: string
@@ -1691,7 +1691,7 @@ spec:
type: string
type: array
x-kubernetes-list-type: set
- projectId:
+ projectID:
type: string
tags:
description: |-
@@ -1782,7 +1782,7 @@ spec:
type: string
type: array
x-kubernetes-list-type: set
- projectId:
+ projectID:
type: string
tags:
description: |-
@@ -1922,7 +1922,7 @@ spec:
type: string
type: array
x-kubernetes-list-type: set
- projectId:
+ projectID:
type: string
tags:
description: |-
diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md
index a0f4caf74b..311b73e3cf 100644
--- a/docs/book/src/api/v1beta1/api.md
+++ b/docs/book/src/api/v1beta1/api.md
@@ -131,7 +131,7 @@ must be IPv4 and the other IPv6.
-networkMtu
+networkMTU
int
@@ -842,7 +842,7 @@ bool
|
-allowedCidrs
+allowedCIDRs
[]string
@@ -1780,7 +1780,7 @@ string
|
-projectId
+projectID
string
@@ -2005,7 +2005,7 @@ must be IPv4 and the other IPv6.
|
-networkMtu
+networkMTU
int
@@ -2550,7 +2550,7 @@ must be IPv4 and the other IPv6.
|
-networkMtu
+networkMTU
int
@@ -3619,7 +3619,7 @@ bastion host.
|
-hostId
+hostID
string
@@ -3968,7 +3968,7 @@ string
|
-projectId
+projectID
string
@@ -4042,7 +4042,7 @@ string
|
-projectId
+projectID
string
@@ -4590,7 +4590,7 @@ string
|
-projectId
+projectID
string
@@ -4610,7 +4610,7 @@ int
|
-gateway_ip
+gatewayIP
string
@@ -4640,7 +4640,7 @@ string
|
-ipv6RaMode
+ipv6RAMode
string
diff --git a/docs/book/src/clusteropenstack/configuration.md b/docs/book/src/clusteropenstack/configuration.md
index 810d33b322..6171fb968d 100644
--- a/docs/book/src/clusteropenstack/configuration.md
+++ b/docs/book/src/clusteropenstack/configuration.md
@@ -313,7 +313,7 @@ metadata:
namespace:
spec:
apiServerLoadBalancer:
- allowedCidrs:
+ allowedCIDRs:
- 192.168.10/24
- 10.10.0.0/16
```
diff --git a/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md b/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
index 126b09b391..7c7484f573 100644
--- a/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
+++ b/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
@@ -25,7 +25,10 @@
- [Change to managedSecurityGroups](#change-to-managedsecuritygroups)
- [Calico CNI](#calico-cni)
- [Change to network](#change-to-network)
- - [Changes to filter tags](#changes-to-filter-tags)
+ - [Change to networkMtu](#change-to-networkmtu)
+ - [Changes to filters](#changes-to-filters)
+ - [Changes to filter tags](#changes-to-filter-tags)
+ - [Field capitalization consistency](#field-capitalization-consistency)
@@ -96,6 +99,11 @@ Setting either of the following fields explicitly to the empty string would prev
* nameSuffix
* description
+The following fields in `PortOpts` are renamed in order to keep them consistent with K8s API conventions:
+
+* `hostId` becomes `hostID`
+* `allowedCidrs` becomes `allowedCIDRs`
+
### `OpenStackCluster`
#### Removal of cloudName
@@ -314,7 +322,13 @@ allow backwards compatibility if `allowAllInClusterTraffic` is set to false.
In v1beta1, when the `OpenStackCluster.Spec.Network` is not defined, the `Subnets` are now used to identify the `Network`.
-### Changes to filter tags
+#### Change to networkMtu
+
+In v1beta1, `OpenStackCluster.spec.NetworkMtu` becomes `OpenStackCluster.spec.NetworkMTU` in order to keep the name consistent with K8s API conventions.
+
+### Changes to filters
+
+#### Changes to filter tags
We currently define filters on 4 different Neutron resources which are used throughout the API:
* Networks
@@ -342,4 +356,19 @@ subnet:
- bar
```
-Due to the limitations of the encoding of tag queries in Neutron, tags must be non-empty and may not contain commas. Tags will be automatically converted to a list of tags during conversion.
\ No newline at end of file
+Due to the limitations of the encoding of tag queries in Neutron, tags must be non-empty and may not contain commas. Tags will be automatically converted to a list of tags during conversion.
+
+#### Field capitalization consistency
+
+In order to keep field names consistent with K8s API conventions, various fields in the `Filters` are renamed. This includes:
+
+* `SecurityGroupFilter`
+ * `projectId` becomes `projectID`
+* `NetworkFilter`
+ * `projectId` becomes `projectID`
+* `SubnetFilter`
+ * `projectId` becomes `projectID`
+ * `gateway_ip` becomes `gatewayIP`
+ * `ipv6RaMode` becomes `ipv6RAMode`
+* `RouterFilter`
+ * `projectId` becomes `projectID`
From 968df70680c88cf158bb647dc3c915efd7a2623d Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Thu, 7 Mar 2024 15:35:03 +0000
Subject: [PATCH 105/180] CI: Specify external network by name
---
test/e2e/data/e2e_conf.yaml | 3 ++-
.../externalNetworkByName/kustomization.yaml | 14 ++++++++++++++
test/e2e/data/kustomize/default/kustomization.yaml | 1 +
.../kustomize/flatcar-sysext/kustomization.yaml | 1 +
test/e2e/data/kustomize/flatcar/kustomization.yaml | 1 +
.../e2e/data/kustomize/v1alpha6/kustomization.yaml | 5 +++++
.../e2e/data/kustomize/v1alpha7/kustomization.yaml | 5 +++++
.../data/kustomize/without-lb/kustomization.yaml | 1 +
8 files changed, 30 insertions(+), 1 deletion(-)
create mode 100644 test/e2e/data/kustomize/common-patches/externalNetworkByName/kustomization.yaml
diff --git a/test/e2e/data/e2e_conf.yaml b/test/e2e/data/e2e_conf.yaml
index 03ac783247..4d9552334c 100644
--- a/test/e2e/data/e2e_conf.yaml
+++ b/test/e2e/data/e2e_conf.yaml
@@ -203,7 +203,8 @@ variables:
OPENSTACK_IMAGE_NAME_UPGRADE_FROM: "ubuntu-2204-kube-v1.27.2"
OPENSTACK_NODE_MACHINE_FLAVOR: "m1.small"
OPENSTACK_SSH_KEY_NAME: "cluster-api-provider-openstack-sigs-k8s-io"
- OPENSTACK_EXTERNAL_NETWORK_ID: ""
+ # The default external network created by devstack
+ OPENSTACK_EXTERNAL_NETWORK_NAME: "public"
OPENSTACK_VOLUME_TYPE_ALT: "test-volume-type"
CONFORMANCE_WORKER_MACHINE_COUNT: "5"
CONFORMANCE_CONTROL_PLANE_MACHINE_COUNT: "1"
diff --git a/test/e2e/data/kustomize/common-patches/externalNetworkByName/kustomization.yaml b/test/e2e/data/kustomize/common-patches/externalNetworkByName/kustomization.yaml
new file mode 100644
index 0000000000..67b3a753a6
--- /dev/null
+++ b/test/e2e/data/kustomize/common-patches/externalNetworkByName/kustomization.yaml
@@ -0,0 +1,14 @@
+---
+apiVersion: kustomize.config.k8s.io/v1alpha1
+kind: Component
+
+patches:
+- patch: |-
+ - op: "remove"
+ path: "/spec/externalNetwork"
+ - op: "add"
+ path: "/spec/externalNetwork"
+ value:
+ name: "${OPENSTACK_EXTERNAL_NETWORK_NAME}"
+ target:
+ kind: OpenStackCluster
diff --git a/test/e2e/data/kustomize/default/kustomization.yaml b/test/e2e/data/kustomize/default/kustomization.yaml
index 3cd7a6cbb8..30f2c9d85d 100644
--- a/test/e2e/data/kustomize/default/kustomization.yaml
+++ b/test/e2e/data/kustomize/default/kustomization.yaml
@@ -6,3 +6,4 @@ components:
- ../common-patches/cni
- ../upgrade-patches
- ../common-patches/ccm
+- ../common-patches/externalNetworkByName
diff --git a/test/e2e/data/kustomize/flatcar-sysext/kustomization.yaml b/test/e2e/data/kustomize/flatcar-sysext/kustomization.yaml
index 8fd5f119f8..6738cde3a8 100644
--- a/test/e2e/data/kustomize/flatcar-sysext/kustomization.yaml
+++ b/test/e2e/data/kustomize/flatcar-sysext/kustomization.yaml
@@ -5,3 +5,4 @@ resources:
components:
- ../common-patches/cni
- ../common-patches/ccm
+- ../common-patches/externalNetworkByName
diff --git a/test/e2e/data/kustomize/flatcar/kustomization.yaml b/test/e2e/data/kustomize/flatcar/kustomization.yaml
index a85308b72c..2de905e98e 100644
--- a/test/e2e/data/kustomize/flatcar/kustomization.yaml
+++ b/test/e2e/data/kustomize/flatcar/kustomization.yaml
@@ -6,3 +6,4 @@ resources:
components:
- ../common-patches/cni
- ../common-patches/ccm
+- ../common-patches/externalNetworkByName
diff --git a/test/e2e/data/kustomize/v1alpha6/kustomization.yaml b/test/e2e/data/kustomize/v1alpha6/kustomization.yaml
index aa3e9c0e5c..9f7ac4445d 100644
--- a/test/e2e/data/kustomize/v1alpha6/kustomization.yaml
+++ b/test/e2e/data/kustomize/v1alpha6/kustomization.yaml
@@ -24,3 +24,8 @@ patches:
target:
kind: OpenStackCluster
name: \${CLUSTER_NAME}
+- patch: |-
+ - op: "remove"
+ path: "/spec/externalNetworkId"
+ target:
+ kind: OpenStackCluster
diff --git a/test/e2e/data/kustomize/v1alpha7/kustomization.yaml b/test/e2e/data/kustomize/v1alpha7/kustomization.yaml
index fe53c35f3f..ed5685505c 100644
--- a/test/e2e/data/kustomize/v1alpha7/kustomization.yaml
+++ b/test/e2e/data/kustomize/v1alpha7/kustomization.yaml
@@ -24,3 +24,8 @@ patches:
target:
kind: OpenStackCluster
name: \${CLUSTER_NAME}
+- patch: |-
+ - op: "remove"
+ path: "/spec/externalNetworkId"
+ target:
+ kind: OpenStackCluster
diff --git a/test/e2e/data/kustomize/without-lb/kustomization.yaml b/test/e2e/data/kustomize/without-lb/kustomization.yaml
index c36196f4ac..7f3842e60c 100644
--- a/test/e2e/data/kustomize/without-lb/kustomization.yaml
+++ b/test/e2e/data/kustomize/without-lb/kustomization.yaml
@@ -6,3 +6,4 @@ resources:
components:
- ../common-patches/cni
- ../common-patches/ccm
+- ../common-patches/externalNetworkByName
From 000b67d8b6179df6d852a6397b33d2e06c5527cc Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Fri, 8 Mar 2024 10:04:51 +0000
Subject: [PATCH 106/180] Add junit output to e2e tests
---
Makefile | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/Makefile b/Makefile
index 1a967b0f2f..d23c75d8ba 100644
--- a/Makefile
+++ b/Makefile
@@ -170,15 +170,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)
@@ -200,7 +201,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.
From 0caecf42388723e5e74e5216d60bc3d5d9993d7d Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Wed, 6 Mar 2024 19:17:12 +0000
Subject: [PATCH 107/180] Add optional.Int, optional.Bool, and
optional.Restore*
---
pkg/utils/optional/conversion.go | 54 ++++++++++++++++++++++++++++++++
pkg/utils/optional/types.go | 12 +++++++
2 files changed, 66 insertions(+)
diff --git a/pkg/utils/optional/conversion.go b/pkg/utils/optional/conversion.go
index 1876927b7a..9e98c9916f 100644
--- a/pkg/utils/optional/conversion.go
+++ b/pkg/utils/optional/conversion.go
@@ -20,6 +20,24 @@ import (
"k8s.io/apimachinery/pkg/conversion"
)
+func RestoreString(previous, dst *String) {
+ if *dst == nil || **dst == "" {
+ *dst = *previous
+ }
+}
+
+func RestoreInt(previous, dst *Int) {
+ if *dst == nil || **dst == 0 {
+ *dst = *previous
+ }
+}
+
+func RestoreBool(previous, dst *Bool) {
+ if *dst == nil || !**dst {
+ *dst = *previous
+ }
+}
+
func Convert_string_To_optional_String(in *string, out *String, _ conversion.Scope) error {
// NOTE: This function has the opposite defaulting behaviour to
// Convert_string_to_Pointer_string defined in apimachinery: it converts
@@ -41,3 +59,39 @@ func Convert_optional_String_To_string(in *String, out *string, _ conversion.Sco
}
return nil
}
+
+func Convert_int_To_optional_Int(in *int, out *Int, _ conversion.Scope) error {
+ if *in == 0 {
+ *out = nil
+ } else {
+ *out = in
+ }
+ return nil
+}
+
+func Convert_optional_Int_To_int(in *Int, out *int, _ conversion.Scope) error {
+ if *in == nil {
+ *out = 0
+ } else {
+ *out = **in
+ }
+ return nil
+}
+
+func Convert_bool_To_optional_Bool(in *bool, out *Bool, _ conversion.Scope) error {
+ if !*in {
+ *out = nil
+ } else {
+ *out = in
+ }
+ return nil
+}
+
+func Convert_optional_Bool_To_bool(in *Bool, out *bool, _ conversion.Scope) error {
+ if *in == nil {
+ *out = false
+ } else {
+ *out = **in
+ }
+ return nil
+}
diff --git a/pkg/utils/optional/types.go b/pkg/utils/optional/types.go
index c9d05ec91b..37815bfb27 100644
--- a/pkg/utils/optional/types.go
+++ b/pkg/utils/optional/types.go
@@ -19,4 +19,16 @@ package optional
// String is a string that can be unspecified. strings which are converted to
// optional.String during API conversion will be converted to nil if the value
// was previously the empty string.
+// +optional.
type String *string
+
+// Int is an int that can be unspecified. ints which are converted to
+// optional.Int during API conversion will be converted to nil if the value
+// was previously 0.
+// +optional.
+type Int *int
+
+// Bool is a bool that can be unspecified. bools which are converted to
+// optional.Bool during API conversion will be converted to nil if the value
+// was previously false.
+type Bool *bool
From cc32a8aca6cfc54cb83e8bdcc4b9b71ac6b5e1d0 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Wed, 6 Mar 2024 19:28:02 +0000
Subject: [PATCH 108/180] PortOpts: Use RestoreString optional.String fields
---
api/v1alpha7/types_conversion.go | 24 ++++++------------------
1 file changed, 6 insertions(+), 18 deletions(-)
diff --git a/api/v1alpha7/types_conversion.go b/api/v1alpha7/types_conversion.go
index f18f77269d..7b966d1320 100644
--- a/api/v1alpha7/types_conversion.go
+++ b/api/v1alpha7/types_conversion.go
@@ -21,6 +21,7 @@ import (
"k8s.io/utils/pointer"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
+ "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/optional"
)
/* SecurityGroupFilter */
@@ -200,17 +201,9 @@ func restorev1alpha7Port(previous *PortOpts, dst *PortOpts) {
}
func restorev1beta1Port(previous *infrav1.PortOpts, dst *infrav1.PortOpts) {
- if dst.NameSuffix == nil || *dst.NameSuffix == "" {
- dst.NameSuffix = previous.NameSuffix
- }
-
- if dst.Description == nil || *dst.Description == "" {
- dst.Description = previous.Description
- }
-
- if dst.MACAddress == nil || *dst.MACAddress == "" {
- dst.MACAddress = previous.MACAddress
- }
+ 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 {
@@ -234,13 +227,8 @@ func restorev1beta1Port(previous *infrav1.PortOpts, dst *infrav1.PortOpts) {
}
}
- if dst.HostID == nil || *dst.HostID == "" {
- dst.HostID = previous.HostID
- }
-
- if dst.VNICType == nil || *dst.VNICType == "" {
- dst.VNICType = previous.VNICType
- }
+ optional.RestoreString(&previous.HostID, &dst.HostID)
+ optional.RestoreString(&previous.VNICType, &dst.VNICType)
if dst.Profile == nil && previous.Profile != nil {
dst.Profile = &infrav1.BindingProfile{}
From 7a0e942324dc03674015799dc36a3fcd5940d74b Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Thu, 7 Mar 2024 11:05:01 +0000
Subject: [PATCH 109/180] make nil resource filters ToListOpts() return empty
ListOpts
This makes the behaviour slightly more ergonomic and safer as we turn
these into pointers.
---
pkg/utils/filterconvert/convert.go | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/pkg/utils/filterconvert/convert.go b/pkg/utils/filterconvert/convert.go
index 3dedad67ac..a4ba88e44f 100644
--- a/pkg/utils/filterconvert/convert.go
+++ b/pkg/utils/filterconvert/convert.go
@@ -27,6 +27,9 @@ import (
)
func SecurityGroupFilterToListOpts(securityGroupFilter *infrav1.SecurityGroupFilter) securitygroups.ListOpts {
+ if securityGroupFilter == nil {
+ return securitygroups.ListOpts{}
+ }
return securitygroups.ListOpts{
ID: securityGroupFilter.ID,
Name: securityGroupFilter.Name,
@@ -40,6 +43,9 @@ func SecurityGroupFilterToListOpts(securityGroupFilter *infrav1.SecurityGroupFil
}
func SubnetFilterToListOpts(subnetFilter *infrav1.SubnetFilter) subnets.ListOpts {
+ if subnetFilter == nil {
+ return subnets.ListOpts{}
+ }
return subnets.ListOpts{
Name: subnetFilter.Name,
Description: subnetFilter.Description,
@@ -58,6 +64,9 @@ func SubnetFilterToListOpts(subnetFilter *infrav1.SubnetFilter) subnets.ListOpts
}
func NetworkFilterToListOpts(networkFilter *infrav1.NetworkFilter) networks.ListOpts {
+ if networkFilter == nil {
+ return networks.ListOpts{}
+ }
return networks.ListOpts{
Name: networkFilter.Name,
Description: networkFilter.Description,
@@ -71,6 +80,9 @@ func NetworkFilterToListOpts(networkFilter *infrav1.NetworkFilter) networks.List
}
func RouterFilterToListOpts(routerFilter *infrav1.RouterFilter) routers.ListOpts {
+ if routerFilter == nil {
+ return routers.ListOpts{}
+ }
return routers.ListOpts{
ID: routerFilter.ID,
Name: routerFilter.Name,
@@ -84,6 +96,9 @@ func RouterFilterToListOpts(routerFilter *infrav1.RouterFilter) routers.ListOpts
}
func ImageFilterToListOpts(imageFilter *infrav1.ImageFilter) images.ListOpts {
+ if imageFilter == nil {
+ return images.ListOpts{}
+ }
return images.ListOpts{
ID: imageFilter.ID,
Name: imageFilter.Name,
From cdc16d2efdb4b813c2101e18194b1e9abc591520 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Thu, 7 Mar 2024 20:41:37 +0000
Subject: [PATCH 110/180] Make NetworkFilter.IsEmpty() return true on nil
receiver
This improves safety and ergonomics checking it when NetworkFilter can be be a
pointer type.
---
api/v1alpha6/openstackcluster_conversion.go | 4 ++++
api/v1alpha7/openstackcluster_conversion.go | 4 ++++
api/v1beta1/types.go | 3 +++
pkg/cloud/services/networking/port.go | 2 +-
4 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/api/v1alpha6/openstackcluster_conversion.go b/api/v1alpha6/openstackcluster_conversion.go
index b8aac5aa5a..5749551667 100644
--- a/api/v1alpha6/openstackcluster_conversion.go
+++ b/api/v1alpha6/openstackcluster_conversion.go
@@ -162,6 +162,10 @@ func restorev1alpha6ClusterSpec(previous *OpenStackClusterSpec, dst *OpenStackCl
func restorev1beta1ClusterSpec(previous *infrav1.OpenStackClusterSpec, dst *infrav1.OpenStackClusterSpec) {
// Bastion is restored separately
+ if dst.Network.IsEmpty() {
+ dst.Network = previous.Network
+ }
+
// Restore all fields except ID, which should have been copied over in conversion
dst.ExternalNetwork.Name = previous.ExternalNetwork.Name
dst.ExternalNetwork.Description = previous.ExternalNetwork.Description
diff --git a/api/v1alpha7/openstackcluster_conversion.go b/api/v1alpha7/openstackcluster_conversion.go
index 5761f11f8c..f25e1f2eca 100644
--- a/api/v1alpha7/openstackcluster_conversion.go
+++ b/api/v1alpha7/openstackcluster_conversion.go
@@ -167,6 +167,10 @@ func restorev1alpha7ClusterSpec(previous *OpenStackClusterSpec, dst *OpenStackCl
func restorev1beta1ClusterSpec(previous *infrav1.OpenStackClusterSpec, dst *infrav1.OpenStackClusterSpec) {
// Bastion is restored separately
+ if dst.Network.IsEmpty() {
+ dst.Network = previous.Network
+ }
+
// Restore all fields except ID, which should have been copied over in conversion
dst.ExternalNetwork.Name = previous.ExternalNetwork.Name
dst.ExternalNetwork.Description = previous.ExternalNetwork.Description
diff --git a/api/v1beta1/types.go b/api/v1beta1/types.go
index 4b31458b4b..1ef0a9f49a 100644
--- a/api/v1beta1/types.go
+++ b/api/v1beta1/types.go
@@ -94,6 +94,9 @@ type NetworkFilter struct {
}
func (networkFilter *NetworkFilter) IsEmpty() bool {
+ if networkFilter == nil {
+ return true
+ }
return networkFilter.Name == "" &&
networkFilter.Description == "" &&
networkFilter.ProjectID == "" &&
diff --git a/pkg/cloud/services/networking/port.go b/pkg/cloud/services/networking/port.go
index 305c58d71a..e651ba992c 100644
--- a/pkg/cloud/services/networking/port.go
+++ b/pkg/cloud/services/networking/port.go
@@ -423,7 +423,7 @@ func (s *Service) normalizePorts(ports []infrav1.PortOpts, openStackCluster *inf
// normalizePortTarget ensures that the port has a network ID.
func (s *Service) normalizePortTarget(port *infrav1.PortOpts, openStackCluster *infrav1.OpenStackCluster, portIdx int) error {
// Treat no Network and empty Network the same
- noNetwork := port.Network == nil || port.Network.IsEmpty()
+ noNetwork := port.Network.IsEmpty()
// No network or subnets defined: use cluster defaults
if noNetwork && len(port.FixedIPs) == 0 {
From 2d96db634dcc83af91a96917000033e65ec2ffba Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Wed, 6 Mar 2024 17:18:46 +0000
Subject: [PATCH 111/180] OpenStackCluster: Add explicit optional tags
---
api/v1beta1/openstackcluster_types.go | 12 ++++++++++++
docs/book/src/api/v1beta1/api.md | 20 ++++++++++++++++++++
2 files changed, 32 insertions(+)
diff --git a/api/v1beta1/openstackcluster_types.go b/api/v1beta1/openstackcluster_types.go
index 3a3fe803c0..94810c487c 100644
--- a/api/v1beta1/openstackcluster_types.go
+++ b/api/v1beta1/openstackcluster_types.go
@@ -34,6 +34,7 @@ type OpenStackClusterSpec struct {
// 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
+ // +optional
ManagedSubnets []SubnetSpec `json:"managedSubnets,omitempty"`
// Router specifies an existing router to be used if ManagedSubnets are
@@ -63,6 +64,7 @@ type OpenStackClusterSpec struct {
// ExternalRouterIPs is an array of externalIPs on the respective subnets.
// This is necessary if the router needs a fixed ip in a specific subnet.
+ // +optional
ExternalRouterIPs []ExternalRouterIPParam `json:"externalRouterIPs,omitempty"`
// ExternalNetwork is the OpenStack Network to be used to get public internet to the VMs.
@@ -131,6 +133,7 @@ type OpenStackClusterSpec struct {
// Tags for all resources in cluster
// +listType=set
+ // +optional
Tags []string `json:"tags,omitempty"`
// ControlPlaneEndpoint represents the endpoint used to communicate with the control plane.
@@ -139,6 +142,7 @@ type OpenStackClusterSpec struct {
// ControlPlaneAvailabilityZones is the az to deploy control plane to
// +listType=set
+ // +optional
ControlPlaneAvailabilityZones []string `json:"controlPlaneAvailabilityZones,omitempty"`
// Indicates whether to omit the az for control plane nodes, allowing the Nova scheduler
@@ -167,15 +171,19 @@ type OpenStackClusterStatus struct {
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.
+ // +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
@@ -184,14 +192,18 @@ type OpenStackClusterStatus struct {
// 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?
+ // +optional
ControlPlaneSecurityGroup *SecurityGroupStatus `json:"controlPlaneSecurityGroup,omitempty"`
// WorkerSecurityGroup contains all the information about the OpenStack Security
// Group that needs to be applied to worker nodes.
+ // +optional
WorkerSecurityGroup *SecurityGroupStatus `json:"workerSecurityGroup,omitempty"`
+ // +optional
BastionSecurityGroup *SecurityGroupStatus `json:"bastionSecurityGroup,omitempty"`
+ // +optional
Bastion *BastionStatus `json:"bastion,omitempty"`
// FailureReason will be set in the event that there is a terminal problem
diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md
index 311b73e3cf..9a26f78c95 100644
--- a/docs/book/src/api/v1beta1/api.md
+++ b/docs/book/src/api/v1beta1/api.md
@@ -77,6 +77,7 @@ OpenStackClusterSpec
|
+(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.
@@ -154,6 +155,7 @@ To use this field, the Openstack installation requires the net-mtu neutron API e
|
+(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.
|
@@ -308,6 +310,7 @@ Kubernetes cluster, which also disables SecurityGroups
+(Optional)
Tags for all resources in cluster
|
@@ -333,6 +336,7 @@ sigs.k8s.io/cluster-api/api/v1beta1.APIEndpoint
+(Optional)
ControlPlaneAvailabilityZones is the az to deploy control plane to
|
@@ -1951,6 +1955,7 @@ It may not be empty and may not contain commas.
+(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.
@@ -2028,6 +2033,7 @@ To use this field, the Openstack installation requires the net-mtu neutron API e
|
+(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.
|
@@ -2182,6 +2188,7 @@ Kubernetes cluster, which also disables SecurityGroups
+(Optional)
Tags for all resources in cluster
|
@@ -2207,6 +2214,7 @@ sigs.k8s.io/cluster-api/api/v1beta1.APIEndpoint
+(Optional)
ControlPlaneAvailabilityZones is the az to deploy control plane to
|
@@ -2294,6 +2302,7 @@ NetworkStatusWithSubnets
+(Optional)
Network contains information about the created OpenStack Network.
|
@@ -2307,6 +2316,7 @@ NetworkStatus
+(Optional)
externalNetwork contains information about the external network used for default ingress and egress traffic.
|
@@ -2320,6 +2330,7 @@ Router
+(Optional)
Router describes the default cluster router
|
@@ -2333,6 +2344,7 @@ LoadBalancer
+(Optional)
APIServerLoadBalancer describes the api server load balancer if one exists
|
@@ -2359,6 +2371,7 @@ SecurityGroupStatus
+(Optional)
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?
@@ -2374,6 +2387,7 @@ SecurityGroupStatus
|
+(Optional)
WorkerSecurityGroup contains all the information about the OpenStack Security
Group that needs to be applied to worker nodes.
|
@@ -2388,6 +2402,7 @@ SecurityGroupStatus
+(Optional)
|
@@ -2400,6 +2415,7 @@ BastionStatus
|
+(Optional)
|
@@ -2496,6 +2512,7 @@ OpenStackClusterSpec
|
+(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.
@@ -2573,6 +2590,7 @@ To use this field, the Openstack installation requires the net-mtu neutron API e
|
+(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.
|
@@ -2727,6 +2745,7 @@ Kubernetes cluster, which also disables SecurityGroups
+(Optional)
Tags for all resources in cluster
|
@@ -2752,6 +2771,7 @@ sigs.k8s.io/cluster-api/api/v1beta1.APIEndpoint
+(Optional)
ControlPlaneAvailabilityZones is the az to deploy control plane to
|
From 75079c728e78395ccf59b54cef6753902fc427de Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Wed, 6 Mar 2024 17:25:31 +0000
Subject: [PATCH 112/180] OpenStackCluster: Set explicit listType=atomic
For non-mergeable list types, make the default 'atomic' behaviour
explicit.
---
api/v1beta1/openstackcluster_types.go | 3 +++
.../infrastructure.cluster.x-k8s.io_openstackclusters.yaml | 3 +++
...rastructure.cluster.x-k8s.io_openstackclustertemplates.yaml | 3 +++
3 files changed, 9 insertions(+)
diff --git a/api/v1beta1/openstackcluster_types.go b/api/v1beta1/openstackcluster_types.go
index 94810c487c..766c56be2e 100644
--- a/api/v1beta1/openstackcluster_types.go
+++ b/api/v1beta1/openstackcluster_types.go
@@ -34,6 +34,7 @@ type OpenStackClusterSpec struct {
// 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
ManagedSubnets []SubnetSpec `json:"managedSubnets,omitempty"`
@@ -52,6 +53,7 @@ type OpenStackClusterSpec struct {
// 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 []SubnetFilter `json:"subnets,omitempty"`
@@ -64,6 +66,7 @@ type OpenStackClusterSpec struct {
// 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"`
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 afe2b5c726..5d39bed3ab 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -5736,6 +5736,7 @@ spec:
- subnet
type: object
type: array
+ x-kubernetes-list-type: atomic
identityRef:
description: |-
IdentityRef is a reference to a secret holding OpenStack credentials
@@ -5893,6 +5894,7 @@ spec:
type: object
maxItems: 1
type: array
+ x-kubernetes-list-type: atomic
network:
description: |-
Network specifies an existing network to use if no ManagedSubnets
@@ -6117,6 +6119,7 @@ spec:
type: object
maxItems: 2
type: array
+ x-kubernetes-list-type: atomic
tags:
description: Tags for all resources in cluster
items:
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 550887a8a6..794607a76e 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -3168,6 +3168,7 @@ spec:
- subnet
type: object
type: array
+ x-kubernetes-list-type: atomic
identityRef:
description: |-
IdentityRef is a reference to a secret holding OpenStack credentials
@@ -3327,6 +3328,7 @@ spec:
type: object
maxItems: 1
type: array
+ x-kubernetes-list-type: atomic
network:
description: |-
Network specifies an existing network to use if no ManagedSubnets
@@ -3551,6 +3553,7 @@ spec:
type: object
maxItems: 2
type: array
+ x-kubernetes-list-type: atomic
tags:
description: Tags for all resources in cluster
items:
From ffbfd403236d04b8860741c4a3b4cd275094d8fa Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Mon, 19 Feb 2024 15:24:38 +0000
Subject: [PATCH 113/180] OpenStackClusterSpec: Network->pointer
---
api/v1alpha5/conversion_test.go | 12 ++++++------
api/v1alpha5/zz_generated.conversion.go | 8 ++------
api/v1alpha6/openstackcluster_conversion.go | 13 +++++++++++++
api/v1alpha6/zz_generated.conversion.go | 8 ++------
api/v1alpha7/openstackcluster_conversion.go | 13 +++++++++++++
api/v1alpha7/zz_generated.conversion.go | 8 ++------
api/v1beta1/openstackcluster_types.go | 3 ++-
api/v1beta1/zz_generated.deepcopy.go | 6 +++++-
controllers/openstackcluster_controller_test.go | 4 ++--
docs/book/src/api/v1beta1/api.md | 3 +++
.../suites/apivalidations/neutronfilters_test.go | 4 ++--
11 files changed, 52 insertions(+), 30 deletions(-)
diff --git a/api/v1alpha5/conversion_test.go b/api/v1alpha5/conversion_test.go
index 1ecbf00a13..6698c73a4c 100644
--- a/api/v1alpha5/conversion_test.go
+++ b/api/v1alpha5/conversion_test.go
@@ -40,7 +40,7 @@ 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{},
@@ -51,13 +51,13 @@ func TestConvertFrom(t *testing.T) {
},
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
- "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"apiServerLoadBalancer\":{},\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"disableExternalNetwork\":false,\"externalNetwork\":{},\"identityRef\":{\"cloudName\":\"\",\"name\":\"\"},\"network\":{}},\"status\":{\"ready\":false}}",
+ "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"apiServerLoadBalancer\":{},\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"disableExternalNetwork\":false,\"externalNetwork\":{},\"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{},
@@ -72,13 +72,13 @@ func TestConvertFrom(t *testing.T) {
},
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
- "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"template\":{\"spec\":{\"apiServerLoadBalancer\":{},\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"disableExternalNetwork\":false,\"externalNetwork\":{},\"identityRef\":{\"cloudName\":\"\",\"name\":\"\"},\"network\":{}}}}}",
+ "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"template\":{\"spec\":{\"apiServerLoadBalancer\":{},\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"disableExternalNetwork\":false,\"externalNetwork\":{},\"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{},
@@ -93,7 +93,7 @@ func TestConvertFrom(t *testing.T) {
},
},
{
- name: "conversion must have conversion-data annotation",
+ name: "machine template conversion must have conversion-data annotation",
spoke: &OpenStackMachineTemplate{},
hub: &infrav1.OpenStackMachineTemplate{
Spec: infrav1.OpenStackMachineTemplateSpec{},
diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go
index 646ce0a938..9bf9a1d331 100644
--- a/api/v1alpha5/zz_generated.conversion.go
+++ b/api/v1alpha5/zz_generated.conversion.go
@@ -659,9 +659,7 @@ func Convert_v1beta1_OpenStackClusterList_To_v1alpha5_OpenStackClusterList(in *v
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
- if err := Convert_v1alpha5_NetworkFilter_To_v1beta1_NetworkFilter(&in.Network, &out.Network, s); err != nil {
- return err
- }
+ // 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.NetworkFilter)
// 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 {
@@ -705,9 +703,7 @@ func autoConvert_v1alpha5_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(i
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_v1beta1_NetworkFilter_To_v1alpha5_NetworkFilter(&in.Network, &out.Network, s); err != nil {
- return err
- }
+ // WARNING: in.Network 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)
// WARNING: in.Subnets requires manual conversion: does not exist in peer-type
// WARNING: in.NetworkMTU requires manual conversion: does not exist in peer-type
if in.ExternalRouterIPs != nil {
diff --git a/api/v1alpha6/openstackcluster_conversion.go b/api/v1alpha6/openstackcluster_conversion.go
index 5749551667..78eb76e12e 100644
--- a/api/v1alpha6/openstackcluster_conversion.go
+++ b/api/v1alpha6/openstackcluster_conversion.go
@@ -197,6 +197,13 @@ func Convert_v1alpha6_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *O
return err
}
+ if in.Network != (NetworkFilter{}) {
+ out.Network = &infrav1.NetworkFilter{}
+ if err := Convert_v1alpha6_NetworkFilter_To_v1beta1_NetworkFilter(&in.Network, out.Network, s); err != nil {
+ return err
+ }
+ }
+
if in.ExternalNetworkID != "" {
out.ExternalNetwork = infrav1.NetworkFilter{
ID: in.ExternalNetworkID,
@@ -245,6 +252,12 @@ func Convert_v1beta1_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(in *i
return err
}
+ if in.Network != nil {
+ if err := Convert_v1beta1_NetworkFilter_To_v1alpha6_NetworkFilter(in.Network, &out.Network, s); err != nil {
+ return err
+ }
+ }
+
if in.ExternalNetwork.ID != "" {
out.ExternalNetworkID = in.ExternalNetwork.ID
}
diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go
index dafa54171b..04ad0264bc 100644
--- a/api/v1alpha6/zz_generated.conversion.go
+++ b/api/v1alpha6/zz_generated.conversion.go
@@ -685,9 +685,7 @@ func Convert_v1beta1_OpenStackClusterList_To_v1alpha6_OpenStackClusterList(in *v
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
- if err := Convert_v1alpha6_NetworkFilter_To_v1beta1_NetworkFilter(&in.Network, &out.Network, s); err != nil {
- return err
- }
+ // 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.NetworkFilter)
// 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 {
@@ -732,9 +730,7 @@ func autoConvert_v1alpha6_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(i
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_v1beta1_NetworkFilter_To_v1alpha6_NetworkFilter(&in.Network, &out.Network, s); err != nil {
- return err
- }
+ // WARNING: in.Network 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)
// WARNING: in.Subnets requires manual conversion: does not exist in peer-type
// WARNING: in.NetworkMTU requires manual conversion: does not exist in peer-type
if in.ExternalRouterIPs != nil {
diff --git a/api/v1alpha7/openstackcluster_conversion.go b/api/v1alpha7/openstackcluster_conversion.go
index f25e1f2eca..3a9ce80707 100644
--- a/api/v1alpha7/openstackcluster_conversion.go
+++ b/api/v1alpha7/openstackcluster_conversion.go
@@ -199,6 +199,13 @@ func Convert_v1alpha7_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *O
return err
}
+ if in.Network != (NetworkFilter{}) {
+ out.Network = &infrav1.NetworkFilter{}
+ if err := Convert_v1alpha7_NetworkFilter_To_v1beta1_NetworkFilter(&in.Network, out.Network, s); err != nil {
+ return err
+ }
+ }
+
if in.ExternalNetworkID != "" {
out.ExternalNetwork = infrav1.NetworkFilter{
ID: in.ExternalNetworkID,
@@ -247,6 +254,12 @@ func Convert_v1beta1_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in *i
return err
}
+ if in.Network != nil {
+ if err := Convert_v1beta1_NetworkFilter_To_v1alpha7_NetworkFilter(in.Network, &out.Network, s); err != nil {
+ return err
+ }
+ }
+
if in.ExternalNetwork.ID != "" {
out.ExternalNetworkID = in.ExternalNetwork.ID
}
diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go
index 2cbd5b0184..63f859f049 100644
--- a/api/v1alpha7/zz_generated.conversion.go
+++ b/api/v1alpha7/zz_generated.conversion.go
@@ -899,9 +899,7 @@ func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(i
} else {
out.Router = nil
}
- if err := Convert_v1alpha7_NetworkFilter_To_v1beta1_NetworkFilter(&in.Network, &out.Network, s); err != nil {
- return err
- }
+ // 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.NetworkFilter)
// WARNING: in.Subnet requires manual conversion: does not exist in peer-type
out.NetworkMTU = in.NetworkMTU
// WARNING: in.DNSNameservers requires manual conversion: does not exist in peer-type
@@ -955,9 +953,7 @@ func autoConvert_v1beta1_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(i
} else {
out.Router = nil
}
- if err := Convert_v1beta1_NetworkFilter_To_v1alpha7_NetworkFilter(&in.Network, &out.Network, s); err != nil {
- return err
- }
+ // WARNING: in.Network requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.NetworkFilter vs sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7.NetworkFilter)
// WARNING: in.Subnets requires manual conversion: does not exist in peer-type
out.NetworkMTU = in.NetworkMTU
if in.ExternalRouterIPs != nil {
diff --git a/api/v1beta1/openstackcluster_types.go b/api/v1beta1/openstackcluster_types.go
index 766c56be2e..dd9e1dea66 100644
--- a/api/v1beta1/openstackcluster_types.go
+++ b/api/v1beta1/openstackcluster_types.go
@@ -45,7 +45,8 @@ type OpenStackClusterSpec struct {
// Network specifies an existing network to use if no ManagedSubnets
// are specified.
- Network NetworkFilter `json:"network,omitempty"`
+ // +optional
+ Network *NetworkFilter `json:"network,omitempty"`
// Subnets specifies existing subnets to use if not ManagedSubnets are
// specified. All subnets must be in the network specified by Network.
diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go
index cd5c538ffa..7edddb44d6 100644
--- a/api/v1beta1/zz_generated.deepcopy.go
+++ b/api/v1beta1/zz_generated.deepcopy.go
@@ -492,7 +492,11 @@ func (in *OpenStackClusterSpec) DeepCopyInto(out *OpenStackClusterSpec) {
*out = new(RouterFilter)
(*in).DeepCopyInto(*out)
}
- in.Network.DeepCopyInto(&out.Network)
+ if in.Network != nil {
+ in, out := &in.Network, &out.Network
+ *out = new(NetworkFilter)
+ (*in).DeepCopyInto(*out)
+ }
if in.Subnets != nil {
in, out := &in.Subnets, &out.Subnets
*out = make([]SubnetFilter, len(*in))
diff --git a/controllers/openstackcluster_controller_test.go b/controllers/openstackcluster_controller_test.go
index 971d0308d2..7512376149 100644
--- a/controllers/openstackcluster_controller_test.go
+++ b/controllers/openstackcluster_controller_test.go
@@ -524,7 +524,7 @@ var _ = Describe("OpenStackCluster controller", func() {
ExternalNetwork: infrav1.NetworkFilter{
ID: externalNetworkID,
},
- Network: infrav1.NetworkFilter{
+ Network: &infrav1.NetworkFilter{
ID: clusterNetworkID,
},
}
@@ -603,7 +603,7 @@ var _ = Describe("OpenStackCluster controller", func() {
ExternalNetwork: infrav1.NetworkFilter{
ID: externalNetworkID,
},
- Network: infrav1.NetworkFilter{
+ Network: &infrav1.NetworkFilter{
ID: clusterNetworkID,
},
Subnets: []infrav1.SubnetFilter{
diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md
index 9a26f78c95..c118ced103 100644
--- a/docs/book/src/api/v1beta1/api.md
+++ b/docs/book/src/api/v1beta1/api.md
@@ -108,6 +108,7 @@ NetworkFilter
+(Optional)
Network specifies an existing network to use if no ManagedSubnets
are specified.
|
@@ -1986,6 +1987,7 @@ NetworkFilter
+(Optional)
Network specifies an existing network to use if no ManagedSubnets
are specified.
|
@@ -2543,6 +2545,7 @@ NetworkFilter
+(Optional)
Network specifies an existing network to use if no ManagedSubnets
are specified.
|
diff --git a/test/e2e/suites/apivalidations/neutronfilters_test.go b/test/e2e/suites/apivalidations/neutronfilters_test.go
index 540cb815c0..e5a1e65dcd 100644
--- a/test/e2e/suites/apivalidations/neutronfilters_test.go
+++ b/test/e2e/suites/apivalidations/neutronfilters_test.go
@@ -73,7 +73,7 @@ var _ = Describe("Neutron filter API validations", func() {
}
cluster.Spec.Subnets = subnets
if len(tags) > 0 {
- cluster.Spec.Network = infrav1.NetworkFilter{FilterByNeutronTags: tags[0]}
+ cluster.Spec.Network = &infrav1.NetworkFilter{FilterByNeutronTags: tags[0]}
cluster.Spec.ExternalNetwork = infrav1.NetworkFilter{FilterByNeutronTags: tags[0]}
cluster.Spec.Router = &infrav1.RouterFilter{FilterByNeutronTags: tags[0]}
}
@@ -137,7 +137,7 @@ var _ = Describe("Neutron filter API validations", func() {
{
cluster := cluster.DeepCopy()
- cluster.Spec.Network = infrav1.NetworkFilter{FilterByNeutronTags: tag}
+ cluster.Spec.Network = &infrav1.NetworkFilter{FilterByNeutronTags: tag}
Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should fail with invalid network neutron tags")
}
From e39c7302a3b297d38744ea1a7e04b816183733dd Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Mon, 19 Feb 2024 16:57:48 +0000
Subject: [PATCH 114/180] OpenStackClusterSpec: ExternalNetwork->pointer
ExternalNetwork was already marked optional. This change allows it to be
omitted when marshalling and unmarshalling the object in Go.
This change also adds the 'external' flag when executing an explicit
external network query.
---
api/v1alpha5/conversion.go | 4 +--
api/v1alpha5/conversion_test.go | 4 +--
api/v1alpha6/openstackcluster_conversion.go | 24 ++++++++-----
api/v1alpha7/openstackcluster_conversion.go | 24 ++++++++-----
api/v1beta1/openstackcluster_types.go | 15 ++++++--
api/v1beta1/zz_generated.deepcopy.go | 6 +++-
...re.cluster.x-k8s.io_openstackclusters.yaml | 20 +++++++++--
...er.x-k8s.io_openstackclustertemplates.yaml | 20 +++++++++--
controllers/openstackcluster_controller.go | 2 +-
.../openstackcluster_controller_test.go | 7 ++--
docs/book/src/api/v1beta1/api.md | 36 +++++++++++++++----
pkg/cloud/services/networking/network.go | 20 +++--------
pkg/cloud/services/networking/network_test.go | 22 ++++++------
.../apivalidations/neutronfilters_test.go | 4 +--
14 files changed, 141 insertions(+), 67 deletions(-)
diff --git a/api/v1alpha5/conversion.go b/api/v1alpha5/conversion.go
index 9fb404b9e7..ddc36a82f2 100644
--- a/api/v1alpha5/conversion.go
+++ b/api/v1alpha5/conversion.go
@@ -205,7 +205,7 @@ func Convert_v1beta1_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(in *i
return err
}
- if in.ExternalNetwork.ID != "" {
+ if in.ExternalNetwork != nil && in.ExternalNetwork.ID != "" {
out.ExternalNetworkID = in.ExternalNetwork.ID
}
@@ -240,7 +240,7 @@ func Convert_v1alpha5_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *O
}
if in.ExternalNetworkID != "" {
- out.ExternalNetwork = infrav1.NetworkFilter{
+ out.ExternalNetwork = &infrav1.NetworkFilter{
ID: in.ExternalNetworkID,
}
}
diff --git a/api/v1alpha5/conversion_test.go b/api/v1alpha5/conversion_test.go
index 6698c73a4c..d2b7a58ef2 100644
--- a/api/v1alpha5/conversion_test.go
+++ b/api/v1alpha5/conversion_test.go
@@ -51,7 +51,7 @@ func TestConvertFrom(t *testing.T) {
},
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
- "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"apiServerLoadBalancer\":{},\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"disableExternalNetwork\":false,\"externalNetwork\":{},\"identityRef\":{\"cloudName\":\"\",\"name\":\"\"}},\"status\":{\"ready\":false}}",
+ "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"apiServerLoadBalancer\":{},\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"disableExternalNetwork\":false,\"identityRef\":{\"cloudName\":\"\",\"name\":\"\"}},\"status\":{\"ready\":false}}",
},
},
},
@@ -72,7 +72,7 @@ func TestConvertFrom(t *testing.T) {
},
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
- "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"template\":{\"spec\":{\"apiServerLoadBalancer\":{},\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"disableExternalNetwork\":false,\"externalNetwork\":{},\"identityRef\":{\"cloudName\":\"\",\"name\":\"\"}}}}}",
+ "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"template\":{\"spec\":{\"apiServerLoadBalancer\":{},\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"disableExternalNetwork\":false,\"identityRef\":{\"cloudName\":\"\",\"name\":\"\"}}}}}",
},
},
},
diff --git a/api/v1alpha6/openstackcluster_conversion.go b/api/v1alpha6/openstackcluster_conversion.go
index 78eb76e12e..1cf9cd7d82 100644
--- a/api/v1alpha6/openstackcluster_conversion.go
+++ b/api/v1alpha6/openstackcluster_conversion.go
@@ -167,13 +167,19 @@ func restorev1beta1ClusterSpec(previous *infrav1.OpenStackClusterSpec, dst *infr
}
// Restore all fields except ID, which should have been copied over in conversion
- dst.ExternalNetwork.Name = previous.ExternalNetwork.Name
- dst.ExternalNetwork.Description = previous.ExternalNetwork.Description
- dst.ExternalNetwork.ProjectID = previous.ExternalNetwork.ProjectID
- dst.ExternalNetwork.Tags = previous.ExternalNetwork.Tags
- dst.ExternalNetwork.TagsAny = previous.ExternalNetwork.TagsAny
- dst.ExternalNetwork.NotTags = previous.ExternalNetwork.NotTags
- dst.ExternalNetwork.NotTagsAny = previous.ExternalNetwork.NotTagsAny
+ if previous.ExternalNetwork != nil {
+ if dst.ExternalNetwork == nil {
+ dst.ExternalNetwork = &infrav1.NetworkFilter{}
+ }
+
+ dst.ExternalNetwork.Name = previous.ExternalNetwork.Name
+ dst.ExternalNetwork.Description = previous.ExternalNetwork.Description
+ dst.ExternalNetwork.ProjectID = previous.ExternalNetwork.ProjectID
+ dst.ExternalNetwork.Tags = previous.ExternalNetwork.Tags
+ dst.ExternalNetwork.TagsAny = previous.ExternalNetwork.TagsAny
+ dst.ExternalNetwork.NotTags = previous.ExternalNetwork.NotTags
+ dst.ExternalNetwork.NotTagsAny = previous.ExternalNetwork.NotTagsAny
+ }
// Restore fields not present in v1alpha6
dst.Router = previous.Router
@@ -205,7 +211,7 @@ func Convert_v1alpha6_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *O
}
if in.ExternalNetworkID != "" {
- out.ExternalNetwork = infrav1.NetworkFilter{
+ out.ExternalNetwork = &infrav1.NetworkFilter{
ID: in.ExternalNetworkID,
}
}
@@ -258,7 +264,7 @@ func Convert_v1beta1_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(in *i
}
}
- if in.ExternalNetwork.ID != "" {
+ if in.ExternalNetwork != nil && in.ExternalNetwork.ID != "" {
out.ExternalNetworkID = in.ExternalNetwork.ID
}
diff --git a/api/v1alpha7/openstackcluster_conversion.go b/api/v1alpha7/openstackcluster_conversion.go
index 3a9ce80707..d5c26ff9a9 100644
--- a/api/v1alpha7/openstackcluster_conversion.go
+++ b/api/v1alpha7/openstackcluster_conversion.go
@@ -172,13 +172,19 @@ func restorev1beta1ClusterSpec(previous *infrav1.OpenStackClusterSpec, dst *infr
}
// Restore all fields except ID, which should have been copied over in conversion
- dst.ExternalNetwork.Name = previous.ExternalNetwork.Name
- dst.ExternalNetwork.Description = previous.ExternalNetwork.Description
- dst.ExternalNetwork.ProjectID = previous.ExternalNetwork.ProjectID
- dst.ExternalNetwork.Tags = previous.ExternalNetwork.Tags
- dst.ExternalNetwork.TagsAny = previous.ExternalNetwork.TagsAny
- dst.ExternalNetwork.NotTags = previous.ExternalNetwork.NotTags
- dst.ExternalNetwork.NotTagsAny = previous.ExternalNetwork.NotTagsAny
+ if previous.ExternalNetwork != nil {
+ if dst.ExternalNetwork == nil {
+ dst.ExternalNetwork = &infrav1.NetworkFilter{}
+ }
+
+ dst.ExternalNetwork.Name = previous.ExternalNetwork.Name
+ dst.ExternalNetwork.Description = previous.ExternalNetwork.Description
+ dst.ExternalNetwork.ProjectID = previous.ExternalNetwork.ProjectID
+ dst.ExternalNetwork.Tags = previous.ExternalNetwork.Tags
+ dst.ExternalNetwork.TagsAny = previous.ExternalNetwork.TagsAny
+ dst.ExternalNetwork.NotTags = previous.ExternalNetwork.NotTags
+ dst.ExternalNetwork.NotTagsAny = previous.ExternalNetwork.NotTagsAny
+ }
dst.DisableExternalNetwork = previous.DisableExternalNetwork
@@ -207,7 +213,7 @@ func Convert_v1alpha7_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *O
}
if in.ExternalNetworkID != "" {
- out.ExternalNetwork = infrav1.NetworkFilter{
+ out.ExternalNetwork = &infrav1.NetworkFilter{
ID: in.ExternalNetworkID,
}
}
@@ -260,7 +266,7 @@ func Convert_v1beta1_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in *i
}
}
- if in.ExternalNetwork.ID != "" {
+ if in.ExternalNetwork != nil && in.ExternalNetwork.ID != "" {
out.ExternalNetworkID = in.ExternalNetwork.ID
}
diff --git a/api/v1beta1/openstackcluster_types.go b/api/v1beta1/openstackcluster_types.go
index dd9e1dea66..9a4a3ad9be 100644
--- a/api/v1beta1/openstackcluster_types.go
+++ b/api/v1beta1/openstackcluster_types.go
@@ -72,10 +72,21 @@ type OpenStackClusterSpec struct {
ExternalRouterIPs []ExternalRouterIPParam `json:"externalRouterIPs,omitempty"`
// 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 NetworkFilter `json:"externalNetwork,omitempty"`
+ ExternalNetwork *NetworkFilter `json:"externalNetwork,omitempty"`
- // DisableExternalNetwork determines whether or not to attempt to connect the cluster
+ // 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
diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go
index 7edddb44d6..a642946cbd 100644
--- a/api/v1beta1/zz_generated.deepcopy.go
+++ b/api/v1beta1/zz_generated.deepcopy.go
@@ -511,7 +511,11 @@ func (in *OpenStackClusterSpec) DeepCopyInto(out *OpenStackClusterSpec) {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
- in.ExternalNetwork.DeepCopyInto(&out.ExternalNetwork)
+ if in.ExternalNetwork != nil {
+ in, out := &in.ExternalNetwork, &out.ExternalNetwork
+ *out = new(NetworkFilter)
+ (*in).DeepCopyInto(*out)
+ }
in.APIServerLoadBalancer.DeepCopyInto(&out.APIServerLoadBalancer)
if in.ManagedSecurityGroups != nil {
in, out := &in.ManagedSecurityGroups, &out.ManagedSecurityGroups
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 5d39bed3ab..9e8f44f067 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -5572,7 +5572,7 @@ spec:
type: boolean
disableExternalNetwork:
description: |-
- DisableExternalNetwork determines whether or not to attempt to connect the cluster
+ 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
@@ -5582,8 +5582,22 @@ spec:
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.
+ 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.
properties:
description:
type: string
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 794607a76e..4149022c39 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -3004,7 +3004,7 @@ spec:
type: boolean
disableExternalNetwork:
description: |-
- DisableExternalNetwork determines whether or not to attempt to connect the cluster
+ 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
@@ -3014,8 +3014,22 @@ spec:
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.
+ 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.
properties:
description:
type: string
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index eea38455f2..e19d605a12 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -634,7 +634,7 @@ func reconcilePreExistingNetworkComponents(scope *scope.WithLogger, networkingSe
}
if !openStackCluster.Spec.Network.IsEmpty() {
- netOpts := filterconvert.NetworkFilterToListOpts(&openStackCluster.Spec.Network)
+ netOpts := filterconvert.NetworkFilterToListOpts(openStackCluster.Spec.Network)
networkList, err := networkingService.GetNetworksByFilter(&netOpts)
if err != nil {
handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to find network: %w", err))
diff --git a/controllers/openstackcluster_controller_test.go b/controllers/openstackcluster_controller_test.go
index 7512376149..0bd5e68bde 100644
--- a/controllers/openstackcluster_controller_test.go
+++ b/controllers/openstackcluster_controller_test.go
@@ -34,6 +34,7 @@ import (
. "github.com/onsi/gomega"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
+ "k8s.io/utils/pointer"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
"sigs.k8s.io/cluster-api/test/framework"
"sigs.k8s.io/cluster-api/util/annotations"
@@ -521,7 +522,7 @@ var _ = Describe("OpenStackCluster controller", func() {
},
DisableAPIServerFloatingIP: true,
APIServerFixedIP: "10.0.0.1",
- ExternalNetwork: infrav1.NetworkFilter{
+ ExternalNetwork: &infrav1.NetworkFilter{
ID: externalNetworkID,
},
Network: &infrav1.NetworkFilter{
@@ -556,6 +557,7 @@ var _ = Describe("OpenStackCluster controller", func() {
ListOptsBuilder: networks.ListOpts{
ID: externalNetworkID,
},
+ External: pointer.Bool(true),
}).Return([]networks.Network{
{
ID: externalNetworkID,
@@ -600,7 +602,7 @@ var _ = Describe("OpenStackCluster controller", func() {
},
DisableAPIServerFloatingIP: true,
APIServerFixedIP: "10.0.0.1",
- ExternalNetwork: infrav1.NetworkFilter{
+ ExternalNetwork: &infrav1.NetworkFilter{
ID: externalNetworkID,
},
Network: &infrav1.NetworkFilter{
@@ -639,6 +641,7 @@ var _ = Describe("OpenStackCluster controller", func() {
ListOptsBuilder: networks.ListOpts{
ID: externalNetworkID,
},
+ External: pointer.Bool(true),
}).Return([]networks.Network{
{
ID: externalNetworkID,
diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md
index c118ced103..1849ebcf04 100644
--- a/docs/book/src/api/v1beta1/api.md
+++ b/docs/book/src/api/v1beta1/api.md
@@ -172,7 +172,15 @@ NetworkFilter
(Optional)
- ExternalNetwork is the OpenStack Network to be used 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.
|
@@ -184,7 +192,7 @@ bool
|
(Optional)
- DisableExternalNetwork determines whether or not to attempt to connect the cluster
+ 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.
|
@@ -2051,7 +2059,15 @@ NetworkFilter
(Optional)
- ExternalNetwork is the OpenStack Network to be used 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.
|
@@ -2063,7 +2079,7 @@ bool
|
(Optional)
- DisableExternalNetwork determines whether or not to attempt to connect the cluster
+ 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.
|
@@ -2609,7 +2625,15 @@ NetworkFilter
(Optional)
- ExternalNetwork is the OpenStack Network to be used 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.
|
@@ -2621,7 +2645,7 @@ bool
|
(Optional)
- DisableExternalNetwork determines whether or not to attempt to connect the cluster
+ 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.
|
diff --git a/pkg/cloud/services/networking/network.go b/pkg/cloud/services/networking/network.go
index 1904b3823c..f585cdd269 100644
--- a/pkg/cloud/services/networking/network.go
+++ b/pkg/cloud/services/networking/network.go
@@ -24,6 +24,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external"
"github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
"github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
+ "k8s.io/utils/pointer"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/metrics"
@@ -78,7 +79,6 @@ func (c createOpts) ToNetworkCreateMap() (map[string]interface{}, error) {
// - the user has set OpenStackCluster.Spec.DisableExternalNetwork to true.
func (s *Service) ReconcileExternalNetwork(openStackCluster *infrav1.OpenStackCluster) error {
var listOpts external.ListOptsExt
- var isAutoDetecting bool
if openStackCluster.Spec.DisableExternalNetwork {
s.scope.Logger().Info("External network is disabled - proceeding with internal network only")
@@ -86,20 +86,10 @@ func (s *Service) ReconcileExternalNetwork(openStackCluster *infrav1.OpenStackCl
return nil
}
- externalNetworkListOpts := filterconvert.NetworkFilterToListOpts(&openStackCluster.Spec.ExternalNetwork)
- if externalNetworkListOpts != (networks.ListOpts{}) {
- listOpts = external.ListOptsExt{
- ListOptsBuilder: externalNetworkListOpts,
- }
- } else {
- // ExternalNetwork is not given so we'll list all networks and filter for external networks
- isAutoDetecting = true
- listOpts = external.ListOptsExt{
- ListOptsBuilder: networks.ListOpts{},
- External: &isAutoDetecting,
- }
+ listOpts = external.ListOptsExt{
+ ListOptsBuilder: filterconvert.NetworkFilterToListOpts(openStackCluster.Spec.ExternalNetwork),
+ External: pointer.Bool(true),
}
-
networkList, err := s.client.ListNetwork(listOpts)
if err != nil {
return err
@@ -107,7 +97,7 @@ func (s *Service) ReconcileExternalNetwork(openStackCluster *infrav1.OpenStackCl
switch len(networkList) {
case 0:
- if isAutoDetecting {
+ if openStackCluster.Spec.ExternalNetwork == nil {
// Not finding an external network is fine if ExternalNetwork is not set
openStackCluster.Status.ExternalNetwork = nil
s.scope.Logger().Info("No external network found - proceeding with internal network only")
diff --git a/pkg/cloud/services/networking/network_test.go b/pkg/cloud/services/networking/network_test.go
index 27a07580ba..d67e80739d 100644
--- a/pkg/cloud/services/networking/network_test.go
+++ b/pkg/cloud/services/networking/network_test.go
@@ -207,7 +207,6 @@ func Test_ReconcileExternalNetwork(t *testing.T) {
fakeNetworkID := "d08803fc-2fa5-4179-b9f7-8c43d0af2fe6"
fakeNetworkname := "external-network"
- isAutodetecting := true
tests := []struct {
name string
@@ -220,7 +219,7 @@ func Test_ReconcileExternalNetwork(t *testing.T) {
name: "reconcile external network by ID",
openStackCluster: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
- ExternalNetwork: infrav1.NetworkFilter{
+ ExternalNetwork: &infrav1.NetworkFilter{
ID: fakeNetworkID,
},
},
@@ -229,6 +228,7 @@ func Test_ReconcileExternalNetwork(t *testing.T) {
m.
ListNetwork(external.ListOptsExt{
ListOptsBuilder: networks.ListOpts{ID: fakeNetworkID},
+ External: pointer.Bool(true),
}).
Return([]networks.Network{
{
@@ -239,7 +239,7 @@ func Test_ReconcileExternalNetwork(t *testing.T) {
},
want: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
- ExternalNetwork: infrav1.NetworkFilter{
+ ExternalNetwork: &infrav1.NetworkFilter{
ID: fakeNetworkID,
},
},
@@ -256,7 +256,7 @@ func Test_ReconcileExternalNetwork(t *testing.T) {
name: "reconcile external network by name",
openStackCluster: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
- ExternalNetwork: infrav1.NetworkFilter{
+ ExternalNetwork: &infrav1.NetworkFilter{
Name: fakeNetworkname,
},
},
@@ -265,6 +265,7 @@ func Test_ReconcileExternalNetwork(t *testing.T) {
m.
ListNetwork(external.ListOptsExt{
ListOptsBuilder: networks.ListOpts{Name: fakeNetworkname},
+ External: pointer.Bool(true),
}).
Return([]networks.Network{
{
@@ -275,7 +276,7 @@ func Test_ReconcileExternalNetwork(t *testing.T) {
},
want: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
- ExternalNetwork: infrav1.NetworkFilter{
+ ExternalNetwork: &infrav1.NetworkFilter{
Name: fakeNetworkname,
},
},
@@ -292,7 +293,7 @@ func Test_ReconcileExternalNetwork(t *testing.T) {
name: "reconcile external network by ID when no external network found",
openStackCluster: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
- ExternalNetwork: infrav1.NetworkFilter{
+ ExternalNetwork: &infrav1.NetworkFilter{
ID: fakeNetworkID,
},
},
@@ -301,12 +302,13 @@ func Test_ReconcileExternalNetwork(t *testing.T) {
m.
ListNetwork(external.ListOptsExt{
ListOptsBuilder: networks.ListOpts{ID: fakeNetworkID},
+ External: pointer.Bool(true),
}).
Return([]networks.Network{}, nil)
},
want: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
- ExternalNetwork: infrav1.NetworkFilter{
+ ExternalNetwork: &infrav1.NetworkFilter{
ID: fakeNetworkID,
},
},
@@ -340,7 +342,7 @@ func Test_ReconcileExternalNetwork(t *testing.T) {
m.
ListNetwork(external.ListOptsExt{
ListOptsBuilder: networks.ListOpts{},
- External: &isAutodetecting,
+ External: pointer.Bool(true),
}).
Return([]networks.Network{}, nil)
},
@@ -361,7 +363,7 @@ func Test_ReconcileExternalNetwork(t *testing.T) {
m.
ListNetwork(external.ListOptsExt{
ListOptsBuilder: networks.ListOpts{},
- External: &isAutodetecting,
+ External: pointer.Bool(true),
}).
Return([]networks.Network{
{
@@ -390,7 +392,7 @@ func Test_ReconcileExternalNetwork(t *testing.T) {
m.
ListNetwork(external.ListOptsExt{
ListOptsBuilder: networks.ListOpts{},
- External: &isAutodetecting,
+ External: pointer.Bool(true),
}).
Return([]networks.Network{
{
diff --git a/test/e2e/suites/apivalidations/neutronfilters_test.go b/test/e2e/suites/apivalidations/neutronfilters_test.go
index e5a1e65dcd..59fb80e9fd 100644
--- a/test/e2e/suites/apivalidations/neutronfilters_test.go
+++ b/test/e2e/suites/apivalidations/neutronfilters_test.go
@@ -74,7 +74,7 @@ var _ = Describe("Neutron filter API validations", func() {
cluster.Spec.Subnets = subnets
if len(tags) > 0 {
cluster.Spec.Network = &infrav1.NetworkFilter{FilterByNeutronTags: tags[0]}
- cluster.Spec.ExternalNetwork = infrav1.NetworkFilter{FilterByNeutronTags: tags[0]}
+ cluster.Spec.ExternalNetwork = &infrav1.NetworkFilter{FilterByNeutronTags: tags[0]}
cluster.Spec.Router = &infrav1.RouterFilter{FilterByNeutronTags: tags[0]}
}
Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
@@ -143,7 +143,7 @@ var _ = Describe("Neutron filter API validations", func() {
{
cluster := cluster.DeepCopy()
- cluster.Spec.ExternalNetwork = infrav1.NetworkFilter{FilterByNeutronTags: tag}
+ cluster.Spec.ExternalNetwork = &infrav1.NetworkFilter{FilterByNeutronTags: tag}
Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should fail with invalid external network neutron tags")
}
From e5d963081000e30a1b7ca7f8141d759cbb6e92e0 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Mon, 19 Feb 2024 18:06:46 +0000
Subject: [PATCH 115/180] OpenStackClusterSpec: ApiServerLoadBalancer->pointer
Affects go marshalling only.
---
api/v1alpha5/conversion.go | 13 +++++++++++++
api/v1alpha5/conversion_test.go | 4 ++--
api/v1alpha5/zz_generated.conversion.go | 8 ++------
api/v1alpha6/openstackcluster_conversion.go | 18 ++++++++++++++++++
api/v1alpha6/zz_generated.conversion.go | 8 ++------
api/v1alpha7/openstackcluster_conversion.go | 18 ++++++++++++++++++
api/v1alpha7/zz_generated.conversion.go | 8 ++------
api/v1beta1/openstackcluster_types.go | 2 +-
api/v1beta1/types.go | 8 ++++++++
api/v1beta1/zz_generated.deepcopy.go | 6 +++++-
controllers/openstackcluster_controller.go | 4 ++--
controllers/openstackmachine_controller.go | 6 +++---
.../services/loadbalancer/loadbalancer.go | 19 ++++++++++++++-----
.../loadbalancer/loadbalancer_test.go | 11 +++++++----
.../services/networking/securitygroups.go | 2 +-
pkg/webhooks/openstackcluster_webhook.go | 2 +-
pkg/webhooks/openstackcluster_webhook_test.go | 4 ++--
17 files changed, 101 insertions(+), 40 deletions(-)
diff --git a/api/v1alpha5/conversion.go b/api/v1alpha5/conversion.go
index ddc36a82f2..3114f22185 100644
--- a/api/v1alpha5/conversion.go
+++ b/api/v1alpha5/conversion.go
@@ -227,6 +227,12 @@ func Convert_v1beta1_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(in *i
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}
@@ -273,6 +279,13 @@ func Convert_v1alpha5_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *O
}
}
+ 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
diff --git a/api/v1alpha5/conversion_test.go b/api/v1alpha5/conversion_test.go
index d2b7a58ef2..ceb18344a9 100644
--- a/api/v1alpha5/conversion_test.go
+++ b/api/v1alpha5/conversion_test.go
@@ -51,7 +51,7 @@ func TestConvertFrom(t *testing.T) {
},
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
- "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"apiServerLoadBalancer\":{},\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"disableExternalNetwork\":false,\"identityRef\":{\"cloudName\":\"\",\"name\":\"\"}},\"status\":{\"ready\":false}}",
+ "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"disableExternalNetwork\":false,\"identityRef\":{\"cloudName\":\"\",\"name\":\"\"}},\"status\":{\"ready\":false}}",
},
},
},
@@ -72,7 +72,7 @@ func TestConvertFrom(t *testing.T) {
},
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
- "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"template\":{\"spec\":{\"apiServerLoadBalancer\":{},\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"disableExternalNetwork\":false,\"identityRef\":{\"cloudName\":\"\",\"name\":\"\"}}}}}",
+ "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"template\":{\"spec\":{\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"disableExternalNetwork\":false,\"identityRef\":{\"cloudName\":\"\",\"name\":\"\"}}}}}",
},
},
},
diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go
index 9bf9a1d331..d5d1059671 100644
--- a/api/v1alpha5/zz_generated.conversion.go
+++ b/api/v1alpha5/zz_generated.conversion.go
@@ -674,9 +674,7 @@ func autoConvert_v1alpha5_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(i
out.ExternalRouterIPs = nil
}
// WARNING: in.ExternalNetworkID requires manual conversion: does not exist in peer-type
- if err := Convert_v1alpha5_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil {
- return err
- }
+ // 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)
out.DisableAPIServerFloatingIP = in.DisableAPIServerFloatingIP
out.APIServerFloatingIP = in.APIServerFloatingIP
out.APIServerFixedIP = in.APIServerFixedIP
@@ -719,9 +717,7 @@ func autoConvert_v1beta1_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(i
}
// WARNING: in.ExternalNetwork requires manual conversion: does not exist in peer-type
// WARNING: in.DisableExternalNetwork requires manual conversion: does not exist in peer-type
- if err := Convert_v1beta1_APIServerLoadBalancer_To_v1alpha5_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil {
- return err
- }
+ // 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)
out.DisableAPIServerFloatingIP = in.DisableAPIServerFloatingIP
out.APIServerFloatingIP = in.APIServerFloatingIP
out.APIServerFixedIP = in.APIServerFixedIP
diff --git a/api/v1alpha6/openstackcluster_conversion.go b/api/v1alpha6/openstackcluster_conversion.go
index 1cf9cd7d82..301d5f0d5f 100644
--- a/api/v1alpha6/openstackcluster_conversion.go
+++ b/api/v1alpha6/openstackcluster_conversion.go
@@ -195,6 +195,10 @@ func restorev1beta1ClusterSpec(previous *infrav1.OpenStackClusterSpec, dst *infr
if previous.ManagedSecurityGroups != nil {
dst.ManagedSecurityGroups.AllNodesSecurityGroupRules = previous.ManagedSecurityGroups.AllNodesSecurityGroupRules
}
+
+ if dst.APIServerLoadBalancer.IsZero() {
+ dst.APIServerLoadBalancer = previous.APIServerLoadBalancer
+ }
}
func Convert_v1alpha6_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *OpenStackClusterSpec, out *infrav1.OpenStackClusterSpec, s apiconversion.Scope) error {
@@ -249,6 +253,14 @@ func Convert_v1alpha6_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *O
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
}
@@ -287,6 +299,12 @@ func Convert_v1beta1_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(in *i
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
}
diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go
index 04ad0264bc..0ecfdf4cf0 100644
--- a/api/v1alpha6/zz_generated.conversion.go
+++ b/api/v1alpha6/zz_generated.conversion.go
@@ -700,9 +700,7 @@ func autoConvert_v1alpha6_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(i
out.ExternalRouterIPs = nil
}
// WARNING: in.ExternalNetworkID requires manual conversion: does not exist in peer-type
- if err := Convert_v1alpha6_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil {
- return err
- }
+ // 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)
out.DisableAPIServerFloatingIP = in.DisableAPIServerFloatingIP
out.APIServerFloatingIP = in.APIServerFloatingIP
out.APIServerFixedIP = in.APIServerFixedIP
@@ -746,9 +744,7 @@ func autoConvert_v1beta1_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(i
}
// WARNING: in.ExternalNetwork requires manual conversion: does not exist in peer-type
// WARNING: in.DisableExternalNetwork requires manual conversion: does not exist in peer-type
- if err := Convert_v1beta1_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil {
- return err
- }
+ // 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)
out.DisableAPIServerFloatingIP = in.DisableAPIServerFloatingIP
out.APIServerFloatingIP = in.APIServerFloatingIP
out.APIServerFixedIP = in.APIServerFixedIP
diff --git a/api/v1alpha7/openstackcluster_conversion.go b/api/v1alpha7/openstackcluster_conversion.go
index d5c26ff9a9..191566c5dd 100644
--- a/api/v1alpha7/openstackcluster_conversion.go
+++ b/api/v1alpha7/openstackcluster_conversion.go
@@ -197,6 +197,10 @@ func restorev1beta1ClusterSpec(previous *infrav1.OpenStackClusterSpec, dst *infr
if previous.ManagedSecurityGroups != nil {
dst.ManagedSecurityGroups.AllNodesSecurityGroupRules = previous.ManagedSecurityGroups.AllNodesSecurityGroupRules
}
+
+ if dst.APIServerLoadBalancer.IsZero() {
+ dst.APIServerLoadBalancer = previous.APIServerLoadBalancer
+ }
}
func Convert_v1alpha7_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *OpenStackClusterSpec, out *infrav1.OpenStackClusterSpec, s apiconversion.Scope) error {
@@ -251,6 +255,14 @@ func Convert_v1alpha7_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *O
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
}
@@ -289,6 +301,12 @@ func Convert_v1beta1_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in *i
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
}
diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go
index 63f859f049..353d7f0d05 100644
--- a/api/v1alpha7/zz_generated.conversion.go
+++ b/api/v1alpha7/zz_generated.conversion.go
@@ -915,9 +915,7 @@ func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(i
out.ExternalRouterIPs = nil
}
// WARNING: in.ExternalNetworkID requires manual conversion: does not exist in peer-type
- if err := Convert_v1alpha7_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil {
- return err
- }
+ // 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)
out.DisableAPIServerFloatingIP = in.DisableAPIServerFloatingIP
out.APIServerFloatingIP = in.APIServerFloatingIP
out.APIServerFixedIP = in.APIServerFixedIP
@@ -969,9 +967,7 @@ func autoConvert_v1beta1_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(i
}
// WARNING: in.ExternalNetwork requires manual conversion: does not exist in peer-type
// WARNING: in.DisableExternalNetwork requires manual conversion: does not exist in peer-type
- if err := Convert_v1beta1_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer(&in.APIServerLoadBalancer, &out.APIServerLoadBalancer, s); err != nil {
- return err
- }
+ // 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)
out.DisableAPIServerFloatingIP = in.DisableAPIServerFloatingIP
out.APIServerFloatingIP = in.APIServerFloatingIP
out.APIServerFixedIP = in.APIServerFixedIP
diff --git a/api/v1beta1/openstackcluster_types.go b/api/v1beta1/openstackcluster_types.go
index 9a4a3ad9be..686009f5af 100644
--- a/api/v1beta1/openstackcluster_types.go
+++ b/api/v1beta1/openstackcluster_types.go
@@ -95,7 +95,7 @@ type OpenStackClusterSpec struct {
// APIServerLoadBalancer configures the optional LoadBalancer for the APIServer.
// It must be activated by setting `enabled: true`.
// +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
diff --git a/api/v1beta1/types.go b/api/v1beta1/types.go
index 1ef0a9f49a..b242a9585d 100644
--- a/api/v1beta1/types.go
+++ b/api/v1beta1/types.go
@@ -615,6 +615,14 @@ type APIServerLoadBalancer struct {
Provider string `json:"provider,omitempty"`
}
+func (s *APIServerLoadBalancer) IsZero() bool {
+ return s == nil || (!s.Enabled && len(s.AdditionalPorts) == 0 && len(s.AllowedCIDRs) == 0 && s.Provider == "")
+}
+
+func (s *APIServerLoadBalancer) IsEnabled() bool {
+ return s != nil && s.Enabled
+}
+
// ReferencedMachineResources contains resolved references to resources required by the machine.
type ReferencedMachineResources struct {
// ServerGroupID is the ID of the server group the machine should be added to and is calculated based on ServerGroupFilter.
diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go
index a642946cbd..6dbf28e798 100644
--- a/api/v1beta1/zz_generated.deepcopy.go
+++ b/api/v1beta1/zz_generated.deepcopy.go
@@ -516,7 +516,11 @@ func (in *OpenStackClusterSpec) DeepCopyInto(out *OpenStackClusterSpec) {
*out = new(NetworkFilter)
(*in).DeepCopyInto(*out)
}
- in.APIServerLoadBalancer.DeepCopyInto(&out.APIServerLoadBalancer)
+ if in.APIServerLoadBalancer != nil {
+ in, out := &in.APIServerLoadBalancer, &out.APIServerLoadBalancer
+ *out = new(APIServerLoadBalancer)
+ (*in).DeepCopyInto(*out)
+ }
if in.ManagedSecurityGroups != nil {
in, out := &in.ManagedSecurityGroups, &out.ManagedSecurityGroups
*out = new(ManagedSecurityGroups)
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index e19d605a12..55400169fe 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -184,7 +184,7 @@ func (r *OpenStackClusterReconciler) reconcileDelete(ctx context.Context, scope
clusterName := fmt.Sprintf("%s-%s", cluster.Namespace, cluster.Name)
- if openStackCluster.Spec.APIServerLoadBalancer.Enabled {
+ if openStackCluster.Spec.APIServerLoadBalancer != nil && openStackCluster.Spec.APIServerLoadBalancer.Enabled {
loadBalancerService, err := loadbalancer.NewService(scope)
if err != nil {
return reconcile.Result{}, err
@@ -718,7 +718,7 @@ func reconcileControlPlaneEndpoint(scope *scope.WithLogger, networkingService *n
// 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.Enabled:
+ case openStackCluster.Spec.APIServerLoadBalancer != nil && openStackCluster.Spec.APIServerLoadBalancer.Enabled:
loadBalancerService, err := loadbalancer.NewService(scope)
if err != nil {
return err
diff --git a/controllers/openstackmachine_controller.go b/controllers/openstackmachine_controller.go
index 2a296bcfed..f926cb8aa6 100644
--- a/controllers/openstackmachine_controller.go
+++ b/controllers/openstackmachine_controller.go
@@ -256,7 +256,7 @@ func (r *OpenStackMachineReconciler) reconcileDelete(scope *scope.WithLogger, cl
return ctrl.Result{}, err
}
- if openStackCluster.Spec.APIServerLoadBalancer.Enabled {
+ if openStackCluster.Spec.APIServerLoadBalancer.IsEnabled() {
loadBalancerService, err := loadbalancer.NewService(scope)
if err != nil {
return ctrl.Result{}, err
@@ -278,7 +278,7 @@ func (r *OpenStackMachineReconciler) reconcileDelete(scope *scope.WithLogger, cl
} else if instanceStatus, err = computeService.GetInstanceStatusByName(openStackMachine, openStackMachine.Name); err != nil {
return ctrl.Result{}, err
}
- if !openStackCluster.Spec.APIServerLoadBalancer.Enabled && util.IsControlPlaneMachine(machine) && openStackCluster.Spec.APIServerFloatingIP == "" {
+ if !openStackCluster.Spec.APIServerLoadBalancer.IsEnabled() && util.IsControlPlaneMachine(machine) && openStackCluster.Spec.APIServerFloatingIP == "" {
if instanceStatus != nil {
instanceNS, err := instanceStatus.NetworkStatus()
if err != nil {
@@ -452,7 +452,7 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope
return ctrl.Result{}, nil
}
- if openStackCluster.Spec.APIServerLoadBalancer.Enabled {
+ if openStackCluster.Spec.APIServerLoadBalancer.IsEnabled() {
err = r.reconcileLoadBalancerMember(scope, openStackCluster, openStackMachine, instanceNS, clusterName)
if err != nil {
conditions.MarkFalse(openStackMachine, infrav1.APIServerIngressReadyCondition, infrav1.LoadBalancerMemberErrorReason, clusterv1.ConditionSeverityError, "Reconciling load balancer member failed: %v", err)
diff --git a/pkg/cloud/services/loadbalancer/loadbalancer.go b/pkg/cloud/services/loadbalancer/loadbalancer.go
index 38dda5ecb6..7a5d3ceaa4 100644
--- a/pkg/cloud/services/loadbalancer/loadbalancer.go
+++ b/pkg/cloud/services/loadbalancer/loadbalancer.go
@@ -67,6 +67,11 @@ var lookupHost = func(host string) (string, error) {
// ReconcileLoadBalancer reconciles the load balancer for the given cluster.
func (s *Service) ReconcileLoadBalancer(openStackCluster *infrav1.OpenStackCluster, clusterName string, apiServerPort int) (bool, error) {
+ lbSpec := openStackCluster.Spec.APIServerLoadBalancer
+ if !lbSpec.IsEnabled() {
+ return false, nil
+ }
+
loadBalancerName := getLoadBalancerName(clusterName)
s.scope.Logger().Info("Reconciling load balancer", "name", loadBalancerName)
@@ -128,7 +133,7 @@ func (s *Service) ReconcileLoadBalancer(openStackCluster *infrav1.OpenStackClust
}
portList := []int{apiServerPort}
- portList = append(portList, openStackCluster.Spec.APIServerLoadBalancer.AdditionalPorts...)
+ portList = append(portList, lbSpec.AdditionalPorts...)
for _, port := range portList {
if err := s.reconcileAPILoadBalancerListener(lb, openStackCluster, clusterName, port); err != nil {
return false, err
@@ -192,7 +197,7 @@ func getAPIServerFloatingIP(openStackCluster *infrav1.OpenStackCluster) (string,
func getCanonicalAllowedCIDRs(openStackCluster *infrav1.OpenStackCluster) []string {
allowedCIDRs := []string{}
- if len(openStackCluster.Spec.APIServerLoadBalancer.AllowedCIDRs) > 0 {
+ if openStackCluster.Spec.APIServerLoadBalancer != nil && len(openStackCluster.Spec.APIServerLoadBalancer.AllowedCIDRs) > 0 {
allowedCIDRs = append(allowedCIDRs, openStackCluster.Spec.APIServerLoadBalancer.AllowedCIDRs...)
// In the first reconciliation loop, only the Ready field is set in openStackCluster.Status
@@ -275,7 +280,7 @@ func (s *Service) getOrCreateAPILoadBalancer(openStackCluster *infrav1.OpenStack
// Choose the selected provider if it is set in cluster spec, if not, omit the field and Octavia will use the default provider.
lbProvider := ""
- if openStackCluster.Spec.APIServerLoadBalancer.Provider != "" {
+ if openStackCluster.Spec.APIServerLoadBalancer != nil && openStackCluster.Spec.APIServerLoadBalancer.Provider != "" {
for _, v := range providers {
if v.Name == openStackCluster.Spec.APIServerLoadBalancer.Provider {
lbProvider = v.Name
@@ -515,7 +520,9 @@ func (s *Service) ReconcileLoadBalancerMember(openStackCluster *infrav1.OpenStac
lbID := openStackCluster.Status.APIServerLoadBalancer.ID
portList := []int{int(openStackCluster.Spec.ControlPlaneEndpoint.Port)}
- portList = append(portList, openStackCluster.Spec.APIServerLoadBalancer.AdditionalPorts...)
+ if openStackCluster.Spec.APIServerLoadBalancer != nil {
+ portList = append(portList, openStackCluster.Spec.APIServerLoadBalancer.AdditionalPorts...)
+ }
for _, port := range portList {
lbPortObjectsName := fmt.Sprintf("%s-%d", loadBalancerName, port)
name := lbPortObjectsName + "-" + openStackMachine.Name
@@ -646,7 +653,9 @@ func (s *Service) DeleteLoadBalancerMember(openStackCluster *infrav1.OpenStackCl
lbID := lb.ID
portList := []int{int(openStackCluster.Spec.ControlPlaneEndpoint.Port)}
- portList = append(portList, openStackCluster.Spec.APIServerLoadBalancer.AdditionalPorts...)
+ if openStackCluster.Spec.APIServerLoadBalancer != nil {
+ portList = append(portList, openStackCluster.Spec.APIServerLoadBalancer.AdditionalPorts...)
+ }
for _, port := range portList {
lbPortObjectsName := fmt.Sprintf("%s-%d", loadBalancerName, port)
name := lbPortObjectsName + "-" + openStackMachine.Name
diff --git a/pkg/cloud/services/loadbalancer/loadbalancer_test.go b/pkg/cloud/services/loadbalancer/loadbalancer_test.go
index f264a83415..7011ebd6c7 100644
--- a/pkg/cloud/services/loadbalancer/loadbalancer_test.go
+++ b/pkg/cloud/services/loadbalancer/loadbalancer_test.go
@@ -57,6 +57,9 @@ func Test_ReconcileLoadBalancer(t *testing.T) {
openStackCluster := &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
+ APIServerLoadBalancer: &infrav1.APIServerLoadBalancer{
+ Enabled: true,
+ },
DisableAPIServerFloatingIP: true,
ControlPlaneEndpoint: clusterv1.APIEndpoint{
Host: apiHostname,
@@ -346,7 +349,7 @@ func Test_getCanonicalAllowedCIDRs(t *testing.T) {
name: "allowed CIDRs are set",
openStackCluster: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
- APIServerLoadBalancer: infrav1.APIServerLoadBalancer{
+ APIServerLoadBalancer: &infrav1.APIServerLoadBalancer{
AllowedCIDRs: []string{"1.2.3.4/32"},
},
},
@@ -357,7 +360,7 @@ func Test_getCanonicalAllowedCIDRs(t *testing.T) {
name: "allowed CIDRs are set with bastion",
openStackCluster: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
- APIServerLoadBalancer: infrav1.APIServerLoadBalancer{
+ APIServerLoadBalancer: &infrav1.APIServerLoadBalancer{
AllowedCIDRs: []string{"1.2.3.4/32"},
},
},
@@ -374,7 +377,7 @@ func Test_getCanonicalAllowedCIDRs(t *testing.T) {
name: "allowed CIDRs are set with network status",
openStackCluster: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
- APIServerLoadBalancer: infrav1.APIServerLoadBalancer{
+ APIServerLoadBalancer: &infrav1.APIServerLoadBalancer{
AllowedCIDRs: []string{"1.2.3.4/32"},
},
},
@@ -394,7 +397,7 @@ func Test_getCanonicalAllowedCIDRs(t *testing.T) {
name: "allowed CIDRs are set with network status and router IP",
openStackCluster: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
- APIServerLoadBalancer: infrav1.APIServerLoadBalancer{
+ APIServerLoadBalancer: &infrav1.APIServerLoadBalancer{
AllowedCIDRs: []string{"1.2.3.4/32"},
},
},
diff --git a/pkg/cloud/services/networking/securitygroups.go b/pkg/cloud/services/networking/securitygroups.go
index cd1f64360b..d1fd89d847 100644
--- a/pkg/cloud/services/networking/securitygroups.go
+++ b/pkg/cloud/services/networking/securitygroups.go
@@ -165,7 +165,7 @@ func (s *Service) generateDesiredSecGroups(openStackCluster *infrav1.OpenStackCl
workerRules = append(workerRules, getSGWorkerNodePort()...)
// If we set additional ports to LB, we need create secgroup rules those ports, this apply to controlPlaneRules only
- if openStackCluster.Spec.APIServerLoadBalancer.Enabled {
+ if openStackCluster.Spec.APIServerLoadBalancer != nil && openStackCluster.Spec.APIServerLoadBalancer.Enabled {
controlPlaneRules = append(controlPlaneRules, getSGControlPlaneAdditionalPorts(openStackCluster.Spec.APIServerLoadBalancer.AdditionalPorts)...)
}
diff --git a/pkg/webhooks/openstackcluster_webhook.go b/pkg/webhooks/openstackcluster_webhook.go
index 6541e93681..0ee6326b54 100644
--- a/pkg/webhooks/openstackcluster_webhook.go
+++ b/pkg/webhooks/openstackcluster_webhook.go
@@ -126,7 +126,7 @@ func (*openStackClusterWebhook) ValidateUpdate(_ context.Context, oldObjRaw, new
}
// Allow changes on AllowedCIDRs
- if newObj.Spec.APIServerLoadBalancer.Enabled {
+ if newObj.Spec.APIServerLoadBalancer != nil && oldObj.Spec.APIServerLoadBalancer != nil {
oldObj.Spec.APIServerLoadBalancer.AllowedCIDRs = []string{}
newObj.Spec.APIServerLoadBalancer.AllowedCIDRs = []string{}
}
diff --git a/pkg/webhooks/openstackcluster_webhook_test.go b/pkg/webhooks/openstackcluster_webhook_test.go
index 5a4c44269c..8668059030 100644
--- a/pkg/webhooks/openstackcluster_webhook_test.go
+++ b/pkg/webhooks/openstackcluster_webhook_test.go
@@ -166,7 +166,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
Name: "foobar",
CloudName: "foobar",
},
- APIServerLoadBalancer: infrav1.APIServerLoadBalancer{
+ APIServerLoadBalancer: &infrav1.APIServerLoadBalancer{
Enabled: true,
AllowedCIDRs: []string{
"0.0.0.0/0",
@@ -181,7 +181,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
Name: "foobar",
CloudName: "foobar",
},
- APIServerLoadBalancer: infrav1.APIServerLoadBalancer{
+ APIServerLoadBalancer: &infrav1.APIServerLoadBalancer{
Enabled: true,
AllowedCIDRs: []string{
"0.0.0.0/0",
From 2c7b44b312e874de35550b3759f59740e42b6bcb Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Wed, 21 Feb 2024 12:52:02 +0000
Subject: [PATCH 116/180] OpenStackClusterSpec: APIServerFloatingIP,
APIServerFixedIP, APIServerPort->optional
Affects go marshalling only.
---
api/v1alpha5/conversion.go | 12 +++++
api/v1alpha5/zz_generated.conversion.go | 24 ++++++---
api/v1alpha6/openstackcluster_conversion.go | 5 ++
api/v1alpha6/zz_generated.conversion.go | 24 ++++++---
api/v1alpha7/openstackcluster_conversion.go | 5 ++
api/v1alpha7/zz_generated.conversion.go | 24 ++++++---
api/v1beta1/openstackcluster_types.go | 11 ++--
api/v1beta1/zz_generated.deepcopy.go | 15 ++++++
controllers/openstackcluster_controller.go | 18 ++++---
.../openstackcluster_controller_test.go | 8 +--
controllers/openstackmachine_controller.go | 11 ++--
docs/book/src/api/v1beta1/api.md | 9 ++++
.../services/loadbalancer/loadbalancer.go | 35 +++++++------
.../loadbalancer/loadbalancer_test.go | 51 ++++++++++---------
pkg/cloud/services/networking/floatingip.go | 13 +++--
.../services/networking/floatingip_test.go | 10 +++-
pkg/webhooks/openstackcluster_webhook.go | 16 +++---
pkg/webhooks/openstackcluster_webhook_test.go | 14 +++--
18 files changed, 208 insertions(+), 97 deletions(-)
diff --git a/api/v1alpha5/conversion.go b/api/v1alpha5/conversion.go
index 3114f22185..cd66e62bd3 100644
--- a/api/v1alpha5/conversion.go
+++ b/api/v1alpha5/conversion.go
@@ -291,6 +291,18 @@ func Convert_v1alpha5_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *O
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 = pointer.Int(in.APIServerPort)
+ }
+
return nil
}
diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go
index d5d1059671..a23b47e552 100644
--- a/api/v1alpha5/zz_generated.conversion.go
+++ b/api/v1alpha5/zz_generated.conversion.go
@@ -676,9 +676,15 @@ func autoConvert_v1alpha5_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(i
// 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)
out.DisableAPIServerFloatingIP = in.DisableAPIServerFloatingIP
- out.APIServerFloatingIP = in.APIServerFloatingIP
- out.APIServerFixedIP = in.APIServerFixedIP
- out.APIServerPort = in.APIServerPort
+ 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
out.DisablePortSecurity = in.DisablePortSecurity
@@ -719,9 +725,15 @@ func autoConvert_v1beta1_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(i
// 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)
out.DisableAPIServerFloatingIP = in.DisableAPIServerFloatingIP
- out.APIServerFloatingIP = in.APIServerFloatingIP
- out.APIServerFixedIP = in.APIServerFixedIP
- out.APIServerPort = in.APIServerPort
+ 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)
out.DisablePortSecurity = in.DisablePortSecurity
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
diff --git a/api/v1alpha6/openstackcluster_conversion.go b/api/v1alpha6/openstackcluster_conversion.go
index 301d5f0d5f..33a174b1a8 100644
--- a/api/v1alpha6/openstackcluster_conversion.go
+++ b/api/v1alpha6/openstackcluster_conversion.go
@@ -24,6 +24,7 @@ import (
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{}
@@ -199,6 +200,10 @@ func restorev1beta1ClusterSpec(previous *infrav1.OpenStackClusterSpec, dst *infr
if dst.APIServerLoadBalancer.IsZero() {
dst.APIServerLoadBalancer = previous.APIServerLoadBalancer
}
+
+ optional.RestoreString(&previous.APIServerFloatingIP, &dst.APIServerFloatingIP)
+ optional.RestoreString(&previous.APIServerFixedIP, &dst.APIServerFixedIP)
+ optional.RestoreInt(&previous.APIServerPort, &dst.APIServerPort)
}
func Convert_v1alpha6_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *OpenStackClusterSpec, out *infrav1.OpenStackClusterSpec, s apiconversion.Scope) error {
diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go
index 0ecfdf4cf0..6a2c5a1ed0 100644
--- a/api/v1alpha6/zz_generated.conversion.go
+++ b/api/v1alpha6/zz_generated.conversion.go
@@ -702,9 +702,15 @@ func autoConvert_v1alpha6_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(i
// 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)
out.DisableAPIServerFloatingIP = in.DisableAPIServerFloatingIP
- out.APIServerFloatingIP = in.APIServerFloatingIP
- out.APIServerFixedIP = in.APIServerFixedIP
- out.APIServerPort = in.APIServerPort
+ 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
out.DisablePortSecurity = in.DisablePortSecurity
@@ -746,9 +752,15 @@ func autoConvert_v1beta1_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(i
// 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)
out.DisableAPIServerFloatingIP = in.DisableAPIServerFloatingIP
- out.APIServerFloatingIP = in.APIServerFloatingIP
- out.APIServerFixedIP = in.APIServerFixedIP
- out.APIServerPort = in.APIServerPort
+ 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)
out.DisablePortSecurity = in.DisablePortSecurity
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
diff --git a/api/v1alpha7/openstackcluster_conversion.go b/api/v1alpha7/openstackcluster_conversion.go
index 191566c5dd..8a478229a8 100644
--- a/api/v1alpha7/openstackcluster_conversion.go
+++ b/api/v1alpha7/openstackcluster_conversion.go
@@ -22,6 +22,7 @@ import (
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{}
@@ -201,6 +202,10 @@ func restorev1beta1ClusterSpec(previous *infrav1.OpenStackClusterSpec, dst *infr
if dst.APIServerLoadBalancer.IsZero() {
dst.APIServerLoadBalancer = previous.APIServerLoadBalancer
}
+
+ optional.RestoreString(&previous.APIServerFloatingIP, &dst.APIServerFloatingIP)
+ optional.RestoreString(&previous.APIServerFixedIP, &dst.APIServerFixedIP)
+ optional.RestoreInt(&previous.APIServerPort, &dst.APIServerPort)
}
func Convert_v1alpha7_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *OpenStackClusterSpec, out *infrav1.OpenStackClusterSpec, s apiconversion.Scope) error {
diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go
index 353d7f0d05..f78a3eee73 100644
--- a/api/v1alpha7/zz_generated.conversion.go
+++ b/api/v1alpha7/zz_generated.conversion.go
@@ -917,9 +917,15 @@ func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(i
// 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)
out.DisableAPIServerFloatingIP = in.DisableAPIServerFloatingIP
- out.APIServerFloatingIP = in.APIServerFloatingIP
- out.APIServerFixedIP = in.APIServerFixedIP
- out.APIServerPort = in.APIServerPort
+ 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
out.DisablePortSecurity = in.DisablePortSecurity
@@ -969,9 +975,15 @@ func autoConvert_v1beta1_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(i
// 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)
out.DisableAPIServerFloatingIP = in.DisableAPIServerFloatingIP
- out.APIServerFloatingIP = in.APIServerFloatingIP
- out.APIServerFixedIP = in.APIServerFixedIP
- out.APIServerPort = in.APIServerPort
+ 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)
out.DisablePortSecurity = in.DisablePortSecurity
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
diff --git a/api/v1beta1/openstackcluster_types.go b/api/v1beta1/openstackcluster_types.go
index 686009f5af..66075e01c6 100644
--- a/api/v1beta1/openstackcluster_types.go
+++ b/api/v1beta1/openstackcluster_types.go
@@ -20,6 +20,8 @@ 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 (
@@ -116,7 +118,8 @@ type OpenStackClusterSpec struct {
// 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,
@@ -126,11 +129,13 @@ 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
diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go
index 6dbf28e798..94c33c44d5 100644
--- a/api/v1beta1/zz_generated.deepcopy.go
+++ b/api/v1beta1/zz_generated.deepcopy.go
@@ -521,6 +521,21 @@ func (in *OpenStackClusterSpec) DeepCopyInto(out *OpenStackClusterSpec) {
*out = new(APIServerLoadBalancer)
(*in).DeepCopyInto(*out)
}
+ 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)
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index 55400169fe..97bb1a988a 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -464,10 +464,14 @@ func reconcileBastion(scope *scope.WithLogger, cluster *clusterv1.Cluster, openS
return ctrl.Result{}, nil
}
- floatingIP := openStackCluster.Spec.Bastion.FloatingIP
- if openStackCluster.Status.Bastion.FloatingIP != "" {
+ 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
+ floatingIP = &openStackCluster.Status.Bastion.FloatingIP
+ case openStackCluster.Spec.Bastion.FloatingIP != "":
+ // 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, clusterName, floatingIP)
@@ -760,8 +764,8 @@ func reconcileControlPlaneEndpoint(scope *scope.WithLogger, networkingService *n
// 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 != "":
- host = openStackCluster.Spec.APIServerFixedIP
+ case openStackCluster.Spec.APIServerFixedIP != nil:
+ host = *openStackCluster.Spec.APIServerFixedIP
// Control plane endpoint is not set, and none can be created
default:
@@ -783,8 +787,8 @@ func getAPIServerPort(openStackCluster *infrav1.OpenStackCluster) int {
switch {
case openStackCluster.Spec.ControlPlaneEndpoint.IsValid():
return int(openStackCluster.Spec.ControlPlaneEndpoint.Port)
- case openStackCluster.Spec.APIServerPort != 0:
- return openStackCluster.Spec.APIServerPort
+ case openStackCluster.Spec.APIServerPort != nil:
+ return *openStackCluster.Spec.APIServerPort
}
return 6443
}
diff --git a/controllers/openstackcluster_controller_test.go b/controllers/openstackcluster_controller_test.go
index 0bd5e68bde..8f9f501f35 100644
--- a/controllers/openstackcluster_controller_test.go
+++ b/controllers/openstackcluster_controller_test.go
@@ -521,7 +521,7 @@ var _ = Describe("OpenStackCluster controller", func() {
Enabled: true,
},
DisableAPIServerFloatingIP: true,
- APIServerFixedIP: "10.0.0.1",
+ APIServerFixedIP: pointer.String("10.0.0.1"),
ExternalNetwork: &infrav1.NetworkFilter{
ID: externalNetworkID,
},
@@ -601,7 +601,7 @@ var _ = Describe("OpenStackCluster controller", func() {
Enabled: true,
},
DisableAPIServerFloatingIP: true,
- APIServerFixedIP: "10.0.0.1",
+ APIServerFixedIP: pointer.String("10.0.0.1"),
ExternalNetwork: &infrav1.NetworkFilter{
ID: externalNetworkID,
},
@@ -683,7 +683,7 @@ var _ = Describe("OpenStackCluster controller", func() {
testCluster.SetName("subnet-filtering")
testCluster.Spec = infrav1.OpenStackClusterSpec{
DisableAPIServerFloatingIP: true,
- APIServerFixedIP: "10.0.0.1",
+ APIServerFixedIP: pointer.String("10.0.0.1"),
DisableExternalNetwork: true,
Subnets: []infrav1.SubnetFilter{
{ID: clusterSubnetID},
@@ -777,7 +777,7 @@ func Test_getAPIServerPort(t *testing.T) {
name: "with API server port",
openStackCluster: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
- APIServerPort: 6445,
+ APIServerPort: pointer.Int(6445),
},
},
want: 6445,
diff --git a/controllers/openstackmachine_controller.go b/controllers/openstackmachine_controller.go
index f926cb8aa6..1915ffb0d1 100644
--- a/controllers/openstackmachine_controller.go
+++ b/controllers/openstackmachine_controller.go
@@ -278,7 +278,7 @@ func (r *OpenStackMachineReconciler) reconcileDelete(scope *scope.WithLogger, cl
} else if instanceStatus, err = computeService.GetInstanceStatusByName(openStackMachine, openStackMachine.Name); err != nil {
return ctrl.Result{}, err
}
- if !openStackCluster.Spec.APIServerLoadBalancer.IsEnabled() && util.IsControlPlaneMachine(machine) && openStackCluster.Spec.APIServerFloatingIP == "" {
+ if !openStackCluster.Spec.APIServerLoadBalancer.IsEnabled() && util.IsControlPlaneMachine(machine) && openStackCluster.Spec.APIServerFloatingIP == nil {
if instanceStatus != nil {
instanceNS, err := instanceStatus.NetworkStatus()
if err != nil {
@@ -459,14 +459,17 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope
return ctrl.Result{}, fmt.Errorf("reconcile load balancer member: %w", err)
}
} else if !openStackCluster.Spec.DisableAPIServerFloatingIP {
- floatingIPAddress := openStackCluster.Spec.ControlPlaneEndpoint.Host
- if openStackCluster.Spec.APIServerFloatingIP != "" {
+ var floatingIPAddress *string
+ switch {
+ case 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)
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 ctrl.Result{}, fmt.Errorf("get or create floating IP %v: %w", floatingIPAddress, err)
}
port, err := computeService.GetManagementPort(openStackCluster, instanceStatus)
if err != nil {
diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md
index 1849ebcf04..332513b930 100644
--- a/docs/book/src/api/v1beta1/api.md
+++ b/docs/book/src/api/v1beta1/api.md
@@ -243,6 +243,7 @@ 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.
@@ -257,6 +258,7 @@ 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.
@@ -275,6 +277,7 @@ int
|
+(Optional)
APIServerPort is the port on which the listener on the APIServer
will be created
|
@@ -2130,6 +2133,7 @@ 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.
@@ -2144,6 +2148,7 @@ 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.
@@ -2162,6 +2167,7 @@ int
|
+(Optional)
APIServerPort is the port on which the listener on the APIServer
will be created
|
@@ -2696,6 +2702,7 @@ 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.
@@ -2710,6 +2717,7 @@ 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.
@@ -2728,6 +2736,7 @@ int
|
+(Optional)
APIServerPort is the port on which the listener on the APIServer
will be created
|
diff --git a/pkg/cloud/services/loadbalancer/loadbalancer.go b/pkg/cloud/services/loadbalancer/loadbalancer.go
index 7a5d3ceaa4..a2ffd1ebf1 100644
--- a/pkg/cloud/services/loadbalancer/loadbalancer.go
+++ b/pkg/cloud/services/loadbalancer/loadbalancer.go
@@ -52,17 +52,17 @@ const loadBalancerProvisioningStatusActive = "ACTIVE"
// We wrap the LookupHost function in a variable to allow overriding it in unit tests.
//
//nolint:gocritic
-var lookupHost = func(host string) (string, error) {
+var lookupHost = func(host string) (*string, error) {
ctx, cancel := context.WithTimeout(context.TODO(), 30*time.Second)
defer cancel()
ips, err := net.DefaultResolver.LookupHost(ctx, host)
if err != nil {
- return "", err
+ return nil, err
}
if ip := net.ParseIP(ips[0]); ip == nil {
- return "", fmt.Errorf("failed to resolve IP address for host %s", host)
+ return nil, fmt.Errorf("failed to resolve IP address for host %s", host)
}
- return ips[0], nil
+ return &ips[0], nil
}
// ReconcileLoadBalancer reconciles the load balancer for the given cluster.
@@ -145,50 +145,50 @@ func (s *Service) ReconcileLoadBalancer(openStackCluster *infrav1.OpenStackClust
// getAPIServerVIPAddress gets the VIP address for the API server from wherever it is specified.
// Returns an empty string if the VIP address is not specified and it should be allocated automatically.
-func getAPIServerVIPAddress(openStackCluster *infrav1.OpenStackCluster) (string, error) {
+func getAPIServerVIPAddress(openStackCluster *infrav1.OpenStackCluster) (*string, error) {
switch {
// We only use call this function when creating the loadbalancer, so this case should never be used
case openStackCluster.Status.APIServerLoadBalancer != nil && openStackCluster.Status.APIServerLoadBalancer.InternalIP != "":
- return openStackCluster.Status.APIServerLoadBalancer.InternalIP, nil
+ return &openStackCluster.Status.APIServerLoadBalancer.InternalIP, nil
// Explicit fixed IP in the cluster spec
- case openStackCluster.Spec.APIServerFixedIP != "":
+ case openStackCluster.Spec.APIServerFixedIP != nil:
return openStackCluster.Spec.APIServerFixedIP, nil
// If we are using the VIP as the control plane endpoint, use any value explicitly set on the control plane endpoint
case openStackCluster.Spec.DisableAPIServerFloatingIP && openStackCluster.Spec.ControlPlaneEndpoint.IsValid():
fixedIPAddress, err := lookupHost(openStackCluster.Spec.ControlPlaneEndpoint.Host)
if err != nil {
- return "", fmt.Errorf("lookup host: %w", err)
+ return nil, fmt.Errorf("lookup host: %w", err)
}
return fixedIPAddress, nil
}
- return "", nil
+ return nil, nil
}
// getAPIServerFloatingIP gets the floating IP from wherever it is specified.
// Returns an empty string if the floating IP is not specified and it should be allocated automatically.
-func getAPIServerFloatingIP(openStackCluster *infrav1.OpenStackCluster) (string, error) {
+func getAPIServerFloatingIP(openStackCluster *infrav1.OpenStackCluster) (*string, error) {
switch {
// The floating IP was created previously
case openStackCluster.Status.APIServerLoadBalancer != nil && openStackCluster.Status.APIServerLoadBalancer.IP != "":
- return openStackCluster.Status.APIServerLoadBalancer.IP, nil
+ return &openStackCluster.Status.APIServerLoadBalancer.IP, nil
// Explicit floating IP in the cluster spec
- case openStackCluster.Spec.APIServerFloatingIP != "":
+ case openStackCluster.Spec.APIServerFloatingIP != nil:
return openStackCluster.Spec.APIServerFloatingIP, nil
// An IP address is specified explicitly in the control plane endpoint
case openStackCluster.Spec.ControlPlaneEndpoint.IsValid():
floatingIPAddress, err := lookupHost(openStackCluster.Spec.ControlPlaneEndpoint.Host)
if err != nil {
- return "", fmt.Errorf("lookup host: %w", err)
+ return nil, fmt.Errorf("lookup host: %w", err)
}
return floatingIPAddress, nil
}
- return "", nil
+ return nil, nil
}
// getCanonicalAllowedCIDRs gets a filtered list of CIDRs which should be allowed to access the API server loadbalancer.
@@ -301,11 +301,14 @@ func (s *Service) getOrCreateAPILoadBalancer(openStackCluster *infrav1.OpenStack
lbCreateOpts := loadbalancers.CreateOpts{
Name: loadBalancerName,
VipSubnetID: subnetID,
- VipAddress: vipAddress,
Description: names.GetDescription(clusterName),
Provider: lbProvider,
Tags: openStackCluster.Spec.Tags,
}
+ if vipAddress != nil {
+ lbCreateOpts.VipAddress = *vipAddress
+ }
+
lb, err = s.loadbalancerClient.CreateLoadBalancer(lbCreateOpts)
if err != nil {
record.Warnf(openStackCluster, "FailedCreateLoadBalancer", "Failed to create load balancer %s: %v", loadBalancerName, err)
@@ -611,7 +614,7 @@ func (s *Service) DeleteLoadBalancer(openStackCluster *infrav1.OpenStackCluster,
}
// If the floating is user-provider (BYO floating IP), don't delete it.
- if openStackCluster.Spec.APIServerFloatingIP != fip.FloatingIP {
+ if openStackCluster.Spec.APIServerFloatingIP == nil || *openStackCluster.Spec.APIServerFloatingIP != fip.FloatingIP {
if err = s.networkingService.DeleteFloatingIP(openStackCluster, fip.FloatingIP); err != nil {
return err
}
diff --git a/pkg/cloud/services/loadbalancer/loadbalancer_test.go b/pkg/cloud/services/loadbalancer/loadbalancer_test.go
index 7011ebd6c7..2f24832e41 100644
--- a/pkg/cloud/services/loadbalancer/loadbalancer_test.go
+++ b/pkg/cloud/services/loadbalancer/loadbalancer_test.go
@@ -31,6 +31,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/pools"
"github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/providers"
. "github.com/onsi/gomega"
+ "k8s.io/utils/pointer"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
@@ -45,14 +46,14 @@ func Test_ReconcileLoadBalancer(t *testing.T) {
defer mockCtrl.Finish()
// Stub the call to net.LookupHost
- lookupHost = func(host string) (addrs string, err error) {
+ lookupHost = func(host string) (addrs *string, err error) {
if net.ParseIP(host) != nil {
- return host, nil
+ return &host, nil
} else if host == apiHostname {
ips := []string{"192.168.100.10"}
- return ips[0], nil
+ return &ips[0], nil
}
- return "", errors.New("Unknown Host " + host)
+ return nil, errors.New("Unknown Host " + host)
}
openStackCluster := &infrav1.OpenStackCluster{
@@ -162,25 +163,25 @@ func Test_ReconcileLoadBalancer(t *testing.T) {
func Test_getAPIServerVIPAddress(t *testing.T) {
// Stub the call to net.LookupHost
- lookupHost = func(host string) (addrs string, err error) {
+ lookupHost = func(host string) (addrs *string, err error) {
if net.ParseIP(host) != nil {
- return host, nil
+ return &host, nil
} else if host == apiHostname {
ips := []string{"192.168.100.10"}
- return ips[0], nil
+ return &ips[0], nil
}
- return "", errors.New("Unknown Host " + host)
+ return nil, errors.New("Unknown Host " + host)
}
tests := []struct {
name string
openStackCluster *infrav1.OpenStackCluster
- want string
+ want *string
wantError bool
}{
{
name: "empty cluster returns empty VIP",
openStackCluster: &infrav1.OpenStackCluster{},
- want: "",
+ want: nil,
wantError: false,
},
{
@@ -192,17 +193,17 @@ func Test_getAPIServerVIPAddress(t *testing.T) {
},
},
},
- want: "1.2.3.4",
+ want: pointer.String("1.2.3.4"),
wantError: false,
},
{
name: "API server VIP is API Server Fixed IP",
openStackCluster: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
- APIServerFixedIP: "1.2.3.4",
+ APIServerFixedIP: pointer.String("1.2.3.4"),
},
},
- want: "1.2.3.4",
+ want: pointer.String("1.2.3.4"),
wantError: false,
},
{
@@ -216,7 +217,7 @@ func Test_getAPIServerVIPAddress(t *testing.T) {
},
},
},
- want: "192.168.100.10",
+ want: pointer.String("192.168.100.10"),
wantError: false,
},
{
@@ -240,6 +241,7 @@ func Test_getAPIServerVIPAddress(t *testing.T) {
got, err := getAPIServerVIPAddress(tt.openStackCluster)
if tt.wantError {
g.Expect(err).To(HaveOccurred())
+ g.Expect(got).To(BeNil())
} else {
g.Expect(err).NotTo(HaveOccurred())
g.Expect(got).To(Equal(tt.want))
@@ -250,25 +252,25 @@ func Test_getAPIServerVIPAddress(t *testing.T) {
func Test_getAPIServerFloatingIP(t *testing.T) {
// Stub the call to net.LookupHost
- lookupHost = func(host string) (addrs string, err error) {
+ lookupHost = func(host string) (addrs *string, err error) {
if net.ParseIP(host) != nil {
- return host, nil
+ return &host, nil
} else if host == apiHostname {
ips := []string{"192.168.100.10"}
- return ips[0], nil
+ return &ips[0], nil
}
- return "", errors.New("Unknown Host " + host)
+ return nil, errors.New("Unknown Host " + host)
}
tests := []struct {
name string
openStackCluster *infrav1.OpenStackCluster
- want string
+ want *string
wantError bool
}{
{
name: "empty cluster returns empty FIP",
openStackCluster: &infrav1.OpenStackCluster{},
- want: "",
+ want: nil,
wantError: false,
},
{
@@ -280,17 +282,17 @@ func Test_getAPIServerFloatingIP(t *testing.T) {
},
},
},
- want: "1.2.3.4",
+ want: pointer.String("1.2.3.4"),
wantError: false,
},
{
name: "API server FIP is API Server Floating IP",
openStackCluster: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
- APIServerFloatingIP: "1.2.3.4",
+ APIServerFloatingIP: pointer.String("1.2.3.4"),
},
},
- want: "1.2.3.4",
+ want: pointer.String("1.2.3.4"),
wantError: false,
},
{
@@ -303,7 +305,7 @@ func Test_getAPIServerFloatingIP(t *testing.T) {
},
},
},
- want: "192.168.100.10",
+ want: pointer.String("192.168.100.10"),
wantError: false,
},
{
@@ -326,6 +328,7 @@ func Test_getAPIServerFloatingIP(t *testing.T) {
got, err := getAPIServerFloatingIP(tt.openStackCluster)
if tt.wantError {
g.Expect(err).To(HaveOccurred())
+ g.Expect(got).To(BeNil())
} else {
g.Expect(err).NotTo(HaveOccurred())
g.Expect(got).To(Equal(tt.want))
diff --git a/pkg/cloud/services/networking/floatingip.go b/pkg/cloud/services/networking/floatingip.go
index f7fc8dc308..68f6cb2aac 100644
--- a/pkg/cloud/services/networking/floatingip.go
+++ b/pkg/cloud/services/networking/floatingip.go
@@ -24,6 +24,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/wait"
+ "k8s.io/utils/pointer"
"sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha1"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
@@ -32,13 +33,13 @@ import (
"sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/names"
)
-func (s *Service) GetOrCreateFloatingIP(eventObject runtime.Object, openStackCluster *infrav1.OpenStackCluster, clusterName, ip string) (*floatingips.FloatingIP, error) {
+func (s *Service) GetOrCreateFloatingIP(eventObject runtime.Object, openStackCluster *infrav1.OpenStackCluster, clusterName string, ip *string) (*floatingips.FloatingIP, error) {
var fp *floatingips.FloatingIP
var err error
var fpCreateOpts floatingips.CreateOpts
- if ip != "" {
- fp, err = s.GetFloatingIP(ip)
+ if pointer.StringDeref(ip, "") != "" {
+ fp, err = s.GetFloatingIP(*ip)
if err != nil {
return nil, err
}
@@ -46,15 +47,17 @@ func (s *Service) GetOrCreateFloatingIP(eventObject runtime.Object, openStackClu
return fp, nil
}
// only admin can add ip address
- fpCreateOpts.FloatingIP = ip
+ fpCreateOpts.FloatingIP = *ip
}
fpCreateOpts.FloatingNetworkID = openStackCluster.Status.ExternalNetwork.ID
fpCreateOpts.Description = names.GetDescription(clusterName)
+ s.scope.Logger().Info("Creating floating IP", "ip", fpCreateOpts.FloatingIP, "floatingNetworkID", openStackCluster.Status.ExternalNetwork.ID, "description", fpCreateOpts.Description)
+
fp, err = s.client.CreateFloatingIP(fpCreateOpts)
if err != nil {
- record.Warnf(eventObject, "FailedCreateFloatingIP", "Failed to create floating IP %s: %v", ip, err)
+ record.Warnf(eventObject, "FailedCreateFloatingIP", "Failed to create floating IP %s: %v", fpCreateOpts.FloatingIP, err)
return nil, err
}
diff --git a/pkg/cloud/services/networking/floatingip_test.go b/pkg/cloud/services/networking/floatingip_test.go
index e25a42ab53..60a9db4300 100644
--- a/pkg/cloud/services/networking/floatingip_test.go
+++ b/pkg/cloud/services/networking/floatingip_test.go
@@ -19,12 +19,15 @@ package networking
import (
"testing"
+ "github.com/go-logr/logr/testr"
"github.com/golang/mock/gomock"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips"
. "github.com/onsi/gomega"
+ "k8s.io/utils/pointer"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/mock"
+ "sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
)
func Test_GetOrCreateFloatingIP(t *testing.T) {
@@ -72,13 +75,18 @@ func Test_GetOrCreateFloatingIP(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
g := NewWithT(t)
+ log := testr.New(t)
mockClient := mock.NewMockNetworkClient(mockCtrl)
+ mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "")
tt.expect(mockClient.EXPECT())
+
+ scope := scope.NewWithLogger(mockScopeFactory, log)
s := Service{
+ scope: scope,
client: mockClient,
}
eventObject := infrav1.OpenStackMachine{}
- got, err := s.GetOrCreateFloatingIP(&eventObject, openStackCluster, "test-cluster", tt.ip)
+ got, err := s.GetOrCreateFloatingIP(&eventObject, openStackCluster, "test-cluster", pointer.String(tt.ip))
g.Expect(err).ShouldNot(HaveOccurred())
g.Expect(got).To(Equal(tt.want))
})
diff --git a/pkg/webhooks/openstackcluster_webhook.go b/pkg/webhooks/openstackcluster_webhook.go
index 0ee6326b54..ed266ca369 100644
--- a/pkg/webhooks/openstackcluster_webhook.go
+++ b/pkg/webhooks/openstackcluster_webhook.go
@@ -23,6 +23,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
+ "k8s.io/utils/pointer"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/manager"
@@ -95,13 +96,14 @@ func (*openStackClusterWebhook) ValidateUpdate(_ context.Context, oldObjRaw, new
}
// Allow change only for the first time.
- if oldObj.Spec.DisableAPIServerFloatingIP && oldObj.Spec.APIServerFixedIP == "" {
- newObj.Spec.APIServerFixedIP = ""
+ if oldObj.Spec.DisableAPIServerFloatingIP && pointer.StringDeref(oldObj.Spec.APIServerFixedIP, "") == "" {
+ oldObj.Spec.APIServerFixedIP = nil
+ newObj.Spec.APIServerFixedIP = nil
}
// If API Server floating IP is disabled, allow the change of the API Server port only for the first time.
- if oldObj.Spec.DisableAPIServerFloatingIP && oldObj.Spec.APIServerPort == 0 && newObj.Spec.APIServerPort > 0 {
- newObj.Spec.APIServerPort = 0
+ if oldObj.Spec.DisableAPIServerFloatingIP && oldObj.Spec.APIServerPort == nil && newObj.Spec.APIServerPort != nil {
+ newObj.Spec.APIServerPort = nil
}
// Allow to remove the bastion spec only if it was disabled before.
@@ -141,9 +143,9 @@ func (*openStackClusterWebhook) ValidateUpdate(_ context.Context, oldObjRaw, new
newObj.Spec.ControlPlaneOmitAvailabilityZone = false
// Allow change on the spec.APIServerFloatingIP only if it matches the current api server loadbalancer IP.
- if oldObj.Status.APIServerLoadBalancer != nil && newObj.Spec.APIServerFloatingIP == oldObj.Status.APIServerLoadBalancer.IP {
- newObj.Spec.APIServerFloatingIP = ""
- oldObj.Spec.APIServerFloatingIP = ""
+ if oldObj.Status.APIServerLoadBalancer != nil && pointer.StringDeref(newObj.Spec.APIServerFloatingIP, "") == oldObj.Status.APIServerLoadBalancer.IP {
+ newObj.Spec.APIServerFloatingIP = nil
+ oldObj.Spec.APIServerFloatingIP = nil
}
if !reflect.DeepEqual(oldObj.Spec, newObj.Spec) {
diff --git a/pkg/webhooks/openstackcluster_webhook_test.go b/pkg/webhooks/openstackcluster_webhook_test.go
index 8668059030..c64e384a72 100644
--- a/pkg/webhooks/openstackcluster_webhook_test.go
+++ b/pkg/webhooks/openstackcluster_webhook_test.go
@@ -309,7 +309,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
CloudName: "foobar",
},
DisableAPIServerFloatingIP: true,
- APIServerFixedIP: "20.1.56.1",
+ APIServerFixedIP: pointer.String("20.1.56.1"),
},
},
wantErr: false,
@@ -332,7 +332,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
CloudName: "foobar",
},
DisableAPIServerFloatingIP: false,
- APIServerFixedIP: "20.1.56.1",
+ APIServerFixedIP: pointer.String("20.1.56.1"),
},
},
wantErr: true,
@@ -352,7 +352,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
newTemplate: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
DisableAPIServerFloatingIP: true,
- APIServerPort: 8443,
+ APIServerPort: pointer.Int(8443),
},
},
wantErr: false,
@@ -375,7 +375,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
CloudName: "foobar",
},
DisableAPIServerFloatingIP: false,
- APIServerPort: 8443,
+ APIServerPort: pointer.Int(8443),
},
},
wantErr: true,
@@ -388,7 +388,6 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
Name: "foobar",
CloudName: "foobar",
},
- APIServerFloatingIP: "",
},
Status: infrav1.OpenStackClusterStatus{
APIServerLoadBalancer: &infrav1.LoadBalancer{
@@ -402,7 +401,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
Name: "foobar",
CloudName: "foobar",
},
- APIServerFloatingIP: "1.2.3.4",
+ APIServerFloatingIP: pointer.String("1.2.3.4"),
},
Status: infrav1.OpenStackClusterStatus{
APIServerLoadBalancer: &infrav1.LoadBalancer{
@@ -420,7 +419,6 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
Name: "foobar",
CloudName: "foobar",
},
- APIServerFloatingIP: "",
},
Status: infrav1.OpenStackClusterStatus{
APIServerLoadBalancer: &infrav1.LoadBalancer{
@@ -434,7 +432,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
Name: "foobar",
CloudName: "foobar",
},
- APIServerFloatingIP: "5.6.7.8",
+ APIServerFloatingIP: pointer.String("5.6.7.8"),
},
Status: infrav1.OpenStackClusterStatus{
APIServerLoadBalancer: &infrav1.LoadBalancer{
From 9223883df61151215286df3442ee1c29a1590c38 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Wed, 6 Mar 2024 20:06:32 +0000
Subject: [PATCH 117/180] OpenStackClusterSpec: scalar fields to optional types
The following types become a corresponding optional type:
* NetworkMTU
* DisableExternalNetwork
* DisableAPIServerFloatingIP
* DisablePortSecurity
* ControlPlaneOmitAvailabilityZone
---
api/v1alpha5/conversion_test.go | 4 +--
api/v1alpha5/zz_generated.conversion.go | 16 +++++++---
api/v1alpha6/openstackcluster_conversion.go | 3 ++
api/v1alpha6/zz_generated.conversion.go | 24 ++++++++++----
api/v1alpha7/openstackcluster_conversion.go | 3 ++
api/v1alpha7/zz_generated.conversion.go | 32 ++++++++++++++-----
api/v1beta1/openstackcluster_types.go | 18 +++++++----
api/v1beta1/zz_generated.deepcopy.go | 25 +++++++++++++++
...re.cluster.x-k8s.io_openstackclusters.yaml | 6 ++--
...er.x-k8s.io_openstackclustertemplates.yaml | 6 ++--
controllers/openstackcluster_controller.go | 4 +--
.../openstackcluster_controller_test.go | 8 ++---
controllers/openstackmachine_controller.go | 2 +-
docs/book/src/api/v1beta1/api.md | 24 ++++++++++----
.../services/loadbalancer/loadbalancer.go | 5 +--
.../loadbalancer/loadbalancer_test.go | 6 ++--
pkg/cloud/services/networking/network.go | 8 ++---
pkg/cloud/services/networking/network_test.go | 8 ++---
pkg/webhooks/openstackcluster_webhook.go | 8 ++---
pkg/webhooks/openstackcluster_webhook_test.go | 18 +++++------
20 files changed, 158 insertions(+), 70 deletions(-)
diff --git a/api/v1alpha5/conversion_test.go b/api/v1alpha5/conversion_test.go
index ceb18344a9..1657cee45d 100644
--- a/api/v1alpha5/conversion_test.go
+++ b/api/v1alpha5/conversion_test.go
@@ -51,7 +51,7 @@ func TestConvertFrom(t *testing.T) {
},
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
- "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"disableExternalNetwork\":false,\"identityRef\":{\"cloudName\":\"\",\"name\":\"\"}},\"status\":{\"ready\":false}}",
+ "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"identityRef\":{\"cloudName\":\"\",\"name\":\"\"}},\"status\":{\"ready\":false}}",
},
},
},
@@ -72,7 +72,7 @@ func TestConvertFrom(t *testing.T) {
},
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
- "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"template\":{\"spec\":{\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"disableExternalNetwork\":false,\"identityRef\":{\"cloudName\":\"\",\"name\":\"\"}}}}}",
+ "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"template\":{\"spec\":{\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"identityRef\":{\"cloudName\":\"\",\"name\":\"\"}}}}}",
},
},
},
diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go
index a23b47e552..d5f2ca7c80 100644
--- a/api/v1alpha5/zz_generated.conversion.go
+++ b/api/v1alpha5/zz_generated.conversion.go
@@ -675,7 +675,9 @@ func autoConvert_v1alpha5_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(i
}
// 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)
- out.DisableAPIServerFloatingIP = in.DisableAPIServerFloatingIP
+ 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
}
@@ -687,7 +689,9 @@ func autoConvert_v1alpha5_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(i
}
// 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
- out.DisablePortSecurity = in.DisablePortSecurity
+ if err := optional.Convert_bool_To_optional_Bool(&in.DisablePortSecurity, &out.DisablePortSecurity, s); err != nil {
+ return err
+ }
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
out.ControlPlaneEndpoint = in.ControlPlaneEndpoint
out.ControlPlaneAvailabilityZones = *(*[]string)(unsafe.Pointer(&in.ControlPlaneAvailabilityZones))
@@ -724,7 +728,9 @@ func autoConvert_v1beta1_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(i
// 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)
- out.DisableAPIServerFloatingIP = in.DisableAPIServerFloatingIP
+ 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
}
@@ -735,7 +741,9 @@ func autoConvert_v1beta1_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(i
return err
}
// WARNING: in.ManagedSecurityGroups requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ManagedSecurityGroups vs bool)
- out.DisablePortSecurity = in.DisablePortSecurity
+ if err := optional.Convert_optional_Bool_To_bool(&in.DisablePortSecurity, &out.DisablePortSecurity, s); err != nil {
+ return err
+ }
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
out.ControlPlaneEndpoint = in.ControlPlaneEndpoint
out.ControlPlaneAvailabilityZones = *(*[]string)(unsafe.Pointer(&in.ControlPlaneAvailabilityZones))
diff --git a/api/v1alpha6/openstackcluster_conversion.go b/api/v1alpha6/openstackcluster_conversion.go
index 33a174b1a8..84913eeb30 100644
--- a/api/v1alpha6/openstackcluster_conversion.go
+++ b/api/v1alpha6/openstackcluster_conversion.go
@@ -204,6 +204,9 @@ func restorev1beta1ClusterSpec(previous *infrav1.OpenStackClusterSpec, dst *infr
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)
}
func Convert_v1alpha6_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *OpenStackClusterSpec, out *infrav1.OpenStackClusterSpec, s apiconversion.Scope) error {
diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go
index 6a2c5a1ed0..bf26270b5b 100644
--- a/api/v1alpha6/zz_generated.conversion.go
+++ b/api/v1alpha6/zz_generated.conversion.go
@@ -701,7 +701,9 @@ func autoConvert_v1alpha6_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(i
}
// 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)
- out.DisableAPIServerFloatingIP = in.DisableAPIServerFloatingIP
+ 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
}
@@ -713,11 +715,15 @@ func autoConvert_v1alpha6_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(i
}
// 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
- out.DisablePortSecurity = in.DisablePortSecurity
+ if err := optional.Convert_bool_To_optional_Bool(&in.DisablePortSecurity, &out.DisablePortSecurity, s); err != nil {
+ return err
+ }
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
out.ControlPlaneEndpoint = in.ControlPlaneEndpoint
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(v1beta1.Bastion)
@@ -751,7 +757,9 @@ func autoConvert_v1beta1_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(i
// 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)
- out.DisableAPIServerFloatingIP = in.DisableAPIServerFloatingIP
+ 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
}
@@ -762,11 +770,15 @@ func autoConvert_v1beta1_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(i
return err
}
// WARNING: in.ManagedSecurityGroups requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ManagedSecurityGroups vs bool)
- out.DisablePortSecurity = in.DisablePortSecurity
+ if err := optional.Convert_optional_Bool_To_bool(&in.DisablePortSecurity, &out.DisablePortSecurity, s); err != nil {
+ return err
+ }
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
out.ControlPlaneEndpoint = in.ControlPlaneEndpoint
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)
diff --git a/api/v1alpha7/openstackcluster_conversion.go b/api/v1alpha7/openstackcluster_conversion.go
index 8a478229a8..55ccc713a3 100644
--- a/api/v1alpha7/openstackcluster_conversion.go
+++ b/api/v1alpha7/openstackcluster_conversion.go
@@ -206,6 +206,9 @@ func restorev1beta1ClusterSpec(previous *infrav1.OpenStackClusterSpec, dst *infr
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)
}
func Convert_v1alpha7_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *OpenStackClusterSpec, out *infrav1.OpenStackClusterSpec, s apiconversion.Scope) error {
diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go
index f78a3eee73..586a18a335 100644
--- a/api/v1alpha7/zz_generated.conversion.go
+++ b/api/v1alpha7/zz_generated.conversion.go
@@ -901,7 +901,9 @@ func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(i
}
// 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.NetworkFilter)
// WARNING: in.Subnet requires manual conversion: does not exist in peer-type
- out.NetworkMTU = in.NetworkMTU
+ 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
@@ -916,7 +918,9 @@ func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(i
}
// 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)
- out.DisableAPIServerFloatingIP = in.DisableAPIServerFloatingIP
+ 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
}
@@ -928,11 +932,15 @@ func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(i
}
// 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
- out.DisablePortSecurity = in.DisablePortSecurity
+ if err := optional.Convert_bool_To_optional_Bool(&in.DisablePortSecurity, &out.DisablePortSecurity, s); err != nil {
+ return err
+ }
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
out.ControlPlaneEndpoint = in.ControlPlaneEndpoint
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(v1beta1.Bastion)
@@ -959,7 +967,9 @@ func autoConvert_v1beta1_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(i
}
// WARNING: in.Network requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.NetworkFilter vs sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7.NetworkFilter)
// WARNING: in.Subnets requires manual conversion: does not exist in peer-type
- out.NetworkMTU = in.NetworkMTU
+ 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))
@@ -974,7 +984,9 @@ func autoConvert_v1beta1_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(i
// 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)
- out.DisableAPIServerFloatingIP = in.DisableAPIServerFloatingIP
+ 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
}
@@ -985,11 +997,15 @@ func autoConvert_v1beta1_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(i
return err
}
// WARNING: in.ManagedSecurityGroups requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ManagedSecurityGroups vs bool)
- out.DisablePortSecurity = in.DisablePortSecurity
+ if err := optional.Convert_optional_Bool_To_bool(&in.DisablePortSecurity, &out.DisablePortSecurity, s); err != nil {
+ return err
+ }
out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags))
out.ControlPlaneEndpoint = in.ControlPlaneEndpoint
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)
diff --git a/api/v1beta1/openstackcluster_types.go b/api/v1beta1/openstackcluster_types.go
index 66075e01c6..7a3fd2c7e2 100644
--- a/api/v1beta1/openstackcluster_types.go
+++ b/api/v1beta1/openstackcluster_types.go
@@ -65,7 +65,7 @@ type OpenStackClusterSpec struct {
// 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"`
// ExternalRouterIPs is an array of externalIPs on the respective subnets.
// This is necessary if the router needs a fixed ip in a specific subnet.
@@ -92,7 +92,7 @@ type OpenStackClusterSpec struct {
// 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
- DisableExternalNetwork bool `json:"disableExternalNetwork"`
+ DisableExternalNetwork optional.Bool `json:"disableExternalNetwork,omitempty"`
// APIServerLoadBalancer configures the optional LoadBalancer for the APIServer.
// It must be activated by setting `enabled: true`.
@@ -112,7 +112,7 @@ 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.
@@ -149,7 +149,8 @@ type OpenStackClusterSpec struct {
// 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
// +listType=set
@@ -165,9 +166,12 @@ type OpenStackClusterSpec struct {
// +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
//
diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go
index 94c33c44d5..d9a1b5c547 100644
--- a/api/v1beta1/zz_generated.deepcopy.go
+++ b/api/v1beta1/zz_generated.deepcopy.go
@@ -504,6 +504,11 @@ func (in *OpenStackClusterSpec) DeepCopyInto(out *OpenStackClusterSpec) {
(*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))
@@ -516,11 +521,21 @@ func (in *OpenStackClusterSpec) DeepCopyInto(out *OpenStackClusterSpec) {
*out = new(NetworkFilter)
(*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)
@@ -541,6 +556,11 @@ func (in *OpenStackClusterSpec) DeepCopyInto(out *OpenStackClusterSpec) {
*out = new(ManagedSecurityGroups)
(*in).DeepCopyInto(*out)
}
+ if in.DisablePortSecurity != nil {
+ in, out := &in.DisablePortSecurity, &out.DisablePortSecurity
+ *out = new(bool)
+ **out = **in
+ }
if in.Tags != nil {
in, out := &in.Tags, &out.Tags
*out = make([]string, len(*in))
@@ -552,6 +572,11 @@ func (in *OpenStackClusterSpec) DeepCopyInto(out *OpenStackClusterSpec) {
*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)
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 9e8f44f067..12dbb3d98d 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -5552,8 +5552,10 @@ spec:
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
+ 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: |-
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 4149022c39..bbb278a74f 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -2984,8 +2984,10 @@ spec:
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
+ 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: |-
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index 97bb1a988a..0b4b894a05 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -348,7 +348,7 @@ func reconcileNormal(scope *scope.WithLogger, cluster *clusterv1.Cluster, openSt
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 := !pointer.BoolDeref(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)
@@ -752,7 +752,7 @@ func reconcileControlPlaneEndpoint(scope *scope.WithLogger, networkingService *n
// 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 !openStackCluster.Spec.DisableAPIServerFloatingIP:
+ case !pointer.BoolDeref(openStackCluster.Spec.DisableAPIServerFloatingIP, false):
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))
diff --git a/controllers/openstackcluster_controller_test.go b/controllers/openstackcluster_controller_test.go
index 8f9f501f35..e6e2263791 100644
--- a/controllers/openstackcluster_controller_test.go
+++ b/controllers/openstackcluster_controller_test.go
@@ -520,7 +520,7 @@ var _ = Describe("OpenStackCluster controller", func() {
Bastion: &infrav1.Bastion{
Enabled: true,
},
- DisableAPIServerFloatingIP: true,
+ DisableAPIServerFloatingIP: pointer.Bool(true),
APIServerFixedIP: pointer.String("10.0.0.1"),
ExternalNetwork: &infrav1.NetworkFilter{
ID: externalNetworkID,
@@ -600,7 +600,7 @@ var _ = Describe("OpenStackCluster controller", func() {
Bastion: &infrav1.Bastion{
Enabled: true,
},
- DisableAPIServerFloatingIP: true,
+ DisableAPIServerFloatingIP: pointer.Bool(true),
APIServerFixedIP: pointer.String("10.0.0.1"),
ExternalNetwork: &infrav1.NetworkFilter{
ID: externalNetworkID,
@@ -682,9 +682,9 @@ var _ = Describe("OpenStackCluster controller", func() {
testCluster.SetName("subnet-filtering")
testCluster.Spec = infrav1.OpenStackClusterSpec{
- DisableAPIServerFloatingIP: true,
+ DisableAPIServerFloatingIP: pointer.Bool(true),
APIServerFixedIP: pointer.String("10.0.0.1"),
- DisableExternalNetwork: true,
+ DisableExternalNetwork: pointer.Bool(true),
Subnets: []infrav1.SubnetFilter{
{ID: clusterSubnetID},
},
diff --git a/controllers/openstackmachine_controller.go b/controllers/openstackmachine_controller.go
index 1915ffb0d1..ac1b5a41d1 100644
--- a/controllers/openstackmachine_controller.go
+++ b/controllers/openstackmachine_controller.go
@@ -458,7 +458,7 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope
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)
}
- } else if !openStackCluster.Spec.DisableAPIServerFloatingIP {
+ } else if !pointer.BoolDeref(openStackCluster.Spec.DisableAPIServerFloatingIP, false) {
var floatingIPAddress *string
switch {
case openStackCluster.Spec.ControlPlaneEndpoint.IsValid():
diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md
index 332513b930..ee7b0ee054 100644
--- a/docs/book/src/api/v1beta1/api.md
+++ b/docs/book/src/api/v1beta1/api.md
@@ -310,6 +310,7 @@ bool
+(Optional)
DisablePortSecurity disables the port security of the network created for the
Kubernetes cluster, which also disables SecurityGroups
|
@@ -360,8 +361,11 @@ 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
+(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
|
@@ -2200,6 +2204,7 @@ bool
|
+(Optional)
DisablePortSecurity disables the port security of the network created for the
Kubernetes cluster, which also disables SecurityGroups
|
@@ -2250,8 +2255,11 @@ 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
+(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
|
@@ -2769,6 +2777,7 @@ bool
|
+(Optional)
DisablePortSecurity disables the port security of the network created for the
Kubernetes cluster, which also disables SecurityGroups
|
@@ -2819,8 +2828,11 @@ 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
+(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
|
diff --git a/pkg/cloud/services/loadbalancer/loadbalancer.go b/pkg/cloud/services/loadbalancer/loadbalancer.go
index a2ffd1ebf1..bcc413bf45 100644
--- a/pkg/cloud/services/loadbalancer/loadbalancer.go
+++ b/pkg/cloud/services/loadbalancer/loadbalancer.go
@@ -30,6 +30,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/pools"
"k8s.io/apimachinery/pkg/util/wait"
utilsnet "k8s.io/utils/net"
+ "k8s.io/utils/pointer"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
"sigs.k8s.io/cluster-api/util"
@@ -99,7 +100,7 @@ func (s *Service) ReconcileLoadBalancer(openStackCluster *infrav1.OpenStackClust
}
}
- if !openStackCluster.Spec.DisableAPIServerFloatingIP {
+ if !pointer.BoolDeref(openStackCluster.Spec.DisableAPIServerFloatingIP, false) {
floatingIPAddress, err := getAPIServerFloatingIP(openStackCluster)
if err != nil {
return false, err
@@ -156,7 +157,7 @@ func getAPIServerVIPAddress(openStackCluster *infrav1.OpenStackCluster) (*string
return openStackCluster.Spec.APIServerFixedIP, nil
// If we are using the VIP as the control plane endpoint, use any value explicitly set on the control plane endpoint
- case openStackCluster.Spec.DisableAPIServerFloatingIP && openStackCluster.Spec.ControlPlaneEndpoint.IsValid():
+ case pointer.BoolDeref(openStackCluster.Spec.DisableAPIServerFloatingIP, false) && openStackCluster.Spec.ControlPlaneEndpoint.IsValid():
fixedIPAddress, err := lookupHost(openStackCluster.Spec.ControlPlaneEndpoint.Host)
if err != nil {
return nil, fmt.Errorf("lookup host: %w", err)
diff --git a/pkg/cloud/services/loadbalancer/loadbalancer_test.go b/pkg/cloud/services/loadbalancer/loadbalancer_test.go
index 2f24832e41..3f43c2cdbe 100644
--- a/pkg/cloud/services/loadbalancer/loadbalancer_test.go
+++ b/pkg/cloud/services/loadbalancer/loadbalancer_test.go
@@ -61,7 +61,7 @@ func Test_ReconcileLoadBalancer(t *testing.T) {
APIServerLoadBalancer: &infrav1.APIServerLoadBalancer{
Enabled: true,
},
- DisableAPIServerFloatingIP: true,
+ DisableAPIServerFloatingIP: pointer.Bool(true),
ControlPlaneEndpoint: clusterv1.APIEndpoint{
Host: apiHostname,
Port: 6443,
@@ -210,7 +210,7 @@ func Test_getAPIServerVIPAddress(t *testing.T) {
name: "API server VIP with valid control plane endpoint",
openStackCluster: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
- DisableAPIServerFloatingIP: true,
+ DisableAPIServerFloatingIP: pointer.Bool(true),
ControlPlaneEndpoint: clusterv1.APIEndpoint{
Host: apiHostname,
Port: 6443,
@@ -224,7 +224,7 @@ func Test_getAPIServerVIPAddress(t *testing.T) {
name: "API server VIP with invalid control plane endpoint",
openStackCluster: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
- DisableAPIServerFloatingIP: true,
+ DisableAPIServerFloatingIP: pointer.Bool(true),
ControlPlaneEndpoint: clusterv1.APIEndpoint{
Host: "invalid-api.test-cluster.test",
Port: 6443,
diff --git a/pkg/cloud/services/networking/network.go b/pkg/cloud/services/networking/network.go
index f585cdd269..b5c16b003c 100644
--- a/pkg/cloud/services/networking/network.go
+++ b/pkg/cloud/services/networking/network.go
@@ -80,7 +80,7 @@ func (c createOpts) ToNetworkCreateMap() (map[string]interface{}, error) {
func (s *Service) ReconcileExternalNetwork(openStackCluster *infrav1.OpenStackCluster) error {
var listOpts external.ListOptsExt
- if openStackCluster.Spec.DisableExternalNetwork {
+ if pointer.BoolDeref(openStackCluster.Spec.DisableExternalNetwork, false) {
s.scope.Logger().Info("External network is disabled - proceeding with internal network only")
openStackCluster.Status.ExternalNetwork = nil
return nil
@@ -140,12 +140,12 @@ func (s *Service) ReconcileNetwork(openStackCluster *infrav1.OpenStackCluster, c
Name: networkName,
}
- if openStackCluster.Spec.DisablePortSecurity {
+ if pointer.BoolDeref(openStackCluster.Spec.DisablePortSecurity, false) {
opts.PortSecurityEnabled = gophercloud.Disabled
}
- if openStackCluster.Spec.NetworkMTU > 0 {
- opts.MTU = &openStackCluster.Spec.NetworkMTU
+ if openStackCluster.Spec.NetworkMTU != nil {
+ opts.MTU = openStackCluster.Spec.NetworkMTU
}
network, err := s.client.CreateNetwork(opts)
diff --git a/pkg/cloud/services/networking/network_test.go b/pkg/cloud/services/networking/network_test.go
index d67e80739d..52b0fdb0d4 100644
--- a/pkg/cloud/services/networking/network_test.go
+++ b/pkg/cloud/services/networking/network_test.go
@@ -113,7 +113,7 @@ func Test_ReconcileNetwork(t *testing.T) {
name: "creation with disabled port security",
openStackCluster: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
- DisablePortSecurity: true,
+ DisablePortSecurity: pointer.Bool(true),
},
},
expect: func(m *mock.MockNetworkClientMockRecorder) {
@@ -149,7 +149,7 @@ func Test_ReconcileNetwork(t *testing.T) {
name: "creation with mtu set",
openStackCluster: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
- NetworkMTU: 1500,
+ NetworkMTU: pointer.Int(1500),
},
},
expect: func(m *mock.MockNetworkClientMockRecorder) {
@@ -319,13 +319,13 @@ func Test_ReconcileExternalNetwork(t *testing.T) {
name: "not reconcile external network when external network disabled",
openStackCluster: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
- DisableExternalNetwork: true,
+ DisableExternalNetwork: pointer.Bool(true),
},
},
expect: func(m *mock.MockNetworkClientMockRecorder) {},
want: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
- DisableExternalNetwork: true,
+ DisableExternalNetwork: pointer.Bool(true),
},
Status: infrav1.OpenStackClusterStatus{
ExternalNetwork: nil,
diff --git a/pkg/webhooks/openstackcluster_webhook.go b/pkg/webhooks/openstackcluster_webhook.go
index ed266ca369..eb9b705492 100644
--- a/pkg/webhooks/openstackcluster_webhook.go
+++ b/pkg/webhooks/openstackcluster_webhook.go
@@ -96,13 +96,13 @@ func (*openStackClusterWebhook) ValidateUpdate(_ context.Context, oldObjRaw, new
}
// Allow change only for the first time.
- if oldObj.Spec.DisableAPIServerFloatingIP && pointer.StringDeref(oldObj.Spec.APIServerFixedIP, "") == "" {
+ if pointer.BoolDeref(oldObj.Spec.DisableAPIServerFloatingIP, false) && pointer.StringDeref(oldObj.Spec.APIServerFixedIP, "") == "" {
oldObj.Spec.APIServerFixedIP = nil
newObj.Spec.APIServerFixedIP = nil
}
// If API Server floating IP is disabled, allow the change of the API Server port only for the first time.
- if oldObj.Spec.DisableAPIServerFloatingIP && oldObj.Spec.APIServerPort == nil && newObj.Spec.APIServerPort != nil {
+ if pointer.BoolDeref(oldObj.Spec.DisableAPIServerFloatingIP, false) && oldObj.Spec.APIServerPort == nil && newObj.Spec.APIServerPort != nil {
newObj.Spec.APIServerPort = nil
}
@@ -139,8 +139,8 @@ func (*openStackClusterWebhook) ValidateUpdate(_ context.Context, oldObjRaw, new
// Allow the scheduling to be changed from CAPI managed to Nova and
// vice versa.
- oldObj.Spec.ControlPlaneOmitAvailabilityZone = false
- newObj.Spec.ControlPlaneOmitAvailabilityZone = false
+ oldObj.Spec.ControlPlaneOmitAvailabilityZone = nil
+ newObj.Spec.ControlPlaneOmitAvailabilityZone = nil
// Allow change on the spec.APIServerFloatingIP only if it matches the current api server loadbalancer IP.
if oldObj.Status.APIServerLoadBalancer != nil && pointer.StringDeref(newObj.Spec.APIServerFloatingIP, "") == oldObj.Status.APIServerLoadBalancer.IP {
diff --git a/pkg/webhooks/openstackcluster_webhook_test.go b/pkg/webhooks/openstackcluster_webhook_test.go
index c64e384a72..8c9ed564ae 100644
--- a/pkg/webhooks/openstackcluster_webhook_test.go
+++ b/pkg/webhooks/openstackcluster_webhook_test.go
@@ -286,7 +286,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
Name: "foobar",
CloudName: "foobar",
},
- ControlPlaneOmitAvailabilityZone: true,
+ ControlPlaneOmitAvailabilityZone: pointer.Bool(true),
},
},
wantErr: false,
@@ -299,7 +299,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
Name: "foobar",
CloudName: "foobar",
},
- DisableAPIServerFloatingIP: true,
+ DisableAPIServerFloatingIP: pointer.Bool(true),
},
},
newTemplate: &infrav1.OpenStackCluster{
@@ -308,7 +308,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
Name: "foobar",
CloudName: "foobar",
},
- DisableAPIServerFloatingIP: true,
+ DisableAPIServerFloatingIP: pointer.Bool(true),
APIServerFixedIP: pointer.String("20.1.56.1"),
},
},
@@ -322,7 +322,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
Name: "foobar",
CloudName: "foobar",
},
- DisableAPIServerFloatingIP: false,
+ DisableAPIServerFloatingIP: pointer.Bool(false),
},
},
newTemplate: &infrav1.OpenStackCluster{
@@ -331,7 +331,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
Name: "foobar",
CloudName: "foobar",
},
- DisableAPIServerFloatingIP: false,
+ DisableAPIServerFloatingIP: pointer.Bool(false),
APIServerFixedIP: pointer.String("20.1.56.1"),
},
},
@@ -346,12 +346,12 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
Name: "foobar",
CloudName: "foobar",
},
- DisableAPIServerFloatingIP: true,
+ DisableAPIServerFloatingIP: pointer.Bool(true),
},
},
newTemplate: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
- DisableAPIServerFloatingIP: true,
+ DisableAPIServerFloatingIP: pointer.Bool(true),
APIServerPort: pointer.Int(8443),
},
},
@@ -365,7 +365,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
Name: "foobar",
CloudName: "foobar",
},
- DisableAPIServerFloatingIP: false,
+ DisableAPIServerFloatingIP: pointer.Bool(false),
},
},
newTemplate: &infrav1.OpenStackCluster{
@@ -374,7 +374,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
Name: "foobar",
CloudName: "foobar",
},
- DisableAPIServerFloatingIP: false,
+ DisableAPIServerFloatingIP: pointer.Bool(false),
APIServerPort: pointer.Int(8443),
},
},
From 70bfdaf360030b2be4d45dd37a45d65535a28f22 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Wed, 6 Mar 2024 21:42:31 +0000
Subject: [PATCH 118/180] OpenStackClusterSpec: ControlPlaneEndpoint->pointer
---
api/v1alpha5/conversion_test.go | 4 ++--
api/v1alpha5/zz_generated.conversion.go | 4 ++--
api/v1alpha6/openstackcluster_conversion.go | 13 ++++++++++++
api/v1alpha6/zz_generated.conversion.go | 4 ++--
api/v1alpha7/openstackcluster_conversion.go | 13 ++++++++++++
api/v1alpha7/zz_generated.conversion.go | 4 ++--
api/v1beta1/openstackcluster_types.go | 7 ++++++-
api/v1beta1/zz_generated.deepcopy.go | 6 +++++-
...re.cluster.x-k8s.io_openstackclusters.yaml | 9 ++++++--
...er.x-k8s.io_openstackclustertemplates.yaml | 9 ++++++--
controllers/openstackcluster_controller.go | 6 +++---
.../openstackcluster_controller_test.go | 2 +-
controllers/openstackmachine_controller.go | 2 +-
docs/book/src/api/v1beta1/api.md | 21 ++++++++++++++++---
.../services/loadbalancer/loadbalancer.go | 17 +++++++++++----
.../loadbalancer/loadbalancer_test.go | 10 ++++-----
pkg/webhooks/openstackcluster_webhook.go | 12 ++++++-----
.../apivalidations/openstackcluster_test.go | 7 +++++--
18 files changed, 112 insertions(+), 38 deletions(-)
diff --git a/api/v1alpha5/conversion_test.go b/api/v1alpha5/conversion_test.go
index 1657cee45d..72b3c62851 100644
--- a/api/v1alpha5/conversion_test.go
+++ b/api/v1alpha5/conversion_test.go
@@ -51,7 +51,7 @@ func TestConvertFrom(t *testing.T) {
},
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
- "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"identityRef\":{\"cloudName\":\"\",\"name\":\"\"}},\"status\":{\"ready\":false}}",
+ "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"identityRef\":{\"cloudName\":\"\",\"name\":\"\"}},\"status\":{\"ready\":false}}",
},
},
},
@@ -72,7 +72,7 @@ func TestConvertFrom(t *testing.T) {
},
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
- "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"template\":{\"spec\":{\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"identityRef\":{\"cloudName\":\"\",\"name\":\"\"}}}}}",
+ "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"template\":{\"spec\":{\"identityRef\":{\"cloudName\":\"\",\"name\":\"\"}}}}}",
},
},
},
diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go
index d5f2ca7c80..3b4f8e916c 100644
--- a/api/v1alpha5/zz_generated.conversion.go
+++ b/api/v1alpha5/zz_generated.conversion.go
@@ -693,7 +693,7 @@ func autoConvert_v1alpha5_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(i
return err
}
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
@@ -745,7 +745,7 @@ func autoConvert_v1beta1_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(i
return err
}
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 {
diff --git a/api/v1alpha6/openstackcluster_conversion.go b/api/v1alpha6/openstackcluster_conversion.go
index 84913eeb30..b1ecec275e 100644
--- a/api/v1alpha6/openstackcluster_conversion.go
+++ b/api/v1alpha6/openstackcluster_conversion.go
@@ -20,6 +20,7 @@ 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"
@@ -201,6 +202,10 @@ func restorev1beta1ClusterSpec(previous *infrav1.OpenStackClusterSpec, dst *infr
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)
@@ -256,6 +261,10 @@ func Convert_v1alpha6_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *O
}
}
+ if in.ControlPlaneEndpoint != (clusterv1.APIEndpoint{}) {
+ out.ControlPlaneEndpoint = &in.ControlPlaneEndpoint
+ }
+
out.IdentityRef.CloudName = in.CloudName
if in.IdentityRef != nil {
out.IdentityRef.Name = in.IdentityRef.Name
@@ -304,6 +313,10 @@ func Convert_v1beta1_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(in *i
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}
diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go
index bf26270b5b..b0ea770cdd 100644
--- a/api/v1alpha6/zz_generated.conversion.go
+++ b/api/v1alpha6/zz_generated.conversion.go
@@ -719,7 +719,7 @@ func autoConvert_v1alpha6_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(i
return err
}
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 err := optional.Convert_bool_To_optional_Bool(&in.ControlPlaneOmitAvailabilityZone, &out.ControlPlaneOmitAvailabilityZone, s); err != nil {
return err
@@ -774,7 +774,7 @@ func autoConvert_v1beta1_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(i
return err
}
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 err := optional.Convert_optional_Bool_To_bool(&in.ControlPlaneOmitAvailabilityZone, &out.ControlPlaneOmitAvailabilityZone, s); err != nil {
return err
diff --git a/api/v1alpha7/openstackcluster_conversion.go b/api/v1alpha7/openstackcluster_conversion.go
index 55ccc713a3..c8b5e29507 100644
--- a/api/v1alpha7/openstackcluster_conversion.go
+++ b/api/v1alpha7/openstackcluster_conversion.go
@@ -18,6 +18,7 @@ package v1alpha7
import (
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"
@@ -203,6 +204,10 @@ func restorev1beta1ClusterSpec(previous *infrav1.OpenStackClusterSpec, dst *infr
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)
@@ -258,6 +263,10 @@ func Convert_v1alpha7_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *O
}
}
+ if in.ControlPlaneEndpoint != (clusterv1.APIEndpoint{}) {
+ out.ControlPlaneEndpoint = &in.ControlPlaneEndpoint
+ }
+
out.IdentityRef.CloudName = in.CloudName
if in.IdentityRef != nil {
out.IdentityRef.Name = in.IdentityRef.Name
@@ -306,6 +315,10 @@ func Convert_v1beta1_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in *i
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}
diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go
index 586a18a335..3ce6bde5ca 100644
--- a/api/v1alpha7/zz_generated.conversion.go
+++ b/api/v1alpha7/zz_generated.conversion.go
@@ -936,7 +936,7 @@ func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(i
return err
}
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 err := optional.Convert_bool_To_optional_Bool(&in.ControlPlaneOmitAvailabilityZone, &out.ControlPlaneOmitAvailabilityZone, s); err != nil {
return err
@@ -1001,7 +1001,7 @@ func autoConvert_v1beta1_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(i
return err
}
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 err := optional.Convert_optional_Bool_To_bool(&in.ControlPlaneOmitAvailabilityZone, &out.ControlPlaneOmitAvailabilityZone, s); err != nil {
return err
diff --git a/api/v1beta1/openstackcluster_types.go b/api/v1beta1/openstackcluster_types.go
index 7a3fd2c7e2..acd110ddb5 100644
--- a/api/v1beta1/openstackcluster_types.go
+++ b/api/v1beta1/openstackcluster_types.go
@@ -158,8 +158,13 @@ type OpenStackClusterSpec struct {
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
// +listType=set
diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go
index d9a1b5c547..3e41b4104d 100644
--- a/api/v1beta1/zz_generated.deepcopy.go
+++ b/api/v1beta1/zz_generated.deepcopy.go
@@ -566,7 +566,11 @@ func (in *OpenStackClusterSpec) DeepCopyInto(out *OpenStackClusterSpec) {
*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))
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 12dbb3d98d..526fe25900 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -5536,8 +5536,13 @@ spec:
type: array
x-kubernetes-list-type: set
controlPlaneEndpoint:
- description: ControlPlaneEndpoint represents the endpoint used to
- communicate with the control plane.
+ 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.
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 bbb278a74f..089e5bd9d4 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -2968,8 +2968,13 @@ spec:
type: array
x-kubernetes-list-type: set
controlPlaneEndpoint:
- description: ControlPlaneEndpoint represents the endpoint
- used to communicate with the control plane.
+ 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.
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index 0b4b894a05..0ce97f12d5 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -747,7 +747,7 @@ func reconcileControlPlaneEndpoint(scope *scope.WithLogger, networkingService *n
// 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.IsValid():
+ 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
@@ -774,7 +774,7 @@ func reconcileControlPlaneEndpoint(scope *scope.WithLogger, networkingService *n
return err
}
- openStackCluster.Spec.ControlPlaneEndpoint = clusterv1.APIEndpoint{
+ openStackCluster.Spec.ControlPlaneEndpoint = &clusterv1.APIEndpoint{
Host: host,
Port: int32(apiServerPort),
}
@@ -785,7 +785,7 @@ func reconcileControlPlaneEndpoint(scope *scope.WithLogger, networkingService *n
// 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.IsValid():
+ case openStackCluster.Spec.ControlPlaneEndpoint != nil && openStackCluster.Spec.ControlPlaneEndpoint.IsValid():
return int(openStackCluster.Spec.ControlPlaneEndpoint.Port)
case openStackCluster.Spec.APIServerPort != nil:
return *openStackCluster.Spec.APIServerPort
diff --git a/controllers/openstackcluster_controller_test.go b/controllers/openstackcluster_controller_test.go
index e6e2263791..9688ffb968 100644
--- a/controllers/openstackcluster_controller_test.go
+++ b/controllers/openstackcluster_controller_test.go
@@ -765,7 +765,7 @@ func Test_getAPIServerPort(t *testing.T) {
name: "with a control plane endpoint",
openStackCluster: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
- ControlPlaneEndpoint: clusterv1.APIEndpoint{
+ ControlPlaneEndpoint: &clusterv1.APIEndpoint{
Host: "192.168.0.1",
Port: 6444,
},
diff --git a/controllers/openstackmachine_controller.go b/controllers/openstackmachine_controller.go
index ac1b5a41d1..0195b007ee 100644
--- a/controllers/openstackmachine_controller.go
+++ b/controllers/openstackmachine_controller.go
@@ -461,7 +461,7 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope
} else if !pointer.BoolDeref(openStackCluster.Spec.DisableAPIServerFloatingIP, false) {
var floatingIPAddress *string
switch {
- case openStackCluster.Spec.ControlPlaneEndpoint.IsValid():
+ case openStackCluster.Spec.ControlPlaneEndpoint != nil && openStackCluster.Spec.ControlPlaneEndpoint.IsValid():
floatingIPAddress = &openStackCluster.Spec.ControlPlaneEndpoint.Host
case openStackCluster.Spec.APIServerFloatingIP != nil:
floatingIPAddress = openStackCluster.Spec.APIServerFloatingIP
diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md
index ee7b0ee054..8a1bad996d 100644
--- a/docs/book/src/api/v1beta1/api.md
+++ b/docs/book/src/api/v1beta1/api.md
@@ -338,7 +338,12 @@ sigs.k8s.io/cluster-api/api/v1beta1.APIEndpoint
|
(Optional)
- ControlPlaneEndpoint represents the endpoint used to communicate with the control plane.
+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.
|
@@ -2232,7 +2237,12 @@ sigs.k8s.io/cluster-api/api/v1beta1.APIEndpoint
|
(Optional)
- ControlPlaneEndpoint represents the endpoint used to communicate with the control plane.
+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.
|
@@ -2805,7 +2815,12 @@ sigs.k8s.io/cluster-api/api/v1beta1.APIEndpoint
|
(Optional)
- ControlPlaneEndpoint represents the endpoint used to communicate with the control plane.
+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.
|
diff --git a/pkg/cloud/services/loadbalancer/loadbalancer.go b/pkg/cloud/services/loadbalancer/loadbalancer.go
index bcc413bf45..6b716e75cd 100644
--- a/pkg/cloud/services/loadbalancer/loadbalancer.go
+++ b/pkg/cloud/services/loadbalancer/loadbalancer.go
@@ -157,7 +157,7 @@ func getAPIServerVIPAddress(openStackCluster *infrav1.OpenStackCluster) (*string
return openStackCluster.Spec.APIServerFixedIP, nil
// If we are using the VIP as the control plane endpoint, use any value explicitly set on the control plane endpoint
- case pointer.BoolDeref(openStackCluster.Spec.DisableAPIServerFloatingIP, false) && openStackCluster.Spec.ControlPlaneEndpoint.IsValid():
+ case pointer.BoolDeref(openStackCluster.Spec.DisableAPIServerFloatingIP, false) && openStackCluster.Spec.ControlPlaneEndpoint != nil && openStackCluster.Spec.ControlPlaneEndpoint.IsValid():
fixedIPAddress, err := lookupHost(openStackCluster.Spec.ControlPlaneEndpoint.Host)
if err != nil {
return nil, fmt.Errorf("lookup host: %w", err)
@@ -181,7 +181,7 @@ func getAPIServerFloatingIP(openStackCluster *infrav1.OpenStackCluster) (*string
return openStackCluster.Spec.APIServerFloatingIP, nil
// An IP address is specified explicitly in the control plane endpoint
- case openStackCluster.Spec.ControlPlaneEndpoint.IsValid():
+ case openStackCluster.Spec.ControlPlaneEndpoint != nil && openStackCluster.Spec.ControlPlaneEndpoint.IsValid():
floatingIPAddress, err := lookupHost(openStackCluster.Spec.ControlPlaneEndpoint.Host)
if err != nil {
return nil, fmt.Errorf("lookup host: %w", err)
@@ -518,12 +518,18 @@ func (s *Service) ReconcileLoadBalancerMember(openStackCluster *infrav1.OpenStac
if openStackCluster.Status.APIServerLoadBalancer == nil {
return errors.New("network.APIServerLoadBalancer is not yet available in openStackCluster.Status")
}
+ if openStackCluster.Spec.ControlPlaneEndpoint == nil || !openStackCluster.Spec.ControlPlaneEndpoint.IsValid() {
+ return errors.New("ControlPlaneEndpoint is not yet set in openStackCluster.Spec")
+ }
loadBalancerName := getLoadBalancerName(clusterName)
s.scope.Logger().Info("Reconciling load balancer member", "loadBalancerName", loadBalancerName)
lbID := openStackCluster.Status.APIServerLoadBalancer.ID
- portList := []int{int(openStackCluster.Spec.ControlPlaneEndpoint.Port)}
+ var portList []int
+ if openStackCluster.Spec.ControlPlaneEndpoint != nil {
+ portList = append(portList, int(openStackCluster.Spec.ControlPlaneEndpoint.Port))
+ }
if openStackCluster.Spec.APIServerLoadBalancer != nil {
portList = append(portList, openStackCluster.Spec.APIServerLoadBalancer.AdditionalPorts...)
}
@@ -656,7 +662,10 @@ func (s *Service) DeleteLoadBalancerMember(openStackCluster *infrav1.OpenStackCl
lbID := lb.ID
- portList := []int{int(openStackCluster.Spec.ControlPlaneEndpoint.Port)}
+ var portList []int
+ if openStackCluster.Spec.ControlPlaneEndpoint != nil {
+ portList = append(portList, int(openStackCluster.Spec.ControlPlaneEndpoint.Port))
+ }
if openStackCluster.Spec.APIServerLoadBalancer != nil {
portList = append(portList, openStackCluster.Spec.APIServerLoadBalancer.AdditionalPorts...)
}
diff --git a/pkg/cloud/services/loadbalancer/loadbalancer_test.go b/pkg/cloud/services/loadbalancer/loadbalancer_test.go
index 3f43c2cdbe..cb5d26d2c0 100644
--- a/pkg/cloud/services/loadbalancer/loadbalancer_test.go
+++ b/pkg/cloud/services/loadbalancer/loadbalancer_test.go
@@ -62,7 +62,7 @@ func Test_ReconcileLoadBalancer(t *testing.T) {
Enabled: true,
},
DisableAPIServerFloatingIP: pointer.Bool(true),
- ControlPlaneEndpoint: clusterv1.APIEndpoint{
+ ControlPlaneEndpoint: &clusterv1.APIEndpoint{
Host: apiHostname,
Port: 6443,
},
@@ -211,7 +211,7 @@ func Test_getAPIServerVIPAddress(t *testing.T) {
openStackCluster: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
DisableAPIServerFloatingIP: pointer.Bool(true),
- ControlPlaneEndpoint: clusterv1.APIEndpoint{
+ ControlPlaneEndpoint: &clusterv1.APIEndpoint{
Host: apiHostname,
Port: 6443,
},
@@ -225,7 +225,7 @@ func Test_getAPIServerVIPAddress(t *testing.T) {
openStackCluster: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
DisableAPIServerFloatingIP: pointer.Bool(true),
- ControlPlaneEndpoint: clusterv1.APIEndpoint{
+ ControlPlaneEndpoint: &clusterv1.APIEndpoint{
Host: "invalid-api.test-cluster.test",
Port: 6443,
},
@@ -299,7 +299,7 @@ func Test_getAPIServerFloatingIP(t *testing.T) {
name: "API server FIP with valid control plane endpoint",
openStackCluster: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
- ControlPlaneEndpoint: clusterv1.APIEndpoint{
+ ControlPlaneEndpoint: &clusterv1.APIEndpoint{
Host: apiHostname,
Port: 6443,
},
@@ -312,7 +312,7 @@ func Test_getAPIServerFloatingIP(t *testing.T) {
name: "API server FIP with invalid control plane endpoint",
openStackCluster: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
- ControlPlaneEndpoint: clusterv1.APIEndpoint{
+ ControlPlaneEndpoint: &clusterv1.APIEndpoint{
Host: "invalid-api.test-cluster.test",
Port: 6443,
},
diff --git a/pkg/webhooks/openstackcluster_webhook.go b/pkg/webhooks/openstackcluster_webhook.go
index eb9b705492..ece642481f 100644
--- a/pkg/webhooks/openstackcluster_webhook.go
+++ b/pkg/webhooks/openstackcluster_webhook.go
@@ -24,7 +24,6 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/utils/pointer"
- clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/manager"
"sigs.k8s.io/controller-runtime/pkg/webhook"
@@ -89,10 +88,13 @@ func (*openStackClusterWebhook) ValidateUpdate(_ context.Context, oldObjRaw, new
oldObj.Spec.IdentityRef = infrav1.OpenStackIdentityReference{}
newObj.Spec.IdentityRef = infrav1.OpenStackIdentityReference{}
- // Allow change only for the first time.
- if oldObj.Spec.ControlPlaneEndpoint.Host == "" {
- oldObj.Spec.ControlPlaneEndpoint = clusterv1.APIEndpoint{}
- newObj.Spec.ControlPlaneEndpoint = clusterv1.APIEndpoint{}
+ // Allow changes to ControlPlaneEndpoint fields only if it was not
+ // previously set, or did not previously have a host.
+ if oldObj.Spec.ControlPlaneEndpoint == nil {
+ newObj.Spec.ControlPlaneEndpoint = nil
+ } else if oldObj.Spec.ControlPlaneEndpoint.Host == "" {
+ oldObj.Spec.ControlPlaneEndpoint = nil
+ newObj.Spec.ControlPlaneEndpoint = nil
}
// Allow change only for the first time.
diff --git a/test/e2e/suites/apivalidations/openstackcluster_test.go b/test/e2e/suites/apivalidations/openstackcluster_test.go
index 00fd97197b..44bc8cbc40 100644
--- a/test/e2e/suites/apivalidations/openstackcluster_test.go
+++ b/test/e2e/suites/apivalidations/openstackcluster_test.go
@@ -20,6 +20,7 @@ import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
+ clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
)
@@ -46,8 +47,10 @@ var _ = Describe("OpenStackCluster API validations", func() {
Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
By("Setting the control plane endpoint")
- cluster.Spec.ControlPlaneEndpoint.Host = "foo"
- cluster.Spec.ControlPlaneEndpoint.Port = 1234
+ cluster.Spec.ControlPlaneEndpoint = &clusterv1.APIEndpoint{
+ Host: "foo",
+ Port: 1234,
+ }
Expect(k8sClient.Update(ctx, cluster)).To(Succeed(), "Setting control plane endpoint should succeed")
By("Modifying the control plane endpoint")
From e6a194b61ab5d5ea9071cd4bf599766c51fe709c Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Wed, 6 Mar 2024 16:47:29 +0000
Subject: [PATCH 119/180] OpenStackCluster: improve doctext
---
api/v1beta1/openstackcluster_types.go | 20 ++++++++-----
...re.cluster.x-k8s.io_openstackclusters.yaml | 26 +++++++++-------
...er.x-k8s.io_openstackclustertemplates.yaml | 8 +++--
docs/book/src/api/v1beta1/api.md | 30 +++++++++++--------
4 files changed, 50 insertions(+), 34 deletions(-)
diff --git a/api/v1beta1/openstackcluster_types.go b/api/v1beta1/openstackcluster_types.go
index acd110ddb5..2aeb112c85 100644
--- a/api/v1beta1/openstackcluster_types.go
+++ b/api/v1beta1/openstackcluster_types.go
@@ -152,7 +152,7 @@ type OpenStackClusterSpec struct {
// +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"`
@@ -166,7 +166,8 @@ type OpenStackClusterSpec struct {
// +optional
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"`
@@ -203,7 +204,7 @@ type OpenStackClusterStatus struct {
// +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"`
@@ -218,20 +219,23 @@ type OpenStackClusterStatus struct {
// 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 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 contains the information about the OpenStack
+ // Security Group that needs to be applied to worker nodes.
// +optional
WorkerSecurityGroup *SecurityGroupStatus `json:"workerSecurityGroup,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"`
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 526fe25900..ff569270af 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -5529,8 +5529,9 @@ spec:
type: object
type: object
controlPlaneAvailabilityZones:
- description: ControlPlaneAvailabilityZones is the az to deploy control
- plane to
+ description: |-
+ ControlPlaneAvailabilityZones is the set of availability zones which
+ control plane machines may be deployed to.
items:
type: string
type: array
@@ -6142,7 +6143,8 @@ spec:
type: array
x-kubernetes-list-type: atomic
tags:
- description: Tags for all resources in cluster
+ description: Tags to set on all resources in cluster which support
+ tags
items:
type: string
type: array
@@ -6180,6 +6182,8 @@ spec:
- name
type: object
bastion:
+ description: Bastion contains the information about the deployed bastion
+ host
properties:
dependentResources:
properties:
@@ -6593,8 +6597,8 @@ spec:
type: object
bastionSecurityGroup:
description: |-
- SecurityGroupStatus represents the basic information of the associated
- OpenStack Neutron Security Group.
+ 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
@@ -6660,9 +6664,9 @@ spec:
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?
+ 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
@@ -6727,7 +6731,7 @@ spec:
- name
type: object
externalNetwork:
- description: externalNetwork contains information about the external
+ description: ExternalNetwork contains information about the external
network used for default ingress and egress traffic.
properties:
id:
@@ -6868,8 +6872,8 @@ spec:
type: object
workerSecurityGroup:
description: |-
- WorkerSecurityGroup contains all the information about the OpenStack Security
- Group that needs to be applied to worker nodes.
+ 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
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 089e5bd9d4..cefd394be1 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -2961,8 +2961,9 @@ spec:
type: object
type: object
controlPlaneAvailabilityZones:
- description: ControlPlaneAvailabilityZones is the az to deploy
- control plane to
+ description: |-
+ ControlPlaneAvailabilityZones is the set of availability zones which
+ control plane machines may be deployed to.
items:
type: string
type: array
@@ -3576,7 +3577,8 @@ spec:
type: array
x-kubernetes-list-type: atomic
tags:
- description: Tags for all resources in cluster
+ description: Tags to set on all resources in cluster which
+ support tags
items:
type: string
type: array
diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md
index 8a1bad996d..7995b52c2a 100644
--- a/docs/book/src/api/v1beta1/api.md
+++ b/docs/book/src/api/v1beta1/api.md
@@ -324,7 +324,7 @@ Kubernetes cluster, which also disables SecurityGroups
|
(Optional)
- Tags for all resources in cluster
+Tags to set on all resources in cluster which support tags
|
@@ -355,7 +355,8 @@ ControlPlaneEndpoint cannot be modified after ControlPlaneEndpoint.Host has been
|
(Optional)
- ControlPlaneAvailabilityZones is the az to deploy control plane to
+ControlPlaneAvailabilityZones is the set of availability zones which
+control plane machines may be deployed to.
|
@@ -2223,7 +2224,7 @@ Kubernetes cluster, which also disables SecurityGroups
|
(Optional)
- Tags for all resources in cluster
+Tags to set on all resources in cluster which support tags
|
@@ -2254,7 +2255,8 @@ ControlPlaneEndpoint cannot be modified after ControlPlaneEndpoint.Host has been
|
(Optional)
- ControlPlaneAvailabilityZones is the az to deploy control plane to
+ControlPlaneAvailabilityZones is the set of availability zones which
+control plane machines may be deployed to.
|
@@ -2359,7 +2361,7 @@ NetworkStatus
|
(Optional)
- 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.
|
@@ -2414,9 +2416,9 @@ SecurityGroupStatus
|
(Optional)
- 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 contains the information about the
+OpenStack Security Group that needs to be applied to control plane
+nodes.
|
@@ -2430,8 +2432,8 @@ SecurityGroupStatus
|
(Optional)
- WorkerSecurityGroup contains all the information about the OpenStack Security
-Group that needs to be applied to worker nodes.
+WorkerSecurityGroup contains the information about the OpenStack
+Security Group that needs to be applied to worker nodes.
|
@@ -2445,6 +2447,8 @@ SecurityGroupStatus
|
(Optional)
+ BastionSecurityGroup contains the information about the OpenStack
+Security Group that needs to be applied to worker nodes.
|
@@ -2458,6 +2462,7 @@ BastionStatus
|
(Optional)
+ Bastion contains the information about the deployed bastion host
|
@@ -2801,7 +2806,7 @@ Kubernetes cluster, which also disables SecurityGroups
|
(Optional)
- Tags for all resources in cluster
+Tags to set on all resources in cluster which support tags
|
@@ -2832,7 +2837,8 @@ ControlPlaneEndpoint cannot be modified after ControlPlaneEndpoint.Host has been
|
(Optional)
- ControlPlaneAvailabilityZones is the az to deploy control plane to
+ControlPlaneAvailabilityZones is the set of availability zones which
+control plane machines may be deployed to.
|
From 44d4732ba98f835e34f6620644395f949af64dd5 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Mon, 11 Mar 2024 20:45:05 +0000
Subject: [PATCH 120/180] Move misplaced sections in v1alpha7 to v1beta changes
doc
---
.../topics/crd-changes/v1alpha7-to-v1beta1.md | 70 +++++++++----------
1 file changed, 35 insertions(+), 35 deletions(-)
diff --git a/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md b/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
index 7c7484f573..e21e5f0c03 100644
--- a/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
+++ b/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
@@ -11,13 +11,13 @@
- [`OpenStackMachine`](#openstackmachine)
- [Removal of cloudName](#removal-of-cloudname)
- [Change to serverGroupID](#change-to-servergroupid)
+ - [Change to image](#change-to-image)
+ - [Removal of imageUUID](#removal-of-imageuuid)
- [Changes to ports](#changes-to-ports)
- [`OpenStackCluster`](#openstackcluster)
- [Removal of cloudName](#removal-of-cloudname-1)
- [identityRef is now required](#identityref-is-now-required)
- [Change to externalNetworkID](#change-to-externalnetworkid)
- - [Change to image](#change-to-image)
- - [Removal of imageUUID](#removal-of-imageuuid)
- [Change to floatingIP](#change-to-floatingip)
- [Change to subnet](#change-to-subnet)
- [Change to nodeCidr and dnsNameservers](#change-to-nodecidr-and-dnsnameservers)
@@ -87,6 +87,39 @@ serverGroup:
If a server group is provided and found, it'll be added to `OpenStackMachine.Status.ReferencedResources.ServerGroupID`. If the server group can't be found or filter matches multiple server groups, an error will be returned.
If empty object or null is provided, Machine will not be added to any server group and `OpenStackMachine.Status.ReferencedResources.ServerGroupID` will be empty.
+#### Change to image
+
+The field `image` is now an `ImageFilter` object rather than a string name.
+The `ImageFilter` object allows selection of an image by name, by ID or by tags.
+
+```yaml
+image: "test-image"
+```
+
+becomes
+
+```yaml
+image:
+ name: "test-image"
+```
+
+The image ID will be added to `OpenStackMachine.Status.ReferencedResources.ImageID`. If the image can't be found or filter matches multiple images, an error will be returned.
+
+#### Removal of imageUUID
+
+The fild `imageUUID` has been removed in favor of the `image` field.
+
+```yaml
+imageUUID: "72a6a1e6-3e0a-4a8b-9b4c-2d6f9e3e5f0a"
+```
+
+becomes
+
+```yaml
+image:
+ id: "72a6a1e6-3e0a-4a8b-9b4c-2d6f9e3e5f0a"
+```
+
#### Changes to ports
These changes apply to ports specified in both OpenStackMachines and the Bastion.
@@ -150,39 +183,6 @@ It is now possible for a user to specify that no external network should be used
disableExternalNetwork: true
```
-#### Change to image
-
-The field `image` is now an `ImageFilter` object rather than a string name.
-The `ImageFilter` object allows selection of an image by name, by ID or by tags.
-
-```yaml
-image: "test-image"
-```
-
-becomes
-
-```yaml
-image:
- name: "test-image"
-```
-
-The image ID will be added to `OpenStackMachine.Status.ReferencedResources.ImageID`. If the image can't be found or filter matches multiple images, an error will be returned.
-
-#### Removal of imageUUID
-
-The fild `imageUUID` has been removed in favor of the `image` field.
-
-```yaml
-imageUUID: "72a6a1e6-3e0a-4a8b-9b4c-2d6f9e3e5f0a"
-```
-
-becomes
-
-```yaml
-image:
- id: "72a6a1e6-3e0a-4a8b-9b4c-2d6f9e3e5f0a"
-```
-
#### Change to floatingIP
The `OpenStackMachineSpec.FloatingIP` field has moved to `OpenStackClusterSpec.Bastion.FloatingIP`.
From 470d30bff0080d53b6218e07de3a858f52a82649 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Mon, 11 Mar 2024 20:38:20 +0000
Subject: [PATCH 121/180] Cleanup APILoadBalancer
Enabled now defaults to true. Provider becomes optional.String.
---
api/v1alpha5/zz_generated.conversion.go | 15 ++++++---
api/v1alpha6/openstackcluster_conversion.go | 6 ++++
api/v1alpha6/zz_generated.conversion.go | 23 +++++++++----
api/v1alpha7/openstackcluster_conversion.go | 6 ++++
api/v1alpha7/zz_generated.conversion.go | 16 ++++++---
api/v1beta1/openstackcluster_types.go | 2 +-
api/v1beta1/types.go | 33 +++++++++++++++----
api/v1beta1/zz_generated.deepcopy.go | 10 ++++++
...re.cluster.x-k8s.io_openstackclusters.yaml | 22 ++++++++++---
...er.x-k8s.io_openstackclustertemplates.yaml | 22 ++++++++++---
controllers/openstackcluster_controller.go | 4 +--
docs/book/src/api/v1beta1/api.md | 19 ++++++++---
.../topics/crd-changes/v1alpha7-to-v1beta1.md | 18 ++++++++++
.../services/loadbalancer/loadbalancer.go | 4 +--
.../loadbalancer/loadbalancer_test.go | 2 +-
.../services/networking/securitygroups.go | 2 +-
pkg/webhooks/openstackcluster_webhook_test.go | 4 +--
.../apivalidations/openstackcluster_test.go | 24 ++++++++++++++
18 files changed, 188 insertions(+), 44 deletions(-)
diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go
index 3b4f8e916c..44dbc571e2 100644
--- a/api/v1alpha5/zz_generated.conversion.go
+++ b/api/v1alpha5/zz_generated.conversion.go
@@ -24,7 +24,8 @@ 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"
v1alpha6 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha6"
@@ -405,7 +406,9 @@ func RegisterConversions(s *runtime.Scheme) error {
}
func autoConvert_v1alpha5_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer(in *APIServerLoadBalancer, out *v1beta1.APIServerLoadBalancer, s conversion.Scope) error {
- out.Enabled = in.Enabled
+ 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
@@ -417,7 +420,9 @@ func Convert_v1alpha5_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer(in
}
func autoConvert_v1beta1_APIServerLoadBalancer_To_v1alpha5_APIServerLoadBalancer(in *v1beta1.APIServerLoadBalancer, out *APIServerLoadBalancer, s conversion.Scope) error {
- out.Enabled = in.Enabled
+ 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
@@ -1189,7 +1194,7 @@ func autoConvert_v1beta1_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(i
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.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))
@@ -1204,7 +1209,7 @@ func Convert_v1alpha5_OpenStackMachineStatus_To_v1beta1_OpenStackMachineStatus(i
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))
+ out.Addresses = *(*[]corev1.NodeAddress)(unsafe.Pointer(&in.Addresses))
out.InstanceState = (*InstanceState)(unsafe.Pointer(in.InstanceState))
// WARNING: in.ReferencedResources requires manual conversion: does not exist in peer-type
// WARNING: in.DependentResources requires manual conversion: does not exist in peer-type
diff --git a/api/v1alpha6/openstackcluster_conversion.go b/api/v1alpha6/openstackcluster_conversion.go
index b1ecec275e..cb295c3147 100644
--- a/api/v1alpha6/openstackcluster_conversion.go
+++ b/api/v1alpha6/openstackcluster_conversion.go
@@ -198,6 +198,12 @@ func restorev1beta1ClusterSpec(previous *infrav1.OpenStackClusterSpec, dst *infr
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 dst.APIServerLoadBalancer.IsZero() {
dst.APIServerLoadBalancer = previous.APIServerLoadBalancer
}
diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go
index b0ea770cdd..e3d5251fae 100644
--- a/api/v1alpha6/zz_generated.conversion.go
+++ b/api/v1alpha6/zz_generated.conversion.go
@@ -24,7 +24,8 @@ 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"
v1beta1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
@@ -419,10 +420,14 @@ func RegisterConversions(s *runtime.Scheme) error {
}
func autoConvert_v1alpha6_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer(in *APIServerLoadBalancer, out *v1beta1.APIServerLoadBalancer, s conversion.Scope) error {
- out.Enabled = in.Enabled
+ 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
}
@@ -432,10 +437,14 @@ func Convert_v1alpha6_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer(in
}
func autoConvert_v1beta1_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalancer(in *v1beta1.APIServerLoadBalancer, out *APIServerLoadBalancer, s conversion.Scope) error {
- out.Enabled = in.Enabled
+ 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
+ }
return nil
}
@@ -1220,7 +1229,7 @@ func autoConvert_v1beta1_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(i
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.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))
@@ -1235,7 +1244,7 @@ func Convert_v1alpha6_OpenStackMachineStatus_To_v1beta1_OpenStackMachineStatus(i
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))
+ out.Addresses = *(*[]corev1.NodeAddress)(unsafe.Pointer(&in.Addresses))
out.InstanceState = (*InstanceState)(unsafe.Pointer(in.InstanceState))
// WARNING: in.ReferencedResources requires manual conversion: does not exist in peer-type
// WARNING: in.DependentResources requires manual conversion: does not exist in peer-type
diff --git a/api/v1alpha7/openstackcluster_conversion.go b/api/v1alpha7/openstackcluster_conversion.go
index c8b5e29507..f36ab2cf33 100644
--- a/api/v1alpha7/openstackcluster_conversion.go
+++ b/api/v1alpha7/openstackcluster_conversion.go
@@ -200,6 +200,12 @@ func restorev1beta1ClusterSpec(previous *infrav1.OpenStackClusterSpec, dst *infr
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 dst.APIServerLoadBalancer.IsZero() {
dst.APIServerLoadBalancer = previous.APIServerLoadBalancer
}
diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go
index 3ce6bde5ca..5f364226bb 100644
--- a/api/v1alpha7/zz_generated.conversion.go
+++ b/api/v1alpha7/zz_generated.conversion.go
@@ -445,10 +445,14 @@ func RegisterConversions(s *runtime.Scheme) error {
}
func autoConvert_v1alpha7_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer(in *APIServerLoadBalancer, out *v1beta1.APIServerLoadBalancer, s conversion.Scope) error {
- out.Enabled = in.Enabled
+ 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
}
@@ -458,10 +462,14 @@ func Convert_v1alpha7_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer(in
}
func autoConvert_v1beta1_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer(in *v1beta1.APIServerLoadBalancer, out *APIServerLoadBalancer, s conversion.Scope) error {
- out.Enabled = in.Enabled
+ 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
+ }
return nil
}
diff --git a/api/v1beta1/openstackcluster_types.go b/api/v1beta1/openstackcluster_types.go
index 2aeb112c85..06d23de650 100644
--- a/api/v1beta1/openstackcluster_types.go
+++ b/api/v1beta1/openstackcluster_types.go
@@ -95,7 +95,7 @@ type OpenStackClusterSpec struct {
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"`
diff --git a/api/v1beta1/types.go b/api/v1beta1/types.go
index b242a9585d..6b643b2f46 100644
--- a/api/v1beta1/types.go
+++ b/api/v1beta1/types.go
@@ -17,6 +17,8 @@ limitations under the License.
package v1beta1
import (
+ "k8s.io/utils/pointer"
+
"sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/optional"
)
@@ -605,22 +607,41 @@ type Bastion struct {
}
type APIServerLoadBalancer struct {
- // Enabled defines whether a load balancer should be created.
- Enabled bool `json:"enabled,omitempty"`
+ // 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"`
- // Octavia Provider Used to create load balancer
- Provider string `json:"provider,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"`
}
func (s *APIServerLoadBalancer) IsZero() bool {
- return s == nil || (!s.Enabled && len(s.AdditionalPorts) == 0 && len(s.AllowedCIDRs) == 0 && s.Provider == "")
+ return s == nil || ((s.Enabled == nil || !*s.Enabled) && len(s.AdditionalPorts) == 0 && len(s.AllowedCIDRs) == 0 && pointer.StringDeref(s.Provider, "") == "")
}
func (s *APIServerLoadBalancer) IsEnabled() bool {
- return s != nil && s.Enabled
+ // 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)
}
// ReferencedMachineResources contains resolved references to resources required by the machine.
diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go
index 3e41b4104d..aa1a30e5eb 100644
--- a/api/v1beta1/zz_generated.deepcopy.go
+++ b/api/v1beta1/zz_generated.deepcopy.go
@@ -30,6 +30,11 @@ import (
// 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,11 @@ 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
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIServerLoadBalancer.
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 ff569270af..db67158b60 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -4866,7 +4866,7 @@ spec:
apiServerLoadBalancer:
description: |-
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.
properties:
additionalPorts:
description: AdditionalPorts adds additional tcp ports to the
@@ -4874,19 +4874,33 @@ spec:
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
enabled:
- description: Enabled defines whether a load balancer should be
- created.
+ 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
provider:
- description: Octavia Provider Used to create load balancer
+ 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
+ required:
+ - enabled
type: object
apiServerPort:
description: |-
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 cefd394be1..5dc38e4098 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -2290,7 +2290,7 @@ spec:
apiServerLoadBalancer:
description: |-
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.
properties:
additionalPorts:
description: AdditionalPorts adds additional tcp ports
@@ -2298,19 +2298,33 @@ spec:
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
enabled:
- description: Enabled defines whether a load balancer should
- be created.
+ 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
provider:
- description: Octavia Provider Used to create load balancer
+ 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
+ required:
+ - enabled
type: object
apiServerPort:
description: |-
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index 0ce97f12d5..794047ca47 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -184,7 +184,7 @@ func (r *OpenStackClusterReconciler) reconcileDelete(ctx context.Context, scope
clusterName := fmt.Sprintf("%s-%s", cluster.Namespace, cluster.Name)
- if openStackCluster.Spec.APIServerLoadBalancer != nil && openStackCluster.Spec.APIServerLoadBalancer.Enabled {
+ if openStackCluster.Spec.APIServerLoadBalancer.IsEnabled() {
loadBalancerService, err := loadbalancer.NewService(scope)
if err != nil {
return reconcile.Result{}, err
@@ -722,7 +722,7 @@ func reconcileControlPlaneEndpoint(scope *scope.WithLogger, networkingService *n
// 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 != nil && openStackCluster.Spec.APIServerLoadBalancer.Enabled:
+ case openStackCluster.Spec.APIServerLoadBalancer.IsEnabled():
loadBalancerService, err := loadbalancer.NewService(scope)
if err != nil {
return err
diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md
index 7995b52c2a..38003ddb7b 100644
--- a/docs/book/src/api/v1beta1/api.md
+++ b/docs/book/src/api/v1beta1/api.md
@@ -209,7 +209,7 @@ APIServerLoadBalancer
|
(Optional)
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.
|
@@ -852,7 +852,11 @@ bool
|
- Enabled defines whether a load balancer should be created.
+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.
|
@@ -863,6 +867,7 @@ bool
|
+(Optional)
AdditionalPorts adds additional tcp ports to the load balancer.
|
@@ -874,6 +879,7 @@ bool
+(Optional)
AllowedCIDRs restrict access to all API-Server listeners to the given address CIDRs.
|
@@ -885,7 +891,10 @@ string
- Octavia Provider Used to create load balancer
+(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.
|
@@ -2109,7 +2118,7 @@ APIServerLoadBalancer
(Optional)
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.
|
@@ -2691,7 +2700,7 @@ APIServerLoadBalancer
|
(Optional)
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.
|
diff --git a/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md b/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
index e21e5f0c03..7c98118078 100644
--- a/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
+++ b/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
@@ -26,6 +26,7 @@
- [Calico CNI](#calico-cni)
- [Change to network](#change-to-network)
- [Change to networkMtu](#change-to-networkmtu)
+ - [Changes to apiServerLoadBalancer](#changes-to-apiserverloadbalancer)
- [Changes to filters](#changes-to-filters)
- [Changes to filter tags](#changes-to-filter-tags)
- [Field capitalization consistency](#field-capitalization-consistency)
@@ -326,6 +327,23 @@ In v1beta1, when the `OpenStackCluster.Spec.Network` is not defined, the `Subnet
In v1beta1, `OpenStackCluster.spec.NetworkMtu` becomes `OpenStackCluster.spec.NetworkMTU` in order to keep the name consistent with K8s API conventions.
+#### Changes to apiServerLoadBalancer
+
+In v1beta1, `OpenStackCluster.spec.apiServerLoadBalancer` becomes optional and can be entirely omitted. Therefore `enabled` can be assumed by the presence of the field. Consequently `enabled` now defaults to `true` if `apiServerLoadBalancer` is specified. The following are now equivalent:
+
+```yaml
+spec:
+ ...
+ apiServerLoadBalancer:
+ enabled: true
+```
+
+```yaml
+spec:
+ ...
+ apiServerLoadBalancer: {}
+```
+
### Changes to filters
#### Changes to filter tags
diff --git a/pkg/cloud/services/loadbalancer/loadbalancer.go b/pkg/cloud/services/loadbalancer/loadbalancer.go
index 6b716e75cd..993a1dfb22 100644
--- a/pkg/cloud/services/loadbalancer/loadbalancer.go
+++ b/pkg/cloud/services/loadbalancer/loadbalancer.go
@@ -281,9 +281,9 @@ func (s *Service) getOrCreateAPILoadBalancer(openStackCluster *infrav1.OpenStack
// Choose the selected provider if it is set in cluster spec, if not, omit the field and Octavia will use the default provider.
lbProvider := ""
- if openStackCluster.Spec.APIServerLoadBalancer != nil && openStackCluster.Spec.APIServerLoadBalancer.Provider != "" {
+ if openStackCluster.Spec.APIServerLoadBalancer != nil && openStackCluster.Spec.APIServerLoadBalancer.Provider != nil {
for _, v := range providers {
- if v.Name == openStackCluster.Spec.APIServerLoadBalancer.Provider {
+ if v.Name == *openStackCluster.Spec.APIServerLoadBalancer.Provider {
lbProvider = v.Name
break
}
diff --git a/pkg/cloud/services/loadbalancer/loadbalancer_test.go b/pkg/cloud/services/loadbalancer/loadbalancer_test.go
index cb5d26d2c0..ce46235d82 100644
--- a/pkg/cloud/services/loadbalancer/loadbalancer_test.go
+++ b/pkg/cloud/services/loadbalancer/loadbalancer_test.go
@@ -59,7 +59,7 @@ func Test_ReconcileLoadBalancer(t *testing.T) {
openStackCluster := &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
APIServerLoadBalancer: &infrav1.APIServerLoadBalancer{
- Enabled: true,
+ Enabled: pointer.Bool(true),
},
DisableAPIServerFloatingIP: pointer.Bool(true),
ControlPlaneEndpoint: &clusterv1.APIEndpoint{
diff --git a/pkg/cloud/services/networking/securitygroups.go b/pkg/cloud/services/networking/securitygroups.go
index d1fd89d847..0b67e5fd92 100644
--- a/pkg/cloud/services/networking/securitygroups.go
+++ b/pkg/cloud/services/networking/securitygroups.go
@@ -165,7 +165,7 @@ func (s *Service) generateDesiredSecGroups(openStackCluster *infrav1.OpenStackCl
workerRules = append(workerRules, getSGWorkerNodePort()...)
// If we set additional ports to LB, we need create secgroup rules those ports, this apply to controlPlaneRules only
- if openStackCluster.Spec.APIServerLoadBalancer != nil && openStackCluster.Spec.APIServerLoadBalancer.Enabled {
+ if openStackCluster.Spec.APIServerLoadBalancer.IsEnabled() {
controlPlaneRules = append(controlPlaneRules, getSGControlPlaneAdditionalPorts(openStackCluster.Spec.APIServerLoadBalancer.AdditionalPorts)...)
}
diff --git a/pkg/webhooks/openstackcluster_webhook_test.go b/pkg/webhooks/openstackcluster_webhook_test.go
index 8c9ed564ae..1d2a4cd6ad 100644
--- a/pkg/webhooks/openstackcluster_webhook_test.go
+++ b/pkg/webhooks/openstackcluster_webhook_test.go
@@ -167,7 +167,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
CloudName: "foobar",
},
APIServerLoadBalancer: &infrav1.APIServerLoadBalancer{
- Enabled: true,
+ Enabled: pointer.Bool(true),
AllowedCIDRs: []string{
"0.0.0.0/0",
"192.168.10.0/24",
@@ -182,7 +182,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
CloudName: "foobar",
},
APIServerLoadBalancer: &infrav1.APIServerLoadBalancer{
- Enabled: true,
+ Enabled: pointer.Bool(true),
AllowedCIDRs: []string{
"0.0.0.0/0",
"192.168.10.0/24",
diff --git a/test/e2e/suites/apivalidations/openstackcluster_test.go b/test/e2e/suites/apivalidations/openstackcluster_test.go
index 44bc8cbc40..ad1c0d502c 100644
--- a/test/e2e/suites/apivalidations/openstackcluster_test.go
+++ b/test/e2e/suites/apivalidations/openstackcluster_test.go
@@ -20,6 +20,7 @@ import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
+ "k8s.io/apimachinery/pkg/types"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
@@ -62,4 +63,27 @@ var _ = Describe("OpenStackCluster API validations", func() {
cluster.Spec.ManagedSecurityGroups = &infrav1.ManagedSecurityGroups{}
Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
})
+
+ It("should default enabled to true if APIServerLoadBalancer is specified without enabled=true", func() {
+ cluster.Spec.APIServerLoadBalancer = &infrav1.APIServerLoadBalancer{}
+ Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
+
+ // Fetch the cluster and check the defaulting
+ fetchedCluster := &infrav1.OpenStackCluster{}
+ Expect(k8sClient.Get(ctx, types.NamespacedName{Name: cluster.Name, Namespace: cluster.Namespace}, fetchedCluster)).To(Succeed(), "OpenStackCluster fetch should succeed")
+
+ Expect(fetchedCluster.Spec.APIServerLoadBalancer.Enabled).ToNot(BeNil(), "APIServerLoadBalancer.Enabled should have been defaulted")
+ Expect(*fetchedCluster.Spec.APIServerLoadBalancer.Enabled).To(BeTrue(), "APIServerLoadBalancer.Enabled should default to true")
+ })
+
+ It("should not default APIServerLoadBalancer if it is not specifid", func() {
+ Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
+
+ // Fetch the cluster and check the defaulting
+ fetchedCluster := &infrav1.OpenStackCluster{}
+ Expect(k8sClient.Get(ctx, types.NamespacedName{Name: cluster.Name, Namespace: cluster.Namespace}, fetchedCluster)).To(Succeed(), "OpenStackCluster fetch should succeed")
+
+ Expect(fetchedCluster.Spec.APIServerLoadBalancer).To(BeNil(), "APIServerLoadBalancer should not have been defaulted")
+ Expect(fetchedCluster.Spec.APIServerLoadBalancer.IsEnabled()).To(BeFalse(), "APIServerLoadBalancer.Enabled should not have been defaulted")
+ })
})
From 4afdb808f0e04057f18b64af10c1b9e295206003 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Tue, 12 Mar 2024 11:31:10 +0000
Subject: [PATCH 122/180] Rename Ports fields in status
The json field names were unnecessarily leaking the internal name of a
struct.
---
api/v1alpha6/openstackcluster_conversion.go | 4 +--
api/v1alpha7/openstackcluster_conversion.go | 4 +--
api/v1beta1/types.go | 8 +++---
api/v1beta1/zz_generated.deepcopy.go | 8 +++---
...re.cluster.x-k8s.io_openstackclusters.yaml | 12 ++++----
...re.cluster.x-k8s.io_openstackmachines.yaml | 10 +++----
controllers/openstackcluster_controller.go | 24 ++++++++--------
.../openstackcluster_controller_test.go | 28 +++++++++----------
controllers/openstackmachine_controller.go | 18 ++++++------
docs/book/src/api/v1beta1/api.md | 8 +++---
.../services/compute/dependent_resources.go | 2 +-
.../compute/dependent_resources_test.go | 8 +++---
.../services/compute/referenced_resources.go | 4 +--
.../compute/referenced_resources_test.go | 2 +-
pkg/cloud/services/networking/port.go | 14 +++++-----
15 files changed, 77 insertions(+), 77 deletions(-)
diff --git a/api/v1alpha6/openstackcluster_conversion.go b/api/v1alpha6/openstackcluster_conversion.go
index cb295c3147..1241469587 100644
--- a/api/v1alpha6/openstackcluster_conversion.go
+++ b/api/v1alpha6/openstackcluster_conversion.go
@@ -370,8 +370,8 @@ func restorev1beta1ClusterStatus(previous *infrav1.OpenStackClusterStatus, dst *
if previous.Bastion != nil {
dst.Bastion.ReferencedResources = previous.Bastion.ReferencedResources
}
- if previous.Bastion != nil && previous.Bastion.DependentResources.PortsStatus != nil {
- dst.Bastion.DependentResources.PortsStatus = previous.Bastion.DependentResources.PortsStatus
+ if previous.Bastion != nil && previous.Bastion.DependentResources.Ports != nil {
+ dst.Bastion.DependentResources.Ports = previous.Bastion.DependentResources.Ports
}
}
diff --git a/api/v1alpha7/openstackcluster_conversion.go b/api/v1alpha7/openstackcluster_conversion.go
index f36ab2cf33..cd31d29f7f 100644
--- a/api/v1alpha7/openstackcluster_conversion.go
+++ b/api/v1alpha7/openstackcluster_conversion.go
@@ -355,8 +355,8 @@ func restorev1beta1ClusterStatus(previous *infrav1.OpenStackClusterStatus, dst *
dst.Bastion.ReferencedResources = previous.Bastion.ReferencedResources
}
- if previous.Bastion != nil && previous.Bastion.DependentResources.PortsStatus != nil {
- dst.Bastion.DependentResources.PortsStatus = previous.Bastion.DependentResources.PortsStatus
+ if previous.Bastion != nil && previous.Bastion.DependentResources.Ports != nil {
+ dst.Bastion.DependentResources.Ports = previous.Bastion.DependentResources.Ports
}
}
diff --git a/api/v1beta1/types.go b/api/v1beta1/types.go
index 6b643b2f46..4dccc85c7a 100644
--- a/api/v1beta1/types.go
+++ b/api/v1beta1/types.go
@@ -654,15 +654,15 @@ type ReferencedMachineResources struct {
// +optional
ImageID string `json:"imageID,omitempty"`
- // portsOpts is the list of ports options to create for the machine.
+ // Ports is the fully resolved list of ports to create for the machine.
// +optional
- PortsOpts []PortOpts `json:"portsOpts,omitempty"`
+ Ports []PortOpts `json:"ports,omitempty"`
}
type DependentMachineResources struct {
- // PortsStatus is the status of the ports created for the machine.
+ // Ports is the status of the ports created for the machine.
// +optional
- PortsStatus []PortStatus `json:"portsStatus,omitempty"`
+ Ports []PortStatus `json:"ports,omitempty"`
}
// ValueSpec represents a single value_spec key-value pair.
diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go
index aa1a30e5eb..abd378418e 100644
--- a/api/v1beta1/zz_generated.deepcopy.go
+++ b/api/v1beta1/zz_generated.deepcopy.go
@@ -209,8 +209,8 @@ func (in *BlockDeviceVolume) DeepCopy() *BlockDeviceVolume {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DependentMachineResources) DeepCopyInto(out *DependentMachineResources) {
*out = *in
- if in.PortsStatus != nil {
- in, out := &in.PortsStatus, &out.PortsStatus
+ if in.Ports != nil {
+ in, out := &in.Ports, &out.Ports
*out = make([]PortStatus, len(*in))
copy(*out, *in)
}
@@ -1175,8 +1175,8 @@ func (in *PortStatus) DeepCopy() *PortStatus {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ReferencedMachineResources) DeepCopyInto(out *ReferencedMachineResources) {
*out = *in
- if in.PortsOpts != nil {
- in, out := &in.PortsOpts, &out.PortsOpts
+ if in.Ports != nil {
+ in, out := &in.Ports, &out.Ports
*out = make([]PortOpts, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
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 db67158b60..2e31f55442 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -6201,9 +6201,9 @@ spec:
properties:
dependentResources:
properties:
- portsStatus:
- description: PortsStatus is the status of the ports created
- for the machine.
+ ports:
+ description: Ports is the status of the ports created for
+ the machine.
items:
properties:
id:
@@ -6230,9 +6230,9 @@ spec:
description: ImageID is the ID of the image to use for the
machine and is calculated based on ImageFilter.
type: string
- portsOpts:
- description: portsOpts is the list of ports options to create
- for the machine.
+ ports:
+ description: Ports is the fully resolved list of ports to
+ create for the machine.
items:
properties:
adminStateUp:
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 3bb1c4a4df..b47a3fe347 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
@@ -2396,9 +2396,9 @@ spec:
description: DependentResources contains resolved dependent resources
that were created by the machine.
properties:
- portsStatus:
- description: PortsStatus is the status of the ports created for
- the machine.
+ ports:
+ description: Ports is the status of the ports created for the
+ machine.
items:
properties:
id:
@@ -2449,8 +2449,8 @@ spec:
description: ImageID is the ID of the image to use for the machine
and is calculated based on ImageFilter.
type: string
- portsOpts:
- description: portsOpts is the list of ports options to create
+ ports:
+ description: Ports is the fully resolved list of ports to create
for the machine.
items:
properties:
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index 794047ca47..11e318ff31 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -293,18 +293,18 @@ func deleteBastion(scope *scope.WithLogger, cluster *clusterv1.Cluster, openStac
}
}
- if openStackCluster.Status.Bastion != nil && len(openStackCluster.Status.Bastion.DependentResources.PortsStatus) > 0 {
+ if openStackCluster.Status.Bastion != nil && len(openStackCluster.Status.Bastion.DependentResources.Ports) > 0 {
trunkSupported, err := networkingService.IsTrunkExtSupported()
if err != nil {
return err
}
- for _, port := range openStackCluster.Status.Bastion.DependentResources.PortsStatus {
+ for _, port := range openStackCluster.Status.Bastion.DependentResources.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)
}
}
- openStackCluster.Status.Bastion.DependentResources.PortsStatus = nil
+ openStackCluster.Status.Bastion.DependentResources.Ports = nil
}
scope.Logger().Info("Deleted Bastion for cluster %s", cluster.Name)
@@ -375,7 +375,7 @@ func reconcileBastion(scope *scope.WithLogger, cluster *clusterv1.Cluster, openS
// If ports options aren't in the status, we'll re-trigger the reconcile to get them
// via adopting the referenced resources.
- if len(openStackCluster.Status.Bastion.ReferencedResources.PortsOpts) == 0 {
+ if len(openStackCluster.Status.Bastion.ReferencedResources.Ports) == 0 {
return reconcile.Result{}, nil
}
@@ -409,7 +409,7 @@ func reconcileBastion(scope *scope.WithLogger, cluster *clusterv1.Cluster, openS
handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to get or create ports for bastion: %w", err))
return ctrl.Result{}, fmt.Errorf("failed to get or create ports for bastion: %w", err)
}
- bastionPortIDs := GetPortIDs(openStackCluster.Status.Bastion.DependentResources.PortsStatus)
+ bastionPortIDs := GetPortIDs(openStackCluster.Status.Bastion.DependentResources.Ports)
var instanceStatus *compute.InstanceStatus
if openStackCluster.Status.Bastion != nil && openStackCluster.Status.Bastion.ID != "" {
@@ -555,12 +555,12 @@ func getOrCreateBastionPorts(scope *scope.WithLogger, cluster *clusterv1.Cluster
openStackCluster.Status.Bastion = &infrav1.BastionStatus{}
}
- desiredPorts := openStackCluster.Status.Bastion.ReferencedResources.PortsOpts
- portsToCreate := networking.MissingPorts(openStackCluster.Status.Bastion.DependentResources.PortsStatus, desiredPorts)
+ desiredPorts := openStackCluster.Status.Bastion.ReferencedResources.Ports
+ portsToCreate := networking.MissingPorts(openStackCluster.Status.Bastion.DependentResources.Ports, desiredPorts)
// Sanity check that the number of desired ports is equal to the addition of ports to create and ports that already exist.
- if len(desiredPorts) != len(portsToCreate)+len(openStackCluster.Status.Bastion.DependentResources.PortsStatus) {
- return fmt.Errorf("length of desired ports (%d) is not equal to the length of ports to create (%d) + the length of ports that already exist (%d)", len(desiredPorts), len(portsToCreate), len(openStackCluster.Status.Bastion.DependentResources.PortsStatus))
+ if len(desiredPorts) != len(portsToCreate)+len(openStackCluster.Status.Bastion.DependentResources.Ports) {
+ return fmt.Errorf("length of desired ports (%d) is not equal to the length of ports to create (%d) + the length of ports that already exist (%d)", len(desiredPorts), len(portsToCreate), len(openStackCluster.Status.Bastion.DependentResources.Ports))
}
if len(portsToCreate) > 0 {
@@ -570,12 +570,12 @@ func getOrCreateBastionPorts(scope *scope.WithLogger, cluster *clusterv1.Cluster
return fmt.Errorf("failed to create ports for bastion %s: %w", bastionName(openStackCluster.Name), err)
}
- openStackCluster.Status.Bastion.DependentResources.PortsStatus = append(openStackCluster.Status.Bastion.DependentResources.PortsStatus, bastionPortsStatus...)
+ openStackCluster.Status.Bastion.DependentResources.Ports = append(openStackCluster.Status.Bastion.DependentResources.Ports, bastionPortsStatus...)
}
// Sanity check that the number of ports that have been put into PortsStatus is equal to the number of desired ports now that we have created them all.
- if len(openStackCluster.Status.Bastion.DependentResources.PortsStatus) != len(desiredPorts) {
- return fmt.Errorf("length of ports that already exist (%d) is not equal to the length of desired ports (%d)", len(openStackCluster.Status.Bastion.DependentResources.PortsStatus), len(desiredPorts))
+ if len(openStackCluster.Status.Bastion.DependentResources.Ports) != len(desiredPorts) {
+ return fmt.Errorf("length of ports that already exist (%d) is not equal to the length of desired ports (%d)", len(openStackCluster.Status.Bastion.DependentResources.Ports), len(desiredPorts))
}
return nil
diff --git a/controllers/openstackcluster_controller_test.go b/controllers/openstackcluster_controller_test.go
index 9688ffb968..5ab69b2d77 100644
--- a/controllers/openstackcluster_controller_test.go
+++ b/controllers/openstackcluster_controller_test.go
@@ -234,7 +234,7 @@ var _ = Describe("OpenStackCluster controller", func() {
Bastion: &infrav1.BastionStatus{
ReferencedResources: infrav1.ReferencedMachineResources{
ImageID: "imageID",
- PortsOpts: []infrav1.PortOpts{
+ Ports: []infrav1.PortOpts{
{
Network: &infrav1.NetworkFilter{
ID: "network-id",
@@ -243,7 +243,7 @@ var _ = Describe("OpenStackCluster controller", func() {
},
},
DependentResources: infrav1.DependentMachineResources{
- PortsStatus: []infrav1.PortStatus{
+ Ports: []infrav1.PortStatus{
{
ID: "portID1",
},
@@ -285,7 +285,7 @@ var _ = Describe("OpenStackCluster controller", func() {
State: "ACTIVE",
ReferencedResources: infrav1.ReferencedMachineResources{
ImageID: "imageID",
- PortsOpts: []infrav1.PortOpts{
+ Ports: []infrav1.PortOpts{
{
Network: &infrav1.NetworkFilter{
ID: "network-id",
@@ -294,7 +294,7 @@ var _ = Describe("OpenStackCluster controller", func() {
},
},
DependentResources: infrav1.DependentMachineResources{
- PortsStatus: []infrav1.PortStatus{
+ Ports: []infrav1.PortStatus{
{
ID: "portID1",
},
@@ -326,7 +326,7 @@ var _ = Describe("OpenStackCluster controller", func() {
ID: "adopted-fip-bastion-uuid",
ReferencedResources: infrav1.ReferencedMachineResources{
ImageID: "imageID",
- PortsOpts: []infrav1.PortOpts{
+ Ports: []infrav1.PortOpts{
{
Network: &infrav1.NetworkFilter{
ID: "network-id",
@@ -335,7 +335,7 @@ var _ = Describe("OpenStackCluster controller", func() {
},
},
DependentResources: infrav1.DependentMachineResources{
- PortsStatus: []infrav1.PortStatus{
+ Ports: []infrav1.PortStatus{
{
ID: "portID1",
},
@@ -370,7 +370,7 @@ var _ = Describe("OpenStackCluster controller", func() {
State: "ACTIVE",
ReferencedResources: infrav1.ReferencedMachineResources{
ImageID: "imageID",
- PortsOpts: []infrav1.PortOpts{
+ Ports: []infrav1.PortOpts{
{
Network: &infrav1.NetworkFilter{
ID: "network-id",
@@ -379,7 +379,7 @@ var _ = Describe("OpenStackCluster controller", func() {
},
},
DependentResources: infrav1.DependentMachineResources{
- PortsStatus: []infrav1.PortStatus{
+ Ports: []infrav1.PortStatus{
{
ID: "portID1",
},
@@ -411,7 +411,7 @@ var _ = Describe("OpenStackCluster controller", func() {
ID: "requeue-bastion-uuid",
ReferencedResources: infrav1.ReferencedMachineResources{
ImageID: "imageID",
- PortsOpts: []infrav1.PortOpts{
+ Ports: []infrav1.PortOpts{
{
Network: &infrav1.NetworkFilter{
ID: "network-id",
@@ -420,7 +420,7 @@ var _ = Describe("OpenStackCluster controller", func() {
},
},
DependentResources: infrav1.DependentMachineResources{
- PortsStatus: []infrav1.PortStatus{
+ Ports: []infrav1.PortStatus{
{
ID: "portID1",
},
@@ -449,7 +449,7 @@ var _ = Describe("OpenStackCluster controller", func() {
State: "BUILD",
ReferencedResources: infrav1.ReferencedMachineResources{
ImageID: "imageID",
- PortsOpts: []infrav1.PortOpts{
+ Ports: []infrav1.PortOpts{
{
Network: &infrav1.NetworkFilter{
ID: "network-id",
@@ -458,7 +458,7 @@ var _ = Describe("OpenStackCluster controller", func() {
},
},
DependentResources: infrav1.DependentMachineResources{
- PortsStatus: []infrav1.PortStatus{
+ Ports: []infrav1.PortStatus{
{
ID: "portID1",
},
@@ -532,7 +532,7 @@ var _ = Describe("OpenStackCluster controller", func() {
testCluster.Status = infrav1.OpenStackClusterStatus{
Bastion: &infrav1.BastionStatus{
DependentResources: infrav1.DependentMachineResources{
- PortsStatus: []infrav1.PortStatus{
+ Ports: []infrav1.PortStatus{
{
ID: "port-id",
},
@@ -616,7 +616,7 @@ var _ = Describe("OpenStackCluster controller", func() {
testCluster.Status = infrav1.OpenStackClusterStatus{
Bastion: &infrav1.BastionStatus{
DependentResources: infrav1.DependentMachineResources{
- PortsStatus: []infrav1.PortStatus{
+ Ports: []infrav1.PortStatus{
{
ID: "port-id",
},
diff --git a/controllers/openstackmachine_controller.go b/controllers/openstackmachine_controller.go
index 0195b007ee..4bc510cf9d 100644
--- a/controllers/openstackmachine_controller.go
+++ b/controllers/openstackmachine_controller.go
@@ -313,7 +313,7 @@ func (r *OpenStackMachineReconciler) reconcileDelete(scope *scope.WithLogger, cl
return ctrl.Result{}, err
}
- portsStatus := openStackMachine.Status.DependentResources.PortsStatus
+ portsStatus := openStackMachine.Status.DependentResources.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)
@@ -383,7 +383,7 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope
if err != nil {
return ctrl.Result{}, err
}
- portIDs := GetPortIDs(openStackMachine.Status.DependentResources.PortsStatus)
+ portIDs := GetPortIDs(openStackMachine.Status.DependentResources.Ports)
instanceStatus, err := r.getOrCreateInstance(scope.Logger(), openStackCluster, machine, openStackMachine, computeService, userData, portIDs)
if err != nil || instanceStatus == nil {
@@ -498,12 +498,12 @@ func getOrCreateMachinePorts(scope *scope.WithLogger, openStackCluster *infrav1.
var machinePortsStatus []infrav1.PortStatus
var err error
- desiredPorts := openStackMachine.Status.ReferencedResources.PortsOpts
- portsToCreate := networking.MissingPorts(openStackMachine.Status.DependentResources.PortsStatus, desiredPorts)
+ desiredPorts := openStackMachine.Status.ReferencedResources.Ports
+ portsToCreate := networking.MissingPorts(openStackMachine.Status.DependentResources.Ports, desiredPorts)
// Sanity check that the number of desired ports is equal to the addition of ports to create and ports that already exist.
- if len(desiredPorts) != len(portsToCreate)+len(openStackMachine.Status.DependentResources.PortsStatus) {
- return fmt.Errorf("length of desired ports (%d) is not equal to the length of ports to create (%d) + the length of ports that already exist (%d)", len(desiredPorts), len(portsToCreate), len(openStackMachine.Status.DependentResources.PortsStatus))
+ if len(desiredPorts) != len(portsToCreate)+len(openStackMachine.Status.DependentResources.Ports) {
+ return fmt.Errorf("length of desired ports (%d) is not equal to the length of ports to create (%d) + the length of ports that already exist (%d)", len(desiredPorts), len(portsToCreate), len(openStackMachine.Status.DependentResources.Ports))
}
if len(portsToCreate) > 0 {
@@ -513,12 +513,12 @@ func getOrCreateMachinePorts(scope *scope.WithLogger, openStackCluster *infrav1.
if err != nil {
return fmt.Errorf("create ports: %w", err)
}
- openStackMachine.Status.DependentResources.PortsStatus = append(openStackMachine.Status.DependentResources.PortsStatus, machinePortsStatus...)
+ openStackMachine.Status.DependentResources.Ports = append(openStackMachine.Status.DependentResources.Ports, machinePortsStatus...)
}
// Sanity check that the number of ports that have been put into PortsStatus is equal to the number of desired ports now that we have created them all.
- if len(openStackMachine.Status.DependentResources.PortsStatus) != len(desiredPorts) {
- return fmt.Errorf("length of ports that already exist (%d) is not equal to the length of desired ports (%d)", len(openStackMachine.Status.DependentResources.PortsStatus), len(desiredPorts))
+ if len(openStackMachine.Status.DependentResources.Ports) != len(desiredPorts) {
+ return fmt.Errorf("length of ports that already exist (%d) is not equal to the length of desired ports (%d)", len(openStackMachine.Status.DependentResources.Ports), len(desiredPorts))
}
return nil
diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md
index 38003ddb7b..ce660d5e0d 100644
--- a/docs/book/src/api/v1beta1/api.md
+++ b/docs/book/src/api/v1beta1/api.md
@@ -1396,7 +1396,7 @@ further information.
-portsStatus
+ports
[]PortStatus
@@ -1405,7 +1405,7 @@ further information.
|
(Optional)
- PortsStatus is the status of the ports created for the machine.
+Ports is the status of the ports created for the machine.
|
@@ -3895,7 +3895,7 @@ string
-portsOpts
+ports
[]PortOpts
@@ -3904,7 +3904,7 @@ string
|
(Optional)
- portsOpts is the list of ports options to create for the machine.
+Ports is the fully resolved list of ports to create for the machine.
|
diff --git a/pkg/cloud/services/compute/dependent_resources.go b/pkg/cloud/services/compute/dependent_resources.go
index ab8bf67547..7a7d4e5b65 100644
--- a/pkg/cloud/services/compute/dependent_resources.go
+++ b/pkg/cloud/services/compute/dependent_resources.go
@@ -30,7 +30,7 @@ func ResolveDependentMachineResources(scope *scope.WithLogger, openStackMachine
return changed, err
}
- return networkingService.AdoptMachinePorts(scope, openStackMachine, openStackMachine.Status.ReferencedResources.PortsOpts)
+ return networkingService.AdoptMachinePorts(scope, openStackMachine, openStackMachine.Status.ReferencedResources.Ports)
}
func ResolveDependentBastionResources(scope *scope.WithLogger, openStackCluster *infrav1.OpenStackCluster, bastionName string) (changed bool, err error) {
diff --git a/pkg/cloud/services/compute/dependent_resources_test.go b/pkg/cloud/services/compute/dependent_resources_test.go
index e1e91f27f3..e25caba053 100644
--- a/pkg/cloud/services/compute/dependent_resources_test.go
+++ b/pkg/cloud/services/compute/dependent_resources_test.go
@@ -73,7 +73,7 @@ func Test_ResolveDependentMachineResources(t *testing.T) {
},
openStackMachineStatus: infrav1.OpenStackMachineStatus{
DependentResources: infrav1.DependentMachineResources{
- PortsStatus: []infrav1.PortStatus{
+ Ports: []infrav1.PortStatus{
{
ID: portID,
},
@@ -81,7 +81,7 @@ func Test_ResolveDependentMachineResources(t *testing.T) {
},
},
want: &infrav1.DependentMachineResources{
- PortsStatus: []infrav1.PortStatus{
+ Ports: []infrav1.PortStatus{
{
ID: portID,
},
@@ -167,7 +167,7 @@ func TestResolveDependentBastionResources(t *testing.T) {
Status: infrav1.OpenStackClusterStatus{
Bastion: &infrav1.BastionStatus{
DependentResources: infrav1.DependentMachineResources{
- PortsStatus: []infrav1.PortStatus{
+ Ports: []infrav1.PortStatus{
{
ID: portID,
},
@@ -182,7 +182,7 @@ func TestResolveDependentBastionResources(t *testing.T) {
},
},
want: &infrav1.DependentMachineResources{
- PortsStatus: []infrav1.PortStatus{
+ Ports: []infrav1.PortStatus{
{
ID: portID,
},
diff --git a/pkg/cloud/services/compute/referenced_resources.go b/pkg/cloud/services/compute/referenced_resources.go
index 657a14f93a..8fad1bf36b 100644
--- a/pkg/cloud/services/compute/referenced_resources.go
+++ b/pkg/cloud/services/compute/referenced_resources.go
@@ -62,7 +62,7 @@ func ResolveReferencedMachineResources(scope *scope.WithLogger, openStackCluster
}
// Network resources are required in order to get ports options.
- if len(resources.PortsOpts) == 0 && openStackCluster.Status.Network != nil {
+ if len(resources.Ports) == 0 && openStackCluster.Status.Network != nil {
// For now we put this here but realistically an OpenStack administrator could enable/disable trunk
// support at any time, so we should probably check this on every reconcile.
trunkSupported, err := networkingService.IsTrunkExtSupported()
@@ -73,7 +73,7 @@ func ResolveReferencedMachineResources(scope *scope.WithLogger, openStackCluster
if err != nil {
return changed, err
}
- resources.PortsOpts = portsOpts
+ resources.Ports = portsOpts
changed = true
}
diff --git a/pkg/cloud/services/compute/referenced_resources_test.go b/pkg/cloud/services/compute/referenced_resources_test.go
index e4107ba302..a62ce19e2f 100644
--- a/pkg/cloud/services/compute/referenced_resources_test.go
+++ b/pkg/cloud/services/compute/referenced_resources_test.go
@@ -133,7 +133,7 @@ func Test_ResolveReferencedMachineResources(t *testing.T) {
},
want: &infrav1.ReferencedMachineResources{
ImageID: imageID1,
- PortsOpts: []infrav1.PortOpts{
+ Ports: []infrav1.PortOpts{
{
Network: &infrav1.NetworkFilter{
ID: "test-network-id",
diff --git a/pkg/cloud/services/networking/port.go b/pkg/cloud/services/networking/port.go
index e651ba992c..6ca2d38e77 100644
--- a/pkg/cloud/services/networking/port.go
+++ b/pkg/cloud/services/networking/port.go
@@ -532,7 +532,7 @@ func (s *Service) AdoptMachinePorts(scope *scope.WithLogger, openStackMachine *i
// We can skip adoption if the instance is ready because OpenStackMachine is immutable once ready
// or if the ports are already in the status
- if openStackMachine.Status.Ready && len(openStackMachine.Status.DependentResources.PortsStatus) == len(desiredPorts) {
+ if openStackMachine.Status.Ready && len(openStackMachine.Status.DependentResources.Ports) == len(desiredPorts) {
scope.Logger().V(5).Info("OpenStackMachine is ready, skipping the adoption of ports")
return changed, nil
}
@@ -544,7 +544,7 @@ func (s *Service) AdoptMachinePorts(scope *scope.WithLogger, openStackMachine *i
// We can therefore stop searching for ports once we find one that doesn't exist.
for i, port := range desiredPorts {
// check if the port is in status first and if it is, skip it
- if i < len(openStackMachine.Status.DependentResources.PortsStatus) {
+ if i < len(openStackMachine.Status.DependentResources.Ports) {
scope.Logger().V(5).Info("Port already in status, skipping it", "port index", i)
continue
}
@@ -570,7 +570,7 @@ func (s *Service) AdoptMachinePorts(scope *scope.WithLogger, openStackMachine *i
// The desired port was found, so we add it to the status
scope.Logger().V(5).Info("Port found, adding it to the status", "port index", i)
- openStackMachine.Status.DependentResources.PortsStatus = append(openStackMachine.Status.DependentResources.PortsStatus, infrav1.PortStatus{ID: ports[0].ID})
+ openStackMachine.Status.DependentResources.Ports = append(openStackMachine.Status.DependentResources.Ports, infrav1.PortStatus{ID: ports[0].ID})
changed = true
}
@@ -594,10 +594,10 @@ func (s *Service) AdoptBastionPorts(scope *scope.WithLogger, openStackCluster *i
openStackCluster.Status.Bastion = &infrav1.BastionStatus{}
}
- desiredPorts := openStackCluster.Status.Bastion.ReferencedResources.PortsOpts
+ desiredPorts := openStackCluster.Status.Bastion.ReferencedResources.Ports
// We can skip adoption if the ports are already in the status
- if len(desiredPorts) == len(openStackCluster.Status.Bastion.DependentResources.PortsStatus) {
+ if len(desiredPorts) == len(openStackCluster.Status.Bastion.DependentResources.Ports) {
return changed, nil
}
@@ -608,7 +608,7 @@ func (s *Service) AdoptBastionPorts(scope *scope.WithLogger, openStackCluster *i
// We can therefore stop searching for ports once we find one that doesn't exist.
for i, port := range desiredPorts {
// check if the port is in status first and if it is, skip it
- if i < len(openStackCluster.Status.Bastion.DependentResources.PortsStatus) {
+ if i < len(openStackCluster.Status.Bastion.DependentResources.Ports) {
scope.Logger().V(5).Info("Port already in status, skipping it", "port index", i)
continue
}
@@ -634,7 +634,7 @@ func (s *Service) AdoptBastionPorts(scope *scope.WithLogger, openStackCluster *i
// The desired port was found, so we add it to the status
scope.Logger().V(5).Info("Port found, adding it to the status", "port index", i)
- openStackCluster.Status.Bastion.DependentResources.PortsStatus = append(openStackCluster.Status.Bastion.DependentResources.PortsStatus, infrav1.PortStatus{ID: ports[0].ID})
+ openStackCluster.Status.Bastion.DependentResources.Ports = append(openStackCluster.Status.Bastion.DependentResources.Ports, infrav1.PortStatus{ID: ports[0].ID})
changed = true
}
From 7dce82c232b08c05eab8db38f726862a6204cb47 Mon Sep 17 00:00:00 2001
From: bilbo
Date: Wed, 24 Jan 2024 13:15:22 +0100
Subject: [PATCH 123/180] Get floating IP for openstack machine from IPAM
provider
---
api/v1alpha5/zz_generated.conversion.go | 1 +
api/v1alpha6/openstackmachine_conversion.go | 1 +
api/v1alpha6/zz_generated.conversion.go | 1 +
api/v1alpha7/openstackmachine_conversion.go | 1 +
api/v1alpha7/zz_generated.conversion.go | 1 +
api/v1beta1/conditions_consts.go | 9 +
api/v1beta1/openstackmachine_types.go | 9 +-
api/v1beta1/zz_generated.deepcopy.go | 5 +
...re.cluster.x-k8s.io_openstackclusters.yaml | 23 +++
...er.x-k8s.io_openstackclustertemplates.yaml | 25 +++
...re.cluster.x-k8s.io_openstackmachines.yaml | 23 +++
...er.x-k8s.io_openstackmachinetemplates.yaml | 23 +++
config/rbac/role.yaml | 1 +
controllers/openstackmachine_controller.go | 190 +++++++++++++++++-
docs/book/src/api/v1beta1/api.md | 42 ++++
.../topics/crd-changes/v1alpha7-to-v1beta1.md | 18 ++
pkg/cloud/services/networking/port.go | 51 +++++
pkg/utils/names/names.go | 13 ++
18 files changed, 429 insertions(+), 8 deletions(-)
diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go
index 44dbc571e2..4d472de0be 100644
--- a/api/v1alpha5/zz_generated.conversion.go
+++ b/api/v1alpha5/zz_generated.conversion.go
@@ -1189,6 +1189,7 @@ func autoConvert_v1beta1_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(i
} else {
out.IdentityRef = nil
}
+ // WARNING: in.FloatingIPPoolRef requires manual conversion: does not exist in peer-type
return nil
}
diff --git a/api/v1alpha6/openstackmachine_conversion.go b/api/v1alpha6/openstackmachine_conversion.go
index 6720f99f90..2dcbec0f7b 100644
--- a/api/v1alpha6/openstackmachine_conversion.go
+++ b/api/v1alpha6/openstackmachine_conversion.go
@@ -161,6 +161,7 @@ func restorev1beta1MachineSpec(previous *infrav1.OpenStackMachineSpec, dst *infr
dst.AdditionalBlockDevices = previous.AdditionalBlockDevices
dst.ServerGroup = previous.ServerGroup
dst.Image = previous.Image
+ dst.FloatingIPPoolRef = previous.FloatingIPPoolRef
}
func convertNetworksToPorts(networks []NetworkParam, s apiconversion.Scope) ([]infrav1.PortOpts, error) {
diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go
index e3d5251fae..7530cc7dea 100644
--- a/api/v1alpha6/zz_generated.conversion.go
+++ b/api/v1alpha6/zz_generated.conversion.go
@@ -1224,6 +1224,7 @@ func autoConvert_v1beta1_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(i
} else {
out.IdentityRef = nil
}
+ // WARNING: in.FloatingIPPoolRef requires manual conversion: does not exist in peer-type
return nil
}
diff --git a/api/v1alpha7/openstackmachine_conversion.go b/api/v1alpha7/openstackmachine_conversion.go
index 575f8ad40b..0d21eb3617 100644
--- a/api/v1alpha7/openstackmachine_conversion.go
+++ b/api/v1alpha7/openstackmachine_conversion.go
@@ -137,6 +137,7 @@ func restorev1beta1MachineSpec(previous *infrav1.OpenStackMachineSpec, dst *infr
restorev1beta1Port(&previous.Ports[i], &dst.Ports[i])
}
}
+ dst.FloatingIPPoolRef = previous.FloatingIPPoolRef
}
func Convert_v1alpha7_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(in *OpenStackMachineSpec, out *infrav1.OpenStackMachineSpec, s apiconversion.Scope) error {
diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go
index 5f364226bb..d22715b316 100644
--- a/api/v1alpha7/zz_generated.conversion.go
+++ b/api/v1alpha7/zz_generated.conversion.go
@@ -1424,6 +1424,7 @@ func autoConvert_v1beta1_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(i
} else {
out.IdentityRef = nil
}
+ // WARNING: in.FloatingIPPoolRef requires manual conversion: does not exist in peer-type
return nil
}
diff --git a/api/v1beta1/conditions_consts.go b/api/v1beta1/conditions_consts.go
index 288251636d..df2da634ec 100644
--- a/api/v1beta1/conditions_consts.go
+++ b/api/v1beta1/conditions_consts.go
@@ -53,3 +53,12 @@ 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"
+)
diff --git a/api/v1beta1/openstackmachine_types.go b/api/v1beta1/openstackmachine_types.go
index 9e36fa9dd8..343063622d 100644
--- a/api/v1beta1/openstackmachine_types.go
+++ b/api/v1beta1/openstackmachine_types.go
@@ -27,7 +27,8 @@ import (
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.
@@ -89,6 +90,12 @@ type OpenStackMachineSpec struct {
// 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 {
diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go
index aa1a30e5eb..00e173153a 100644
--- a/api/v1beta1/zz_generated.deepcopy.go
+++ b/api/v1beta1/zz_generated.deepcopy.go
@@ -910,6 +910,11 @@ func (in *OpenStackMachineSpec) DeepCopyInto(out *OpenStackMachineSpec) {
*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.
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 db67158b60..e86bfff42e 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -4996,6 +4996,29 @@ spec:
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
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 5dc38e4098..56a34a5b19 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -2421,6 +2421,31 @@ spec:
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
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 3bb1c4a4df..ef4dd7f27f 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
@@ -1784,6 +1784,29 @@ spec:
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
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 975c907650..f42138d667 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
@@ -1457,6 +1457,29 @@ spec:
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
diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml
index 6a40632602..4790f87801 100644
--- a/config/rbac/role.yaml
+++ b/config/rbac/role.yaml
@@ -123,6 +123,7 @@ rules:
- delete
- get
- list
+ - patch
- update
- watch
- apiGroups:
diff --git a/controllers/openstackmachine_controller.go b/controllers/openstackmachine_controller.go
index 0195b007ee..5f10024af8 100644
--- a/controllers/openstackmachine_controller.go
+++ b/controllers/openstackmachine_controller.go
@@ -27,12 +27,14 @@ import (
"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"
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"
@@ -53,6 +55,7 @@ import (
"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.
@@ -73,6 +76,8 @@ const (
// +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
@@ -238,6 +243,10 @@ 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)
}
@@ -320,6 +329,10 @@ func (r *OpenStackMachineReconciler) reconcileDelete(scope *scope.WithLogger, cl
}
}
+ if err := r.reconcileDeleteFloatingAddressFromPool(scope, openStackMachine); err != nil {
+ return ctrl.Result{}, err
+ }
+
controllerutil.RemoveFinalizer(openStackMachine, infrav1.MachineFinalizer)
scope.Logger().Info("Reconciled Machine delete successfully")
return ctrl.Result{}, nil
@@ -334,6 +347,136 @@ func GetPortIDs(ports []infrav1.PortStatus) []string {
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, cluster *clusterv1.Cluster, openStackCluster *infrav1.OpenStackCluster, machine *clusterv1.Machine, openStackMachine *infrav1.OpenStackMachine) (_ ctrl.Result, reterr error) {
var err error
@@ -374,6 +517,11 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope
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
@@ -415,6 +563,14 @@ 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())
@@ -444,6 +600,7 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope
// 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
}
@@ -452,11 +609,32 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope
return ctrl.Result{}, nil
}
+ err = r.reconcileAPIServerLoadBalancer(scope, openStackCluster, openStackMachine, instanceStatus, instanceNS, clusterName)
+ 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, clusterName 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, clusterName)
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 !pointer.BoolDeref(openStackCluster.Spec.DisableAPIServerFloatingIP, false) {
var floatingIPAddress *string
@@ -469,12 +647,12 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope
fp, err := networkingService.GetOrCreateFloatingIP(openStackMachine, openStackCluster, clusterName, 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 %v: %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 != "" {
@@ -483,14 +661,12 @@ 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 getOrCreateMachinePorts(scope *scope.WithLogger, openStackCluster *infrav1.OpenStackCluster, machine *clusterv1.Machine, openStackMachine *infrav1.OpenStackMachine, networkingService *networking.Service, clusterName string) error {
diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md
index 38003ddb7b..8f1731e094 100644
--- a/docs/book/src/api/v1beta1/api.md
+++ b/docs/book/src/api/v1beta1/api.md
@@ -739,6 +739,20 @@ 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.
+ |
+
@@ -3186,6 +3200,20 @@ 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.
+ |
+
OpenStackMachineStatus
@@ -3539,6 +3567,20 @@ 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.
+ |
+
diff --git a/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md b/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
index 7c98118078..9c12188e41 100644
--- a/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
+++ b/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
@@ -14,6 +14,7 @@
- [Change to image](#change-to-image)
- [Removal of imageUUID](#removal-of-imageuuid)
- [Changes to ports](#changes-to-ports)
+ - [Additon of floatingIPPoolRef](#additon-of-floatingippoolref)
- [`OpenStackCluster`](#openstackcluster)
- [Removal of cloudName](#removal-of-cloudname-1)
- [identityRef is now required](#identityref-is-now-required)
@@ -138,6 +139,23 @@ The following fields in `PortOpts` are renamed in order to keep them consistent
* `hostId` becomes `hostID`
* `allowedCidrs` becomes `allowedCIDRs`
+#### Addition of floatingIPPoolRef
+
+A new field, FloatingIPPoolRef, has been introduced. It is important to note that this feature requires the existence of an IPPool to operate seamlessly. This new field references an IPPool whice will be used for floating IP allocation.
+In additon to this field an IPPool resource called `OpenStackFloatingIPPool` has been added. Please note that this resource is new and still in alpha meaning its more likely to contain bugs and change in the future.
+
+When creating an OpenStackFloatingIPPool resource named MyOpenStackFloatingIPPool, you can reference it within your OpenStackMachine configuration YAML as follows:
+
+```yaml
+spec:
+ template:
+ spec:
+ floatingIPPoolRef:
+ apiGroup: "infrastructure.cluster.x-k8s.io"
+ kind: "OpenStackFloatingIPPool"
+ name: "MyOpenStackFloatingIPPool"
+```
+
### `OpenStackCluster`
#### Removal of cloudName
diff --git a/pkg/cloud/services/networking/port.go b/pkg/cloud/services/networking/port.go
index e651ba992c..1f26739b91 100644
--- a/pkg/cloud/services/networking/port.go
+++ b/pkg/cloud/services/networking/port.go
@@ -58,6 +58,57 @@ func (s *Service) GetPortFromInstanceIP(instanceID string, ip string) ([]ports.P
return s.client.ListPort(portOpts)
}
+func (s *Service) GetPortForExternalNetwork(instanceID string, externalNetworkID string) (*ports.Port, error) {
+ instancePortsOpts := ports.ListOpts{
+ DeviceID: instanceID,
+ }
+ instancePorts, err := s.client.ListPort(instancePortsOpts)
+ if err != nil {
+ return nil, fmt.Errorf("lookup ports for server %s: %w", instanceID, err)
+ }
+
+ for _, instancePort := range instancePorts {
+ networkPortsOpts := ports.ListOpts{
+ NetworkID: instancePort.NetworkID,
+ DeviceOwner: "network:router_interface",
+ }
+
+ networkPorts, err := s.client.ListPort(networkPortsOpts)
+ if err != nil {
+ return nil, fmt.Errorf("lookup ports for network %s: %w", instancePort.NetworkID, err)
+ }
+
+ for _, networkPort := range networkPorts {
+ // Check if the instance port and the network port share a subnet
+ matchingSubnet := false
+ for _, fixedIP := range instancePort.FixedIPs {
+ for _, networkFixedIP := range networkPort.FixedIPs {
+ if fixedIP.SubnetID == networkFixedIP.SubnetID {
+ matchingSubnet = true
+ break
+ }
+ }
+ if matchingSubnet {
+ break
+ }
+ }
+ if !matchingSubnet {
+ continue
+ }
+
+ router, err := s.client.GetRouter(networkPort.DeviceID)
+ if err != nil {
+ return nil, fmt.Errorf("lookup router %s: %w", networkPort.DeviceID, err)
+ }
+
+ if router.GatewayInfo.NetworkID == externalNetworkID {
+ return &instancePort, nil
+ }
+ }
+ }
+ return nil, nil
+}
+
func (s *Service) CreatePort(eventObject runtime.Object, clusterName string, portName string, portOpts *infrav1.PortOpts, instanceSecurityGroups []string, instanceTags []string) (*ports.Port, error) {
var err error
networkID := portOpts.Network.ID
diff --git a/pkg/utils/names/names.go b/pkg/utils/names/names.go
index e97ccc41c5..95c1bd455c 100644
--- a/pkg/utils/names/names.go
+++ b/pkg/utils/names/names.go
@@ -18,8 +18,21 @@ package names
import (
"fmt"
+ "strings"
+)
+
+const (
+ FloatingAddressIPClaimNameSuffix = "floating-ip-address"
)
func GetDescription(clusterName string) string {
return fmt.Sprintf("Created by cluster-api-provider-openstack cluster %s", clusterName)
}
+
+func GetFloatingAddressClaimName(openStackMachineName string) string {
+ return fmt.Sprintf("%s-%s", openStackMachineName, FloatingAddressIPClaimNameSuffix)
+}
+
+func GetOpenStackMachineNameFromClaimName(claimName string) string {
+ return strings.TrimSuffix(claimName, fmt.Sprintf("-%s", FloatingAddressIPClaimNameSuffix))
+}
From a00fa808108fc7749b2f438f7334992e5320118c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20Dulko?=
Date: Tue, 12 Mar 2024 14:15:33 +0100
Subject: [PATCH 124/180] ImageFilter - add validations, switch to pointers
This commit changes `ID` and `Name` of `ImageFilter` to pointers which
should only affect go marshalling.
Other than that it adds CEL validation of the ImageFilter, so that Name
or Tags can only be set when ID is unset. Conversions are updated
accordingly to make sure we only set Name when ID is unset.
Moreover validation is added that ID has to be UUID. It's not enforced
in conversions, as non-UUID IDs would produce clusters or machines that
would not work properly.
---
api/v1alpha5/conversion.go | 15 +++++++-------
api/v1alpha6/openstackmachine_conversion.go | 20 +++++++++++--------
api/v1alpha7/openstackmachine_conversion.go | 20 +++++++++++--------
api/v1beta1/openstackmachine_types.go | 3 ++-
api/v1beta1/types.go | 13 +++++++++---
api/v1beta1/zz_generated.deepcopy.go | 10 ++++++++++
...re.cluster.x-k8s.io_openstackclusters.yaml | 12 +++++++++--
...er.x-k8s.io_openstackclustertemplates.yaml | 12 +++++++++--
...re.cluster.x-k8s.io_openstackmachines.yaml | 10 ++++++++--
...er.x-k8s.io_openstackmachinetemplates.yaml | 12 +++++++++--
.../openstackmachine_controller_test.go | 2 +-
docs/book/src/api/v1beta1/api.md | 6 +++++-
.../topics/crd-changes/v1alpha7-to-v1beta1.md | 2 +-
pkg/cloud/services/compute/instance.go | 4 ++--
pkg/cloud/services/compute/instance_test.go | 14 ++++++-------
.../compute/referenced_resources_test.go | 9 +++++----
pkg/utils/filterconvert/convert.go | 16 +++++++++------
pkg/webhooks/openstackcluster_webhook_test.go | 8 ++++----
.../openstackmachinetemplate_webhook_test.go | 16 +++++++--------
test/e2e/suites/e2e/e2e_test.go | 4 ++--
20 files changed, 136 insertions(+), 72 deletions(-)
diff --git a/api/v1alpha5/conversion.go b/api/v1alpha5/conversion.go
index cd66e62bd3..1ba726f9c8 100644
--- a/api/v1alpha5/conversion.go
+++ b/api/v1alpha5/conversion.go
@@ -358,11 +358,10 @@ func Convert_v1alpha5_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(in *O
}
imageFilter := infrav1.ImageFilter{}
- if in.Image != "" {
- imageFilter.Name = in.Image
- }
if in.ImageUUID != "" {
- imageFilter.ID = in.ImageUUID
+ imageFilter.ID = &in.ImageUUID
+ } else if in.Image != "" { // Only add name when ID is not set, in v1beta1 it's not possible to set both.
+ imageFilter.Name = &in.Image
}
out.Image = imageFilter
@@ -643,12 +642,12 @@ func Convert_v1beta1_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(in *i
out.ServerGroupID = in.ServerGroup.ID
}
- if in.Image.Name != "" {
- out.Image = in.Image.Name
+ if in.Image.Name != nil && *in.Image.Name != "" {
+ out.Image = *in.Image.Name
}
- if in.Image.ID != "" {
- out.ImageUUID = in.Image.ID
+ if in.Image.ID != nil && *in.Image.ID != "" {
+ out.ImageUUID = *in.Image.ID
}
if in.IdentityRef != nil {
diff --git a/api/v1alpha6/openstackmachine_conversion.go b/api/v1alpha6/openstackmachine_conversion.go
index 6720f99f90..108db09757 100644
--- a/api/v1alpha6/openstackmachine_conversion.go
+++ b/api/v1alpha6/openstackmachine_conversion.go
@@ -152,6 +152,11 @@ func restorev1alpha6MachineSpec(previous *OpenStackMachineSpec, dst *OpenStackMa
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) {
@@ -258,11 +263,10 @@ func Convert_v1alpha6_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(in *O
}
imageFilter := infrav1.ImageFilter{}
- if in.Image != "" {
- imageFilter.Name = in.Image
- }
if in.ImageUUID != "" {
- imageFilter.ID = in.ImageUUID
+ imageFilter.ID = &in.ImageUUID
+ } else if in.Image != "" { // Only add name when ID is not set, in v1beta1 it's not possible to set both.
+ imageFilter.Name = &in.Image
}
out.Image = imageFilter
@@ -306,12 +310,12 @@ func Convert_v1beta1_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(in *i
out.ServerGroupID = in.ServerGroup.ID
}
- if in.Image.Name != "" {
- out.Image = in.Image.Name
+ if in.Image.Name != nil && *in.Image.Name != "" {
+ out.Image = *in.Image.Name
}
- if in.Image.ID != "" {
- out.ImageUUID = in.Image.ID
+ if in.Image.ID != nil && *in.Image.ID != "" {
+ out.ImageUUID = *in.Image.ID
}
if len(in.ServerMetadata) > 0 {
diff --git a/api/v1alpha7/openstackmachine_conversion.go b/api/v1alpha7/openstackmachine_conversion.go
index 575f8ad40b..0939b1c2f6 100644
--- a/api/v1alpha7/openstackmachine_conversion.go
+++ b/api/v1alpha7/openstackmachine_conversion.go
@@ -126,6 +126,11 @@ func restorev1alpha7MachineSpec(previous *OpenStackMachineSpec, dst *OpenStackMa
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) {
@@ -152,11 +157,10 @@ func Convert_v1alpha7_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(in *O
}
imageFilter := infrav1.ImageFilter{}
- if in.Image != "" {
- imageFilter.Name = in.Image
- }
if in.ImageUUID != "" {
- imageFilter.ID = in.ImageUUID
+ imageFilter.ID = &in.ImageUUID
+ } else if in.Image != "" { // Only add name when ID is not set, in v1beta1 it's not possible to set both.
+ imageFilter.Name = &in.Image
}
out.Image = imageFilter
@@ -197,12 +201,12 @@ func Convert_v1beta1_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(in *i
out.ServerGroupID = in.ServerGroup.ID
}
- if in.Image.Name != "" {
- out.Image = in.Image.Name
+ if in.Image.Name != nil && *in.Image.Name != "" {
+ out.Image = *in.Image.Name
}
- if in.Image.ID != "" {
- out.ImageUUID = in.Image.ID
+ if in.Image.ID != nil && *in.Image.ID != "" {
+ out.ImageUUID = *in.Image.ID
}
if len(in.ServerMetadata) > 0 {
diff --git a/api/v1beta1/openstackmachine_types.go b/api/v1beta1/openstackmachine_types.go
index 9e36fa9dd8..743468399a 100644
--- a/api/v1beta1/openstackmachine_types.go
+++ b/api/v1beta1/openstackmachine_types.go
@@ -43,7 +43,8 @@ type OpenStackMachineSpec struct {
// The image to use for your server instance.
// If the rootVolume is specified, this will be used when creating the root volume.
- Image ImageFilter `json:"image,omitempty"`
+ // +required
+ Image ImageFilter `json:"image"`
// The ssh key to inject in the instance
SSHKeyName string `json:"sshKeyName,omitempty"`
diff --git a/api/v1beta1/types.go b/api/v1beta1/types.go
index 4dccc85c7a..94625b20db 100644
--- a/api/v1beta1/types.go
+++ b/api/v1beta1/types.go
@@ -28,12 +28,19 @@ type OpenStackMachineTemplateResource struct {
Spec OpenStackMachineSpec `json:"spec"`
}
+// ImageFilter describes the data needed to identify which image to use. If ID is provided it is required that all other fields are unset.
+// +kubebuilder:validation:XValidation:rule="(has(self.id) && !has(self.name) && !has(self.tags)) || !has(self.id)",message="when ID is set you cannot set other options"
type ImageFilter struct {
- // The ID of the desired image. If this is provided, the other filters will be ignored.
- ID string `json:"id,omitempty"`
+ // The ID of the desired image. 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"`
// 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.
- Name string `json:"name,omitempty"`
+ // +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"`
}
diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go
index abd378418e..2fe078f3dd 100644
--- a/api/v1beta1/zz_generated.deepcopy.go
+++ b/api/v1beta1/zz_generated.deepcopy.go
@@ -305,6 +305,16 @@ func (in *FixedIP) DeepCopy() *FixedIP {
// 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.ID != nil {
+ in, out := &in.ID, &out.ID
+ *out = new(string)
+ **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))
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 2e31f55442..50fca991d1 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -5022,8 +5022,10 @@ spec:
If the rootVolume is specified, this will be used when creating the root volume.
properties:
id:
- description: The ID of the desired image. If this is provided,
- the other filters will be ignored.
+ description: The ID of the desired image. If ID is provided,
+ the other filters cannot be provided. Must be in UUID
+ format.
+ format: uuid
type: string
name:
description: The name of the desired image. If specified,
@@ -5037,7 +5039,12 @@ spec:
items:
type: string
type: array
+ x-kubernetes-list-type: set
type: object
+ x-kubernetes-validations:
+ - message: when ID is set you cannot set other options
+ rule: (has(self.id) && !has(self.name) && !has(self.tags))
+ || !has(self.id)
instanceID:
description: InstanceID is the OpenStack instance ID for this
machine.
@@ -5540,6 +5547,7 @@ spec:
type: boolean
required:
- flavor
+ - image
type: object
type: object
controlPlaneAvailabilityZones:
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 5dc38e4098..acb1556d63 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -2447,8 +2447,10 @@ spec:
If the rootVolume is specified, this will be used when creating the root volume.
properties:
id:
- description: The ID of the desired image. If this
- is provided, the other filters will be ignored.
+ description: The ID of the desired image. If ID
+ is provided, the other filters cannot be provided.
+ Must be in UUID format.
+ format: uuid
type: string
name:
description: The name of the desired image. If
@@ -2464,7 +2466,12 @@ spec:
items:
type: string
type: array
+ x-kubernetes-list-type: set
type: object
+ x-kubernetes-validations:
+ - message: when ID is set you cannot set other options
+ rule: (has(self.id) && !has(self.name) && !has(self.tags))
+ || !has(self.id)
instanceID:
description: InstanceID is the OpenStack instance
ID for this machine.
@@ -2972,6 +2979,7 @@ spec:
type: boolean
required:
- flavor
+ - image
type: object
type: object
controlPlaneAvailabilityZones:
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 b47a3fe347..475ff16f1b 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
@@ -1810,8 +1810,9 @@ spec:
If the rootVolume is specified, this will be used when creating the root volume.
properties:
id:
- description: The ID of the desired image. If this is provided,
- the other filters will be ignored.
+ description: The ID of the desired image. If ID is provided, the
+ other filters cannot be provided. Must be in UUID format.
+ format: uuid
type: string
name:
description: The name of the desired image. If specified, the
@@ -1825,7 +1826,11 @@ spec:
items:
type: string
type: array
+ x-kubernetes-list-type: set
type: object
+ x-kubernetes-validations:
+ - message: when ID is set you cannot set other options
+ rule: (has(self.id) && !has(self.name) && !has(self.tags)) || !has(self.id)
instanceID:
description: InstanceID is the OpenStack instance ID for this machine.
type: string
@@ -2324,6 +2329,7 @@ spec:
type: boolean
required:
- flavor
+ - image
type: object
status:
description: OpenStackMachineStatus defines the observed state of OpenStackMachine.
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 975c907650..6c982124ae 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
@@ -1483,8 +1483,10 @@ spec:
If the rootVolume is specified, this will be used when creating the root volume.
properties:
id:
- description: The ID of the desired image. If this is provided,
- the other filters will be ignored.
+ description: The ID of the desired image. If ID is provided,
+ the other filters cannot be provided. Must be in UUID
+ format.
+ format: uuid
type: string
name:
description: The name of the desired image. If specified,
@@ -1498,7 +1500,12 @@ spec:
items:
type: string
type: array
+ x-kubernetes-list-type: set
type: object
+ x-kubernetes-validations:
+ - message: when ID is set you cannot set other options
+ rule: (has(self.id) && !has(self.name) && !has(self.tags))
+ || !has(self.id)
instanceID:
description: InstanceID is the OpenStack instance ID for this
machine.
@@ -2001,6 +2008,7 @@ spec:
type: boolean
required:
- flavor
+ - image
type: object
required:
- spec
diff --git a/controllers/openstackmachine_controller_test.go b/controllers/openstackmachine_controller_test.go
index a03120ce5e..648b1abc0d 100644
--- a/controllers/openstackmachine_controller_test.go
+++ b/controllers/openstackmachine_controller_test.go
@@ -83,7 +83,7 @@ func getDefaultOpenStackMachine() *infrav1.OpenStackMachine {
// FloatingIP is only used by the cluster controller for the Bastion
// TODO: Test Networks, Ports, Subnet, and Trunk separately
Flavor: flavorName,
- Image: infrav1.ImageFilter{ID: imageUUID},
+ Image: infrav1.ImageFilter{ID: pointer.String(imageUUID)},
SSHKeyName: sshKeyName,
Tags: []string{"test-tag"},
ServerMetadata: []infrav1.ServerMetadata{
diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md
index ce660d5e0d..5ac1613daf 100644
--- a/docs/book/src/api/v1beta1/api.md
+++ b/docs/book/src/api/v1beta1/api.md
@@ -1589,6 +1589,7 @@ address in any subnet of the port’s network.
OpenStackMachineSpec)
+
ImageFilter describes the data needed to identify which image to use. If ID is provided it is required that all other fields are unset.
@@ -1606,7 +1607,8 @@ string
|
- The ID of the desired image. If this is provided, the other filters will be ignored.
+(Optional)
+The ID of the desired image. If ID is provided, the other filters cannot be provided. Must be in UUID format.
|
@@ -1617,6 +1619,7 @@ 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.
|
@@ -1628,6 +1631,7 @@ 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.
|
diff --git a/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md b/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
index 7c98118078..3776822cf7 100644
--- a/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
+++ b/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
@@ -91,7 +91,7 @@ If empty object or null is provided, Machine will not be added to any server gro
#### Change to image
The field `image` is now an `ImageFilter` object rather than a string name.
-The `ImageFilter` object allows selection of an image by name, by ID or by tags.
+The `ImageFilter` object allows selection of an image by ID or by name and tags. If ID is set, no other fields can be set in the object.
```yaml
image: "test-image"
diff --git a/pkg/cloud/services/compute/instance.go b/pkg/cloud/services/compute/instance.go
index 9981ebeabb..eebfd9278d 100644
--- a/pkg/cloud/services/compute/instance.go
+++ b/pkg/cloud/services/compute/instance.go
@@ -333,8 +333,8 @@ func applyServerGroupID(opts servers.CreateOptsBuilder, serverGroupID string) se
// Helper function for getting image ID from name, ID, or tags.
func (s *Service) GetImageID(image infrav1.ImageFilter) (string, error) {
- if image.ID != "" {
- return image.ID, nil
+ if image.ID != nil {
+ return *image.ID, nil
}
listOpts := filterconvert.ImageFilterToListOpts(&image)
diff --git a/pkg/cloud/services/compute/instance_test.go b/pkg/cloud/services/compute/instance_test.go
index bc5b01def5..e715171556 100644
--- a/pkg/cloud/services/compute/instance_test.go
+++ b/pkg/cloud/services/compute/instance_test.go
@@ -41,8 +41,8 @@ import (
)
func TestService_getImageID(t *testing.T) {
- const imageID = "ce96e584-7ebc-46d6-9e55-987d72e3806c"
- const imageName = "test-image"
+ imageID := "ce96e584-7ebc-46d6-9e55-987d72e3806c"
+ imageName := "test-image"
imageTags := []string{"test-tag"}
tests := []struct {
@@ -54,14 +54,14 @@ func TestService_getImageID(t *testing.T) {
}{
{
testName: "Return image ID when ID given",
- image: infrav1.ImageFilter{ID: imageID},
+ image: infrav1.ImageFilter{ID: &imageID},
want: imageID,
expect: func(m *mock.MockImageClientMockRecorder) {},
wantErr: false,
},
{
testName: "Return image ID when name given",
- image: infrav1.ImageFilter{Name: imageName},
+ image: infrav1.ImageFilter{Name: &imageName},
want: imageID,
expect: func(m *mock.MockImageClientMockRecorder) {
m.ListImages(images.ListOpts{Name: imageName}).Return(
@@ -83,7 +83,7 @@ func TestService_getImageID(t *testing.T) {
},
{
testName: "Return no results",
- image: infrav1.ImageFilter{Name: imageName},
+ image: infrav1.ImageFilter{Name: &imageName},
expect: func(m *mock.MockImageClientMockRecorder) {
m.ListImages(images.ListOpts{Name: imageName}).Return(
[]images.Image{},
@@ -94,7 +94,7 @@ func TestService_getImageID(t *testing.T) {
},
{
testName: "Return multiple results",
- image: infrav1.ImageFilter{Name: imageName},
+ image: infrav1.ImageFilter{Name: &imageName},
expect: func(m *mock.MockImageClientMockRecorder) {
m.ListImages(images.ListOpts{Name: "test-image"}).Return(
[]images.Image{
@@ -107,7 +107,7 @@ func TestService_getImageID(t *testing.T) {
},
{
testName: "OpenStack returns error",
- image: infrav1.ImageFilter{Name: imageName},
+ image: infrav1.ImageFilter{Name: &imageName},
expect: func(m *mock.MockImageClientMockRecorder) {
m.ListImages(images.ListOpts{Name: "test-image"}).Return(
nil,
diff --git a/pkg/cloud/services/compute/referenced_resources_test.go b/pkg/cloud/services/compute/referenced_resources_test.go
index a62ce19e2f..1dd50788b6 100644
--- a/pkg/cloud/services/compute/referenced_resources_test.go
+++ b/pkg/cloud/services/compute/referenced_resources_test.go
@@ -26,6 +26,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/imageservice/v2/images"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions"
. "github.com/onsi/gomega"
+ "k8s.io/utils/pointer"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/mock"
@@ -35,7 +36,7 @@ import (
func Test_ResolveReferencedMachineResources(t *testing.T) {
constFalse := false
const serverGroupID1 = "ce96e584-7ebc-46d6-9e55-987d72e3806c"
- const imageID1 = "de96e584-7ebc-46d6-9e55-987d72e3806c"
+ imageID1 := "de96e584-7ebc-46d6-9e55-987d72e3806c"
minimumReferences := &infrav1.ReferencedMachineResources{
ImageID: imageID1,
@@ -56,7 +57,7 @@ func Test_ResolveReferencedMachineResources(t *testing.T) {
{
testName: "Resources ID passed",
serverGroupFilter: &infrav1.ServerGroupFilter{ID: serverGroupID1},
- imageFilter: &infrav1.ImageFilter{ID: imageID1},
+ imageFilter: &infrav1.ImageFilter{ID: &imageID1},
expectComputeMock: func(m *mock.MockComputeClientMockRecorder) {},
expectImageMock: func(m *mock.MockImageClientMockRecorder) {},
expectNetworkMock: func(m *mock.MockNetworkClientMockRecorder) {},
@@ -96,7 +97,7 @@ func Test_ResolveReferencedMachineResources(t *testing.T) {
},
{
testName: "Image by Name not found",
- imageFilter: &infrav1.ImageFilter{Name: "test-image"},
+ imageFilter: &infrav1.ImageFilter{Name: pointer.String("test-image")},
expectComputeMock: func(m *mock.MockComputeClientMockRecorder) {},
expectImageMock: func(m *mock.MockImageClientMockRecorder) {
m.ListImages(images.ListOpts{Name: "test-image"}).Return(
@@ -157,7 +158,7 @@ func Test_ResolveReferencedMachineResources(t *testing.T) {
tt.expectNetworkMock(mockScopeFactory.NetworkClient.EXPECT())
// Set defaults for required fields
- imageFilter := &infrav1.ImageFilter{ID: imageID1}
+ imageFilter := &infrav1.ImageFilter{ID: pointer.String(imageID1)}
if tt.imageFilter != nil {
imageFilter = tt.imageFilter
}
diff --git a/pkg/utils/filterconvert/convert.go b/pkg/utils/filterconvert/convert.go
index a4ba88e44f..a1574cc49f 100644
--- a/pkg/utils/filterconvert/convert.go
+++ b/pkg/utils/filterconvert/convert.go
@@ -95,13 +95,17 @@ func RouterFilterToListOpts(routerFilter *infrav1.RouterFilter) routers.ListOpts
}
}
-func ImageFilterToListOpts(imageFilter *infrav1.ImageFilter) images.ListOpts {
+func ImageFilterToListOpts(imageFilter *infrav1.ImageFilter) (listOpts images.ListOpts) {
if imageFilter == nil {
- return images.ListOpts{}
+ return
}
- return images.ListOpts{
- ID: imageFilter.ID,
- Name: imageFilter.Name,
- Tags: imageFilter.Tags,
+
+ if imageFilter.Name != nil && *imageFilter.Name != "" {
+ listOpts.Name = *imageFilter.Name
+ }
+
+ if len(imageFilter.Tags) > 0 {
+ listOpts.Tags = imageFilter.Tags
}
+ return
}
diff --git a/pkg/webhooks/openstackcluster_webhook_test.go b/pkg/webhooks/openstackcluster_webhook_test.go
index 1d2a4cd6ad..dcead6be4f 100644
--- a/pkg/webhooks/openstackcluster_webhook_test.go
+++ b/pkg/webhooks/openstackcluster_webhook_test.go
@@ -85,7 +85,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
Bastion: &infrav1.Bastion{
Instance: infrav1.OpenStackMachineSpec{
- Image: infrav1.ImageFilter{Name: "foobar"},
+ Image: infrav1.ImageFilter{Name: pointer.String("foobar")},
Flavor: "minimal",
},
Enabled: true,
@@ -105,7 +105,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
Bastion: &infrav1.Bastion{
Instance: infrav1.OpenStackMachineSpec{
- Image: infrav1.ImageFilter{Name: "foobarbaz"},
+ Image: infrav1.ImageFilter{Name: pointer.String("foobarbaz")},
Flavor: "medium",
},
Enabled: true,
@@ -454,7 +454,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
Enabled: true,
Instance: infrav1.OpenStackMachineSpec{
Flavor: "m1.small",
- Image: infrav1.ImageFilter{Name: "ubuntu"},
+ Image: infrav1.ImageFilter{Name: pointer.String("ubuntu")},
},
},
},
@@ -481,7 +481,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
Enabled: false,
Instance: infrav1.OpenStackMachineSpec{
Flavor: "m1.small",
- Image: infrav1.ImageFilter{Name: "ubuntu"},
+ Image: infrav1.ImageFilter{Name: pointer.String("ubuntu")},
},
},
},
diff --git a/pkg/webhooks/openstackmachinetemplate_webhook_test.go b/pkg/webhooks/openstackmachinetemplate_webhook_test.go
index b6d30791c6..899cf509f1 100644
--- a/pkg/webhooks/openstackmachinetemplate_webhook_test.go
+++ b/pkg/webhooks/openstackmachinetemplate_webhook_test.go
@@ -47,7 +47,7 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) {
Template: infrav1.OpenStackMachineTemplateResource{
Spec: infrav1.OpenStackMachineSpec{
Flavor: "foo",
- Image: infrav1.ImageFilter{Name: "bar"},
+ Image: infrav1.ImageFilter{Name: pointer.String("bar")},
},
},
},
@@ -57,7 +57,7 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) {
Template: infrav1.OpenStackMachineTemplateResource{
Spec: infrav1.OpenStackMachineSpec{
Flavor: "foo",
- Image: infrav1.ImageFilter{Name: "NewImage"},
+ Image: infrav1.ImageFilter{Name: pointer.String("NewImage")},
},
},
},
@@ -72,7 +72,7 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) {
Template: infrav1.OpenStackMachineTemplateResource{
Spec: infrav1.OpenStackMachineSpec{
Flavor: "foo",
- Image: infrav1.ImageFilter{Name: "bar"},
+ Image: infrav1.ImageFilter{Name: pointer.String("bar")},
},
},
},
@@ -85,7 +85,7 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) {
Template: infrav1.OpenStackMachineTemplateResource{
Spec: infrav1.OpenStackMachineSpec{
Flavor: "foo",
- Image: infrav1.ImageFilter{Name: "bar"},
+ Image: infrav1.ImageFilter{Name: pointer.String("bar")},
},
},
},
@@ -102,7 +102,7 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) {
Template: infrav1.OpenStackMachineTemplateResource{
Spec: infrav1.OpenStackMachineSpec{
Flavor: "foo",
- Image: infrav1.ImageFilter{Name: "bar"},
+ Image: infrav1.ImageFilter{Name: pointer.String("bar")},
},
},
},
@@ -112,7 +112,7 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) {
Template: infrav1.OpenStackMachineTemplateResource{
Spec: infrav1.OpenStackMachineSpec{
Flavor: "foo",
- Image: infrav1.ImageFilter{Name: "NewImage"},
+ Image: infrav1.ImageFilter{Name: pointer.String("NewImage")},
},
},
},
@@ -127,7 +127,7 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) {
Template: infrav1.OpenStackMachineTemplateResource{
Spec: infrav1.OpenStackMachineSpec{
Flavor: "foo",
- Image: infrav1.ImageFilter{Name: "bar"},
+ Image: infrav1.ImageFilter{Name: pointer.String("bar")},
},
},
},
@@ -142,7 +142,7 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) {
Template: infrav1.OpenStackMachineTemplateResource{
Spec: infrav1.OpenStackMachineSpec{
Flavor: "foo",
- Image: infrav1.ImageFilter{Name: "NewImage"},
+ Image: infrav1.ImageFilter{Name: pointer.String("NewImage")},
},
},
},
diff --git a/test/e2e/suites/e2e/e2e_test.go b/test/e2e/suites/e2e/e2e_test.go
index c184f96011..e57c5bdd99 100644
--- a/test/e2e/suites/e2e/e2e_test.go
+++ b/test/e2e/suites/e2e/e2e_test.go
@@ -861,7 +861,7 @@ func makeOpenStackMachineTemplate(namespace, clusterName, name string) *infrav1.
Spec: infrav1.OpenStackMachineSpec{
Flavor: e2eCtx.E2EConfig.GetVariable(shared.OpenStackNodeMachineFlavor),
Image: infrav1.ImageFilter{
- Name: e2eCtx.E2EConfig.GetVariable(shared.OpenStackImageName),
+ Name: pointer.String(e2eCtx.E2EConfig.GetVariable(shared.OpenStackImageName)),
},
SSHKeyName: shared.DefaultSSHKeyPairName,
IdentityRef: &infrav1.OpenStackIdentityReference{
@@ -885,7 +885,7 @@ func makeOpenStackMachineTemplateWithPortOptions(namespace, clusterName, name st
Spec: infrav1.OpenStackMachineSpec{
Flavor: e2eCtx.E2EConfig.GetVariable(shared.OpenStackNodeMachineFlavor),
Image: infrav1.ImageFilter{
- Name: e2eCtx.E2EConfig.GetVariable(shared.OpenStackImageName),
+ Name: pointer.String(e2eCtx.E2EConfig.GetVariable(shared.OpenStackImageName)),
},
SSHKeyName: shared.DefaultSSHKeyPairName,
IdentityRef: &infrav1.OpenStackIdentityReference{
From dc3959e0dd803c30361cbf6697293db6090dad66 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20Dulko?=
Date: Tue, 12 Mar 2024 16:02:43 +0100
Subject: [PATCH 125/180] Add ImageFilter API validations
This adds tests related to kubebuilder validations of ImageFilter.
---
...neutronfilters_test.go => filters_test.go} | 48 ++++++++++++++++++-
1 file changed, 47 insertions(+), 1 deletion(-)
rename test/e2e/suites/apivalidations/{neutronfilters_test.go => filters_test.go} (79%)
diff --git a/test/e2e/suites/apivalidations/neutronfilters_test.go b/test/e2e/suites/apivalidations/filters_test.go
similarity index 79%
rename from test/e2e/suites/apivalidations/neutronfilters_test.go
rename to test/e2e/suites/apivalidations/filters_test.go
index 59fb80e9fd..b4e256cff8 100644
--- a/test/e2e/suites/apivalidations/neutronfilters_test.go
+++ b/test/e2e/suites/apivalidations/filters_test.go
@@ -20,11 +20,12 @@ import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
+ "k8s.io/utils/pointer"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
)
-var _ = Describe("Neutron filter API validations", func() {
+var _ = Describe("Filter API validations", func() {
var (
namespace *corev1.Namespace
cluster *infrav1.OpenStackCluster
@@ -173,4 +174,49 @@ var _ = Describe("Neutron filter API validations", func() {
{Tags: []infrav1.NeutronTag{"foo", ""}},
}),
)
+
+ const imageUUID = "5a78f794-cdc3-48d2-8d9f-0fd472fdd743"
+
+ It("should not allow both ID and Name of ImageFilter to be set", func() {
+ By("Creating a machine")
+ machine.Spec.Image = infrav1.ImageFilter{
+ ID: pointer.String(imageUUID),
+ Name: pointer.String("bar"),
+ }
+ Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail")
+ })
+
+ It("should not allow both ID and Tags of ImageFilter to be set", func() {
+ By("Creating a machine")
+ machine.Spec.Image = infrav1.ImageFilter{
+ ID: pointer.String(imageUUID),
+ Tags: []string{"bar", "baz"},
+ }
+ Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail")
+ })
+
+ It("should allow UUID ID of ImageFilter to be set", func() {
+ By("Creating a machine")
+ machine.Spec.Image = infrav1.ImageFilter{
+ ID: pointer.String(imageUUID),
+ }
+ Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "OpenStackMachine creation should succeed")
+ })
+
+ It("should not allow non-UUID ID of ImageFilter to be set", func() {
+ By("Creating a machine")
+ machine.Spec.Image = infrav1.ImageFilter{
+ ID: pointer.String("foo"),
+ }
+ Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail")
+ })
+
+ It("should allow Name and Tags of ImageFilter to be set", func() {
+ By("Creating a machine")
+ machine.Spec.Image = infrav1.ImageFilter{
+ Name: pointer.String("bar"),
+ Tags: []string{"bar", "baz"},
+ }
+ Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "OpenStackMachine creation should succeed")
+ })
})
From f79fdf853e46b6dd78fd50f989d5e079cfc05d40 Mon Sep 17 00:00:00 2001
From: Mathieu Tortuyaux
Date: Mon, 11 Mar 2024 18:34:56 +0100
Subject: [PATCH 126/180] test: bump Flatcar version
Signed-off-by: Mathieu Tortuyaux
---
hack/ci/cloud-init/controller.yaml.tpl | 2 +-
test/e2e/data/e2e_conf.yaml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/hack/ci/cloud-init/controller.yaml.tpl b/hack/ci/cloud-init/controller.yaml.tpl
index 20eb78627f..a3b8bb23b3 100644
--- a/hack/ci/cloud-init/controller.yaml.tpl
+++ b/hack/ci/cloud-init/controller.yaml.tpl
@@ -70,7 +70,7 @@
IMAGE_URLS+="https://storage.googleapis.com/artifacts.k8s-staging-capi-openstack.appspot.com/test/cirros/2022-12-05/cirros-0.6.1-x86_64-disk.img,"
IMAGE_URLS+="https://storage.googleapis.com/artifacts.k8s-staging-capi-openstack.appspot.com/test/ubuntu/2023-09-29/ubuntu-2204-kube-v1.27.2.img,"
IMAGE_URLS+="https://storage.googleapis.com/artifacts.k8s-staging-capi-openstack.appspot.com/test/ubuntu/2024-01-10/ubuntu-2204-kube-v1.28.5.img,"
- IMAGE_URLS+="https://storage.googleapis.com/artifacts.k8s-staging-capi-openstack.appspot.com/test/flatcar/flatcar-stable-3760.2.0-kube-v1.28.5.img,"
+ IMAGE_URLS+="https://storage.googleapis.com/artifacts.k8s-staging-capi-openstack.appspot.com/test/flatcar/flatcar-stable-3815.2.0-kube-v1.28.5.img,"
IMAGE_URLS+="https://stable.release.flatcar-linux.net/amd64-usr/current/flatcar_production_openstack_image.img"
[[post-config|$NOVA_CONF]]
diff --git a/test/e2e/data/e2e_conf.yaml b/test/e2e/data/e2e_conf.yaml
index 4d9552334c..e7e4581c49 100644
--- a/test/e2e/data/e2e_conf.yaml
+++ b/test/e2e/data/e2e_conf.yaml
@@ -214,7 +214,7 @@ variables:
SSH_USER_MACHINE: "ubuntu"
EXP_KUBEADM_BOOTSTRAP_FORMAT_IGNITION: "true"
# The Flatcar image produced by the image-builder
- OPENSTACK_FLATCAR_IMAGE_NAME: "flatcar-stable-3760.2.0-kube-v1.28.5"
+ OPENSTACK_FLATCAR_IMAGE_NAME: "flatcar-stable-3815.2.0-kube-v1.28.5"
# A plain Flatcar from the Flatcar releases server
FLATCAR_IMAGE_NAME: "flatcar_production_openstack_image"
From 957c9fc464331d19e6187233a68a6be2accf2a32 Mon Sep 17 00:00:00 2001
From: Lennart Jern
Date: Thu, 25 May 2023 14:42:55 +0300
Subject: [PATCH 127/180] Templates: Set provider ID directly via kubelet
This commit sets the provider ID in the flatcar templates.
To avoid issues with potential mismatches between node names and
openstack servers we can configure the kubelet to set the provider ID.
Otherwise, the cloud controller will try to match nodes and servers
based on just the name. The names can differ because of special
characters, like dots. When this happens, the cloud controller will be
unable to match them and thus believe that the node has no underlying
server.
Co-authored-by: Mathieu Tortuyaux
---
.../v1alpha7/flatcar-sysext/patch-flatcar.yaml | 14 +++++---------
kustomize/v1alpha7/flatcar/patch-flatcar.yaml | 14 +++++---------
.../v1beta1/flatcar-sysext/patch-flatcar.yaml | 14 +++++---------
kustomize/v1beta1/flatcar/patch-flatcar.yaml | 14 +++++---------
templates/cluster-template-flatcar-sysext.yaml | 5 +++++
templates/cluster-template-flatcar.yaml | 5 +++++
6 files changed, 30 insertions(+), 36 deletions(-)
diff --git a/kustomize/v1alpha7/flatcar-sysext/patch-flatcar.yaml b/kustomize/v1alpha7/flatcar-sysext/patch-flatcar.yaml
index 9f8b858c08..6c1d092ea6 100644
--- a/kustomize/v1alpha7/flatcar-sysext/patch-flatcar.yaml
+++ b/kustomize/v1alpha7/flatcar-sysext/patch-flatcar.yaml
@@ -18,15 +18,12 @@ spec:
nodeRegistration:
name: $${COREOS_OPENSTACK_HOSTNAME}
kubeletExtraArgs:
- provider-id: null
+ provider-id: openstack:///$${COREOS_OPENSTACK_INSTANCE_UUID}
initConfiguration:
nodeRegistration:
name: $${COREOS_OPENSTACK_HOSTNAME}
kubeletExtraArgs:
- # Fixme(lentzi90): This is here just to override the value set in the default
- # kustomization. It will be replaced with a value that works for flatcar in
- # https://github.com/kubernetes-sigs/cluster-api-provider-openstack/pull/1564
- provider-id: null
+ provider-id: openstack:///$${COREOS_OPENSTACK_INSTANCE_UUID}
format: ignition
ignition:
containerLinuxConfig:
@@ -86,6 +83,7 @@ spec:
EnvironmentFile=/run/metadata/flatcar
preKubeadmCommands:
- export COREOS_OPENSTACK_HOSTNAME=$${COREOS_OPENSTACK_HOSTNAME%.*}
+ - export COREOS_OPENSTACK_INSTANCE_UUID=$${COREOS_OPENSTACK_INSTANCE_UUID}
- envsubst < /etc/kubeadm.yml > /etc/kubeadm.yml.tmp
- mv /etc/kubeadm.yml.tmp /etc/kubeadm.yml
---
@@ -100,12 +98,10 @@ spec:
nodeRegistration:
name: $${COREOS_OPENSTACK_HOSTNAME}
kubeletExtraArgs:
- # Fixme(lentzi90): This is here just to override the value set in the default
- # kustomization. It will be replaced with a value that works for flatcar in
- # https://github.com/kubernetes-sigs/cluster-api-provider-openstack/pull/1564
- provider-id: null
+ provider-id: openstack:///$${COREOS_OPENSTACK_INSTANCE_UUID}
preKubeadmCommands:
- export COREOS_OPENSTACK_HOSTNAME=$${COREOS_OPENSTACK_HOSTNAME%.*}
+ - export COREOS_OPENSTACK_INSTANCE_UUID=$${COREOS_OPENSTACK_INSTANCE_UUID}
- envsubst < /etc/kubeadm.yml > /etc/kubeadm.yml.tmp
- mv /etc/kubeadm.yml.tmp /etc/kubeadm.yml
format: ignition
diff --git a/kustomize/v1alpha7/flatcar/patch-flatcar.yaml b/kustomize/v1alpha7/flatcar/patch-flatcar.yaml
index 02dacc00af..446f005b5f 100644
--- a/kustomize/v1alpha7/flatcar/patch-flatcar.yaml
+++ b/kustomize/v1alpha7/flatcar/patch-flatcar.yaml
@@ -18,15 +18,12 @@ spec:
nodeRegistration:
name: $${COREOS_OPENSTACK_HOSTNAME}
kubeletExtraArgs:
- provider-id: null
+ provider-id: openstack:///$${COREOS_OPENSTACK_INSTANCE_UUID}
initConfiguration:
nodeRegistration:
name: $${COREOS_OPENSTACK_HOSTNAME}
kubeletExtraArgs:
- # Fixme(lentzi90): This is here just to override the value set in the default
- # kustomization. It will be replaced with a value that works for flatcar in
- # https://github.com/kubernetes-sigs/cluster-api-provider-openstack/pull/1564
- provider-id: null
+ provider-id: openstack:///$${COREOS_OPENSTACK_INSTANCE_UUID}
format: ignition
ignition:
containerLinuxConfig:
@@ -48,6 +45,7 @@ spec:
EnvironmentFile=/run/metadata/flatcar
preKubeadmCommands:
- export COREOS_OPENSTACK_HOSTNAME=$${COREOS_OPENSTACK_HOSTNAME%.*}
+ - export COREOS_OPENSTACK_INSTANCE_UUID=$${COREOS_OPENSTACK_INSTANCE_UUID}
- envsubst < /etc/kubeadm.yml > /etc/kubeadm.yml.tmp
- mv /etc/kubeadm.yml.tmp /etc/kubeadm.yml
---
@@ -62,12 +60,10 @@ spec:
nodeRegistration:
name: $${COREOS_OPENSTACK_HOSTNAME}
kubeletExtraArgs:
- # Fixme(lentzi90): This is here just to override the value set in the default
- # kustomization. It will be replaced with a value that works for flatcar in
- # https://github.com/kubernetes-sigs/cluster-api-provider-openstack/pull/1564
- provider-id: null
+ provider-id: openstack:///$${COREOS_OPENSTACK_INSTANCE_UUID}
preKubeadmCommands:
- export COREOS_OPENSTACK_HOSTNAME=$${COREOS_OPENSTACK_HOSTNAME%.*}
+ - export COREOS_OPENSTACK_INSTANCE_UUID=$${COREOS_OPENSTACK_INSTANCE_UUID}
- envsubst < /etc/kubeadm.yml > /etc/kubeadm.yml.tmp
- mv /etc/kubeadm.yml.tmp /etc/kubeadm.yml
format: ignition
diff --git a/kustomize/v1beta1/flatcar-sysext/patch-flatcar.yaml b/kustomize/v1beta1/flatcar-sysext/patch-flatcar.yaml
index fce635f466..0c60d2e460 100644
--- a/kustomize/v1beta1/flatcar-sysext/patch-flatcar.yaml
+++ b/kustomize/v1beta1/flatcar-sysext/patch-flatcar.yaml
@@ -18,15 +18,12 @@ spec:
nodeRegistration:
name: $${COREOS_OPENSTACK_HOSTNAME}
kubeletExtraArgs:
- provider-id: null
+ provider-id: openstack:///$${COREOS_OPENSTACK_INSTANCE_UUID}
initConfiguration:
nodeRegistration:
name: $${COREOS_OPENSTACK_HOSTNAME}
kubeletExtraArgs:
- # Fixme(lentzi90): This is here just to override the value set in the default
- # kustomization. It will be replaced with a value that works for flatcar in
- # https://github.com/kubernetes-sigs/cluster-api-provider-openstack/pull/1564
- provider-id: null
+ provider-id: openstack:///$${COREOS_OPENSTACK_INSTANCE_UUID}
format: ignition
ignition:
containerLinuxConfig:
@@ -86,6 +83,7 @@ spec:
EnvironmentFile=/run/metadata/flatcar
preKubeadmCommands:
- export COREOS_OPENSTACK_HOSTNAME=$${COREOS_OPENSTACK_HOSTNAME%.*}
+ - export COREOS_OPENSTACK_INSTANCE_UUID=$${COREOS_OPENSTACK_INSTANCE_UUID}
- envsubst < /etc/kubeadm.yml > /etc/kubeadm.yml.tmp
- mv /etc/kubeadm.yml.tmp /etc/kubeadm.yml
---
@@ -100,12 +98,10 @@ spec:
nodeRegistration:
name: $${COREOS_OPENSTACK_HOSTNAME}
kubeletExtraArgs:
- # Fixme(lentzi90): This is here just to override the value set in the default
- # kustomization. It will be replaced with a value that works for flatcar in
- # https://github.com/kubernetes-sigs/cluster-api-provider-openstack/pull/1564
- provider-id: null
+ provider-id: openstack:///$${COREOS_OPENSTACK_INSTANCE_UUID}
preKubeadmCommands:
- export COREOS_OPENSTACK_HOSTNAME=$${COREOS_OPENSTACK_HOSTNAME%.*}
+ - export COREOS_OPENSTACK_INSTANCE_UUID=$${COREOS_OPENSTACK_INSTANCE_UUID}
- envsubst < /etc/kubeadm.yml > /etc/kubeadm.yml.tmp
- mv /etc/kubeadm.yml.tmp /etc/kubeadm.yml
format: ignition
diff --git a/kustomize/v1beta1/flatcar/patch-flatcar.yaml b/kustomize/v1beta1/flatcar/patch-flatcar.yaml
index 19e7b7fece..d95991efc9 100644
--- a/kustomize/v1beta1/flatcar/patch-flatcar.yaml
+++ b/kustomize/v1beta1/flatcar/patch-flatcar.yaml
@@ -18,15 +18,12 @@ spec:
nodeRegistration:
name: $${COREOS_OPENSTACK_HOSTNAME}
kubeletExtraArgs:
- provider-id: null
+ provider-id: openstack:///$${COREOS_OPENSTACK_INSTANCE_UUID}
initConfiguration:
nodeRegistration:
name: $${COREOS_OPENSTACK_HOSTNAME}
kubeletExtraArgs:
- # Fixme(lentzi90): This is here just to override the value set in the default
- # kustomization. It will be replaced with a value that works for flatcar in
- # https://github.com/kubernetes-sigs/cluster-api-provider-openstack/pull/1564
- provider-id: null
+ provider-id: openstack:///$${COREOS_OPENSTACK_INSTANCE_UUID}
format: ignition
ignition:
containerLinuxConfig:
@@ -48,6 +45,7 @@ spec:
EnvironmentFile=/run/metadata/flatcar
preKubeadmCommands:
- export COREOS_OPENSTACK_HOSTNAME=$${COREOS_OPENSTACK_HOSTNAME%.*}
+ - export COREOS_OPENSTACK_INSTANCE_UUID=$${COREOS_OPENSTACK_INSTANCE_UUID}
- envsubst < /etc/kubeadm.yml > /etc/kubeadm.yml.tmp
- mv /etc/kubeadm.yml.tmp /etc/kubeadm.yml
---
@@ -62,12 +60,10 @@ spec:
nodeRegistration:
name: $${COREOS_OPENSTACK_HOSTNAME}
kubeletExtraArgs:
- # Fixme(lentzi90): This is here just to override the value set in the default
- # kustomization. It will be replaced with a value that works for flatcar in
- # https://github.com/kubernetes-sigs/cluster-api-provider-openstack/pull/1564
- provider-id: null
+ provider-id: openstack:///$${COREOS_OPENSTACK_INSTANCE_UUID}
preKubeadmCommands:
- export COREOS_OPENSTACK_HOSTNAME=$${COREOS_OPENSTACK_HOSTNAME%.*}
+ - export COREOS_OPENSTACK_INSTANCE_UUID=$${COREOS_OPENSTACK_INSTANCE_UUID}
- envsubst < /etc/kubeadm.yml > /etc/kubeadm.yml.tmp
- mv /etc/kubeadm.yml.tmp /etc/kubeadm.yml
format: ignition
diff --git a/templates/cluster-template-flatcar-sysext.yaml b/templates/cluster-template-flatcar-sysext.yaml
index 360ff1c005..9cbef933cc 100644
--- a/templates/cluster-template-flatcar-sysext.yaml
+++ b/templates/cluster-template-flatcar-sysext.yaml
@@ -77,9 +77,11 @@ spec:
nodeRegistration:
kubeletExtraArgs:
cloud-provider: external
+ provider-id: openstack:///$${COREOS_OPENSTACK_INSTANCE_UUID}
name: $${COREOS_OPENSTACK_HOSTNAME}
preKubeadmCommands:
- export COREOS_OPENSTACK_HOSTNAME=$${COREOS_OPENSTACK_HOSTNAME%.*}
+ - export COREOS_OPENSTACK_INSTANCE_UUID=$${COREOS_OPENSTACK_INSTANCE_UUID}
- envsubst < /etc/kubeadm.yml > /etc/kubeadm.yml.tmp
- mv /etc/kubeadm.yml.tmp /etc/kubeadm.yml
---
@@ -201,14 +203,17 @@ spec:
nodeRegistration:
kubeletExtraArgs:
cloud-provider: external
+ provider-id: openstack:///$${COREOS_OPENSTACK_INSTANCE_UUID}
name: $${COREOS_OPENSTACK_HOSTNAME}
joinConfiguration:
nodeRegistration:
kubeletExtraArgs:
cloud-provider: external
+ provider-id: openstack:///$${COREOS_OPENSTACK_INSTANCE_UUID}
name: $${COREOS_OPENSTACK_HOSTNAME}
preKubeadmCommands:
- export COREOS_OPENSTACK_HOSTNAME=$${COREOS_OPENSTACK_HOSTNAME%.*}
+ - export COREOS_OPENSTACK_INSTANCE_UUID=$${COREOS_OPENSTACK_INSTANCE_UUID}
- envsubst < /etc/kubeadm.yml > /etc/kubeadm.yml.tmp
- mv /etc/kubeadm.yml.tmp /etc/kubeadm.yml
machineTemplate:
diff --git a/templates/cluster-template-flatcar.yaml b/templates/cluster-template-flatcar.yaml
index 691a98daee..3d3f92ba23 100644
--- a/templates/cluster-template-flatcar.yaml
+++ b/templates/cluster-template-flatcar.yaml
@@ -39,9 +39,11 @@ spec:
nodeRegistration:
kubeletExtraArgs:
cloud-provider: external
+ provider-id: openstack:///$${COREOS_OPENSTACK_INSTANCE_UUID}
name: $${COREOS_OPENSTACK_HOSTNAME}
preKubeadmCommands:
- export COREOS_OPENSTACK_HOSTNAME=$${COREOS_OPENSTACK_HOSTNAME%.*}
+ - export COREOS_OPENSTACK_INSTANCE_UUID=$${COREOS_OPENSTACK_INSTANCE_UUID}
- envsubst < /etc/kubeadm.yml > /etc/kubeadm.yml.tmp
- mv /etc/kubeadm.yml.tmp /etc/kubeadm.yml
---
@@ -125,14 +127,17 @@ spec:
nodeRegistration:
kubeletExtraArgs:
cloud-provider: external
+ provider-id: openstack:///$${COREOS_OPENSTACK_INSTANCE_UUID}
name: $${COREOS_OPENSTACK_HOSTNAME}
joinConfiguration:
nodeRegistration:
kubeletExtraArgs:
cloud-provider: external
+ provider-id: openstack:///$${COREOS_OPENSTACK_INSTANCE_UUID}
name: $${COREOS_OPENSTACK_HOSTNAME}
preKubeadmCommands:
- export COREOS_OPENSTACK_HOSTNAME=$${COREOS_OPENSTACK_HOSTNAME%.*}
+ - export COREOS_OPENSTACK_INSTANCE_UUID=$${COREOS_OPENSTACK_INSTANCE_UUID}
- envsubst < /etc/kubeadm.yml > /etc/kubeadm.yml.tmp
- mv /etc/kubeadm.yml.tmp /etc/kubeadm.yml
machineTemplate:
From 559cbf2eb9a82aee27d2c920be434acd0faa10bc Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Thu, 14 Mar 2024 17:58:23 +0000
Subject: [PATCH 128/180] v1alpha5: Fix panic in conversion when port has no
binding profile
---
api/v1alpha5/conversion.go | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/api/v1alpha5/conversion.go b/api/v1alpha5/conversion.go
index cd66e62bd3..dd0c90ee0a 100644
--- a/api/v1alpha5/conversion.go
+++ b/api/v1alpha5/conversion.go
@@ -335,13 +335,16 @@ func Convert_v1beta1_PortOpts_To_v1alpha5_PortOpts(in *infrav1.PortOpts, out *Po
}
}
- out.Profile = make(map[string]string)
- if pointer.BoolDeref(in.Profile.OVSHWOffload, false) {
- (out.Profile)["capabilities"] = "[\"switchdev\"]"
- }
- if pointer.BoolDeref(in.Profile.TrustedVF, false) {
- (out.Profile)["trusted"] = trueString
+ if in.Profile != nil {
+ out.Profile = make(map[string]string)
+ if pointer.BoolDeref(in.Profile.OVSHWOffload, false) {
+ (out.Profile)["capabilities"] = "[\"switchdev\"]"
+ }
+ if pointer.BoolDeref(in.Profile.TrustedVF, false) {
+ (out.Profile)["trusted"] = trueString
+ }
}
+
return nil
}
From cc78607a4a80cf787acaeb51a17412587c270360 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Tue, 12 Mar 2024 16:52:11 +0000
Subject: [PATCH 129/180] Fix port name after port creation failure
CreatePorts was creating a port name based on the index of the port in
the *current reconcile*. This could be different to the absolute index
of the port if ports had been partially created in a previous reconcile.
We fix this by passing all current state into CreatePorts so it can
create an absolute index. This also ensures that partially created ports
will be persisted on failure so we don't have to rely on adoption in the
next reconcile.
---
controllers/openstackcluster_controller.go | 35 ++++-------
controllers/openstackmachine_controller.go | 32 +++-------
pkg/cloud/services/networking/port.go | 52 ++++++-----------
pkg/cloud/services/networking/port_test.go | 68 ----------------------
4 files changed, 36 insertions(+), 151 deletions(-)
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index 11e318ff31..6adcc1100d 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -404,7 +404,7 @@ func reconcileBastion(scope *scope.WithLogger, cluster *clusterv1.Cluster, openS
}
}
- err = getOrCreateBastionPorts(scope, cluster, openStackCluster, networkingService, cluster.Name)
+ err = getOrCreateBastionPorts(openStackCluster, networkingService, cluster.Name)
if err != nil {
handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to get or create ports for bastion: %w", err))
return ctrl.Result{}, fmt.Errorf("failed to get or create ports for bastion: %w", err)
@@ -548,34 +548,19 @@ func getBastionSecurityGroups(openStackCluster *infrav1.OpenStackCluster) []infr
return instanceSpecSecurityGroups
}
-func getOrCreateBastionPorts(scope *scope.WithLogger, cluster *clusterv1.Cluster, openStackCluster *infrav1.OpenStackCluster, networkingService *networking.Service, clusterName string) error {
- scope.Logger().Info("Reconciling ports for bastion", "bastion", bastionName(openStackCluster.Name))
-
- if openStackCluster.Status.Bastion == nil {
- openStackCluster.Status.Bastion = &infrav1.BastionStatus{}
- }
-
+func getOrCreateBastionPorts(openStackCluster *infrav1.OpenStackCluster, networkingService *networking.Service, clusterName string) error {
desiredPorts := openStackCluster.Status.Bastion.ReferencedResources.Ports
- portsToCreate := networking.MissingPorts(openStackCluster.Status.Bastion.DependentResources.Ports, desiredPorts)
-
- // Sanity check that the number of desired ports is equal to the addition of ports to create and ports that already exist.
- if len(desiredPorts) != len(portsToCreate)+len(openStackCluster.Status.Bastion.DependentResources.Ports) {
- return fmt.Errorf("length of desired ports (%d) is not equal to the length of ports to create (%d) + the length of ports that already exist (%d)", len(desiredPorts), len(portsToCreate), len(openStackCluster.Status.Bastion.DependentResources.Ports))
- }
+ dependentResources := &openStackCluster.Status.Bastion.DependentResources
- if len(portsToCreate) > 0 {
- securityGroups := getBastionSecurityGroups(openStackCluster)
- bastionPortsStatus, err := networkingService.CreatePorts(openStackCluster, clusterName, portsToCreate, securityGroups, []string{}, bastionName(cluster.Name))
- if err != nil {
- return fmt.Errorf("failed to create ports for bastion %s: %w", bastionName(openStackCluster.Name), err)
- }
-
- openStackCluster.Status.Bastion.DependentResources.Ports = append(openStackCluster.Status.Bastion.DependentResources.Ports, bastionPortsStatus...)
+ if len(desiredPorts) == len(dependentResources.Ports) {
+ return nil
}
- // Sanity check that the number of ports that have been put into PortsStatus is equal to the number of desired ports now that we have created them all.
- if len(openStackCluster.Status.Bastion.DependentResources.Ports) != len(desiredPorts) {
- return fmt.Errorf("length of ports that already exist (%d) is not equal to the length of desired ports (%d)", len(openStackCluster.Status.Bastion.DependentResources.Ports), len(desiredPorts))
+ securityGroups := getBastionSecurityGroups(openStackCluster)
+ bastionTags := []string{}
+ err := networkingService.CreatePorts(openStackCluster, clusterName, bastionName(clusterName), securityGroups, bastionTags, desiredPorts, dependentResources)
+ if err != nil {
+ return fmt.Errorf("failed to create ports for bastion %s: %w", bastionName(openStackCluster.Name), err)
}
return nil
diff --git a/controllers/openstackmachine_controller.go b/controllers/openstackmachine_controller.go
index 1e7d71695a..97f234b6ad 100644
--- a/controllers/openstackmachine_controller.go
+++ b/controllers/openstackmachine_controller.go
@@ -527,7 +527,7 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope
return ctrl.Result{}, err
}
- err = getOrCreateMachinePorts(scope, openStackCluster, machine, openStackMachine, networkingService, clusterName)
+ err = getOrCreateMachinePorts(openStackCluster, machine, openStackMachine, networkingService, clusterName)
if err != nil {
return ctrl.Result{}, err
}
@@ -669,32 +669,18 @@ func (r *OpenStackMachineReconciler) reconcileAPIServerLoadBalancer(scope *scope
return nil
}
-func getOrCreateMachinePorts(scope *scope.WithLogger, openStackCluster *infrav1.OpenStackCluster, machine *clusterv1.Machine, openStackMachine *infrav1.OpenStackMachine, networkingService *networking.Service, clusterName string) error {
- scope.Logger().Info("Reconciling ports for machine", "machine", machine.Name)
- var machinePortsStatus []infrav1.PortStatus
- var err error
-
+func getOrCreateMachinePorts(openStackCluster *infrav1.OpenStackCluster, machine *clusterv1.Machine, openStackMachine *infrav1.OpenStackMachine, networkingService *networking.Service, clusterName string) error {
desiredPorts := openStackMachine.Status.ReferencedResources.Ports
- portsToCreate := networking.MissingPorts(openStackMachine.Status.DependentResources.Ports, desiredPorts)
-
- // Sanity check that the number of desired ports is equal to the addition of ports to create and ports that already exist.
- if len(desiredPorts) != len(portsToCreate)+len(openStackMachine.Status.DependentResources.Ports) {
- return fmt.Errorf("length of desired ports (%d) is not equal to the length of ports to create (%d) + the length of ports that already exist (%d)", len(desiredPorts), len(portsToCreate), len(openStackMachine.Status.DependentResources.Ports))
- }
+ dependentResources := &openStackMachine.Status.DependentResources
- if len(portsToCreate) > 0 {
- instanceTags := getInstanceTags(openStackMachine, openStackCluster)
- managedSecurityGroups := getManagedSecurityGroups(openStackCluster, machine, openStackMachine)
- machinePortsStatus, err = networkingService.CreatePorts(openStackMachine, clusterName, portsToCreate, managedSecurityGroups, instanceTags, openStackMachine.Name)
- if err != nil {
- return fmt.Errorf("create ports: %w", err)
- }
- openStackMachine.Status.DependentResources.Ports = append(openStackMachine.Status.DependentResources.Ports, machinePortsStatus...)
+ if len(desiredPorts) == len(dependentResources.Ports) {
+ return nil
}
- // Sanity check that the number of ports that have been put into PortsStatus is equal to the number of desired ports now that we have created them all.
- if len(openStackMachine.Status.DependentResources.Ports) != len(desiredPorts) {
- return fmt.Errorf("length of ports that already exist (%d) is not equal to the length of desired ports (%d)", len(openStackMachine.Status.DependentResources.Ports), len(desiredPorts))
+ instanceTags := getInstanceTags(openStackMachine, openStackCluster)
+ managedSecurityGroups := getManagedSecurityGroups(openStackCluster, machine, openStackMachine)
+ if err := networkingService.CreatePorts(openStackMachine, clusterName, openStackMachine.Name, managedSecurityGroups, instanceTags, desiredPorts, dependentResources); err != nil {
+ return fmt.Errorf("creating ports: %w", err)
}
return nil
diff --git a/pkg/cloud/services/networking/port.go b/pkg/cloud/services/networking/port.go
index aaae36781a..b5d5aee5a1 100644
--- a/pkg/cloud/services/networking/port.go
+++ b/pkg/cloud/services/networking/port.go
@@ -109,7 +109,7 @@ func (s *Service) GetPortForExternalNetwork(instanceID string, externalNetworkID
return nil, nil
}
-func (s *Service) CreatePort(eventObject runtime.Object, clusterName string, portName string, portOpts *infrav1.PortOpts, instanceSecurityGroups []string, instanceTags []string) (*ports.Port, error) {
+func (s *Service) CreatePort(eventObject runtime.Object, clusterName string, portName string, portOpts *infrav1.PortOpts, defaultSecurityGroups []string, baseTags []string) (*ports.Port, error) {
var err error
networkID := portOpts.Network.ID
@@ -137,7 +137,7 @@ func (s *Service) CreatePort(eventObject runtime.Object, clusterName string, por
}
// inherit port security groups from the instance if not explicitly specified
if len(securityGroups) == 0 {
- securityGroups = instanceSecurityGroups
+ securityGroups = defaultSecurityGroups
}
}
@@ -209,7 +209,7 @@ func (s *Service) CreatePort(eventObject runtime.Object, clusterName string, por
}
var tags []string
- tags = append(tags, instanceTags...)
+ tags = append(tags, baseTags...)
tags = append(tags, portOpts.Tags...)
if len(tags) > 0 {
if err = s.replaceAllAttributesTags(eventObject, portResource, port.ID, tags); err != nil {
@@ -365,37 +365,32 @@ func GetPortName(instanceName string, opts *infrav1.PortOpts, netIndex int) stri
return fmt.Sprintf("%s-%d", instanceName, netIndex)
}
-func (s *Service) CreatePorts(eventObject runtime.Object, clusterName string, ports []infrav1.PortOpts, securityGroups []infrav1.SecurityGroupFilter, instanceTags []string, instanceName string) ([]infrav1.PortStatus, error) {
- return s.createPortsImpl(eventObject, clusterName, ports, securityGroups, instanceTags, instanceName)
-}
-
-func (s *Service) createPortsImpl(eventObject runtime.Object, clusterName string, ports []infrav1.PortOpts, securityGroups []infrav1.SecurityGroupFilter, instanceTags []string, instanceName string) ([]infrav1.PortStatus, error) {
- instanceSecurityGroups, err := s.GetSecurityGroups(securityGroups)
+func (s *Service) CreatePorts(eventObject runtime.Object, clusterName, baseName string, securityGroups []infrav1.SecurityGroupFilter, baseTags []string, desiredPorts []infrav1.PortOpts, dependentResources *infrav1.DependentMachineResources) error {
+ defaultSecurityGroups, err := s.GetSecurityGroups(securityGroups)
if err != nil {
- return nil, fmt.Errorf("error getting security groups: %v", err)
+ return fmt.Errorf("error getting security groups: %v", err)
}
- portsStatus := make([]infrav1.PortStatus, 0, len(ports))
-
- for i := range ports {
- portOpts := &ports[i]
- iTags := []string{}
- if len(instanceTags) > 0 {
- iTags = instanceTags
+ for i := range desiredPorts {
+ // Skip creation of ports which already exist
+ if i < len(dependentResources.Ports) {
+ continue
}
- portName := GetPortName(instanceName, portOpts, i)
+
+ portOpts := &desiredPorts[i]
+ portName := GetPortName(baseName, portOpts, i)
// Events are recorded in CreatePort
- port, err := s.CreatePort(eventObject, clusterName, portName, portOpts, instanceSecurityGroups, iTags)
+ port, err := s.CreatePort(eventObject, clusterName, portName, portOpts, defaultSecurityGroups, baseTags)
if err != nil {
- return nil, err
+ return err
}
- portsStatus = append(portsStatus, infrav1.PortStatus{
+ dependentResources.Ports = append(dependentResources.Ports, infrav1.PortStatus{
ID: port.ID,
})
}
- return portsStatus, nil
+ return nil
}
// ConstructPorts builds an array of ports from the instance spec.
@@ -691,16 +686,3 @@ func (s *Service) AdoptBastionPorts(scope *scope.WithLogger, openStackCluster *i
return changed, nil
}
-
-// MissingPorts returns the ports that are not in the ports status but are desired ports which should be created.
-func MissingPorts(portsStatus []infrav1.PortStatus, desiredPorts []infrav1.PortOpts) []infrav1.PortOpts {
- // missingPorts is equal to the ports status minus its length
- missingPortsLength := len(desiredPorts) - len(portsStatus)
-
- // rebuild desiredPorts to only contain the ports that were not adopted
- missingPorts := make([]infrav1.PortOpts, missingPortsLength)
- for i := 0; i < missingPortsLength; i++ {
- missingPorts[i] = desiredPorts[i+len(portsStatus)]
- }
- return missingPorts
-}
diff --git a/pkg/cloud/services/networking/port_test.go b/pkg/cloud/services/networking/port_test.go
index 5219886060..c6bb99c95d 100644
--- a/pkg/cloud/services/networking/port_test.go
+++ b/pkg/cloud/services/networking/port_test.go
@@ -837,71 +837,3 @@ func Test_getPortName(t *testing.T) {
})
}
}
-
-func Test_MissingPorts(t *testing.T) {
- tests := []struct {
- name string
- portsStatus []infrav1.PortStatus
- desiredPorts []infrav1.PortOpts
- expectedMissing []infrav1.PortOpts
- }{
- {
- name: "no missing ports",
- portsStatus: []infrav1.PortStatus{
- {
- ID: "06d18afd-a8d2-4c0f-b6be-63fe71d6c16d",
- },
- {
- ID: "7bf62a7e-a969-40cc-b50c-87bd52e97188",
- },
- },
- desiredPorts: []infrav1.PortOpts{
- {
- Network: &infrav1.NetworkFilter{
- ID: "94588d9b-21f1-4583-97ed-c7367327b0ea",
- },
- },
- {
- Network: &infrav1.NetworkFilter{
- ID: "9cc0ebba-eaec-4dc7-b5cf-ece51f699f47",
- },
- },
- },
- expectedMissing: []infrav1.PortOpts{},
- },
- {
- name: "missing ports",
- portsStatus: []infrav1.PortStatus{
- {
- ID: "06d18afd-a8d2-4c0f-b6be-63fe71d6c16d",
- },
- },
- desiredPorts: []infrav1.PortOpts{
- {
- Network: &infrav1.NetworkFilter{
- ID: "94588d9b-21f1-4583-97ed-c7367327b0ea",
- },
- },
- {
- Network: &infrav1.NetworkFilter{
- ID: "9cc0ebba-eaec-4dc7-b5cf-ece51f699f47",
- },
- },
- },
- expectedMissing: []infrav1.PortOpts{
- {
- Network: &infrav1.NetworkFilter{
- ID: "9cc0ebba-eaec-4dc7-b5cf-ece51f699f47",
- },
- },
- },
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- g := NewWithT(t)
- got := MissingPorts(tt.portsStatus, tt.desiredPorts)
- g.Expect(got).To(Equal(tt.expectedMissing))
- })
- }
-}
From 801f5ef2ff819d9f34e9e561d2c8c0044a7688d6 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Fri, 15 Mar 2024 15:58:51 +0000
Subject: [PATCH 130/180] Simplify bastion resource initialisation
Firstly, we remove the resource reconcile calls from the cluster flow
before calling reconcileNormal/reconcileDelete because the guards around
them and various other guards throughout the code are heavily
inter-depdendent and hard to reason about. Instead, we push them to the
the places we:
* know they are required
* know we are sufficiently initialised that they can work
Firstly we resolve references at the top of reconcileBastion. We know
the cluster has been initialised at this point, so we don't need to
guard against it. This also means that it is always called when entering
that function, so we don't need to guard against it not having been
called during first cluster initialisation.
We also force that function to re-reconcile if it calls deleteBastion(),
because deleteBastion() removes the bastion status. We reconcile again,
so we always know that it is set.
We also add an explicit call to resource reconcile in the
reconcileDelete flow. This is the only place we now need a 'weird' guard
against the cluster network not having been set. We add a comment about
that appropriate to its weirdness.
---
controllers/openstackcluster_controller.go | 155 +++++++++++-------
.../openstackcluster_controller_test.go | 6 +-
2 files changed, 100 insertions(+), 61 deletions(-)
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index 6adcc1100d..b34f0f4201 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -24,6 +24,7 @@ import (
"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"
@@ -123,30 +124,6 @@ func (r *OpenStackClusterReconciler) Reconcile(ctx context.Context, req ctrl.Req
}
scope := scope.NewWithLogger(clientScope, log)
- // Resolve and store referenced & dependent resources for the bastion
- if openStackCluster.Spec.Bastion != nil && openStackCluster.Spec.Bastion.Enabled {
- if openStackCluster.Status.Bastion == nil {
- openStackCluster.Status.Bastion = &infrav1.BastionStatus{}
- }
- changed, err := compute.ResolveReferencedMachineResources(scope, openStackCluster, &openStackCluster.Spec.Bastion.Instance, &openStackCluster.Status.Bastion.ReferencedResources)
- if err != nil {
- return reconcile.Result{}, err
- }
- if changed {
- // If the referenced resources have changed, we need to update the OpenStackCluster status now.
- return reconcile.Result{}, nil
- }
-
- changed, err = compute.ResolveDependentBastionResources(scope, openStackCluster, bastionName(cluster.Name))
- if err != nil {
- return reconcile.Result{}, err
- }
- if changed {
- // If the dependent resources have changed, we need to update the OpenStackCluster status now.
- return reconcile.Result{}, nil
- }
- }
-
// Handle deleted clusters
if !openStackCluster.DeletionTimestamp.IsZero() {
return r.reconcileDelete(ctx, scope, cluster, openStackCluster)
@@ -173,8 +150,17 @@ 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
+ // 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, openStackCluster); err != nil {
+ return reconcile.Result{}, err
+ }
+
+ if err := deleteBastion(scope, cluster, openStackCluster); err != nil {
+ return reconcile.Result{}, err
+ }
}
networkingService, err := networking.NewService(scope)
@@ -234,6 +220,32 @@ func contains(arr []string, target string) bool {
return false
}
+func resolveBastionResources(scope *scope.WithLogger, openStackCluster *infrav1.OpenStackCluster) (bool, error) {
+ if openStackCluster.Spec.Bastion != nil && openStackCluster.Spec.Bastion.Enabled {
+ if openStackCluster.Status.Bastion == nil {
+ openStackCluster.Status.Bastion = &infrav1.BastionStatus{}
+ }
+ changed, err := compute.ResolveReferencedMachineResources(scope, openStackCluster, &openStackCluster.Spec.Bastion.Instance, &openStackCluster.Status.Bastion.ReferencedResources)
+ if err != nil {
+ return false, err
+ }
+ if changed {
+ // If the referenced resources have changed, we need to update the OpenStackCluster status now.
+ return true, nil
+ }
+
+ changed, err = compute.ResolveDependentBastionResources(scope, openStackCluster, bastionName(openStackCluster.Name))
+ if err != nil {
+ return false, err
+ }
+ if changed {
+ // If the dependent resources have changed, we need to update the OpenStackCluster status now.
+ return true, nil
+ }
+ }
+ return false, nil
+}
+
func deleteBastion(scope *scope.WithLogger, cluster *clusterv1.Cluster, openStackCluster *infrav1.OpenStackCluster) error {
scope.Logger().Info("Deleting Bastion")
@@ -307,7 +319,7 @@ func deleteBastion(scope *scope.WithLogger, cluster *clusterv1.Cluster, openStac
openStackCluster.Status.Bastion.DependentResources.Ports = nil
}
- scope.Logger().Info("Deleted Bastion for cluster %s", cluster.Name)
+ scope.Logger().Info("Deleted Bastion")
openStackCluster.Status.Bastion = nil
delete(openStackCluster.ObjectMeta.Annotations, BastionInstanceHashAnnotation)
@@ -335,8 +347,11 @@ func reconcileNormal(scope *scope.WithLogger, cluster *clusterv1.Cluster, openSt
}
result, err := reconcileBastion(scope, cluster, openStackCluster)
- if err != nil || !reflect.DeepEqual(result, reconcile.Result{}) {
- return result, err
+ if err != nil {
+ return reconcile.Result{}, err
+ }
+ if result != nil {
+ return *result, nil
}
availabilityZones, err := computeService.GetAvailabilityZones()
@@ -366,102 +381,126 @@ func reconcileNormal(scope *scope.WithLogger, cluster *clusterv1.Cluster, openSt
return reconcile.Result{}, nil
}
-func reconcileBastion(scope *scope.WithLogger, cluster *clusterv1.Cluster, openStackCluster *infrav1.OpenStackCluster) (ctrl.Result, 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 reconcile.Result{}, deleteBastion(scope, cluster, openStackCluster)
+ changed, err := resolveBastionResources(scope, openStackCluster)
+ if err != nil {
+ return nil, err
+ }
+ if changed {
+ return &reconcile.Result{}, nil
}
- // If ports options aren't in the status, we'll re-trigger the reconcile to get them
- // via adopting the referenced resources.
- if len(openStackCluster.Status.Bastion.ReferencedResources.Ports) == 0 {
- return reconcile.Result{}, nil
+ // No Bastion defined
+ if openStackCluster.Spec.Bastion == nil || !openStackCluster.Spec.Bastion.Enabled {
+ // 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 reconcile.Result{}, err
+ return nil, err
}
networkingService, err := networking.NewService(scope)
if err != nil {
- return reconcile.Result{}, err
+ return nil, err
}
instanceSpec, err := bastionToInstanceSpec(openStackCluster, cluster)
if err != nil {
- return reconcile.Result{}, err
+ return nil, err
}
clusterName := fmt.Sprintf("%s-%s", cluster.Namespace, cluster.Name)
+
bastionHash, err := compute.HashInstanceSpec(instanceSpec)
if err != nil {
- return reconcile.Result{}, fmt.Errorf("failed computing bastion hash from instance spec: %w", err)
+ return nil, fmt.Errorf("failed computing bastion hash from instance spec: %w", err)
}
if bastionHashHasChanged(bastionHash, openStackCluster.ObjectMeta.Annotations) {
if err := deleteBastion(scope, cluster, openStackCluster); err != nil {
- return ctrl.Result{}, 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
}
err = getOrCreateBastionPorts(openStackCluster, networkingService, cluster.Name)
if err != nil {
handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to get or create ports for bastion: %w", err))
- return ctrl.Result{}, 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.DependentResources.Ports)
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 reconcile.Result{}, err
+ return nil, 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 reconcile.Result{}, err
+ return nil, err
}
}
if instanceStatus == nil {
instanceStatus, err = computeService.CreateInstance(openStackCluster, instanceSpec, bastionPortIDs)
if err != nil {
- return reconcile.Result{}, fmt.Errorf("failed to create bastion: %w", err)
+ 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)
- annotations.AddAnnotations(openStackCluster, map[string]string{BastionInstanceHashAnnotation: bastionHash})
// Make sure that bastion instance has a valid state
switch instanceStatus.State() {
case infrav1.InstanceStateError:
- return ctrl.Result{}, fmt.Errorf("failed to reconcile bastion, instance state is ERROR")
+ 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 ctrl.Result{RequeueAfter: waitForBuildingInstanceToReconcile}, nil
+ return &reconcile.Result{RequeueAfter: waitForBuildingInstanceToReconcile}, nil
case infrav1.InstanceStateDeleted:
- // This should normally be handled by deleteBastion
- openStackCluster.Status.Bastion = nil
- return ctrl.Result{}, nil
+ // 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 ctrl.Result{}, err
+ return nil, err
}
+
+ return bastionAddFloatingIP(openStackCluster, clusterName, port, networkingService)
+}
+
+func bastionAddFloatingIP(openStackCluster *infrav1.OpenStackCluster, clusterName 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 ctrl.Result{}, fmt.Errorf("failed to get floating IP for bastion port: %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 ctrl.Result{}, nil
+ return nil, nil
}
var floatingIP *string
@@ -477,17 +516,17 @@ func reconcileBastion(scope *scope.WithLogger, cluster *clusterv1.Cluster, openS
fp, err = networkingService.GetOrCreateFloatingIP(openStackCluster, openStackCluster, clusterName, floatingIP)
if err != nil {
handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to get or create floating IP for bastion: %w", err))
- return ctrl.Result{}, 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 ctrl.Result{}, fmt.Errorf("failed to associate floating IP with bastion: %w", err)
+ return nil, fmt.Errorf("failed to associate floating IP with bastion: %w", err)
}
- return ctrl.Result{}, nil
+ return nil, nil
}
func bastionToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, cluster *clusterv1.Cluster) (*compute.InstanceSpec, error) {
diff --git a/controllers/openstackcluster_controller_test.go b/controllers/openstackcluster_controller_test.go
index 5ab69b2d77..3f3ec703d7 100644
--- a/controllers/openstackcluster_controller_test.go
+++ b/controllers/openstackcluster_controller_test.go
@@ -302,7 +302,7 @@ var _ = Describe("OpenStackCluster controller", func() {
},
}))
Expect(err).To(BeNil())
- Expect(res).To(Equal(reconcile.Result{}))
+ 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")
@@ -387,7 +387,7 @@ var _ = Describe("OpenStackCluster controller", func() {
},
}))
Expect(err).To(BeNil())
- Expect(res).To(Equal(reconcile.Result{}))
+ Expect(res).To(BeNil())
})
It("should requeue until bastion becomes active", func() {
testCluster.SetName("requeue-bastion")
@@ -466,7 +466,7 @@ var _ = Describe("OpenStackCluster controller", func() {
},
}))
Expect(err).To(BeNil())
- Expect(res).To(Equal(reconcile.Result{RequeueAfter: waitForBuildingInstanceToReconcile}))
+ 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")
From acd9297400f8c34f016b2c92178c7cf4c5218a06 Mon Sep 17 00:00:00 2001
From: Jan Gutter
Date: Sun, 17 Mar 2024 12:46:42 +0000
Subject: [PATCH 131/180] Fix accidental parsing of password
When clouds.yaml gets parsed by `env.rc`, the `yq` command
is accidentally parsing the contents of the password
variable.
Under most circumstances the password contents is detected
correctly as a string. This fixes failures when the
password is accidentally parseable as a yaml structure.
More info at:
https://mikefarah.gitbook.io/yq/operators/env-variable-operators
---
templates/env.rc | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/templates/env.rc b/templates/env.rc
index 4e0f083dd4..5289f2a87e 100755
--- a/templates/env.rc
+++ b/templates/env.rc
@@ -115,7 +115,7 @@ else
if [[ "$CAPO_PASSWORD" = "" || "$CAPO_PASSWORD" = "null" ]]; then
CAPO_OPENSTACK_CLOUD_YAML_SELECTED_CLOUD_B64=$(echo "${CAPO_OPENSTACK_CLOUD_YAML_CONTENT}" | yq e .clouds.${CAPO_CLOUD} - | yq e '{"clouds": {"'${CAPO_CLOUD}'": . }}' - | b64encode)
else
- CAPO_OPENSTACK_CLOUD_YAML_SELECTED_CLOUD_B64=$(echo "${CAPO_OPENSTACK_CLOUD_YAML_CONTENT}" | yq e .clouds.${CAPO_CLOUD} - | PASSWORD=${CAPO_PASSWORD} yq e '.auth.password = env(PASSWORD)' - | yq e '{"clouds": {"'${CAPO_CLOUD}'": . }}' - | b64encode)
+ CAPO_OPENSTACK_CLOUD_YAML_SELECTED_CLOUD_B64=$(echo "${CAPO_OPENSTACK_CLOUD_YAML_CONTENT}" | yq e .clouds.${CAPO_CLOUD} - | PASSWORD=${CAPO_PASSWORD} yq e '.auth.password = strenv(PASSWORD)' - | yq e '{"clouds": {"'${CAPO_CLOUD}'": . }}' - | b64encode)
fi
fi
export OPENSTACK_CLOUD_YAML_B64="${CAPO_OPENSTACK_CLOUD_YAML_SELECTED_CLOUD_B64}"
From 6f8ac4f6b418951590af343e6c71a3e3770aedaf Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Mon, 18 Mar 2024 15:13:54 +0000
Subject: [PATCH 132/180] Fix a race when updating status before reconcile
completes
We were ignoring any update which only touched the status. This code has
been there an extremely long time, and was originally copied from CAPA.
Unfortunately this introduces a race for recently added code which sets
port status and exits the reconcile early for transactional safety.
---
controllers/openstackcluster_controller.go | 20 +-------------------
controllers/openstackmachine_controller.go | 21 +--------------------
2 files changed, 2 insertions(+), 39 deletions(-)
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index b34f0f4201..2e21fa4a1d 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -20,7 +20,6 @@ import (
"context"
"errors"
"fmt"
- "reflect"
"time"
"github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
@@ -43,9 +42,7 @@ 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/v1beta1"
@@ -823,22 +820,7 @@ func (r *OpenStackClusterReconciler) SetupWithManager(ctx context.Context, mgr c
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 {
diff --git a/controllers/openstackmachine_controller.go b/controllers/openstackmachine_controller.go
index 97f234b6ad..a5d6475c5f 100644
--- a/controllers/openstackmachine_controller.go
+++ b/controllers/openstackmachine_controller.go
@@ -21,7 +21,6 @@ import (
"encoding/base64"
"errors"
"fmt"
- "reflect"
"time"
"github.com/go-logr/logr"
@@ -45,9 +44,7 @@ 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/v1beta1"
@@ -212,23 +209,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"))),
From 567469e7d0cd978d79a63366875ae23ef46885dd Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Tue, 12 Mar 2024 17:56:24 +0000
Subject: [PATCH 133/180] Deduplicate AdoptMachinePorts and AdoptBastionPorts
Both of these methods rely on ReferencedMachineResources and
DependentMachineResources, so they can be easily refactored to have a
common implementation.
---
controllers/openstackcluster_controller.go | 5 +-
controllers/openstackmachine_controller.go | 4 +-
.../services/compute/dependent_resources.go | 19 +-
.../compute/dependent_resources_test.go | 219 ------------------
pkg/cloud/services/networking/port.go | 89 +------
pkg/cloud/services/networking/port_test.go | 158 ++++++++++++-
6 files changed, 172 insertions(+), 322 deletions(-)
delete mode 100644 pkg/cloud/services/compute/dependent_resources_test.go
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index 2e21fa4a1d..f091a66c46 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -231,7 +231,10 @@ func resolveBastionResources(scope *scope.WithLogger, openStackCluster *infrav1.
return true, nil
}
- changed, err = compute.ResolveDependentBastionResources(scope, openStackCluster, bastionName(openStackCluster.Name))
+ changed, err = compute.AdoptDependentMachineResources(scope,
+ bastionName(openStackCluster.Name),
+ &openStackCluster.Status.Bastion.ReferencedResources,
+ &openStackCluster.Status.Bastion.DependentResources)
if err != nil {
return false, err
}
diff --git a/controllers/openstackmachine_controller.go b/controllers/openstackmachine_controller.go
index a5d6475c5f..f33b5c4c30 100644
--- a/controllers/openstackmachine_controller.go
+++ b/controllers/openstackmachine_controller.go
@@ -160,8 +160,8 @@ func (r *OpenStackMachineReconciler) Reconcile(ctx context.Context, req ctrl.Req
return reconcile.Result{}, nil
}
- // Resolve and store dependent resources
- changed, err = compute.ResolveDependentMachineResources(scope, openStackMachine)
+ // Adopt any existing dependent resources
+ changed, err = compute.AdoptDependentMachineResources(scope, openStackMachine.Name, &openStackMachine.Status.ReferencedResources, &openStackMachine.Status.DependentResources)
if err != nil {
return reconcile.Result{}, err
}
diff --git a/pkg/cloud/services/compute/dependent_resources.go b/pkg/cloud/services/compute/dependent_resources.go
index 7a7d4e5b65..a9b1c49dc8 100644
--- a/pkg/cloud/services/compute/dependent_resources.go
+++ b/pkg/cloud/services/compute/dependent_resources.go
@@ -22,24 +22,11 @@ import (
"sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
)
-func ResolveDependentMachineResources(scope *scope.WithLogger, openStackMachine *infrav1.OpenStackMachine) (changed bool, err error) {
- changed = false
-
- networkingService, err := networking.NewService(scope)
- if err != nil {
- return changed, err
- }
-
- return networkingService.AdoptMachinePorts(scope, openStackMachine, openStackMachine.Status.ReferencedResources.Ports)
-}
-
-func ResolveDependentBastionResources(scope *scope.WithLogger, openStackCluster *infrav1.OpenStackCluster, bastionName string) (changed bool, err error) {
- changed = false
-
+func AdoptDependentMachineResources(scope *scope.WithLogger, baseName string, referencedResources *infrav1.ReferencedMachineResources, dependentResources *infrav1.DependentMachineResources) (bool, error) {
networkingService, err := networking.NewService(scope)
if err != nil {
- return changed, err
+ return false, err
}
- return networkingService.AdoptBastionPorts(scope, openStackCluster, bastionName)
+ return networkingService.AdoptPorts(scope, baseName, referencedResources.Ports, dependentResources)
}
diff --git a/pkg/cloud/services/compute/dependent_resources_test.go b/pkg/cloud/services/compute/dependent_resources_test.go
deleted file mode 100644
index e25caba053..0000000000
--- a/pkg/cloud/services/compute/dependent_resources_test.go
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
-Copyright 2024 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 compute
-
-import (
- "testing"
-
- "github.com/go-logr/logr/testr"
- "github.com/golang/mock/gomock"
- "github.com/google/go-cmp/cmp"
- . "github.com/onsi/gomega"
- metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-
- infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
- "sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
-)
-
-func Test_ResolveDependentMachineResources(t *testing.T) {
- const networkID = "5e8e0d3b-7f3d-4f3e-8b3f-3e3e3e3e3e3e"
- const portID = "78e0d3b-7f3d-4f3e-8b3f-3e3e3e3e3e3e"
-
- tests := []struct {
- testName string
- openStackCluster *infrav1.OpenStackCluster
- openStackMachineStatus infrav1.OpenStackMachineStatus
- want *infrav1.DependentMachineResources
- wantErr bool
- }{
- {
- testName: "no Network ID yet and no ports in status",
- openStackCluster: &infrav1.OpenStackCluster{},
- want: &infrav1.DependentMachineResources{},
- wantErr: false,
- },
- {
- testName: "Network ID set but no ports in status",
- openStackCluster: &infrav1.OpenStackCluster{
- Status: infrav1.OpenStackClusterStatus{
- Network: &infrav1.NetworkStatusWithSubnets{
- NetworkStatus: infrav1.NetworkStatus{
- ID: networkID,
- },
- },
- },
- },
- want: &infrav1.DependentMachineResources{},
- wantErr: false,
- },
- {
- testName: "Network ID set and ports in status",
- openStackCluster: &infrav1.OpenStackCluster{
- Status: infrav1.OpenStackClusterStatus{
- Network: &infrav1.NetworkStatusWithSubnets{
- NetworkStatus: infrav1.NetworkStatus{
- ID: networkID,
- },
- },
- },
- },
- openStackMachineStatus: infrav1.OpenStackMachineStatus{
- DependentResources: infrav1.DependentMachineResources{
- Ports: []infrav1.PortStatus{
- {
- ID: portID,
- },
- },
- },
- },
- want: &infrav1.DependentMachineResources{
- Ports: []infrav1.PortStatus{
- {
- ID: portID,
- },
- },
- },
- wantErr: false,
- },
- }
- for _, tt := range tests {
- t.Run(tt.testName, func(t *testing.T) {
- g := NewWithT(t)
- log := testr.New(t)
- mockCtrl := gomock.NewController(t)
- mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "")
-
- defaultOpenStackMachine := &infrav1.OpenStackMachine{
- ObjectMeta: metav1.ObjectMeta{
- Name: "test",
- },
- Status: tt.openStackMachineStatus,
- }
-
- _, err := ResolveDependentMachineResources(scope.NewWithLogger(mockScopeFactory, log), defaultOpenStackMachine)
- if tt.wantErr {
- g.Expect(err).Error()
- return
- }
-
- g.Expect(&defaultOpenStackMachine.Status.DependentResources).To(Equal(tt.want), cmp.Diff(&defaultOpenStackMachine.Status.DependentResources, tt.want))
- })
- }
-}
-
-func TestResolveDependentBastionResources(t *testing.T) {
- const networkID = "5e8e0d3b-7f3d-4f3e-8b3f-3e3e3e3e3e3e"
- const portID = "78e0d3b-7f3d-4f3e-8b3f-3e3e3e3e3e3e"
- const bastionName = "bastion"
-
- tests := []struct {
- testName string
- openStackCluster *infrav1.OpenStackCluster
- want *infrav1.DependentMachineResources
- wantErr bool
- }{
- {
- testName: "no Network ID yet and no ports in status",
- openStackCluster: &infrav1.OpenStackCluster{
- Spec: infrav1.OpenStackClusterSpec{
- Bastion: &infrav1.Bastion{
- Enabled: true,
- },
- },
- },
- want: &infrav1.DependentMachineResources{},
- wantErr: false,
- },
- {
- testName: "Network ID set but no ports in status",
- openStackCluster: &infrav1.OpenStackCluster{
- Spec: infrav1.OpenStackClusterSpec{
- Bastion: &infrav1.Bastion{
- Enabled: true,
- },
- },
- Status: infrav1.OpenStackClusterStatus{
- Network: &infrav1.NetworkStatusWithSubnets{
- NetworkStatus: infrav1.NetworkStatus{
- ID: networkID,
- },
- },
- },
- },
- want: &infrav1.DependentMachineResources{},
- },
- {
- testName: "Network ID set and ports in status",
- openStackCluster: &infrav1.OpenStackCluster{
- Spec: infrav1.OpenStackClusterSpec{
- Bastion: &infrav1.Bastion{
- Enabled: true,
- },
- },
- Status: infrav1.OpenStackClusterStatus{
- Bastion: &infrav1.BastionStatus{
- DependentResources: infrav1.DependentMachineResources{
- Ports: []infrav1.PortStatus{
- {
- ID: portID,
- },
- },
- },
- },
- Network: &infrav1.NetworkStatusWithSubnets{
- NetworkStatus: infrav1.NetworkStatus{
- ID: networkID,
- },
- },
- },
- },
- want: &infrav1.DependentMachineResources{
- Ports: []infrav1.PortStatus{
- {
- ID: portID,
- },
- },
- },
- },
- }
- for _, tt := range tests {
- t.Run(tt.testName, func(t *testing.T) {
- g := NewWithT(t)
- log := testr.New(t)
- mockCtrl := gomock.NewController(t)
- mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "")
-
- _, err := ResolveDependentBastionResources(scope.NewWithLogger(mockScopeFactory, log), tt.openStackCluster, bastionName)
- if tt.wantErr {
- g.Expect(err).Error()
- return
- }
-
- defaultOpenStackCluster := &infrav1.OpenStackCluster{
- ObjectMeta: metav1.ObjectMeta{
- Name: "test",
- },
- Spec: tt.openStackCluster.Spec,
- Status: tt.openStackCluster.Status,
- }
-
- if tt.openStackCluster.Status.Bastion != nil {
- g.Expect(&defaultOpenStackCluster.Status.Bastion.DependentResources).To(Equal(tt.want), cmp.Diff(&defaultOpenStackCluster.Status.Bastion.DependentResources, tt.want))
- }
- })
- }
-}
diff --git a/pkg/cloud/services/networking/port.go b/pkg/cloud/services/networking/port.go
index b5d5aee5a1..bdd01b0ef9 100644
--- a/pkg/cloud/services/networking/port.go
+++ b/pkg/cloud/services/networking/port.go
@@ -569,104 +569,36 @@ func (s *Service) IsTrunkExtSupported() (trunknSupported bool, err error) {
return true, nil
}
-// AdoptMachinePorts checks if the ports are in ready condition. If not, it'll try to adopt them
-// by checking if they exist and if they do, it'll add them to the OpenStackMachine status.
-// A port is searched by name and network ID and has to be unique.
-// If the port is not found, it'll be ignored because it'll be created after the adoption.
-func (s *Service) AdoptMachinePorts(scope *scope.WithLogger, openStackMachine *infrav1.OpenStackMachine, desiredPorts []infrav1.PortOpts) (changed bool, err error) {
+// AdoptPorts looks for ports in desiredPorts which were previously created, and adds them to dependentResources.Ports.
+// A port matches if it has the same name and network ID as the desired port.
+func (s *Service) AdoptPorts(scope *scope.WithLogger, baseName string, desiredPorts []infrav1.PortOpts, dependentResources *infrav1.DependentMachineResources) (changed bool, err error) {
changed = false
- // We can skip adoption if the instance is ready because OpenStackMachine is immutable once ready
- // or if the ports are already in the status
- if openStackMachine.Status.Ready && len(openStackMachine.Status.DependentResources.Ports) == len(desiredPorts) {
- scope.Logger().V(5).Info("OpenStackMachine is ready, skipping the adoption of ports")
- return changed, nil
- }
-
- scope.Logger().Info("Adopting ports for OpenStackMachine", "name", openStackMachine.Name)
-
- // We create ports in order and adopt them in order in PortsStatus.
- // This means that if port N doesn't exist we know that ports >N don't exist.
- // We can therefore stop searching for ports once we find one that doesn't exist.
- for i, port := range desiredPorts {
- // check if the port is in status first and if it is, skip it
- if i < len(openStackMachine.Status.DependentResources.Ports) {
- scope.Logger().V(5).Info("Port already in status, skipping it", "port index", i)
- continue
- }
-
- portOpts := &desiredPorts[i]
- portName := GetPortName(openStackMachine.Name, portOpts, i)
- ports, err := s.client.ListPort(ports.ListOpts{
- Name: portName,
- NetworkID: port.Network.ID,
- })
- if err != nil {
- return changed, fmt.Errorf("searching for existing port for machine %s: %v", openStackMachine.Name, err)
- }
- // if the port is not found, we stop the adoption of ports since the rest of the ports will not be found either
- // and will be created after the adoption
- if len(ports) == 0 {
- scope.Logger().V(5).Info("Port not found, stopping the adoption of ports", "port index", i)
- return changed, nil
- }
- if len(ports) > 1 {
- return changed, fmt.Errorf("found multiple ports with name %s", portName)
- }
-
- // The desired port was found, so we add it to the status
- scope.Logger().V(5).Info("Port found, adding it to the status", "port index", i)
- openStackMachine.Status.DependentResources.Ports = append(openStackMachine.Status.DependentResources.Ports, infrav1.PortStatus{ID: ports[0].ID})
- changed = true
- }
-
- return changed, nil
-}
-
-// AdopteBastionPorts tries to adopt the ports for the bastion instance by checking if they exist and if they do,
-// it'll add them to the OpenStackCluster status.
-// A port is searched by name and network ID and has to be unique.
-// If the port is not found, it'll be ignored because it'll be created after the adoption.
-func (s *Service) AdoptBastionPorts(scope *scope.WithLogger, openStackCluster *infrav1.OpenStackCluster, bastionName string) (changed bool, err error) {
- changed = false
-
- if openStackCluster.Status.Network == nil {
- scope.Logger().V(5).Info("Network status is nil, skipping the adoption of ports")
- return changed, nil
- }
-
- if openStackCluster.Status.Bastion == nil {
- scope.Logger().V(5).Info("Bastion status is nil, initializing it")
- openStackCluster.Status.Bastion = &infrav1.BastionStatus{}
- }
-
- desiredPorts := openStackCluster.Status.Bastion.ReferencedResources.Ports
-
// We can skip adoption if the ports are already in the status
- if len(desiredPorts) == len(openStackCluster.Status.Bastion.DependentResources.Ports) {
+ if len(desiredPorts) == len(dependentResources.Ports) {
return changed, nil
}
- scope.Logger().Info("Adopting bastion ports for OpenStackCluster", "name", openStackCluster.Name)
+ scope.Logger().V(5).Info("Adopting ports")
// We create ports in order and adopt them in order in PortsStatus.
// This means that if port N doesn't exist we know that ports >N don't exist.
// We can therefore stop searching for ports once we find one that doesn't exist.
for i, port := range desiredPorts {
// check if the port is in status first and if it is, skip it
- if i < len(openStackCluster.Status.Bastion.DependentResources.Ports) {
+ if i < len(dependentResources.Ports) {
scope.Logger().V(5).Info("Port already in status, skipping it", "port index", i)
continue
}
portOpts := &desiredPorts[i]
- portName := GetPortName(bastionName, portOpts, i)
+ portName := GetPortName(baseName, portOpts, i)
ports, err := s.client.ListPort(ports.ListOpts{
Name: portName,
NetworkID: port.Network.ID,
})
if err != nil {
- return changed, fmt.Errorf("searching for existing port for bastion %s: %v", bastionName, err)
+ return changed, fmt.Errorf("searching for existing port %s in network %s: %v", portName, port.Network.ID, err)
}
// if the port is not found, we stop the adoption of ports since the rest of the ports will not be found either
// and will be created after the adoption
@@ -679,8 +611,9 @@ func (s *Service) AdoptBastionPorts(scope *scope.WithLogger, openStackCluster *i
}
// The desired port was found, so we add it to the status
- scope.Logger().V(5).Info("Port found, adding it to the status", "port index", i)
- openStackCluster.Status.Bastion.DependentResources.Ports = append(openStackCluster.Status.Bastion.DependentResources.Ports, infrav1.PortStatus{ID: ports[0].ID})
+ portID := ports[0].ID
+ scope.Logger().Info("Adopted previously created port which was not in status", "port index", i, "portID", portID)
+ dependentResources.Ports = append(dependentResources.Ports, infrav1.PortStatus{ID: portID})
changed = true
}
diff --git a/pkg/cloud/services/networking/port_test.go b/pkg/cloud/services/networking/port_test.go
index c6bb99c95d..e281125689 100644
--- a/pkg/cloud/services/networking/port_test.go
+++ b/pkg/cloud/services/networking/port_test.go
@@ -38,9 +38,6 @@ import (
)
func Test_CreatePort(t *testing.T) {
- mockCtrl := gomock.NewController(t)
- defer mockCtrl.Finish()
-
// Arbitrary GUIDs used in the tests
netID := "7fd24ceb-788a-441f-ad0a-d8e2f5d31a1d"
subnetID1 := "d9c88a6d-0b8c-48ff-8f0e-8d85a078c194"
@@ -412,6 +409,9 @@ func Test_CreatePort(t *testing.T) {
for i := range tests {
tt := tests[i]
t.Run(tt.name, func(t *testing.T) {
+ mockCtrl := gomock.NewController(t)
+ defer mockCtrl.Finish()
+
g := NewWithT(t)
mockClient := mock.NewMockNetworkClient(mockCtrl)
tt.expect(mockClient.EXPECT())
@@ -437,9 +437,6 @@ func Test_CreatePort(t *testing.T) {
}
func TestService_normalizePorts(t *testing.T) {
- mockCtrl := gomock.NewController(t)
- defer mockCtrl.Finish()
-
const (
defaultNetworkID = "3c66f3ca-2d26-4d9d-ae3b-568f54129773"
defaultSubnetID = "d8dbba89-8c39-4192-a571-e702fca35bac"
@@ -775,6 +772,8 @@ func TestService_normalizePorts(t *testing.T) {
g := NewWithT(t)
log := testr.New(t)
+ mockCtrl := gomock.NewController(t)
+ defer mockCtrl.Finish()
mockClient := mock.NewMockNetworkClient(mockCtrl)
if tt.expectNetwork != nil {
tt.expectNetwork(mockClient.EXPECT())
@@ -837,3 +836,150 @@ func Test_getPortName(t *testing.T) {
})
}
}
+
+func Test_AdoptPorts(t *testing.T) {
+ const (
+ networkID1 = "5e8e0d3b-7f3d-4f3e-8b3f-3e3e3e3e3e3e"
+ networkID2 = "0a4ff38e-1e03-4b4e-994c-c8ae38a2915e"
+ networkID3 = "bd22ea65-53de-4585-bb6f-b0a84d0085d1"
+ portID1 = "78e0d3b-7f3d-4f3e-8b3f-3e3e3e3e3e3e"
+ portID2 = "a838209b-389a-47a0-9161-3d6919891074"
+ )
+
+ tests := []struct {
+ testName string
+ desiredPorts []infrav1.PortOpts
+ dependentResources infrav1.DependentMachineResources
+ expect func(*mock.MockNetworkClientMockRecorder)
+ want infrav1.DependentMachineResources
+ wantErr bool
+ }{
+ {
+ testName: "No desired ports",
+ },
+ {
+ testName: "desired port already in status: no-op",
+ desiredPorts: []infrav1.PortOpts{
+ {Network: &infrav1.NetworkFilter{ID: networkID1}},
+ },
+ dependentResources: infrav1.DependentMachineResources{
+ Ports: []infrav1.PortStatus{
+ {
+ ID: portID1,
+ },
+ },
+ },
+ want: infrav1.DependentMachineResources{
+ Ports: []infrav1.PortStatus{
+ {
+ ID: portID1,
+ },
+ },
+ },
+ },
+ {
+ testName: "desired port not in status, exists: adopt",
+ desiredPorts: []infrav1.PortOpts{
+ {Network: &infrav1.NetworkFilter{ID: networkID1}},
+ },
+ expect: func(m *mock.MockNetworkClientMockRecorder) {
+ m.ListPort(ports.ListOpts{Name: "test-machine-0", NetworkID: networkID1}).
+ Return([]ports.Port{{ID: portID1}}, nil)
+ },
+ want: infrav1.DependentMachineResources{
+ Ports: []infrav1.PortStatus{
+ {
+ ID: portID1,
+ },
+ },
+ },
+ },
+ {
+ testName: "desired port not in status, does not exist: ignore",
+ desiredPorts: []infrav1.PortOpts{
+ {Network: &infrav1.NetworkFilter{ID: networkID1}},
+ },
+ expect: func(m *mock.MockNetworkClientMockRecorder) {
+ m.ListPort(ports.ListOpts{Name: "test-machine-0", NetworkID: networkID1}).
+ Return(nil, nil)
+ },
+ want: infrav1.DependentMachineResources{},
+ },
+ {
+ testName: "2 desired ports, first in status, second exists: adopt second",
+ desiredPorts: []infrav1.PortOpts{
+ {Network: &infrav1.NetworkFilter{ID: networkID1}},
+ {Network: &infrav1.NetworkFilter{ID: networkID2}},
+ },
+ dependentResources: infrav1.DependentMachineResources{
+ Ports: []infrav1.PortStatus{
+ {
+ ID: portID1,
+ },
+ },
+ },
+ expect: func(m *mock.MockNetworkClientMockRecorder) {
+ m.ListPort(ports.ListOpts{Name: "test-machine-1", NetworkID: networkID2}).
+ Return([]ports.Port{{ID: portID2}}, nil)
+ },
+ want: infrav1.DependentMachineResources{
+ Ports: []infrav1.PortStatus{
+ {ID: portID1},
+ {ID: portID2},
+ },
+ },
+ },
+ {
+ testName: "3 desired ports, first in status, second does not exist: ignore, do no look for third",
+ desiredPorts: []infrav1.PortOpts{
+ {Network: &infrav1.NetworkFilter{ID: networkID1}},
+ {Network: &infrav1.NetworkFilter{ID: networkID2}},
+ {Network: &infrav1.NetworkFilter{ID: networkID3}},
+ },
+ dependentResources: infrav1.DependentMachineResources{
+ Ports: []infrav1.PortStatus{
+ {
+ ID: portID1,
+ },
+ },
+ },
+ expect: func(m *mock.MockNetworkClientMockRecorder) {
+ m.ListPort(ports.ListOpts{Name: "test-machine-1", NetworkID: networkID2}).
+ Return(nil, nil)
+ },
+ want: infrav1.DependentMachineResources{
+ Ports: []infrav1.PortStatus{
+ {ID: portID1},
+ },
+ },
+ },
+ }
+ for i := range tests {
+ tt := &tests[i]
+ t.Run(tt.testName, func(t *testing.T) {
+ g := NewWithT(t)
+ log := testr.New(t)
+
+ mockCtrl := gomock.NewController(t)
+ mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "")
+ mockClient := mock.NewMockNetworkClient(mockCtrl)
+ if tt.expect != nil {
+ tt.expect(mockClient.EXPECT())
+ }
+
+ s := Service{
+ client: mockClient,
+ }
+
+ _, err := s.AdoptPorts(scope.NewWithLogger(mockScopeFactory, log),
+ "test-machine",
+ tt.desiredPorts, &tt.dependentResources)
+ if tt.wantErr {
+ g.Expect(err).Error()
+ return
+ }
+
+ g.Expect(tt.dependentResources).To(Equal(tt.want), cmp.Diff(&tt.dependentResources, tt.want))
+ })
+ }
+}
From ad00c648c2f66f5fc61032d31d8922a178b39cc9 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Sat, 16 Mar 2024 19:43:42 +0000
Subject: [PATCH 134/180] Don't re-reconcile when adopting resources
Unlike referenced resources, which specify a future intent, adoption
only affects resources which have already been created. Successive
executions will produce the same output, so there is no need to
re-reconcile if we found orphaned resources.
Also we seem to be hitting this a lot in practise, most likely due to
the controller-runtime read-after-write cache inconsistency issue.
---
controllers/openstackcluster_controller.go | 6 +-----
controllers/openstackmachine_controller.go | 6 +-----
pkg/cloud/services/compute/dependent_resources.go | 4 ++--
pkg/cloud/services/networking/port.go | 15 ++++++---------
pkg/cloud/services/networking/port_test.go | 2 +-
5 files changed, 11 insertions(+), 22 deletions(-)
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index f091a66c46..6f0b9592b3 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -231,17 +231,13 @@ func resolveBastionResources(scope *scope.WithLogger, openStackCluster *infrav1.
return true, nil
}
- changed, err = compute.AdoptDependentMachineResources(scope,
+ err = compute.AdoptDependentMachineResources(scope,
bastionName(openStackCluster.Name),
&openStackCluster.Status.Bastion.ReferencedResources,
&openStackCluster.Status.Bastion.DependentResources)
if err != nil {
return false, err
}
- if changed {
- // If the dependent resources have changed, we need to update the OpenStackCluster status now.
- return true, nil
- }
}
return false, nil
}
diff --git a/controllers/openstackmachine_controller.go b/controllers/openstackmachine_controller.go
index f33b5c4c30..14eec5fd7b 100644
--- a/controllers/openstackmachine_controller.go
+++ b/controllers/openstackmachine_controller.go
@@ -161,14 +161,10 @@ func (r *OpenStackMachineReconciler) Reconcile(ctx context.Context, req ctrl.Req
}
// Adopt any existing dependent resources
- changed, err = compute.AdoptDependentMachineResources(scope, openStackMachine.Name, &openStackMachine.Status.ReferencedResources, &openStackMachine.Status.DependentResources)
+ err = compute.AdoptDependentMachineResources(scope, openStackMachine.Name, &openStackMachine.Status.ReferencedResources, &openStackMachine.Status.DependentResources)
if err != nil {
return reconcile.Result{}, err
}
- if changed {
- // If the dependent resources have changed, we need to update the OpenStackMachine status now.
- return reconcile.Result{}, nil
- }
// Handle deleted machines
if !openStackMachine.DeletionTimestamp.IsZero() {
diff --git a/pkg/cloud/services/compute/dependent_resources.go b/pkg/cloud/services/compute/dependent_resources.go
index a9b1c49dc8..1425c46fbf 100644
--- a/pkg/cloud/services/compute/dependent_resources.go
+++ b/pkg/cloud/services/compute/dependent_resources.go
@@ -22,10 +22,10 @@ import (
"sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
)
-func AdoptDependentMachineResources(scope *scope.WithLogger, baseName string, referencedResources *infrav1.ReferencedMachineResources, dependentResources *infrav1.DependentMachineResources) (bool, error) {
+func AdoptDependentMachineResources(scope *scope.WithLogger, baseName string, referencedResources *infrav1.ReferencedMachineResources, dependentResources *infrav1.DependentMachineResources) error {
networkingService, err := networking.NewService(scope)
if err != nil {
- return false, err
+ return err
}
return networkingService.AdoptPorts(scope, baseName, referencedResources.Ports, dependentResources)
diff --git a/pkg/cloud/services/networking/port.go b/pkg/cloud/services/networking/port.go
index bdd01b0ef9..b3fd46b3c2 100644
--- a/pkg/cloud/services/networking/port.go
+++ b/pkg/cloud/services/networking/port.go
@@ -571,12 +571,10 @@ func (s *Service) IsTrunkExtSupported() (trunknSupported bool, err error) {
// AdoptPorts looks for ports in desiredPorts which were previously created, and adds them to dependentResources.Ports.
// A port matches if it has the same name and network ID as the desired port.
-func (s *Service) AdoptPorts(scope *scope.WithLogger, baseName string, desiredPorts []infrav1.PortOpts, dependentResources *infrav1.DependentMachineResources) (changed bool, err error) {
- changed = false
-
+func (s *Service) AdoptPorts(scope *scope.WithLogger, baseName string, desiredPorts []infrav1.PortOpts, dependentResources *infrav1.DependentMachineResources) error {
// We can skip adoption if the ports are already in the status
if len(desiredPorts) == len(dependentResources.Ports) {
- return changed, nil
+ return nil
}
scope.Logger().V(5).Info("Adopting ports")
@@ -598,24 +596,23 @@ func (s *Service) AdoptPorts(scope *scope.WithLogger, baseName string, desiredPo
NetworkID: port.Network.ID,
})
if err != nil {
- return changed, fmt.Errorf("searching for existing port %s in network %s: %v", portName, port.Network.ID, err)
+ return fmt.Errorf("searching for existing port %s in network %s: %v", portName, port.Network.ID, err)
}
// if the port is not found, we stop the adoption of ports since the rest of the ports will not be found either
// and will be created after the adoption
if len(ports) == 0 {
scope.Logger().V(5).Info("Port not found, stopping the adoption of ports", "port index", i)
- return changed, nil
+ return nil
}
if len(ports) > 1 {
- return changed, fmt.Errorf("found multiple ports with name %s", portName)
+ return fmt.Errorf("found multiple ports with name %s", portName)
}
// The desired port was found, so we add it to the status
portID := ports[0].ID
scope.Logger().Info("Adopted previously created port which was not in status", "port index", i, "portID", portID)
dependentResources.Ports = append(dependentResources.Ports, infrav1.PortStatus{ID: portID})
- changed = true
}
- return changed, nil
+ return nil
}
diff --git a/pkg/cloud/services/networking/port_test.go b/pkg/cloud/services/networking/port_test.go
index e281125689..340d78ff91 100644
--- a/pkg/cloud/services/networking/port_test.go
+++ b/pkg/cloud/services/networking/port_test.go
@@ -971,7 +971,7 @@ func Test_AdoptPorts(t *testing.T) {
client: mockClient,
}
- _, err := s.AdoptPorts(scope.NewWithLogger(mockScopeFactory, log),
+ err := s.AdoptPorts(scope.NewWithLogger(mockScopeFactory, log),
"test-machine",
tt.desiredPorts, &tt.dependentResources)
if tt.wantErr {
From 750af594e967893ad328897785b91ffc21b0fbeb Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Sat, 16 Mar 2024 11:14:27 +0000
Subject: [PATCH 135/180] Fix premature attempt to resolve machine resources
We can't resolve machine resources until the cluster is initialised.
---
controllers/openstackmachine_controller.go | 54 +++++++++++--------
.../services/compute/referenced_resources.go | 11 +++-
2 files changed, 42 insertions(+), 23 deletions(-)
diff --git a/controllers/openstackmachine_controller.go b/controllers/openstackmachine_controller.go
index 14eec5fd7b..294959e410 100644
--- a/controllers/openstackmachine_controller.go
+++ b/controllers/openstackmachine_controller.go
@@ -150,29 +150,32 @@ func (r *OpenStackMachineReconciler) Reconcile(ctx context.Context, req ctrl.Req
}
scope := scope.NewWithLogger(clientScope, log)
+ clusterName := fmt.Sprintf("%s-%s", cluster.Namespace, cluster.Name)
+
+ // Handle deleted machines
+ if !openStackMachine.DeletionTimestamp.IsZero() {
+ return r.reconcileDelete(scope, clusterName, infraCluster, machine, openStackMachine)
+ }
+
+ // Handle non-deleted clusters
+ return r.reconcileNormal(ctx, scope, clusterName, infraCluster, machine, openStackMachine)
+}
+
+func resolveMachineResources(scope *scope.WithLogger, openStackCluster *infrav1.OpenStackCluster, openStackMachine *infrav1.OpenStackMachine) (bool, error) {
// Resolve and store referenced resources
- changed, err := compute.ResolveReferencedMachineResources(scope, infraCluster, &openStackMachine.Spec, &openStackMachine.Status.ReferencedResources)
+ changed, err := compute.ResolveReferencedMachineResources(scope,
+ openStackCluster,
+ &openStackMachine.Spec, &openStackMachine.Status.ReferencedResources)
if err != nil {
- return reconcile.Result{}, err
+ return false, err
}
if changed {
// If the referenced resources have changed, we need to update the OpenStackMachine status now.
- return reconcile.Result{}, nil
+ return true, nil
}
// Adopt any existing dependent resources
- err = compute.AdoptDependentMachineResources(scope, openStackMachine.Name, &openStackMachine.Status.ReferencedResources, &openStackMachine.Status.DependentResources)
- if err != nil {
- return reconcile.Result{}, err
- }
-
- // Handle deleted machines
- if !openStackMachine.DeletionTimestamp.IsZero() {
- return r.reconcileDelete(scope, cluster, infraCluster, machine, openStackMachine)
- }
-
- // Handle non-deleted clusters
- return r.reconcileNormal(ctx, scope, cluster, infraCluster, machine, openStackMachine)
+ return false, compute.AdoptDependentMachineResources(scope, openStackMachine.Name, &openStackMachine.Status.ReferencedResources, &openStackMachine.Status.DependentResources)
}
func patchMachine(ctx context.Context, patchHelper *patch.Helper, openStackMachine *infrav1.OpenStackMachine, machine *clusterv1.Machine, options ...patch.Option) error {
@@ -227,11 +230,9 @@ func (r *OpenStackMachineReconciler) SetupWithManager(ctx context.Context, mgr c
Complete(r)
}
-func (r *OpenStackMachineReconciler) reconcileDelete(scope *scope.WithLogger, cluster *clusterv1.Cluster, openStackCluster *infrav1.OpenStackCluster, machine *clusterv1.Machine, openStackMachine *infrav1.OpenStackMachine) (ctrl.Result, error) { //nolint:unparam
+func (r *OpenStackMachineReconciler) reconcileDelete(scope *scope.WithLogger, clusterName 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
@@ -242,6 +243,13 @@ func (r *OpenStackMachineReconciler) reconcileDelete(scope *scope.WithLogger, cl
return ctrl.Result{}, err
}
+ // We may have resources to adopt if the cluster is ready
+ if openStackCluster.Status.Ready && openStackCluster.Status.Network != nil {
+ if _, err := resolveMachineResources(scope, openStackCluster, openStackMachine); err != nil {
+ return ctrl.Result{}, err
+ }
+ }
+
if openStackCluster.Spec.APIServerLoadBalancer.IsEnabled() {
loadBalancerService, err := loadbalancer.NewService(scope)
if err != nil {
@@ -454,7 +462,7 @@ func (r *OpenStackMachineReconciler) reconcileDeleteFloatingAddressFromPool(scop
return r.Client.Update(context.Background(), claim)
}
-func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope *scope.WithLogger, cluster *clusterv1.Cluster, openStackCluster *infrav1.OpenStackCluster, machine *clusterv1.Machine, openStackMachine *infrav1.OpenStackMachine) (_ ctrl.Result, reterr error) {
+func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope *scope.WithLogger, clusterName 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.
@@ -469,12 +477,16 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope
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
}
+ if changed, err := resolveMachineResources(scope, openStackCluster, openStackMachine); changed || err != nil {
+ return ctrl.Result{}, err
+ }
+
// Make sure bootstrap data is available and populated.
if machine.Spec.Bootstrap.DataSecretName == nil {
scope.Logger().Info("Bootstrap data secret reference is not yet available")
@@ -487,8 +499,6 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope
}
scope.Logger().Info("Reconciling Machine")
- clusterName := fmt.Sprintf("%s-%s", cluster.ObjectMeta.Namespace, cluster.Name)
-
computeService, err := compute.NewService(scope)
if err != nil {
return ctrl.Result{}, err
diff --git a/pkg/cloud/services/compute/referenced_resources.go b/pkg/cloud/services/compute/referenced_resources.go
index 8fad1bf36b..ae967b19cc 100644
--- a/pkg/cloud/services/compute/referenced_resources.go
+++ b/pkg/cloud/services/compute/referenced_resources.go
@@ -17,6 +17,8 @@ limitations under the License.
package compute
import (
+ "fmt"
+
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"
@@ -61,8 +63,15 @@ func ResolveReferencedMachineResources(scope *scope.WithLogger, openStackCluster
changed = true
}
+ // ConstructPorts requires the cluster network to have been set. We only
+ // call this from places where we know it should have been set, but the
+ // cluster status is externally-provided data so we check it anyway.
+ if openStackCluster.Status.Network == nil {
+ return changed, fmt.Errorf("called ResolveReferencedMachineResources with nil OpenStackCluster.Status.Network")
+ }
+
// Network resources are required in order to get ports options.
- if len(resources.Ports) == 0 && openStackCluster.Status.Network != nil {
+ if len(resources.Ports) == 0 {
// For now we put this here but realistically an OpenStack administrator could enable/disable trunk
// support at any time, so we should probably check this on every reconcile.
trunkSupported, err := networkingService.IsTrunkExtSupported()
From c4e5c2a99503874e160154e091cf712788213566 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Tue, 19 Mar 2024 10:04:11 +0000
Subject: [PATCH 136/180] Remove security group rules from status
---
api/v1alpha5/conversion.go | 43 ---
api/v1alpha6/types_conversion.go | 47 +--
api/v1alpha7/openstackcluster_conversion.go | 4 -
api/v1alpha7/types_conversion.go | 80 +----
api/v1beta1/types.go | 53 ---
api/v1beta1/zz_generated.deepcopy.go | 63 +---
...re.cluster.x-k8s.io_openstackclusters.yaml | 156 ---------
docs/book/src/api/v1beta1/api.md | 147 --------
go.mod | 2 +-
.../services/networking/securitygroups.go | 226 ++++++------
.../networking/securitygroups_test.go | 329 +++++++++++-------
11 files changed, 311 insertions(+), 839 deletions(-)
diff --git a/api/v1alpha5/conversion.go b/api/v1alpha5/conversion.go
index ed0bbe4571..e01b164813 100644
--- a/api/v1alpha5/conversion.go
+++ b/api/v1alpha5/conversion.go
@@ -687,55 +687,12 @@ func Convert_v1alpha5_Bastion_To_v1beta1_Bastion(in *Bastion, out *infrav1.Basti
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
- out.Rules = make([]SecurityGroupRule, len(in.Rules))
- for i, rule := range in.Rules {
- out.Rules[i] = SecurityGroupRule{
- ID: rule.ID,
- Direction: rule.Direction,
- }
- if rule.Description != nil {
- out.Rules[i].Description = *rule.Description
- }
- if rule.EtherType != nil {
- out.Rules[i].EtherType = *rule.EtherType
- }
- if rule.PortRangeMin != nil {
- out.Rules[i].PortRangeMin = *rule.PortRangeMin
- }
- if rule.PortRangeMax != nil {
- out.Rules[i].PortRangeMax = *rule.PortRangeMax
- }
- if rule.Protocol != nil {
- out.Rules[i].Protocol = *rule.Protocol
- }
- if rule.RemoteGroupID != nil {
- out.Rules[i].RemoteGroupID = *rule.RemoteGroupID
- }
- if rule.RemoteIPPrefix != nil {
- out.Rules[i].RemoteIPPrefix = *rule.RemoteIPPrefix
- }
- }
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
- out.Rules = make([]infrav1.SecurityGroupRuleStatus, len(in.Rules))
- for i, rule := range in.Rules {
- out.Rules[i] = infrav1.SecurityGroupRuleStatus{
- ID: rule.ID,
- Description: pointer.String(rule.Description),
- Direction: rule.Direction,
- EtherType: pointer.String(rule.EtherType),
- PortRangeMin: pointer.Int(rule.PortRangeMin),
- PortRangeMax: pointer.Int(rule.PortRangeMax),
- Protocol: pointer.String(rule.Protocol),
- RemoteGroupID: pointer.String(rule.RemoteGroupID),
- RemoteIPPrefix: pointer.String(rule.RemoteIPPrefix),
- }
- }
-
return nil
}
diff --git a/api/v1alpha6/types_conversion.go b/api/v1alpha6/types_conversion.go
index c43f8a23ac..6ec354ecee 100644
--- a/api/v1alpha6/types_conversion.go
+++ b/api/v1alpha6/types_conversion.go
@@ -364,63 +364,18 @@ func restorev1alpha6SecurityGroup(previous *SecurityGroup, dst *SecurityGroup) {
return
}
- for i, rule := range previous.Rules {
- dst.Rules[i].SecurityGroupID = rule.SecurityGroupID
- }
+ 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
- out.Rules = make([]SecurityGroupRule, len(in.Rules))
- for i, rule := range in.Rules {
- out.Rules[i] = SecurityGroupRule{
- ID: rule.ID,
- Direction: rule.Direction,
- }
- if rule.Description != nil {
- out.Rules[i].Description = *rule.Description
- }
- if rule.EtherType != nil {
- out.Rules[i].EtherType = *rule.EtherType
- }
- if rule.PortRangeMin != nil {
- out.Rules[i].PortRangeMin = *rule.PortRangeMin
- }
- if rule.PortRangeMax != nil {
- out.Rules[i].PortRangeMax = *rule.PortRangeMax
- }
- if rule.Protocol != nil {
- out.Rules[i].Protocol = *rule.Protocol
- }
- if rule.RemoteGroupID != nil {
- out.Rules[i].RemoteGroupID = *rule.RemoteGroupID
- }
- if rule.RemoteIPPrefix != nil {
- out.Rules[i].RemoteIPPrefix = *rule.RemoteIPPrefix
- }
- }
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
- out.Rules = make([]infrav1.SecurityGroupRuleStatus, len(in.Rules))
- for i, rule := range in.Rules {
- out.Rules[i] = infrav1.SecurityGroupRuleStatus{
- ID: rule.ID,
- Description: pointer.String(rule.Description),
- Direction: rule.Direction,
- EtherType: pointer.String(rule.EtherType),
- PortRangeMin: pointer.Int(rule.PortRangeMin),
- PortRangeMax: pointer.Int(rule.PortRangeMax),
- Protocol: pointer.String(rule.Protocol),
- RemoteGroupID: pointer.String(rule.RemoteGroupID),
- RemoteIPPrefix: pointer.String(rule.RemoteIPPrefix),
- }
- }
-
return nil
}
diff --git a/api/v1alpha7/openstackcluster_conversion.go b/api/v1alpha7/openstackcluster_conversion.go
index cd31d29f7f..6f1f88e923 100644
--- a/api/v1alpha7/openstackcluster_conversion.go
+++ b/api/v1alpha7/openstackcluster_conversion.go
@@ -346,10 +346,6 @@ func restorev1alpha7ClusterStatus(previous *OpenStackClusterStatus, dst *OpenSta
}
func restorev1beta1ClusterStatus(previous *infrav1.OpenStackClusterStatus, dst *infrav1.OpenStackClusterStatus) {
- restorev1beta1SecurityGroupStatus(previous.ControlPlaneSecurityGroup, dst.ControlPlaneSecurityGroup)
- restorev1beta1SecurityGroupStatus(previous.WorkerSecurityGroup, dst.WorkerSecurityGroup)
- restorev1beta1SecurityGroupStatus(previous.BastionSecurityGroup, dst.BastionSecurityGroup)
-
// ReferencedResources have no equivalent in v1alpha7
if previous.Bastion != nil {
dst.Bastion.ReferencedResources = previous.Bastion.ReferencedResources
diff --git a/api/v1alpha7/types_conversion.go b/api/v1alpha7/types_conversion.go
index 7b966d1320..3c3d0629f2 100644
--- a/api/v1alpha7/types_conversion.go
+++ b/api/v1alpha7/types_conversion.go
@@ -18,7 +18,6 @@ package v1alpha7
import (
apiconversion "k8s.io/apimachinery/pkg/conversion"
- "k8s.io/utils/pointer"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/optional"
@@ -40,9 +39,7 @@ func restorev1alpha7SecurityGroup(previous *SecurityGroup, dst *SecurityGroup) {
return
}
- for i, rule := range previous.Rules {
- dst.Rules[i].SecurityGroupID = rule.SecurityGroupID
- }
+ dst.Rules = previous.Rules
}
func Convert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in *SecurityGroupFilter, out *infrav1.SecurityGroupFilter, s apiconversion.Scope) error {
@@ -142,39 +139,6 @@ func Convert_v1beta1_RouterFilter_To_v1alpha7_RouterFilter(in *infrav1.RouterFil
return nil
}
-func restorev1beta1SecurityGroupStatus(previous *infrav1.SecurityGroupStatus, dst *infrav1.SecurityGroupStatus) {
- if previous == nil || dst == nil {
- return
- }
-
- for i := range dst.Rules {
- dstRule := &dst.Rules[i]
-
- // Conversion from scalar to *scalar is lossy for zero values. We need to restore only nil values.
- if dstRule.Description != nil && *dstRule.Description == "" {
- dstRule.Description = previous.Rules[i].Description
- }
- if dstRule.EtherType != nil && *dstRule.EtherType == "" {
- dstRule.EtherType = previous.Rules[i].EtherType
- }
- if dstRule.PortRangeMin != nil && *dstRule.PortRangeMin == 0 {
- dstRule.PortRangeMin = previous.Rules[i].PortRangeMin
- }
- if dstRule.PortRangeMax != nil && *dstRule.PortRangeMax == 0 {
- dstRule.PortRangeMax = previous.Rules[i].PortRangeMax
- }
- if dstRule.Protocol != nil && *dstRule.Protocol == "" {
- dstRule.Protocol = previous.Rules[i].Protocol
- }
- if dstRule.RemoteGroupID != nil && *dstRule.RemoteGroupID == "" {
- dstRule.RemoteGroupID = previous.Rules[i].RemoteGroupID
- }
- if dstRule.RemoteIPPrefix != nil && *dstRule.RemoteIPPrefix == "" {
- dstRule.RemoteIPPrefix = previous.Rules[i].RemoteIPPrefix
- }
- }
-}
-
/* PortOpts */
func restorev1alpha7Port(previous *PortOpts, dst *PortOpts) {
@@ -300,20 +264,6 @@ func Convert_v1beta1_PortOpts_To_v1alpha7_PortOpts(in *infrav1.PortOpts, out *Po
func Convert_v1alpha7_SecurityGroup_To_v1beta1_SecurityGroupStatus(in *SecurityGroup, out *infrav1.SecurityGroupStatus, _ apiconversion.Scope) error {
out.ID = in.ID
out.Name = in.Name
- out.Rules = make([]infrav1.SecurityGroupRuleStatus, len(in.Rules))
- for i, rule := range in.Rules {
- out.Rules[i] = infrav1.SecurityGroupRuleStatus{
- ID: rule.ID,
- Description: pointer.String(rule.Description),
- Direction: rule.Direction,
- EtherType: pointer.String(rule.EtherType),
- PortRangeMin: pointer.Int(rule.PortRangeMin),
- PortRangeMax: pointer.Int(rule.PortRangeMax),
- Protocol: pointer.String(rule.Protocol),
- RemoteGroupID: pointer.String(rule.RemoteGroupID),
- RemoteIPPrefix: pointer.String(rule.RemoteIPPrefix),
- }
- }
return nil
}
@@ -321,34 +271,6 @@ func Convert_v1alpha7_SecurityGroup_To_v1beta1_SecurityGroupStatus(in *SecurityG
func Convert_v1beta1_SecurityGroupStatus_To_v1alpha7_SecurityGroup(in *infrav1.SecurityGroupStatus, out *SecurityGroup, _ apiconversion.Scope) error {
out.ID = in.ID
out.Name = in.Name
- out.Rules = make([]SecurityGroupRule, len(in.Rules))
- for i, rule := range in.Rules {
- out.Rules[i] = SecurityGroupRule{
- ID: rule.ID,
- Direction: rule.Direction,
- }
- if rule.Description != nil {
- out.Rules[i].Description = *rule.Description
- }
- if rule.EtherType != nil {
- out.Rules[i].EtherType = *rule.EtherType
- }
- if rule.PortRangeMin != nil {
- out.Rules[i].PortRangeMin = *rule.PortRangeMin
- }
- if rule.PortRangeMax != nil {
- out.Rules[i].PortRangeMax = *rule.PortRangeMax
- }
- if rule.Protocol != nil {
- out.Rules[i].Protocol = *rule.Protocol
- }
- if rule.RemoteGroupID != nil {
- out.Rules[i].RemoteGroupID = *rule.RemoteGroupID
- }
- if rule.RemoteIPPrefix != nil {
- out.Rules[i].RemoteIPPrefix = *rule.RemoteIPPrefix
- }
- }
return nil
}
diff --git a/api/v1beta1/types.go b/api/v1beta1/types.go
index 94625b20db..b7950d294e 100644
--- a/api/v1beta1/types.go
+++ b/api/v1beta1/types.go
@@ -448,10 +448,6 @@ type SecurityGroupStatus struct {
// id of the security group
// +kubebuilder:validation:Required
ID string `json:"id"`
-
- // list of security group rules
- // +optional
- Rules []SecurityGroupRuleStatus `json:"rules,omitempty"`
}
// SecurityGroupRuleSpec represent the basic information of the associated OpenStack
@@ -514,55 +510,6 @@ type SecurityGroupRuleSpec struct {
RemoteManagedGroups []ManagedSecurityGroupName `json:"remoteManagedGroups,omitempty"`
}
-type SecurityGroupRuleStatus struct {
- // id of the security group rule
- // +kubebuilder:validation:Required
- ID string `json:"id"`
-
- // 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"`
-}
-
// +kubebuilder:validation:Enum=bastion;controlplane;worker
type ManagedSecurityGroupName string
diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go
index 73e1fb8368..9635d65ab9 100644
--- a/api/v1beta1/zz_generated.deepcopy.go
+++ b/api/v1beta1/zz_generated.deepcopy.go
@@ -652,17 +652,17 @@ func (in *OpenStackClusterStatus) DeepCopyInto(out *OpenStackClusterStatus) {
if in.ControlPlaneSecurityGroup != nil {
in, out := &in.ControlPlaneSecurityGroup, &out.ControlPlaneSecurityGroup
*out = new(SecurityGroupStatus)
- (*in).DeepCopyInto(*out)
+ **out = **in
}
if in.WorkerSecurityGroup != nil {
in, out := &in.WorkerSecurityGroup, &out.WorkerSecurityGroup
*out = new(SecurityGroupStatus)
- (*in).DeepCopyInto(*out)
+ **out = **in
}
if in.BastionSecurityGroup != nil {
in, out := &in.BastionSecurityGroup, &out.BastionSecurityGroup
*out = new(SecurityGroupStatus)
- (*in).DeepCopyInto(*out)
+ **out = **in
}
if in.Bastion != nil {
in, out := &in.Bastion, &out.Bastion
@@ -1336,66 +1336,9 @@ func (in *SecurityGroupRuleSpec) DeepCopy() *SecurityGroupRuleSpec {
return out
}
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *SecurityGroupRuleStatus) DeepCopyInto(out *SecurityGroupRuleStatus) {
- *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
- }
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecurityGroupRuleStatus.
-func (in *SecurityGroupRuleStatus) DeepCopy() *SecurityGroupRuleStatus {
- if in == nil {
- return nil
- }
- out := new(SecurityGroupRuleStatus)
- 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
- if in.Rules != nil {
- in, out := &in.Rules, &out.Rules
- *out = make([]SecurityGroupRuleStatus, len(*in))
- for i := range *in {
- (*in)[i].DeepCopyInto(&(*out)[i])
- }
- }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecurityGroupStatus.
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 f2e491f4b3..30ae084647 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -6651,58 +6651,6 @@ spec:
name:
description: name of the security group
type: string
- rules:
- description: list of security group rules
- items:
- 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
- id:
- description: id of the security group rule
- 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
- required:
- - direction
- - id
- type: object
- type: array
required:
- id
- name
@@ -6719,58 +6667,6 @@ spec:
name:
description: name of the security group
type: string
- rules:
- description: list of security group rules
- items:
- 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
- id:
- description: id of the security group rule
- 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
- required:
- - direction
- - id
- type: object
- type: array
required:
- id
- name
@@ -6926,58 +6822,6 @@ spec:
name:
description: name of the security group
type: string
- rules:
- description: list of security group rules
- items:
- 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
- id:
- description: id of the security group rule
- 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
- required:
- - direction
- - id
- type: object
- type: array
required:
- id
- name
diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md
index ae9159d5fb..2b12258bef 100644
--- a/docs/book/src/api/v1beta1/api.md
+++ b/docs/book/src/api/v1beta1/api.md
@@ -4365,139 +4365,6 @@ You can specify either remoteGroupID or remoteIPPrefix or remoteManagedGroups.
-SecurityGroupRuleStatus
-
-
-(Appears on:
-SecurityGroupStatus)
-
-
-
-
-
-
-| Field |
-Description |
-
-
-
-
-
-id
-
-string
-
- |
-
- id of the security group rule
- |
-
-
-
-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.
- |
-
-
-
SecurityGroupStatus
@@ -4538,20 +4405,6 @@ string
id of the security group
-
-
-rules
-
-
-[]SecurityGroupRuleStatus
-
-
- |
-
-(Optional)
- list of security group rules
- |
-
ServerGroupFilter
diff --git a/go.mod b/go.mod
index 50ebe0a6a8..c2bfc1a442 100644
--- a/go.mod
+++ b/go.mod
@@ -8,6 +8,7 @@ require (
github.com/golang/mock v1.6.0
github.com/google/go-cmp v0.6.0
github.com/google/gofuzz v1.2.0
+ github.com/google/uuid v1.3.1
github.com/gophercloud/gophercloud v1.7.0
github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56
github.com/hashicorp/go-version v1.4.0
@@ -80,7 +81,6 @@ require (
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect
github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2 // indirect
- github.com/google/uuid v1.3.1 // indirect
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect
github.com/hashicorp/go-uuid v1.0.3 // indirect
diff --git a/pkg/cloud/services/networking/securitygroups.go b/pkg/cloud/services/networking/securitygroups.go
index 0b67e5fd92..76cc8e349e 100644
--- a/pkg/cloud/services/networking/securitygroups.go
+++ b/pkg/cloud/services/networking/securitygroups.go
@@ -18,6 +18,7 @@ package networking
import (
"fmt"
+ "slices"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/attributestags"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups"
@@ -45,52 +46,74 @@ func (s *Service) ReconcileSecurityGroups(openStackCluster *infrav1.OpenStackClu
return nil
}
+ bastionEnabled := openStackCluster.Spec.Bastion != nil && openStackCluster.Spec.Bastion.Enabled
+
secControlPlaneGroupName := getSecControlPlaneGroupName(clusterName)
secWorkerGroupName := getSecWorkerGroupName(clusterName)
- secGroupNames := map[string]string{
+ suffixToNameMap := map[string]string{
controlPlaneSuffix: secControlPlaneGroupName,
workerSuffix: secWorkerGroupName,
}
- if openStackCluster.Spec.Bastion != nil && openStackCluster.Spec.Bastion.Enabled {
+ if bastionEnabled {
secBastionGroupName := getSecBastionGroupName(clusterName)
- secGroupNames[bastionSuffix] = secBastionGroupName
+ suffixToNameMap[bastionSuffix] = secBastionGroupName
}
// create security groups first, because desired rules use group ids.
- for _, v := range secGroupNames {
- if err := s.createSecurityGroupIfNotExists(openStackCluster, v); err != nil {
+ observedSecGroupBySuffix := make(map[string]*groups.SecGroup)
+ for suffix, secGroupName := range suffixToNameMap {
+ group, err := s.getOrCreateSecurityGroup(openStackCluster, secGroupName)
+ if err != nil {
return err
}
+ observedSecGroupBySuffix[suffix] = group
+
+ normaliseTags := func(tags []string) []string {
+ tags = slices.Clone(tags)
+ slices.Sort(tags)
+ return slices.Compact(tags)
+ }
+
+ if !slices.Equal(normaliseTags(openStackCluster.Spec.Tags), normaliseTags(group.Tags)) {
+ _, err = s.client.ReplaceAllAttributesTags("security-groups", group.ID, attributestags.ReplaceAllOpts{
+ Tags: openStackCluster.Spec.Tags,
+ })
+ if err != nil {
+ return err
+ }
+ s.scope.Logger().V(6).Info("Updated tags for security group", "name", group.Name, "id", group.ID)
+ }
}
+
// create desired security groups
- desiredSecGroups, err := s.generateDesiredSecGroups(openStackCluster, secGroupNames)
+ desiredSecGroupsBySuffix, err := s.generateDesiredSecGroups(openStackCluster, suffixToNameMap, observedSecGroupBySuffix)
if err != nil {
return err
}
- observedSecGroups := make(map[string]*infrav1.SecurityGroupStatus)
- for k, desiredSecGroup := range desiredSecGroups {
- var err error
- observedSecGroups[k], err = s.getSecurityGroupByName(desiredSecGroup.Name)
+ for suffix := range desiredSecGroupsBySuffix {
+ desiredSecGroup := desiredSecGroupsBySuffix[suffix]
+ observedSecGroup, ok := observedSecGroupBySuffix[suffix]
+ if !ok {
+ // This should never happen
+ return fmt.Errorf("unable to reconcile security groups: security group %s not found", suffix)
+ }
+ err := s.reconcileGroupRules(&desiredSecGroup, observedSecGroup)
if err != nil {
return err
}
-
- if observedSecGroups[k].ID != "" {
- observedSecGroup, err := s.reconcileGroupRules(desiredSecGroup, *observedSecGroups[k])
- if err != nil {
- return err
- }
- observedSecGroups[k] = &observedSecGroup
- continue
- }
+ continue
}
- openStackCluster.Status.ControlPlaneSecurityGroup = observedSecGroups[controlPlaneSuffix]
- openStackCluster.Status.WorkerSecurityGroup = observedSecGroups[workerSuffix]
- openStackCluster.Status.BastionSecurityGroup = observedSecGroups[bastionSuffix]
+ openStackCluster.Status.ControlPlaneSecurityGroup = convertOSSecGroupToConfigSecGroup(observedSecGroupBySuffix[controlPlaneSuffix])
+ openStackCluster.Status.WorkerSecurityGroup = convertOSSecGroupToConfigSecGroup(observedSecGroupBySuffix[workerSuffix])
+ if bastionEnabled {
+ openStackCluster.Status.BastionSecurityGroup = convertOSSecGroupToConfigSecGroup(observedSecGroupBySuffix[bastionSuffix])
+ } else {
+ openStackCluster.Status.BastionSecurityGroup = nil
+ }
return nil
}
@@ -111,24 +134,22 @@ type resolvedSecurityGroupRuleSpec struct {
RemoteIPPrefix string `json:"remoteIPPrefix,omitempty"`
}
-func (r resolvedSecurityGroupRuleSpec) Matches(other infrav1.SecurityGroupRuleStatus) bool {
- return r.Description == *other.Description &&
+func (r resolvedSecurityGroupRuleSpec) Matches(other rules.SecGroupRule) bool {
+ return r.Description == other.Description &&
r.Direction == other.Direction &&
- r.EtherType == *other.EtherType &&
- r.PortRangeMin == *other.PortRangeMin &&
- r.PortRangeMax == *other.PortRangeMax &&
- r.Protocol == *other.Protocol &&
- r.RemoteGroupID == *other.RemoteGroupID &&
- r.RemoteIPPrefix == *other.RemoteIPPrefix
+ r.EtherType == other.EtherType &&
+ r.PortRangeMin == other.PortRangeMin &&
+ r.PortRangeMax == other.PortRangeMax &&
+ r.Protocol == other.Protocol &&
+ r.RemoteGroupID == other.RemoteGroupID &&
+ r.RemoteIPPrefix == other.RemoteIPPrefix
}
-func (s *Service) generateDesiredSecGroups(openStackCluster *infrav1.OpenStackCluster, secGroupNames map[string]string) (map[string]securityGroupSpec, error) {
+func (s *Service) generateDesiredSecGroups(openStackCluster *infrav1.OpenStackCluster, suffixToNameMap map[string]string, observedSecGroupsBySuffix map[string]*groups.SecGroup) (map[string]securityGroupSpec, error) {
if openStackCluster.Spec.ManagedSecurityGroups == nil {
return nil, nil
}
- desiredSecGroups := make(map[string]securityGroupSpec)
-
var secControlPlaneGroupID string
var secWorkerGroupID string
var secBastionGroupID string
@@ -139,12 +160,13 @@ func (s *Service) generateDesiredSecGroups(openStackCluster *infrav1.OpenStackCl
// For now, we only reference the control plane and worker security groups.
remoteManagedGroups := make(map[string]string)
- for i, v := range secGroupNames {
- secGroup, err := s.getSecurityGroupByName(v)
- if err != nil {
- return desiredSecGroups, err
+ for suffix := range suffixToNameMap {
+ secGroup, ok := observedSecGroupsBySuffix[suffix]
+ if !ok {
+ // This should never happen, as we should have created the security group earlier in this reconcile if it does not exist.
+ return nil, fmt.Errorf("unable to generate desired security group rules: security group for %s not found", suffix)
}
- switch i {
+ switch suffix {
case controlPlaneSuffix:
secControlPlaneGroupID = secGroup.ID
remoteManagedGroups[controlPlaneSuffix] = secControlPlaneGroupID
@@ -182,17 +204,19 @@ func (s *Service) generateDesiredSecGroups(openStackCluster *infrav1.OpenStackCl
// Instead, we append the rules for allNodes to the control plane and worker security groups.
allNodesRules, err := getAllNodesRules(remoteManagedGroups, openStackCluster.Spec.ManagedSecurityGroups.AllNodesSecurityGroupRules)
if err != nil {
- return desiredSecGroups, err
+ return nil, err
}
controlPlaneRules = append(controlPlaneRules, allNodesRules...)
workerRules = append(workerRules, allNodesRules...)
+ desiredSecGroupsBySuffix := make(map[string]securityGroupSpec)
+
if openStackCluster.Spec.Bastion != nil && openStackCluster.Spec.Bastion.Enabled {
controlPlaneRules = append(controlPlaneRules, getSGControlPlaneSSH(secBastionGroupID)...)
workerRules = append(workerRules, getSGWorkerSSH(secBastionGroupID)...)
- desiredSecGroups[bastionSuffix] = securityGroupSpec{
- Name: secGroupNames[bastionSuffix],
+ desiredSecGroupsBySuffix[bastionSuffix] = securityGroupSpec{
+ Name: suffixToNameMap[bastionSuffix],
Rules: append(
[]resolvedSecurityGroupRuleSpec{
{
@@ -209,16 +233,16 @@ func (s *Service) generateDesiredSecGroups(openStackCluster *infrav1.OpenStackCl
}
}
- desiredSecGroups[controlPlaneSuffix] = securityGroupSpec{
- Name: secGroupNames[controlPlaneSuffix],
+ desiredSecGroupsBySuffix[controlPlaneSuffix] = securityGroupSpec{
+ Name: suffixToNameMap[controlPlaneSuffix],
Rules: controlPlaneRules,
}
- desiredSecGroups[workerSuffix] = securityGroupSpec{
- Name: secGroupNames[workerSuffix],
+ desiredSecGroupsBySuffix[workerSuffix] = securityGroupSpec{
+ Name: suffixToNameMap[workerSuffix],
Rules: workerRules,
}
- return desiredSecGroups, nil
+ return desiredSecGroupsBySuffix, nil
}
// getAllNodesRules returns the rules for the allNodes security group that should be created.
@@ -345,7 +369,7 @@ func (s *Service) deleteSecurityGroup(openStackCluster *infrav1.OpenStackCluster
if err != nil {
return err
}
- if group.ID == "" {
+ if group == nil {
// nothing to do
return nil
}
@@ -361,7 +385,7 @@ func (s *Service) deleteSecurityGroup(openStackCluster *infrav1.OpenStackCluster
// reconcileGroupRules reconciles an already existing observed group by deleting rules not needed anymore and
// creating rules that are missing.
-func (s *Service) reconcileGroupRules(desired securityGroupSpec, observed infrav1.SecurityGroupStatus) (infrav1.SecurityGroupStatus, error) {
+func (s *Service) reconcileGroupRules(desired *securityGroupSpec, observed *groups.SecGroup) error {
var rulesToDelete []string
// fills rulesToDelete by calculating observed - desired
for _, observedRule := range observed.Rules {
@@ -382,7 +406,6 @@ func (s *Service) reconcileGroupRules(desired securityGroupSpec, observed infrav
}
rulesToCreate := []resolvedSecurityGroupRuleSpec{}
- reconciledRules := make([]infrav1.SecurityGroupRuleStatus, 0, len(desired.Rules))
// fills rulesToCreate by calculating desired - observed
// also adds rules which are in observed and desired to reconcileGroupRules.
for _, desiredRule := range desired.Rules {
@@ -394,7 +417,6 @@ func (s *Service) reconcileGroupRules(desired securityGroupSpec, observed infrav
for _, observedRule := range observed.Rules {
if r.Matches(observedRule) {
// add already existing rules to reconciledRules because we won't touch them anymore
- reconciledRules = append(reconciledRules, observedRule)
createRule = false
break
}
@@ -409,7 +431,7 @@ func (s *Service) reconcileGroupRules(desired securityGroupSpec, observed infrav
s.scope.Logger().V(6).Info("Deleting rule", "ID", rule, "name", observed.Name)
err := s.client.DeleteSecGroupRule(rule)
if err != nil {
- return infrav1.SecurityGroupStatus{}, err
+ return err
}
}
@@ -419,61 +441,44 @@ func (s *Service) reconcileGroupRules(desired securityGroupSpec, observed infrav
if r.RemoteGroupID == remoteGroupIDSelf {
r.RemoteGroupID = observed.ID
}
- newRule, err := s.createRule(observed.ID, r)
+ err := s.createRule(observed.ID, r)
if err != nil {
- return infrav1.SecurityGroupStatus{}, err
+ return err
}
- reconciledRules = append(reconciledRules, newRule)
}
- observed.Rules = reconciledRules
- if len(reconciledRules) == 0 {
- return infrav1.SecurityGroupStatus{}, nil
- }
-
- return observed, nil
+ return nil
}
-func (s *Service) createSecurityGroupIfNotExists(openStackCluster *infrav1.OpenStackCluster, groupName string) error {
+func (s *Service) getOrCreateSecurityGroup(openStackCluster *infrav1.OpenStackCluster, groupName string) (*groups.SecGroup, error) {
secGroup, err := s.getSecurityGroupByName(groupName)
if err != nil {
- return err
+ return nil, err
+ }
+ if secGroup != nil {
+ s.scope.Logger().V(6).Info("Reusing existing SecurityGroup", "name", groupName, "id", secGroup.ID)
+ return secGroup, nil
}
- if secGroup == nil || secGroup.ID == "" {
- s.scope.Logger().V(6).Info("Group doesn't exist, creating it", "name", groupName)
-
- createOpts := groups.CreateOpts{
- Name: groupName,
- Description: "Cluster API managed group",
- }
- s.scope.Logger().V(6).Info("Creating group", "name", groupName)
-
- group, err := s.client.CreateSecGroup(createOpts)
- if err != nil {
- record.Warnf(openStackCluster, "FailedCreateSecurityGroup", "Failed to create security group %s: %v", groupName, err)
- return err
- }
- if len(openStackCluster.Spec.Tags) > 0 {
- _, err = s.client.ReplaceAllAttributesTags("security-groups", group.ID, attributestags.ReplaceAllOpts{
- Tags: openStackCluster.Spec.Tags,
- })
- if err != nil {
- return err
- }
- }
+ s.scope.Logger().V(6).Info("Group doesn't exist, creating it", "name", groupName)
- record.Eventf(openStackCluster, "SuccessfulCreateSecurityGroup", "Created security group %s with id %s", groupName, group.ID)
- return nil
+ createOpts := groups.CreateOpts{
+ Name: groupName,
+ Description: "Cluster API managed group",
}
+ s.scope.Logger().V(6).Info("Creating group", "name", groupName)
- sInfo := fmt.Sprintf("Reuse Existing SecurityGroup %s with %s", groupName, secGroup.ID)
- s.scope.Logger().V(6).Info(sInfo)
+ group, err := s.client.CreateSecGroup(createOpts)
+ if err != nil {
+ record.Warnf(openStackCluster, "FailedCreateSecurityGroup", "Failed to create security group %s: %v", groupName, err)
+ return nil, err
+ }
- return nil
+ record.Eventf(openStackCluster, "SuccessfulCreateSecurityGroup", "Created security group %s with id %s", groupName, group.ID)
+ return group, nil
}
-func (s *Service) getSecurityGroupByName(name string) (*infrav1.SecurityGroupStatus, error) {
+func (s *Service) getSecurityGroupByName(name string) (*groups.SecGroup, error) {
opts := groups.ListOpts{
Name: name,
}
@@ -481,20 +486,20 @@ func (s *Service) getSecurityGroupByName(name string) (*infrav1.SecurityGroupSta
s.scope.Logger().V(6).Info("Attempting to fetch security group with", "name", name)
allGroups, err := s.client.ListSecGroup(opts)
if err != nil {
- return &infrav1.SecurityGroupStatus{}, err
+ return nil, err
}
switch len(allGroups) {
case 0:
- return &infrav1.SecurityGroupStatus{}, nil
+ return nil, nil
case 1:
- return convertOSSecGroupToConfigSecGroup(allGroups[0]), nil
+ return &allGroups[0], nil
}
- return &infrav1.SecurityGroupStatus{}, fmt.Errorf("more than one security group found named: %s", name)
+ return nil, fmt.Errorf("more than one security group found named: %s", name)
}
-func (s *Service) createRule(securityGroupID string, r resolvedSecurityGroupRuleSpec) (infrav1.SecurityGroupRuleStatus, error) {
+func (s *Service) createRule(securityGroupID string, r resolvedSecurityGroupRuleSpec) error {
dir := rules.RuleDirection(r.Direction)
proto := rules.RuleProtocol(r.Protocol)
etherType := rules.RuleEtherType(r.EtherType)
@@ -511,11 +516,11 @@ func (s *Service) createRule(securityGroupID string, r resolvedSecurityGroupRule
SecGroupID: securityGroupID,
}
s.scope.Logger().V(6).Info("Creating rule", "description", r.Description, "direction", dir, "portRangeMin", r.PortRangeMin, "portRangeMax", r.PortRangeMax, "proto", proto, "etherType", etherType, "remoteGroupID", r.RemoteGroupID, "remoteIPPrefix", r.RemoteIPPrefix, "securityGroupID", securityGroupID)
- rule, err := s.client.CreateSecGroupRule(createOpts)
+ _, err := s.client.CreateSecGroupRule(createOpts)
if err != nil {
- return infrav1.SecurityGroupRuleStatus{}, err
+ return err
}
- return convertOSSecGroupRuleToConfigSecGroupRule(*rule), nil
+ return nil
}
func getSecControlPlaneGroupName(clusterName string) string {
@@ -530,29 +535,10 @@ func getSecBastionGroupName(clusterName string) string {
return fmt.Sprintf("%s-cluster-%s-secgroup-%s", secGroupPrefix, clusterName, bastionSuffix)
}
-func convertOSSecGroupToConfigSecGroup(osSecGroup groups.SecGroup) *infrav1.SecurityGroupStatus {
- securityGroupRules := make([]infrav1.SecurityGroupRuleStatus, len(osSecGroup.Rules))
- for i, rule := range osSecGroup.Rules {
- securityGroupRules[i] = convertOSSecGroupRuleToConfigSecGroupRule(rule)
- }
+func convertOSSecGroupToConfigSecGroup(osSecGroup *groups.SecGroup) *infrav1.SecurityGroupStatus {
return &infrav1.SecurityGroupStatus{
- ID: osSecGroup.ID,
- Name: osSecGroup.Name,
- Rules: securityGroupRules,
- }
-}
-
-func convertOSSecGroupRuleToConfigSecGroupRule(osSecGroupRule rules.SecGroupRule) infrav1.SecurityGroupRuleStatus {
- return infrav1.SecurityGroupRuleStatus{
- ID: osSecGroupRule.ID,
- Direction: osSecGroupRule.Direction,
- Description: &osSecGroupRule.Description,
- EtherType: &osSecGroupRule.EtherType,
- PortRangeMin: &osSecGroupRule.PortRangeMin,
- PortRangeMax: &osSecGroupRule.PortRangeMax,
- Protocol: &osSecGroupRule.Protocol,
- RemoteGroupID: &osSecGroupRule.RemoteGroupID,
- RemoteIPPrefix: &osSecGroupRule.RemoteIPPrefix,
+ ID: osSecGroup.ID,
+ Name: osSecGroup.Name,
}
}
diff --git a/pkg/cloud/services/networking/securitygroups_test.go b/pkg/cloud/services/networking/securitygroups_test.go
index b88a81cd43..04d4ff870d 100644
--- a/pkg/cloud/services/networking/securitygroups_test.go
+++ b/pkg/cloud/services/networking/securitygroups_test.go
@@ -19,8 +19,11 @@ import (
"reflect"
"testing"
+ "github.com/go-logr/logr"
"github.com/go-logr/logr/testr"
"github.com/golang/mock/gomock"
+ "github.com/google/go-cmp/cmp"
+ "github.com/google/uuid"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules"
. "github.com/onsi/gomega"
@@ -224,18 +227,25 @@ func TestGetAllNodesRules(t *testing.T) {
}
func TestGenerateDesiredSecGroups(t *testing.T) {
- mockCtrl := gomock.NewController(t)
- defer mockCtrl.Finish()
-
secGroupNames := map[string]string{
"controlplane": "k8s-cluster-mycluster-secgroup-controlplane",
"worker": "k8s-cluster-mycluster-secgroup-worker",
}
+ observedSecGroupsBySuffix := map[string]*groups.SecGroup{
+ "controlplane": {
+ ID: "0",
+ Name: "k8s-cluster-mycluster-secgroup-controlplane",
+ },
+ "worker": {
+ ID: "1",
+ Name: "k8s-cluster-mycluster-secgroup-worker",
+ },
+ }
+
tests := []struct {
name string
openStackCluster *infrav1.OpenStackCluster
- mockExpect func(m *mock.MockNetworkClientMockRecorder)
// We could also test the exact rules that are returned, but that'll be a lot data to write out.
// For now we just make sure that the number of rules is correct.
expectedNumberSecurityGroupRules int
@@ -244,7 +254,6 @@ func TestGenerateDesiredSecGroups(t *testing.T) {
{
name: "Valid openStackCluster with unmanaged securityGroups",
openStackCluster: &infrav1.OpenStackCluster{},
- mockExpect: func(m *mock.MockNetworkClientMockRecorder) {},
expectedNumberSecurityGroupRules: 0,
wantErr: false,
},
@@ -255,20 +264,6 @@ func TestGenerateDesiredSecGroups(t *testing.T) {
ManagedSecurityGroups: &infrav1.ManagedSecurityGroups{},
},
},
- mockExpect: func(m *mock.MockNetworkClientMockRecorder) {
- m.ListSecGroup(groups.ListOpts{Name: "k8s-cluster-mycluster-secgroup-controlplane"}).Return([]groups.SecGroup{
- {
- ID: "0",
- Name: "k8s-cluster-mycluster-secgroup-controlplane",
- },
- }, nil)
- m.ListSecGroup(groups.ListOpts{Name: "k8s-cluster-mycluster-secgroup-worker"}).Return([]groups.SecGroup{
- {
- ID: "1",
- Name: "k8s-cluster-mycluster-secgroup-worker",
- },
- }, nil)
- },
expectedNumberSecurityGroupRules: 12,
wantErr: false,
},
@@ -288,20 +283,6 @@ func TestGenerateDesiredSecGroups(t *testing.T) {
},
},
},
- mockExpect: func(m *mock.MockNetworkClientMockRecorder) {
- m.ListSecGroup(groups.ListOpts{Name: "k8s-cluster-mycluster-secgroup-controlplane"}).Return([]groups.SecGroup{
- {
- ID: "0",
- Name: "k8s-cluster-mycluster-secgroup-controlplane",
- },
- }, nil)
- m.ListSecGroup(groups.ListOpts{Name: "k8s-cluster-mycluster-secgroup-worker"}).Return([]groups.SecGroup{
- {
- ID: "1",
- Name: "k8s-cluster-mycluster-secgroup-worker",
- },
- }, nil)
- },
expectedNumberSecurityGroupRules: 16,
wantErr: false,
},
@@ -321,26 +302,15 @@ func TestGenerateDesiredSecGroups(t *testing.T) {
},
},
},
- mockExpect: func(m *mock.MockNetworkClientMockRecorder) {
- m.ListSecGroup(groups.ListOpts{Name: "k8s-cluster-mycluster-secgroup-controlplane"}).Return([]groups.SecGroup{
- {
- ID: "0",
- Name: "k8s-cluster-mycluster-secgroup-controlplane",
- },
- }, nil)
- m.ListSecGroup(groups.ListOpts{Name: "k8s-cluster-mycluster-secgroup-worker"}).Return([]groups.SecGroup{
- {
- ID: "1",
- Name: "k8s-cluster-mycluster-secgroup-worker",
- },
- }, nil)
- },
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
+ mockCtrl := gomock.NewController(t)
+ defer mockCtrl.Finish()
+
g := NewWithT(t)
log := testr.New(t)
mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "")
@@ -349,9 +319,8 @@ func TestGenerateDesiredSecGroups(t *testing.T) {
if err != nil {
t.Fatalf("Failed to create service: %v", err)
}
- tt.mockExpect(mockScopeFactory.NetworkClient.EXPECT())
- gotSecurityGroups, err := s.generateDesiredSecGroups(tt.openStackCluster, secGroupNames)
+ gotSecurityGroups, err := s.generateDesiredSecGroups(tt.openStackCluster, secGroupNames, observedSecGroupsBySuffix)
if tt.wantErr {
g.Expect(err).To(HaveOccurred())
} else {
@@ -367,27 +336,35 @@ func TestGenerateDesiredSecGroups(t *testing.T) {
}
func TestReconcileGroupRules(t *testing.T) {
- mockCtrl := gomock.NewController(t)
- defer mockCtrl.Finish()
+ const (
+ sgID = "6260e813-af79-4592-8d1a-0f42dd26cc42"
+ sgRuleID = "52a532c4-2b44-4582-ba87-b64e62e19b1a"
+ sgLegacyRuleID = "a057dcc4-1535-469d-9d28-923cad9d4c56"
+ sgName = "k8s-cluster-mycluster-secgroup-controlplane"
+ )
tests := []struct {
- name string
- desiredSGSpecs securityGroupSpec
- observedSGStatus infrav1.SecurityGroupStatus
- mockExpect func(m *mock.MockNetworkClientMockRecorder)
- wantSGStatus infrav1.SecurityGroupStatus
+ name string
+ desiredSGSpec securityGroupSpec
+ observedSG groups.SecGroup
+ mockExpect func(m *mock.MockNetworkClientMockRecorder)
+ wantSGStatus infrav1.SecurityGroupStatus
}{
{
- name: "Empty desiredSGSpecs and observedSGStatus",
- desiredSGSpecs: securityGroupSpec{},
- observedSGStatus: infrav1.SecurityGroupStatus{},
- mockExpect: func(m *mock.MockNetworkClientMockRecorder) {},
- wantSGStatus: infrav1.SecurityGroupStatus{},
+ name: "Empty desiredSGSpec and observedSG",
+ desiredSGSpec: securityGroupSpec{},
+ observedSG: groups.SecGroup{
+ ID: sgID,
+ Name: sgName,
+ Rules: []rules.SecGroupRule{},
+ },
+ mockExpect: func(m *mock.MockNetworkClientMockRecorder) {},
+ wantSGStatus: infrav1.SecurityGroupStatus{},
},
{
- name: "Same desiredSGSpecs and observedSGStatus produces no changes",
- desiredSGSpecs: securityGroupSpec{
- Name: "k8s-cluster-mycluster-secgroup-controlplane",
+ name: "Same desiredSGSpec and observedSG produces no changes",
+ desiredSGSpec: securityGroupSpec{
+ Name: sgName,
Rules: []resolvedSecurityGroupRuleSpec{
{
Description: "Allow SSH",
@@ -401,46 +378,29 @@ func TestReconcileGroupRules(t *testing.T) {
},
},
},
- observedSGStatus: infrav1.SecurityGroupStatus{
- ID: "idSG",
- Name: "k8s-cluster-mycluster-secgroup-controlplane",
- Rules: []infrav1.SecurityGroupRuleStatus{
+ observedSG: groups.SecGroup{
+ ID: sgID,
+ Name: sgName,
+ Rules: []rules.SecGroupRule{
{
- Description: pointer.String("Allow SSH"),
+ Description: "Allow SSH",
Direction: "ingress",
- EtherType: pointer.String("IPv4"),
+ EtherType: "IPv4",
ID: "idSGRule",
- Protocol: pointer.String("tcp"),
- PortRangeMin: pointer.Int(22),
- PortRangeMax: pointer.Int(22),
- RemoteGroupID: pointer.String("1"),
- RemoteIPPrefix: pointer.String(""),
+ Protocol: "tcp",
+ PortRangeMin: 22,
+ PortRangeMax: 22,
+ RemoteGroupID: "1",
+ RemoteIPPrefix: "",
},
},
},
mockExpect: func(m *mock.MockNetworkClientMockRecorder) {},
- wantSGStatus: infrav1.SecurityGroupStatus{
- ID: "idSG",
- Name: "k8s-cluster-mycluster-secgroup-controlplane",
- Rules: []infrav1.SecurityGroupRuleStatus{
- {
- Description: pointer.String("Allow SSH"),
- Direction: "ingress",
- EtherType: pointer.String("IPv4"),
- ID: "idSGRule",
- Protocol: pointer.String("tcp"),
- PortRangeMin: pointer.Int(22),
- PortRangeMax: pointer.Int(22),
- RemoteGroupID: pointer.String("1"),
- RemoteIPPrefix: pointer.String(""),
- },
- },
- },
},
{
- name: "Different desiredSGSpecs and observedSGStatus produces changes",
- desiredSGSpecs: securityGroupSpec{
- Name: "k8s-cluster-mycluster-secgroup-controlplane",
+ name: "Different desiredSGSpec and observedSG produces changes",
+ desiredSGSpec: securityGroupSpec{
+ Name: sgName,
Rules: []resolvedSecurityGroupRuleSpec{
{
Description: "Allow SSH",
@@ -454,27 +414,27 @@ func TestReconcileGroupRules(t *testing.T) {
},
},
},
- observedSGStatus: infrav1.SecurityGroupStatus{
- ID: "idSG",
- Name: "k8s-cluster-mycluster-secgroup-controlplane",
- Rules: []infrav1.SecurityGroupRuleStatus{
+ observedSG: groups.SecGroup{
+ ID: sgID,
+ Name: sgName,
+ Rules: []rules.SecGroupRule{
{
- Description: pointer.String("Allow SSH legacy"),
+ ID: sgLegacyRuleID,
+ Description: "Allow SSH legacy",
Direction: "ingress",
- EtherType: pointer.String("IPv4"),
- ID: "idSGRuleLegacy",
- Protocol: pointer.String("tcp"),
- PortRangeMin: pointer.Int(222),
- PortRangeMax: pointer.Int(222),
- RemoteGroupID: pointer.String("2"),
- RemoteIPPrefix: pointer.String(""),
+ EtherType: "IPv4",
+ Protocol: "tcp",
+ PortRangeMin: 222,
+ PortRangeMax: 222,
+ RemoteGroupID: "2",
+ RemoteIPPrefix: "",
},
},
},
mockExpect: func(m *mock.MockNetworkClientMockRecorder) {
- m.DeleteSecGroupRule("idSGRuleLegacy").Return(nil)
+ m.DeleteSecGroupRule(sgLegacyRuleID).Return(nil)
m.CreateSecGroupRule(rules.CreateOpts{
- SecGroupID: "idSG",
+ SecGroupID: sgID,
Description: "Allow SSH",
Direction: "ingress",
EtherType: "IPv4",
@@ -483,7 +443,7 @@ func TestReconcileGroupRules(t *testing.T) {
PortRangeMax: 22,
RemoteGroupID: "1",
}).Return(&rules.SecGroupRule{
- ID: "idSGRule",
+ ID: sgRuleID,
Description: "Allow SSH",
Direction: "ingress",
EtherType: "IPv4",
@@ -493,28 +453,15 @@ func TestReconcileGroupRules(t *testing.T) {
RemoteGroupID: "1",
}, nil)
},
- wantSGStatus: infrav1.SecurityGroupStatus{
- ID: "idSG",
- Name: "k8s-cluster-mycluster-secgroup-controlplane",
- Rules: []infrav1.SecurityGroupRuleStatus{
- {
- Description: pointer.String("Allow SSH"),
- Direction: "ingress",
- EtherType: pointer.String("IPv4"),
- ID: "idSGRule",
- Protocol: pointer.String("tcp"),
- PortRangeMin: pointer.Int(22),
- PortRangeMax: pointer.Int(22),
- RemoteGroupID: pointer.String("1"),
- RemoteIPPrefix: pointer.String(""),
- },
- },
- },
},
}
- for _, tt := range tests {
+ for i := range tests {
+ tt := &tests[i]
t.Run(tt.name, func(t *testing.T) {
+ mockCtrl := gomock.NewController(t)
+ defer mockCtrl.Finish()
+
g := NewWithT(t)
log := testr.New(t)
mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "")
@@ -525,9 +472,131 @@ func TestReconcileGroupRules(t *testing.T) {
}
tt.mockExpect(mockScopeFactory.NetworkClient.EXPECT())
- sgStatus, err := s.reconcileGroupRules(tt.desiredSGSpecs, tt.observedSGStatus)
+ err = s.reconcileGroupRules(&tt.desiredSGSpec, &tt.observedSG)
g.Expect(err).To(BeNil())
- g.Expect(sgStatus).To(Equal(tt.wantSGStatus))
+ })
+ }
+}
+
+func TestService_ReconcileSecurityGroups(t *testing.T) {
+ const (
+ clusterName = "test-cluster"
+
+ controlPlaneSGName = "k8s-cluster-test-cluster-secgroup-controlplane"
+ workerSGName = "k8s-cluster-test-cluster-secgroup-worker"
+ bastionSGName = "k8s-cluster-test-cluster-secgroup-bastion"
+ )
+
+ tests := []struct {
+ name string
+ openStackClusterSpec infrav1.OpenStackClusterSpec
+ expectedClusterStatus infrav1.OpenStackClusterStatus
+ expect func(log logr.Logger, m *mock.MockNetworkClientMockRecorder)
+ wantErr bool
+ }{
+ {
+ name: "Do nothing if ManagedSecurityGroups is not enabled",
+ openStackClusterSpec: infrav1.OpenStackClusterSpec{},
+ expectedClusterStatus: infrav1.OpenStackClusterStatus{},
+ },
+ {
+ name: "Default control plane and worker security groups",
+ openStackClusterSpec: infrav1.OpenStackClusterSpec{
+ ManagedSecurityGroups: &infrav1.ManagedSecurityGroups{},
+ },
+ expect: func(log logr.Logger, m *mock.MockNetworkClientMockRecorder) {
+ m.ListSecGroup(groups.ListOpts{Name: controlPlaneSGName}).
+ Return([]groups.SecGroup{{ID: "0", Name: controlPlaneSGName}}, nil)
+ m.ListSecGroup(groups.ListOpts{Name: workerSGName}).
+ Return([]groups.SecGroup{{ID: "1", Name: workerSGName}}, nil)
+
+ // We expect a total of 12 rules to be created.
+ // Nothing actually looks at the generated
+ // rules, but we give them unique IDs anyway
+ m.CreateSecGroupRule(gomock.Any()).DoAndReturn(func(opts rules.CreateOpts) (*rules.SecGroupRule, error) {
+ log.Info("Created rule", "securityGroup", opts.SecGroupID, "description", opts.Description)
+ return &rules.SecGroupRule{ID: uuid.NewString()}, nil
+ }).Times(12)
+ },
+ expectedClusterStatus: infrav1.OpenStackClusterStatus{
+ ControlPlaneSecurityGroup: &infrav1.SecurityGroupStatus{
+ ID: "0",
+ Name: controlPlaneSGName,
+ },
+ WorkerSecurityGroup: &infrav1.SecurityGroupStatus{
+ ID: "1",
+ Name: workerSGName,
+ },
+ },
+ },
+ {
+ name: "Default control plane, worker, and bastion security groups",
+ openStackClusterSpec: infrav1.OpenStackClusterSpec{
+ Bastion: &infrav1.Bastion{
+ Enabled: true,
+ },
+ ManagedSecurityGroups: &infrav1.ManagedSecurityGroups{},
+ },
+ expect: func(log logr.Logger, m *mock.MockNetworkClientMockRecorder) {
+ m.ListSecGroup(groups.ListOpts{Name: controlPlaneSGName}).
+ Return([]groups.SecGroup{{ID: "0", Name: controlPlaneSGName}}, nil)
+ m.ListSecGroup(groups.ListOpts{Name: workerSGName}).
+ Return([]groups.SecGroup{{ID: "1", Name: workerSGName}}, nil)
+ m.ListSecGroup(groups.ListOpts{Name: bastionSGName}).
+ Return([]groups.SecGroup{{ID: "2", Name: bastionSGName}}, nil)
+
+ // We expect a total of 12 rules to be created.
+ // Nothing actually looks at the generated
+ // rules, but we give them unique IDs anyway
+ m.CreateSecGroupRule(gomock.Any()).DoAndReturn(func(opts rules.CreateOpts) (*rules.SecGroupRule, error) {
+ log.Info("Created rule", "securityGroup", opts.SecGroupID, "description", opts.Description)
+ return &rules.SecGroupRule{ID: uuid.NewString()}, nil
+ }).Times(17)
+ },
+ expectedClusterStatus: infrav1.OpenStackClusterStatus{
+ ControlPlaneSecurityGroup: &infrav1.SecurityGroupStatus{
+ ID: "0",
+ Name: controlPlaneSGName,
+ },
+ WorkerSecurityGroup: &infrav1.SecurityGroupStatus{
+ ID: "1",
+ Name: workerSGName,
+ },
+ BastionSecurityGroup: &infrav1.SecurityGroupStatus{
+ ID: "2",
+ Name: bastionSGName,
+ },
+ },
+ },
+ }
+ for i := range tests {
+ tt := &tests[i]
+ t.Run(tt.name, func(t *testing.T) {
+ mockCtrl := gomock.NewController(t)
+ defer mockCtrl.Finish()
+
+ g := NewWithT(t)
+ log := testr.New(t)
+ mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "")
+ scope := scope.NewWithLogger(mockScopeFactory, log)
+
+ s := &Service{
+ scope: scope,
+ client: mockScopeFactory.NetworkClient,
+ }
+ if tt.expect != nil {
+ tt.expect(log, mockScopeFactory.NetworkClient.EXPECT())
+ }
+ openStackCluster := &infrav1.OpenStackCluster{
+ Spec: tt.openStackClusterSpec,
+ }
+ err := s.ReconcileSecurityGroups(openStackCluster, clusterName)
+ if tt.wantErr {
+ g.Expect(err).ToNot(BeNil(), "ReconcileSecurityGroups")
+ } else {
+ g.Expect(err).To(BeNil(), "ReconcileSecurityGroups")
+ g.Expect(openStackCluster.Status).To(Equal(tt.expectedClusterStatus), cmp.Diff(openStackCluster.Status, tt.expectedClusterStatus))
+ }
})
}
}
From 24b7961f9227a9b7d6ff9914a3e8aa684c906c06 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Wed, 20 Mar 2024 11:42:20 +0000
Subject: [PATCH 137/180] Update FloatingIPPool to use v1beta1
Also make IdentityRef required, as it doesn't currently permit fallback
to cluster credentials.
---
api/v1alpha1/openstackfloatingippool_types.go | 18 ++---
api/v1alpha1/zz_generated.deepcopy.go | 16 ++--
...ter.x-k8s.io_openstackfloatingippools.yaml | 76 ++++++++++++++-----
.../openstackfloatingippool_controller.go | 7 +-
pkg/scope/provider.go | 12 +--
5 files changed, 76 insertions(+), 53 deletions(-)
diff --git a/api/v1alpha1/openstackfloatingippool_types.go b/api/v1alpha1/openstackfloatingippool_types.go
index fe3316e4af..b3b0ebfc2a 100644
--- a/api/v1alpha1/openstackfloatingippool_types.go
+++ b/api/v1alpha1/openstackfloatingippool_types.go
@@ -22,11 +22,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
- // We use v1alpha7 here rather than anything newer because as of writing
- // it is the newest API version we should no longer be making breaking
- // changes to. If we bump this we need to look carefully for resulting
- // CRD changes in v1alpha1 to ensure they are compatible.
- infrav1alpha7 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
)
const (
@@ -62,16 +58,12 @@ type OpenStackFloatingIPPoolSpec struct {
MaxIPs *int `json:"maxIPs,omitempty"`
// IdentityRef is a reference to a identity to be used when reconciling this pool.
- // +optional
- IdentityRef *infrav1alpha7.OpenStackIdentityReference `json:"identityRef,omitempty"`
+ // +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 infrav1alpha7.NetworkFilter `json:"floatingIPNetwork"`
-
- // The name of the cloud to use from the clouds secret
- // +optional
- CloudName string `json:"cloudName"`
+ FloatingIPNetwork infrav1.NetworkFilter `json:"floatingIPNetwork"`
// The stratergy to use for reclaiming floating ips when they are released from a machine
// +kubebuilder:validation:Optional
@@ -95,7 +87,7 @@ type OpenStackFloatingIPPoolStatus struct {
// floatingIPNetwork contains information about the network used for floating ips
// +optional
- FloatingIPNetwork *infrav1alpha7.NetworkStatus `json:"floatingIPNetwork,omitempty"`
+ FloatingIPNetwork *infrav1.NetworkStatus `json:"floatingIPNetwork,omitempty"`
Conditions clusterv1.Conditions `json:"conditions,omitempty"`
}
diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go
index 353d53b3b7..558d53bde3 100644
--- a/api/v1alpha1/zz_generated.deepcopy.go
+++ b/api/v1alpha1/zz_generated.deepcopy.go
@@ -22,8 +22,8 @@ package v1alpha1
import (
runtime "k8s.io/apimachinery/pkg/runtime"
- "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
- "sigs.k8s.io/cluster-api/api/v1beta1"
+ "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.
@@ -98,12 +98,8 @@ func (in *OpenStackFloatingIPPoolSpec) DeepCopyInto(out *OpenStackFloatingIPPool
*out = new(int)
**out = **in
}
- if in.IdentityRef != nil {
- in, out := &in.IdentityRef, &out.IdentityRef
- *out = new(v1alpha7.OpenStackIdentityReference)
- **out = **in
- }
- out.FloatingIPNetwork = in.FloatingIPNetwork
+ out.IdentityRef = in.IdentityRef
+ in.FloatingIPNetwork.DeepCopyInto(&out.FloatingIPNetwork)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenStackFloatingIPPoolSpec.
@@ -136,12 +132,12 @@ func (in *OpenStackFloatingIPPoolStatus) DeepCopyInto(out *OpenStackFloatingIPPo
}
if in.FloatingIPNetwork != nil {
in, out := &in.FloatingIPNetwork, &out.FloatingIPNetwork
- *out = new(v1alpha7.NetworkStatus)
+ *out = new(v1beta1.NetworkStatus)
(*in).DeepCopyInto(*out)
}
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])
}
diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackfloatingippools.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackfloatingippools.yaml
index e7677735be..75281a6f06 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackfloatingippools.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackfloatingippools.yaml
@@ -41,9 +41,6 @@ spec:
description: OpenStackFloatingIPPoolSpec defines the desired state of
OpenStackFloatingIPPool.
properties:
- cloudName:
- description: The name of the cloud to use from the clouds secret
- type: string
floatingIPNetwork:
description: FloatingIPNetwork is the external network to use for
floating ips, if there's only one external network it will be used
@@ -56,34 +53,77 @@ spec:
name:
type: string
notTags:
- type: string
+ 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:
- type: string
- projectId:
+ 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:
- type: string
+ 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:
- type: string
+ 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
identityRef:
description: IdentityRef is a reference to a identity to be used when
reconciling this pool.
properties:
- kind:
- description: |-
- Kind of the identity. Must be supported by the infrastructure
- provider and may be either cluster or namespace-scoped.
- minLength: 1
+ cloudName:
+ description: CloudName specifies the name of the entry in the
+ clouds.yaml file to use.
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.
+ 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:
- - kind
+ - cloudName
- name
type: object
maxIPs:
@@ -105,6 +145,8 @@ spec:
- Retain
- Delete
type: string
+ required:
+ - identityRef
type: object
status:
description: OpenStackFloatingIPPoolStatus defines the observed state
diff --git a/controllers/openstackfloatingippool_controller.go b/controllers/openstackfloatingippool_controller.go
index ac08dc9185..f002752111 100644
--- a/controllers/openstackfloatingippool_controller.go
+++ b/controllers/openstackfloatingippool_controller.go
@@ -41,11 +41,10 @@ import (
"sigs.k8s.io/controller-runtime/pkg/reconcile"
infrav1alpha1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha1"
- infrav1alpha7 "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/networking"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
- filterconvert "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/filterconvert/v1alpha7"
+ "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/filterconvert"
)
const (
@@ -402,7 +401,7 @@ func (r *OpenStackFloatingIPPoolReconciler) reconcileFloatingIPNetwork(scope *sc
}
netListOpts := external.ListOptsExt{
- ListOptsBuilder: filterconvert.NetworkFilterToListOpt(&pool.Spec.FloatingIPNetwork),
+ ListOptsBuilder: filterconvert.NetworkFilterToListOpts(&pool.Spec.FloatingIPNetwork),
External: pointer.Bool(true),
}
@@ -414,7 +413,7 @@ func (r *OpenStackFloatingIPPoolReconciler) reconcileFloatingIPNetwork(scope *sc
return fmt.Errorf("found multiple networks, expects filter to match one (result: %v)", networkList)
}
- pool.Status.FloatingIPNetwork = &infrav1alpha7.NetworkStatus{
+ pool.Status.FloatingIPNetwork = &infrav1.NetworkStatus{
ID: networkList[0].ID,
Name: networkList[0].Name,
Tags: networkList[0].Tags,
diff --git a/pkg/scope/provider.go b/pkg/scope/provider.go
index d20cee5bc2..f7aa449d76 100644
--- a/pkg/scope/provider.go
+++ b/pkg/scope/provider.go
@@ -106,15 +106,9 @@ func (f *providerScopeFactory) NewClientScopeFromCluster(ctx context.Context, ct
}
func (f *providerScopeFactory) NewClientScopeFromFloatingIPPool(ctx context.Context, ctrlClient client.Client, openstackFloatingIPPool *v1alpha1.OpenStackFloatingIPPool, defaultCACert []byte, logger logr.Logger) (Scope, error) {
- var cloud clientconfig.Cloud
- var caCert []byte
-
- if openstackFloatingIPPool.Spec.IdentityRef != nil {
- var err error
- cloud, caCert, err = getCloudFromSecret(ctx, ctrlClient, openstackFloatingIPPool.Namespace, openstackFloatingIPPool.Spec.IdentityRef.Name, openstackFloatingIPPool.Spec.CloudName)
- if err != nil {
- return nil, err
- }
+ cloud, caCert, err := getCloudFromSecret(ctx, ctrlClient, openstackFloatingIPPool.Namespace, openstackFloatingIPPool.Spec.IdentityRef.Name, openstackFloatingIPPool.Spec.IdentityRef.CloudName)
+ if err != nil {
+ return nil, err
}
if caCert == nil {
From 4cd4e9ff98195f622e9bddd91df450ddc2523e71 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Wed, 20 Mar 2024 11:41:37 +0000
Subject: [PATCH 138/180] Add .gitattributes to identify generated files to
GitHub
---
.gitattributes | 12 ++++++++++++
1 file changed, 12 insertions(+)
create mode 100644 .gitattributes
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
From ffa82b3783fc2285835804276aa7d3869933bdf3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20Dulko?=
Date: Thu, 14 Mar 2024 12:14:34 +0100
Subject: [PATCH 139/180] API: Cleanup Bastion
This commit works with .spec.bastion:
* makes availablityZone, floatingIP and instance pointers
* adds floatingIP IPv4 validation
* adds validation that if Bastion is enabled, instance cannot be null
---
api/v1alpha5/conversion.go | 8 ++-
api/v1alpha5/zz_generated.conversion.go | 8 +--
api/v1alpha6/openstackcluster_conversion.go | 50 ++++++++++++++----
api/v1alpha6/openstackmachine_conversion.go | 3 ++
api/v1alpha6/zz_generated.conversion.go | 8 +--
api/v1alpha7/openstackcluster_conversion.go | 52 +++++++++++++++----
api/v1alpha7/openstackmachine_conversion.go | 3 ++
api/v1alpha7/zz_generated.conversion.go | 8 +--
api/v1beta1/types.go | 20 ++++---
api/v1beta1/zz_generated.deepcopy.go | 16 +++++-
...re.cluster.x-k8s.io_openstackclusters.yaml | 16 +++++-
...er.x-k8s.io_openstackclustertemplates.yaml | 17 +++++-
controllers/openstackcluster_controller.go | 28 ++++++----
.../openstackcluster_controller_test.go | 26 ++++++----
docs/book/src/api/v1beta1/api.md | 10 ++--
.../topics/crd-changes/v1alpha7-to-v1beta1.md | 2 +
pkg/webhooks/openstackcluster_webhook_test.go | 8 +--
.../apivalidations/openstackcluster_test.go | 51 ++++++++++++++++++
18 files changed, 260 insertions(+), 74 deletions(-)
diff --git a/api/v1alpha5/conversion.go b/api/v1alpha5/conversion.go
index ed0bbe4571..6e45b44360 100644
--- a/api/v1alpha5/conversion.go
+++ b/api/v1alpha5/conversion.go
@@ -671,7 +671,9 @@ func Convert_v1beta1_Bastion_To_v1alpha5_Bastion(in *infrav1.Bastion, out *Basti
if err != nil {
return err
}
- in.FloatingIP = out.Instance.FloatingIP
+ if in.FloatingIP != nil {
+ out.Instance.FloatingIP = *in.FloatingIP
+ }
return nil
}
@@ -680,7 +682,9 @@ func Convert_v1alpha5_Bastion_To_v1beta1_Bastion(in *Bastion, out *infrav1.Basti
if err != nil {
return err
}
- in.Instance.FloatingIP = out.FloatingIP
+ if in.Instance.FloatingIP != "" {
+ out.FloatingIP = &in.Instance.FloatingIP
+ }
return nil
}
diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go
index 4d472de0be..de12e75f92 100644
--- a/api/v1alpha5/zz_generated.conversion.go
+++ b/api/v1alpha5/zz_generated.conversion.go
@@ -457,19 +457,19 @@ func Convert_v1beta1_AddressPair_To_v1alpha5_AddressPair(in *v1beta1.AddressPair
func autoConvert_v1alpha5_Bastion_To_v1beta1_Bastion(in *Bastion, out *v1beta1.Bastion, s conversion.Scope) error {
out.Enabled = in.Enabled
- if err := Convert_v1alpha5_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(&in.Instance, &out.Instance, s); err != nil {
+ // WARNING: in.Instance requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha5.OpenStackMachineSpec vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.OpenStackMachineSpec)
+ if err := optional.Convert_string_To_optional_String(&in.AvailabilityZone, &out.AvailabilityZone, s); err != nil {
return err
}
- out.AvailabilityZone = in.AvailabilityZone
return nil
}
func autoConvert_v1beta1_Bastion_To_v1alpha5_Bastion(in *v1beta1.Bastion, out *Bastion, s conversion.Scope) error {
out.Enabled = in.Enabled
- if err := Convert_v1beta1_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(&in.Instance, &out.Instance, s); err != nil {
+ // WARNING: in.Instance requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.OpenStackMachineSpec vs sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha5.OpenStackMachineSpec)
+ 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
}
diff --git a/api/v1alpha6/openstackcluster_conversion.go b/api/v1alpha6/openstackcluster_conversion.go
index 1241469587..14bffeb1fc 100644
--- a/api/v1alpha6/openstackcluster_conversion.go
+++ b/api/v1alpha6/openstackcluster_conversion.go
@@ -412,8 +412,13 @@ func Convert_v1alpha6_OpenStackClusterStatus_To_v1beta1_OpenStackClusterStatus(i
/* Bastion */
func restorev1beta1Bastion(previous **infrav1.Bastion, dst **infrav1.Bastion) {
- if *previous != nil && *dst != nil {
- restorev1beta1MachineSpec(&(*previous).Instance, &(*dst).Instance)
+ if *previous != nil {
+ if *dst != nil && (*previous).Instance != nil && (*dst).Instance != nil {
+ restorev1beta1MachineSpec((*previous).Instance, (*dst).Instance)
+ }
+
+ optional.RestoreString(&(*previous).FloatingIP, &(*dst).FloatingIP)
+ optional.RestoreString(&(*previous).AvailabilityZone, &(*dst).AvailabilityZone)
}
}
@@ -445,13 +450,30 @@ func Convert_v1alpha6_Bastion_To_v1beta1_Bastion(in *Bastion, out *infrav1.Basti
return err
}
- if in.Instance.ServerGroupID != "" {
- out.Instance.ServerGroup = &infrav1.ServerGroupFilter{ID: in.Instance.ServerGroupID}
- } else {
- out.Instance.ServerGroup = nil
+ if !reflect.ValueOf(in.Instance).IsZero() {
+ out.Instance = &infrav1.OpenStackMachineSpec{}
+
+ err = Convert_v1alpha6_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(&in.Instance, out.Instance, s)
+ if err != nil {
+ return err
+ }
+
+ if in.Instance.ServerGroupID != "" {
+ out.Instance.ServerGroup = &infrav1.ServerGroupFilter{ID: in.Instance.ServerGroupID}
+ } else {
+ out.Instance.ServerGroup = nil
+ }
+
+ err = optional.Convert_string_To_optional_String(&in.Instance.FloatingIP, &out.FloatingIP, s)
+ if err != nil {
+ return err
+ }
}
- out.FloatingIP = in.Instance.FloatingIP
+ // nil the Instance if it's basically an empty object.
+ if out.Instance != nil && reflect.ValueOf(*out.Instance).IsZero() {
+ out.Instance = nil
+ }
return nil
}
@@ -461,10 +483,16 @@ func Convert_v1beta1_Bastion_To_v1alpha6_Bastion(in *infrav1.Bastion, out *Basti
return err
}
- if in.Instance.ServerGroup != nil && in.Instance.ServerGroup.ID != "" {
- out.Instance.ServerGroupID = in.Instance.ServerGroup.ID
+ if in.Instance != nil {
+ err = Convert_v1beta1_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(in.Instance, &out.Instance, s)
+ if err != nil {
+ return err
+ }
+
+ if in.Instance.ServerGroup != nil && in.Instance.ServerGroup.ID != "" {
+ out.Instance.ServerGroupID = in.Instance.ServerGroup.ID
+ }
}
- out.Instance.FloatingIP = in.FloatingIP
- return nil
+ return optional.Convert_optional_String_To_string(&in.FloatingIP, &out.Instance.FloatingIP, s)
}
diff --git a/api/v1alpha6/openstackmachine_conversion.go b/api/v1alpha6/openstackmachine_conversion.go
index fe136a1b4e..f7b114ed12 100644
--- a/api/v1alpha6/openstackmachine_conversion.go
+++ b/api/v1alpha6/openstackmachine_conversion.go
@@ -133,6 +133,9 @@ func restorev1alpha6MachineSpec(previous *OpenStackMachineSpec, dst *OpenStackMa
}
if kd != k || vd != v {
+ if dst.ServerMetadata == nil {
+ dst.ServerMetadata = make(map[string]string)
+ }
delete(dst.ServerMetadata, kd)
dst.ServerMetadata[k] = v
}
diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go
index 7530cc7dea..c5e616cde8 100644
--- a/api/v1alpha6/zz_generated.conversion.go
+++ b/api/v1alpha6/zz_generated.conversion.go
@@ -481,19 +481,19 @@ func Convert_v1beta1_AddressPair_To_v1alpha6_AddressPair(in *v1beta1.AddressPair
func autoConvert_v1alpha6_Bastion_To_v1beta1_Bastion(in *Bastion, out *v1beta1.Bastion, s conversion.Scope) error {
out.Enabled = in.Enabled
- if err := Convert_v1alpha6_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(&in.Instance, &out.Instance, s); err != nil {
+ // WARNING: in.Instance requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha6.OpenStackMachineSpec vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.OpenStackMachineSpec)
+ if err := optional.Convert_string_To_optional_String(&in.AvailabilityZone, &out.AvailabilityZone, s); err != nil {
return err
}
- out.AvailabilityZone = in.AvailabilityZone
return nil
}
func autoConvert_v1beta1_Bastion_To_v1alpha6_Bastion(in *v1beta1.Bastion, out *Bastion, s conversion.Scope) error {
out.Enabled = in.Enabled
- if err := Convert_v1beta1_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(&in.Instance, &out.Instance, s); err != nil {
+ // WARNING: in.Instance requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.OpenStackMachineSpec vs sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha6.OpenStackMachineSpec)
+ 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
}
diff --git a/api/v1alpha7/openstackcluster_conversion.go b/api/v1alpha7/openstackcluster_conversion.go
index cd31d29f7f..09496fc92f 100644
--- a/api/v1alpha7/openstackcluster_conversion.go
+++ b/api/v1alpha7/openstackcluster_conversion.go
@@ -17,6 +17,8 @@ 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"
@@ -373,8 +375,13 @@ func restorev1alpha7Bastion(previous **Bastion, dst **Bastion) {
}
func restorev1beta1Bastion(previous **infrav1.Bastion, dst **infrav1.Bastion) {
- if *previous != nil && *dst != nil {
- restorev1beta1MachineSpec(&(*previous).Instance, &(*dst).Instance)
+ if *previous != nil {
+ if *dst != nil && (*previous).Instance != nil && (*dst).Instance != nil {
+ restorev1beta1MachineSpec((*previous).Instance, (*dst).Instance)
+ }
+
+ optional.RestoreString(&(*previous).FloatingIP, &(*dst).FloatingIP)
+ optional.RestoreString(&(*previous).AvailabilityZone, &(*dst).AvailabilityZone)
}
}
@@ -384,13 +391,30 @@ func Convert_v1alpha7_Bastion_To_v1beta1_Bastion(in *Bastion, out *infrav1.Basti
return err
}
- if in.Instance.ServerGroupID != "" {
- out.Instance.ServerGroup = &infrav1.ServerGroupFilter{ID: in.Instance.ServerGroupID}
- } else {
- out.Instance.ServerGroup = nil
+ if !reflect.ValueOf(in.Instance).IsZero() {
+ out.Instance = &infrav1.OpenStackMachineSpec{}
+
+ err = Convert_v1alpha7_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(&in.Instance, out.Instance, s)
+ if err != nil {
+ return err
+ }
+
+ if in.Instance.ServerGroupID != "" {
+ out.Instance.ServerGroup = &infrav1.ServerGroupFilter{ID: in.Instance.ServerGroupID}
+ } else {
+ out.Instance.ServerGroup = nil
+ }
+
+ err = optional.Convert_string_To_optional_String(&in.Instance.FloatingIP, &out.FloatingIP, s)
+ if err != nil {
+ return err
+ }
}
- out.FloatingIP = in.Instance.FloatingIP
+ // nil the Instance if it's basically an empty object.
+ if out.Instance != nil && reflect.ValueOf(*out.Instance).IsZero() {
+ out.Instance = nil
+ }
return nil
}
@@ -400,12 +424,18 @@ func Convert_v1beta1_Bastion_To_v1alpha7_Bastion(in *infrav1.Bastion, out *Basti
return err
}
- if in.Instance.ServerGroup != nil && in.Instance.ServerGroup.ID != "" {
- out.Instance.ServerGroupID = in.Instance.ServerGroup.ID
+ if in.Instance != nil {
+ err = Convert_v1beta1_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(in.Instance, &out.Instance, s)
+ if err != nil {
+ return err
+ }
+
+ if in.Instance.ServerGroup != nil && in.Instance.ServerGroup.ID != "" {
+ out.Instance.ServerGroupID = in.Instance.ServerGroup.ID
+ }
}
- out.Instance.FloatingIP = in.FloatingIP
- return nil
+ return optional.Convert_optional_String_To_string(&in.FloatingIP, &out.Instance.FloatingIP, s)
}
func Convert_v1beta1_BastionStatus_To_v1alpha7_BastionStatus(in *infrav1.BastionStatus, out *BastionStatus, s apiconversion.Scope) error {
diff --git a/api/v1alpha7/openstackmachine_conversion.go b/api/v1alpha7/openstackmachine_conversion.go
index 9d4331b01c..d18db4e676 100644
--- a/api/v1alpha7/openstackmachine_conversion.go
+++ b/api/v1alpha7/openstackmachine_conversion.go
@@ -107,6 +107,9 @@ func restorev1alpha7MachineSpec(previous *OpenStackMachineSpec, dst *OpenStackMa
}
if kd != k || vd != v {
+ if dst.ServerMetadata == nil {
+ dst.ServerMetadata = make(map[string]string)
+ }
delete(dst.ServerMetadata, kd)
dst.ServerMetadata[k] = v
}
diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go
index d22715b316..0bfa002200 100644
--- a/api/v1alpha7/zz_generated.conversion.go
+++ b/api/v1alpha7/zz_generated.conversion.go
@@ -534,19 +534,19 @@ func Convert_v1beta1_AddressPair_To_v1alpha7_AddressPair(in *v1beta1.AddressPair
func autoConvert_v1alpha7_Bastion_To_v1beta1_Bastion(in *Bastion, out *v1beta1.Bastion, s conversion.Scope) error {
out.Enabled = in.Enabled
- if err := Convert_v1alpha7_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(&in.Instance, &out.Instance, s); err != nil {
+ // WARNING: in.Instance requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7.OpenStackMachineSpec vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.OpenStackMachineSpec)
+ if err := optional.Convert_string_To_optional_String(&in.AvailabilityZone, &out.AvailabilityZone, s); err != nil {
return err
}
- out.AvailabilityZone = in.AvailabilityZone
return nil
}
func autoConvert_v1beta1_Bastion_To_v1alpha7_Bastion(in *v1beta1.Bastion, out *Bastion, s conversion.Scope) error {
out.Enabled = in.Enabled
- if err := Convert_v1beta1_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(&in.Instance, &out.Instance, s); err != nil {
+ // WARNING: in.Instance requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.OpenStackMachineSpec vs sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7.OpenStackMachineSpec)
+ 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
}
diff --git a/api/v1beta1/types.go b/api/v1beta1/types.go
index 94625b20db..ac57b14d41 100644
--- a/api/v1beta1/types.go
+++ b/api/v1beta1/types.go
@@ -596,21 +596,27 @@ var (
InstanceStateUndefined = InstanceState("")
)
-// Bastion represents basic information about the bastion node.
+// 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.instance)",message="you need to specify the instance if bastion is enabled"
type Bastion struct {
- //+optional
+ // Enabled means that bastion is enabled. Defaults to false.
+ // +kubebuilder:validation:Required
+ // +kubebuilder:default:=false
Enabled bool `json:"enabled"`
// Instance for the bastion itself
- Instance OpenStackMachineSpec `json:"instance,omitempty"`
+ Instance *OpenStackMachineSpec `json:"instance,omitempty"`
+ // AvailabilityZone is the failure domain that will be used to create the Bastion Instance.
//+optional
- AvailabilityZone string `json:"availabilityZone,omitempty"`
+ AvailabilityZone optional.String `json:"availabilityZone,omitempty"`
- // FloatingIP which will be associated to the bastion machine.
- // The floating IP should already exist and should not be associated with a port.
+ // 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
- FloatingIP string `json:"floatingIP,omitempty"`
+ //+kubebuilder:validation:Format:=ipv4
+ FloatingIP optional.String `json:"floatingIP,omitempty"`
}
type APIServerLoadBalancer struct {
diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go
index 73e1fb8368..1ccde03be1 100644
--- a/api/v1beta1/zz_generated.deepcopy.go
+++ b/api/v1beta1/zz_generated.deepcopy.go
@@ -116,7 +116,21 @@ func (in *AllocationPool) DeepCopy() *AllocationPool {
// 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.Instance != nil {
+ in, out := &in.Instance, &out.Instance
+ *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.
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 f2e491f4b3..0fd36b2a8c 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -4917,13 +4917,20 @@ spec:
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 Instance.
type: string
enabled:
+ default: false
+ description: Enabled means that bastion is enabled. Defaults to
+ false.
type: boolean
floatingIP:
description: |-
- FloatingIP which will be associated to the bastion machine.
- The floating IP should already exist and should not be associated with a port.
+ 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
instance:
description: Instance for the bastion itself
@@ -5572,7 +5579,12 @@ spec:
- flavor
- image
type: object
+ required:
+ - enabled
type: object
+ x-kubernetes-validations:
+ - message: you need to specify the instance if bastion is enabled
+ rule: '!self.enabled || has(self.instance)'
controlPlaneAvailabilityZones:
description: |-
ControlPlaneAvailabilityZones is the set of availability zones which
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 f577f0eb3b..c5ceb4f872 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -2341,13 +2341,20 @@ spec:
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 Instance.
type: string
enabled:
+ default: false
+ description: Enabled means that bastion is enabled. Defaults
+ to false.
type: boolean
floatingIP:
description: |-
- FloatingIP which will be associated to the bastion machine.
- The floating IP should already exist and should not be associated with a port.
+ 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
instance:
description: Instance for the bastion itself
@@ -3006,7 +3013,13 @@ spec:
- flavor
- image
type: object
+ required:
+ - enabled
type: object
+ x-kubernetes-validations:
+ - message: you need to specify the instance if bastion is
+ enabled
+ rule: '!self.enabled || has(self.instance)'
controlPlaneAvailabilityZones:
description: |-
ControlPlaneAvailabilityZones is the set of availability zones which
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index 6f0b9592b3..dcd0f1d789 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -222,7 +222,10 @@ func resolveBastionResources(scope *scope.WithLogger, openStackCluster *infrav1.
if openStackCluster.Status.Bastion == nil {
openStackCluster.Status.Bastion = &infrav1.BastionStatus{}
}
- changed, err := compute.ResolveReferencedMachineResources(scope, openStackCluster, &openStackCluster.Spec.Bastion.Instance, &openStackCluster.Status.Bastion.ReferencedResources)
+ if openStackCluster.Spec.Bastion.Instance == nil {
+ return false, fmt.Errorf("bastion spec is nil when bastion is enabled, this shouldn't happen")
+ }
+ changed, err := compute.ResolveReferencedMachineResources(scope, openStackCluster, openStackCluster.Spec.Bastion.Instance, &openStackCluster.Status.Bastion.ReferencedResources)
if err != nil {
return false, err
}
@@ -504,9 +507,9 @@ func bastionAddFloatingIP(openStackCluster *infrav1.OpenStackCluster, clusterNam
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 != "":
+ case openStackCluster.Spec.Bastion.FloatingIP != nil:
// Use floating IP from the spec
- floatingIP = &openStackCluster.Spec.Bastion.FloatingIP
+ 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, clusterName, floatingIP)
@@ -529,17 +532,24 @@ func bastionToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, cluster *
if openStackCluster.Spec.Bastion == nil {
return nil, fmt.Errorf("bastion spec is nil")
}
+ if openStackCluster.Spec.Bastion.Instance == 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.
+ openStackCluster.Spec.Bastion.Instance = &infrav1.OpenStackMachineSpec{}
+ }
if openStackCluster.Status.Bastion == nil {
return nil, fmt.Errorf("bastion status is nil")
}
instanceSpec := &compute.InstanceSpec{
- Name: bastionName(cluster.Name),
- Flavor: openStackCluster.Spec.Bastion.Instance.Flavor,
- SSHKeyName: openStackCluster.Spec.Bastion.Instance.SSHKeyName,
- ImageID: openStackCluster.Status.Bastion.ReferencedResources.ImageID,
- FailureDomain: openStackCluster.Spec.Bastion.AvailabilityZone,
- RootVolume: openStackCluster.Spec.Bastion.Instance.RootVolume,
+ Name: bastionName(cluster.Name),
+ Flavor: openStackCluster.Spec.Bastion.Instance.Flavor,
+ SSHKeyName: openStackCluster.Spec.Bastion.Instance.SSHKeyName,
+ ImageID: openStackCluster.Status.Bastion.ReferencedResources.ImageID,
+ RootVolume: openStackCluster.Spec.Bastion.Instance.RootVolume,
+ }
+ if openStackCluster.Spec.Bastion.AvailabilityZone != nil {
+ instanceSpec.FailureDomain = *openStackCluster.Spec.Bastion.AvailabilityZone
}
instanceSpec.SecurityGroups = openStackCluster.Spec.Bastion.Instance.SecurityGroups
diff --git a/controllers/openstackcluster_controller_test.go b/controllers/openstackcluster_controller_test.go
index 3f3ec703d7..c492ffab95 100644
--- a/controllers/openstackcluster_controller_test.go
+++ b/controllers/openstackcluster_controller_test.go
@@ -61,6 +61,11 @@ var _ = Describe("OpenStackCluster controller", func() {
capiClusterName := "capi-cluster"
testClusterName := "test-cluster"
testNum := 0
+ instance := infrav1.OpenStackMachineSpec{
+ Image: infrav1.ImageFilter{
+ Name: pointer.String("fake-name"),
+ },
+ }
BeforeEach(func() {
ctx = context.TODO()
@@ -192,9 +197,7 @@ var _ = Describe("OpenStackCluster controller", func() {
It("should be able to reconcile when bastion is disabled and does not exist", func() {
testCluster.SetName("no-bastion")
testCluster.Spec = infrav1.OpenStackClusterSpec{
- Bastion: &infrav1.Bastion{
- Enabled: false,
- },
+ Bastion: &infrav1.Bastion{},
}
err := k8sClient.Create(ctx, testCluster)
Expect(err).To(BeNil())
@@ -223,7 +226,8 @@ var _ = Describe("OpenStackCluster controller", func() {
testCluster.SetName("adopt-existing-bastion")
testCluster.Spec = infrav1.OpenStackClusterSpec{
Bastion: &infrav1.Bastion{
- Enabled: true,
+ Enabled: true,
+ Instance: &instance,
},
}
err := k8sClient.Create(ctx, testCluster)
@@ -308,7 +312,8 @@ var _ = Describe("OpenStackCluster controller", func() {
testCluster.SetName("requeue-bastion")
testCluster.Spec = infrav1.OpenStackClusterSpec{
Bastion: &infrav1.Bastion{
- Enabled: true,
+ Enabled: true,
+ Instance: &instance,
},
}
err := k8sClient.Create(ctx, testCluster)
@@ -393,7 +398,8 @@ var _ = Describe("OpenStackCluster controller", func() {
testCluster.SetName("requeue-bastion")
testCluster.Spec = infrav1.OpenStackClusterSpec{
Bastion: &infrav1.Bastion{
- Enabled: true,
+ Enabled: true,
+ Instance: &instance,
},
}
err := k8sClient.Create(ctx, testCluster)
@@ -518,7 +524,8 @@ var _ = Describe("OpenStackCluster controller", func() {
testCluster.SetName("subnet-filtering")
testCluster.Spec = infrav1.OpenStackClusterSpec{
Bastion: &infrav1.Bastion{
- Enabled: true,
+ Enabled: true,
+ Instance: &instance,
},
DisableAPIServerFloatingIP: pointer.Bool(true),
APIServerFixedIP: pointer.String("10.0.0.1"),
@@ -598,7 +605,8 @@ var _ = Describe("OpenStackCluster controller", func() {
testCluster.SetName("subnet-filtering")
testCluster.Spec = infrav1.OpenStackClusterSpec{
Bastion: &infrav1.Bastion{
- Enabled: true,
+ Enabled: true,
+ Instance: &instance,
},
DisableAPIServerFloatingIP: pointer.Bool(true),
APIServerFixedIP: pointer.String("10.0.0.1"),
@@ -796,7 +804,7 @@ func TestGetBastionSecurityGroups(t *testing.T) {
openStackCluster := &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
Bastion: &infrav1.Bastion{
- Instance: infrav1.OpenStackMachineSpec{
+ Instance: &infrav1.OpenStackMachineSpec{
SecurityGroups: []infrav1.SecurityGroupFilter{
{
ID: "sg-123",
diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md
index ae9159d5fb..e6707e8405 100644
--- a/docs/book/src/api/v1beta1/api.md
+++ b/docs/book/src/api/v1beta1/api.md
@@ -1064,7 +1064,7 @@ string
OpenStackClusterSpec)
-
Bastion represents basic information about the bastion node.
+Bastion represents basic information about the bastion node. If you enable bastion, the spec has to be specified.
@@ -1082,7 +1082,7 @@ bool
|
-(Optional)
+ Enabled means that bastion is enabled. Defaults to false.
|
@@ -1107,6 +1107,7 @@ string
|
(Optional)
+ AvailabilityZone is the failure domain that will be used to create the Bastion Instance.
|
@@ -1118,8 +1119,9 @@ string
|
(Optional)
- FloatingIP which will be associated to the bastion machine.
-The floating IP should already exist and should not be associated with a port.
+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.
|
diff --git a/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md b/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
index aa5fe6b66b..64ece98c60 100644
--- a/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
+++ b/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
@@ -234,6 +234,8 @@ spec:
floatingIP: "1.2.3.4"
```
+The new field has IPv4 validation added.
+
#### Change to subnet
In v1beta1, `Subnet` of `OpenStackCluster` is modified to `Subnets` to allow specification of two existent subnets for the dual-stack scenario.
diff --git a/pkg/webhooks/openstackcluster_webhook_test.go b/pkg/webhooks/openstackcluster_webhook_test.go
index dcead6be4f..d1d04c16eb 100644
--- a/pkg/webhooks/openstackcluster_webhook_test.go
+++ b/pkg/webhooks/openstackcluster_webhook_test.go
@@ -84,7 +84,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
CloudName: "foobar",
},
Bastion: &infrav1.Bastion{
- Instance: infrav1.OpenStackMachineSpec{
+ Instance: &infrav1.OpenStackMachineSpec{
Image: infrav1.ImageFilter{Name: pointer.String("foobar")},
Flavor: "minimal",
},
@@ -104,7 +104,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
CloudName: "foobar",
},
Bastion: &infrav1.Bastion{
- Instance: infrav1.OpenStackMachineSpec{
+ Instance: &infrav1.OpenStackMachineSpec{
Image: infrav1.ImageFilter{Name: pointer.String("foobarbaz")},
Flavor: "medium",
},
@@ -452,7 +452,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
Bastion: &infrav1.Bastion{
Enabled: true,
- Instance: infrav1.OpenStackMachineSpec{
+ Instance: &infrav1.OpenStackMachineSpec{
Flavor: "m1.small",
Image: infrav1.ImageFilter{Name: pointer.String("ubuntu")},
},
@@ -479,7 +479,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
Bastion: &infrav1.Bastion{
Enabled: false,
- Instance: infrav1.OpenStackMachineSpec{
+ Instance: &infrav1.OpenStackMachineSpec{
Flavor: "m1.small",
Image: infrav1.ImageFilter{Name: pointer.String("ubuntu")},
},
diff --git a/test/e2e/suites/apivalidations/openstackcluster_test.go b/test/e2e/suites/apivalidations/openstackcluster_test.go
index ad1c0d502c..299715a161 100644
--- a/test/e2e/suites/apivalidations/openstackcluster_test.go
+++ b/test/e2e/suites/apivalidations/openstackcluster_test.go
@@ -21,6 +21,7 @@ import (
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
+ "k8s.io/utils/pointer"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
@@ -86,4 +87,54 @@ var _ = Describe("OpenStackCluster API validations", func() {
Expect(fetchedCluster.Spec.APIServerLoadBalancer).To(BeNil(), "APIServerLoadBalancer should not have been defaulted")
Expect(fetchedCluster.Spec.APIServerLoadBalancer.IsEnabled()).To(BeFalse(), "APIServerLoadBalancer.Enabled should not have been defaulted")
})
+
+ It("should allow bastion.enabled=true with an instance", func() {
+ cluster.Spec.Bastion = &infrav1.Bastion{
+ Enabled: true,
+ Instance: &infrav1.OpenStackMachineSpec{
+ Image: infrav1.ImageFilter{Name: pointer.String("fake-image")},
+ },
+ }
+ Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
+ })
+
+ It("should not allow bastion.enabled=true without an instance", func() {
+ cluster.Spec.Bastion = &infrav1.Bastion{
+ Enabled: true,
+ }
+ Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should not succeed")
+ })
+
+ It("should default bastion.enabled=false", func() {
+ cluster.Spec.Bastion = &infrav1.Bastion{}
+ Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should not succeed")
+
+ // Fetch the cluster and check the defaulting
+ fetchedCluster := &infrav1.OpenStackCluster{}
+ Expect(k8sClient.Get(ctx, types.NamespacedName{Name: cluster.Name, Namespace: cluster.Namespace}, fetchedCluster)).To(Succeed(), "OpenStackCluster fetch should succeed")
+
+ Expect(fetchedCluster.Spec.Bastion.Enabled).To(BeFalse(), "Bastion.Enabled should default to false")
+ })
+
+ It("should allow IPv4 as bastion floatingIP", func() {
+ cluster.Spec.Bastion = &infrav1.Bastion{
+ Enabled: true,
+ Instance: &infrav1.OpenStackMachineSpec{
+ Image: infrav1.ImageFilter{Name: pointer.String("fake-image")},
+ },
+ FloatingIP: pointer.String("10.0.0.0"),
+ }
+ Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
+ })
+
+ It("should not allow non-IPv4 as bastion floating IP", func() {
+ cluster.Spec.Bastion = &infrav1.Bastion{
+ Enabled: true,
+ Instance: &infrav1.OpenStackMachineSpec{
+ Image: infrav1.ImageFilter{Name: pointer.String("fake-image")},
+ },
+ FloatingIP: pointer.String("foobar"),
+ }
+ Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should not succeed")
+ })
})
From c321574212d868965da9391eaf6da6049a4a2b41 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20Dulko?=
Date: Tue, 19 Mar 2024 21:01:52 +0100
Subject: [PATCH 140/180] Rename Bastion.Instance to Bastion.Spec
Bastion.Spec is way more descriptive and it suggests it's an
OpenStackMachineSpec.
---
api/v1alpha5/conversion.go | 4 +--
api/v1alpha5/zz_generated.conversion.go | 4 +--
api/v1alpha6/openstackcluster_conversion.go | 30 +++++++++----------
api/v1alpha6/zz_generated.conversion.go | 4 +--
api/v1alpha7/openstackcluster_conversion.go | 26 ++++++++--------
api/v1alpha7/zz_generated.conversion.go | 4 +--
api/v1beta1/types.go | 8 ++---
api/v1beta1/zz_generated.deepcopy.go | 4 +--
...re.cluster.x-k8s.io_openstackclusters.yaml | 10 +++----
...er.x-k8s.io_openstackclustertemplates.yaml | 11 ++++---
controllers/openstackcluster_controller.go | 22 +++++++-------
.../openstackcluster_controller_test.go | 24 +++++++--------
docs/book/src/api/v1beta1/api.md | 10 +++++--
.../src/clusteropenstack/configuration.md | 2 +-
.../topics/crd-changes/v1alpha7-to-v1beta1.md | 25 ++++++++++++++++
pkg/cloud/services/compute/instance_types.go | 3 --
pkg/webhooks/openstackcluster_webhook_test.go | 8 ++---
.../common-patches/cni/patch-cluster.yaml | 2 +-
test/e2e/data/kustomize/v1alpha6/bastion.yaml | 2 +-
test/e2e/data/kustomize/v1alpha7/bastion.yaml | 2 +-
.../apivalidations/openstackcluster_test.go | 10 +++----
test/e2e/suites/e2e/e2e_test.go | 2 +-
22 files changed, 121 insertions(+), 96 deletions(-)
diff --git a/api/v1alpha5/conversion.go b/api/v1alpha5/conversion.go
index 6e45b44360..06c4128e55 100644
--- a/api/v1alpha5/conversion.go
+++ b/api/v1alpha5/conversion.go
@@ -448,7 +448,7 @@ func Convert_v1alpha5_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *infrav1.Po
}
func Convert_v1alpha5_Instance_To_v1beta1_BastionStatus(in *Instance, out *infrav1.BastionStatus, _ conversion.Scope) error {
- // BastionStatus is the same as Instance with unused fields removed
+ // BastionStatus is the same as Spec with unused fields removed
out.ID = in.ID
out.Name = in.Name
out.SSHKeyName = in.SSHKeyName
@@ -460,7 +460,7 @@ func Convert_v1alpha5_Instance_To_v1beta1_BastionStatus(in *Instance, out *infra
}
func Convert_v1beta1_BastionStatus_To_v1alpha5_Instance(in *infrav1.BastionStatus, out *Instance, _ conversion.Scope) error {
- // BastionStatus is the same as Instance with unused fields removed
+ // BastionStatus is the same as Spec with unused fields removed
out.ID = in.ID
out.Name = in.Name
out.SSHKeyName = in.SSHKeyName
diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go
index de12e75f92..2acff1d4aa 100644
--- a/api/v1alpha5/zz_generated.conversion.go
+++ b/api/v1alpha5/zz_generated.conversion.go
@@ -457,7 +457,7 @@ func Convert_v1beta1_AddressPair_To_v1alpha5_AddressPair(in *v1beta1.AddressPair
func autoConvert_v1alpha5_Bastion_To_v1beta1_Bastion(in *Bastion, out *v1beta1.Bastion, s conversion.Scope) error {
out.Enabled = in.Enabled
- // WARNING: in.Instance requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha5.OpenStackMachineSpec vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.OpenStackMachineSpec)
+ // 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
}
@@ -466,7 +466,7 @@ func autoConvert_v1alpha5_Bastion_To_v1beta1_Bastion(in *Bastion, out *v1beta1.B
func autoConvert_v1beta1_Bastion_To_v1alpha5_Bastion(in *v1beta1.Bastion, out *Bastion, s conversion.Scope) error {
out.Enabled = in.Enabled
- // WARNING: in.Instance requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.OpenStackMachineSpec vs sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha5.OpenStackMachineSpec)
+ // 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
}
diff --git a/api/v1alpha6/openstackcluster_conversion.go b/api/v1alpha6/openstackcluster_conversion.go
index 14bffeb1fc..2991efe751 100644
--- a/api/v1alpha6/openstackcluster_conversion.go
+++ b/api/v1alpha6/openstackcluster_conversion.go
@@ -413,8 +413,8 @@ func Convert_v1alpha6_OpenStackClusterStatus_To_v1beta1_OpenStackClusterStatus(i
func restorev1beta1Bastion(previous **infrav1.Bastion, dst **infrav1.Bastion) {
if *previous != nil {
- if *dst != nil && (*previous).Instance != nil && (*dst).Instance != nil {
- restorev1beta1MachineSpec((*previous).Instance, (*dst).Instance)
+ if *dst != nil && (*previous).Spec != nil && (*dst).Spec != nil {
+ restorev1beta1MachineSpec((*previous).Spec, (*dst).Spec)
}
optional.RestoreString(&(*previous).FloatingIP, &(*dst).FloatingIP)
@@ -423,7 +423,7 @@ func restorev1beta1Bastion(previous **infrav1.Bastion, dst **infrav1.Bastion) {
}
func Convert_v1alpha6_Instance_To_v1beta1_BastionStatus(in *Instance, out *infrav1.BastionStatus, _ apiconversion.Scope) error {
- // BastionStatus is the same as Instance with unused fields removed
+ // BastionStatus is the same as Spec with unused fields removed
out.ID = in.ID
out.Name = in.Name
out.SSHKeyName = in.SSHKeyName
@@ -434,7 +434,7 @@ func Convert_v1alpha6_Instance_To_v1beta1_BastionStatus(in *Instance, out *infra
}
func Convert_v1beta1_BastionStatus_To_v1alpha6_Instance(in *infrav1.BastionStatus, out *Instance, _ apiconversion.Scope) error {
- // BastionStatus is the same as Instance with unused fields removed
+ // BastionStatus is the same as Spec with unused fields removed
out.ID = in.ID
out.Name = in.Name
out.SSHKeyName = in.SSHKeyName
@@ -451,17 +451,17 @@ func Convert_v1alpha6_Bastion_To_v1beta1_Bastion(in *Bastion, out *infrav1.Basti
}
if !reflect.ValueOf(in.Instance).IsZero() {
- out.Instance = &infrav1.OpenStackMachineSpec{}
+ out.Spec = &infrav1.OpenStackMachineSpec{}
- err = Convert_v1alpha6_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(&in.Instance, out.Instance, s)
+ err = Convert_v1alpha6_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(&in.Instance, out.Spec, s)
if err != nil {
return err
}
if in.Instance.ServerGroupID != "" {
- out.Instance.ServerGroup = &infrav1.ServerGroupFilter{ID: in.Instance.ServerGroupID}
+ out.Spec.ServerGroup = &infrav1.ServerGroupFilter{ID: in.Instance.ServerGroupID}
} else {
- out.Instance.ServerGroup = nil
+ out.Spec.ServerGroup = nil
}
err = optional.Convert_string_To_optional_String(&in.Instance.FloatingIP, &out.FloatingIP, s)
@@ -470,9 +470,9 @@ func Convert_v1alpha6_Bastion_To_v1beta1_Bastion(in *Bastion, out *infrav1.Basti
}
}
- // nil the Instance if it's basically an empty object.
- if out.Instance != nil && reflect.ValueOf(*out.Instance).IsZero() {
- out.Instance = nil
+ // nil the Spec if it's basically an empty object.
+ if out.Spec != nil && reflect.ValueOf(*out.Spec).IsZero() {
+ out.Spec = nil
}
return nil
}
@@ -483,14 +483,14 @@ func Convert_v1beta1_Bastion_To_v1alpha6_Bastion(in *infrav1.Bastion, out *Basti
return err
}
- if in.Instance != nil {
- err = Convert_v1beta1_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(in.Instance, &out.Instance, s)
+ if in.Spec != nil {
+ err = Convert_v1beta1_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(in.Spec, &out.Instance, s)
if err != nil {
return err
}
- if in.Instance.ServerGroup != nil && in.Instance.ServerGroup.ID != "" {
- out.Instance.ServerGroupID = in.Instance.ServerGroup.ID
+ if in.Spec.ServerGroup != nil && in.Spec.ServerGroup.ID != "" {
+ out.Instance.ServerGroupID = in.Spec.ServerGroup.ID
}
}
diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go
index c5e616cde8..a6dcc278d4 100644
--- a/api/v1alpha6/zz_generated.conversion.go
+++ b/api/v1alpha6/zz_generated.conversion.go
@@ -481,7 +481,7 @@ func Convert_v1beta1_AddressPair_To_v1alpha6_AddressPair(in *v1beta1.AddressPair
func autoConvert_v1alpha6_Bastion_To_v1beta1_Bastion(in *Bastion, out *v1beta1.Bastion, s conversion.Scope) error {
out.Enabled = in.Enabled
- // WARNING: in.Instance requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha6.OpenStackMachineSpec vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.OpenStackMachineSpec)
+ // 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
}
@@ -490,7 +490,7 @@ func autoConvert_v1alpha6_Bastion_To_v1beta1_Bastion(in *Bastion, out *v1beta1.B
func autoConvert_v1beta1_Bastion_To_v1alpha6_Bastion(in *v1beta1.Bastion, out *Bastion, s conversion.Scope) error {
out.Enabled = in.Enabled
- // WARNING: in.Instance requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.OpenStackMachineSpec vs sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha6.OpenStackMachineSpec)
+ // 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
}
diff --git a/api/v1alpha7/openstackcluster_conversion.go b/api/v1alpha7/openstackcluster_conversion.go
index 09496fc92f..13f36f68a1 100644
--- a/api/v1alpha7/openstackcluster_conversion.go
+++ b/api/v1alpha7/openstackcluster_conversion.go
@@ -376,8 +376,8 @@ func restorev1alpha7Bastion(previous **Bastion, dst **Bastion) {
func restorev1beta1Bastion(previous **infrav1.Bastion, dst **infrav1.Bastion) {
if *previous != nil {
- if *dst != nil && (*previous).Instance != nil && (*dst).Instance != nil {
- restorev1beta1MachineSpec((*previous).Instance, (*dst).Instance)
+ if *dst != nil && (*previous).Spec != nil && (*dst).Spec != nil {
+ restorev1beta1MachineSpec((*previous).Spec, (*dst).Spec)
}
optional.RestoreString(&(*previous).FloatingIP, &(*dst).FloatingIP)
@@ -392,17 +392,17 @@ func Convert_v1alpha7_Bastion_To_v1beta1_Bastion(in *Bastion, out *infrav1.Basti
}
if !reflect.ValueOf(in.Instance).IsZero() {
- out.Instance = &infrav1.OpenStackMachineSpec{}
+ out.Spec = &infrav1.OpenStackMachineSpec{}
- err = Convert_v1alpha7_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(&in.Instance, out.Instance, s)
+ err = Convert_v1alpha7_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(&in.Instance, out.Spec, s)
if err != nil {
return err
}
if in.Instance.ServerGroupID != "" {
- out.Instance.ServerGroup = &infrav1.ServerGroupFilter{ID: in.Instance.ServerGroupID}
+ out.Spec.ServerGroup = &infrav1.ServerGroupFilter{ID: in.Instance.ServerGroupID}
} else {
- out.Instance.ServerGroup = nil
+ out.Spec.ServerGroup = nil
}
err = optional.Convert_string_To_optional_String(&in.Instance.FloatingIP, &out.FloatingIP, s)
@@ -411,9 +411,9 @@ func Convert_v1alpha7_Bastion_To_v1beta1_Bastion(in *Bastion, out *infrav1.Basti
}
}
- // nil the Instance if it's basically an empty object.
- if out.Instance != nil && reflect.ValueOf(*out.Instance).IsZero() {
- out.Instance = nil
+ // nil the Spec if it's basically an empty object.
+ if out.Spec != nil && reflect.ValueOf(*out.Spec).IsZero() {
+ out.Spec = nil
}
return nil
}
@@ -424,14 +424,14 @@ func Convert_v1beta1_Bastion_To_v1alpha7_Bastion(in *infrav1.Bastion, out *Basti
return err
}
- if in.Instance != nil {
- err = Convert_v1beta1_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(in.Instance, &out.Instance, s)
+ if in.Spec != nil {
+ err = Convert_v1beta1_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(in.Spec, &out.Instance, s)
if err != nil {
return err
}
- if in.Instance.ServerGroup != nil && in.Instance.ServerGroup.ID != "" {
- out.Instance.ServerGroupID = in.Instance.ServerGroup.ID
+ if in.Spec.ServerGroup != nil && in.Spec.ServerGroup.ID != "" {
+ out.Instance.ServerGroupID = in.Spec.ServerGroup.ID
}
}
diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go
index 0bfa002200..8264250f84 100644
--- a/api/v1alpha7/zz_generated.conversion.go
+++ b/api/v1alpha7/zz_generated.conversion.go
@@ -534,7 +534,7 @@ func Convert_v1beta1_AddressPair_To_v1alpha7_AddressPair(in *v1beta1.AddressPair
func autoConvert_v1alpha7_Bastion_To_v1beta1_Bastion(in *Bastion, out *v1beta1.Bastion, s conversion.Scope) error {
out.Enabled = in.Enabled
- // WARNING: in.Instance requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7.OpenStackMachineSpec vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.OpenStackMachineSpec)
+ // 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
}
@@ -543,7 +543,7 @@ func autoConvert_v1alpha7_Bastion_To_v1beta1_Bastion(in *Bastion, out *v1beta1.B
func autoConvert_v1beta1_Bastion_To_v1alpha7_Bastion(in *v1beta1.Bastion, out *Bastion, s conversion.Scope) error {
out.Enabled = in.Enabled
- // WARNING: in.Instance requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.OpenStackMachineSpec vs sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7.OpenStackMachineSpec)
+ // 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
}
diff --git a/api/v1beta1/types.go b/api/v1beta1/types.go
index ac57b14d41..a4687a47ee 100644
--- a/api/v1beta1/types.go
+++ b/api/v1beta1/types.go
@@ -597,17 +597,17 @@ var (
)
// 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.instance)",message="you need to specify the instance if bastion is enabled"
+// +kubebuilder:validation:XValidation:rule="!self.enabled || has(self.spec)",message="you need to specify the spec if bastion is enabled"
type Bastion struct {
// Enabled means that bastion is enabled. Defaults to false.
// +kubebuilder:validation:Required
// +kubebuilder:default:=false
Enabled bool `json:"enabled"`
- // Instance for the bastion itself
- Instance *OpenStackMachineSpec `json:"instance,omitempty"`
+ // Spec for the bastion itself
+ Spec *OpenStackMachineSpec `json:"spec,omitempty"`
- // AvailabilityZone is the failure domain that will be used to create the Bastion Instance.
+ // AvailabilityZone is the failure domain that will be used to create the Bastion Spec.
//+optional
AvailabilityZone optional.String `json:"availabilityZone,omitempty"`
diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go
index 1ccde03be1..be62dda940 100644
--- a/api/v1beta1/zz_generated.deepcopy.go
+++ b/api/v1beta1/zz_generated.deepcopy.go
@@ -116,8 +116,8 @@ func (in *AllocationPool) DeepCopy() *AllocationPool {
// 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
- if in.Instance != nil {
- in, out := &in.Instance, &out.Instance
+ if in.Spec != nil {
+ in, out := &in.Spec, &out.Spec
*out = new(OpenStackMachineSpec)
(*in).DeepCopyInto(*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 0fd36b2a8c..fbacc663ed 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -4918,7 +4918,7 @@ spec:
properties:
availabilityZone:
description: AvailabilityZone is the failure domain that will
- be used to create the Bastion Instance.
+ be used to create the Bastion Spec.
type: string
enabled:
default: false
@@ -4932,8 +4932,8 @@ spec:
exist, CAPO will try to create it, but by default only OpenStack administrators have privileges to do so.
format: ipv4
type: string
- instance:
- description: Instance for the bastion itself
+ spec:
+ description: Spec for the bastion itself
properties:
additionalBlockDevices:
description: AdditionalBlockDevices is a list of specifications
@@ -5583,8 +5583,8 @@ spec:
- enabled
type: object
x-kubernetes-validations:
- - message: you need to specify the instance if bastion is enabled
- rule: '!self.enabled || has(self.instance)'
+ - message: you need to specify the spec if bastion is enabled
+ rule: '!self.enabled || has(self.spec)'
controlPlaneAvailabilityZones:
description: |-
ControlPlaneAvailabilityZones is the set of availability zones which
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 c5ceb4f872..9d1b3799ec 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -2342,7 +2342,7 @@ spec:
properties:
availabilityZone:
description: AvailabilityZone is the failure domain that
- will be used to create the Bastion Instance.
+ will be used to create the Bastion Spec.
type: string
enabled:
default: false
@@ -2356,8 +2356,8 @@ spec:
exist, CAPO will try to create it, but by default only OpenStack administrators have privileges to do so.
format: ipv4
type: string
- instance:
- description: Instance for the bastion itself
+ spec:
+ description: Spec for the bastion itself
properties:
additionalBlockDevices:
description: AdditionalBlockDevices is a list of specifications
@@ -3017,9 +3017,8 @@ spec:
- enabled
type: object
x-kubernetes-validations:
- - message: you need to specify the instance if bastion is
- enabled
- rule: '!self.enabled || has(self.instance)'
+ - message: you need to specify the spec if bastion is enabled
+ rule: '!self.enabled || has(self.spec)'
controlPlaneAvailabilityZones:
description: |-
ControlPlaneAvailabilityZones is the set of availability zones which
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index dcd0f1d789..61ea41cff2 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -222,10 +222,10 @@ func resolveBastionResources(scope *scope.WithLogger, openStackCluster *infrav1.
if openStackCluster.Status.Bastion == nil {
openStackCluster.Status.Bastion = &infrav1.BastionStatus{}
}
- if openStackCluster.Spec.Bastion.Instance == nil {
+ if openStackCluster.Spec.Bastion.Spec == nil {
return false, fmt.Errorf("bastion spec is nil when bastion is enabled, this shouldn't happen")
}
- changed, err := compute.ResolveReferencedMachineResources(scope, openStackCluster, openStackCluster.Spec.Bastion.Instance, &openStackCluster.Status.Bastion.ReferencedResources)
+ changed, err := compute.ResolveReferencedMachineResources(scope, openStackCluster, openStackCluster.Spec.Bastion.Spec, &openStackCluster.Status.Bastion.ReferencedResources)
if err != nil {
return false, err
}
@@ -532,10 +532,10 @@ func bastionToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, cluster *
if openStackCluster.Spec.Bastion == nil {
return nil, fmt.Errorf("bastion spec is nil")
}
- if openStackCluster.Spec.Bastion.Instance == nil {
+ if openStackCluster.Spec.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.
- openStackCluster.Spec.Bastion.Instance = &infrav1.OpenStackMachineSpec{}
+ openStackCluster.Spec.Bastion.Spec = &infrav1.OpenStackMachineSpec{}
}
if openStackCluster.Status.Bastion == nil {
@@ -543,16 +543,16 @@ func bastionToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, cluster *
}
instanceSpec := &compute.InstanceSpec{
Name: bastionName(cluster.Name),
- Flavor: openStackCluster.Spec.Bastion.Instance.Flavor,
- SSHKeyName: openStackCluster.Spec.Bastion.Instance.SSHKeyName,
+ Flavor: openStackCluster.Spec.Bastion.Spec.Flavor,
+ SSHKeyName: openStackCluster.Spec.Bastion.Spec.SSHKeyName,
ImageID: openStackCluster.Status.Bastion.ReferencedResources.ImageID,
- RootVolume: openStackCluster.Spec.Bastion.Instance.RootVolume,
+ RootVolume: openStackCluster.Spec.Bastion.Spec.RootVolume,
}
if openStackCluster.Spec.Bastion.AvailabilityZone != nil {
instanceSpec.FailureDomain = *openStackCluster.Spec.Bastion.AvailabilityZone
}
- instanceSpec.SecurityGroups = openStackCluster.Spec.Bastion.Instance.SecurityGroups
+ instanceSpec.SecurityGroups = openStackCluster.Spec.Bastion.Spec.SecurityGroups
if openStackCluster.Spec.ManagedSecurityGroups != nil {
if openStackCluster.Status.BastionSecurityGroup != nil {
instanceSpec.SecurityGroups = append(instanceSpec.SecurityGroups, infrav1.SecurityGroupFilter{
@@ -562,7 +562,7 @@ func bastionToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, cluster *
}
instanceSpec.SecurityGroups = getBastionSecurityGroups(openStackCluster)
- instanceSpec.Ports = openStackCluster.Spec.Bastion.Instance.Ports
+ instanceSpec.Ports = openStackCluster.Spec.Bastion.Spec.Ports
return instanceSpec, nil
}
@@ -571,10 +571,10 @@ func bastionName(clusterName string) string {
return fmt.Sprintf("%s-bastion", clusterName)
}
-// getBastionSecurityGroups returns a combination of openStackCluster.Spec.Bastion.Instance.SecurityGroups
+// getBastionSecurityGroups returns a combination of openStackCluster.Spec.Bastion.Spec.SecurityGroups
// and the security group managed by the OpenStackCluster.
func getBastionSecurityGroups(openStackCluster *infrav1.OpenStackCluster) []infrav1.SecurityGroupFilter {
- instanceSpecSecurityGroups := openStackCluster.Spec.Bastion.Instance.SecurityGroups
+ instanceSpecSecurityGroups := openStackCluster.Spec.Bastion.Spec.SecurityGroups
if openStackCluster.Spec.ManagedSecurityGroups == nil {
return instanceSpecSecurityGroups
diff --git a/controllers/openstackcluster_controller_test.go b/controllers/openstackcluster_controller_test.go
index c492ffab95..9c94b12d40 100644
--- a/controllers/openstackcluster_controller_test.go
+++ b/controllers/openstackcluster_controller_test.go
@@ -61,7 +61,7 @@ var _ = Describe("OpenStackCluster controller", func() {
capiClusterName := "capi-cluster"
testClusterName := "test-cluster"
testNum := 0
- instance := infrav1.OpenStackMachineSpec{
+ bastionSpec := infrav1.OpenStackMachineSpec{
Image: infrav1.ImageFilter{
Name: pointer.String("fake-name"),
},
@@ -226,8 +226,8 @@ var _ = Describe("OpenStackCluster controller", func() {
testCluster.SetName("adopt-existing-bastion")
testCluster.Spec = infrav1.OpenStackClusterSpec{
Bastion: &infrav1.Bastion{
- Enabled: true,
- Instance: &instance,
+ Enabled: true,
+ Spec: &bastionSpec,
},
}
err := k8sClient.Create(ctx, testCluster)
@@ -312,8 +312,8 @@ var _ = Describe("OpenStackCluster controller", func() {
testCluster.SetName("requeue-bastion")
testCluster.Spec = infrav1.OpenStackClusterSpec{
Bastion: &infrav1.Bastion{
- Enabled: true,
- Instance: &instance,
+ Enabled: true,
+ Spec: &bastionSpec,
},
}
err := k8sClient.Create(ctx, testCluster)
@@ -398,8 +398,8 @@ var _ = Describe("OpenStackCluster controller", func() {
testCluster.SetName("requeue-bastion")
testCluster.Spec = infrav1.OpenStackClusterSpec{
Bastion: &infrav1.Bastion{
- Enabled: true,
- Instance: &instance,
+ Enabled: true,
+ Spec: &bastionSpec,
},
}
err := k8sClient.Create(ctx, testCluster)
@@ -524,8 +524,8 @@ var _ = Describe("OpenStackCluster controller", func() {
testCluster.SetName("subnet-filtering")
testCluster.Spec = infrav1.OpenStackClusterSpec{
Bastion: &infrav1.Bastion{
- Enabled: true,
- Instance: &instance,
+ Enabled: true,
+ Spec: &bastionSpec,
},
DisableAPIServerFloatingIP: pointer.Bool(true),
APIServerFixedIP: pointer.String("10.0.0.1"),
@@ -605,8 +605,8 @@ var _ = Describe("OpenStackCluster controller", func() {
testCluster.SetName("subnet-filtering")
testCluster.Spec = infrav1.OpenStackClusterSpec{
Bastion: &infrav1.Bastion{
- Enabled: true,
- Instance: &instance,
+ Enabled: true,
+ Spec: &bastionSpec,
},
DisableAPIServerFloatingIP: pointer.Bool(true),
APIServerFixedIP: pointer.String("10.0.0.1"),
@@ -804,7 +804,7 @@ func TestGetBastionSecurityGroups(t *testing.T) {
openStackCluster := &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
Bastion: &infrav1.Bastion{
- Instance: &infrav1.OpenStackMachineSpec{
+ Spec: &infrav1.OpenStackMachineSpec{
SecurityGroups: []infrav1.SecurityGroupFilter{
{
ID: "sg-123",
diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md
index e6707e8405..b3ec0505bc 100644
--- a/docs/book/src/api/v1beta1/api.md
+++ b/docs/book/src/api/v1beta1/api.md
@@ -1087,7 +1087,7 @@ bool
-instance
+spec
OpenStackMachineSpec
@@ -1095,7 +1095,11 @@ OpenStackMachineSpec
|
- Instance for the bastion itself
+Spec for the bastion itself
+
+
+
|
@@ -1107,7 +1111,7 @@ string
|
(Optional)
- AvailabilityZone is the failure domain that will be used to create the Bastion Instance.
+AvailabilityZone is the failure domain that will be used to create the Bastion Spec.
|
diff --git a/docs/book/src/clusteropenstack/configuration.md b/docs/book/src/clusteropenstack/configuration.md
index 6171fb968d..cb9e20360a 100644
--- a/docs/book/src/clusteropenstack/configuration.md
+++ b/docs/book/src/clusteropenstack/configuration.md
@@ -693,7 +693,7 @@ spec:
...
bastion:
enabled: true
- instance:
+ spec:
flavor:
image:
sshKeyName:
diff --git a/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md b/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
index 64ece98c60..36d68a5b19 100644
--- a/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
+++ b/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
@@ -28,6 +28,7 @@
- [Change to network](#change-to-network)
- [Change to networkMtu](#change-to-networkmtu)
- [Changes to apiServerLoadBalancer](#changes-to-apiserverloadbalancer)
+ - [Changes to bastion](#changes-to-bastion)
- [Changes to filters](#changes-to-filters)
- [Changes to filter tags](#changes-to-filter-tags)
- [Field capitalization consistency](#field-capitalization-consistency)
@@ -364,6 +365,30 @@ spec:
apiServerLoadBalancer: {}
```
+#### Changes to bastion
+
+In v1beta1, `OpenStackCluster.spec.bastion.instance` becomes `OpenStackCluster.spec.bastion.spec`.
+
+```yaml
+spec:
+ ...
+ bastion:
+ instance:
+ image:
+ name: foobar
+```
+
+becomes
+
+```yaml
+spec:
+ ...
+ bastion:
+ spec:
+ image:
+ name: foobar
+```
+
### Changes to filters
#### Changes to filter tags
diff --git a/pkg/cloud/services/compute/instance_types.go b/pkg/cloud/services/compute/instance_types.go
index 6c9c211936..5457d39bd1 100644
--- a/pkg/cloud/services/compute/instance_types.go
+++ b/pkg/cloud/services/compute/instance_types.go
@@ -29,9 +29,6 @@ import (
)
// InstanceSpec defines the fields which can be set on a new OpenStack instance.
-//
-// InstanceSpec does not contain all of the fields of infrav1.Instance, as not
-// all of them can be set on a new instance.
type InstanceSpec struct {
Name string
ImageID string
diff --git a/pkg/webhooks/openstackcluster_webhook_test.go b/pkg/webhooks/openstackcluster_webhook_test.go
index d1d04c16eb..3d65376486 100644
--- a/pkg/webhooks/openstackcluster_webhook_test.go
+++ b/pkg/webhooks/openstackcluster_webhook_test.go
@@ -84,7 +84,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
CloudName: "foobar",
},
Bastion: &infrav1.Bastion{
- Instance: &infrav1.OpenStackMachineSpec{
+ Spec: &infrav1.OpenStackMachineSpec{
Image: infrav1.ImageFilter{Name: pointer.String("foobar")},
Flavor: "minimal",
},
@@ -104,7 +104,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
CloudName: "foobar",
},
Bastion: &infrav1.Bastion{
- Instance: &infrav1.OpenStackMachineSpec{
+ Spec: &infrav1.OpenStackMachineSpec{
Image: infrav1.ImageFilter{Name: pointer.String("foobarbaz")},
Flavor: "medium",
},
@@ -452,7 +452,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
Bastion: &infrav1.Bastion{
Enabled: true,
- Instance: &infrav1.OpenStackMachineSpec{
+ Spec: &infrav1.OpenStackMachineSpec{
Flavor: "m1.small",
Image: infrav1.ImageFilter{Name: pointer.String("ubuntu")},
},
@@ -479,7 +479,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
Bastion: &infrav1.Bastion{
Enabled: false,
- Instance: &infrav1.OpenStackMachineSpec{
+ Spec: &infrav1.OpenStackMachineSpec{
Flavor: "m1.small",
Image: infrav1.ImageFilter{Name: pointer.String("ubuntu")},
},
diff --git a/test/e2e/data/kustomize/common-patches/cni/patch-cluster.yaml b/test/e2e/data/kustomize/common-patches/cni/patch-cluster.yaml
index 26f94a6d4a..23bc8f4fdf 100644
--- a/test/e2e/data/kustomize/common-patches/cni/patch-cluster.yaml
+++ b/test/e2e/data/kustomize/common-patches/cni/patch-cluster.yaml
@@ -3,7 +3,7 @@
path: /spec/bastion
value:
enabled: true
- instance:
+ spec:
flavor: ${OPENSTACK_BASTION_MACHINE_FLAVOR}
image:
name: ${OPENSTACK_BASTION_IMAGE_NAME}
diff --git a/test/e2e/data/kustomize/v1alpha6/bastion.yaml b/test/e2e/data/kustomize/v1alpha6/bastion.yaml
index 45c9e0f508..5296978b46 100644
--- a/test/e2e/data/kustomize/v1alpha6/bastion.yaml
+++ b/test/e2e/data/kustomize/v1alpha6/bastion.yaml
@@ -3,7 +3,7 @@
path: /spec/bastion
value:
enabled: true
- instance:
+ spec:
flavor: ${OPENSTACK_BASTION_MACHINE_FLAVOR}
image: ${OPENSTACK_BASTION_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
diff --git a/test/e2e/data/kustomize/v1alpha7/bastion.yaml b/test/e2e/data/kustomize/v1alpha7/bastion.yaml
index 45c9e0f508..5296978b46 100644
--- a/test/e2e/data/kustomize/v1alpha7/bastion.yaml
+++ b/test/e2e/data/kustomize/v1alpha7/bastion.yaml
@@ -3,7 +3,7 @@
path: /spec/bastion
value:
enabled: true
- instance:
+ spec:
flavor: ${OPENSTACK_BASTION_MACHINE_FLAVOR}
image: ${OPENSTACK_BASTION_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
diff --git a/test/e2e/suites/apivalidations/openstackcluster_test.go b/test/e2e/suites/apivalidations/openstackcluster_test.go
index 299715a161..f84e1d13d7 100644
--- a/test/e2e/suites/apivalidations/openstackcluster_test.go
+++ b/test/e2e/suites/apivalidations/openstackcluster_test.go
@@ -88,17 +88,17 @@ var _ = Describe("OpenStackCluster API validations", func() {
Expect(fetchedCluster.Spec.APIServerLoadBalancer.IsEnabled()).To(BeFalse(), "APIServerLoadBalancer.Enabled should not have been defaulted")
})
- It("should allow bastion.enabled=true with an instance", func() {
+ It("should allow bastion.enabled=true with a spec", func() {
cluster.Spec.Bastion = &infrav1.Bastion{
Enabled: true,
- Instance: &infrav1.OpenStackMachineSpec{
+ Spec: &infrav1.OpenStackMachineSpec{
Image: infrav1.ImageFilter{Name: pointer.String("fake-image")},
},
}
Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
})
- It("should not allow bastion.enabled=true without an instance", func() {
+ It("should not allow bastion.enabled=true without a spec", func() {
cluster.Spec.Bastion = &infrav1.Bastion{
Enabled: true,
}
@@ -119,7 +119,7 @@ var _ = Describe("OpenStackCluster API validations", func() {
It("should allow IPv4 as bastion floatingIP", func() {
cluster.Spec.Bastion = &infrav1.Bastion{
Enabled: true,
- Instance: &infrav1.OpenStackMachineSpec{
+ Spec: &infrav1.OpenStackMachineSpec{
Image: infrav1.ImageFilter{Name: pointer.String("fake-image")},
},
FloatingIP: pointer.String("10.0.0.0"),
@@ -130,7 +130,7 @@ var _ = Describe("OpenStackCluster API validations", func() {
It("should not allow non-IPv4 as bastion floating IP", func() {
cluster.Spec.Bastion = &infrav1.Bastion{
Enabled: true,
- Instance: &infrav1.OpenStackMachineSpec{
+ Spec: &infrav1.OpenStackMachineSpec{
Image: infrav1.ImageFilter{Name: pointer.String("fake-image")},
},
FloatingIP: pointer.String("foobar"),
diff --git a/test/e2e/suites/e2e/e2e_test.go b/test/e2e/suites/e2e/e2e_test.go
index e57c5bdd99..c8fdc0aea6 100644
--- a/test/e2e/suites/e2e/e2e_test.go
+++ b/test/e2e/suites/e2e/e2e_test.go
@@ -227,7 +227,7 @@ var _ = Describe("e2e tests [PR-Blocking]", func() {
Expect(err).NotTo(HaveOccurred())
openStackClusterWithNewBastionFlavor := openStackCluster.DeepCopy()
openStackClusterWithNewBastionFlavor.Spec.Bastion = bastionSpec
- openStackClusterWithNewBastionFlavor.Spec.Bastion.Instance.Flavor = bastionNewFlavorName
+ openStackClusterWithNewBastionFlavor.Spec.Bastion.Spec.Flavor = bastionNewFlavorName
Expect(e2eCtx.Environment.BootstrapClusterProxy.GetClient().Update(ctx, openStackClusterWithNewBastionFlavor)).To(Succeed())
Eventually(
func() (bool, error) {
From ad3fd18ad26511faf17dcb231590d41a73064049 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Wed, 20 Mar 2024 16:52:29 +0000
Subject: [PATCH 141/180] Fix server metadata length validation
---
api/v1beta1/openstackmachine_types.go | 6 ++--
...re.cluster.x-k8s.io_openstackclusters.yaml | 10 +++---
...er.x-k8s.io_openstackclustertemplates.yaml | 10 +++---
...re.cluster.x-k8s.io_openstackmachines.yaml | 10 +++---
...er.x-k8s.io_openstackmachinetemplates.yaml | 10 +++---
docs/book/src/api/v1beta1/api.md | 6 ++--
.../apivalidations/openstackmachine_test.go | 31 +++++++++++++++++++
7 files changed, 53 insertions(+), 30 deletions(-)
diff --git a/api/v1beta1/openstackmachine_types.go b/api/v1beta1/openstackmachine_types.go
index 52caccbaf1..17249383d4 100644
--- a/api/v1beta1/openstackmachine_types.go
+++ b/api/v1beta1/openstackmachine_types.go
@@ -101,11 +101,13 @@ type OpenStackMachineSpec struct {
type ServerMetadata struct {
// Key is the server metadata key
- // kubebuilder:validation:MaxLength:=255
+ // +kubebuilder:validation:MaxLength:=255
+ // +kubebuilder:validation:Required
Key string `json:"key"`
// Value is the server metadata value
- // kubebuilder:validation:MaxLength:=255
+ // +kubebuilder:validation:MaxLength:=255
+ // +kubebuilder:validation:Required
Value string `json:"value"`
}
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 30ae084647..88d9ebb896 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -5536,14 +5536,12 @@ spec:
items:
properties:
key:
- description: |-
- Key is the server metadata key
- kubebuilder:validation:MaxLength:=255
+ description: Key is the server metadata key
+ maxLength: 255
type: string
value:
- description: |-
- Value is the server metadata value
- kubebuilder:validation:MaxLength:=255
+ description: Value is the server metadata value
+ maxLength: 255
type: string
required:
- key
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 f577f0eb3b..85ff200d31 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -2970,14 +2970,12 @@ spec:
items:
properties:
key:
- description: |-
- Key is the server metadata key
- kubebuilder:validation:MaxLength:=255
+ description: Key is the server metadata key
+ maxLength: 255
type: string
value:
- description: |-
- Value is the server metadata value
- kubebuilder:validation:MaxLength:=255
+ description: Value is the server metadata value
+ maxLength: 255
type: string
required:
- key
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 26e74f69e6..2067fad50e 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
@@ -2318,14 +2318,12 @@ spec:
items:
properties:
key:
- description: |-
- Key is the server metadata key
- kubebuilder:validation:MaxLength:=255
+ description: Key is the server metadata key
+ maxLength: 255
type: string
value:
- description: |-
- Value is the server metadata value
- kubebuilder:validation:MaxLength:=255
+ description: Value is the server metadata value
+ maxLength: 255
type: string
required:
- key
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 0780b5e09f..b71228fa4a 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
@@ -1997,14 +1997,12 @@ spec:
items:
properties:
key:
- description: |-
- Key is the server metadata key
- kubebuilder:validation:MaxLength:=255
+ description: Key is the server metadata key
+ maxLength: 255
type: string
value:
- description: |-
- Value is the server metadata value
- kubebuilder:validation:MaxLength:=255
+ description: Value is the server metadata value
+ maxLength: 255
type: string
required:
- key
diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md
index 2b12258bef..58b54fa8ae 100644
--- a/docs/book/src/api/v1beta1/api.md
+++ b/docs/book/src/api/v1beta1/api.md
@@ -4469,8 +4469,7 @@ string
|
- Key is the server metadata key
-kubebuilder:validation:MaxLength:=255
+Key is the server metadata key
|
@@ -4481,8 +4480,7 @@ string
|
- Value is the server metadata value
-kubebuilder:validation:MaxLength:=255
+Value is the server metadata value
|
diff --git a/test/e2e/suites/apivalidations/openstackmachine_test.go b/test/e2e/suites/apivalidations/openstackmachine_test.go
index 00f262cc0b..c984ab1e61 100644
--- a/test/e2e/suites/apivalidations/openstackmachine_test.go
+++ b/test/e2e/suites/apivalidations/openstackmachine_test.go
@@ -17,6 +17,8 @@ limitations under the License.
package apivalidations
import (
+ "strings"
+
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
@@ -54,4 +56,33 @@ var _ = Describe("OpenStackMachine API validations", func() {
machine.Spec.ProviderID = pointer.String("bar")
Expect(k8sClient.Update(ctx, machine)).NotTo(Succeed(), "Updating providerID should fail")
})
+
+ It("should not allow server metadata to exceed 255 characters", func() {
+ By("Creating a machine with a metadata key that is too long")
+ machine.Spec.ServerMetadata = []infrav1.ServerMetadata{
+ {
+ Key: strings.Repeat("a", 256),
+ Value: "value",
+ },
+ }
+ Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "Creating a machine with a long metadata key should fail")
+
+ By("Creating a machine with a metadata value that is too long")
+ machine.Spec.ServerMetadata = []infrav1.ServerMetadata{
+ {
+ Key: "key",
+ Value: strings.Repeat("a", 256),
+ },
+ }
+ Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "Creating a machine with a long metadata value should fail")
+
+ By("Creating a machine with a metadata key and value of 255 characters should succeed")
+ machine.Spec.ServerMetadata = []infrav1.ServerMetadata{
+ {
+ Key: strings.Repeat("a", 255),
+ Value: strings.Repeat("b", 255),
+ },
+ }
+ Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "Creating a machine with max metadata key and value should succeed")
+ })
})
From 61b056060e869d8a43e767d386aa79cbd6716393 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Thu, 21 Mar 2024 16:32:04 +0000
Subject: [PATCH 142/180] Revert accidental update to previous API templates
---
test/e2e/data/kustomize/v1alpha6/bastion.yaml | 2 +-
test/e2e/data/kustomize/v1alpha7/bastion.yaml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/test/e2e/data/kustomize/v1alpha6/bastion.yaml b/test/e2e/data/kustomize/v1alpha6/bastion.yaml
index 5296978b46..45c9e0f508 100644
--- a/test/e2e/data/kustomize/v1alpha6/bastion.yaml
+++ b/test/e2e/data/kustomize/v1alpha6/bastion.yaml
@@ -3,7 +3,7 @@
path: /spec/bastion
value:
enabled: true
- spec:
+ instance:
flavor: ${OPENSTACK_BASTION_MACHINE_FLAVOR}
image: ${OPENSTACK_BASTION_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
diff --git a/test/e2e/data/kustomize/v1alpha7/bastion.yaml b/test/e2e/data/kustomize/v1alpha7/bastion.yaml
index 5296978b46..45c9e0f508 100644
--- a/test/e2e/data/kustomize/v1alpha7/bastion.yaml
+++ b/test/e2e/data/kustomize/v1alpha7/bastion.yaml
@@ -3,7 +3,7 @@
path: /spec/bastion
value:
enabled: true
- spec:
+ instance:
flavor: ${OPENSTACK_BASTION_MACHINE_FLAVOR}
image: ${OPENSTACK_BASTION_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
From 8017c89044c8d36559dae5d7ade60650ce6a9b9e Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Fri, 15 Mar 2024 13:15:50 +0000
Subject: [PATCH 143/180] Store []ResolvedPortSpec in
ReferencedMachineResources
The purpose of this change is fix an issue where we are storing
unresolved references in ReferencedMachineResources. Specifically we are
storing a PortOpts, which is a user-intent struct. PortOpts can contain
unresolved references to both subnets and security groups, as well
fields requiring additional processing which reference external objects:
the port name, description, and tags.
We create a new type, ResolvedPortSpec, which can contain only fully
resolved data. This can be seen in the new signature of CreatePorts(),
which no longer requires any source of data other than the
[]ResolvedPortSpec from ReferencedMachineResources, and is now greatly
simplified.
Fully resolving the port name also allows a simplification in port
adoption.
All of the complexity now moves to ConstructPorts(), which is updated to
return []ResolvedPortSpec instead of []PortOpts. ConstructPorts() is
updated to resolve security groups, port name, description, and all
subnets referenced in FixedIPs.
---
api/v1alpha5/zz_generated.conversion.go | 60 +-
api/v1alpha6/conversion_test.go | 8 +-
api/v1alpha6/zz_generated.conversion.go | 62 +-
api/v1alpha7/types_conversion.go | 67 +
api/v1alpha7/zz_generated.conversion.go | 64 +-
api/v1beta1/openstackmachine_types.go | 4 +-
api/v1beta1/types.go | 100 +-
api/v1beta1/zz_generated.deepcopy.go | 187 ++-
...re.cluster.x-k8s.io_openstackclusters.yaml | 250 +---
...er.x-k8s.io_openstackclustertemplates.yaml | 4 +-
...re.cluster.x-k8s.io_openstackmachines.yaml | 250 +---
...er.x-k8s.io_openstackmachinetemplates.yaml | 4 +-
controllers/openstackcluster_controller.go | 92 +-
.../openstackcluster_controller_test.go | 79 +-
controllers/openstackmachine_controller.go | 77 +-
.../openstackmachine_controller_test.go | 321 +----
docs/book/src/api/v1beta1/api.md | 409 ++++--
.../services/compute/dependent_resources.go | 4 +-
pkg/cloud/services/compute/instance_test.go | 9 +-
pkg/cloud/services/compute/instance_types.go | 2 -
.../services/compute/referenced_resources.go | 29 +-
.../compute/referenced_resources_test.go | 297 +++--
pkg/cloud/services/networking/network_test.go | 6 +-
pkg/cloud/services/networking/port.go | 392 +++---
pkg/cloud/services/networking/port_test.go | 1154 +++++++++--------
pkg/cloud/services/networking/trunk.go | 14 +-
pkg/cloud/services/networking/trunk_test.go | 57 +-
pkg/utils/names/names.go | 6 +
test/e2e/suites/e2e/e2e_test.go | 5 +-
29 files changed, 1839 insertions(+), 2174 deletions(-)
diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go
index 2acff1d4aa..60a6ff055b 100644
--- a/api/v1alpha5/zz_generated.conversion.go
+++ b/api/v1alpha5/zz_generated.conversion.go
@@ -1352,10 +1352,8 @@ func autoConvert_v1alpha5_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *v1beta
if err := optional.Convert_string_To_optional_String(&in.Description, &out.Description, s); err != nil {
return err
}
- out.AdminStateUp = (*bool)(unsafe.Pointer(in.AdminStateUp))
- if err := optional.Convert_string_To_optional_String(&in.MACAddress, &out.MACAddress, 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))
@@ -1371,26 +1369,12 @@ func autoConvert_v1alpha5_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *v1beta
// 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
- if in.AllowedAddressPairs != nil {
- in, out := &in.AllowedAddressPairs, &out.AllowedAddressPairs
- *out = make([]v1beta1.AddressPair, len(*in))
- for i := range *in {
- if err := Convert_v1alpha5_AddressPair_To_v1beta1_AddressPair(&(*in)[i], &(*out)[i], s); err != nil {
- return err
- }
- }
- } else {
- out.AllowedAddressPairs = nil
- }
+ // WARNING: in.AllowedAddressPairs requires manual conversion: does not exist in peer-type
out.Trunk = (*bool)(unsafe.Pointer(in.Trunk))
- if err := optional.Convert_string_To_optional_String(&in.HostID, &out.HostID, s); err != nil {
- return err
- }
- if err := optional.Convert_string_To_optional_String(&in.VNICType, &out.VNICType, s); err != nil {
- return err
- }
- // WARNING: in.Profile requires manual conversion: inconvertible types (map[string]string vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.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
}
@@ -1405,14 +1389,10 @@ func autoConvert_v1beta1_PortOpts_To_v1alpha5_PortOpts(in *v1beta1.PortOpts, out
} else {
out.Network = nil
}
- if err := optional.Convert_optional_String_To_string(&in.NameSuffix, &out.NameSuffix, s); err != nil {
- return err
- }
if err := optional.Convert_optional_String_To_string(&in.Description, &out.Description, s); err != nil {
return err
}
- out.AdminStateUp = (*bool)(unsafe.Pointer(in.AdminStateUp))
- if err := optional.Convert_optional_String_To_string(&in.MACAddress, &out.MACAddress, s); err != nil {
+ if err := optional.Convert_optional_String_To_string(&in.NameSuffix, &out.NameSuffix, s); err != nil {
return err
}
if in.FixedIPs != nil {
@@ -1437,29 +1417,9 @@ func autoConvert_v1beta1_PortOpts_To_v1alpha5_PortOpts(in *v1beta1.PortOpts, out
} else {
out.SecurityGroups = nil
}
- if in.AllowedAddressPairs != nil {
- in, out := &in.AllowedAddressPairs, &out.AllowedAddressPairs
- *out = make([]AddressPair, len(*in))
- for i := range *in {
- if err := Convert_v1beta1_AddressPair_To_v1alpha5_AddressPair(&(*in)[i], &(*out)[i], s); err != nil {
- return err
- }
- }
- } else {
- out.AllowedAddressPairs = nil
- }
- out.Trunk = (*bool)(unsafe.Pointer(in.Trunk))
- if err := optional.Convert_optional_String_To_string(&in.HostID, &out.HostID, s); err != nil {
- return err
- }
- if err := optional.Convert_optional_String_To_string(&in.VNICType, &out.VNICType, s); err != nil {
- return err
- }
- // WARNING: in.Profile requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.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
}
diff --git a/api/v1alpha6/conversion_test.go b/api/v1alpha6/conversion_test.go
index 984d7ffb46..3e5484cafd 100644
--- a/api/v1alpha6/conversion_test.go
+++ b/api/v1alpha6/conversion_test.go
@@ -570,7 +570,9 @@ func TestPortOptsConvertTo(t *testing.T) {
SecurityGroups: uuids,
}},
hubPortOpts: []infrav1.PortOpts{{
- Profile: &convertedPortProfile,
+ ResolvedPortSpecFields: infrav1.ResolvedPortSpecFields{
+ Profile: &convertedPortProfile,
+ },
SecurityGroups: securityGroupsUuids,
}},
},
@@ -582,7 +584,9 @@ func TestPortOptsConvertTo(t *testing.T) {
SecurityGroupFilters: securityGroupFilter,
}},
hubPortOpts: []infrav1.PortOpts{{
- Profile: &convertedPortProfile,
+ ResolvedPortSpecFields: infrav1.ResolvedPortSpecFields{
+ Profile: &convertedPortProfile,
+ },
SecurityGroups: securityGroupFilterMerged,
}},
},
diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go
index a6dcc278d4..b38e4436e2 100644
--- a/api/v1alpha6/zz_generated.conversion.go
+++ b/api/v1alpha6/zz_generated.conversion.go
@@ -1387,10 +1387,8 @@ func autoConvert_v1alpha6_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *v1beta
if err := optional.Convert_string_To_optional_String(&in.Description, &out.Description, s); err != nil {
return err
}
- out.AdminStateUp = (*bool)(unsafe.Pointer(in.AdminStateUp))
- if err := optional.Convert_string_To_optional_String(&in.MACAddress, &out.MACAddress, 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))
@@ -1406,28 +1404,14 @@ func autoConvert_v1alpha6_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *v1beta
// 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
- if in.AllowedAddressPairs != nil {
- in, out := &in.AllowedAddressPairs, &out.AllowedAddressPairs
- *out = make([]v1beta1.AddressPair, len(*in))
- for i := range *in {
- if err := Convert_v1alpha6_AddressPair_To_v1beta1_AddressPair(&(*in)[i], &(*out)[i], s); err != nil {
- return err
- }
- }
- } else {
- out.AllowedAddressPairs = nil
- }
+ // WARNING: in.AllowedAddressPairs requires manual conversion: does not exist in peer-type
out.Trunk = (*bool)(unsafe.Pointer(in.Trunk))
- if err := optional.Convert_string_To_optional_String(&in.HostID, &out.HostID, s); err != nil {
- return err
- }
- if err := optional.Convert_string_To_optional_String(&in.VNICType, &out.VNICType, s); err != nil {
- return err
- }
- // WARNING: in.Profile requires manual conversion: inconvertible types (map[string]string vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.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 = *(*[]v1beta1.ValueSpec)(unsafe.Pointer(&in.ValueSpecs))
+ // WARNING: in.ValueSpecs requires manual conversion: does not exist in peer-type
return nil
}
@@ -1441,14 +1425,10 @@ func autoConvert_v1beta1_PortOpts_To_v1alpha6_PortOpts(in *v1beta1.PortOpts, out
} else {
out.Network = nil
}
- if err := optional.Convert_optional_String_To_string(&in.NameSuffix, &out.NameSuffix, s); err != nil {
- return err
- }
if err := optional.Convert_optional_String_To_string(&in.Description, &out.Description, s); err != nil {
return err
}
- out.AdminStateUp = (*bool)(unsafe.Pointer(in.AdminStateUp))
- if err := optional.Convert_optional_String_To_string(&in.MACAddress, &out.MACAddress, s); err != nil {
+ if err := optional.Convert_optional_String_To_string(&in.NameSuffix, &out.NameSuffix, s); err != nil {
return err
}
if in.FixedIPs != nil {
@@ -1473,29 +1453,9 @@ func autoConvert_v1beta1_PortOpts_To_v1alpha6_PortOpts(in *v1beta1.PortOpts, out
} else {
out.SecurityGroups = nil
}
- if in.AllowedAddressPairs != nil {
- in, out := &in.AllowedAddressPairs, &out.AllowedAddressPairs
- *out = make([]AddressPair, len(*in))
- for i := range *in {
- if err := Convert_v1beta1_AddressPair_To_v1alpha6_AddressPair(&(*in)[i], &(*out)[i], s); err != nil {
- return err
- }
- }
- } else {
- out.AllowedAddressPairs = nil
- }
- out.Trunk = (*bool)(unsafe.Pointer(in.Trunk))
- if err := optional.Convert_optional_String_To_string(&in.HostID, &out.HostID, s); err != nil {
- return err
- }
- if err := optional.Convert_optional_String_To_string(&in.VNICType, &out.VNICType, s); err != nil {
- return err
- }
- // WARNING: in.Profile requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.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
}
diff --git a/api/v1alpha7/types_conversion.go b/api/v1alpha7/types_conversion.go
index 3c3d0629f2..98bdd6df26 100644
--- a/api/v1alpha7/types_conversion.go
+++ b/api/v1alpha7/types_conversion.go
@@ -17,6 +17,8 @@ limitations under the License.
package v1alpha7
import (
+ "errors"
+
apiconversion "k8s.io/apimachinery/pkg/conversion"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
@@ -217,6 +219,38 @@ func Convert_v1alpha7_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *infrav1.Po
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.SecurityGroupFilter, len(in.SecurityGroupFilters))
for i := range in.SecurityGroupFilters {
@@ -241,6 +275,39 @@ func Convert_v1beta1_PortOpts_To_v1alpha7_PortOpts(in *infrav1.PortOpts, out *Po
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 {
diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go
index 8264250f84..4d72d623f4 100644
--- a/api/v1alpha7/zz_generated.conversion.go
+++ b/api/v1alpha7/zz_generated.conversion.go
@@ -1587,10 +1587,8 @@ func autoConvert_v1alpha7_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *v1beta
if err := optional.Convert_string_To_optional_String(&in.Description, &out.Description, s); err != nil {
return err
}
- out.AdminStateUp = (*bool)(unsafe.Pointer(in.AdminStateUp))
- if err := optional.Convert_string_To_optional_String(&in.MACAddress, &out.MACAddress, 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))
@@ -1603,29 +1601,15 @@ func autoConvert_v1alpha7_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *v1beta
out.FixedIPs = nil
}
// WARNING: in.SecurityGroupFilters requires manual conversion: does not exist in peer-type
- if in.AllowedAddressPairs != nil {
- in, out := &in.AllowedAddressPairs, &out.AllowedAddressPairs
- *out = make([]v1beta1.AddressPair, len(*in))
- for i := range *in {
- if err := Convert_v1alpha7_AddressPair_To_v1beta1_AddressPair(&(*in)[i], &(*out)[i], s); err != nil {
- return err
- }
- }
- } else {
- out.AllowedAddressPairs = nil
- }
+ // WARNING: in.AllowedAddressPairs requires manual conversion: does not exist in peer-type
out.Trunk = (*bool)(unsafe.Pointer(in.Trunk))
- if err := optional.Convert_string_To_optional_String(&in.HostID, &out.HostID, s); err != nil {
- return err
- }
- if err := optional.Convert_string_To_optional_String(&in.VNICType, &out.VNICType, s); err != nil {
- return err
- }
- // WARNING: in.Profile requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7.BindingProfile vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.BindingProfile)
- out.DisablePortSecurity = (*bool)(unsafe.Pointer(in.DisablePortSecurity))
- out.PropagateUplinkStatus = (*bool)(unsafe.Pointer(in.PropagateUplinkStatus))
+ // 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))
- out.ValueSpecs = *(*[]v1beta1.ValueSpec)(unsafe.Pointer(&in.ValueSpecs))
+ // WARNING: in.ValueSpecs requires manual conversion: does not exist in peer-type
return nil
}
@@ -1639,14 +1623,10 @@ func autoConvert_v1beta1_PortOpts_To_v1alpha7_PortOpts(in *v1beta1.PortOpts, out
} else {
out.Network = nil
}
- if err := optional.Convert_optional_String_To_string(&in.NameSuffix, &out.NameSuffix, s); err != nil {
- return err
- }
if err := optional.Convert_optional_String_To_string(&in.Description, &out.Description, s); err != nil {
return err
}
- out.AdminStateUp = (*bool)(unsafe.Pointer(in.AdminStateUp))
- if err := optional.Convert_optional_String_To_string(&in.MACAddress, &out.MACAddress, s); err != nil {
+ if err := optional.Convert_optional_String_To_string(&in.NameSuffix, &out.NameSuffix, s); err != nil {
return err
}
if in.FixedIPs != nil {
@@ -1661,29 +1641,9 @@ func autoConvert_v1beta1_PortOpts_To_v1alpha7_PortOpts(in *v1beta1.PortOpts, out
out.FixedIPs = nil
}
// WARNING: in.SecurityGroups requires manual conversion: does not exist in peer-type
- if in.AllowedAddressPairs != nil {
- in, out := &in.AllowedAddressPairs, &out.AllowedAddressPairs
- *out = make([]AddressPair, len(*in))
- for i := range *in {
- if err := Convert_v1beta1_AddressPair_To_v1alpha7_AddressPair(&(*in)[i], &(*out)[i], s); err != nil {
- return err
- }
- }
- } else {
- out.AllowedAddressPairs = nil
- }
- out.Trunk = (*bool)(unsafe.Pointer(in.Trunk))
- if err := optional.Convert_optional_String_To_string(&in.HostID, &out.HostID, s); err != nil {
- return err
- }
- if err := optional.Convert_optional_String_To_string(&in.VNICType, &out.VNICType, s); err != nil {
- return err
- }
- // WARNING: in.Profile requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.BindingProfile vs sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7.BindingProfile)
- out.DisablePortSecurity = (*bool)(unsafe.Pointer(in.DisablePortSecurity))
- out.PropagateUplinkStatus = (*bool)(unsafe.Pointer(in.PropagateUplinkStatus))
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
}
diff --git a/api/v1beta1/openstackmachine_types.go b/api/v1beta1/openstackmachine_types.go
index 17249383d4..b4f3babef9 100644
--- a/api/v1beta1/openstackmachine_types.go
+++ b/api/v1beta1/openstackmachine_types.go
@@ -60,7 +60,9 @@ type OpenStackMachineSpec struct {
// 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"`
diff --git a/api/v1beta1/types.go b/api/v1beta1/types.go
index b8a524c54a..f5f8fcfa22 100644
--- a/api/v1beta1/types.go
+++ b/api/v1beta1/types.go
@@ -171,21 +171,13 @@ type PortOpts struct {
// +optional
Network *NetworkFilter `json:"network,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"`
-
// Description is a human-readable description for the port.
// +optional
Description optional.String `json:"description,omitempty"`
- // 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.
+ // 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
- MACAddress optional.String `json:"macAddress,omitempty"`
+ 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
@@ -197,13 +189,11 @@ type PortOpts struct {
// +listType=atomic
SecurityGroups []SecurityGroupFilter `json:"securityGroups,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.
+ // 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
- AllowedAddressPairs []AddressPair `json:"allowedAddressPairs,omitempty"`
+ 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
@@ -211,6 +201,29 @@ type PortOpts struct {
// +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"`
@@ -245,12 +258,6 @@ type PortOpts struct {
// +optional
PropagateUplinkStatus *bool `json:"propagateUplinkStatus,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"`
-
// 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.
@@ -260,6 +267,39 @@ type PortOpts struct {
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
@@ -290,6 +330,20 @@ type FixedIP struct {
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
@@ -616,7 +670,7 @@ type ReferencedMachineResources struct {
// Ports is the fully resolved list of ports to create for the machine.
// +optional
- Ports []PortOpts `json:"ports,omitempty"`
+ Ports []ResolvedPortSpec `json:"ports,omitempty"`
}
type DependentMachineResources struct {
diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go
index 2ffc417727..98c11cbbf4 100644
--- a/api/v1beta1/zz_generated.deepcopy.go
+++ b/api/v1beta1/zz_generated.deepcopy.go
@@ -1093,23 +1093,13 @@ func (in *PortOpts) DeepCopyInto(out *PortOpts) {
*out = new(NetworkFilter)
(*in).DeepCopyInto(*out)
}
- if in.NameSuffix != nil {
- in, out := &in.NameSuffix, &out.NameSuffix
- *out = new(string)
- **out = **in
- }
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)
- **out = **in
- }
- if in.MACAddress != nil {
- in, out := &in.MACAddress, &out.MACAddress
+ if in.NameSuffix != nil {
+ in, out := &in.NameSuffix, &out.NameSuffix
*out = new(string)
**out = **in
}
@@ -1127,53 +1117,17 @@ func (in *PortOpts) DeepCopyInto(out *PortOpts) {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
- 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.Trunk != nil {
- in, out := &in.Trunk, &out.Trunk
- *out = new(bool)
- **out = **in
- }
- 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)
- **out = **in
- }
- if in.PropagateUplinkStatus != nil {
- in, out := &in.PropagateUplinkStatus, &out.PropagateUplinkStatus
- *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))
- copy(*out, *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.
@@ -1206,7 +1160,7 @@ func (in *ReferencedMachineResources) DeepCopyInto(out *ReferencedMachineResourc
*out = *in
if in.Ports != nil {
in, out := &in.Ports, &out.Ports
- *out = make([]PortOpts, len(*in))
+ *out = make([]ResolvedPortSpec, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
@@ -1223,6 +1177,131 @@ func (in *ReferencedMachineResources) DeepCopy() *ReferencedMachineResources {
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 *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 {
+ in, out := &in.Trunk, &out.Trunk
+ *out = new(bool)
+ **out = **in
+ }
+ 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)
+ **out = **in
+ }
+ if in.PropagateUplinkStatus != nil {
+ in, out := &in.PropagateUplinkStatus, &out.PropagateUplinkStatus
+ *out = new(bool)
+ **out = **in
+ }
+ if in.ValueSpecs != nil {
+ in, out := &in.ValueSpecs, &out.ValueSpecs
+ *out = make([]ValueSpec, len(*in))
+ copy(*out, *in)
+ }
+}
+
+// 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(ResolvedPortSpecFields)
+ in.DeepCopyInto(out)
+ return out
+}
+
// 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
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 d02a6db1b0..3130c26513 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -5563,7 +5563,9 @@ spec:
type: string
tags:
description: |-
- 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!
items:
type: string
@@ -6275,6 +6277,8 @@ spec:
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
@@ -6319,91 +6323,20 @@ spec:
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 Subnet
+ 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: |-
- 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
- description:
- type: string
- gatewayIP:
- type: string
- id:
- 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
+ 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
@@ -6416,78 +6349,13 @@ spec:
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.
+ 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
- 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
- id:
- 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
profile:
description: |-
Profile is a set of key-value pairs that are used for binding
@@ -6512,88 +6380,22 @@ spec:
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.
+ description: SecurityGroups is a list of security group
+ IDs to assign to the port.
items:
- properties:
- description:
- type: string
- id:
- 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
+ type: string
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.
+ 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. If not
- provided the value is inherited from the machine, or false for a
- bastion host.
+ description: Trunk specifies whether trunking is enabled
+ at the port level.
type: boolean
valueSpecs:
description: |-
@@ -6636,6 +6438,10 @@ spec:
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:
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 7d67ac96de..66b4e12174 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -2997,7 +2997,9 @@ spec:
type: string
tags:
description: |-
- 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!
items:
type: string
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 2067fad50e..74bbae9e0b 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
@@ -2338,7 +2338,9 @@ spec:
type: string
tags:
description: |-
- 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!
items:
type: string
@@ -2480,6 +2482,8 @@ spec:
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
@@ -2524,91 +2528,20 @@ spec:
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 Subnet
+ 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: |-
- 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
- description:
- type: string
- gatewayIP:
- type: string
- id:
- 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
+ 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
@@ -2620,78 +2553,13 @@ spec:
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.
+ 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
- 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
- id:
- 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
profile:
description: |-
Profile is a set of key-value pairs that are used for binding
@@ -2716,88 +2584,22 @@ spec:
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.
+ description: SecurityGroups is a list of security group
+ IDs to assign to the port.
items:
- properties:
- description:
- type: string
- id:
- 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
+ type: string
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.
+ 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. If not
- provided the value is inherited from the machine, or false for a
- bastion host.
+ description: Trunk specifies whether trunking is enabled
+ at the port level.
type: boolean
valueSpecs:
description: |-
@@ -2839,6 +2641,10 @@ spec:
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:
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 b71228fa4a..12d3b1ea40 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
@@ -2017,7 +2017,9 @@ spec:
type: string
tags:
description: |-
- 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!
items:
type: string
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index 61ea41cff2..9b659b7174 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -52,6 +52,7 @@ import (
"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/filterconvert"
+ "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/names"
)
const (
@@ -147,11 +148,13 @@ func (r *OpenStackClusterReconciler) reconcileDelete(ctx context.Context, scope
return ctrl.Result{RequeueAfter: 5 * time.Second}, nil
}
+ clusterName := names.ClusterName(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, openStackCluster); err != nil {
+ if _, err := resolveBastionResources(scope, clusterName, openStackCluster); err != nil {
return reconcile.Result{}, err
}
@@ -165,8 +168,6 @@ 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.IsEnabled() {
loadBalancerService, err := loadbalancer.NewService(scope)
if err != nil {
@@ -217,7 +218,8 @@ func contains(arr []string, target string) bool {
return false
}
-func resolveBastionResources(scope *scope.WithLogger, openStackCluster *infrav1.OpenStackCluster) (bool, error) {
+func resolveBastionResources(scope *scope.WithLogger, clusterName string, openStackCluster *infrav1.OpenStackCluster) (bool, error) {
+ // Resolve and store referenced & dependent resources for the bastion
if openStackCluster.Spec.Bastion != nil && openStackCluster.Spec.Bastion.Enabled {
if openStackCluster.Status.Bastion == nil {
openStackCluster.Status.Bastion = &infrav1.BastionStatus{}
@@ -225,7 +227,10 @@ func resolveBastionResources(scope *scope.WithLogger, openStackCluster *infrav1.
if openStackCluster.Spec.Bastion.Spec == nil {
return false, fmt.Errorf("bastion spec is nil when bastion is enabled, this shouldn't happen")
}
- changed, err := compute.ResolveReferencedMachineResources(scope, openStackCluster, openStackCluster.Spec.Bastion.Spec, &openStackCluster.Status.Bastion.ReferencedResources)
+ changed, err := compute.ResolveReferencedMachineResources(scope,
+ openStackCluster.Spec.Bastion.Spec, &openStackCluster.Status.Bastion.ReferencedResources,
+ clusterName, bastionName(clusterName),
+ openStackCluster, getBastionSecurityGroupID(openStackCluster))
if err != nil {
return false, err
}
@@ -235,7 +240,6 @@ func resolveBastionResources(scope *scope.WithLogger, openStackCluster *infrav1.
}
err = compute.AdoptDependentMachineResources(scope,
- bastionName(openStackCluster.Name),
&openStackCluster.Status.Bastion.ReferencedResources,
&openStackCluster.Status.Bastion.DependentResources)
if err != nil {
@@ -383,7 +387,8 @@ func reconcileNormal(scope *scope.WithLogger, cluster *clusterv1.Cluster, openSt
func reconcileBastion(scope *scope.WithLogger, cluster *clusterv1.Cluster, openStackCluster *infrav1.OpenStackCluster) (*ctrl.Result, error) {
scope.Logger().V(4).Info("Reconciling Bastion")
- changed, err := resolveBastionResources(scope, openStackCluster)
+ clusterName := names.ClusterName(cluster)
+ changed, err := resolveBastionResources(scope, clusterName, openStackCluster)
if err != nil {
return nil, err
}
@@ -420,7 +425,6 @@ func reconcileBastion(scope *scope.WithLogger, cluster *clusterv1.Cluster, openS
if err != nil {
return nil, err
}
- clusterName := fmt.Sprintf("%s-%s", cluster.Namespace, cluster.Name)
bastionHash, err := compute.HashInstanceSpec(instanceSpec)
if err != nil {
@@ -436,7 +440,7 @@ func reconcileBastion(scope *scope.WithLogger, cluster *clusterv1.Cluster, openS
return &reconcile.Result{}, nil
}
- err = getOrCreateBastionPorts(openStackCluster, networkingService, cluster.Name)
+ err = getOrCreateBastionPorts(openStackCluster, networkingService)
if err != nil {
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)
@@ -529,41 +533,30 @@ func bastionAddFloatingIP(openStackCluster *infrav1.OpenStackCluster, clusterNam
}
func bastionToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, cluster *clusterv1.Cluster) (*compute.InstanceSpec, error) {
- if openStackCluster.Spec.Bastion == nil {
+ bastion := openStackCluster.Spec.Bastion
+ if bastion == nil {
return nil, fmt.Errorf("bastion spec is nil")
}
- if openStackCluster.Spec.Bastion.Spec == nil {
+ 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.
- openStackCluster.Spec.Bastion.Spec = &infrav1.OpenStackMachineSpec{}
+ bastion.Spec = &infrav1.OpenStackMachineSpec{}
}
+ referencedResources := &openStackCluster.Status.Bastion.ReferencedResources
- if openStackCluster.Status.Bastion == nil {
- return nil, fmt.Errorf("bastion status is nil")
- }
+ machineSpec := bastion.Spec
instanceSpec := &compute.InstanceSpec{
- Name: bastionName(cluster.Name),
- Flavor: openStackCluster.Spec.Bastion.Spec.Flavor,
- SSHKeyName: openStackCluster.Spec.Bastion.Spec.SSHKeyName,
- ImageID: openStackCluster.Status.Bastion.ReferencedResources.ImageID,
- RootVolume: openStackCluster.Spec.Bastion.Spec.RootVolume,
+ Name: bastionName(cluster.Name),
+ Flavor: machineSpec.Flavor,
+ SSHKeyName: machineSpec.SSHKeyName,
+ ImageID: referencedResources.ImageID,
+ RootVolume: machineSpec.RootVolume,
+ ServerGroupID: referencedResources.ServerGroupID,
+ Tags: compute.InstanceTags(machineSpec, openStackCluster),
}
- if openStackCluster.Spec.Bastion.AvailabilityZone != nil {
- instanceSpec.FailureDomain = *openStackCluster.Spec.Bastion.AvailabilityZone
+ if bastion.AvailabilityZone != nil {
+ instanceSpec.FailureDomain = *bastion.AvailabilityZone
}
-
- instanceSpec.SecurityGroups = openStackCluster.Spec.Bastion.Spec.SecurityGroups
- if openStackCluster.Spec.ManagedSecurityGroups != nil {
- if openStackCluster.Status.BastionSecurityGroup != nil {
- instanceSpec.SecurityGroups = append(instanceSpec.SecurityGroups, infrav1.SecurityGroupFilter{
- ID: openStackCluster.Status.BastionSecurityGroup.ID,
- })
- }
- }
- instanceSpec.SecurityGroups = getBastionSecurityGroups(openStackCluster)
-
- instanceSpec.Ports = openStackCluster.Spec.Bastion.Spec.Ports
-
return instanceSpec, nil
}
@@ -571,29 +564,20 @@ func bastionName(clusterName string) string {
return fmt.Sprintf("%s-bastion", clusterName)
}
-// getBastionSecurityGroups returns a combination of openStackCluster.Spec.Bastion.Spec.SecurityGroups
-// and the security group managed by the OpenStackCluster.
-func getBastionSecurityGroups(openStackCluster *infrav1.OpenStackCluster) []infrav1.SecurityGroupFilter {
- instanceSpecSecurityGroups := openStackCluster.Spec.Bastion.Spec.SecurityGroups
-
+// 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 instanceSpecSecurityGroups
+ return nil
}
- var managedSecurityGroup string
if openStackCluster.Status.BastionSecurityGroup != nil {
- managedSecurityGroup = openStackCluster.Status.BastionSecurityGroup.ID
+ return &openStackCluster.Status.BastionSecurityGroup.ID
}
-
- if managedSecurityGroup != "" {
- instanceSpecSecurityGroups = append(instanceSpecSecurityGroups, infrav1.SecurityGroupFilter{
- ID: managedSecurityGroup,
- })
- }
- return instanceSpecSecurityGroups
+ return nil
}
-func getOrCreateBastionPorts(openStackCluster *infrav1.OpenStackCluster, networkingService *networking.Service, clusterName string) error {
+func getOrCreateBastionPorts(openStackCluster *infrav1.OpenStackCluster, networkingService *networking.Service) error {
desiredPorts := openStackCluster.Status.Bastion.ReferencedResources.Ports
dependentResources := &openStackCluster.Status.Bastion.DependentResources
@@ -601,9 +585,7 @@ func getOrCreateBastionPorts(openStackCluster *infrav1.OpenStackCluster, network
return nil
}
- securityGroups := getBastionSecurityGroups(openStackCluster)
- bastionTags := []string{}
- err := networkingService.CreatePorts(openStackCluster, clusterName, bastionName(clusterName), securityGroups, bastionTags, desiredPorts, dependentResources)
+ err := networkingService.CreatePorts(openStackCluster, desiredPorts, dependentResources)
if err != nil {
return fmt.Errorf("failed to create ports for bastion %s: %w", bastionName(openStackCluster.Name), err)
}
@@ -621,7 +603,7 @@ func bastionHashHasChanged(computeHash string, clusterAnnotations map[string]str
}
func reconcileNetworkComponents(scope *scope.WithLogger, cluster *clusterv1.Cluster, openStackCluster *infrav1.OpenStackCluster) error {
- clusterName := fmt.Sprintf("%s-%s", cluster.Namespace, cluster.Name)
+ clusterName := names.ClusterName(cluster)
networkingService, err := networking.NewService(scope)
if err != nil {
diff --git a/controllers/openstackcluster_controller_test.go b/controllers/openstackcluster_controller_test.go
index 9c94b12d40..198f55a818 100644
--- a/controllers/openstackcluster_controller_test.go
+++ b/controllers/openstackcluster_controller_test.go
@@ -23,6 +23,7 @@ import (
"testing"
"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/external"
@@ -238,11 +239,9 @@ var _ = Describe("OpenStackCluster controller", func() {
Bastion: &infrav1.BastionStatus{
ReferencedResources: infrav1.ReferencedMachineResources{
ImageID: "imageID",
- Ports: []infrav1.PortOpts{
+ Ports: []infrav1.ResolvedPortSpec{
{
- Network: &infrav1.NetworkFilter{
- ID: "network-id",
- },
+ NetworkID: "network-id",
},
},
},
@@ -284,16 +283,14 @@ var _ = Describe("OpenStackCluster controller", func() {
networkClientRecorder.ListFloatingIP(floatingips.ListOpts{PortID: "portID1"}).Return(make([]floatingips.FloatingIP, 1), nil)
res, err := reconcileBastion(scope, capiCluster, testCluster)
- Expect(testCluster.Status.Bastion).To(Equal(&infrav1.BastionStatus{
+ expectedStatus := &infrav1.BastionStatus{
ID: "adopted-bastion-uuid",
State: "ACTIVE",
ReferencedResources: infrav1.ReferencedMachineResources{
ImageID: "imageID",
- Ports: []infrav1.PortOpts{
+ Ports: []infrav1.ResolvedPortSpec{
{
- Network: &infrav1.NetworkFilter{
- ID: "network-id",
- },
+ NetworkID: "network-id",
},
},
},
@@ -304,7 +301,8 @@ var _ = Describe("OpenStackCluster controller", func() {
},
},
},
- }))
+ }
+ Expect(testCluster.Status.Bastion).To(Equal(expectedStatus), cmp.Diff(testCluster.Status.Bastion, expectedStatus))
Expect(err).To(BeNil())
Expect(res).To(BeNil())
})
@@ -331,11 +329,9 @@ var _ = Describe("OpenStackCluster controller", func() {
ID: "adopted-fip-bastion-uuid",
ReferencedResources: infrav1.ReferencedMachineResources{
ImageID: "imageID",
- Ports: []infrav1.PortOpts{
+ Ports: []infrav1.ResolvedPortSpec{
{
- Network: &infrav1.NetworkFilter{
- ID: "network-id",
- },
+ NetworkID: "network-id",
},
},
},
@@ -375,11 +371,9 @@ var _ = Describe("OpenStackCluster controller", func() {
State: "ACTIVE",
ReferencedResources: infrav1.ReferencedMachineResources{
ImageID: "imageID",
- Ports: []infrav1.PortOpts{
+ Ports: []infrav1.ResolvedPortSpec{
{
- Network: &infrav1.NetworkFilter{
- ID: "network-id",
- },
+ NetworkID: "network-id",
},
},
},
@@ -417,11 +411,9 @@ var _ = Describe("OpenStackCluster controller", func() {
ID: "requeue-bastion-uuid",
ReferencedResources: infrav1.ReferencedMachineResources{
ImageID: "imageID",
- Ports: []infrav1.PortOpts{
+ Ports: []infrav1.ResolvedPortSpec{
{
- Network: &infrav1.NetworkFilter{
- ID: "network-id",
- },
+ NetworkID: "network-id",
},
},
},
@@ -455,11 +447,9 @@ var _ = Describe("OpenStackCluster controller", func() {
State: "BUILD",
ReferencedResources: infrav1.ReferencedMachineResources{
ImageID: "imageID",
- Ports: []infrav1.PortOpts{
+ Ports: []infrav1.ResolvedPortSpec{
{
- Network: &infrav1.NetworkFilter{
- ID: "network-id",
- },
+ NetworkID: "network-id",
},
},
},
@@ -799,40 +789,3 @@ func Test_getAPIServerPort(t *testing.T) {
})
}
}
-
-func TestGetBastionSecurityGroups(t *testing.T) {
- openStackCluster := &infrav1.OpenStackCluster{
- Spec: infrav1.OpenStackClusterSpec{
- Bastion: &infrav1.Bastion{
- Spec: &infrav1.OpenStackMachineSpec{
- SecurityGroups: []infrav1.SecurityGroupFilter{
- {
- ID: "sg-123",
- },
- },
- },
- },
- ManagedSecurityGroups: &infrav1.ManagedSecurityGroups{},
- },
- Status: infrav1.OpenStackClusterStatus{
- BastionSecurityGroup: &infrav1.SecurityGroupStatus{
- ID: "sg-456",
- },
- },
- }
-
- expectedSecurityGroups := []infrav1.SecurityGroupFilter{
- {
- ID: "sg-123",
- },
- {
- ID: "sg-456",
- },
- }
-
- securityGroups := getBastionSecurityGroups(openStackCluster)
-
- if !reflect.DeepEqual(securityGroups, expectedSecurityGroups) {
- t.Errorf("Expected security groups %v, but got %v", expectedSecurityGroups, securityGroups)
- }
-}
diff --git a/controllers/openstackmachine_controller.go b/controllers/openstackmachine_controller.go
index 294959e410..3bce8afa22 100644
--- a/controllers/openstackmachine_controller.go
+++ b/controllers/openstackmachine_controller.go
@@ -161,11 +161,12 @@ func (r *OpenStackMachineReconciler) Reconcile(ctx context.Context, req ctrl.Req
return r.reconcileNormal(ctx, scope, clusterName, infraCluster, machine, openStackMachine)
}
-func resolveMachineResources(scope *scope.WithLogger, openStackCluster *infrav1.OpenStackCluster, openStackMachine *infrav1.OpenStackMachine) (bool, error) {
+func resolveMachineResources(scope *scope.WithLogger, clusterName string, openStackCluster *infrav1.OpenStackCluster, openStackMachine *infrav1.OpenStackMachine, machine *clusterv1.Machine) (bool, error) {
// Resolve and store referenced resources
changed, err := compute.ResolveReferencedMachineResources(scope,
- openStackCluster,
- &openStackMachine.Spec, &openStackMachine.Status.ReferencedResources)
+ &openStackMachine.Spec, &openStackMachine.Status.ReferencedResources,
+ clusterName, openStackMachine.Name,
+ openStackCluster, getManagedSecurityGroup(openStackCluster, machine))
if err != nil {
return false, err
}
@@ -175,7 +176,7 @@ func resolveMachineResources(scope *scope.WithLogger, openStackCluster *infrav1.
}
// Adopt any existing dependent resources
- return false, compute.AdoptDependentMachineResources(scope, openStackMachine.Name, &openStackMachine.Status.ReferencedResources, &openStackMachine.Status.DependentResources)
+ return false, compute.AdoptDependentMachineResources(scope, &openStackMachine.Status.ReferencedResources, &openStackMachine.Status.DependentResources)
}
func patchMachine(ctx context.Context, patchHelper *patch.Helper, openStackMachine *infrav1.OpenStackMachine, machine *clusterv1.Machine, options ...patch.Option) error {
@@ -245,7 +246,7 @@ func (r *OpenStackMachineReconciler) reconcileDelete(scope *scope.WithLogger, cl
// We may have resources to adopt if the cluster is ready
if openStackCluster.Status.Ready && openStackCluster.Status.Network != nil {
- if _, err := resolveMachineResources(scope, openStackCluster, openStackMachine); err != nil {
+ if _, err := resolveMachineResources(scope, clusterName, openStackCluster, openStackMachine, machine); err != nil {
return ctrl.Result{}, err
}
}
@@ -483,7 +484,7 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope
return ctrl.Result{RequeueAfter: waitForClusterInfrastructureReadyDuration}, nil
}
- if changed, err := resolveMachineResources(scope, openStackCluster, openStackMachine); changed || err != nil {
+ if changed, err := resolveMachineResources(scope, clusterName, openStackCluster, openStackMachine, machine); changed || err != nil {
return ctrl.Result{}, err
}
@@ -514,7 +515,7 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope
return ctrl.Result{}, err
}
- err = getOrCreateMachinePorts(openStackCluster, machine, openStackMachine, networkingService, clusterName)
+ err = getOrCreateMachinePorts(openStackMachine, networkingService)
if err != nil {
return ctrl.Result{}, err
}
@@ -656,7 +657,7 @@ func (r *OpenStackMachineReconciler) reconcileAPIServerLoadBalancer(scope *scope
return nil
}
-func getOrCreateMachinePorts(openStackCluster *infrav1.OpenStackCluster, machine *clusterv1.Machine, openStackMachine *infrav1.OpenStackMachine, networkingService *networking.Service, clusterName string) error {
+func getOrCreateMachinePorts(openStackMachine *infrav1.OpenStackMachine, networkingService *networking.Service) error {
desiredPorts := openStackMachine.Status.ReferencedResources.Ports
dependentResources := &openStackMachine.Status.DependentResources
@@ -664,9 +665,7 @@ func getOrCreateMachinePorts(openStackCluster *infrav1.OpenStackCluster, machine
return nil
}
- instanceTags := getInstanceTags(openStackMachine, openStackCluster)
- managedSecurityGroups := getManagedSecurityGroups(openStackCluster, machine, openStackMachine)
- if err := networkingService.CreatePorts(openStackMachine, clusterName, openStackMachine.Name, managedSecurityGroups, instanceTags, desiredPorts, dependentResources); err != nil {
+ if err := networkingService.CreatePorts(openStackMachine, desiredPorts, dependentResources); err != nil {
return fmt.Errorf("creating ports: %w", err)
}
@@ -735,69 +734,29 @@ func machineToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, machine *
instanceSpec.FailureDomain = *machine.Spec.FailureDomain
}
- instanceSpec.Tags = getInstanceTags(openStackMachine, openStackCluster)
- instanceSpec.SecurityGroups = getManagedSecurityGroups(openStackCluster, machine, openStackMachine)
- instanceSpec.Ports = openStackMachine.Spec.Ports
+ instanceSpec.Tags = compute.InstanceTags(&openStackMachine.Spec, openStackCluster)
return &instanceSpec
}
-// getInstanceTags returns the tags that should be applied to the instance.
-// The tags are a combination of the tags specified on the OpenStackMachine and
-// the ones specified on the OpenStackCluster.
-func getInstanceTags(openStackMachine *infrav1.OpenStackMachine, openStackCluster *infrav1.OpenStackCluster) []string {
- machineTags := []string{}
-
- // Append machine specific tags
- machineTags = append(machineTags, openStackMachine.Spec.Tags...)
-
- // Append cluster scope tags
- machineTags = append(machineTags, openStackCluster.Spec.Tags...)
-
- // 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
- }
- machineTags = deduplicate(machineTags)
-
- return machineTags
-}
-
-// getManagedSecurityGroups returns a combination of OpenStackMachine.Spec.SecurityGroups
-// and the security group managed by the OpenStackCluster whether it's a control plane or a worker machine.
-func getManagedSecurityGroups(openStackCluster *infrav1.OpenStackCluster, machine *clusterv1.Machine, openStackMachine *infrav1.OpenStackMachine) []infrav1.SecurityGroupFilter {
- machineSpecSecurityGroups := openStackMachine.Spec.SecurityGroups
-
+// 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 machineSpecSecurityGroups
+ return nil
}
- var managedSecurityGroup string
if util.IsControlPlaneMachine(machine) {
if openStackCluster.Status.ControlPlaneSecurityGroup != nil {
- managedSecurityGroup = openStackCluster.Status.ControlPlaneSecurityGroup.ID
+ return &openStackCluster.Status.ControlPlaneSecurityGroup.ID
}
} else {
if openStackCluster.Status.WorkerSecurityGroup != nil {
- managedSecurityGroup = openStackCluster.Status.WorkerSecurityGroup.ID
+ return &openStackCluster.Status.WorkerSecurityGroup.ID
}
}
- if managedSecurityGroup != "" {
- machineSpecSecurityGroups = append(machineSpecSecurityGroups, infrav1.SecurityGroupFilter{
- ID: managedSecurityGroup,
- })
- }
-
- return machineSpecSecurityGroups
+ return nil
}
func (r *OpenStackMachineReconciler) reconcileLoadBalancerMember(scope *scope.WithLogger, openStackCluster *infrav1.OpenStackCluster, openStackMachine *infrav1.OpenStackMachine, instanceNS *compute.InstanceNetworkStatus, clusterName string) error {
diff --git a/controllers/openstackmachine_controller_test.go b/controllers/openstackmachine_controller_test.go
index 648b1abc0d..1351f3e2f6 100644
--- a/controllers/openstackmachine_controller_test.go
+++ b/controllers/openstackmachine_controller_test.go
@@ -20,6 +20,7 @@ import (
"reflect"
"testing"
+ "github.com/google/go-cmp/cmp"
. "github.com/onsi/gomega"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/utils/pointer"
@@ -112,11 +113,10 @@ func getDefaultInstanceSpec() *compute.InstanceSpec {
Metadata: map[string]string{
"test-metadata": "test-value",
},
- ConfigDrive: *pointer.Bool(true),
- FailureDomain: *pointer.String(failureDomain),
- ServerGroupID: serverGroupUUID,
- SecurityGroups: []infrav1.SecurityGroupFilter{},
- Tags: []string{"test-tag"},
+ ConfigDrive: *pointer.Bool(true),
+ FailureDomain: *pointer.String(failureDomain),
+ ServerGroupID: serverGroupUUID,
+ Tags: []string{"test-tag"},
}
}
@@ -137,102 +137,6 @@ func Test_machineToInstanceSpec(t *testing.T) {
openStackMachine: getDefaultOpenStackMachine,
wantInstanceSpec: getDefaultInstanceSpec,
},
- {
- name: "Control plane security group",
- openStackCluster: func() *infrav1.OpenStackCluster {
- c := getDefaultOpenStackCluster()
- c.Spec.ManagedSecurityGroups = &infrav1.ManagedSecurityGroups{}
- return c
- },
- machine: func() *clusterv1.Machine {
- m := getDefaultMachine()
- m.Labels = map[string]string{
- clusterv1.MachineControlPlaneLabel: "true",
- }
- return m
- },
- openStackMachine: getDefaultOpenStackMachine,
- wantInstanceSpec: func() *compute.InstanceSpec {
- i := getDefaultInstanceSpec()
- i.SecurityGroups = []infrav1.SecurityGroupFilter{{ID: controlPlaneSecurityGroupUUID}}
- return i
- },
- },
- {
- name: "Worker security group",
- openStackCluster: func() *infrav1.OpenStackCluster {
- c := getDefaultOpenStackCluster()
- c.Spec.ManagedSecurityGroups = &infrav1.ManagedSecurityGroups{}
- return c
- },
- machine: getDefaultMachine,
- openStackMachine: getDefaultOpenStackMachine,
- wantInstanceSpec: func() *compute.InstanceSpec {
- i := getDefaultInstanceSpec()
- i.SecurityGroups = []infrav1.SecurityGroupFilter{{ID: workerSecurityGroupUUID}}
- return i
- },
- },
- {
- name: "Control plane security group not applied to worker",
- openStackCluster: func() *infrav1.OpenStackCluster {
- c := getDefaultOpenStackCluster()
- c.Spec.ManagedSecurityGroups = &infrav1.ManagedSecurityGroups{}
- c.Status.WorkerSecurityGroup = nil
- return c
- },
- machine: getDefaultMachine,
- openStackMachine: getDefaultOpenStackMachine,
- wantInstanceSpec: func() *compute.InstanceSpec {
- i := getDefaultInstanceSpec()
- i.SecurityGroups = []infrav1.SecurityGroupFilter{}
- return i
- },
- },
- {
- name: "Worker security group not applied to control plane",
- openStackCluster: func() *infrav1.OpenStackCluster {
- c := getDefaultOpenStackCluster()
- c.Spec.ManagedSecurityGroups = &infrav1.ManagedSecurityGroups{}
- c.Status.ControlPlaneSecurityGroup = nil
- return c
- },
- machine: func() *clusterv1.Machine {
- m := getDefaultMachine()
- m.Labels = map[string]string{
- clusterv1.MachineControlPlaneLabel: "true",
- }
- return m
- },
- openStackMachine: getDefaultOpenStackMachine,
- wantInstanceSpec: func() *compute.InstanceSpec {
- i := getDefaultInstanceSpec()
- i.SecurityGroups = []infrav1.SecurityGroupFilter{}
- return i
- },
- },
- {
- name: "Extra security group",
- openStackCluster: func() *infrav1.OpenStackCluster {
- c := getDefaultOpenStackCluster()
- c.Spec.ManagedSecurityGroups = &infrav1.ManagedSecurityGroups{}
- return c
- },
- machine: getDefaultMachine,
- openStackMachine: func() *infrav1.OpenStackMachine {
- m := getDefaultOpenStackMachine()
- m.Spec.SecurityGroups = []infrav1.SecurityGroupFilter{{ID: extraSecurityGroupUUID}}
- return m
- },
- wantInstanceSpec: func() *compute.InstanceSpec {
- i := getDefaultInstanceSpec()
- i.SecurityGroups = []infrav1.SecurityGroupFilter{
- {ID: extraSecurityGroupUUID},
- {ID: workerSecurityGroupUUID},
- }
- return i
- },
- },
{
name: "Tags",
openStackCluster: func() *infrav1.OpenStackCluster {
@@ -255,220 +159,11 @@ func Test_machineToInstanceSpec(t *testing.T) {
}
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")
- Expect(got).To(Equal(tt.wantInstanceSpec()))
- })
- }
-}
-
-func Test_getInstanceTags(t *testing.T) {
- tests := []struct {
- name string
- openStackMachine func() *infrav1.OpenStackMachine
- openStackCluster func() *infrav1.OpenStackCluster
- wantMachineTags []string
- }{
- {
- name: "No tags",
- openStackMachine: func() *infrav1.OpenStackMachine {
- return &infrav1.OpenStackMachine{
- Spec: infrav1.OpenStackMachineSpec{},
- }
- },
- openStackCluster: func() *infrav1.OpenStackCluster {
- return &infrav1.OpenStackCluster{
- Spec: infrav1.OpenStackClusterSpec{},
- }
- },
- wantMachineTags: []string{},
- },
- {
- name: "Machine tags only",
- openStackMachine: func() *infrav1.OpenStackMachine {
- return &infrav1.OpenStackMachine{
- Spec: infrav1.OpenStackMachineSpec{
- Tags: []string{"machine-tag1", "machine-tag2"},
- },
- }
- },
- openStackCluster: func() *infrav1.OpenStackCluster {
- return &infrav1.OpenStackCluster{
- Spec: infrav1.OpenStackClusterSpec{},
- }
- },
- wantMachineTags: []string{"machine-tag1", "machine-tag2"},
- },
- {
- name: "Cluster tags only",
- openStackMachine: func() *infrav1.OpenStackMachine {
- return &infrav1.OpenStackMachine{
- Spec: infrav1.OpenStackMachineSpec{},
- }
- },
- openStackCluster: func() *infrav1.OpenStackCluster {
- return &infrav1.OpenStackCluster{
- Spec: infrav1.OpenStackClusterSpec{
- Tags: []string{"cluster-tag1", "cluster-tag2"},
- },
- }
- },
- wantMachineTags: []string{"cluster-tag1", "cluster-tag2"},
- },
- {
- name: "Machine and cluster tags",
- openStackMachine: func() *infrav1.OpenStackMachine {
- return &infrav1.OpenStackMachine{
- Spec: infrav1.OpenStackMachineSpec{
- Tags: []string{"machine-tag1", "machine-tag2"},
- },
- }
- },
- openStackCluster: func() *infrav1.OpenStackCluster {
- return &infrav1.OpenStackCluster{
- Spec: infrav1.OpenStackClusterSpec{
- Tags: []string{"cluster-tag1", "cluster-tag2"},
- },
- }
- },
- wantMachineTags: []string{"machine-tag1", "machine-tag2", "cluster-tag1", "cluster-tag2"},
- },
- {
- name: "Duplicate tags",
- openStackMachine: func() *infrav1.OpenStackMachine {
- return &infrav1.OpenStackMachine{
- Spec: infrav1.OpenStackMachineSpec{
- Tags: []string{"tag1", "tag2", "tag1"},
- },
- }
- },
- openStackCluster: func() *infrav1.OpenStackCluster {
- return &infrav1.OpenStackCluster{
- Spec: infrav1.OpenStackClusterSpec{
- Tags: []string{"tag2", "tag3", "tag3"},
- },
- }
- },
- wantMachineTags: []string{"tag1", "tag2", "tag3"},
- },
- }
+ wanted := tt.wantInstanceSpec()
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- gotMachineTags := getInstanceTags(tt.openStackMachine(), tt.openStackCluster())
- if !reflect.DeepEqual(gotMachineTags, tt.wantMachineTags) {
- t.Errorf("getInstanceTags() = %v, want %v", gotMachineTags, tt.wantMachineTags)
- }
- })
- }
-}
-
-func Test_getManagedSecurityGroups(t *testing.T) {
- tests := []struct {
- name string
- openStackCluster func() *infrav1.OpenStackCluster
- machine func() *clusterv1.Machine
- openStackMachine func() *infrav1.OpenStackMachine
- wantSecurityGroups []infrav1.SecurityGroupFilter
- }{
- {
- name: "Defaults",
- openStackCluster: getDefaultOpenStackCluster,
- machine: getDefaultMachine,
- openStackMachine: getDefaultOpenStackMachine,
- wantSecurityGroups: []infrav1.SecurityGroupFilter{},
- },
- {
- name: "Control plane machine with control plane security group",
- openStackCluster: func() *infrav1.OpenStackCluster {
- c := getDefaultOpenStackCluster()
- c.Spec.ManagedSecurityGroups = &infrav1.ManagedSecurityGroups{}
- c.Status.ControlPlaneSecurityGroup = &infrav1.SecurityGroupStatus{ID: controlPlaneSecurityGroupUUID}
- return c
- },
- machine: func() *clusterv1.Machine {
- m := getDefaultMachine()
- m.Labels = map[string]string{
- clusterv1.MachineControlPlaneLabel: "true",
- }
- return m
- },
- openStackMachine: getDefaultOpenStackMachine,
- wantSecurityGroups: []infrav1.SecurityGroupFilter{
- {ID: controlPlaneSecurityGroupUUID},
- },
- },
- {
- name: "Worker machine with worker security group",
- openStackCluster: func() *infrav1.OpenStackCluster {
- c := getDefaultOpenStackCluster()
- c.Spec.ManagedSecurityGroups = &infrav1.ManagedSecurityGroups{}
- c.Status.WorkerSecurityGroup = &infrav1.SecurityGroupStatus{ID: workerSecurityGroupUUID}
- return c
- },
- machine: getDefaultMachine,
- openStackMachine: getDefaultOpenStackMachine,
- wantSecurityGroups: []infrav1.SecurityGroupFilter{
- {ID: workerSecurityGroupUUID},
- },
- },
- {
- name: "Control plane machine without control plane security group",
- openStackCluster: func() *infrav1.OpenStackCluster {
- c := getDefaultOpenStackCluster()
- c.Spec.ManagedSecurityGroups = &infrav1.ManagedSecurityGroups{}
- c.Status.ControlPlaneSecurityGroup = nil
- return c
- },
- machine: func() *clusterv1.Machine {
- m := getDefaultMachine()
- m.Labels = map[string]string{
- clusterv1.MachineControlPlaneLabel: "true",
- }
- return m
- },
- openStackMachine: getDefaultOpenStackMachine,
- wantSecurityGroups: []infrav1.SecurityGroupFilter{},
- },
- {
- name: "Worker machine without worker security group",
- openStackCluster: func() *infrav1.OpenStackCluster {
- c := getDefaultOpenStackCluster()
- c.Spec.ManagedSecurityGroups = &infrav1.ManagedSecurityGroups{}
- c.Status.WorkerSecurityGroup = nil
- return c
- },
- machine: getDefaultMachine,
- openStackMachine: getDefaultOpenStackMachine,
- wantSecurityGroups: []infrav1.SecurityGroupFilter{},
- },
- {
- name: "Machine with additional security groups",
- openStackCluster: func() *infrav1.OpenStackCluster {
- c := getDefaultOpenStackCluster()
- c.Spec.ManagedSecurityGroups = &infrav1.ManagedSecurityGroups{}
- c.Status.ControlPlaneSecurityGroup = &infrav1.SecurityGroupStatus{ID: controlPlaneSecurityGroupUUID}
- c.Status.WorkerSecurityGroup = &infrav1.SecurityGroupStatus{ID: workerSecurityGroupUUID}
- return c
- },
- machine: getDefaultMachine,
- openStackMachine: func() *infrav1.OpenStackMachine {
- m := getDefaultOpenStackMachine()
- m.Spec.SecurityGroups = []infrav1.SecurityGroupFilter{{ID: extraSecurityGroupUUID}}
- return m
- },
- wantSecurityGroups: []infrav1.SecurityGroupFilter{
- {ID: extraSecurityGroupUUID},
- {ID: workerSecurityGroupUUID},
- },
- },
- }
-
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- gotMachineSecurity := getManagedSecurityGroups(tt.openStackCluster(), tt.machine(), tt.openStackMachine())
- if !reflect.DeepEqual(gotMachineSecurity, tt.wantSecurityGroups) {
- t.Errorf("getManagedSecurityGroups() = %v, want %v", gotMachineSecurity, tt.wantSecurityGroups)
- }
+ g.Expect(got).To(Equal(wanted), cmp.Diff(got, wanted))
})
}
}
diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md
index fe145f612c..e4d1ac338a 100644
--- a/docs/book/src/api/v1beta1/api.md
+++ b/docs/book/src/api/v1beta1/api.md
@@ -654,7 +654,9 @@ bool
- 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!
|
@@ -977,7 +979,7 @@ additional storage options.
(Appears on:
-PortOpts)
+ResolvedPortSpecFields)
@@ -1238,7 +1240,7 @@ DependentMachineResources
(Appears on:
-PortOpts)
+ResolvedPortSpecFields)
@@ -3125,7 +3127,9 @@ bool
- 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!
|
@@ -3492,7 +3496,9 @@ bool
- 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!
|
@@ -3631,8 +3637,7 @@ OpenStackMachineTemplateResource
(Appears on:
-OpenStackMachineSpec,
-ReferencedMachineResources)
+OpenStackMachineSpec)
@@ -3661,18 +3666,6 @@ This will fail if the query returns more than one network.
-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.
- |
-
-
-
description
string
@@ -3685,26 +3678,14 @@ string
|
-adminStateUp
-
-bool
-
- |
-
-(Optional)
- AdminStateUp specifies whether the port should be created in the up (true) or down (false) state. The default is up.
- |
-
-
-
-macAddress
+nameSuffix
string
|
(Optional)
- MACAddress specifies the MAC address of the port. If not specified, the MAC address will be generated.
+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.
|
@@ -3737,20 +3718,15 @@ string
-allowedAddressPairs
+tags
-
-[]AddressPair
-
+[]string
|
(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.
+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.
|
@@ -3769,118 +3745,162 @@ bastion host.
-hostID
+ResolvedPortSpecFields
-string
+
+ResolvedPortSpecFields
+
|
-(Optional)
- HostID specifies the ID of the host where the port resides.
+
+(Members of ResolvedPortSpecFields are embedded into this type.)
+
|
+
+
+PortStatus
+
+
+(Appears on:
+DependentMachineResources)
+
+
+
+
+
+
+| Field |
+Description |
+
+
+
-vnicType
+id
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.
+ID is the unique identifier of the port.
|
+
+
+ReferencedMachineResources
+
+
+(Appears on:
+BastionStatus,
+OpenStackMachineStatus)
+
+
+
ReferencedMachineResources contains resolved references to resources required by the machine.
+
+
+
+
+| Field |
+Description |
+
+
+
-profile
+serverGroupID
-
-BindingProfile
-
+string
|
(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
+ServerGroupID is the ID of the server group the machine should be added to and is calculated based on ServerGroupFilter.
|
-disablePortSecurity
+imageID
-bool
+string
|
(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.
+ImageID is the ID of the image to use for the machine and is calculated based on ImageFilter.
|
-propagateUplinkStatus
+ports
-bool
+
+[]ResolvedPortSpec
+
|
(Optional)
- PropageteUplinkStatus enables or disables the propagate uplink status on the port.
+Ports is the fully resolved list of ports to create for the machine.
|
+
+
+ResolvedFixedIP
+
+
+(Appears on:
+ResolvedPortSpec)
+
+
+
ResolvedFixedIP is a FixedIP with the Subnet resolved to an ID.
+
+
+
+
+| Field |
+Description |
+
+
+
-tags
+subnet
-[]string
+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.
+SubnetID is the id of a subnet to create the fixed IP of a port in.
|
-valueSpecs
+ipAddress
-
-[]ValueSpec
-
+string
|
(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.
+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.
|
-PortStatus
+ResolvedPortSpec
(Appears on:
-DependentMachineResources)
+ReferencedMachineResources)
+
ResolvedPortSpec is a PortOpts with all contained references fully resolved.
@@ -3892,26 +3912,115 @@ depends on the specific OpenStack implementation.
-id
+name
string
|
- ID is the unique identifier of the port.
+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 ResolvedPortSpecFields are embedded into this type.)
+
|
-ReferencedMachineResources
+ResolvedPortSpecFields
(Appears on:
-BastionStatus,
-OpenStackMachineStatus)
+PortOpts,
+ResolvedPortSpec)
-
ReferencedMachineResources contains resolved references to resources required by the machine.
+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.
@@ -3923,40 +4032,136 @@ string
-serverGroupID
+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)
- ServerGroupID is the ID of the server group the machine should be added to and is calculated based on ServerGroupFilter.
+MACAddress specifies the MAC address of the port. If not specified, the MAC address will be generated.
|
-imageID
+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)
- ImageID is the ID of the image to use for the machine and is calculated based on ImageFilter.
+HostID specifies the ID of the host where the port resides.
|
-ports
+vnicType
-
-[]PortOpts
+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)
- Ports is the fully resolved list of ports to create for the machine.
+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.
|
@@ -4737,7 +4942,7 @@ outside of these ranges manually.
(Appears on:
-PortOpts)
+ResolvedPortSpecFields)
ValueSpec represents a single value_spec key-value pair.
diff --git a/pkg/cloud/services/compute/dependent_resources.go b/pkg/cloud/services/compute/dependent_resources.go
index 1425c46fbf..0d45f07fb4 100644
--- a/pkg/cloud/services/compute/dependent_resources.go
+++ b/pkg/cloud/services/compute/dependent_resources.go
@@ -22,11 +22,11 @@ import (
"sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
)
-func AdoptDependentMachineResources(scope *scope.WithLogger, baseName string, referencedResources *infrav1.ReferencedMachineResources, dependentResources *infrav1.DependentMachineResources) error {
+func AdoptDependentMachineResources(scope *scope.WithLogger, referencedResources *infrav1.ReferencedMachineResources, dependentResources *infrav1.DependentMachineResources) error {
networkingService, err := networking.NewService(scope)
if err != nil {
return err
}
- return networkingService.AdoptPorts(scope, baseName, referencedResources.Ports, dependentResources)
+ return networkingService.AdoptPorts(scope, referencedResources.Ports, dependentResources)
}
diff --git a/pkg/cloud/services/compute/instance_test.go b/pkg/cloud/services/compute/instance_test.go
index e715171556..af9214e8a7 100644
--- a/pkg/cloud/services/compute/instance_test.go
+++ b/pkg/cloud/services/compute/instance_test.go
@@ -175,11 +175,10 @@ func getDefaultInstanceSpec() *InstanceSpec {
Metadata: map[string]string{
"test-metadata": "test-value",
},
- ConfigDrive: *pointer.Bool(true),
- FailureDomain: *pointer.String(failureDomain),
- ServerGroupID: serverGroupUUID,
- Tags: []string{"test-tag"},
- SecurityGroups: []infrav1.SecurityGroupFilter{{ID: workerSecurityGroupUUID}},
+ ConfigDrive: *pointer.Bool(true),
+ FailureDomain: *pointer.String(failureDomain),
+ ServerGroupID: serverGroupUUID,
+ Tags: []string{"test-tag"},
}
}
diff --git a/pkg/cloud/services/compute/instance_types.go b/pkg/cloud/services/compute/instance_types.go
index 5457d39bd1..c9940db7f1 100644
--- a/pkg/cloud/services/compute/instance_types.go
+++ b/pkg/cloud/services/compute/instance_types.go
@@ -43,8 +43,6 @@ type InstanceSpec struct {
ServerGroupID string
Trunk bool
Tags []string
- SecurityGroups []infrav1.SecurityGroupFilter
- Ports []infrav1.PortOpts
}
// InstanceIdentifier describes an instance which has not necessarily been fetched.
diff --git a/pkg/cloud/services/compute/referenced_resources.go b/pkg/cloud/services/compute/referenced_resources.go
index ae967b19cc..11004b699e 100644
--- a/pkg/cloud/services/compute/referenced_resources.go
+++ b/pkg/cloud/services/compute/referenced_resources.go
@@ -18,6 +18,7 @@ package compute
import (
"fmt"
+ "slices"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/cloud/services/networking"
@@ -30,7 +31,7 @@ import (
// Note that we only set the fields in ReferencedMachineResources that are not set yet. This is ok because:
// - OpenStackMachine is immutable, so we can't change the spec after the machine is created.
// - the bastion is mutable, but we delete the bastion when the spec changes, so the bastion status will be empty.
-func ResolveReferencedMachineResources(scope *scope.WithLogger, openStackCluster *infrav1.OpenStackCluster, spec *infrav1.OpenStackMachineSpec, resources *infrav1.ReferencedMachineResources) (changed bool, err error) {
+func ResolveReferencedMachineResources(scope *scope.WithLogger, spec *infrav1.OpenStackMachineSpec, resources *infrav1.ReferencedMachineResources, clusterName, baseName string, openStackCluster *infrav1.OpenStackCluster, managedSecurityGroup *string) (changed bool, err error) {
changed = false
computeService, err := NewService(scope)
@@ -72,13 +73,8 @@ func ResolveReferencedMachineResources(scope *scope.WithLogger, openStackCluster
// Network resources are required in order to get ports options.
if len(resources.Ports) == 0 {
- // For now we put this here but realistically an OpenStack administrator could enable/disable trunk
- // support at any time, so we should probably check this on every reconcile.
- trunkSupported, err := networkingService.IsTrunkExtSupported()
- if err != nil {
- return changed, err
- }
- portsOpts, err := networkingService.ConstructPorts(openStackCluster, spec.Ports, spec.Trunk, trunkSupported)
+ defaultNetwork := openStackCluster.Status.Network
+ portsOpts, err := networkingService.ConstructPorts(spec, clusterName, baseName, defaultNetwork, managedSecurityGroup, InstanceTags(spec, openStackCluster))
if err != nil {
return changed, err
}
@@ -88,3 +84,20 @@ func ResolveReferencedMachineResources(scope *scope.WithLogger, openStackCluster
return changed, nil
}
+
+// InstanceTags returns the tags that should be applied to an instance.
+// The tags are a deduplicated combination of the tags specified in the
+// OpenStackMachineSpec and the ones specified on the OpenStackCluster.
+func InstanceTags(spec *infrav1.OpenStackMachineSpec, openStackCluster *infrav1.OpenStackCluster) []string {
+ machineTags := slices.Concat(spec.Tags, openStackCluster.Spec.Tags)
+
+ seen := make(map[string]struct{}, len(machineTags))
+ unique := make([]string, 0, len(machineTags))
+ for _, tag := range machineTags {
+ if _, ok := seen[tag]; !ok {
+ seen[tag] = struct{}{}
+ unique = append(unique, tag)
+ }
+ }
+ return slices.Clip(unique)
+}
diff --git a/pkg/cloud/services/compute/referenced_resources_test.go b/pkg/cloud/services/compute/referenced_resources_test.go
index 1dd50788b6..489f92cde2 100644
--- a/pkg/cloud/services/compute/referenced_resources_test.go
+++ b/pkg/cloud/services/compute/referenced_resources_test.go
@@ -17,6 +17,7 @@ limitations under the License.
package compute
import (
+ "reflect"
"testing"
"github.com/go-logr/logr/testr"
@@ -24,7 +25,6 @@ import (
"github.com/google/go-cmp/cmp"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/servergroups"
"github.com/gophercloud/gophercloud/openstack/imageservice/v2/images"
- "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions"
. "github.com/onsi/gomega"
"k8s.io/utils/pointer"
@@ -34,154 +34,160 @@ import (
)
func Test_ResolveReferencedMachineResources(t *testing.T) {
- constFalse := false
- const serverGroupID1 = "ce96e584-7ebc-46d6-9e55-987d72e3806c"
- imageID1 := "de96e584-7ebc-46d6-9e55-987d72e3806c"
+ const (
+ serverGroupID1 = "ce96e584-7ebc-46d6-9e55-987d72e3806c"
+ imageID1 = "de96e584-7ebc-46d6-9e55-987d72e3806c"
+ networkID1 = "23ab8b71-89d4-425f-ac81-4eb83b35125a"
+ networkID2 = "cc8f75ce-6ce4-4b8a-836e-e5dac91cc9c8"
+ subnetID = "32dc0e7f-34b6-4544-a69b-248955618736"
+ )
- minimumReferences := &infrav1.ReferencedMachineResources{
- ImageID: imageID1,
+ defaultPorts := []infrav1.ResolvedPortSpec{
+ {
+ Name: "test-instance-0",
+ Description: "Created by cluster-api-provider-openstack cluster test-cluster",
+ NetworkID: networkID1,
+ FixedIPs: []infrav1.ResolvedFixedIP{
+ {SubnetID: pointer.String(subnetID)},
+ },
+ },
}
tests := []struct {
- testName string
- serverGroupFilter *infrav1.ServerGroupFilter
- imageFilter *infrav1.ImageFilter
- portsOpts *[]infrav1.PortOpts
- clusterStatus *infrav1.OpenStackClusterStatus
- expectComputeMock func(m *mock.MockComputeClientMockRecorder)
- expectImageMock func(m *mock.MockImageClientMockRecorder)
- expectNetworkMock func(m *mock.MockNetworkClientMockRecorder)
- want *infrav1.ReferencedMachineResources
- wantErr bool
+ testName string
+ spec infrav1.OpenStackMachineSpec
+ managedSecurityGroup *string
+ expectComputeMock func(m *mock.MockComputeClientMockRecorder)
+ expectImageMock func(m *mock.MockImageClientMockRecorder)
+ expectNetworkMock func(m *mock.MockNetworkClientMockRecorder)
+ before *infrav1.ReferencedMachineResources
+ want *infrav1.ReferencedMachineResources
+ wantErr bool
}{
{
- testName: "Resources ID passed",
- serverGroupFilter: &infrav1.ServerGroupFilter{ID: serverGroupID1},
- imageFilter: &infrav1.ImageFilter{ID: &imageID1},
- expectComputeMock: func(m *mock.MockComputeClientMockRecorder) {},
- expectImageMock: func(m *mock.MockImageClientMockRecorder) {},
- expectNetworkMock: func(m *mock.MockNetworkClientMockRecorder) {},
- want: &infrav1.ReferencedMachineResources{ImageID: imageID1, ServerGroupID: serverGroupID1},
- wantErr: false,
+ testName: "Resources ID passed",
+ spec: infrav1.OpenStackMachineSpec{
+ ServerGroup: &infrav1.ServerGroupFilter{ID: serverGroupID1},
+ Image: infrav1.ImageFilter{ID: pointer.String(imageID1)},
+ },
+ want: &infrav1.ReferencedMachineResources{
+ ImageID: imageID1,
+ ServerGroupID: serverGroupID1,
+ Ports: defaultPorts,
+ },
},
{
- testName: "Server group filter nil",
- serverGroupFilter: nil,
- expectComputeMock: func(m *mock.MockComputeClientMockRecorder) {},
- expectImageMock: func(m *mock.MockImageClientMockRecorder) {},
- expectNetworkMock: func(m *mock.MockNetworkClientMockRecorder) {},
- want: minimumReferences,
- wantErr: false,
+ testName: "Only image ID passed: want image id and default ports",
+ spec: infrav1.OpenStackMachineSpec{
+ Image: infrav1.ImageFilter{ID: pointer.String(imageID1)},
+ },
+ want: &infrav1.ReferencedMachineResources{
+ ImageID: imageID1,
+ Ports: defaultPorts,
+ },
},
{
- testName: "Server group ID empty",
- serverGroupFilter: &infrav1.ServerGroupFilter{},
- expectComputeMock: func(m *mock.MockComputeClientMockRecorder) {},
- expectImageMock: func(m *mock.MockImageClientMockRecorder) {},
- expectNetworkMock: func(m *mock.MockNetworkClientMockRecorder) {},
- want: minimumReferences,
- wantErr: false,
+ testName: "Server group empty",
+ spec: infrav1.OpenStackMachineSpec{
+ Image: infrav1.ImageFilter{ID: pointer.String(imageID1)},
+ ServerGroup: &infrav1.ServerGroupFilter{},
+ },
+ want: &infrav1.ReferencedMachineResources{
+ ImageID: imageID1,
+ Ports: defaultPorts,
+ },
},
{
- testName: "Server group by Name not found",
- serverGroupFilter: &infrav1.ServerGroupFilter{Name: "test-server-group"},
+ testName: "Server group by Name not found",
+ spec: infrav1.OpenStackMachineSpec{
+ Image: infrav1.ImageFilter{ID: pointer.String(imageID1)},
+ ServerGroup: &infrav1.ServerGroupFilter{Name: "test-server-group"},
+ },
expectComputeMock: func(m *mock.MockComputeClientMockRecorder) {
m.ListServerGroups().Return(
[]servergroups.ServerGroup{},
nil)
},
- expectImageMock: func(m *mock.MockImageClientMockRecorder) {},
- expectNetworkMock: func(m *mock.MockNetworkClientMockRecorder) {},
- want: &infrav1.ReferencedMachineResources{},
- wantErr: true,
+ want: &infrav1.ReferencedMachineResources{},
+ wantErr: true,
},
{
- testName: "Image by Name not found",
- imageFilter: &infrav1.ImageFilter{Name: pointer.String("test-image")},
- expectComputeMock: func(m *mock.MockComputeClientMockRecorder) {},
+ testName: "Image by Name not found",
+ spec: infrav1.OpenStackMachineSpec{
+ Image: infrav1.ImageFilter{Name: pointer.String("test-image")},
+ },
expectImageMock: func(m *mock.MockImageClientMockRecorder) {
- m.ListImages(images.ListOpts{Name: "test-image"}).Return(
- []images.Image{},
- nil)
+ m.ListImages(images.ListOpts{Name: "test-image"}).Return([]images.Image{}, nil)
},
- expectNetworkMock: func(m *mock.MockNetworkClientMockRecorder) {},
- want: &infrav1.ReferencedMachineResources{},
- wantErr: true,
+ want: &infrav1.ReferencedMachineResources{},
+ wantErr: true,
},
{
- testName: "PortsOpts set",
- clusterStatus: &infrav1.OpenStackClusterStatus{
- Network: &infrav1.NetworkStatusWithSubnets{
- Subnets: []infrav1.Subnet{
- {
- ID: "test-subnet-id",
+ testName: "Ports set",
+ spec: infrav1.OpenStackMachineSpec{
+ Image: infrav1.ImageFilter{ID: pointer.String(imageID1)},
+ Ports: []infrav1.PortOpts{
+ {
+ Network: &infrav1.NetworkFilter{
+ ID: networkID2,
},
},
},
},
- portsOpts: &[]infrav1.PortOpts{
- {
- Network: &infrav1.NetworkFilter{
- ID: "test-network-id",
- },
- Trunk: &constFalse,
- },
- },
- expectComputeMock: func(m *mock.MockComputeClientMockRecorder) {},
- expectImageMock: func(m *mock.MockImageClientMockRecorder) {},
- expectNetworkMock: func(m *mock.MockNetworkClientMockRecorder) {
- m.ListExtensions().Return([]extensions.Extension{}, nil)
- },
want: &infrav1.ReferencedMachineResources{
ImageID: imageID1,
- Ports: []infrav1.PortOpts{
+ Ports: []infrav1.ResolvedPortSpec{
{
- Network: &infrav1.NetworkFilter{
- ID: "test-network-id",
- },
- Trunk: &constFalse,
+ Name: "test-instance-0",
+ Description: "Created by cluster-api-provider-openstack cluster test-cluster",
+ NetworkID: networkID2,
},
},
},
- wantErr: false,
},
}
- for _, tt := range tests {
+ for i, tt := range tests {
t.Run(tt.testName, func(t *testing.T) {
+ tt := &tests[i]
g := NewWithT(t)
log := testr.New(t)
mockCtrl := gomock.NewController(t)
mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "")
- tt.expectComputeMock(mockScopeFactory.ComputeClient.EXPECT())
- tt.expectImageMock(mockScopeFactory.ImageClient.EXPECT())
- tt.expectNetworkMock(mockScopeFactory.NetworkClient.EXPECT())
-
- // Set defaults for required fields
- imageFilter := &infrav1.ImageFilter{ID: pointer.String(imageID1)}
- if tt.imageFilter != nil {
- imageFilter = tt.imageFilter
+ if tt.expectComputeMock != nil {
+ tt.expectComputeMock(mockScopeFactory.ComputeClient.EXPECT())
}
- portsOpts := &[]infrav1.PortOpts{}
- if tt.portsOpts != nil {
- portsOpts = tt.portsOpts
+ if tt.expectImageMock != nil {
+ tt.expectImageMock(mockScopeFactory.ImageClient.EXPECT())
}
-
- openStackCluster := &infrav1.OpenStackCluster{}
- if tt.clusterStatus != nil {
- openStackCluster.Status = *tt.clusterStatus
+ if tt.expectNetworkMock != nil {
+ tt.expectNetworkMock(mockScopeFactory.NetworkClient.EXPECT())
}
- machineSpec := &infrav1.OpenStackMachineSpec{
- ServerGroup: tt.serverGroupFilter,
- Image: *imageFilter,
- Ports: *portsOpts,
+ openStackCluster := &infrav1.OpenStackCluster{
+ Status: infrav1.OpenStackClusterStatus{
+ Network: &infrav1.NetworkStatusWithSubnets{
+ NetworkStatus: infrav1.NetworkStatus{
+ ID: networkID1,
+ },
+ Subnets: []infrav1.Subnet{
+ {
+ ID: subnetID,
+ },
+ },
+ },
+ },
}
- resources := &infrav1.ReferencedMachineResources{}
+ resources := tt.before
+ if resources == nil {
+ resources = &infrav1.ReferencedMachineResources{}
+ }
+ clusterName := "test-cluster"
+ baseName := "test-instance"
scope := scope.NewWithLogger(mockScopeFactory, log)
- _, err := ResolveReferencedMachineResources(scope, openStackCluster, machineSpec, resources)
+ _, err := ResolveReferencedMachineResources(scope, &tt.spec, resources, clusterName, baseName, openStackCluster, tt.managedSecurityGroup)
if tt.wantErr {
g.Expect(err).Error()
return
@@ -191,3 +197,94 @@ func Test_ResolveReferencedMachineResources(t *testing.T) {
})
}
}
+
+func Test_getInstanceTags(t *testing.T) {
+ tests := []struct {
+ name string
+ spec func() *infrav1.OpenStackMachineSpec
+ openStackCluster func() *infrav1.OpenStackCluster
+ wantMachineTags []string
+ }{
+ {
+ name: "No tags",
+ spec: func() *infrav1.OpenStackMachineSpec {
+ return &infrav1.OpenStackMachineSpec{}
+ },
+ openStackCluster: func() *infrav1.OpenStackCluster {
+ return &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{},
+ }
+ },
+ wantMachineTags: []string{},
+ },
+ {
+ name: "Machine tags only",
+ spec: func() *infrav1.OpenStackMachineSpec {
+ return &infrav1.OpenStackMachineSpec{
+ Tags: []string{"machine-tag1", "machine-tag2"},
+ }
+ },
+ openStackCluster: func() *infrav1.OpenStackCluster {
+ return &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{},
+ }
+ },
+ wantMachineTags: []string{"machine-tag1", "machine-tag2"},
+ },
+ {
+ name: "Cluster tags only",
+ spec: func() *infrav1.OpenStackMachineSpec {
+ return &infrav1.OpenStackMachineSpec{}
+ },
+ openStackCluster: func() *infrav1.OpenStackCluster {
+ return &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ Tags: []string{"cluster-tag1", "cluster-tag2"},
+ },
+ }
+ },
+ wantMachineTags: []string{"cluster-tag1", "cluster-tag2"},
+ },
+ {
+ name: "Machine and cluster tags",
+ spec: func() *infrav1.OpenStackMachineSpec {
+ return &infrav1.OpenStackMachineSpec{
+ Tags: []string{"machine-tag1", "machine-tag2"},
+ }
+ },
+ openStackCluster: func() *infrav1.OpenStackCluster {
+ return &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ Tags: []string{"cluster-tag1", "cluster-tag2"},
+ },
+ }
+ },
+ wantMachineTags: []string{"machine-tag1", "machine-tag2", "cluster-tag1", "cluster-tag2"},
+ },
+ {
+ name: "Duplicate tags",
+ spec: func() *infrav1.OpenStackMachineSpec {
+ return &infrav1.OpenStackMachineSpec{
+ Tags: []string{"tag1", "tag2", "tag1"},
+ }
+ },
+ openStackCluster: func() *infrav1.OpenStackCluster {
+ return &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ Tags: []string{"tag2", "tag3", "tag3"},
+ },
+ }
+ },
+ wantMachineTags: []string{"tag1", "tag2", "tag3"},
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ gotMachineTags := InstanceTags(tt.spec(), tt.openStackCluster())
+ if !reflect.DeepEqual(gotMachineTags, tt.wantMachineTags) {
+ t.Errorf("getInstanceTags() = %v, want %v", gotMachineTags, tt.wantMachineTags)
+ }
+ })
+ }
+}
diff --git a/pkg/cloud/services/networking/network_test.go b/pkg/cloud/services/networking/network_test.go
index 52b0fdb0d4..4a3401ce55 100644
--- a/pkg/cloud/services/networking/network_test.go
+++ b/pkg/cloud/services/networking/network_test.go
@@ -34,11 +34,14 @@ import (
"sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/names"
)
+const (
+ clusterName = "test-cluster"
+)
+
func Test_ReconcileNetwork(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
- clusterName := "test-cluster"
expectedNetworkName := getNetworkName(clusterName)
fakeNetworkID := "d08803fc-2fa5-4179-b9f7-8c43d0af2fe6"
@@ -435,7 +438,6 @@ func Test_ReconcileSubnet(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
- clusterName := "test-cluster"
expectedSubnetName := getSubnetName(clusterName)
expectedSubnetDesc := names.GetDescription(clusterName)
fakeSubnetID := "d08803fc-2fa5-4179-b9d7-8c43d0af2fe6"
diff --git a/pkg/cloud/services/networking/port.go b/pkg/cloud/services/networking/port.go
index b3fd46b3c2..4b6a894d56 100644
--- a/pkg/cloud/services/networking/port.go
+++ b/pkg/cloud/services/networking/port.go
@@ -20,6 +20,7 @@ import (
"context"
"errors"
"fmt"
+ "slices"
"strings"
"time"
@@ -109,123 +110,94 @@ func (s *Service) GetPortForExternalNetwork(instanceID string, externalNetworkID
return nil, nil
}
-func (s *Service) CreatePort(eventObject runtime.Object, clusterName string, portName string, portOpts *infrav1.PortOpts, defaultSecurityGroups []string, baseTags []string) (*ports.Port, error) {
- var err error
- networkID := portOpts.Network.ID
-
- var description string
- if portOpts.Description != nil {
- description = *portOpts.Description
- } else {
- description = names.GetDescription(clusterName)
- }
-
- var securityGroups []string
- addressPairs := []ports.AddressPair{}
- if portOpts.DisablePortSecurity == nil || !*portOpts.DisablePortSecurity {
- for _, ap := range portOpts.AllowedAddressPairs {
+func (s *Service) CreatePort(eventObject runtime.Object, portSpec *infrav1.ResolvedPortSpec) (*ports.Port, error) {
+ var addressPairs []ports.AddressPair
+ if !pointer.BoolDeref(portSpec.DisablePortSecurity, false) {
+ for _, ap := range portSpec.AllowedAddressPairs {
addressPairs = append(addressPairs, ports.AddressPair{
IPAddress: ap.IPAddress,
MACAddress: pointer.StringDeref(ap.MACAddress, ""),
})
}
- if portOpts.SecurityGroups != nil {
- securityGroups, err = s.GetSecurityGroups(portOpts.SecurityGroups)
- if err != nil {
- return nil, fmt.Errorf("error getting security groups: %v", err)
- }
- }
- // inherit port security groups from the instance if not explicitly specified
- if len(securityGroups) == 0 {
- securityGroups = defaultSecurityGroups
- }
}
- var fixedIPs interface{}
- if len(portOpts.FixedIPs) > 0 {
- fips := make([]ports.IP, 0, len(portOpts.FixedIPs)+1)
- for _, fixedIP := range portOpts.FixedIPs {
- subnetID, err := s.getSubnetIDForFixedIP(fixedIP.Subnet, networkID)
- if err != nil {
- return nil, err
- }
- fips = append(fips, ports.IP{
- SubnetID: subnetID,
+ var fixedIPs []ports.IP
+ if len(portSpec.FixedIPs) > 0 {
+ fixedIPs = make([]ports.IP, len(portSpec.FixedIPs))
+ for i, fixedIP := range portSpec.FixedIPs {
+ fixedIPs[i] = ports.IP{
+ SubnetID: pointer.StringDeref(fixedIP.SubnetID, ""),
IPAddress: pointer.StringDeref(fixedIP.IPAddress, ""),
- })
+ }
}
- fixedIPs = fips
}
var valueSpecs *map[string]string
- if len(portOpts.ValueSpecs) > 0 {
- vs := make(map[string]string, len(portOpts.ValueSpecs))
- for _, valueSpec := range portOpts.ValueSpecs {
+ if len(portSpec.ValueSpecs) > 0 {
+ vs := make(map[string]string, len(portSpec.ValueSpecs))
+ for _, valueSpec := range portSpec.ValueSpecs {
vs[valueSpec.Key] = valueSpec.Value
}
valueSpecs = &vs
}
- var createOpts ports.CreateOptsBuilder
-
- // Gophercloud expects a *[]string. We translate a nil slice to a nil pointer.
- var securityGroupsPtr *[]string
- if securityGroups != nil {
- securityGroupsPtr = &securityGroups
- }
-
- createOpts = ports.CreateOpts{
- Name: portName,
- NetworkID: networkID,
- Description: description,
- AdminStateUp: portOpts.AdminStateUp,
- MACAddress: pointer.StringDeref(portOpts.MACAddress, ""),
- SecurityGroups: securityGroupsPtr,
+ var builder ports.CreateOptsBuilder
+ createOpts := ports.CreateOpts{
+ Name: portSpec.Name,
+ NetworkID: portSpec.NetworkID,
+ Description: portSpec.Description,
+ AdminStateUp: portSpec.AdminStateUp,
+ MACAddress: pointer.StringDeref(portSpec.MACAddress, ""),
AllowedAddressPairs: addressPairs,
- FixedIPs: fixedIPs,
ValueSpecs: valueSpecs,
- PropagateUplinkStatus: portOpts.PropagateUplinkStatus,
+ PropagateUplinkStatus: portSpec.PropagateUplinkStatus,
+ }
+ if fixedIPs != nil {
+ createOpts.FixedIPs = fixedIPs
+ }
+ if portSpec.SecurityGroups != nil {
+ createOpts.SecurityGroups = &portSpec.SecurityGroups
}
+ builder = createOpts
- if portOpts.DisablePortSecurity != nil {
- portSecurity := !*portOpts.DisablePortSecurity
- createOpts = portsecurity.PortCreateOptsExt{
- CreateOptsBuilder: createOpts,
+ if portSpec.DisablePortSecurity != nil {
+ portSecurity := !*portSpec.DisablePortSecurity
+ portSecurityOpts := portsecurity.PortCreateOptsExt{
+ CreateOptsBuilder: builder,
PortSecurityEnabled: &portSecurity,
}
+ builder = portSecurityOpts
}
- createOpts = portsbinding.CreateOptsExt{
- CreateOptsBuilder: createOpts,
- HostID: pointer.StringDeref(portOpts.HostID, ""),
- VNICType: pointer.StringDeref(portOpts.VNICType, ""),
- Profile: getPortProfile(portOpts.Profile),
+ portsBindingOpts := portsbinding.CreateOptsExt{
+ CreateOptsBuilder: builder,
+ HostID: pointer.StringDeref(portSpec.HostID, ""),
+ VNICType: pointer.StringDeref(portSpec.VNICType, ""),
+ Profile: getPortProfile(portSpec.Profile),
}
+ builder = portsBindingOpts
- port, err := s.client.CreatePort(createOpts)
+ port, err := s.client.CreatePort(builder)
if err != nil {
- record.Warnf(eventObject, "FailedCreatePort", "Failed to create port %s: %v", portName, err)
+ record.Warnf(eventObject, "FailedCreatePort", "Failed to create port %s: %v", port.Name, err)
return nil, err
}
- var tags []string
- tags = append(tags, baseTags...)
- tags = append(tags, portOpts.Tags...)
- if len(tags) > 0 {
- if err = s.replaceAllAttributesTags(eventObject, portResource, port.ID, tags); err != nil {
- record.Warnf(eventObject, "FailedReplaceTags", "Failed to replace port tags %s: %v", portName, err)
+ if len(portSpec.Tags) > 0 {
+ if err = s.replaceAllAttributesTags(eventObject, portResource, port.ID, portSpec.Tags); err != nil {
+ record.Warnf(eventObject, "FailedReplaceTags", "Failed to replace port tags %s: %v", portSpec.Name, err)
return nil, err
}
}
record.Eventf(eventObject, "SuccessfulCreatePort", "Created port %s with id %s", port.Name, port.ID)
- if portOpts.Trunk != nil && *portOpts.Trunk {
- trunk, err := s.getOrCreateTrunk(eventObject, clusterName, port.Name, port.ID)
+ if pointer.BoolDeref(portSpec.Trunk, false) {
+ trunk, err := s.getOrCreateTrunkForPort(eventObject, port)
if err != nil {
- record.Warnf(eventObject, "FailedCreateTrunk", "Failed to create trunk for port %s: %v", portName, err)
+ record.Warnf(eventObject, "FailedCreateTrunk", "Failed to create trunk for port %s: %v", port.Name, err)
return nil, err
}
- if err = s.replaceAllAttributesTags(eventObject, trunkResource, trunk.ID, tags); err != nil {
- record.Warnf(eventObject, "FailedReplaceTags", "Failed to replace trunk tags %s: %v", portName, err)
+ if err = s.replaceAllAttributesTags(eventObject, trunkResource, trunk.ID, portSpec.Tags); err != nil {
+ record.Warnf(eventObject, "FailedReplaceTags", "Failed to replace trunk tags %s: %v", port.Name, err)
return nil, err
}
}
@@ -233,32 +205,6 @@ func (s *Service) CreatePort(eventObject runtime.Object, clusterName string, por
return port, nil
}
-func (s *Service) getSubnetIDForFixedIP(subnet *infrav1.SubnetFilter, networkID string) (string, error) {
- if subnet == nil {
- return "", nil
- }
- // Do not query for subnets if UUID is already provided
- if subnet.ID != "" {
- return subnet.ID, nil
- }
-
- opts := filterconvert.SubnetFilterToListOpts(subnet)
- opts.NetworkID = networkID
- subnets, err := s.client.ListSubnet(opts)
- if err != nil {
- return "", err
- }
-
- switch len(subnets) {
- case 0:
- return "", fmt.Errorf("subnet query %v, returns no subnets", *subnet)
- case 1:
- return subnets[0].ID, nil
- default:
- return "", fmt.Errorf("subnet query %v, returns too many subnets: %v", *subnet, subnets)
- }
-}
-
func getPortProfile(p *infrav1.BindingProfile) map[string]interface{} {
if p == nil {
return nil
@@ -357,30 +303,24 @@ func (s *Service) DeleteClusterPorts(openStackCluster *infrav1.OpenStackCluster)
return nil
}
-// GetPortName appends a suffix to an instance name in order to try and get a unique name per port.
-func GetPortName(instanceName string, opts *infrav1.PortOpts, netIndex int) string {
- if opts != nil && opts.NameSuffix != nil {
- return fmt.Sprintf("%s-%s", instanceName, *opts.NameSuffix)
+// getPortName appends a suffix to an instance name in order to try and get a unique name per port.
+func getPortName(baseName string, portSpec *infrav1.PortOpts, netIndex int) string {
+ if portSpec != nil && portSpec.NameSuffix != nil {
+ return fmt.Sprintf("%s-%s", baseName, *portSpec.NameSuffix)
}
- return fmt.Sprintf("%s-%d", instanceName, netIndex)
+ return fmt.Sprintf("%s-%d", baseName, netIndex)
}
-func (s *Service) CreatePorts(eventObject runtime.Object, clusterName, baseName string, securityGroups []infrav1.SecurityGroupFilter, baseTags []string, desiredPorts []infrav1.PortOpts, dependentResources *infrav1.DependentMachineResources) error {
- defaultSecurityGroups, err := s.GetSecurityGroups(securityGroups)
- if err != nil {
- return fmt.Errorf("error getting security groups: %v", err)
- }
-
+func (s *Service) CreatePorts(eventObject runtime.Object, desiredPorts []infrav1.ResolvedPortSpec, dependentResources *infrav1.DependentMachineResources) error {
for i := range desiredPorts {
// Skip creation of ports which already exist
if i < len(dependentResources.Ports) {
continue
}
- portOpts := &desiredPorts[i]
- portName := GetPortName(baseName, portOpts, i)
+ portSpec := &desiredPorts[i]
// Events are recorded in CreatePort
- port, err := s.CreatePort(eventObject, clusterName, portName, portOpts, defaultSecurityGroups, baseTags)
+ port, err := s.CreatePort(eventObject, portSpec)
if err != nil {
return err
}
@@ -393,112 +333,159 @@ func (s *Service) CreatePorts(eventObject runtime.Object, clusterName, baseName
return nil
}
-// ConstructPorts builds an array of ports from the instance spec.
+// ConstructPorts builds an array of ports from the machine spec.
// If no ports are in the spec, returns a single port for a network connection to the default cluster network.
-func (s *Service) ConstructPorts(openStackCluster *infrav1.OpenStackCluster, ports []infrav1.PortOpts, trunkEnabled bool, trunkSupported bool) ([]infrav1.PortOpts, error) {
- // If no network is specified, return nil
- if openStackCluster.Status.Network == nil {
- return nil, nil
+func (s *Service) ConstructPorts(spec *infrav1.OpenStackMachineSpec, clusterName, baseName string, defaultNetwork *infrav1.NetworkStatusWithSubnets, managedSecurityGroup *string, baseTags []string) ([]infrav1.ResolvedPortSpec, error) {
+ ports := spec.Ports
+
+ defaultSecurityGroupIDs, err := s.GetSecurityGroups(spec.SecurityGroups)
+ if err != nil {
+ return nil, fmt.Errorf("error getting security groups: %v", err)
+ }
+ if managedSecurityGroup != nil {
+ defaultSecurityGroupIDs = append(defaultSecurityGroupIDs, *managedSecurityGroup)
}
// Ensure user-specified ports have all required fields
- ports, err := s.normalizePorts(ports, openStackCluster, trunkEnabled)
+ resolvedPorts, err := s.normalizePorts(ports, clusterName, baseName, spec.Trunk, defaultSecurityGroupIDs, defaultNetwork, baseTags)
if err != nil {
return nil, err
}
// no networks or ports found in the spec, so create a port on the cluster network
- if len(ports) == 0 {
- port := infrav1.PortOpts{
- Network: &infrav1.NetworkFilter{
- ID: openStackCluster.Status.Network.ID,
- },
- Trunk: &trunkEnabled,
+ if len(resolvedPorts) == 0 {
+ resolvedPorts = make([]infrav1.ResolvedPortSpec, 1)
+ resolvedPort := &resolvedPorts[0]
+ resolvedPort.Name = getPortName(baseName, nil, 0)
+ resolvedPort.Description = names.GetDescription(clusterName)
+ if len(baseTags) > 0 {
+ resolvedPort.Tags = baseTags
}
- for _, subnet := range openStackCluster.Status.Network.Subnets {
- port.FixedIPs = append(port.FixedIPs, infrav1.FixedIP{
- Subnet: &infrav1.SubnetFilter{
- ID: subnet.ID,
- },
- })
+ if spec.Trunk {
+ resolvedPort.Trunk = &spec.Trunk
}
- ports = []infrav1.PortOpts{port}
+ resolvedPort.SecurityGroups = defaultSecurityGroupIDs
+ resolvedPort.NetworkID, resolvedPort.FixedIPs, _ = defaultNetworkTarget(defaultNetwork)
}
// trunk support is required if any port has trunk enabled
portUsesTrunk := func() bool {
- for _, port := range ports {
- if port.Trunk != nil && *port.Trunk {
+ for _, port := range resolvedPorts {
+ if pointer.BoolDeref(port.Trunk, false) {
return true
}
}
return false
}
if portUsesTrunk() {
+ trunkSupported, err := s.IsTrunkExtSupported()
+ if err != nil {
+ return nil, err
+ }
+
if !trunkSupported {
return nil, fmt.Errorf("there is no trunk support. please ensure that the trunk extension is enabled in your OpenStack deployment")
}
}
- return ports, nil
+ return resolvedPorts, nil
}
// normalizePorts ensures that a user-specified PortOpts has all required fields set. Specifically it:
// - sets the Trunk field to the instance spec default if not specified
// - sets the Network ID field if not specified.
-func (s *Service) normalizePorts(ports []infrav1.PortOpts, openStackCluster *infrav1.OpenStackCluster, trunkEnabled bool) ([]infrav1.PortOpts, error) {
- normalizedPorts := make([]infrav1.PortOpts, 0, len(ports))
+func (s *Service) normalizePorts(ports []infrav1.PortOpts, clusterName, baseName string, trunkEnabled bool, defaultSecurityGroupIDs []string, defaultNetwork *infrav1.NetworkStatusWithSubnets, baseTags []string) ([]infrav1.ResolvedPortSpec, error) {
+ normalizedPorts := make([]infrav1.ResolvedPortSpec, len(ports))
for i := range ports {
- // Deep copy the port to avoid mutating the original
- port := ports[i].DeepCopy()
+ port := &ports[i]
+ normalizedPort := &normalizedPorts[i]
+
+ // Copy fields which don't need to be resolved
+ normalizedPort.ResolvedPortSpecFields = port.ResolvedPortSpecFields
+
+ // Generate a standardised name
+ normalizedPort.Name = getPortName(baseName, port, i)
+
+ // Generate a description if none is provided
+ if port.Description != nil {
+ normalizedPort.Description = *port.Description
+ } else {
+ normalizedPort.Description = names.GetDescription(clusterName)
+ }
+
+ // Tags are inherited base tags plus any port-specific tags
+ normalizedPort.Tags = slices.Concat(baseTags, port.Tags)
// No Trunk field specified for the port, inherit the machine default
if port.Trunk == nil {
- port.Trunk = &trunkEnabled
+ if trunkEnabled {
+ normalizedPort.Trunk = &trunkEnabled
+ }
+ } else {
+ normalizedPort.Trunk = port.Trunk
}
- if err := s.normalizePortTarget(port, openStackCluster, i); err != nil {
+ // Resolve network ID and fixed IPs
+ var err error
+ normalizedPort.NetworkID, normalizedPort.FixedIPs, err = s.normalizePortTarget(port, defaultNetwork, i)
+ if err != nil {
return nil, err
}
- normalizedPorts = append(normalizedPorts, *port)
+ // Resolve security groups
+ if len(port.SecurityGroups) == 0 {
+ normalizedPort.SecurityGroups = defaultSecurityGroupIDs
+ } else {
+ normalizedPort.SecurityGroups, err = s.GetSecurityGroups(port.SecurityGroups)
+ if err != nil {
+ return nil, fmt.Errorf("error getting security groups: %v", err)
+ }
+ }
}
return normalizedPorts, nil
}
-// normalizePortTarget ensures that the port has a network ID.
-func (s *Service) normalizePortTarget(port *infrav1.PortOpts, openStackCluster *infrav1.OpenStackCluster, portIdx int) error {
- // Treat no Network and empty Network the same
- noNetwork := port.Network.IsEmpty()
+func defaultNetworkTarget(network *infrav1.NetworkStatusWithSubnets) (string, []infrav1.ResolvedFixedIP, error) {
+ networkID := network.ID
+ fixedIPs := make([]infrav1.ResolvedFixedIP, len(network.Subnets))
+ for i := range network.Subnets {
+ subnet := &network.Subnets[i]
+ fixedIPs[i].SubnetID = &subnet.ID
+ }
+ return networkID, fixedIPs, nil
+}
+// normalizePortTarget ensures that the port has a network ID.
+func (s *Service) normalizePortTarget(port *infrav1.PortOpts, defaultNetwork *infrav1.NetworkStatusWithSubnets, portIdx int) (string, []infrav1.ResolvedFixedIP, error) {
// No network or subnets defined: use cluster defaults
- if noNetwork && len(port.FixedIPs) == 0 {
- port.Network = &infrav1.NetworkFilter{
- ID: openStackCluster.Status.Network.ID,
- }
- for _, subnet := range openStackCluster.Status.Network.Subnets {
- port.FixedIPs = append(port.FixedIPs, infrav1.FixedIP{
- Subnet: &infrav1.SubnetFilter{
- ID: subnet.ID,
- },
- })
- }
+ if port.Network == nil && len(port.FixedIPs) == 0 {
+ return defaultNetworkTarget(defaultNetwork)
+ }
- return nil
+ var networkID string
+ var resolvedFixedIPs []infrav1.ResolvedFixedIP
+ if len(port.FixedIPs) > 0 {
+ resolvedFixedIPs = make([]infrav1.ResolvedFixedIP, len(port.FixedIPs))
}
+ switch {
+ case port.Network != nil && port.Network.ID != "":
+ networkID = port.Network.ID
+
// No network, but fixed IPs are defined(we handled the no fixed
// IPs case above): try to infer network from a subnet
- if noNetwork {
+ case len(port.FixedIPs) > 0:
s.scope.Logger().V(4).Info("No network defined for port, attempting to infer from subnet", "port", portIdx)
// Look for a unique subnet defined in FixedIPs. If we find one
// we can use it to infer the network ID. We don't need to worry
// here about the case where different FixedIPs have different
- // networks because that will cause an error later when we try
- // to create the port.
- networkID, err := func() (string, error) {
+ // networks because that will cause an error later.
+ var err error
+ networkID, err = func() (string, error) {
for i, fixedIP := range port.FixedIPs {
+ resolvedFixedIP := &resolvedFixedIPs[i]
+
if fixedIP.Subnet == nil {
continue
}
@@ -514,8 +501,8 @@ func (s *Service) normalizePortTarget(port *infrav1.PortOpts, openStackCluster *
return "", err
}
- // Cache the subnet ID in the FixedIP
- fixedIP.Subnet.ID = subnet.ID
+ // Cache the known subnet ID in the FixedIP so we don't fetch it again later
+ resolvedFixedIP.SubnetID = &subnet.ID
return subnet.NetworkID, nil
}
@@ -523,38 +510,40 @@ func (s *Service) normalizePortTarget(port *infrav1.PortOpts, openStackCluster *
return "", fmt.Errorf("port %d has no network and unable to infer from fixed IPs", portIdx)
}()
if err != nil {
- return err
+ return "", nil, err
}
- port.Network = &infrav1.NetworkFilter{
- ID: networkID,
+ // Network is defined by filter
+ default:
+ networkListOpts := filterconvert.NetworkFilterToListOpts(port.Network)
+ netIDs, err := s.GetNetworkIDsByFilter(networkListOpts)
+ if err != nil {
+ return "", nil, err
}
- return nil
- }
-
- // Nothing to do if network ID is already set
- if port.Network.ID != "" {
- return nil
- }
-
- // Network is defined by Filter
- networkListOpts := filterconvert.NetworkFilterToListOpts(port.Network)
- netIDs, err := s.GetNetworkIDsByFilter(networkListOpts)
- if err != nil {
- return err
+ // TODO: These are spec errors: they should set the machine to failed
+ if len(netIDs) > 1 {
+ return "", nil, fmt.Errorf("network filter for port %d returns more than one result", portIdx)
+ } else if len(netIDs) == 0 {
+ return "", nil, fmt.Errorf("network filter for port %d returns no networks", portIdx)
+ }
+ networkID = netIDs[0]
}
- // TODO: These are spec errors: they should set the machine to failed
- if len(netIDs) > 1 {
- return fmt.Errorf("network filter for port %d returns more than one result", portIdx)
- } else if len(netIDs) == 0 {
- return fmt.Errorf("network filter for port %d returns no networks", portIdx)
+ // Network ID is now known. Resolve all FixedIPs
+ for i, fixedIP := range port.FixedIPs {
+ resolvedFixedIP := &resolvedFixedIPs[i]
+ resolvedFixedIP.IPAddress = fixedIP.IPAddress
+ if fixedIP.Subnet != nil && resolvedFixedIP.SubnetID == nil {
+ subnet, err := s.GetNetworkSubnetByFilter(networkID, fixedIP.Subnet)
+ if err != nil {
+ return "", nil, err
+ }
+ resolvedFixedIP.SubnetID = &subnet.ID
+ }
}
- port.Network.ID = netIDs[0]
-
- return nil
+ return networkID, resolvedFixedIPs, nil
}
// IsTrunkExtSupported verifies trunk setup on the OpenStack deployment.
@@ -571,7 +560,7 @@ func (s *Service) IsTrunkExtSupported() (trunknSupported bool, err error) {
// AdoptPorts looks for ports in desiredPorts which were previously created, and adds them to dependentResources.Ports.
// A port matches if it has the same name and network ID as the desired port.
-func (s *Service) AdoptPorts(scope *scope.WithLogger, baseName string, desiredPorts []infrav1.PortOpts, dependentResources *infrav1.DependentMachineResources) error {
+func (s *Service) AdoptPorts(scope *scope.WithLogger, desiredPorts []infrav1.ResolvedPortSpec, dependentResources *infrav1.DependentMachineResources) error {
// We can skip adoption if the ports are already in the status
if len(desiredPorts) == len(dependentResources.Ports) {
return nil
@@ -582,21 +571,20 @@ func (s *Service) AdoptPorts(scope *scope.WithLogger, baseName string, desiredPo
// We create ports in order and adopt them in order in PortsStatus.
// This means that if port N doesn't exist we know that ports >N don't exist.
// We can therefore stop searching for ports once we find one that doesn't exist.
- for i, port := range desiredPorts {
+ for i := range desiredPorts {
// check if the port is in status first and if it is, skip it
if i < len(dependentResources.Ports) {
scope.Logger().V(5).Info("Port already in status, skipping it", "port index", i)
continue
}
- portOpts := &desiredPorts[i]
- portName := GetPortName(baseName, portOpts, i)
+ portSpec := &desiredPorts[i]
ports, err := s.client.ListPort(ports.ListOpts{
- Name: portName,
- NetworkID: port.Network.ID,
+ Name: portSpec.Name,
+ NetworkID: portSpec.NetworkID,
})
if err != nil {
- return fmt.Errorf("searching for existing port %s in network %s: %v", portName, port.Network.ID, err)
+ return fmt.Errorf("searching for existing port %s in network %s: %v", portSpec.Name, portSpec.NetworkID, err)
}
// if the port is not found, we stop the adoption of ports since the rest of the ports will not be found either
// and will be created after the adoption
@@ -605,7 +593,7 @@ func (s *Service) AdoptPorts(scope *scope.WithLogger, baseName string, desiredPo
return nil
}
if len(ports) > 1 {
- return fmt.Errorf("found multiple ports with name %s", portName)
+ return fmt.Errorf("found multiple ports with name %s", portSpec.Name)
}
// The desired port was found, so we add it to the status
diff --git a/pkg/cloud/services/networking/port_test.go b/pkg/cloud/services/networking/port_test.go
index 340d78ff91..ecf567fe74 100644
--- a/pkg/cloud/services/networking/port_test.go
+++ b/pkg/cloud/services/networking/port_test.go
@@ -22,14 +22,17 @@ import (
"github.com/go-logr/logr/testr"
"github.com/golang/mock/gomock"
"github.com/google/go-cmp/cmp"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/attributestags"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/portsbinding"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/portsecurity"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/trunks"
"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/gomega"
+ "github.com/onsi/gomega/types"
"k8s.io/utils/pointer"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
@@ -38,370 +41,282 @@ import (
)
func Test_CreatePort(t *testing.T) {
- // Arbitrary GUIDs used in the tests
- netID := "7fd24ceb-788a-441f-ad0a-d8e2f5d31a1d"
- subnetID1 := "d9c88a6d-0b8c-48ff-8f0e-8d85a078c194"
- subnetID2 := "d9c2346d-05gc-48er-9ut4-ig83ayt8c7h4"
- portID1 := "50214c48-c09e-4a54-914f-97b40fd22802"
- hostID := "825c1b11-3dca-4bfe-a2d8-a3cc1964c8d5"
- trunkID := "eb7541fa-5e2a-4cca-b2c3-dfa409b917ce"
- portSecurityGroupID := "f51d1206-fc5a-4f7a-a5c0-2e03e44e4dc0"
-
- // Other arbitrary variables passed in to the tests
- instanceSecurityGroups := []string{"instance-secgroup"}
- securityGroupUUIDs := []string{portSecurityGroupID}
- portSecurityGroupFilters := []infrav1.SecurityGroupFilter{{ID: portSecurityGroupID, Name: "port-secgroup"}}
- valueSpecs := map[string]string{"key": "value"}
+ // Arbitrary values used in the tests
+ const (
+ netID = "7fd24ceb-788a-441f-ad0a-d8e2f5d31a1d"
+ subnetID1 = "d9c88a6d-0b8c-48ff-8f0e-8d85a078c194"
+ subnetID2 = "d9c2346d-05gc-48er-9ut4-ig83ayt8c7h4"
+ portID = "50214c48-c09e-4a54-914f-97b40fd22802"
+ hostID = "825c1b11-3dca-4bfe-a2d8-a3cc1964c8d5"
+ trunkID = "eb7541fa-5e2a-4cca-b2c3-dfa409b917ce"
+ portSecurityGroupID = "f51d1206-fc5a-4f7a-a5c0-2e03e44e4dc0"
+ ipAddress1 = "192.0.2.1"
+ ipAddress2 = "198.51.100.1"
+ macAddress = "de:ad:be:ef:fe:ed"
+ )
tests := []struct {
- name string
- portName string
- port infrav1.PortOpts
- instanceSecurityGroups []string
- tags []string
- expect func(m *mock.MockNetworkClientMockRecorder)
+ name string
+ port infrav1.ResolvedPortSpec
+ expect func(m *mock.MockNetworkClientMockRecorder, g Gomega)
// Note the 'wanted' port isn't so important, since it will be whatever we tell ListPort or CreatePort to return.
// Mostly in this test suite, we're checking that CreatePort is called with the expected port opts.
want *ports.Port
wantErr bool
}{
{
- "creates port with defaults (description and secgroups) if not specified in portOpts",
- "foo-port-1",
- infrav1.PortOpts{
- Network: &infrav1.NetworkFilter{
- ID: netID,
- },
- },
- instanceSecurityGroups,
- []string{},
- func(m *mock.MockNetworkClientMockRecorder) {
- m.
- CreatePort(portsbinding.CreateOptsExt{
- CreateOptsBuilder: ports.CreateOpts{
- Name: "foo-port-1",
- Description: "Created by cluster-api-provider-openstack cluster test-cluster",
- SecurityGroups: &instanceSecurityGroups,
- NetworkID: netID,
- AllowedAddressPairs: []ports.AddressPair{},
- },
- }).Return(&ports.Port{ID: portID1}, nil)
- },
- &ports.Port{ID: portID1},
- false,
- },
- {
- "creates port with specified portOpts if no matching port exists",
- "foo-port-bar",
- infrav1.PortOpts{
- Network: &infrav1.NetworkFilter{
- ID: netID,
- },
- NameSuffix: pointer.String("bar"),
- Description: pointer.String("this is a test port"),
- MACAddress: pointer.String("fe:fe:fe:fe:fe:fe"),
- AdminStateUp: pointer.Bool(true),
- FixedIPs: []infrav1.FixedIP{
+ name: "creates port correctly with all options specified except tags, trunk and disablePortSecurity",
+ port: infrav1.ResolvedPortSpec{
+ Name: "foo-port-1",
+ Description: "Created by cluster-api-provider-openstack cluster test-cluster",
+ NetworkID: netID,
+ FixedIPs: []infrav1.ResolvedFixedIP{
+ {
+ SubnetID: pointer.String(subnetID1),
+ IPAddress: pointer.String(ipAddress1),
+ },
{
- Subnet: &infrav1.SubnetFilter{
- Name: "subnetFoo",
+ IPAddress: pointer.String(ipAddress2),
+ },
+ {
+ SubnetID: pointer.String(subnetID2),
+ },
+ },
+ SecurityGroups: []string{portSecurityGroupID},
+ ResolvedPortSpecFields: infrav1.ResolvedPortSpecFields{
+ AdminStateUp: pointer.Bool(true),
+ MACAddress: pointer.String(macAddress),
+ AllowedAddressPairs: []infrav1.AddressPair{
+ {
+ IPAddress: ipAddress1,
+ MACAddress: pointer.String(macAddress),
+ },
+ {
+ IPAddress: ipAddress2,
},
- IPAddress: pointer.String("192.168.0.50"),
- }, {
- IPAddress: pointer.String("192.168.1.50"),
- },
- },
- SecurityGroups: portSecurityGroupFilters,
- AllowedAddressPairs: []infrav1.AddressPair{{
- IPAddress: "10.10.10.10",
- MACAddress: pointer.String("f1:f1:f1:f1:f1:f1"),
- }},
- HostID: pointer.String(hostID),
- VNICType: pointer.String("direct"),
- Profile: &infrav1.BindingProfile{
- OVSHWOffload: pointer.Bool(true),
- TrustedVF: pointer.Bool(true),
- },
- DisablePortSecurity: pointer.Bool(false),
- Tags: []string{"my-port-tag"},
- },
- nil,
- nil,
- func(m *mock.MockNetworkClientMockRecorder) {
- portCreateOpts := ports.CreateOpts{
+ },
+ HostID: pointer.String(hostID),
+ VNICType: pointer.String("normal"),
+ Profile: &infrav1.BindingProfile{
+ OVSHWOffload: pointer.Bool(true),
+ TrustedVF: pointer.Bool(true),
+ },
+ PropagateUplinkStatus: pointer.Bool(true),
+ ValueSpecs: []infrav1.ValueSpec{
+ {
+ Name: "test-valuespec",
+ Key: "test-key",
+ Value: "test-value",
+ },
+ },
+ },
+ },
+ expect: func(m *mock.MockNetworkClientMockRecorder, g Gomega) {
+ var expectedCreateOpts ports.CreateOptsBuilder
+ expectedCreateOpts = ports.CreateOpts{
+ Name: "foo-port-1",
+ Description: "Created by cluster-api-provider-openstack cluster test-cluster",
NetworkID: netID,
- Name: "foo-port-bar",
- Description: "this is a test port",
AdminStateUp: pointer.Bool(true),
- MACAddress: "fe:fe:fe:fe:fe:fe",
+ MACAddress: macAddress,
FixedIPs: []ports.IP{
{
SubnetID: subnetID1,
- IPAddress: "192.168.0.50",
- }, {
- IPAddress: "192.168.1.50",
+ IPAddress: ipAddress1,
+ },
+ {
+ IPAddress: ipAddress2,
+ },
+ {
+ SubnetID: subnetID2,
},
},
- SecurityGroups: &securityGroupUUIDs,
- AllowedAddressPairs: []ports.AddressPair{{
- IPAddress: "10.10.10.10",
- MACAddress: "f1:f1:f1:f1:f1:f1",
- }},
- }
- portsecurityCreateOptsExt := portsecurity.PortCreateOptsExt{
- CreateOptsBuilder: portCreateOpts,
- PortSecurityEnabled: pointer.Bool(true),
+ SecurityGroups: &[]string{portSecurityGroupID},
+ AllowedAddressPairs: []ports.AddressPair{
+ {
+ IPAddress: ipAddress1,
+ MACAddress: macAddress,
+ },
+ {
+ IPAddress: ipAddress2,
+ },
+ },
+ PropagateUplinkStatus: pointer.Bool(true),
+ ValueSpecs: &map[string]string{
+ "test-key": "test-value",
+ },
}
- portbindingCreateOptsExt := portsbinding.CreateOptsExt{
- // Note for the test matching, the order in which the builders are composed
- // must be the same as in the function we are testing.
- CreateOptsBuilder: portsecurityCreateOptsExt,
+ expectedCreateOpts = portsbinding.CreateOptsExt{
+ CreateOptsBuilder: expectedCreateOpts,
HostID: hostID,
- VNICType: "direct",
+ VNICType: "normal",
Profile: map[string]interface{}{
"capabilities": []string{"switchdev"},
"trusted": true,
},
}
- m.
- CreatePort(portbindingCreateOptsExt).
- Return(&ports.Port{
- ID: portID1,
- }, nil)
- m.ReplaceAllAttributesTags("ports", portID1, attributestags.ReplaceAllOpts{Tags: []string{"my-port-tag"}}).Return([]string{"my-port-tag"}, nil)
- m.
- ListSubnet(subnets.ListOpts{
- Name: "subnetFoo",
- NetworkID: netID,
- }).Return([]subnets.Subnet{
- {
- ID: subnetID1,
- Name: "subnetFoo",
- NetworkID: netID,
- },
- }, nil)
- },
- &ports.Port{
- ID: portID1,
+
+ // The following allows us to use gomega to
+ // compare the argument instead of gomock.
+ // Gomock's output in the case of a mismatch is
+ // not usable for this struct.
+ m.CreatePort(gomock.Any()).DoAndReturn(func(builder ports.CreateOptsBuilder) (*ports.Port, error) {
+ gotCreateOpts := builder.(portsbinding.CreateOptsExt)
+ g.Expect(gotCreateOpts).To(Equal(expectedCreateOpts), cmp.Diff(gotCreateOpts, expectedCreateOpts))
+ return &ports.Port{ID: portID}, nil
+ })
},
- false,
+ want: &ports.Port{ID: portID},
},
{
- "fails to create port with specified portOpts if subnet query returns more than one subnet",
- "foo-port-bar",
- infrav1.PortOpts{
- Network: &infrav1.NetworkFilter{
- ID: netID,
- },
- NameSuffix: pointer.String("foo-port-bar"),
- Description: pointer.String("this is a test port"),
- FixedIPs: []infrav1.FixedIP{{
- Subnet: &infrav1.SubnetFilter{
- FilterByNeutronTags: infrav1.FilterByNeutronTags{
- Tags: []infrav1.NeutronTag{"Foo"},
- },
- },
- IPAddress: pointer.String("192.168.0.50"),
- }},
- },
- nil,
- nil,
- func(m *mock.MockNetworkClientMockRecorder) {
- m.
- ListSubnet(subnets.ListOpts{
- Tags: "Foo",
- NetworkID: netID,
- }).Return([]subnets.Subnet{
- {
- ID: subnetID1,
- NetworkID: netID,
- Name: "subnetFoo",
- },
- {
- ID: subnetID2,
- NetworkID: netID,
- Name: "subnetBar",
- },
- }, nil)
+ name: "creates minimum port correctly",
+ port: infrav1.ResolvedPortSpec{
+ Name: "test-port",
+ NetworkID: netID,
+ },
+ expect: func(m *mock.MockNetworkClientMockRecorder, g Gomega) {
+ var expectedCreateOpts ports.CreateOptsBuilder
+ expectedCreateOpts = ports.CreateOpts{
+ NetworkID: netID,
+ Name: "test-port",
+ }
+ expectedCreateOpts = portsbinding.CreateOptsExt{
+ CreateOptsBuilder: expectedCreateOpts,
+ }
+ m.CreatePort(gomock.Any()).DoAndReturn(func(builder ports.CreateOptsBuilder) (*ports.Port, error) {
+ gotCreateOpts := builder.(portsbinding.CreateOptsExt)
+ g.Expect(gotCreateOpts).To(Equal(expectedCreateOpts), cmp.Diff(gotCreateOpts, expectedCreateOpts))
+ return &ports.Port{ID: portID}, nil
+ })
},
- nil,
- true,
+ want: &ports.Port{ID: portID},
},
{
- "overrides default (instance) security groups if port security groups are specified",
- "foo-port-1",
- infrav1.PortOpts{
- Network: &infrav1.NetworkFilter{
- ID: netID,
- },
- SecurityGroups: portSecurityGroupFilters,
- },
- instanceSecurityGroups,
- []string{},
- func(m *mock.MockNetworkClientMockRecorder) {
- m.
- CreatePort(portsbinding.CreateOptsExt{
- CreateOptsBuilder: ports.CreateOpts{
- Name: "foo-port-1",
- Description: "Created by cluster-api-provider-openstack cluster test-cluster",
- SecurityGroups: &securityGroupUUIDs,
- NetworkID: netID,
- AllowedAddressPairs: []ports.AddressPair{},
+ name: "disable port security also ignores allowed address pairs",
+ port: infrav1.ResolvedPortSpec{
+ Name: "test-port",
+ NetworkID: netID,
+ ResolvedPortSpecFields: infrav1.ResolvedPortSpecFields{
+ DisablePortSecurity: pointer.Bool(true),
+ AllowedAddressPairs: []infrav1.AddressPair{
+ {
+ IPAddress: ipAddress1,
+ MACAddress: pointer.String(macAddress),
},
},
- ).Return(&ports.Port{ID: portID1}, nil)
+ },
},
- &ports.Port{ID: portID1},
- false,
- },
- {
- "creates port with instance tags when port tags aren't specified",
- "foo-port-1",
- infrav1.PortOpts{
- Network: &infrav1.NetworkFilter{
- ID: netID,
- },
- },
- nil,
- []string{"my-instance-tag"},
- func(m *mock.MockNetworkClientMockRecorder) {
- m.CreatePort(portsbinding.CreateOptsExt{
- CreateOptsBuilder: ports.CreateOpts{
- Name: "foo-port-1",
- Description: "Created by cluster-api-provider-openstack cluster test-cluster",
- NetworkID: netID,
- AllowedAddressPairs: []ports.AddressPair{},
- },
- }).Return(&ports.Port{ID: portID1}, nil)
- m.ReplaceAllAttributesTags("ports", portID1, attributestags.ReplaceAllOpts{Tags: []string{"my-instance-tag"}}).Return([]string{"my-instance-tag"}, nil)
- },
- &ports.Port{ID: portID1},
- false,
- },
- {
- "creates port with port specific tags appending to instance tags",
- "foo-port-1",
- infrav1.PortOpts{
- Network: &infrav1.NetworkFilter{
- ID: netID,
- },
- Tags: []string{"my-port-tag"},
- },
- nil,
- []string{"my-instance-tag"},
- func(m *mock.MockNetworkClientMockRecorder) {
- m.CreatePort(portsbinding.CreateOptsExt{
- CreateOptsBuilder: ports.CreateOpts{
- Name: "foo-port-1",
- Description: "Created by cluster-api-provider-openstack cluster test-cluster",
- NetworkID: netID,
- AllowedAddressPairs: []ports.AddressPair{},
- },
- }).Return(&ports.Port{ID: portID1}, nil)
- m.
- ReplaceAllAttributesTags("ports", portID1, attributestags.ReplaceAllOpts{Tags: []string{"my-instance-tag", "my-port-tag"}}).
- Return([]string{"my-instance-tag", "my-port-tag"}, nil)
- },
- &ports.Port{ID: portID1},
- false,
+ expect: func(m *mock.MockNetworkClientMockRecorder, g Gomega) {
+ var expectedCreateOpts ports.CreateOptsBuilder
+ expectedCreateOpts = ports.CreateOpts{
+ NetworkID: netID,
+ Name: "test-port",
+ }
+ expectedCreateOpts = portsecurity.PortCreateOptsExt{
+ CreateOptsBuilder: expectedCreateOpts,
+ PortSecurityEnabled: pointer.Bool(false),
+ }
+ expectedCreateOpts = portsbinding.CreateOptsExt{
+ CreateOptsBuilder: expectedCreateOpts,
+ }
+ m.CreatePort(gomock.Any()).DoAndReturn(func(builder ports.CreateOptsBuilder) (*ports.Port, error) {
+ gotCreateOpts := builder.(portsbinding.CreateOptsExt)
+ g.Expect(gotCreateOpts).To(Equal(expectedCreateOpts), cmp.Diff(gotCreateOpts, expectedCreateOpts))
+ return &ports.Port{ID: portID}, nil
+ })
+ },
+ want: &ports.Port{ID: portID},
},
{
- "creates port and trunk (with tags) if they aren't found",
- "foo-port-1",
- infrav1.PortOpts{
- Network: &infrav1.NetworkFilter{
- ID: netID,
- },
- Trunk: pointer.Bool(true),
- },
- nil,
- []string{"my-tag"},
- func(m *mock.MockNetworkClientMockRecorder) {
- m.
- CreatePort(portsbinding.CreateOptsExt{
- CreateOptsBuilder: ports.CreateOpts{
- Name: "foo-port-1",
- Description: "Created by cluster-api-provider-openstack cluster test-cluster",
- NetworkID: netID,
- AllowedAddressPairs: []ports.AddressPair{},
+ name: "disable port security explicitly false includes allowed address pairs",
+ port: infrav1.ResolvedPortSpec{
+ Name: "test-port",
+ NetworkID: netID,
+ ResolvedPortSpecFields: infrav1.ResolvedPortSpecFields{
+ DisablePortSecurity: pointer.Bool(false),
+ AllowedAddressPairs: []infrav1.AddressPair{
+ {
+ IPAddress: ipAddress1,
+ MACAddress: pointer.String(macAddress),
},
- }).Return(&ports.Port{Name: "foo-port-1", ID: portID1}, nil)
- m.
- ListTrunk(trunks.ListOpts{
- Name: "foo-port-1",
- PortID: portID1,
- }).Return([]trunks.Trunk{}, nil)
- m.
- CreateTrunk(trunks.CreateOpts{
- Name: "foo-port-1",
- PortID: portID1,
- Description: "Created by cluster-api-provider-openstack cluster test-cluster",
- }).Return(&trunks.Trunk{ID: trunkID}, nil)
-
- m.ReplaceAllAttributesTags("ports", portID1, attributestags.ReplaceAllOpts{Tags: []string{"my-tag"}}).Return([]string{"my-tag"}, nil)
- m.ReplaceAllAttributesTags("trunks", trunkID, attributestags.ReplaceAllOpts{Tags: []string{"my-tag"}}).Return([]string{"my-tag"}, nil)
- },
- &ports.Port{Name: "foo-port-1", ID: portID1},
- false,
- },
- {
- "creates port with value_specs",
- "foo-port-1",
- infrav1.PortOpts{
- Network: &infrav1.NetworkFilter{
- ID: netID,
+ },
},
- ValueSpecs: []infrav1.ValueSpec{
- {
- Name: "Not important",
- Key: "key",
- Value: "value",
- },
- },
- },
- nil,
- nil,
- func(m *mock.MockNetworkClientMockRecorder) {
- m.
- CreatePort(portsbinding.CreateOptsExt{
- CreateOptsBuilder: ports.CreateOpts{
- Name: "foo-port-1",
- Description: "Created by cluster-api-provider-openstack cluster test-cluster",
- NetworkID: netID,
- AllowedAddressPairs: []ports.AddressPair{},
- ValueSpecs: &valueSpecs,
+ },
+ expect: func(m *mock.MockNetworkClientMockRecorder, g types.Gomega) {
+ var expectedCreateOpts ports.CreateOptsBuilder
+ expectedCreateOpts = ports.CreateOpts{
+ NetworkID: netID,
+ Name: "test-port",
+ AllowedAddressPairs: []ports.AddressPair{
+ {
+ IPAddress: ipAddress1,
+ MACAddress: macAddress,
},
- }).Return(&ports.Port{ID: portID1}, nil)
+ },
+ }
+ expectedCreateOpts = portsecurity.PortCreateOptsExt{
+ CreateOptsBuilder: expectedCreateOpts,
+ PortSecurityEnabled: pointer.Bool(true),
+ }
+ expectedCreateOpts = portsbinding.CreateOptsExt{
+ CreateOptsBuilder: expectedCreateOpts,
+ }
+ m.CreatePort(gomock.Any()).DoAndReturn(func(builder ports.CreateOptsBuilder) (*ports.Port, error) {
+ gotCreateOpts := builder.(portsbinding.CreateOptsExt)
+ g.Expect(gotCreateOpts).To(Equal(expectedCreateOpts), cmp.Diff(gotCreateOpts, expectedCreateOpts))
+ return &ports.Port{ID: portID}, nil
+ })
},
- &ports.Port{ID: portID1},
- false,
+ want: &ports.Port{ID: portID},
},
{
- "creates port with propagate uplink status",
- "foo-port-1",
- infrav1.PortOpts{
- Network: &infrav1.NetworkFilter{
- ID: netID,
- },
- PropagateUplinkStatus: pointer.Bool(true),
- },
- instanceSecurityGroups,
- []string{},
- func(m *mock.MockNetworkClientMockRecorder) {
- m.
- CreatePort(portsbinding.CreateOptsExt{
- CreateOptsBuilder: ports.CreateOpts{
- Name: "foo-port-1",
- Description: "Created by cluster-api-provider-openstack cluster test-cluster",
- SecurityGroups: &instanceSecurityGroups,
- NetworkID: netID,
- AllowedAddressPairs: []ports.AddressPair{},
- PropagateUplinkStatus: pointer.Bool(true),
- },
- }).Return(&ports.Port{ID: portID1, PropagateUplinkStatus: true}, nil)
+ name: "tags and trunk",
+ port: infrav1.ResolvedPortSpec{
+ Name: "test-port",
+ NetworkID: netID,
+ Tags: []string{"tag1", "tag2"},
+ Trunk: pointer.Bool(true),
},
- &ports.Port{ID: portID1, PropagateUplinkStatus: true},
- false,
+ expect: func(m *mock.MockNetworkClientMockRecorder, g types.Gomega) {
+ var expectedCreateOpts ports.CreateOptsBuilder
+ expectedCreateOpts = ports.CreateOpts{
+ NetworkID: netID,
+ Name: "test-port",
+ }
+ expectedCreateOpts = portsbinding.CreateOptsExt{
+ CreateOptsBuilder: expectedCreateOpts,
+ }
+
+ // Create the port
+ m.CreatePort(gomock.Any()).DoAndReturn(func(builder ports.CreateOptsBuilder) (*ports.Port, error) {
+ gotCreateOpts := builder.(portsbinding.CreateOptsExt)
+ g.Expect(gotCreateOpts).To(Equal(expectedCreateOpts), cmp.Diff(gotCreateOpts, expectedCreateOpts))
+ return &ports.Port{ID: portID, Name: "test-port"}, nil
+ })
+
+ // Tag the port
+ m.ReplaceAllAttributesTags("ports", portID, attributestags.ReplaceAllOpts{
+ Tags: []string{"tag1", "tag2"},
+ })
+
+ // Look for existing trunk
+ m.ListTrunk(trunks.ListOpts{
+ PortID: portID,
+ Name: "test-port",
+ }).Return([]trunks.Trunk{}, nil)
+
+ // Create the trunk
+ m.CreateTrunk(trunks.CreateOpts{
+ PortID: portID,
+ Name: "test-port",
+ }).Return(&trunks.Trunk{ID: trunkID}, nil)
+
+ // Tag the trunk
+ m.ReplaceAllAttributesTags("trunks", trunkID, attributestags.ReplaceAllOpts{
+ Tags: []string{"tag1", "tag2"},
+ })
+ },
+ want: &ports.Port{ID: portID, Name: "test-port"},
},
}
@@ -414,17 +329,13 @@ func Test_CreatePort(t *testing.T) {
g := NewWithT(t)
mockClient := mock.NewMockNetworkClient(mockCtrl)
- tt.expect(mockClient.EXPECT())
+ tt.expect(mockClient.EXPECT(), g)
s := Service{
client: mockClient,
}
got, err := s.CreatePort(
eventObject,
- "test-cluster",
- tt.portName,
&tt.port,
- tt.instanceSecurityGroups,
- tt.tags,
)
if tt.wantErr {
g.Expect(err).To(HaveOccurred())
@@ -436,163 +347,159 @@ func Test_CreatePort(t *testing.T) {
}
}
-func TestService_normalizePorts(t *testing.T) {
+func TestService_ConstructPorts(t *testing.T) {
const (
defaultNetworkID = "3c66f3ca-2d26-4d9d-ae3b-568f54129773"
defaultSubnetID = "d8dbba89-8c39-4192-a571-e702fca35bac"
- networkID = "afa54944-1443-4132-9ef5-ce37eb4d6ab6"
- subnetID = "d786e715-c299-4a97-911d-640c10fc0392"
+ networkID = "afa54944-1443-4132-9ef5-ce37eb4d6ab6"
+ subnetID1 = "d786e715-c299-4a97-911d-640c10fc0392"
+ subnetID2 = "41ad8201-5b2f-4e0e-b29d-3d82fad6ef10"
+ securityGroupID1 = "044f6d31-3938-4f09-ad45-47b661e2ba1c"
+ securityGroupID2 = "427b77ee-40b7-4f1b-b025-72ad1a42ee51"
+
+ defaultDescription = "Created by cluster-api-provider-openstack cluster test-cluster"
)
- openStackCluster := &infrav1.OpenStackCluster{
- Status: infrav1.OpenStackClusterStatus{
- Network: &infrav1.NetworkStatusWithSubnets{
- NetworkStatus: infrav1.NetworkStatus{
- ID: defaultNetworkID,
- },
- Subnets: []infrav1.Subnet{
- {ID: defaultSubnetID},
- },
- },
- },
+ expectListExtensions := func(m *mock.MockNetworkClientMockRecorder) {
+ trunkExtension := extensions.Extension{}
+ trunkExtension.Alias = "trunk"
+ m.ListExtensions().Return([]extensions.Extension{trunkExtension}, nil)
}
tests := []struct {
- name string
- ports []infrav1.PortOpts
- instanceTrunk bool
- expectNetwork func(m *mock.MockNetworkClientMockRecorder)
- want []infrav1.PortOpts
- wantErr bool
+ name string
+ spec infrav1.OpenStackMachineSpec
+ managedSecurityGroup *string
+ expectNetwork func(m *mock.MockNetworkClientMockRecorder)
+ want []infrav1.ResolvedPortSpec
+ wantErr bool
}{
{
- name: "No ports: no ports",
- ports: []infrav1.PortOpts{},
- want: []infrav1.PortOpts{},
- },
- {
- name: "Nil network, no fixed IPs: cluster defaults",
- ports: []infrav1.PortOpts{
- {
- Network: nil,
- FixedIPs: nil,
- },
- },
- want: []infrav1.PortOpts{
+ name: "No ports creates port on default network",
+ spec: infrav1.OpenStackMachineSpec{},
+ want: []infrav1.ResolvedPortSpec{
{
- Network: &infrav1.NetworkFilter{
- ID: defaultNetworkID,
- },
- FixedIPs: []infrav1.FixedIP{
- {
- Subnet: &infrav1.SubnetFilter{
- ID: defaultSubnetID,
- },
- },
+ Name: "test-instance-0",
+ Description: defaultDescription,
+ Tags: []string{"test-tag"},
+ NetworkID: defaultNetworkID,
+ FixedIPs: []infrav1.ResolvedFixedIP{
+ {SubnetID: pointer.String(defaultSubnetID)},
},
- Trunk: pointer.Bool(false),
},
},
},
{
- name: "Empty network, no fixed IPs: cluster defaults",
- ports: []infrav1.PortOpts{
- {
- Network: &infrav1.NetworkFilter{},
- FixedIPs: nil,
+ name: "Nil network, no fixed IPs: cluster defaults",
+ spec: infrav1.OpenStackMachineSpec{
+ Ports: []infrav1.PortOpts{
+ {
+ NameSuffix: pointer.String("custom"),
+ Network: nil,
+ FixedIPs: nil,
+ },
},
},
- want: []infrav1.PortOpts{
+ want: []infrav1.ResolvedPortSpec{
{
- Network: &infrav1.NetworkFilter{
- ID: defaultNetworkID,
- },
- FixedIPs: []infrav1.FixedIP{
+ Name: "test-instance-custom",
+ Description: defaultDescription,
+ NetworkID: defaultNetworkID,
+ FixedIPs: []infrav1.ResolvedFixedIP{
{
- Subnet: &infrav1.SubnetFilter{
- ID: defaultSubnetID,
- },
+ SubnetID: pointer.String(defaultSubnetID),
},
},
- Trunk: pointer.Bool(false),
+ Tags: []string{"test-tag"},
},
},
},
{
name: "Port inherits trunk from instance",
- ports: []infrav1.PortOpts{
- {
- Network: &infrav1.NetworkFilter{},
- FixedIPs: nil,
+ spec: infrav1.OpenStackMachineSpec{
+ Ports: []infrav1.PortOpts{
+ {
+ NameSuffix: pointer.String("custom"),
+ Network: nil,
+ FixedIPs: nil,
+ },
},
+ Trunk: true,
+ },
+ expectNetwork: func(m *mock.MockNetworkClientMockRecorder) {
+ expectListExtensions(m)
},
- instanceTrunk: true,
- want: []infrav1.PortOpts{
+ want: []infrav1.ResolvedPortSpec{
{
- Network: &infrav1.NetworkFilter{
- ID: defaultNetworkID,
- },
- FixedIPs: []infrav1.FixedIP{
- {
- Subnet: &infrav1.SubnetFilter{
- ID: defaultSubnetID,
- },
- },
+ Name: "test-instance-custom",
+ Description: defaultDescription,
+ NetworkID: defaultNetworkID,
+ FixedIPs: []infrav1.ResolvedFixedIP{
+ {SubnetID: pointer.String(defaultSubnetID)},
},
+ Tags: []string{"test-tag"},
Trunk: pointer.Bool(true),
},
},
+ wantErr: false,
},
{
name: "Port overrides trunk from instance",
- ports: []infrav1.PortOpts{
- {
- Network: &infrav1.NetworkFilter{},
- FixedIPs: nil,
- Trunk: pointer.Bool(true),
+ spec: infrav1.OpenStackMachineSpec{
+ Ports: []infrav1.PortOpts{
+ {
+ Trunk: pointer.Bool(true),
+ },
},
+ Trunk: false,
},
- want: []infrav1.PortOpts{
+ expectNetwork: func(m *mock.MockNetworkClientMockRecorder) {
+ expectListExtensions(m)
+ },
+ want: []infrav1.ResolvedPortSpec{
{
- Network: &infrav1.NetworkFilter{
- ID: defaultNetworkID,
- },
- FixedIPs: []infrav1.FixedIP{
- {
- Subnet: &infrav1.SubnetFilter{
- ID: defaultSubnetID,
- },
- },
+ Name: "test-instance-0",
+ Description: defaultDescription,
+ NetworkID: defaultNetworkID,
+ FixedIPs: []infrav1.ResolvedFixedIP{
+ {SubnetID: pointer.String(defaultSubnetID)},
},
+ Tags: []string{"test-tag"},
Trunk: pointer.Bool(true),
},
},
},
{
- name: "Network defined by ID: unchanged",
- ports: []infrav1.PortOpts{
- {
- Network: &infrav1.NetworkFilter{
- ID: networkID,
+ name: "Network defined by ID: no lookup",
+ spec: infrav1.OpenStackMachineSpec{
+ Ports: []infrav1.PortOpts{
+ {
+ Network: &infrav1.NetworkFilter{
+ ID: networkID,
+ },
},
},
},
- want: []infrav1.PortOpts{
+ want: []infrav1.ResolvedPortSpec{
{
- Network: &infrav1.NetworkFilter{
- ID: networkID,
- },
- Trunk: pointer.Bool(false),
+ NetworkID: networkID,
+
+ // Defaults
+ Name: "test-instance-0",
+ Description: defaultDescription,
+ Tags: []string{"test-tag"},
},
},
},
{
name: "Network defined by filter: add ID from network lookup",
- ports: []infrav1.PortOpts{
- {
- Network: &infrav1.NetworkFilter{
- Name: "test-network",
+ spec: infrav1.OpenStackMachineSpec{
+ Ports: []infrav1.PortOpts{
+ {
+ Network: &infrav1.NetworkFilter{
+ Name: "test-network",
+ },
},
},
},
@@ -601,56 +508,59 @@ func TestService_normalizePorts(t *testing.T) {
{ID: networkID},
}, nil)
},
- want: []infrav1.PortOpts{
+ want: []infrav1.ResolvedPortSpec{
{
- Network: &infrav1.NetworkFilter{
- ID: networkID,
- Name: "test-network",
- },
- Trunk: pointer.Bool(false),
+ NetworkID: networkID,
+
+ // Defaults
+ Name: "test-instance-0",
+ Description: defaultDescription,
+ Tags: []string{"test-tag"},
},
},
},
{
name: "No network, fixed IP has subnet by ID: add ID from subnet",
- ports: []infrav1.PortOpts{
- {
- FixedIPs: []infrav1.FixedIP{
- {
- Subnet: &infrav1.SubnetFilter{
- ID: subnetID,
+ spec: infrav1.OpenStackMachineSpec{
+ Ports: []infrav1.PortOpts{
+ {
+ FixedIPs: []infrav1.FixedIP{
+ {
+ Subnet: &infrav1.SubnetFilter{
+ ID: subnetID1,
+ },
},
},
},
},
},
expectNetwork: func(m *mock.MockNetworkClientMockRecorder) {
- m.GetSubnet(subnetID).Return(&subnets.Subnet{ID: subnetID, NetworkID: networkID}, nil)
+ m.GetSubnet(subnetID1).Return(&subnets.Subnet{ID: subnetID1, NetworkID: networkID}, nil)
},
- want: []infrav1.PortOpts{
+ want: []infrav1.ResolvedPortSpec{
{
- Network: &infrav1.NetworkFilter{
- ID: networkID,
+ NetworkID: networkID,
+ FixedIPs: []infrav1.ResolvedFixedIP{
+ {SubnetID: pointer.String(subnetID1)},
},
- FixedIPs: []infrav1.FixedIP{
- {
- Subnet: &infrav1.SubnetFilter{
- ID: subnetID,
- },
- },
- },
- Trunk: pointer.Bool(false),
+
+ // Defaults
+ Name: "test-instance-0",
+ Description: defaultDescription,
+ Tags: []string{"test-tag"},
},
},
},
{
name: "No network, fixed IP has subnet by filter: add ID from subnet",
- ports: []infrav1.PortOpts{
- {
- FixedIPs: []infrav1.FixedIP{
- {
- Subnet: &infrav1.SubnetFilter{
- Name: "test-subnet",
+ spec: infrav1.OpenStackMachineSpec{
+ Ports: []infrav1.PortOpts{
+ {
+ FixedIPs: []infrav1.FixedIP{
+ {
+ Subnet: &infrav1.SubnetFilter{
+ Name: "test-subnet",
+ },
},
},
},
@@ -658,34 +568,35 @@ func TestService_normalizePorts(t *testing.T) {
},
expectNetwork: func(m *mock.MockNetworkClientMockRecorder) {
m.ListSubnet(subnets.ListOpts{Name: "test-subnet"}).Return([]subnets.Subnet{
- {ID: subnetID, NetworkID: networkID},
+ {ID: subnetID1, NetworkID: networkID},
}, nil)
},
- want: []infrav1.PortOpts{
+ want: []infrav1.ResolvedPortSpec{
{
- Network: &infrav1.NetworkFilter{
- ID: networkID,
- },
- FixedIPs: []infrav1.FixedIP{
+ NetworkID: networkID,
+ FixedIPs: []infrav1.ResolvedFixedIP{
{
- Subnet: &infrav1.SubnetFilter{
- ID: subnetID,
- Name: "test-subnet",
- },
+ SubnetID: pointer.String(subnetID1),
},
},
- Trunk: pointer.Bool(false),
+
+ // Defaults
+ Name: "test-instance-0",
+ Description: defaultDescription,
+ Tags: []string{"test-tag"},
},
},
},
{
name: "No network, fixed IP subnet returns no matches: error",
- ports: []infrav1.PortOpts{
- {
- FixedIPs: []infrav1.FixedIP{
- {
- Subnet: &infrav1.SubnetFilter{
- Name: "test-subnet",
+ spec: infrav1.OpenStackMachineSpec{
+ Ports: []infrav1.PortOpts{
+ {
+ FixedIPs: []infrav1.FixedIP{
+ {
+ Subnet: &infrav1.SubnetFilter{
+ Name: "test-subnet",
+ },
},
},
},
@@ -698,12 +609,14 @@ func TestService_normalizePorts(t *testing.T) {
},
{
name: "No network, only fixed IP subnet returns multiple matches: error",
- ports: []infrav1.PortOpts{
- {
- FixedIPs: []infrav1.FixedIP{
- {
- Subnet: &infrav1.SubnetFilter{
- Name: "test-subnet",
+ spec: infrav1.OpenStackMachineSpec{
+ Ports: []infrav1.PortOpts{
+ {
+ FixedIPs: []infrav1.FixedIP{
+ {
+ Subnet: &infrav1.SubnetFilter{
+ Name: "test-subnet",
+ },
},
},
},
@@ -711,7 +624,7 @@ func TestService_normalizePorts(t *testing.T) {
},
expectNetwork: func(m *mock.MockNetworkClientMockRecorder) {
m.ListSubnet(subnets.ListOpts{Name: "test-subnet"}).Return([]subnets.Subnet{
- {ID: subnetID, NetworkID: networkID},
+ {ID: subnetID1, NetworkID: networkID},
{ID: "8008494c-301e-4e5c-951b-a8ab568447fd", NetworkID: "5d48bfda-db28-42ee-8374-50e13d1fe5ea"},
}, nil)
},
@@ -719,17 +632,19 @@ func TestService_normalizePorts(t *testing.T) {
},
{
name: "No network, first fixed IP subnet returns multiple matches: used ID from second fixed IP",
- ports: []infrav1.PortOpts{
- {
- FixedIPs: []infrav1.FixedIP{
- {
- Subnet: &infrav1.SubnetFilter{
- Name: "test-subnet1",
+ spec: infrav1.OpenStackMachineSpec{
+ Ports: []infrav1.PortOpts{
+ {
+ FixedIPs: []infrav1.FixedIP{
+ {
+ Subnet: &infrav1.SubnetFilter{
+ Name: "test-subnet1",
+ },
},
- },
- {
- Subnet: &infrav1.SubnetFilter{
- Name: "test-subnet2",
+ {
+ Subnet: &infrav1.SubnetFilter{
+ Name: "test-subnet2",
+ },
},
},
},
@@ -737,43 +652,143 @@ func TestService_normalizePorts(t *testing.T) {
},
expectNetwork: func(m *mock.MockNetworkClientMockRecorder) {
m.ListSubnet(subnets.ListOpts{Name: "test-subnet1"}).Return([]subnets.Subnet{
- {ID: subnetID, NetworkID: networkID},
+ {ID: subnetID1, NetworkID: networkID},
{ID: "8008494c-301e-4e5c-951b-a8ab568447fd", NetworkID: "5d48bfda-db28-42ee-8374-50e13d1fe5ea"},
}, nil)
m.ListSubnet(subnets.ListOpts{Name: "test-subnet2"}).Return([]subnets.Subnet{
- {ID: subnetID, NetworkID: networkID},
+ {ID: subnetID2, NetworkID: networkID},
+ }, nil)
+ // Fetch the first subnet again, this time with network ID from the second subnet
+ m.ListSubnet(subnets.ListOpts{NetworkID: networkID, Name: "test-subnet1"}).Return([]subnets.Subnet{
+ {ID: subnetID1, NetworkID: networkID},
}, nil)
},
- want: []infrav1.PortOpts{
+ want: []infrav1.ResolvedPortSpec{
{
- Network: &infrav1.NetworkFilter{
- ID: networkID,
- },
- FixedIPs: []infrav1.FixedIP{
+ NetworkID: networkID,
+ FixedIPs: []infrav1.ResolvedFixedIP{
{
- Subnet: &infrav1.SubnetFilter{
- Name: "test-subnet1",
- },
+ SubnetID: pointer.String(subnetID1),
},
{
- Subnet: &infrav1.SubnetFilter{
- ID: subnetID,
- Name: "test-subnet2",
- },
+ SubnetID: pointer.String(subnetID2),
},
},
- Trunk: pointer.Bool(false),
+
+ // Defaults
+ Name: "test-instance-0",
+ Description: defaultDescription,
+ Tags: []string{"test-tag"},
+ },
+ },
+ },
+ {
+ name: "machine spec security groups added to defaults",
+ spec: infrav1.OpenStackMachineSpec{
+ SecurityGroups: []infrav1.SecurityGroupFilter{
+ {Name: "test-security-group"},
+ },
+ },
+ expectNetwork: func(m *mock.MockNetworkClientMockRecorder) {
+ m.ListSecGroup(groups.ListOpts{Name: "test-security-group"}).Return([]groups.SecGroup{
+ {ID: securityGroupID1},
+ }, nil)
+ },
+ want: []infrav1.ResolvedPortSpec{
+ {
+ Name: "test-instance-0",
+ NetworkID: defaultNetworkID,
+ FixedIPs: []infrav1.ResolvedFixedIP{
+ {SubnetID: pointer.String(defaultSubnetID)},
+ },
+ Description: defaultDescription,
+ Tags: []string{"test-tag"},
+ SecurityGroups: []string{securityGroupID1},
+ },
+ },
+ },
+ {
+ name: "port security groups override machine spec security groups",
+ spec: infrav1.OpenStackMachineSpec{
+ SecurityGroups: []infrav1.SecurityGroupFilter{
+ {Name: "machine-security-group"},
+ },
+ Ports: []infrav1.PortOpts{
+ {SecurityGroups: []infrav1.SecurityGroupFilter{{Name: "port-security-group"}}},
+ },
+ },
+ expectNetwork: func(m *mock.MockNetworkClientMockRecorder) {
+ m.ListSecGroup(groups.ListOpts{Name: "machine-security-group"}).Return([]groups.SecGroup{
+ {ID: securityGroupID1},
+ }, nil)
+ m.ListSecGroup(groups.ListOpts{Name: "port-security-group"}).Return([]groups.SecGroup{
+ {ID: securityGroupID2},
+ }, nil)
+ },
+ want: []infrav1.ResolvedPortSpec{
+ {
+ Name: "test-instance-0",
+ NetworkID: defaultNetworkID,
+ FixedIPs: []infrav1.ResolvedFixedIP{
+ {SubnetID: pointer.String(defaultSubnetID)},
+ },
+ Description: defaultDescription,
+ Tags: []string{"test-tag"},
+ SecurityGroups: []string{securityGroupID2},
+ },
+ },
+ },
+ {
+ name: "managed security group added to port",
+ spec: infrav1.OpenStackMachineSpec{},
+ managedSecurityGroup: pointer.String(securityGroupID1),
+ want: []infrav1.ResolvedPortSpec{
+ {
+ Name: "test-instance-0",
+ NetworkID: defaultNetworkID,
+ FixedIPs: []infrav1.ResolvedFixedIP{
+ {SubnetID: pointer.String(defaultSubnetID)},
+ },
+ Description: defaultDescription,
+ Tags: []string{"test-tag"},
+ SecurityGroups: []string{securityGroupID1},
+ },
+ },
+ },
+ {
+ name: "managed security group and machine security groups added to port",
+ spec: infrav1.OpenStackMachineSpec{
+ SecurityGroups: []infrav1.SecurityGroupFilter{{Name: "machine-security-group"}},
+ },
+ managedSecurityGroup: pointer.String(securityGroupID1),
+ expectNetwork: func(m *mock.MockNetworkClientMockRecorder) {
+ m.ListSecGroup(groups.ListOpts{Name: "machine-security-group"}).Return([]groups.SecGroup{
+ {ID: securityGroupID2},
+ }, nil)
+ },
+ want: []infrav1.ResolvedPortSpec{
+ {
+ Name: "test-instance-0",
+ NetworkID: defaultNetworkID,
+ FixedIPs: []infrav1.ResolvedFixedIP{
+ {SubnetID: pointer.String(defaultSubnetID)},
+ },
+ Description: defaultDescription,
+ Tags: []string{"test-tag"},
+ SecurityGroups: []string{securityGroupID2, securityGroupID1},
},
},
},
}
- for _, tt := range tests {
+ for i := range tests {
+ tt := &tests[i]
t.Run(tt.name, func(t *testing.T) {
+ mockCtrl := gomock.NewController(t)
+ defer mockCtrl.Finish()
+
g := NewWithT(t)
log := testr.New(t)
- mockCtrl := gomock.NewController(t)
- defer mockCtrl.Finish()
mockClient := mock.NewMockNetworkClient(mockCtrl)
if tt.expectNetwork != nil {
tt.expectNetwork(mockClient.EXPECT())
@@ -784,7 +799,19 @@ func TestService_normalizePorts(t *testing.T) {
scope: scope.NewWithLogger(mockScopeFactory, log),
}
- got, err := s.normalizePorts(tt.ports, openStackCluster, tt.instanceTrunk)
+ defaultNetwork := &infrav1.NetworkStatusWithSubnets{
+ NetworkStatus: infrav1.NetworkStatus{
+ ID: defaultNetworkID,
+ },
+ Subnets: []infrav1.Subnet{
+ {ID: defaultSubnetID},
+ },
+ }
+
+ clusterName := "test-cluster"
+ baseName := "test-instance"
+ baseTags := []string{"test-tag"}
+ got, err := s.ConstructPorts(&tt.spec, clusterName, baseName, defaultNetwork, tt.managedSecurityGroup, baseTags)
if tt.wantErr {
g.Expect(err).To(HaveOccurred())
return
@@ -797,40 +824,52 @@ func TestService_normalizePorts(t *testing.T) {
}
func Test_getPortName(t *testing.T) {
- type args struct {
+ tests := []struct {
+ name string
instanceName string
- opts *infrav1.PortOpts
+ spec *infrav1.PortOpts
netIndex int
- }
- tests := []struct {
- name string
- args args
- want string
+ want string
}{
{
- name: "with nil PortOpts",
- args: args{"test-1-instance", nil, 2},
- want: "test-1-instance-2",
+ name: "with nil PortOpts",
+ instanceName: "test-1-instance",
+ netIndex: 2,
+ want: "test-1-instance-2",
},
{
- name: "with PortOpts name suffix",
- args: args{"test-1-instance", &infrav1.PortOpts{NameSuffix: pointer.String("foo")}, 4},
- want: "test-1-instance-foo",
+ name: "with PortOpts name suffix",
+ instanceName: "test-1-instance",
+ spec: &infrav1.PortOpts{
+ NameSuffix: pointer.String("foo"),
+ },
+ netIndex: 4,
+ want: "test-1-instance-foo",
},
{
- name: "without PortOpts name suffix",
- args: args{"test-1-instance", &infrav1.PortOpts{}, 4},
- want: "test-1-instance-4",
+ name: "without PortOpts name suffix",
+ instanceName: "test-1-instance",
+ spec: &infrav1.PortOpts{},
+ netIndex: 4,
+ want: "test-1-instance-4",
},
{
- name: "with PortOpts name suffix",
- args: args{"test-1-instance", &infrav1.PortOpts{NameSuffix: pointer.String("foo2"), Network: &infrav1.NetworkFilter{ID: "bar"}, DisablePortSecurity: pointer.Bool(true)}, 4},
- want: "test-1-instance-foo2",
+ name: "with PortOpts name suffix",
+ instanceName: "test-1-instance",
+ spec: &infrav1.PortOpts{
+ NameSuffix: pointer.String("foo2"),
+ Network: &infrav1.NetworkFilter{ID: "bar"},
+ ResolvedPortSpecFields: infrav1.ResolvedPortSpecFields{
+ DisablePortSecurity: pointer.Bool(true),
+ },
+ },
+ netIndex: 4,
+ want: "test-1-instance-foo2",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- if got := GetPortName(tt.args.instanceName, tt.args.opts, tt.args.netIndex); got != tt.want {
+ if got := getPortName(tt.instanceName, tt.spec, tt.netIndex); got != tt.want {
t.Errorf("getPortName() = %v, want %v", got, tt.want)
}
})
@@ -848,7 +887,7 @@ func Test_AdoptPorts(t *testing.T) {
tests := []struct {
testName string
- desiredPorts []infrav1.PortOpts
+ desiredPorts []infrav1.ResolvedPortSpec
dependentResources infrav1.DependentMachineResources
expect func(*mock.MockNetworkClientMockRecorder)
want infrav1.DependentMachineResources
@@ -859,8 +898,8 @@ func Test_AdoptPorts(t *testing.T) {
},
{
testName: "desired port already in status: no-op",
- desiredPorts: []infrav1.PortOpts{
- {Network: &infrav1.NetworkFilter{ID: networkID1}},
+ desiredPorts: []infrav1.ResolvedPortSpec{
+ {NetworkID: networkID1},
},
dependentResources: infrav1.DependentMachineResources{
Ports: []infrav1.PortStatus{
@@ -879,8 +918,8 @@ func Test_AdoptPorts(t *testing.T) {
},
{
testName: "desired port not in status, exists: adopt",
- desiredPorts: []infrav1.PortOpts{
- {Network: &infrav1.NetworkFilter{ID: networkID1}},
+ desiredPorts: []infrav1.ResolvedPortSpec{
+ {Name: "test-machine-0", NetworkID: networkID1},
},
expect: func(m *mock.MockNetworkClientMockRecorder) {
m.ListPort(ports.ListOpts{Name: "test-machine-0", NetworkID: networkID1}).
@@ -896,8 +935,8 @@ func Test_AdoptPorts(t *testing.T) {
},
{
testName: "desired port not in status, does not exist: ignore",
- desiredPorts: []infrav1.PortOpts{
- {Network: &infrav1.NetworkFilter{ID: networkID1}},
+ desiredPorts: []infrav1.ResolvedPortSpec{
+ {Name: "test-machine-0", NetworkID: networkID1},
},
expect: func(m *mock.MockNetworkClientMockRecorder) {
m.ListPort(ports.ListOpts{Name: "test-machine-0", NetworkID: networkID1}).
@@ -907,9 +946,9 @@ func Test_AdoptPorts(t *testing.T) {
},
{
testName: "2 desired ports, first in status, second exists: adopt second",
- desiredPorts: []infrav1.PortOpts{
- {Network: &infrav1.NetworkFilter{ID: networkID1}},
- {Network: &infrav1.NetworkFilter{ID: networkID2}},
+ desiredPorts: []infrav1.ResolvedPortSpec{
+ {Name: "test-machine-0", NetworkID: networkID1},
+ {Name: "test-machine-1", NetworkID: networkID2},
},
dependentResources: infrav1.DependentMachineResources{
Ports: []infrav1.PortStatus{
@@ -931,10 +970,10 @@ func Test_AdoptPorts(t *testing.T) {
},
{
testName: "3 desired ports, first in status, second does not exist: ignore, do no look for third",
- desiredPorts: []infrav1.PortOpts{
- {Network: &infrav1.NetworkFilter{ID: networkID1}},
- {Network: &infrav1.NetworkFilter{ID: networkID2}},
- {Network: &infrav1.NetworkFilter{ID: networkID3}},
+ desiredPorts: []infrav1.ResolvedPortSpec{
+ {Name: "test-machine-0", NetworkID: networkID1},
+ {Name: "test-machine-1", NetworkID: networkID2},
+ {Name: "test-machine-2", NetworkID: networkID3},
},
dependentResources: infrav1.DependentMachineResources{
Ports: []infrav1.PortStatus{
@@ -953,6 +992,30 @@ func Test_AdoptPorts(t *testing.T) {
},
},
},
+ {
+ testName: "3 desired ports with arbitrary names, first in status, second does not exist: ignore, do no look for third",
+ desiredPorts: []infrav1.ResolvedPortSpec{
+ {Name: "test-machine-foo", NetworkID: networkID1},
+ {Name: "test-machine-bar", NetworkID: networkID2},
+ {Name: "test-machine-baz", NetworkID: networkID3},
+ },
+ dependentResources: infrav1.DependentMachineResources{
+ Ports: []infrav1.PortStatus{
+ {
+ ID: portID1,
+ },
+ },
+ },
+ expect: func(m *mock.MockNetworkClientMockRecorder) {
+ m.ListPort(ports.ListOpts{Name: "test-machine-bar", NetworkID: networkID2}).
+ Return(nil, nil)
+ },
+ want: infrav1.DependentMachineResources{
+ Ports: []infrav1.PortStatus{
+ {ID: portID1},
+ },
+ },
+ },
}
for i := range tests {
tt := &tests[i]
@@ -972,7 +1035,6 @@ func Test_AdoptPorts(t *testing.T) {
}
err := s.AdoptPorts(scope.NewWithLogger(mockScopeFactory, log),
- "test-machine",
tt.desiredPorts, &tt.dependentResources)
if tt.wantErr {
g.Expect(err).Error()
diff --git a/pkg/cloud/services/networking/trunk.go b/pkg/cloud/services/networking/trunk.go
index 6743478ffd..12ef3f4462 100644
--- a/pkg/cloud/services/networking/trunk.go
+++ b/pkg/cloud/services/networking/trunk.go
@@ -22,12 +22,12 @@ import (
"time"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/trunks"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/wait"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/record"
capoerrors "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/errors"
- "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/names"
)
const (
@@ -49,10 +49,10 @@ func (s *Service) GetTrunkSupport() (bool, error) {
return false, nil
}
-func (s *Service) getOrCreateTrunk(eventObject runtime.Object, clusterName, trunkName, portID string) (*trunks.Trunk, error) {
+func (s *Service) getOrCreateTrunkForPort(eventObject runtime.Object, port *ports.Port) (*trunks.Trunk, error) {
trunkList, err := s.client.ListTrunk(trunks.ListOpts{
- Name: trunkName,
- PortID: portID,
+ Name: port.Name,
+ PortID: port.ID,
})
if err != nil {
return nil, fmt.Errorf("searching for existing trunk for server: %v", err)
@@ -63,9 +63,9 @@ func (s *Service) getOrCreateTrunk(eventObject runtime.Object, clusterName, trun
}
trunkCreateOpts := trunks.CreateOpts{
- Name: trunkName,
- PortID: portID,
- Description: names.GetDescription(clusterName),
+ Name: port.Name,
+ PortID: port.ID,
+ Description: port.Description,
}
trunk, err := s.client.CreateTrunk(trunkCreateOpts)
diff --git a/pkg/cloud/services/networking/trunk_test.go b/pkg/cloud/services/networking/trunk_test.go
index a75519d8a8..079f5e45f9 100644
--- a/pkg/cloud/services/networking/trunk_test.go
+++ b/pkg/cloud/services/networking/trunk_test.go
@@ -21,6 +21,7 @@ import (
"github.com/golang/mock/gomock"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/trunks"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
. "github.com/onsi/gomega"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
@@ -31,54 +32,63 @@ func Test_GetOrCreateTrunk(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
+ const portID = "021e5dbe-a27b-4824-839e-239d5a027c7f"
+
tests := []struct {
- name string
- trunkName string
- portID string
- expect func(m *mock.MockNetworkClientMockRecorder)
+ name string
+ port *ports.Port
+ expect func(m *mock.MockNetworkClientMockRecorder)
// Note the 'wanted' port isn't so important, since it will be whatever we tell ListPort or CreatePort to return.
// Mostly in this test suite, we're checking that ListPort/CreatePort is called with the expected port opts.
want *trunks.Trunk
wantErr bool
}{
{
- "return trunk if found",
- "trunk-1",
- "port-1",
- func(m *mock.MockNetworkClientMockRecorder) {
+ name: "return trunk if found",
+ port: &ports.Port{
+ ID: portID,
+ Name: "trunk-1",
+ },
+ expect: func(m *mock.MockNetworkClientMockRecorder) {
m.
ListTrunk(trunks.ListOpts{
Name: "trunk-1",
- PortID: "port-1",
+ PortID: portID,
}).Return([]trunks.Trunk{{
Name: "trunk-1",
- ID: "port-1",
+ ID: portID,
}}, nil)
},
- &trunks.Trunk{Name: "trunk-1", ID: "port-1"},
- false,
+ want: &trunks.Trunk{
+ Name: "trunk-1",
+ ID: portID,
+ },
+ wantErr: false,
},
{
- "creates trunk if not found",
- "trunk-1",
- "port-1",
- func(m *mock.MockNetworkClientMockRecorder) {
+ name: "creates trunk if not found",
+ port: &ports.Port{
+ ID: portID,
+ Name: "trunk-1",
+ Description: "Created by cluster-api-provider-openstack cluster test-cluster",
+ },
+ expect: func(m *mock.MockNetworkClientMockRecorder) {
// No ports found
m.
ListTrunk(trunks.ListOpts{
Name: "trunk-1",
- PortID: "port-1",
+ PortID: portID,
}).Return([]trunks.Trunk{}, nil)
m.
CreateTrunk(trunks.CreateOpts{
Name: "trunk-1",
- PortID: "port-1",
+ PortID: portID,
Description: "Created by cluster-api-provider-openstack cluster test-cluster",
},
).Return(&trunks.Trunk{Name: "trunk-1", ID: "port-1"}, nil)
},
- &trunks.Trunk{Name: "trunk-1", ID: "port-1"},
- false,
+ want: &trunks.Trunk{Name: "trunk-1", ID: "port-1"},
+ wantErr: false,
},
}
@@ -91,12 +101,7 @@ func Test_GetOrCreateTrunk(t *testing.T) {
s := Service{
client: mockClient,
}
- got, err := s.getOrCreateTrunk(
- eventObject,
- "test-cluster",
- tt.trunkName,
- tt.portID,
- )
+ got, err := s.getOrCreateTrunkForPort(eventObject, tt.port)
if tt.wantErr {
g.Expect(err).To(HaveOccurred())
} else {
diff --git a/pkg/utils/names/names.go b/pkg/utils/names/names.go
index 95c1bd455c..ee1238f48f 100644
--- a/pkg/utils/names/names.go
+++ b/pkg/utils/names/names.go
@@ -19,6 +19,8 @@ package names
import (
"fmt"
"strings"
+
+ clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
)
const (
@@ -36,3 +38,7 @@ func GetFloatingAddressClaimName(openStackMachineName string) string {
func GetOpenStackMachineNameFromClaimName(claimName string) string {
return strings.TrimSuffix(claimName, fmt.Sprintf("-%s", FloatingAddressIPClaimNameSuffix))
}
+
+func ClusterName(cluster *clusterv1.Cluster) string {
+ return fmt.Sprintf("%s-%s", cluster.Namespace, cluster.Name)
+}
diff --git a/test/e2e/suites/e2e/e2e_test.go b/test/e2e/suites/e2e/e2e_test.go
index c8fdc0aea6..ff0cb9c7ba 100644
--- a/test/e2e/suites/e2e/e2e_test.go
+++ b/test/e2e/suites/e2e/e2e_test.go
@@ -123,11 +123,10 @@ var _ = Describe("e2e tests [PR-Blocking]", func() {
openStackCluster, err := shared.ClusterForSpec(ctx, e2eCtx, namespace)
Expect(err).NotTo(HaveOccurred())
- // Tag: clusterName is declared on OpenStackCluster and gets propagated to all machines
- // except the bastion host
+ // Tag: clusterName is declared on OpenStackCluster and gets propagated to all machines, including the bastion.
allServers, err := shared.DumpOpenStackServers(e2eCtx, servers.ListOpts{Tags: clusterName})
Expect(err).NotTo(HaveOccurred())
- Expect(allServers).To(HaveLen(2))
+ Expect(allServers).To(HaveLen(3))
// When listing servers with multiple tags, nova api requires a single, comma-separated string
// with all the tags
From b6d7748a7800f0cfde7d6edea510b3d55f0503fc Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Fri, 22 Mar 2024 10:21:26 +0000
Subject: [PATCH 144/180] Rename ClusterName to ClusterResourceName
---
controllers/openstackcluster_controller.go | 52 +++++++++----------
controllers/openstackmachine_controller.go | 32 ++++++------
.../services/compute/referenced_resources.go | 4 +-
.../compute/referenced_resources_test.go | 4 +-
.../services/loadbalancer/loadbalancer.go | 36 ++++++-------
pkg/cloud/services/networking/floatingip.go | 4 +-
pkg/cloud/services/networking/network.go | 26 +++++-----
pkg/cloud/services/networking/network_test.go | 12 ++---
pkg/cloud/services/networking/port.go | 10 ++--
pkg/cloud/services/networking/port_test.go | 4 +-
pkg/cloud/services/networking/router.go | 22 ++++----
.../services/networking/securitygroups.go | 28 +++++-----
.../networking/securitygroups_test.go | 4 +-
pkg/utils/names/names.go | 8 +--
14 files changed, 124 insertions(+), 122 deletions(-)
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index 9b659b7174..2f742c5545 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -148,13 +148,13 @@ func (r *OpenStackClusterReconciler) reconcileDelete(ctx context.Context, scope
return ctrl.Result{RequeueAfter: 5 * time.Second}, nil
}
- clusterName := names.ClusterName(cluster)
+ 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, clusterName, openStackCluster); err != nil {
+ if _, err := resolveBastionResources(scope, clusterResourceName, openStackCluster); err != nil {
return reconcile.Result{}, err
}
@@ -174,7 +174,7 @@ func (r *OpenStackClusterReconciler) reconcileDelete(ctx context.Context, scope
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)
}
@@ -182,7 +182,7 @@ func (r *OpenStackClusterReconciler) reconcileDelete(ctx context.Context, scope
// if ManagedSubnets was not set, no network was created.
if len(openStackCluster.Spec.ManagedSubnets) > 0 {
- if err = networkingService.DeleteRouter(openStackCluster, clusterName); err != nil {
+ 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)
}
@@ -192,13 +192,13 @@ func (r *OpenStackClusterReconciler) reconcileDelete(ctx context.Context, scope
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, clusterName); err != nil {
+ 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)
}
@@ -218,7 +218,7 @@ func contains(arr []string, target string) bool {
return false
}
-func resolveBastionResources(scope *scope.WithLogger, clusterName string, openStackCluster *infrav1.OpenStackCluster) (bool, error) {
+func resolveBastionResources(scope *scope.WithLogger, clusterResourceName string, openStackCluster *infrav1.OpenStackCluster) (bool, error) {
// Resolve and store referenced & dependent resources for the bastion
if openStackCluster.Spec.Bastion != nil && openStackCluster.Spec.Bastion.Enabled {
if openStackCluster.Status.Bastion == nil {
@@ -229,7 +229,7 @@ func resolveBastionResources(scope *scope.WithLogger, clusterName string, openSt
}
changed, err := compute.ResolveReferencedMachineResources(scope,
openStackCluster.Spec.Bastion.Spec, &openStackCluster.Status.Bastion.ReferencedResources,
- clusterName, bastionName(clusterName),
+ clusterResourceName, bastionName(clusterResourceName),
openStackCluster, getBastionSecurityGroupID(openStackCluster))
if err != nil {
return false, err
@@ -387,8 +387,8 @@ func reconcileNormal(scope *scope.WithLogger, cluster *clusterv1.Cluster, openSt
func reconcileBastion(scope *scope.WithLogger, cluster *clusterv1.Cluster, openStackCluster *infrav1.OpenStackCluster) (*ctrl.Result, error) {
scope.Logger().V(4).Info("Reconciling Bastion")
- clusterName := names.ClusterName(cluster)
- changed, err := resolveBastionResources(scope, clusterName, openStackCluster)
+ clusterResourceName := names.ClusterResourceName(cluster)
+ changed, err := resolveBastionResources(scope, clusterResourceName, openStackCluster)
if err != nil {
return nil, err
}
@@ -491,10 +491,10 @@ func reconcileBastion(scope *scope.WithLogger, cluster *clusterv1.Cluster, openS
return nil, err
}
- return bastionAddFloatingIP(openStackCluster, clusterName, port, networkingService)
+ return bastionAddFloatingIP(openStackCluster, clusterResourceName, port, networkingService)
}
-func bastionAddFloatingIP(openStackCluster *infrav1.OpenStackCluster, clusterName string, port *ports.Port, networkingService *networking.Service) (*reconcile.Result, error) {
+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))
@@ -516,7 +516,7 @@ func bastionAddFloatingIP(openStackCluster *infrav1.OpenStackCluster, clusterNam
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, clusterName, floatingIP)
+ 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)
@@ -560,8 +560,8 @@ func bastionToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, cluster *
return instanceSpec, nil
}
-func bastionName(clusterName string) string {
- return fmt.Sprintf("%s-bastion", clusterName)
+func bastionName(clusterResourceName string) string {
+ return fmt.Sprintf("%s-bastion", clusterResourceName)
}
// getBastionSecurityGroupID returns the ID of the bastion security group if
@@ -603,7 +603,7 @@ func bastionHashHasChanged(computeHash string, clusterAnnotations map[string]str
}
func reconcileNetworkComponents(scope *scope.WithLogger, cluster *clusterv1.Cluster, openStackCluster *infrav1.OpenStackCluster) error {
- clusterName := names.ClusterName(cluster)
+ clusterResourceName := names.ClusterResourceName(cluster)
networkingService, err := networking.NewService(scope)
if err != nil {
@@ -623,20 +623,20 @@ func reconcileNetworkComponents(scope *scope.WithLogger, cluster *clusterv1.Clus
return err
}
} else if len(openStackCluster.Spec.ManagedSubnets) == 1 {
- if err := reconcileProvisionedNetworkComponents(networkingService, openStackCluster, clusterName); err != nil {
+ if err := reconcileProvisionedNetworkComponents(networkingService, openStackCluster, clusterResourceName); err != nil {
return err
}
} else {
return fmt.Errorf("failed to reconcile network: ManagedSubnets only supports one element, %d provided", len(openStackCluster.Spec.ManagedSubnets))
}
- err = networkingService.ReconcileSecurityGroups(openStackCluster, clusterName)
+ 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 reconcileControlPlaneEndpoint(scope, networkingService, openStackCluster, clusterName)
+ return reconcileControlPlaneEndpoint(scope, networkingService, openStackCluster, clusterResourceName)
}
// reconcilePreExistingNetworkComponents reconciles the cluster network status when the cluster is
@@ -700,18 +700,18 @@ func reconcilePreExistingNetworkComponents(scope *scope.WithLogger, networkingSe
return nil
}
-func reconcileProvisionedNetworkComponents(networkingService *networking.Service, openStackCluster *infrav1.OpenStackCluster, clusterName string) error {
- err := networkingService.ReconcileNetwork(openStackCluster, clusterName)
+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 network: %w", err))
return fmt.Errorf("failed to reconcile network: %w", err)
}
- err = networkingService.ReconcileSubnet(openStackCluster, clusterName)
+ 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, clusterName)
+ 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)
@@ -723,7 +723,7 @@ func reconcileProvisionedNetworkComponents(networkingService *networking.Service
// 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, clusterName string) error {
+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
apiServerPort := getAPIServerPort(openStackCluster)
@@ -740,7 +740,7 @@ func reconcileControlPlaneEndpoint(scope *scope.WithLogger, networkingService *n
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 {
@@ -765,7 +765,7 @@ func reconcileControlPlaneEndpoint(scope *scope.WithLogger, networkingService *n
// 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 !pointer.BoolDeref(openStackCluster.Spec.DisableAPIServerFloatingIP, false):
- fp, err := networkingService.GetOrCreateFloatingIP(openStackCluster, openStackCluster, clusterName, openStackCluster.Spec.APIServerFloatingIP)
+ 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)
diff --git a/controllers/openstackmachine_controller.go b/controllers/openstackmachine_controller.go
index 3bce8afa22..230768a73a 100644
--- a/controllers/openstackmachine_controller.go
+++ b/controllers/openstackmachine_controller.go
@@ -150,22 +150,22 @@ func (r *OpenStackMachineReconciler) Reconcile(ctx context.Context, req ctrl.Req
}
scope := scope.NewWithLogger(clientScope, log)
- clusterName := fmt.Sprintf("%s-%s", cluster.Namespace, cluster.Name)
+ clusterResourceName := fmt.Sprintf("%s-%s", cluster.Namespace, cluster.Name)
// Handle deleted machines
if !openStackMachine.DeletionTimestamp.IsZero() {
- return r.reconcileDelete(scope, clusterName, infraCluster, machine, openStackMachine)
+ return r.reconcileDelete(scope, clusterResourceName, infraCluster, machine, openStackMachine)
}
// Handle non-deleted clusters
- return r.reconcileNormal(ctx, scope, clusterName, infraCluster, machine, openStackMachine)
+ return r.reconcileNormal(ctx, scope, clusterResourceName, infraCluster, machine, openStackMachine)
}
-func resolveMachineResources(scope *scope.WithLogger, clusterName string, openStackCluster *infrav1.OpenStackCluster, openStackMachine *infrav1.OpenStackMachine, machine *clusterv1.Machine) (bool, error) {
+func resolveMachineResources(scope *scope.WithLogger, clusterResourceName string, openStackCluster *infrav1.OpenStackCluster, openStackMachine *infrav1.OpenStackMachine, machine *clusterv1.Machine) (bool, error) {
// Resolve and store referenced resources
changed, err := compute.ResolveReferencedMachineResources(scope,
&openStackMachine.Spec, &openStackMachine.Status.ReferencedResources,
- clusterName, openStackMachine.Name,
+ clusterResourceName, openStackMachine.Name,
openStackCluster, getManagedSecurityGroup(openStackCluster, machine))
if err != nil {
return false, err
@@ -231,7 +231,7 @@ func (r *OpenStackMachineReconciler) SetupWithManager(ctx context.Context, mgr c
Complete(r)
}
-func (r *OpenStackMachineReconciler) reconcileDelete(scope *scope.WithLogger, clusterName string, 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")
computeService, err := compute.NewService(scope)
@@ -246,7 +246,7 @@ func (r *OpenStackMachineReconciler) reconcileDelete(scope *scope.WithLogger, cl
// We may have resources to adopt if the cluster is ready
if openStackCluster.Status.Ready && openStackCluster.Status.Network != nil {
- if _, err := resolveMachineResources(scope, clusterName, openStackCluster, openStackMachine, machine); err != nil {
+ if _, err := resolveMachineResources(scope, clusterResourceName, openStackCluster, openStackMachine, machine); err != nil {
return ctrl.Result{}, err
}
}
@@ -257,7 +257,7 @@ func (r *OpenStackMachineReconciler) reconcileDelete(scope *scope.WithLogger, cl
return ctrl.Result{}, err
}
- err = loadBalancerService.DeleteLoadBalancerMember(openStackCluster, machine, openStackMachine, clusterName)
+ err = loadBalancerService.DeleteLoadBalancerMember(openStackCluster, machine, 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 ctrl.Result{}, err
@@ -463,7 +463,7 @@ func (r *OpenStackMachineReconciler) reconcileDeleteFloatingAddressFromPool(scop
return r.Client.Update(context.Background(), claim)
}
-func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope *scope.WithLogger, clusterName string, openStackCluster *infrav1.OpenStackCluster, machine *clusterv1.Machine, openStackMachine *infrav1.OpenStackMachine) (_ ctrl.Result, reterr error) {
+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.
@@ -484,7 +484,7 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope
return ctrl.Result{RequeueAfter: waitForClusterInfrastructureReadyDuration}, nil
}
- if changed, err := resolveMachineResources(scope, clusterName, openStackCluster, openStackMachine, machine); changed || err != nil {
+ if changed, err := resolveMachineResources(scope, clusterResourceName, openStackCluster, openStackMachine, machine); changed || err != nil {
return ctrl.Result{}, err
}
@@ -597,7 +597,7 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope
return ctrl.Result{}, nil
}
- err = r.reconcileAPIServerLoadBalancer(scope, openStackCluster, openStackMachine, instanceStatus, instanceNS, clusterName)
+ err = r.reconcileAPIServerLoadBalancer(scope, openStackCluster, openStackMachine, instanceStatus, instanceNS, clusterResourceName)
if err != nil {
return ctrl.Result{}, err
}
@@ -606,7 +606,7 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope
return ctrl.Result{}, nil
}
-func (r *OpenStackMachineReconciler) reconcileAPIServerLoadBalancer(scope *scope.WithLogger, openStackCluster *infrav1.OpenStackCluster, openStackMachine *infrav1.OpenStackMachine, instanceStatus *compute.InstanceStatus, instanceNS *compute.InstanceNetworkStatus, clusterName string) error {
+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 {
@@ -619,7 +619,7 @@ func (r *OpenStackMachineReconciler) reconcileAPIServerLoadBalancer(scope *scope
}
if openStackCluster.Spec.APIServerLoadBalancer.IsEnabled() {
- err = r.reconcileLoadBalancerMember(scope, openStackCluster, openStackMachine, instanceNS, clusterName)
+ 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 fmt.Errorf("reconcile load balancer member: %w", err)
@@ -632,7 +632,7 @@ func (r *OpenStackMachineReconciler) reconcileAPIServerLoadBalancer(scope *scope
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 fmt.Errorf("get or create floating IP %v: %w", floatingIPAddress, err)
@@ -759,14 +759,14 @@ func getManagedSecurityGroup(openStackCluster *infrav1.OpenStackCluster, machine
return nil
}
-func (r *OpenStackMachineReconciler) reconcileLoadBalancerMember(scope *scope.WithLogger, 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/pkg/cloud/services/compute/referenced_resources.go b/pkg/cloud/services/compute/referenced_resources.go
index 11004b699e..72cd91047e 100644
--- a/pkg/cloud/services/compute/referenced_resources.go
+++ b/pkg/cloud/services/compute/referenced_resources.go
@@ -31,7 +31,7 @@ import (
// Note that we only set the fields in ReferencedMachineResources that are not set yet. This is ok because:
// - OpenStackMachine is immutable, so we can't change the spec after the machine is created.
// - the bastion is mutable, but we delete the bastion when the spec changes, so the bastion status will be empty.
-func ResolveReferencedMachineResources(scope *scope.WithLogger, spec *infrav1.OpenStackMachineSpec, resources *infrav1.ReferencedMachineResources, clusterName, baseName string, openStackCluster *infrav1.OpenStackCluster, managedSecurityGroup *string) (changed bool, err error) {
+func ResolveReferencedMachineResources(scope *scope.WithLogger, spec *infrav1.OpenStackMachineSpec, resources *infrav1.ReferencedMachineResources, clusterResourceName, baseName string, openStackCluster *infrav1.OpenStackCluster, managedSecurityGroup *string) (changed bool, err error) {
changed = false
computeService, err := NewService(scope)
@@ -74,7 +74,7 @@ func ResolveReferencedMachineResources(scope *scope.WithLogger, spec *infrav1.Op
// Network resources are required in order to get ports options.
if len(resources.Ports) == 0 {
defaultNetwork := openStackCluster.Status.Network
- portsOpts, err := networkingService.ConstructPorts(spec, clusterName, baseName, defaultNetwork, managedSecurityGroup, InstanceTags(spec, openStackCluster))
+ portsOpts, err := networkingService.ConstructPorts(spec, clusterResourceName, baseName, defaultNetwork, managedSecurityGroup, InstanceTags(spec, openStackCluster))
if err != nil {
return changed, err
}
diff --git a/pkg/cloud/services/compute/referenced_resources_test.go b/pkg/cloud/services/compute/referenced_resources_test.go
index 489f92cde2..47d2a6adb9 100644
--- a/pkg/cloud/services/compute/referenced_resources_test.go
+++ b/pkg/cloud/services/compute/referenced_resources_test.go
@@ -183,11 +183,11 @@ func Test_ResolveReferencedMachineResources(t *testing.T) {
if resources == nil {
resources = &infrav1.ReferencedMachineResources{}
}
- clusterName := "test-cluster"
+ clusterResourceName := "test-cluster"
baseName := "test-instance"
scope := scope.NewWithLogger(mockScopeFactory, log)
- _, err := ResolveReferencedMachineResources(scope, &tt.spec, resources, clusterName, baseName, openStackCluster, tt.managedSecurityGroup)
+ _, err := ResolveReferencedMachineResources(scope, &tt.spec, resources, clusterResourceName, baseName, openStackCluster, tt.managedSecurityGroup)
if tt.wantErr {
g.Expect(err).Error()
return
diff --git a/pkg/cloud/services/loadbalancer/loadbalancer.go b/pkg/cloud/services/loadbalancer/loadbalancer.go
index 993a1dfb22..2de72c81d6 100644
--- a/pkg/cloud/services/loadbalancer/loadbalancer.go
+++ b/pkg/cloud/services/loadbalancer/loadbalancer.go
@@ -67,13 +67,13 @@ var lookupHost = func(host string) (*string, error) {
}
// ReconcileLoadBalancer reconciles the load balancer for the given cluster.
-func (s *Service) ReconcileLoadBalancer(openStackCluster *infrav1.OpenStackCluster, clusterName string, apiServerPort int) (bool, error) {
+func (s *Service) ReconcileLoadBalancer(openStackCluster *infrav1.OpenStackCluster, clusterResourceName string, apiServerPort int) (bool, error) {
lbSpec := openStackCluster.Spec.APIServerLoadBalancer
if !lbSpec.IsEnabled() {
return false, nil
}
- loadBalancerName := getLoadBalancerName(clusterName)
+ loadBalancerName := getLoadBalancerName(clusterResourceName)
s.scope.Logger().Info("Reconciling load balancer", "name", loadBalancerName)
lbStatus := openStackCluster.Status.APIServerLoadBalancer
@@ -82,7 +82,7 @@ func (s *Service) ReconcileLoadBalancer(openStackCluster *infrav1.OpenStackClust
openStackCluster.Status.APIServerLoadBalancer = lbStatus
}
- lb, err := s.getOrCreateAPILoadBalancer(openStackCluster, clusterName)
+ lb, err := s.getOrCreateAPILoadBalancer(openStackCluster, clusterResourceName)
if err != nil {
return false, err
}
@@ -106,7 +106,7 @@ func (s *Service) ReconcileLoadBalancer(openStackCluster *infrav1.OpenStackClust
return false, err
}
- fp, err := s.networkingService.GetOrCreateFloatingIP(openStackCluster, openStackCluster, clusterName, floatingIPAddress)
+ fp, err := s.networkingService.GetOrCreateFloatingIP(openStackCluster, openStackCluster, clusterResourceName, floatingIPAddress)
if err != nil {
return false, err
}
@@ -136,7 +136,7 @@ func (s *Service) ReconcileLoadBalancer(openStackCluster *infrav1.OpenStackClust
portList := []int{apiServerPort}
portList = append(portList, lbSpec.AdditionalPorts...)
for _, port := range portList {
- if err := s.reconcileAPILoadBalancerListener(lb, openStackCluster, clusterName, port); err != nil {
+ if err := s.reconcileAPILoadBalancerListener(lb, openStackCluster, clusterResourceName, port); err != nil {
return false, err
}
}
@@ -256,8 +256,8 @@ func (s *Service) isAllowsCIDRSSupported(lb *loadbalancers.LoadBalancer) (bool,
}
// getOrCreateAPILoadBalancer returns an existing API loadbalancer if it already exists, or creates a new one if it does not.
-func (s *Service) getOrCreateAPILoadBalancer(openStackCluster *infrav1.OpenStackCluster, clusterName string) (*loadbalancers.LoadBalancer, error) {
- loadBalancerName := getLoadBalancerName(clusterName)
+func (s *Service) getOrCreateAPILoadBalancer(openStackCluster *infrav1.OpenStackCluster, clusterResourceName string) (*loadbalancers.LoadBalancer, error) {
+ loadBalancerName := getLoadBalancerName(clusterResourceName)
lb, err := s.checkIfLbExists(loadBalancerName)
if err != nil {
return nil, err
@@ -302,7 +302,7 @@ func (s *Service) getOrCreateAPILoadBalancer(openStackCluster *infrav1.OpenStack
lbCreateOpts := loadbalancers.CreateOpts{
Name: loadBalancerName,
VipSubnetID: subnetID,
- Description: names.GetDescription(clusterName),
+ Description: names.GetDescription(clusterResourceName),
Provider: lbProvider,
Tags: openStackCluster.Spec.Tags,
}
@@ -321,8 +321,8 @@ func (s *Service) getOrCreateAPILoadBalancer(openStackCluster *infrav1.OpenStack
}
// reconcileAPILoadBalancerListener ensures that the listener on the given port exists and is configured correctly.
-func (s *Service) reconcileAPILoadBalancerListener(lb *loadbalancers.LoadBalancer, openStackCluster *infrav1.OpenStackCluster, clusterName string, port int) error {
- loadBalancerName := getLoadBalancerName(clusterName)
+func (s *Service) reconcileAPILoadBalancerListener(lb *loadbalancers.LoadBalancer, openStackCluster *infrav1.OpenStackCluster, clusterResourceName string, port int) error {
+ loadBalancerName := getLoadBalancerName(clusterResourceName)
lbPortObjectsName := fmt.Sprintf("%s-%d", loadBalancerName, port)
if openStackCluster.Status.APIServerLoadBalancer == nil {
@@ -508,7 +508,7 @@ func (s *Service) getOrCreateMonitor(openStackCluster *infrav1.OpenStackCluster,
return nil
}
-func (s *Service) ReconcileLoadBalancerMember(openStackCluster *infrav1.OpenStackCluster, openStackMachine *infrav1.OpenStackMachine, clusterName, ip string) error {
+func (s *Service) ReconcileLoadBalancerMember(openStackCluster *infrav1.OpenStackCluster, openStackMachine *infrav1.OpenStackMachine, clusterResourceName, ip string) error {
if openStackCluster.Status.Network == nil {
return errors.New("network is not yet available in openStackCluster.Status")
}
@@ -522,7 +522,7 @@ func (s *Service) ReconcileLoadBalancerMember(openStackCluster *infrav1.OpenStac
return errors.New("ControlPlaneEndpoint is not yet set in openStackCluster.Spec")
}
- loadBalancerName := getLoadBalancerName(clusterName)
+ loadBalancerName := getLoadBalancerName(clusterResourceName)
s.scope.Logger().Info("Reconciling load balancer member", "loadBalancerName", loadBalancerName)
lbID := openStackCluster.Status.APIServerLoadBalancer.ID
@@ -598,8 +598,8 @@ func (s *Service) ReconcileLoadBalancerMember(openStackCluster *infrav1.OpenStac
return nil
}
-func (s *Service) DeleteLoadBalancer(openStackCluster *infrav1.OpenStackCluster, clusterName string) error {
- loadBalancerName := getLoadBalancerName(clusterName)
+func (s *Service) DeleteLoadBalancer(openStackCluster *infrav1.OpenStackCluster, clusterResourceName string) error {
+ loadBalancerName := getLoadBalancerName(clusterResourceName)
lb, err := s.checkIfLbExists(loadBalancerName)
if err != nil {
return err
@@ -645,12 +645,12 @@ func (s *Service) DeleteLoadBalancer(openStackCluster *infrav1.OpenStackCluster,
return nil
}
-func (s *Service) DeleteLoadBalancerMember(openStackCluster *infrav1.OpenStackCluster, machine *clusterv1.Machine, openStackMachine *infrav1.OpenStackMachine, clusterName string) error {
+func (s *Service) DeleteLoadBalancerMember(openStackCluster *infrav1.OpenStackCluster, machine *clusterv1.Machine, openStackMachine *infrav1.OpenStackMachine, clusterResourceName string) error {
if openStackMachine == nil || !util.IsControlPlaneMachine(machine) {
return nil
}
- loadBalancerName := getLoadBalancerName(clusterName)
+ loadBalancerName := getLoadBalancerName(clusterResourceName)
lb, err := s.checkIfLbExists(loadBalancerName)
if err != nil {
return err
@@ -705,8 +705,8 @@ func (s *Service) DeleteLoadBalancerMember(openStackCluster *infrav1.OpenStackCl
return nil
}
-func getLoadBalancerName(clusterName string) string {
- return fmt.Sprintf("%s-cluster-%s-%s", networkPrefix, clusterName, kubeapiLBSuffix)
+func getLoadBalancerName(clusterResourceName string) string {
+ return fmt.Sprintf("%s-cluster-%s-%s", networkPrefix, clusterResourceName, kubeapiLBSuffix)
}
func (s *Service) checkIfLbExists(name string) (*loadbalancers.LoadBalancer, error) {
diff --git a/pkg/cloud/services/networking/floatingip.go b/pkg/cloud/services/networking/floatingip.go
index 68f6cb2aac..3e495e77d0 100644
--- a/pkg/cloud/services/networking/floatingip.go
+++ b/pkg/cloud/services/networking/floatingip.go
@@ -33,7 +33,7 @@ import (
"sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/names"
)
-func (s *Service) GetOrCreateFloatingIP(eventObject runtime.Object, openStackCluster *infrav1.OpenStackCluster, clusterName string, ip *string) (*floatingips.FloatingIP, error) {
+func (s *Service) GetOrCreateFloatingIP(eventObject runtime.Object, openStackCluster *infrav1.OpenStackCluster, clusterResourceName string, ip *string) (*floatingips.FloatingIP, error) {
var fp *floatingips.FloatingIP
var err error
var fpCreateOpts floatingips.CreateOpts
@@ -51,7 +51,7 @@ func (s *Service) GetOrCreateFloatingIP(eventObject runtime.Object, openStackClu
}
fpCreateOpts.FloatingNetworkID = openStackCluster.Status.ExternalNetwork.ID
- fpCreateOpts.Description = names.GetDescription(clusterName)
+ fpCreateOpts.Description = names.GetDescription(clusterResourceName)
s.scope.Logger().Info("Creating floating IP", "ip", fpCreateOpts.FloatingIP, "floatingNetworkID", openStackCluster.Status.ExternalNetwork.ID, "description", fpCreateOpts.Description)
diff --git a/pkg/cloud/services/networking/network.go b/pkg/cloud/services/networking/network.go
index b5c16b003c..fbee4d4b10 100644
--- a/pkg/cloud/services/networking/network.go
+++ b/pkg/cloud/services/networking/network.go
@@ -116,8 +116,8 @@ func (s *Service) ReconcileExternalNetwork(openStackCluster *infrav1.OpenStackCl
return fmt.Errorf("found %d external networks, which should not happen", len(networkList))
}
-func (s *Service) ReconcileNetwork(openStackCluster *infrav1.OpenStackCluster, clusterName string) error {
- networkName := getNetworkName(clusterName)
+func (s *Service) ReconcileNetwork(openStackCluster *infrav1.OpenStackCluster, clusterResourceName string) error {
+ networkName := getNetworkName(clusterResourceName)
s.scope.Logger().Info("Reconciling network", "name", networkName)
res, err := s.getNetworkByName(networkName)
@@ -171,8 +171,8 @@ func (s *Service) ReconcileNetwork(openStackCluster *infrav1.OpenStackCluster, c
return nil
}
-func (s *Service) DeleteNetwork(openStackCluster *infrav1.OpenStackCluster, clusterName string) error {
- networkName := getNetworkName(clusterName)
+func (s *Service) DeleteNetwork(openStackCluster *infrav1.OpenStackCluster, clusterResourceName string) error {
+ networkName := getNetworkName(clusterResourceName)
network, err := s.getNetworkByName(networkName)
if err != nil {
return err
@@ -191,13 +191,13 @@ func (s *Service) DeleteNetwork(openStackCluster *infrav1.OpenStackCluster, clus
return nil
}
-func (s *Service) ReconcileSubnet(openStackCluster *infrav1.OpenStackCluster, clusterName string) error {
+func (s *Service) ReconcileSubnet(openStackCluster *infrav1.OpenStackCluster, clusterResourceName string) error {
if openStackCluster.Status.Network == nil || openStackCluster.Status.Network.ID == "" {
s.scope.Logger().V(4).Info("No need to reconcile network components since no network exists")
return nil
}
- subnetName := getSubnetName(clusterName)
+ subnetName := getSubnetName(clusterResourceName)
s.scope.Logger().Info("Reconciling subnet", "name", subnetName)
subnetList, err := s.client.ListSubnet(subnets.ListOpts{
@@ -217,7 +217,7 @@ func (s *Service) ReconcileSubnet(openStackCluster *infrav1.OpenStackCluster, cl
var subnet *subnets.Subnet
if len(subnetList) == 0 {
var err error
- subnet, err = s.createSubnet(openStackCluster, clusterName, subnetName)
+ subnet, err = s.createSubnet(openStackCluster, clusterResourceName, subnetName)
if err != nil {
return err
}
@@ -237,14 +237,14 @@ func (s *Service) ReconcileSubnet(openStackCluster *infrav1.OpenStackCluster, cl
return nil
}
-func (s *Service) createSubnet(openStackCluster *infrav1.OpenStackCluster, clusterName string, name string) (*subnets.Subnet, error) {
+func (s *Service) createSubnet(openStackCluster *infrav1.OpenStackCluster, clusterResourceName string, name string) (*subnets.Subnet, error) {
opts := subnets.CreateOpts{
NetworkID: openStackCluster.Status.Network.ID,
Name: name,
IPVersion: 4,
CIDR: openStackCluster.Spec.ManagedSubnets[0].CIDR,
DNSNameservers: openStackCluster.Spec.ManagedSubnets[0].DNSNameservers,
- Description: names.GetDescription(clusterName),
+ Description: names.GetDescription(clusterResourceName),
}
for _, pool := range openStackCluster.Spec.ManagedSubnets[0].AllocationPools {
@@ -374,12 +374,12 @@ func (s *Service) getSubnetByFilter(listOpts subnets.ListOpts) (*subnets.Subnet,
return &subnets[0], nil
}
-func getSubnetName(clusterName string) string {
- return fmt.Sprintf("%s-cluster-%s", networkPrefix, clusterName)
+func getSubnetName(clusterResourceName string) string {
+ return fmt.Sprintf("%s-cluster-%s", networkPrefix, clusterResourceName)
}
-func getNetworkName(clusterName string) string {
- return fmt.Sprintf("%s-cluster-%s", networkPrefix, clusterName)
+func getNetworkName(clusterResourceName string) string {
+ return fmt.Sprintf("%s-cluster-%s", networkPrefix, clusterResourceName)
}
// GetNetworkByID retrieves network by the ID.
diff --git a/pkg/cloud/services/networking/network_test.go b/pkg/cloud/services/networking/network_test.go
index 4a3401ce55..ff772ffe76 100644
--- a/pkg/cloud/services/networking/network_test.go
+++ b/pkg/cloud/services/networking/network_test.go
@@ -35,14 +35,14 @@ import (
)
const (
- clusterName = "test-cluster"
+ clusterResourceName = "test-cluster"
)
func Test_ReconcileNetwork(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
- expectedNetworkName := getNetworkName(clusterName)
+ expectedNetworkName := getNetworkName(clusterResourceName)
fakeNetworkID := "d08803fc-2fa5-4179-b9f7-8c43d0af2fe6"
tests := []struct {
@@ -198,7 +198,7 @@ func Test_ReconcileNetwork(t *testing.T) {
client: mockClient,
scope: scope.NewWithLogger(scopeFactory, log),
}
- err := s.ReconcileNetwork(tt.openStackCluster, clusterName)
+ err := s.ReconcileNetwork(tt.openStackCluster, clusterResourceName)
g.Expect(err).ShouldNot(HaveOccurred())
})
}
@@ -438,8 +438,8 @@ func Test_ReconcileSubnet(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
- expectedSubnetName := getSubnetName(clusterName)
- expectedSubnetDesc := names.GetDescription(clusterName)
+ expectedSubnetName := getSubnetName(clusterResourceName)
+ expectedSubnetDesc := names.GetDescription(clusterResourceName)
fakeSubnetID := "d08803fc-2fa5-4179-b9d7-8c43d0af2fe6"
fakeCIDR := "10.0.0.0/24"
fakeNetworkID := "d08803fc-2fa5-4279-b9f7-8c45d0ff2fe6"
@@ -686,7 +686,7 @@ func Test_ReconcileSubnet(t *testing.T) {
client: mockClient,
scope: scope.NewWithLogger(mockScopeFactory, log),
}
- err := s.ReconcileSubnet(tt.openStackCluster, clusterName)
+ err := s.ReconcileSubnet(tt.openStackCluster, clusterResourceName)
g.Expect(err).ShouldNot(HaveOccurred())
g.Expect(tt.openStackCluster.Status).To(Equal(*tt.want))
})
diff --git a/pkg/cloud/services/networking/port.go b/pkg/cloud/services/networking/port.go
index 4b6a894d56..df5975981f 100644
--- a/pkg/cloud/services/networking/port.go
+++ b/pkg/cloud/services/networking/port.go
@@ -335,7 +335,7 @@ func (s *Service) CreatePorts(eventObject runtime.Object, desiredPorts []infrav1
// ConstructPorts builds an array of ports from the machine spec.
// If no ports are in the spec, returns a single port for a network connection to the default cluster network.
-func (s *Service) ConstructPorts(spec *infrav1.OpenStackMachineSpec, clusterName, baseName string, defaultNetwork *infrav1.NetworkStatusWithSubnets, managedSecurityGroup *string, baseTags []string) ([]infrav1.ResolvedPortSpec, error) {
+func (s *Service) ConstructPorts(spec *infrav1.OpenStackMachineSpec, clusterResourceName, baseName string, defaultNetwork *infrav1.NetworkStatusWithSubnets, managedSecurityGroup *string, baseTags []string) ([]infrav1.ResolvedPortSpec, error) {
ports := spec.Ports
defaultSecurityGroupIDs, err := s.GetSecurityGroups(spec.SecurityGroups)
@@ -347,7 +347,7 @@ func (s *Service) ConstructPorts(spec *infrav1.OpenStackMachineSpec, clusterName
}
// Ensure user-specified ports have all required fields
- resolvedPorts, err := s.normalizePorts(ports, clusterName, baseName, spec.Trunk, defaultSecurityGroupIDs, defaultNetwork, baseTags)
+ resolvedPorts, err := s.normalizePorts(ports, clusterResourceName, baseName, spec.Trunk, defaultSecurityGroupIDs, defaultNetwork, baseTags)
if err != nil {
return nil, err
}
@@ -357,7 +357,7 @@ func (s *Service) ConstructPorts(spec *infrav1.OpenStackMachineSpec, clusterName
resolvedPorts = make([]infrav1.ResolvedPortSpec, 1)
resolvedPort := &resolvedPorts[0]
resolvedPort.Name = getPortName(baseName, nil, 0)
- resolvedPort.Description = names.GetDescription(clusterName)
+ resolvedPort.Description = names.GetDescription(clusterResourceName)
if len(baseTags) > 0 {
resolvedPort.Tags = baseTags
}
@@ -394,7 +394,7 @@ func (s *Service) ConstructPorts(spec *infrav1.OpenStackMachineSpec, clusterName
// normalizePorts ensures that a user-specified PortOpts has all required fields set. Specifically it:
// - sets the Trunk field to the instance spec default if not specified
// - sets the Network ID field if not specified.
-func (s *Service) normalizePorts(ports []infrav1.PortOpts, clusterName, baseName string, trunkEnabled bool, defaultSecurityGroupIDs []string, defaultNetwork *infrav1.NetworkStatusWithSubnets, baseTags []string) ([]infrav1.ResolvedPortSpec, error) {
+func (s *Service) normalizePorts(ports []infrav1.PortOpts, clusterResourceName, baseName string, trunkEnabled bool, defaultSecurityGroupIDs []string, defaultNetwork *infrav1.NetworkStatusWithSubnets, baseTags []string) ([]infrav1.ResolvedPortSpec, error) {
normalizedPorts := make([]infrav1.ResolvedPortSpec, len(ports))
for i := range ports {
port := &ports[i]
@@ -410,7 +410,7 @@ func (s *Service) normalizePorts(ports []infrav1.PortOpts, clusterName, baseName
if port.Description != nil {
normalizedPort.Description = *port.Description
} else {
- normalizedPort.Description = names.GetDescription(clusterName)
+ normalizedPort.Description = names.GetDescription(clusterResourceName)
}
// Tags are inherited base tags plus any port-specific tags
diff --git a/pkg/cloud/services/networking/port_test.go b/pkg/cloud/services/networking/port_test.go
index ecf567fe74..d0ae57ab6d 100644
--- a/pkg/cloud/services/networking/port_test.go
+++ b/pkg/cloud/services/networking/port_test.go
@@ -808,10 +808,10 @@ func TestService_ConstructPorts(t *testing.T) {
},
}
- clusterName := "test-cluster"
+ clusterResourceName := "test-cluster"
baseName := "test-instance"
baseTags := []string{"test-tag"}
- got, err := s.ConstructPorts(&tt.spec, clusterName, baseName, defaultNetwork, tt.managedSecurityGroup, baseTags)
+ got, err := s.ConstructPorts(&tt.spec, clusterResourceName, baseName, defaultNetwork, tt.managedSecurityGroup, baseTags)
if tt.wantErr {
g.Expect(err).To(HaveOccurred())
return
diff --git a/pkg/cloud/services/networking/router.go b/pkg/cloud/services/networking/router.go
index 749d5c3be9..e6267fdb30 100644
--- a/pkg/cloud/services/networking/router.go
+++ b/pkg/cloud/services/networking/router.go
@@ -31,7 +31,7 @@ import (
"sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/names"
)
-func (s *Service) ReconcileRouter(openStackCluster *infrav1.OpenStackCluster, clusterName string) error {
+func (s *Service) ReconcileRouter(openStackCluster *infrav1.OpenStackCluster, clusterResourceName string) error {
if openStackCluster.Status.Network == nil || openStackCluster.Status.Network.ID == "" {
s.scope.Logger().V(3).Info("No need to reconcile router since no network exists")
return nil
@@ -45,8 +45,8 @@ func (s *Service) ReconcileRouter(openStackCluster *infrav1.OpenStackCluster, cl
return nil
}
- s.scope.Logger().Info("Reconciling router", "cluster", clusterName)
- routerName := getRouterName(clusterName)
+ s.scope.Logger().Info("Reconciling router", "cluster", clusterResourceName)
+ routerName := getRouterName(clusterResourceName)
routerListOpts := routers.ListOpts{Name: routerName}
existingRouter := false
if openStackCluster.Spec.Router != nil {
@@ -65,7 +65,7 @@ func (s *Service) ReconcileRouter(openStackCluster *infrav1.OpenStackCluster, cl
if router.ID == "" {
var err error
- createdRouter, err := s.createRouter(openStackCluster, clusterName, routerName)
+ createdRouter, err := s.createRouter(openStackCluster, clusterResourceName, routerName)
if err != nil {
return err
}
@@ -125,9 +125,9 @@ func (s *Service) ReconcileRouter(openStackCluster *infrav1.OpenStackCluster, cl
return nil
}
-func (s *Service) createRouter(openStackCluster *infrav1.OpenStackCluster, clusterName, name string) (*routers.Router, error) {
+func (s *Service) createRouter(openStackCluster *infrav1.OpenStackCluster, clusterResourceName, name string) (*routers.Router, error) {
opts := routers.CreateOpts{
- Description: names.GetDescription(clusterName),
+ Description: names.GetDescription(clusterResourceName),
Name: name,
}
// only set the GatewayInfo right now when no externalIPs
@@ -192,8 +192,8 @@ func (s *Service) setRouterExternalIPs(openStackCluster *infrav1.OpenStackCluste
return nil
}
-func (s *Service) DeleteRouter(openStackCluster *infrav1.OpenStackCluster, clusterName string) error {
- routerName := getRouterName(clusterName)
+func (s *Service) DeleteRouter(openStackCluster *infrav1.OpenStackCluster, clusterResourceName string) error {
+ routerName := getRouterName(clusterResourceName)
listOpts := routers.ListOpts{Name: routerName}
existingRouter := false
if openStackCluster.Spec.Router != nil {
@@ -206,7 +206,7 @@ func (s *Service) DeleteRouter(openStackCluster *infrav1.OpenStackCluster, clust
return err
}
- subnetName := getSubnetName(clusterName)
+ subnetName := getSubnetName(clusterResourceName)
subnet, err := s.getSubnetByName(subnetName)
if err != nil {
return err
@@ -285,6 +285,6 @@ func (s *Service) getSubnetByName(subnetName string) (subnets.Subnet, error) {
return subnets.Subnet{}, fmt.Errorf("found %d subnets with the name %s, which should not happen", len(subnetList), subnetName)
}
-func getRouterName(clusterName string) string {
- return fmt.Sprintf("%s-cluster-%s", networkPrefix, clusterName)
+func getRouterName(clusterResourceName string) string {
+ return fmt.Sprintf("%s-cluster-%s", networkPrefix, clusterResourceName)
}
diff --git a/pkg/cloud/services/networking/securitygroups.go b/pkg/cloud/services/networking/securitygroups.go
index 76cc8e349e..ecde85fe84 100644
--- a/pkg/cloud/services/networking/securitygroups.go
+++ b/pkg/cloud/services/networking/securitygroups.go
@@ -39,7 +39,7 @@ const (
)
// ReconcileSecurityGroups reconcile the security groups.
-func (s *Service) ReconcileSecurityGroups(openStackCluster *infrav1.OpenStackCluster, clusterName string) error {
+func (s *Service) ReconcileSecurityGroups(openStackCluster *infrav1.OpenStackCluster, clusterResourceName string) error {
s.scope.Logger().Info("Reconciling security groups")
if openStackCluster.Spec.ManagedSecurityGroups == nil {
s.scope.Logger().V(4).Info("No need to reconcile security groups")
@@ -48,15 +48,15 @@ func (s *Service) ReconcileSecurityGroups(openStackCluster *infrav1.OpenStackClu
bastionEnabled := openStackCluster.Spec.Bastion != nil && openStackCluster.Spec.Bastion.Enabled
- secControlPlaneGroupName := getSecControlPlaneGroupName(clusterName)
- secWorkerGroupName := getSecWorkerGroupName(clusterName)
+ secControlPlaneGroupName := getSecControlPlaneGroupName(clusterResourceName)
+ secWorkerGroupName := getSecWorkerGroupName(clusterResourceName)
suffixToNameMap := map[string]string{
controlPlaneSuffix: secControlPlaneGroupName,
workerSuffix: secWorkerGroupName,
}
if bastionEnabled {
- secBastionGroupName := getSecBastionGroupName(clusterName)
+ secBastionGroupName := getSecBastionGroupName(clusterResourceName)
suffixToNameMap[bastionSuffix] = secBastionGroupName
}
@@ -345,14 +345,14 @@ func (s *Service) GetSecurityGroups(securityGroupParams []infrav1.SecurityGroupF
return sgIDs, nil
}
-func (s *Service) DeleteSecurityGroups(openStackCluster *infrav1.OpenStackCluster, clusterName string) error {
+func (s *Service) DeleteSecurityGroups(openStackCluster *infrav1.OpenStackCluster, clusterResourceName string) error {
secGroupNames := []string{
- getSecControlPlaneGroupName(clusterName),
- getSecWorkerGroupName(clusterName),
+ getSecControlPlaneGroupName(clusterResourceName),
+ getSecWorkerGroupName(clusterResourceName),
}
if openStackCluster.Spec.Bastion != nil && openStackCluster.Spec.Bastion.Enabled {
- secGroupNames = append(secGroupNames, getSecBastionGroupName(clusterName))
+ secGroupNames = append(secGroupNames, getSecBastionGroupName(clusterResourceName))
}
for _, secGroupName := range secGroupNames {
@@ -523,16 +523,16 @@ func (s *Service) createRule(securityGroupID string, r resolvedSecurityGroupRule
return nil
}
-func getSecControlPlaneGroupName(clusterName string) string {
- return fmt.Sprintf("%s-cluster-%s-secgroup-%s", secGroupPrefix, clusterName, controlPlaneSuffix)
+func getSecControlPlaneGroupName(clusterResourceName string) string {
+ return fmt.Sprintf("%s-cluster-%s-secgroup-%s", secGroupPrefix, clusterResourceName, controlPlaneSuffix)
}
-func getSecWorkerGroupName(clusterName string) string {
- return fmt.Sprintf("%s-cluster-%s-secgroup-%s", secGroupPrefix, clusterName, workerSuffix)
+func getSecWorkerGroupName(clusterResourceName string) string {
+ return fmt.Sprintf("%s-cluster-%s-secgroup-%s", secGroupPrefix, clusterResourceName, workerSuffix)
}
-func getSecBastionGroupName(clusterName string) string {
- return fmt.Sprintf("%s-cluster-%s-secgroup-%s", secGroupPrefix, clusterName, bastionSuffix)
+func getSecBastionGroupName(clusterResourceName string) string {
+ return fmt.Sprintf("%s-cluster-%s-secgroup-%s", secGroupPrefix, clusterResourceName, bastionSuffix)
}
func convertOSSecGroupToConfigSecGroup(osSecGroup *groups.SecGroup) *infrav1.SecurityGroupStatus {
diff --git a/pkg/cloud/services/networking/securitygroups_test.go b/pkg/cloud/services/networking/securitygroups_test.go
index 04d4ff870d..f40e4a5d75 100644
--- a/pkg/cloud/services/networking/securitygroups_test.go
+++ b/pkg/cloud/services/networking/securitygroups_test.go
@@ -480,7 +480,7 @@ func TestReconcileGroupRules(t *testing.T) {
func TestService_ReconcileSecurityGroups(t *testing.T) {
const (
- clusterName = "test-cluster"
+ clusterResourceName = "test-cluster"
controlPlaneSGName = "k8s-cluster-test-cluster-secgroup-controlplane"
workerSGName = "k8s-cluster-test-cluster-secgroup-worker"
@@ -590,7 +590,7 @@ func TestService_ReconcileSecurityGroups(t *testing.T) {
openStackCluster := &infrav1.OpenStackCluster{
Spec: tt.openStackClusterSpec,
}
- err := s.ReconcileSecurityGroups(openStackCluster, clusterName)
+ err := s.ReconcileSecurityGroups(openStackCluster, clusterResourceName)
if tt.wantErr {
g.Expect(err).ToNot(BeNil(), "ReconcileSecurityGroups")
} else {
diff --git a/pkg/utils/names/names.go b/pkg/utils/names/names.go
index ee1238f48f..5f2ae23045 100644
--- a/pkg/utils/names/names.go
+++ b/pkg/utils/names/names.go
@@ -27,8 +27,8 @@ const (
FloatingAddressIPClaimNameSuffix = "floating-ip-address"
)
-func GetDescription(clusterName string) string {
- return fmt.Sprintf("Created by cluster-api-provider-openstack cluster %s", clusterName)
+func GetDescription(clusterResourceName string) string {
+ return fmt.Sprintf("Created by cluster-api-provider-openstack cluster %s", clusterResourceName)
}
func GetFloatingAddressClaimName(openStackMachineName string) string {
@@ -39,6 +39,8 @@ func GetOpenStackMachineNameFromClaimName(claimName string) string {
return strings.TrimSuffix(claimName, fmt.Sprintf("-%s", FloatingAddressIPClaimNameSuffix))
}
-func ClusterName(cluster *clusterv1.Cluster) string {
+// ClusterResourceName returns a string which is used as the base of all
+// OpenStack resources created for the cluster.
+func ClusterResourceName(cluster *clusterv1.Cluster) string {
return fmt.Sprintf("%s-%s", cluster.Namespace, cluster.Name)
}
From 5f09ba27a2b7d3c3f1825d349ed7618d4f028910 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Thu, 21 Mar 2024 12:11:50 +0000
Subject: [PATCH 145/180] Rename DependentResources to Resources
The intent of this structure is to hold all OpenStack resources created
for the machine, including the server. 'dependent' was redundant.
---
api/v1alpha5/conversion_test.go | 2 +-
api/v1alpha5/zz_generated.conversion.go | 2 +-
api/v1alpha6/openstackcluster_conversion.go | 4 +-
api/v1alpha6/openstackmachine_conversion.go | 4 +-
api/v1alpha6/zz_generated.conversion.go | 2 +-
api/v1alpha7/openstackcluster_conversion.go | 4 +-
api/v1alpha7/openstackmachine_conversion.go | 4 +-
api/v1alpha7/zz_generated.conversion.go | 4 +-
api/v1beta1/openstackmachine_types.go | 4 +-
api/v1beta1/types.go | 4 +-
api/v1beta1/zz_generated.deepcopy.go | 44 +++++-----
...re.cluster.x-k8s.io_openstackclusters.yaml | 30 +++----
...re.cluster.x-k8s.io_openstackmachines.yaml | 34 ++++----
controllers/openstackcluster_controller.go | 20 ++---
.../openstackcluster_controller_test.go | 16 ++--
controllers/openstackmachine_controller.go | 14 ++--
docs/book/src/api/v1beta1/api.md | 82 +++++++++----------
...dent_resources.go => machine_resources.go} | 4 +-
pkg/cloud/services/networking/port.go | 16 ++--
pkg/cloud/services/networking/port_test.go | 36 ++++----
20 files changed, 165 insertions(+), 165 deletions(-)
rename pkg/cloud/services/compute/{dependent_resources.go => machine_resources.go} (82%)
diff --git a/api/v1alpha5/conversion_test.go b/api/v1alpha5/conversion_test.go
index 72b3c62851..b7dbbbac2b 100644
--- a/api/v1alpha5/conversion_test.go
+++ b/api/v1alpha5/conversion_test.go
@@ -87,7 +87,7 @@ func TestConvertFrom(t *testing.T) {
Spec: OpenStackMachineSpec{},
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
- "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"flavor\":\"\",\"image\":{}},\"status\":{\"dependentResources\":{},\"ready\":false,\"referencedResources\":{}}}",
+ "cluster.x-k8s.io/conversion-data": `{"spec":{"flavor":"","image":{}},"status":{"ready":false,"referencedResources":{},"resources":{}}}`,
},
},
},
diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go
index 60a6ff055b..c7cac5b353 100644
--- a/api/v1alpha5/zz_generated.conversion.go
+++ b/api/v1alpha5/zz_generated.conversion.go
@@ -1213,7 +1213,7 @@ func autoConvert_v1beta1_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineStat
out.Addresses = *(*[]corev1.NodeAddress)(unsafe.Pointer(&in.Addresses))
out.InstanceState = (*InstanceState)(unsafe.Pointer(in.InstanceState))
// WARNING: in.ReferencedResources requires manual conversion: does not exist in peer-type
- // WARNING: in.DependentResources 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))
diff --git a/api/v1alpha6/openstackcluster_conversion.go b/api/v1alpha6/openstackcluster_conversion.go
index 2991efe751..8d0a87efea 100644
--- a/api/v1alpha6/openstackcluster_conversion.go
+++ b/api/v1alpha6/openstackcluster_conversion.go
@@ -370,8 +370,8 @@ func restorev1beta1ClusterStatus(previous *infrav1.OpenStackClusterStatus, dst *
if previous.Bastion != nil {
dst.Bastion.ReferencedResources = previous.Bastion.ReferencedResources
}
- if previous.Bastion != nil && previous.Bastion.DependentResources.Ports != nil {
- dst.Bastion.DependentResources.Ports = previous.Bastion.DependentResources.Ports
+ if previous.Bastion != nil && previous.Bastion.Resources.Ports != nil {
+ dst.Bastion.Resources.Ports = previous.Bastion.Resources.Ports
}
}
diff --git a/api/v1alpha6/openstackmachine_conversion.go b/api/v1alpha6/openstackmachine_conversion.go
index f7b114ed12..7f92ec0b65 100644
--- a/api/v1alpha6/openstackmachine_conversion.go
+++ b/api/v1alpha6/openstackmachine_conversion.go
@@ -90,8 +90,8 @@ var v1beta1OpenStackMachineRestorer = conversion.RestorerFor[*infrav1.OpenStackM
restorev1beta1MachineSpec,
),
"depresources": conversion.UnconditionalFieldRestorer(
- func(c *infrav1.OpenStackMachine) *infrav1.DependentMachineResources {
- return &c.Status.DependentResources
+ func(c *infrav1.OpenStackMachine) *infrav1.MachineResources {
+ return &c.Status.Resources
},
),
// No equivalent in v1alpha6
diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go
index b38e4436e2..e9bdedeb0f 100644
--- a/api/v1alpha6/zz_generated.conversion.go
+++ b/api/v1alpha6/zz_generated.conversion.go
@@ -1248,7 +1248,7 @@ func autoConvert_v1beta1_OpenStackMachineStatus_To_v1alpha6_OpenStackMachineStat
out.Addresses = *(*[]corev1.NodeAddress)(unsafe.Pointer(&in.Addresses))
out.InstanceState = (*InstanceState)(unsafe.Pointer(in.InstanceState))
// WARNING: in.ReferencedResources requires manual conversion: does not exist in peer-type
- // WARNING: in.DependentResources 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))
diff --git a/api/v1alpha7/openstackcluster_conversion.go b/api/v1alpha7/openstackcluster_conversion.go
index 7384a9fa2c..641148b654 100644
--- a/api/v1alpha7/openstackcluster_conversion.go
+++ b/api/v1alpha7/openstackcluster_conversion.go
@@ -353,8 +353,8 @@ func restorev1beta1ClusterStatus(previous *infrav1.OpenStackClusterStatus, dst *
dst.Bastion.ReferencedResources = previous.Bastion.ReferencedResources
}
- if previous.Bastion != nil && previous.Bastion.DependentResources.Ports != nil {
- dst.Bastion.DependentResources.Ports = previous.Bastion.DependentResources.Ports
+ if previous.Bastion != nil && previous.Bastion.Resources.Ports != nil {
+ dst.Bastion.Resources.Ports = previous.Bastion.Resources.Ports
}
}
diff --git a/api/v1alpha7/openstackmachine_conversion.go b/api/v1alpha7/openstackmachine_conversion.go
index d18db4e676..9ee3b01c8c 100644
--- a/api/v1alpha7/openstackmachine_conversion.go
+++ b/api/v1alpha7/openstackmachine_conversion.go
@@ -77,8 +77,8 @@ var v1beta1OpenStackMachineRestorer = conversion.RestorerFor[*infrav1.OpenStackM
restorev1beta1MachineSpec,
),
"depresources": conversion.UnconditionalFieldRestorer(
- func(c *infrav1.OpenStackMachine) *infrav1.DependentMachineResources {
- return &c.Status.DependentResources
+ func(c *infrav1.OpenStackMachine) *infrav1.MachineResources {
+ return &c.Status.Resources
},
),
// No equivalent in v1alpha7
diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go
index 4d72d623f4..f7b10f6064 100644
--- a/api/v1alpha7/zz_generated.conversion.go
+++ b/api/v1alpha7/zz_generated.conversion.go
@@ -574,7 +574,7 @@ func autoConvert_v1beta1_BastionStatus_To_v1alpha7_BastionStatus(in *v1beta1.Bas
out.IP = in.IP
out.FloatingIP = in.FloatingIP
// WARNING: in.ReferencedResources requires manual conversion: does not exist in peer-type
- // WARNING: in.DependentResources requires manual conversion: does not exist in peer-type
+ // WARNING: in.Resources requires manual conversion: does not exist in peer-type
return nil
}
@@ -1448,7 +1448,7 @@ func autoConvert_v1beta1_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStat
out.Addresses = *(*[]corev1.NodeAddress)(unsafe.Pointer(&in.Addresses))
out.InstanceState = (*InstanceState)(unsafe.Pointer(in.InstanceState))
// WARNING: in.ReferencedResources requires manual conversion: does not exist in peer-type
- // WARNING: in.DependentResources 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))
diff --git a/api/v1beta1/openstackmachine_types.go b/api/v1beta1/openstackmachine_types.go
index b4f3babef9..43d4f05574 100644
--- a/api/v1beta1/openstackmachine_types.go
+++ b/api/v1beta1/openstackmachine_types.go
@@ -129,8 +129,8 @@ type OpenStackMachineStatus struct {
// ReferencedResources contains resolved references to resources that the machine depends on.
ReferencedResources ReferencedMachineResources `json:"referencedResources,omitempty"`
- // DependentResources contains resolved dependent resources that were created by the machine.
- DependentResources DependentMachineResources `json:"dependentResources,omitempty"`
+ // Resources contains references to OpenStack resources created for the machine.
+ Resources MachineResources `json:"resources,omitempty"`
FailureReason *errors.MachineStatusError `json:"failureReason,omitempty"`
diff --git a/api/v1beta1/types.go b/api/v1beta1/types.go
index f5f8fcfa22..01316d955f 100644
--- a/api/v1beta1/types.go
+++ b/api/v1beta1/types.go
@@ -365,7 +365,7 @@ type BastionStatus struct {
IP string `json:"ip,omitempty"`
FloatingIP string `json:"floatingIP,omitempty"`
ReferencedResources ReferencedMachineResources `json:"referencedResources,omitempty"`
- DependentResources DependentMachineResources `json:"dependentResources,omitempty"`
+ Resources MachineResources `json:"resources,omitempty"`
}
type RootVolume struct {
@@ -673,7 +673,7 @@ type ReferencedMachineResources struct {
Ports []ResolvedPortSpec `json:"ports,omitempty"`
}
-type DependentMachineResources struct {
+type MachineResources struct {
// Ports is the status of the ports created for the machine.
// +optional
Ports []PortStatus `json:"ports,omitempty"`
diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go
index 98c11cbbf4..d9e22e65c4 100644
--- a/api/v1beta1/zz_generated.deepcopy.go
+++ b/api/v1beta1/zz_generated.deepcopy.go
@@ -147,7 +147,7 @@ func (in *Bastion) DeepCopy() *Bastion {
func (in *BastionStatus) DeepCopyInto(out *BastionStatus) {
*out = *in
in.ReferencedResources.DeepCopyInto(&out.ReferencedResources)
- in.DependentResources.DeepCopyInto(&out.DependentResources)
+ in.Resources.DeepCopyInto(&out.Resources)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BastionStatus.
@@ -220,26 +220,6 @@ func (in *BlockDeviceVolume) DeepCopy() *BlockDeviceVolume {
return out
}
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *DependentMachineResources) DeepCopyInto(out *DependentMachineResources) {
- *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 DependentMachineResources.
-func (in *DependentMachineResources) DeepCopy() *DependentMachineResources {
- if in == nil {
- return nil
- }
- out := new(DependentMachineResources)
- in.DeepCopyInto(out)
- return out
-}
-
// 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
@@ -371,6 +351,26 @@ 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
@@ -965,7 +965,7 @@ func (in *OpenStackMachineStatus) DeepCopyInto(out *OpenStackMachineStatus) {
**out = **in
}
in.ReferencedResources.DeepCopyInto(&out.ReferencedResources)
- in.DependentResources.DeepCopyInto(&out.DependentResources)
+ in.Resources.DeepCopyInto(&out.Resources)
if in.FailureReason != nil {
in, out := &in.FailureReason, &out.FailureReason
*out = new(errors.MachineStatusError)
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 3130c26513..fda2df3277 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -6242,21 +6242,6 @@ spec:
description: Bastion contains the information about the deployed bastion
host
properties:
- dependentResources:
- 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
floatingIP:
type: string
id:
@@ -6449,6 +6434,21 @@ spec:
machine should be added to and is calculated based on ServerGroupFilter.
type: string
type: object
+ resources:
+ 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:
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 74bbae9e0b..8cea0408b3 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
@@ -2421,23 +2421,6 @@ spec:
- type
type: object
type: array
- dependentResources:
- description: DependentResources contains resolved dependent resources
- that were created by 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
failureMessage:
description: |-
FailureMessage will be set in the event that there is a terminal problem
@@ -2652,6 +2635,23 @@ spec:
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/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index 2f742c5545..dbc2527042 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -219,7 +219,7 @@ func contains(arr []string, target string) bool {
}
func resolveBastionResources(scope *scope.WithLogger, clusterResourceName string, openStackCluster *infrav1.OpenStackCluster) (bool, error) {
- // Resolve and store referenced & dependent resources for the bastion
+ // Resolve and store resources for the bastion
if openStackCluster.Spec.Bastion != nil && openStackCluster.Spec.Bastion.Enabled {
if openStackCluster.Status.Bastion == nil {
openStackCluster.Status.Bastion = &infrav1.BastionStatus{}
@@ -239,9 +239,9 @@ func resolveBastionResources(scope *scope.WithLogger, clusterResourceName string
return true, nil
}
- err = compute.AdoptDependentMachineResources(scope,
+ err = compute.AdoptMachineResources(scope,
&openStackCluster.Status.Bastion.ReferencedResources,
- &openStackCluster.Status.Bastion.DependentResources)
+ &openStackCluster.Status.Bastion.Resources)
if err != nil {
return false, err
}
@@ -308,18 +308,18 @@ func deleteBastion(scope *scope.WithLogger, cluster *clusterv1.Cluster, openStac
}
}
- if openStackCluster.Status.Bastion != nil && len(openStackCluster.Status.Bastion.DependentResources.Ports) > 0 {
+ if openStackCluster.Status.Bastion != nil && len(openStackCluster.Status.Bastion.Resources.Ports) > 0 {
trunkSupported, err := networkingService.IsTrunkExtSupported()
if err != nil {
return err
}
- for _, port := range openStackCluster.Status.Bastion.DependentResources.Ports {
+ for _, port := range openStackCluster.Status.Bastion.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)
}
}
- openStackCluster.Status.Bastion.DependentResources.Ports = nil
+ openStackCluster.Status.Bastion.Resources.Ports = nil
}
scope.Logger().Info("Deleted Bastion")
@@ -445,7 +445,7 @@ func reconcileBastion(scope *scope.WithLogger, cluster *clusterv1.Cluster, openS
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.DependentResources.Ports)
+ bastionPortIDs := GetPortIDs(openStackCluster.Status.Bastion.Resources.Ports)
var instanceStatus *compute.InstanceStatus
if openStackCluster.Status.Bastion != nil && openStackCluster.Status.Bastion.ID != "" {
@@ -579,13 +579,13 @@ func getBastionSecurityGroupID(openStackCluster *infrav1.OpenStackCluster) *stri
func getOrCreateBastionPorts(openStackCluster *infrav1.OpenStackCluster, networkingService *networking.Service) error {
desiredPorts := openStackCluster.Status.Bastion.ReferencedResources.Ports
- dependentResources := &openStackCluster.Status.Bastion.DependentResources
+ resources := &openStackCluster.Status.Bastion.Resources
- if len(desiredPorts) == len(dependentResources.Ports) {
+ if len(desiredPorts) == len(resources.Ports) {
return nil
}
- err := networkingService.CreatePorts(openStackCluster, desiredPorts, dependentResources)
+ err := networkingService.CreatePorts(openStackCluster, desiredPorts, resources)
if err != nil {
return fmt.Errorf("failed to create ports for bastion %s: %w", bastionName(openStackCluster.Name), err)
}
diff --git a/controllers/openstackcluster_controller_test.go b/controllers/openstackcluster_controller_test.go
index 198f55a818..a7aa20892a 100644
--- a/controllers/openstackcluster_controller_test.go
+++ b/controllers/openstackcluster_controller_test.go
@@ -245,7 +245,7 @@ var _ = Describe("OpenStackCluster controller", func() {
},
},
},
- DependentResources: infrav1.DependentMachineResources{
+ Resources: infrav1.MachineResources{
Ports: []infrav1.PortStatus{
{
ID: "portID1",
@@ -294,7 +294,7 @@ var _ = Describe("OpenStackCluster controller", func() {
},
},
},
- DependentResources: infrav1.DependentMachineResources{
+ Resources: infrav1.MachineResources{
Ports: []infrav1.PortStatus{
{
ID: "portID1",
@@ -335,7 +335,7 @@ var _ = Describe("OpenStackCluster controller", func() {
},
},
},
- DependentResources: infrav1.DependentMachineResources{
+ Resources: infrav1.MachineResources{
Ports: []infrav1.PortStatus{
{
ID: "portID1",
@@ -377,7 +377,7 @@ var _ = Describe("OpenStackCluster controller", func() {
},
},
},
- DependentResources: infrav1.DependentMachineResources{
+ Resources: infrav1.MachineResources{
Ports: []infrav1.PortStatus{
{
ID: "portID1",
@@ -417,7 +417,7 @@ var _ = Describe("OpenStackCluster controller", func() {
},
},
},
- DependentResources: infrav1.DependentMachineResources{
+ Resources: infrav1.MachineResources{
Ports: []infrav1.PortStatus{
{
ID: "portID1",
@@ -453,7 +453,7 @@ var _ = Describe("OpenStackCluster controller", func() {
},
},
},
- DependentResources: infrav1.DependentMachineResources{
+ Resources: infrav1.MachineResources{
Ports: []infrav1.PortStatus{
{
ID: "portID1",
@@ -528,7 +528,7 @@ var _ = Describe("OpenStackCluster controller", func() {
}
testCluster.Status = infrav1.OpenStackClusterStatus{
Bastion: &infrav1.BastionStatus{
- DependentResources: infrav1.DependentMachineResources{
+ Resources: infrav1.MachineResources{
Ports: []infrav1.PortStatus{
{
ID: "port-id",
@@ -613,7 +613,7 @@ var _ = Describe("OpenStackCluster controller", func() {
}
testCluster.Status = infrav1.OpenStackClusterStatus{
Bastion: &infrav1.BastionStatus{
- DependentResources: infrav1.DependentMachineResources{
+ Resources: infrav1.MachineResources{
Ports: []infrav1.PortStatus{
{
ID: "port-id",
diff --git a/controllers/openstackmachine_controller.go b/controllers/openstackmachine_controller.go
index 230768a73a..a537d389f0 100644
--- a/controllers/openstackmachine_controller.go
+++ b/controllers/openstackmachine_controller.go
@@ -175,8 +175,8 @@ func resolveMachineResources(scope *scope.WithLogger, clusterResourceName string
return true, nil
}
- // Adopt any existing dependent resources
- return false, compute.AdoptDependentMachineResources(scope, &openStackMachine.Status.ReferencedResources, &openStackMachine.Status.DependentResources)
+ // Adopt any existing resources
+ return false, compute.AdoptMachineResources(scope, &openStackMachine.Status.ReferencedResources, &openStackMachine.Status.Resources)
}
func patchMachine(ctx context.Context, patchHelper *patch.Helper, openStackMachine *infrav1.OpenStackMachine, machine *clusterv1.Machine, options ...patch.Option) error {
@@ -308,7 +308,7 @@ func (r *OpenStackMachineReconciler) reconcileDelete(scope *scope.WithLogger, cl
return ctrl.Result{}, err
}
- portsStatus := openStackMachine.Status.DependentResources.Ports
+ 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)
@@ -519,7 +519,7 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope
if err != nil {
return ctrl.Result{}, err
}
- portIDs := GetPortIDs(openStackMachine.Status.DependentResources.Ports)
+ portIDs := GetPortIDs(openStackMachine.Status.Resources.Ports)
instanceStatus, err := r.getOrCreateInstance(scope.Logger(), openStackCluster, machine, openStackMachine, computeService, userData, portIDs)
if err != nil || instanceStatus == nil {
@@ -659,13 +659,13 @@ func (r *OpenStackMachineReconciler) reconcileAPIServerLoadBalancer(scope *scope
func getOrCreateMachinePorts(openStackMachine *infrav1.OpenStackMachine, networkingService *networking.Service) error {
desiredPorts := openStackMachine.Status.ReferencedResources.Ports
- dependentResources := &openStackMachine.Status.DependentResources
+ resources := &openStackMachine.Status.Resources
- if len(desiredPorts) == len(dependentResources.Ports) {
+ if len(desiredPorts) == len(resources.Ports) {
return nil
}
- if err := networkingService.CreatePorts(openStackMachine, desiredPorts, dependentResources); err != nil {
+ if err := networkingService.CreatePorts(openStackMachine, desiredPorts, resources); err != nil {
return fmt.Errorf("creating ports: %w", err)
}
diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md
index e4d1ac338a..8909adc3c7 100644
--- a/docs/book/src/api/v1beta1/api.md
+++ b/docs/book/src/api/v1beta1/api.md
@@ -1224,10 +1224,10 @@ ReferencedMachineResources
-dependentResources
+resources
-
-DependentMachineResources
+
+MachineResources
|
@@ -1399,39 +1399,6 @@ further information.
-DependentMachineResources
-
-
-(Appears on:
-BastionStatus,
-OpenStackMachineStatus)
-
-
-
-
-
-
-| Field |
-Description |
-
-
-
-
-
-ports
-
-
-[]PortStatus
-
-
- |
-
-(Optional)
- Ports is the status of the ports created for the machine.
- |
-
-
-
ExternalRouterIPParam
@@ -1750,6 +1717,39 @@ string
+
MachineResources
+
+
+(Appears on:
+BastionStatus,
+OpenStackMachineStatus)
+
+
+
+
+
+
+| Field |
+Description |
+
+
+
+
+
+ports
+
+
+[]PortStatus
+
+
+ |
+
+(Optional)
+ Ports is the status of the ports created for the machine.
+ |
+
+
+
ManagedSecurityGroupName
(string alias)
@@ -3299,15 +3299,15 @@ ReferencedMachineResources
-dependentResources
+resources
-
-DependentMachineResources
+
+MachineResources
|
- DependentResources contains resolved dependent resources that were created by the machine.
+Resources contains references to OpenStack resources created for the machine.
|
@@ -3764,7 +3764,7 @@ ResolvedPortSpecFields
(Appears on:
-DependentMachineResources)
+MachineResources)
diff --git a/pkg/cloud/services/compute/dependent_resources.go b/pkg/cloud/services/compute/machine_resources.go
similarity index 82%
rename from pkg/cloud/services/compute/dependent_resources.go
rename to pkg/cloud/services/compute/machine_resources.go
index 0d45f07fb4..7061fed468 100644
--- a/pkg/cloud/services/compute/dependent_resources.go
+++ b/pkg/cloud/services/compute/machine_resources.go
@@ -22,11 +22,11 @@ import (
"sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
)
-func AdoptDependentMachineResources(scope *scope.WithLogger, referencedResources *infrav1.ReferencedMachineResources, dependentResources *infrav1.DependentMachineResources) error {
+func AdoptMachineResources(scope *scope.WithLogger, referencedResources *infrav1.ReferencedMachineResources, resources *infrav1.MachineResources) error {
networkingService, err := networking.NewService(scope)
if err != nil {
return err
}
- return networkingService.AdoptPorts(scope, referencedResources.Ports, dependentResources)
+ return networkingService.AdoptPorts(scope, referencedResources.Ports, resources)
}
diff --git a/pkg/cloud/services/networking/port.go b/pkg/cloud/services/networking/port.go
index df5975981f..f1fbfef6ce 100644
--- a/pkg/cloud/services/networking/port.go
+++ b/pkg/cloud/services/networking/port.go
@@ -311,10 +311,10 @@ func getPortName(baseName string, portSpec *infrav1.PortOpts, netIndex int) stri
return fmt.Sprintf("%s-%d", baseName, netIndex)
}
-func (s *Service) CreatePorts(eventObject runtime.Object, desiredPorts []infrav1.ResolvedPortSpec, dependentResources *infrav1.DependentMachineResources) error {
+func (s *Service) CreatePorts(eventObject runtime.Object, desiredPorts []infrav1.ResolvedPortSpec, resources *infrav1.MachineResources) error {
for i := range desiredPorts {
// Skip creation of ports which already exist
- if i < len(dependentResources.Ports) {
+ if i < len(resources.Ports) {
continue
}
@@ -325,7 +325,7 @@ func (s *Service) CreatePorts(eventObject runtime.Object, desiredPorts []infrav1
return err
}
- dependentResources.Ports = append(dependentResources.Ports, infrav1.PortStatus{
+ resources.Ports = append(resources.Ports, infrav1.PortStatus{
ID: port.ID,
})
}
@@ -558,11 +558,11 @@ func (s *Service) IsTrunkExtSupported() (trunknSupported bool, err error) {
return true, nil
}
-// AdoptPorts looks for ports in desiredPorts which were previously created, and adds them to dependentResources.Ports.
+// AdoptPorts looks for ports in desiredPorts which were previously created, and adds them to resources.Ports.
// A port matches if it has the same name and network ID as the desired port.
-func (s *Service) AdoptPorts(scope *scope.WithLogger, desiredPorts []infrav1.ResolvedPortSpec, dependentResources *infrav1.DependentMachineResources) error {
+func (s *Service) AdoptPorts(scope *scope.WithLogger, desiredPorts []infrav1.ResolvedPortSpec, resources *infrav1.MachineResources) error {
// We can skip adoption if the ports are already in the status
- if len(desiredPorts) == len(dependentResources.Ports) {
+ if len(desiredPorts) == len(resources.Ports) {
return nil
}
@@ -573,7 +573,7 @@ func (s *Service) AdoptPorts(scope *scope.WithLogger, desiredPorts []infrav1.Res
// We can therefore stop searching for ports once we find one that doesn't exist.
for i := range desiredPorts {
// check if the port is in status first and if it is, skip it
- if i < len(dependentResources.Ports) {
+ if i < len(resources.Ports) {
scope.Logger().V(5).Info("Port already in status, skipping it", "port index", i)
continue
}
@@ -599,7 +599,7 @@ func (s *Service) AdoptPorts(scope *scope.WithLogger, desiredPorts []infrav1.Res
// The desired port was found, so we add it to the status
portID := ports[0].ID
scope.Logger().Info("Adopted previously created port which was not in status", "port index", i, "portID", portID)
- dependentResources.Ports = append(dependentResources.Ports, infrav1.PortStatus{ID: portID})
+ resources.Ports = append(resources.Ports, infrav1.PortStatus{ID: portID})
}
return nil
diff --git a/pkg/cloud/services/networking/port_test.go b/pkg/cloud/services/networking/port_test.go
index d0ae57ab6d..466ee35a89 100644
--- a/pkg/cloud/services/networking/port_test.go
+++ b/pkg/cloud/services/networking/port_test.go
@@ -886,12 +886,12 @@ func Test_AdoptPorts(t *testing.T) {
)
tests := []struct {
- testName string
- desiredPorts []infrav1.ResolvedPortSpec
- dependentResources infrav1.DependentMachineResources
- expect func(*mock.MockNetworkClientMockRecorder)
- want infrav1.DependentMachineResources
- wantErr bool
+ testName string
+ desiredPorts []infrav1.ResolvedPortSpec
+ resources infrav1.MachineResources
+ expect func(*mock.MockNetworkClientMockRecorder)
+ want infrav1.MachineResources
+ wantErr bool
}{
{
testName: "No desired ports",
@@ -901,14 +901,14 @@ func Test_AdoptPorts(t *testing.T) {
desiredPorts: []infrav1.ResolvedPortSpec{
{NetworkID: networkID1},
},
- dependentResources: infrav1.DependentMachineResources{
+ resources: infrav1.MachineResources{
Ports: []infrav1.PortStatus{
{
ID: portID1,
},
},
},
- want: infrav1.DependentMachineResources{
+ want: infrav1.MachineResources{
Ports: []infrav1.PortStatus{
{
ID: portID1,
@@ -925,7 +925,7 @@ func Test_AdoptPorts(t *testing.T) {
m.ListPort(ports.ListOpts{Name: "test-machine-0", NetworkID: networkID1}).
Return([]ports.Port{{ID: portID1}}, nil)
},
- want: infrav1.DependentMachineResources{
+ want: infrav1.MachineResources{
Ports: []infrav1.PortStatus{
{
ID: portID1,
@@ -942,7 +942,7 @@ func Test_AdoptPorts(t *testing.T) {
m.ListPort(ports.ListOpts{Name: "test-machine-0", NetworkID: networkID1}).
Return(nil, nil)
},
- want: infrav1.DependentMachineResources{},
+ want: infrav1.MachineResources{},
},
{
testName: "2 desired ports, first in status, second exists: adopt second",
@@ -950,7 +950,7 @@ func Test_AdoptPorts(t *testing.T) {
{Name: "test-machine-0", NetworkID: networkID1},
{Name: "test-machine-1", NetworkID: networkID2},
},
- dependentResources: infrav1.DependentMachineResources{
+ resources: infrav1.MachineResources{
Ports: []infrav1.PortStatus{
{
ID: portID1,
@@ -961,7 +961,7 @@ func Test_AdoptPorts(t *testing.T) {
m.ListPort(ports.ListOpts{Name: "test-machine-1", NetworkID: networkID2}).
Return([]ports.Port{{ID: portID2}}, nil)
},
- want: infrav1.DependentMachineResources{
+ want: infrav1.MachineResources{
Ports: []infrav1.PortStatus{
{ID: portID1},
{ID: portID2},
@@ -975,7 +975,7 @@ func Test_AdoptPorts(t *testing.T) {
{Name: "test-machine-1", NetworkID: networkID2},
{Name: "test-machine-2", NetworkID: networkID3},
},
- dependentResources: infrav1.DependentMachineResources{
+ resources: infrav1.MachineResources{
Ports: []infrav1.PortStatus{
{
ID: portID1,
@@ -986,7 +986,7 @@ func Test_AdoptPorts(t *testing.T) {
m.ListPort(ports.ListOpts{Name: "test-machine-1", NetworkID: networkID2}).
Return(nil, nil)
},
- want: infrav1.DependentMachineResources{
+ want: infrav1.MachineResources{
Ports: []infrav1.PortStatus{
{ID: portID1},
},
@@ -999,7 +999,7 @@ func Test_AdoptPorts(t *testing.T) {
{Name: "test-machine-bar", NetworkID: networkID2},
{Name: "test-machine-baz", NetworkID: networkID3},
},
- dependentResources: infrav1.DependentMachineResources{
+ resources: infrav1.MachineResources{
Ports: []infrav1.PortStatus{
{
ID: portID1,
@@ -1010,7 +1010,7 @@ func Test_AdoptPorts(t *testing.T) {
m.ListPort(ports.ListOpts{Name: "test-machine-bar", NetworkID: networkID2}).
Return(nil, nil)
},
- want: infrav1.DependentMachineResources{
+ want: infrav1.MachineResources{
Ports: []infrav1.PortStatus{
{ID: portID1},
},
@@ -1035,13 +1035,13 @@ func Test_AdoptPorts(t *testing.T) {
}
err := s.AdoptPorts(scope.NewWithLogger(mockScopeFactory, log),
- tt.desiredPorts, &tt.dependentResources)
+ tt.desiredPorts, &tt.resources)
if tt.wantErr {
g.Expect(err).Error()
return
}
- g.Expect(tt.dependentResources).To(Equal(tt.want), cmp.Diff(&tt.dependentResources, tt.want))
+ g.Expect(tt.resources).To(Equal(tt.want), cmp.Diff(&tt.resources, tt.want))
})
}
}
From 5d11950182257ee750db3c84534ba4621b100544 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Thu, 21 Mar 2024 13:02:10 +0000
Subject: [PATCH 146/180] Rename ReferencedResources to Resolved
This struct has already moved beyond external references, and seems be
evolving towards a fully-resolved machine spec. For want of a better
name we call it 'resolved', which is more accurate.
---
api/v1alpha5/conversion.go | 4 +-
api/v1alpha5/conversion_test.go | 2 +-
api/v1alpha5/zz_generated.conversion.go | 2 +-
api/v1alpha6/openstackcluster_conversion.go | 2 +-
api/v1alpha6/openstackmachine_conversion.go | 4 +-
api/v1alpha6/zz_generated.conversion.go | 2 +-
api/v1alpha7/openstackcluster_conversion.go | 2 +-
api/v1alpha7/openstackmachine_conversion.go | 4 +-
api/v1alpha7/zz_generated.conversion.go | 4 +-
api/v1beta1/openstackmachine_types.go | 5 +-
api/v1beta1/types.go | 20 ++---
api/v1beta1/zz_generated.deepcopy.go | 48 +++++------
...re.cluster.x-k8s.io_openstackclusters.yaml | 4 +-
...re.cluster.x-k8s.io_openstackmachines.yaml | 7 +-
controllers/openstackcluster_controller.go | 16 ++--
.../openstackcluster_controller_test.go | 14 ++--
controllers/openstackmachine_controller.go | 16 ++--
.../openstackmachine_controller_test.go | 2 +-
docs/book/src/api/v1beta1/api.md | 81 ++++++++++---------
.../services/compute/machine_resources.go | 2 +-
.../services/compute/referenced_resources.go | 28 +++----
.../compute/referenced_resources_test.go | 20 ++---
22 files changed, 146 insertions(+), 143 deletions(-)
diff --git a/api/v1alpha5/conversion.go b/api/v1alpha5/conversion.go
index d39cf87314..5c2516b891 100644
--- a/api/v1alpha5/conversion.go
+++ b/api/v1alpha5/conversion.go
@@ -455,7 +455,7 @@ func Convert_v1alpha5_Instance_To_v1beta1_BastionStatus(in *Instance, out *infra
out.State = infrav1.InstanceState(in.State)
out.IP = in.IP
out.FloatingIP = in.FloatingIP
- out.ReferencedResources.ServerGroupID = in.ServerGroupID
+ out.Resolved.ServerGroupID = in.ServerGroupID
return nil
}
@@ -467,7 +467,7 @@ func Convert_v1beta1_BastionStatus_To_v1alpha5_Instance(in *infrav1.BastionStatu
out.State = InstanceState(in.State)
out.IP = in.IP
out.FloatingIP = in.FloatingIP
- out.ServerGroupID = in.ReferencedResources.ServerGroupID
+ out.ServerGroupID = in.Resolved.ServerGroupID
return nil
}
diff --git a/api/v1alpha5/conversion_test.go b/api/v1alpha5/conversion_test.go
index b7dbbbac2b..82afcd82e8 100644
--- a/api/v1alpha5/conversion_test.go
+++ b/api/v1alpha5/conversion_test.go
@@ -87,7 +87,7 @@ func TestConvertFrom(t *testing.T) {
Spec: OpenStackMachineSpec{},
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
- "cluster.x-k8s.io/conversion-data": `{"spec":{"flavor":"","image":{}},"status":{"ready":false,"referencedResources":{},"resources":{}}}`,
+ "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"flavor\":\"\",\"image\":{}},\"status\":{\"ready\":false,\"resolved\":{},\"resources\":{}}}",
},
},
},
diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go
index c7cac5b353..f5d208397e 100644
--- a/api/v1alpha5/zz_generated.conversion.go
+++ b/api/v1alpha5/zz_generated.conversion.go
@@ -1212,7 +1212,7 @@ func autoConvert_v1beta1_OpenStackMachineStatus_To_v1alpha5_OpenStackMachineStat
out.Ready = in.Ready
out.Addresses = *(*[]corev1.NodeAddress)(unsafe.Pointer(&in.Addresses))
out.InstanceState = (*InstanceState)(unsafe.Pointer(in.InstanceState))
- // WARNING: in.ReferencedResources requires manual conversion: does not exist in peer-type
+ // 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))
diff --git a/api/v1alpha6/openstackcluster_conversion.go b/api/v1alpha6/openstackcluster_conversion.go
index 8d0a87efea..95131f6c3f 100644
--- a/api/v1alpha6/openstackcluster_conversion.go
+++ b/api/v1alpha6/openstackcluster_conversion.go
@@ -368,7 +368,7 @@ func restorev1beta1ClusterStatus(previous *infrav1.OpenStackClusterStatus, dst *
dst.BastionSecurityGroup = previous.BastionSecurityGroup
if previous.Bastion != nil {
- dst.Bastion.ReferencedResources = previous.Bastion.ReferencedResources
+ dst.Bastion.Resolved = previous.Bastion.Resolved
}
if previous.Bastion != nil && previous.Bastion.Resources.Ports != nil {
dst.Bastion.Resources.Ports = previous.Bastion.Resources.Ports
diff --git a/api/v1alpha6/openstackmachine_conversion.go b/api/v1alpha6/openstackmachine_conversion.go
index 7f92ec0b65..d0f01cac1b 100644
--- a/api/v1alpha6/openstackmachine_conversion.go
+++ b/api/v1alpha6/openstackmachine_conversion.go
@@ -96,8 +96,8 @@ var v1beta1OpenStackMachineRestorer = conversion.RestorerFor[*infrav1.OpenStackM
),
// No equivalent in v1alpha6
"refresources": conversion.UnconditionalFieldRestorer(
- func(c *infrav1.OpenStackMachine) *infrav1.ReferencedMachineResources {
- return &c.Status.ReferencedResources
+ func(c *infrav1.OpenStackMachine) *infrav1.ResolvedMachineSpec {
+ return &c.Status.Resolved
},
),
}
diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go
index e9bdedeb0f..b35e716ad4 100644
--- a/api/v1alpha6/zz_generated.conversion.go
+++ b/api/v1alpha6/zz_generated.conversion.go
@@ -1247,7 +1247,7 @@ func autoConvert_v1beta1_OpenStackMachineStatus_To_v1alpha6_OpenStackMachineStat
out.Ready = in.Ready
out.Addresses = *(*[]corev1.NodeAddress)(unsafe.Pointer(&in.Addresses))
out.InstanceState = (*InstanceState)(unsafe.Pointer(in.InstanceState))
- // WARNING: in.ReferencedResources requires manual conversion: does not exist in peer-type
+ // 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))
diff --git a/api/v1alpha7/openstackcluster_conversion.go b/api/v1alpha7/openstackcluster_conversion.go
index 641148b654..6cbd9a5118 100644
--- a/api/v1alpha7/openstackcluster_conversion.go
+++ b/api/v1alpha7/openstackcluster_conversion.go
@@ -350,7 +350,7 @@ func restorev1alpha7ClusterStatus(previous *OpenStackClusterStatus, dst *OpenSta
func restorev1beta1ClusterStatus(previous *infrav1.OpenStackClusterStatus, dst *infrav1.OpenStackClusterStatus) {
// ReferencedResources have no equivalent in v1alpha7
if previous.Bastion != nil {
- dst.Bastion.ReferencedResources = previous.Bastion.ReferencedResources
+ dst.Bastion.Resolved = previous.Bastion.Resolved
}
if previous.Bastion != nil && previous.Bastion.Resources.Ports != nil {
diff --git a/api/v1alpha7/openstackmachine_conversion.go b/api/v1alpha7/openstackmachine_conversion.go
index 9ee3b01c8c..08ef6f94ce 100644
--- a/api/v1alpha7/openstackmachine_conversion.go
+++ b/api/v1alpha7/openstackmachine_conversion.go
@@ -83,8 +83,8 @@ var v1beta1OpenStackMachineRestorer = conversion.RestorerFor[*infrav1.OpenStackM
),
// No equivalent in v1alpha7
"refresources": conversion.UnconditionalFieldRestorer(
- func(c *infrav1.OpenStackMachine) *infrav1.ReferencedMachineResources {
- return &c.Status.ReferencedResources
+ func(c *infrav1.OpenStackMachine) *infrav1.ResolvedMachineSpec {
+ return &c.Status.Resolved
},
),
}
diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go
index f7b10f6064..5646dbe6f8 100644
--- a/api/v1alpha7/zz_generated.conversion.go
+++ b/api/v1alpha7/zz_generated.conversion.go
@@ -573,7 +573,7 @@ func autoConvert_v1beta1_BastionStatus_To_v1alpha7_BastionStatus(in *v1beta1.Bas
out.State = InstanceState(in.State)
out.IP = in.IP
out.FloatingIP = in.FloatingIP
- // WARNING: in.ReferencedResources requires manual conversion: does not exist in peer-type
+ // 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
}
@@ -1447,7 +1447,7 @@ func autoConvert_v1beta1_OpenStackMachineStatus_To_v1alpha7_OpenStackMachineStat
out.Ready = in.Ready
out.Addresses = *(*[]corev1.NodeAddress)(unsafe.Pointer(&in.Addresses))
out.InstanceState = (*InstanceState)(unsafe.Pointer(in.InstanceState))
- // WARNING: in.ReferencedResources requires manual conversion: does not exist in peer-type
+ // 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))
diff --git a/api/v1beta1/openstackmachine_types.go b/api/v1beta1/openstackmachine_types.go
index 43d4f05574..95e5edfe88 100644
--- a/api/v1beta1/openstackmachine_types.go
+++ b/api/v1beta1/openstackmachine_types.go
@@ -126,8 +126,9 @@ type OpenStackMachineStatus struct {
// +optional
InstanceState *InstanceState `json:"instanceState,omitempty"`
- // ReferencedResources contains resolved references to resources that the machine depends on.
- ReferencedResources ReferencedMachineResources `json:"referencedResources,omitempty"`
+ // Resolved contains parts of the machine spec with all external
+ // references fully resolved.
+ Resolved ResolvedMachineSpec `json:"resolved,omitempty"`
// Resources contains references to OpenStack resources created for the machine.
Resources MachineResources `json:"resources,omitempty"`
diff --git a/api/v1beta1/types.go b/api/v1beta1/types.go
index 01316d955f..a8a9288393 100644
--- a/api/v1beta1/types.go
+++ b/api/v1beta1/types.go
@@ -358,14 +358,14 @@ type AddressPair struct {
}
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"`
- ReferencedResources ReferencedMachineResources `json:"referencedResources,omitempty"`
- Resources MachineResources `json:"resources,omitempty"`
+ 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 ResolvedMachineSpec `json:"resolved,omitempty"`
+ Resources MachineResources `json:"resources,omitempty"`
}
type RootVolume struct {
@@ -658,8 +658,8 @@ func (s *APIServerLoadBalancer) IsEnabled() bool {
return s != nil && (s.Enabled == nil || *s.Enabled)
}
-// ReferencedMachineResources contains resolved references to resources required by the machine.
-type ReferencedMachineResources struct {
+// 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"`
diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go
index d9e22e65c4..892e950daf 100644
--- a/api/v1beta1/zz_generated.deepcopy.go
+++ b/api/v1beta1/zz_generated.deepcopy.go
@@ -146,7 +146,7 @@ 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
- in.ReferencedResources.DeepCopyInto(&out.ReferencedResources)
+ in.Resolved.DeepCopyInto(&out.Resolved)
in.Resources.DeepCopyInto(&out.Resources)
}
@@ -964,7 +964,7 @@ func (in *OpenStackMachineStatus) DeepCopyInto(out *OpenStackMachineStatus) {
*out = new(InstanceState)
**out = **in
}
- in.ReferencedResources.DeepCopyInto(&out.ReferencedResources)
+ in.Resolved.DeepCopyInto(&out.Resolved)
in.Resources.DeepCopyInto(&out.Resources)
if in.FailureReason != nil {
in, out := &in.FailureReason, &out.FailureReason
@@ -1155,28 +1155,6 @@ func (in *PortStatus) DeepCopy() *PortStatus {
return out
}
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *ReferencedMachineResources) DeepCopyInto(out *ReferencedMachineResources) {
- *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 ReferencedMachineResources.
-func (in *ReferencedMachineResources) DeepCopy() *ReferencedMachineResources {
- if in == nil {
- return nil
- }
- out := new(ReferencedMachineResources)
- 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
@@ -1202,6 +1180,28 @@ func (in *ResolvedFixedIP) DeepCopy() *ResolvedFixedIP {
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
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 fda2df3277..abdbf1c5da 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -6250,8 +6250,8 @@ spec:
type: string
name:
type: string
- referencedResources:
- description: ReferencedMachineResources contains resolved references
+ resolved:
+ description: ResolvedMachineSpec contains resolved references
to resources required by the machine.
properties:
imageID:
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 8cea0408b3..3d866edc37 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
@@ -2453,9 +2453,10 @@ spec:
ready:
description: Ready is true when the provider resource is ready.
type: boolean
- referencedResources:
- description: ReferencedResources contains resolved references to resources
- that the machine depends on.
+ 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
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index dbc2527042..f1ab14b09c 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -227,20 +227,20 @@ func resolveBastionResources(scope *scope.WithLogger, clusterResourceName string
if openStackCluster.Spec.Bastion.Spec == nil {
return false, fmt.Errorf("bastion spec is nil when bastion is enabled, this shouldn't happen")
}
- changed, err := compute.ResolveReferencedMachineResources(scope,
- openStackCluster.Spec.Bastion.Spec, &openStackCluster.Status.Bastion.ReferencedResources,
+ changed, err := compute.ResolveMachineSpec(scope,
+ openStackCluster.Spec.Bastion.Spec, &openStackCluster.Status.Bastion.Resolved,
clusterResourceName, bastionName(clusterResourceName),
openStackCluster, getBastionSecurityGroupID(openStackCluster))
if err != nil {
return false, err
}
if changed {
- // If the referenced resources have changed, we need to update the OpenStackCluster status now.
+ // If the resolved machine spec changed we need to restart the reconcile to avoid inconsistencies between reconciles.
return true, nil
}
err = compute.AdoptMachineResources(scope,
- &openStackCluster.Status.Bastion.ReferencedResources,
+ &openStackCluster.Status.Bastion.Resolved,
&openStackCluster.Status.Bastion.Resources)
if err != nil {
return false, err
@@ -542,16 +542,16 @@ func bastionToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, cluster *
// v1beta1 API validations prevent this from happening in normal circumstances.
bastion.Spec = &infrav1.OpenStackMachineSpec{}
}
- referencedResources := &openStackCluster.Status.Bastion.ReferencedResources
+ resolved := &openStackCluster.Status.Bastion.Resolved
machineSpec := bastion.Spec
instanceSpec := &compute.InstanceSpec{
Name: bastionName(cluster.Name),
Flavor: machineSpec.Flavor,
SSHKeyName: machineSpec.SSHKeyName,
- ImageID: referencedResources.ImageID,
+ ImageID: resolved.ImageID,
RootVolume: machineSpec.RootVolume,
- ServerGroupID: referencedResources.ServerGroupID,
+ ServerGroupID: resolved.ServerGroupID,
Tags: compute.InstanceTags(machineSpec, openStackCluster),
}
if bastion.AvailabilityZone != nil {
@@ -578,7 +578,7 @@ func getBastionSecurityGroupID(openStackCluster *infrav1.OpenStackCluster) *stri
}
func getOrCreateBastionPorts(openStackCluster *infrav1.OpenStackCluster, networkingService *networking.Service) error {
- desiredPorts := openStackCluster.Status.Bastion.ReferencedResources.Ports
+ desiredPorts := openStackCluster.Status.Bastion.Resolved.Ports
resources := &openStackCluster.Status.Bastion.Resources
if len(desiredPorts) == len(resources.Ports) {
diff --git a/controllers/openstackcluster_controller_test.go b/controllers/openstackcluster_controller_test.go
index a7aa20892a..b738cafe47 100644
--- a/controllers/openstackcluster_controller_test.go
+++ b/controllers/openstackcluster_controller_test.go
@@ -237,7 +237,7 @@ var _ = Describe("OpenStackCluster controller", func() {
Expect(err).To(BeNil())
testCluster.Status = infrav1.OpenStackClusterStatus{
Bastion: &infrav1.BastionStatus{
- ReferencedResources: infrav1.ReferencedMachineResources{
+ Resolved: infrav1.ResolvedMachineSpec{
ImageID: "imageID",
Ports: []infrav1.ResolvedPortSpec{
{
@@ -286,7 +286,7 @@ var _ = Describe("OpenStackCluster controller", func() {
expectedStatus := &infrav1.BastionStatus{
ID: "adopted-bastion-uuid",
State: "ACTIVE",
- ReferencedResources: infrav1.ReferencedMachineResources{
+ Resolved: infrav1.ResolvedMachineSpec{
ImageID: "imageID",
Ports: []infrav1.ResolvedPortSpec{
{
@@ -327,7 +327,7 @@ var _ = Describe("OpenStackCluster controller", func() {
},
Bastion: &infrav1.BastionStatus{
ID: "adopted-fip-bastion-uuid",
- ReferencedResources: infrav1.ReferencedMachineResources{
+ Resolved: infrav1.ResolvedMachineSpec{
ImageID: "imageID",
Ports: []infrav1.ResolvedPortSpec{
{
@@ -369,7 +369,7 @@ var _ = Describe("OpenStackCluster controller", func() {
ID: "adopted-fip-bastion-uuid",
FloatingIP: "1.2.3.4",
State: "ACTIVE",
- ReferencedResources: infrav1.ReferencedMachineResources{
+ Resolved: infrav1.ResolvedMachineSpec{
ImageID: "imageID",
Ports: []infrav1.ResolvedPortSpec{
{
@@ -409,7 +409,7 @@ var _ = Describe("OpenStackCluster controller", func() {
},
Bastion: &infrav1.BastionStatus{
ID: "requeue-bastion-uuid",
- ReferencedResources: infrav1.ReferencedMachineResources{
+ Resolved: infrav1.ResolvedMachineSpec{
ImageID: "imageID",
Ports: []infrav1.ResolvedPortSpec{
{
@@ -445,7 +445,7 @@ var _ = Describe("OpenStackCluster controller", func() {
Expect(testCluster.Status.Bastion).To(Equal(&infrav1.BastionStatus{
ID: "requeue-bastion-uuid",
State: "BUILD",
- ReferencedResources: infrav1.ReferencedMachineResources{
+ Resolved: infrav1.ResolvedMachineSpec{
ImageID: "imageID",
Ports: []infrav1.ResolvedPortSpec{
{
@@ -475,7 +475,7 @@ var _ = Describe("OpenStackCluster controller", func() {
Expect(err).To(BeNil())
testCluster.Status = infrav1.OpenStackClusterStatus{
Bastion: &infrav1.BastionStatus{
- ReferencedResources: infrav1.ReferencedMachineResources{
+ Resolved: infrav1.ResolvedMachineSpec{
ImageID: "imageID",
},
},
diff --git a/controllers/openstackmachine_controller.go b/controllers/openstackmachine_controller.go
index a537d389f0..246cf2bfc3 100644
--- a/controllers/openstackmachine_controller.go
+++ b/controllers/openstackmachine_controller.go
@@ -162,21 +162,21 @@ func (r *OpenStackMachineReconciler) Reconcile(ctx context.Context, req ctrl.Req
}
func resolveMachineResources(scope *scope.WithLogger, clusterResourceName string, openStackCluster *infrav1.OpenStackCluster, openStackMachine *infrav1.OpenStackMachine, machine *clusterv1.Machine) (bool, error) {
- // Resolve and store referenced resources
- changed, err := compute.ResolveReferencedMachineResources(scope,
- &openStackMachine.Spec, &openStackMachine.Status.ReferencedResources,
+ // Resolve and store resources
+ changed, err := compute.ResolveMachineSpec(scope,
+ &openStackMachine.Spec, &openStackMachine.Status.Resolved,
clusterResourceName, openStackMachine.Name,
openStackCluster, getManagedSecurityGroup(openStackCluster, machine))
if err != nil {
return false, err
}
if changed {
- // If the referenced resources have changed, we need to update the OpenStackMachine status now.
+ // If the resolved machine spec changed we need to start the reconcile again to prevent inconsistency between reconciles.
return true, nil
}
// Adopt any existing resources
- return false, compute.AdoptMachineResources(scope, &openStackMachine.Status.ReferencedResources, &openStackMachine.Status.Resources)
+ return false, compute.AdoptMachineResources(scope, &openStackMachine.Status.Resolved, &openStackMachine.Status.Resources)
}
func patchMachine(ctx context.Context, patchHelper *patch.Helper, openStackMachine *infrav1.OpenStackMachine, machine *clusterv1.Machine, options ...patch.Option) error {
@@ -658,7 +658,7 @@ func (r *OpenStackMachineReconciler) reconcileAPIServerLoadBalancer(scope *scope
}
func getOrCreateMachinePorts(openStackMachine *infrav1.OpenStackMachine, networkingService *networking.Service) error {
- desiredPorts := openStackMachine.Status.ReferencedResources.Ports
+ desiredPorts := openStackMachine.Status.Resolved.Ports
resources := &openStackMachine.Status.Resources
if len(desiredPorts) == len(resources.Ports) {
@@ -717,7 +717,7 @@ func machineToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, machine *
instanceSpec := compute.InstanceSpec{
Name: openStackMachine.Name,
- ImageID: openStackMachine.Status.ReferencedResources.ImageID,
+ ImageID: openStackMachine.Status.Resolved.ImageID,
Flavor: openStackMachine.Spec.Flavor,
SSHKeyName: openStackMachine.Spec.SSHKeyName,
UserData: userData,
@@ -725,7 +725,7 @@ func machineToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, machine *
ConfigDrive: openStackMachine.Spec.ConfigDrive != nil && *openStackMachine.Spec.ConfigDrive,
RootVolume: openStackMachine.Spec.RootVolume,
AdditionalBlockDevices: openStackMachine.Spec.AdditionalBlockDevices,
- ServerGroupID: openStackMachine.Status.ReferencedResources.ServerGroupID,
+ ServerGroupID: openStackMachine.Status.Resolved.ServerGroupID,
Trunk: openStackMachine.Spec.Trunk,
}
diff --git a/controllers/openstackmachine_controller_test.go b/controllers/openstackmachine_controller_test.go
index 1351f3e2f6..bc2b4897f3 100644
--- a/controllers/openstackmachine_controller_test.go
+++ b/controllers/openstackmachine_controller_test.go
@@ -95,7 +95,7 @@ func getDefaultOpenStackMachine() *infrav1.OpenStackMachine {
ServerGroup: &infrav1.ServerGroupFilter{ID: serverGroupUUID},
},
Status: infrav1.OpenStackMachineStatus{
- ReferencedResources: infrav1.ReferencedMachineResources{
+ Resolved: infrav1.ResolvedMachineSpec{
ImageID: imageUUID,
ServerGroupID: serverGroupUUID,
},
diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md
index 8909adc3c7..fc84797f7a 100644
--- a/docs/book/src/api/v1beta1/api.md
+++ b/docs/book/src/api/v1beta1/api.md
@@ -1212,10 +1212,10 @@ string
-referencedResources
+resolved
-
-ReferencedMachineResources
+
+ResolvedMachineSpec
|
@@ -3286,15 +3286,16 @@ InstanceState
-referencedResources
+resolved
-
-ReferencedMachineResources
+
+ResolvedMachineSpec
|
- ReferencedResources contains resolved references to resources that the machine depends on.
+Resolved contains parts of the machine spec with all external
+references fully resolved.
|
@@ -3789,15 +3790,14 @@ string
-ReferencedMachineResources
+ResolvedFixedIP
(Appears on:
-BastionStatus,
-OpenStackMachineStatus)
+ResolvedPortSpec)
-
ReferencedMachineResources contains resolved references to resources required by the machine.
+ResolvedFixedIP is a FixedIP with the Subnet resolved to an ID.
@@ -3809,52 +3809,42 @@ string
-serverGroupID
+subnet
string
|
(Optional)
- ServerGroupID is the ID of the server group the machine should be added to and is calculated based on ServerGroupFilter.
+SubnetID is the id of a subnet to create the fixed IP of a port in.
|
-imageID
+ipAddress
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.
+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.
|
-ResolvedFixedIP
+ResolvedMachineSpec
(Appears on:
-ResolvedPortSpec)
+BastionStatus,
+OpenStackMachineStatus)
-
ResolvedFixedIP is a FixedIP with the Subnet resolved to an ID.
+ResolvedMachineSpec contains resolved references to resources required by the machine.
@@ -3866,29 +3856,40 @@ string
-subnet
+serverGroupID
string
|
(Optional)
- SubnetID is the id of a subnet to create the fixed IP of a port in.
+ServerGroupID is the ID of the server group the machine should be added to and is calculated based on ServerGroupFilter.
|
-ipAddress
+imageID
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.
+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.
|
@@ -3897,7 +3898,7 @@ address in any subnet of the port’s network.
(Appears on:
-ReferencedMachineResources)
+ResolvedMachineSpec)
ResolvedPortSpec is a PortOpts with all contained references fully resolved.
diff --git a/pkg/cloud/services/compute/machine_resources.go b/pkg/cloud/services/compute/machine_resources.go
index 7061fed468..ced3faff76 100644
--- a/pkg/cloud/services/compute/machine_resources.go
+++ b/pkg/cloud/services/compute/machine_resources.go
@@ -22,7 +22,7 @@ import (
"sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
)
-func AdoptMachineResources(scope *scope.WithLogger, referencedResources *infrav1.ReferencedMachineResources, resources *infrav1.MachineResources) error {
+func AdoptMachineResources(scope *scope.WithLogger, referencedResources *infrav1.ResolvedMachineSpec, resources *infrav1.MachineResources) error {
networkingService, err := networking.NewService(scope)
if err != nil {
return err
diff --git a/pkg/cloud/services/compute/referenced_resources.go b/pkg/cloud/services/compute/referenced_resources.go
index 72cd91047e..c571dfe365 100644
--- a/pkg/cloud/services/compute/referenced_resources.go
+++ b/pkg/cloud/services/compute/referenced_resources.go
@@ -25,13 +25,13 @@ import (
"sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
)
-// ResolveReferencedMachineResources is responsible for populating ReferencedMachineResources with IDs of
-// the resources referenced in the OpenStackMachineSpec by querying the OpenStack APIs. It'll return error
-// if resources cannot be found or their filters are ambiguous.
-// Note that we only set the fields in ReferencedMachineResources that are not set yet. This is ok because:
+// ResolveMachineSpec is responsible for populating a ResolvedMachineSpec from
+// an OpenStackMachineSpec and any external dependencies. The result contains no
+// external dependencies, and does not require any complex logic on creation.
+// Note that we only set the fields in ResolvedMachineSpec that are not set yet. This is ok because:
// - OpenStackMachine is immutable, so we can't change the spec after the machine is created.
// - the bastion is mutable, but we delete the bastion when the spec changes, so the bastion status will be empty.
-func ResolveReferencedMachineResources(scope *scope.WithLogger, spec *infrav1.OpenStackMachineSpec, resources *infrav1.ReferencedMachineResources, clusterResourceName, baseName string, openStackCluster *infrav1.OpenStackCluster, managedSecurityGroup *string) (changed bool, err error) {
+func ResolveMachineSpec(scope *scope.WithLogger, spec *infrav1.OpenStackMachineSpec, resolved *infrav1.ResolvedMachineSpec, clusterResourceName, baseName string, openStackCluster *infrav1.OpenStackCluster, managedSecurityGroup *string) (changed bool, err error) {
changed = false
computeService, err := NewService(scope)
@@ -44,23 +44,23 @@ func ResolveReferencedMachineResources(scope *scope.WithLogger, spec *infrav1.Op
return changed, err
}
- // ServerGroup is optional, so we only need to resolve it if it's set in the spec and not in ReferencedMachineResources yet.
- if spec.ServerGroup != nil && resources.ServerGroupID == "" {
+ // ServerGroup is optional, so we only need to resolve it if it's set in the spec
+ if spec.ServerGroup != nil && resolved.ServerGroupID == "" {
serverGroupID, err := computeService.GetServerGroupID(spec.ServerGroup)
if err != nil {
return changed, err
}
- resources.ServerGroupID = serverGroupID
+ resolved.ServerGroupID = serverGroupID
changed = true
}
- // Image is required, so we need to resolve it if it's not set in ReferencedMachineResources yet.
- if resources.ImageID == "" {
+ // Image is required, so we need to resolve it if it's not set
+ if resolved.ImageID == "" {
imageID, err := computeService.GetImageID(spec.Image)
if err != nil {
return changed, err
}
- resources.ImageID = imageID
+ resolved.ImageID = imageID
changed = true
}
@@ -68,17 +68,17 @@ func ResolveReferencedMachineResources(scope *scope.WithLogger, spec *infrav1.Op
// call this from places where we know it should have been set, but the
// cluster status is externally-provided data so we check it anyway.
if openStackCluster.Status.Network == nil {
- return changed, fmt.Errorf("called ResolveReferencedMachineResources with nil OpenStackCluster.Status.Network")
+ return changed, fmt.Errorf("called ResolveMachineSpec with nil OpenStackCluster.Status.Network")
}
// Network resources are required in order to get ports options.
- if len(resources.Ports) == 0 {
+ if len(resolved.Ports) == 0 {
defaultNetwork := openStackCluster.Status.Network
portsOpts, err := networkingService.ConstructPorts(spec, clusterResourceName, baseName, defaultNetwork, managedSecurityGroup, InstanceTags(spec, openStackCluster))
if err != nil {
return changed, err
}
- resources.Ports = portsOpts
+ resolved.Ports = portsOpts
changed = true
}
diff --git a/pkg/cloud/services/compute/referenced_resources_test.go b/pkg/cloud/services/compute/referenced_resources_test.go
index 47d2a6adb9..1f13ce5427 100644
--- a/pkg/cloud/services/compute/referenced_resources_test.go
+++ b/pkg/cloud/services/compute/referenced_resources_test.go
@@ -60,8 +60,8 @@ func Test_ResolveReferencedMachineResources(t *testing.T) {
expectComputeMock func(m *mock.MockComputeClientMockRecorder)
expectImageMock func(m *mock.MockImageClientMockRecorder)
expectNetworkMock func(m *mock.MockNetworkClientMockRecorder)
- before *infrav1.ReferencedMachineResources
- want *infrav1.ReferencedMachineResources
+ before *infrav1.ResolvedMachineSpec
+ want *infrav1.ResolvedMachineSpec
wantErr bool
}{
{
@@ -70,7 +70,7 @@ func Test_ResolveReferencedMachineResources(t *testing.T) {
ServerGroup: &infrav1.ServerGroupFilter{ID: serverGroupID1},
Image: infrav1.ImageFilter{ID: pointer.String(imageID1)},
},
- want: &infrav1.ReferencedMachineResources{
+ want: &infrav1.ResolvedMachineSpec{
ImageID: imageID1,
ServerGroupID: serverGroupID1,
Ports: defaultPorts,
@@ -81,7 +81,7 @@ func Test_ResolveReferencedMachineResources(t *testing.T) {
spec: infrav1.OpenStackMachineSpec{
Image: infrav1.ImageFilter{ID: pointer.String(imageID1)},
},
- want: &infrav1.ReferencedMachineResources{
+ want: &infrav1.ResolvedMachineSpec{
ImageID: imageID1,
Ports: defaultPorts,
},
@@ -92,7 +92,7 @@ func Test_ResolveReferencedMachineResources(t *testing.T) {
Image: infrav1.ImageFilter{ID: pointer.String(imageID1)},
ServerGroup: &infrav1.ServerGroupFilter{},
},
- want: &infrav1.ReferencedMachineResources{
+ want: &infrav1.ResolvedMachineSpec{
ImageID: imageID1,
Ports: defaultPorts,
},
@@ -108,7 +108,7 @@ func Test_ResolveReferencedMachineResources(t *testing.T) {
[]servergroups.ServerGroup{},
nil)
},
- want: &infrav1.ReferencedMachineResources{},
+ want: &infrav1.ResolvedMachineSpec{},
wantErr: true,
},
{
@@ -119,7 +119,7 @@ func Test_ResolveReferencedMachineResources(t *testing.T) {
expectImageMock: func(m *mock.MockImageClientMockRecorder) {
m.ListImages(images.ListOpts{Name: "test-image"}).Return([]images.Image{}, nil)
},
- want: &infrav1.ReferencedMachineResources{},
+ want: &infrav1.ResolvedMachineSpec{},
wantErr: true,
},
{
@@ -134,7 +134,7 @@ func Test_ResolveReferencedMachineResources(t *testing.T) {
},
},
},
- want: &infrav1.ReferencedMachineResources{
+ want: &infrav1.ResolvedMachineSpec{
ImageID: imageID1,
Ports: []infrav1.ResolvedPortSpec{
{
@@ -181,13 +181,13 @@ func Test_ResolveReferencedMachineResources(t *testing.T) {
resources := tt.before
if resources == nil {
- resources = &infrav1.ReferencedMachineResources{}
+ resources = &infrav1.ResolvedMachineSpec{}
}
clusterResourceName := "test-cluster"
baseName := "test-instance"
scope := scope.NewWithLogger(mockScopeFactory, log)
- _, err := ResolveReferencedMachineResources(scope, &tt.spec, resources, clusterResourceName, baseName, openStackCluster, tt.managedSecurityGroup)
+ _, err := ResolveMachineSpec(scope, &tt.spec, resources, clusterResourceName, baseName, openStackCluster, tt.managedSecurityGroup)
if tt.wantErr {
g.Expect(err).Error()
return
From 2758a6d27d46202ff8cff16374de8a2cc728993a Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Thu, 21 Mar 2024 16:04:59 +0000
Subject: [PATCH 147/180] Resolved and Resources become pointers in machine
status
---
api/v1alpha5/conversion_test.go | 2 +-
api/v1alpha6/openstackcluster_conversion.go | 76 ++++++++++---------
api/v1alpha6/openstackmachine_conversion.go | 4 +-
api/v1alpha7/openstackcluster_conversion.go | 21 +++--
api/v1alpha7/openstackmachine_conversion.go | 4 +-
api/v1beta1/openstackmachine_types.go | 6 +-
api/v1beta1/types.go | 23 ++++--
api/v1beta1/zz_generated.deepcopy.go | 24 +++++-
...re.cluster.x-k8s.io_openstackclusters.yaml | 7 +-
controllers/openstackcluster_controller.go | 36 ++++++---
.../openstackcluster_controller_test.go | 30 ++++----
controllers/openstackmachine_controller.go | 62 +++++++++++----
.../openstackmachine_controller_test.go | 4 +-
docs/book/src/api/v1beta1/api.md | 7 ++
.../services/compute/machine_resources.go | 4 +-
.../compute/referenced_resources_test.go | 2 +-
16 files changed, 207 insertions(+), 105 deletions(-)
diff --git a/api/v1alpha5/conversion_test.go b/api/v1alpha5/conversion_test.go
index 82afcd82e8..7fbf79bda6 100644
--- a/api/v1alpha5/conversion_test.go
+++ b/api/v1alpha5/conversion_test.go
@@ -87,7 +87,7 @@ func TestConvertFrom(t *testing.T) {
Spec: OpenStackMachineSpec{},
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
- "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"flavor\":\"\",\"image\":{}},\"status\":{\"ready\":false,\"resolved\":{},\"resources\":{}}}",
+ "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"flavor\":\"\",\"image\":{}},\"status\":{\"ready\":false}}",
},
},
},
diff --git a/api/v1alpha6/openstackcluster_conversion.go b/api/v1alpha6/openstackcluster_conversion.go
index 95131f6c3f..92fe7df622 100644
--- a/api/v1alpha6/openstackcluster_conversion.go
+++ b/api/v1alpha6/openstackcluster_conversion.go
@@ -367,12 +367,7 @@ func restorev1beta1ClusterStatus(previous *infrav1.OpenStackClusterStatus, dst *
dst.WorkerSecurityGroup = previous.WorkerSecurityGroup
dst.BastionSecurityGroup = previous.BastionSecurityGroup
- if previous.Bastion != nil {
- dst.Bastion.Resolved = previous.Bastion.Resolved
- }
- if previous.Bastion != nil && previous.Bastion.Resources.Ports != nil {
- dst.Bastion.Resources.Ports = previous.Bastion.Resources.Ports
- }
+ restorev1beta1BastionStatus(previous.Bastion, dst.Bastion)
}
func Convert_v1beta1_OpenStackClusterStatus_To_v1alpha6_OpenStackClusterStatus(in *infrav1.OpenStackClusterStatus, out *OpenStackClusterStatus, s apiconversion.Scope) error {
@@ -412,36 +407,15 @@ func Convert_v1alpha6_OpenStackClusterStatus_To_v1beta1_OpenStackClusterStatus(i
/* Bastion */
func restorev1beta1Bastion(previous **infrav1.Bastion, dst **infrav1.Bastion) {
- if *previous != nil {
- 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)
+ if previous == nil || dst == nil || *previous == nil || *dst == nil {
+ return
+ }
+ if *dst != nil && (*previous).Spec != nil && (*dst).Spec != nil {
+ restorev1beta1MachineSpec((*previous).Spec, (*dst).Spec)
}
-}
-
-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
+ optional.RestoreString(&(*previous).FloatingIP, &(*dst).FloatingIP)
+ optional.RestoreString(&(*previous).AvailabilityZone, &(*dst).AvailabilityZone)
}
func Convert_v1alpha6_Bastion_To_v1beta1_Bastion(in *Bastion, out *infrav1.Bastion, s apiconversion.Scope) error {
@@ -496,3 +470,37 @@ func Convert_v1beta1_Bastion_To_v1alpha6_Bastion(in *infrav1.Bastion, out *Basti
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/openstackmachine_conversion.go b/api/v1alpha6/openstackmachine_conversion.go
index d0f01cac1b..ad88c7afc0 100644
--- a/api/v1alpha6/openstackmachine_conversion.go
+++ b/api/v1alpha6/openstackmachine_conversion.go
@@ -90,13 +90,13 @@ var v1beta1OpenStackMachineRestorer = conversion.RestorerFor[*infrav1.OpenStackM
restorev1beta1MachineSpec,
),
"depresources": conversion.UnconditionalFieldRestorer(
- func(c *infrav1.OpenStackMachine) *infrav1.MachineResources {
+ func(c *infrav1.OpenStackMachine) **infrav1.MachineResources {
return &c.Status.Resources
},
),
// No equivalent in v1alpha6
"refresources": conversion.UnconditionalFieldRestorer(
- func(c *infrav1.OpenStackMachine) *infrav1.ResolvedMachineSpec {
+ func(c *infrav1.OpenStackMachine) **infrav1.ResolvedMachineSpec {
return &c.Status.Resolved
},
),
diff --git a/api/v1alpha7/openstackcluster_conversion.go b/api/v1alpha7/openstackcluster_conversion.go
index 6cbd9a5118..3defae462a 100644
--- a/api/v1alpha7/openstackcluster_conversion.go
+++ b/api/v1alpha7/openstackcluster_conversion.go
@@ -348,14 +348,11 @@ func restorev1alpha7ClusterStatus(previous *OpenStackClusterStatus, dst *OpenSta
}
func restorev1beta1ClusterStatus(previous *infrav1.OpenStackClusterStatus, dst *infrav1.OpenStackClusterStatus) {
- // ReferencedResources have no equivalent in v1alpha7
- if previous.Bastion != nil {
- dst.Bastion.Resolved = previous.Bastion.Resolved
+ if previous == nil || dst == nil {
+ return
}
- if previous.Bastion != nil && previous.Bastion.Resources.Ports != nil {
- dst.Bastion.Resources.Ports = previous.Bastion.Resources.Ports
- }
+ restorev1beta1BastionStatus(previous.Bastion, dst.Bastion)
}
func Convert_v1beta1_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(in *infrav1.OpenStackClusterStatus, out *OpenStackClusterStatus, s apiconversion.Scope) error {
@@ -434,6 +431,18 @@ func Convert_v1beta1_Bastion_To_v1alpha7_Bastion(in *infrav1.Bastion, out *Basti
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/openstackmachine_conversion.go b/api/v1alpha7/openstackmachine_conversion.go
index 08ef6f94ce..fa0655288c 100644
--- a/api/v1alpha7/openstackmachine_conversion.go
+++ b/api/v1alpha7/openstackmachine_conversion.go
@@ -77,13 +77,13 @@ var v1beta1OpenStackMachineRestorer = conversion.RestorerFor[*infrav1.OpenStackM
restorev1beta1MachineSpec,
),
"depresources": conversion.UnconditionalFieldRestorer(
- func(c *infrav1.OpenStackMachine) *infrav1.MachineResources {
+ func(c *infrav1.OpenStackMachine) **infrav1.MachineResources {
return &c.Status.Resources
},
),
// No equivalent in v1alpha7
"refresources": conversion.UnconditionalFieldRestorer(
- func(c *infrav1.OpenStackMachine) *infrav1.ResolvedMachineSpec {
+ func(c *infrav1.OpenStackMachine) **infrav1.ResolvedMachineSpec {
return &c.Status.Resolved
},
),
diff --git a/api/v1beta1/openstackmachine_types.go b/api/v1beta1/openstackmachine_types.go
index 95e5edfe88..f222f71761 100644
--- a/api/v1beta1/openstackmachine_types.go
+++ b/api/v1beta1/openstackmachine_types.go
@@ -128,10 +128,12 @@ type OpenStackMachineStatus struct {
// Resolved contains parts of the machine spec with all external
// references fully resolved.
- Resolved ResolvedMachineSpec `json:"resolved,omitempty"`
+ // +optional
+ Resolved *ResolvedMachineSpec `json:"resolved,omitempty"`
// Resources contains references to OpenStack resources created for the machine.
- Resources MachineResources `json:"resources,omitempty"`
+ // +optional
+ Resources *MachineResources `json:"resources,omitempty"`
FailureReason *errors.MachineStatusError `json:"failureReason,omitempty"`
diff --git a/api/v1beta1/types.go b/api/v1beta1/types.go
index a8a9288393..d2d90d8f6e 100644
--- a/api/v1beta1/types.go
+++ b/api/v1beta1/types.go
@@ -358,14 +358,21 @@ type AddressPair struct {
}
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 ResolvedMachineSpec `json:"resolved,omitempty"`
- Resources MachineResources `json:"resources,omitempty"`
+ 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 {
diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go
index 892e950daf..b5d80bafff 100644
--- a/api/v1beta1/zz_generated.deepcopy.go
+++ b/api/v1beta1/zz_generated.deepcopy.go
@@ -146,8 +146,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
- in.Resolved.DeepCopyInto(&out.Resolved)
- in.Resources.DeepCopyInto(&out.Resources)
+ 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.
@@ -964,8 +972,16 @@ func (in *OpenStackMachineStatus) DeepCopyInto(out *OpenStackMachineStatus) {
*out = new(InstanceState)
**out = **in
}
- in.Resolved.DeepCopyInto(&out.Resolved)
- in.Resources.DeepCopyInto(&out.Resources)
+ 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)
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 abdbf1c5da..4aa7ca14b0 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -6251,8 +6251,9 @@ spec:
name:
type: string
resolved:
- description: ResolvedMachineSpec contains resolved references
- to resources required by the machine.
+ 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
@@ -6435,6 +6436,8 @@ spec:
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
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index f1ab14b09c..1af03280f6 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -227,8 +227,13 @@ func resolveBastionResources(scope *scope.WithLogger, clusterResourceName string
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, &openStackCluster.Status.Bastion.Resolved,
+ openStackCluster.Spec.Bastion.Spec, resolved,
clusterResourceName, bastionName(clusterResourceName),
openStackCluster, getBastionSecurityGroupID(openStackCluster))
if err != nil {
@@ -238,10 +243,13 @@ func resolveBastionResources(scope *scope.WithLogger, clusterResourceName string
// 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,
- &openStackCluster.Status.Bastion.Resolved,
- &openStackCluster.Status.Bastion.Resources)
+ err = compute.AdoptMachineResources(scope, resolved, resources)
if err != nil {
return false, err
}
@@ -268,8 +276,10 @@ func deleteBastion(scope *scope.WithLogger, cluster *clusterv1.Cluster, openStac
}
}
+ bastionStatus := openStackCluster.Status.Bastion
+
var instanceStatus *compute.InstanceStatus
- if openStackCluster.Status.Bastion != nil && openStackCluster.Status.Bastion.ID != "" {
+ if bastionStatus != nil && bastionStatus.ID != "" {
instanceStatus, err = computeService.GetInstanceStatus(openStackCluster.Status.Bastion.ID)
if err != nil {
return err
@@ -308,18 +318,18 @@ func deleteBastion(scope *scope.WithLogger, cluster *clusterv1.Cluster, openStac
}
}
- if openStackCluster.Status.Bastion != nil && len(openStackCluster.Status.Bastion.Resources.Ports) > 0 {
+ if bastionStatus != nil && bastionStatus.Resources != nil {
trunkSupported, err := networkingService.IsTrunkExtSupported()
if err != nil {
return err
}
- for _, port := range openStackCluster.Status.Bastion.Resources.Ports {
+ 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)
}
}
- openStackCluster.Status.Bastion.Resources.Ports = nil
+ bastionStatus.Resources.Ports = nil
}
scope.Logger().Info("Deleted Bastion")
@@ -542,7 +552,10 @@ func bastionToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, cluster *
// v1beta1 API validations prevent this from happening in normal circumstances.
bastion.Spec = &infrav1.OpenStackMachineSpec{}
}
- resolved := &openStackCluster.Status.Bastion.Resolved
+ resolved := openStackCluster.Status.Bastion.Resolved
+ if resolved == nil {
+ return nil, errors.New("bastion resolved is nil")
+ }
machineSpec := bastion.Spec
instanceSpec := &compute.InstanceSpec{
@@ -579,7 +592,10 @@ func getBastionSecurityGroupID(openStackCluster *infrav1.OpenStackCluster) *stri
func getOrCreateBastionPorts(openStackCluster *infrav1.OpenStackCluster, networkingService *networking.Service) error {
desiredPorts := openStackCluster.Status.Bastion.Resolved.Ports
- resources := &openStackCluster.Status.Bastion.Resources
+ resources := openStackCluster.Status.Bastion.Resources
+ if resources == nil {
+ return errors.New("bastion resources are nil")
+ }
if len(desiredPorts) == len(resources.Ports) {
return nil
diff --git a/controllers/openstackcluster_controller_test.go b/controllers/openstackcluster_controller_test.go
index b738cafe47..29cfd40a21 100644
--- a/controllers/openstackcluster_controller_test.go
+++ b/controllers/openstackcluster_controller_test.go
@@ -237,7 +237,7 @@ var _ = Describe("OpenStackCluster controller", func() {
Expect(err).To(BeNil())
testCluster.Status = infrav1.OpenStackClusterStatus{
Bastion: &infrav1.BastionStatus{
- Resolved: infrav1.ResolvedMachineSpec{
+ Resolved: &infrav1.ResolvedMachineSpec{
ImageID: "imageID",
Ports: []infrav1.ResolvedPortSpec{
{
@@ -245,7 +245,7 @@ var _ = Describe("OpenStackCluster controller", func() {
},
},
},
- Resources: infrav1.MachineResources{
+ Resources: &infrav1.MachineResources{
Ports: []infrav1.PortStatus{
{
ID: "portID1",
@@ -286,7 +286,7 @@ var _ = Describe("OpenStackCluster controller", func() {
expectedStatus := &infrav1.BastionStatus{
ID: "adopted-bastion-uuid",
State: "ACTIVE",
- Resolved: infrav1.ResolvedMachineSpec{
+ Resolved: &infrav1.ResolvedMachineSpec{
ImageID: "imageID",
Ports: []infrav1.ResolvedPortSpec{
{
@@ -294,7 +294,7 @@ var _ = Describe("OpenStackCluster controller", func() {
},
},
},
- Resources: infrav1.MachineResources{
+ Resources: &infrav1.MachineResources{
Ports: []infrav1.PortStatus{
{
ID: "portID1",
@@ -327,7 +327,7 @@ var _ = Describe("OpenStackCluster controller", func() {
},
Bastion: &infrav1.BastionStatus{
ID: "adopted-fip-bastion-uuid",
- Resolved: infrav1.ResolvedMachineSpec{
+ Resolved: &infrav1.ResolvedMachineSpec{
ImageID: "imageID",
Ports: []infrav1.ResolvedPortSpec{
{
@@ -335,7 +335,7 @@ var _ = Describe("OpenStackCluster controller", func() {
},
},
},
- Resources: infrav1.MachineResources{
+ Resources: &infrav1.MachineResources{
Ports: []infrav1.PortStatus{
{
ID: "portID1",
@@ -369,7 +369,7 @@ var _ = Describe("OpenStackCluster controller", func() {
ID: "adopted-fip-bastion-uuid",
FloatingIP: "1.2.3.4",
State: "ACTIVE",
- Resolved: infrav1.ResolvedMachineSpec{
+ Resolved: &infrav1.ResolvedMachineSpec{
ImageID: "imageID",
Ports: []infrav1.ResolvedPortSpec{
{
@@ -377,7 +377,7 @@ var _ = Describe("OpenStackCluster controller", func() {
},
},
},
- Resources: infrav1.MachineResources{
+ Resources: &infrav1.MachineResources{
Ports: []infrav1.PortStatus{
{
ID: "portID1",
@@ -409,7 +409,7 @@ var _ = Describe("OpenStackCluster controller", func() {
},
Bastion: &infrav1.BastionStatus{
ID: "requeue-bastion-uuid",
- Resolved: infrav1.ResolvedMachineSpec{
+ Resolved: &infrav1.ResolvedMachineSpec{
ImageID: "imageID",
Ports: []infrav1.ResolvedPortSpec{
{
@@ -417,7 +417,7 @@ var _ = Describe("OpenStackCluster controller", func() {
},
},
},
- Resources: infrav1.MachineResources{
+ Resources: &infrav1.MachineResources{
Ports: []infrav1.PortStatus{
{
ID: "portID1",
@@ -445,7 +445,7 @@ var _ = Describe("OpenStackCluster controller", func() {
Expect(testCluster.Status.Bastion).To(Equal(&infrav1.BastionStatus{
ID: "requeue-bastion-uuid",
State: "BUILD",
- Resolved: infrav1.ResolvedMachineSpec{
+ Resolved: &infrav1.ResolvedMachineSpec{
ImageID: "imageID",
Ports: []infrav1.ResolvedPortSpec{
{
@@ -453,7 +453,7 @@ var _ = Describe("OpenStackCluster controller", func() {
},
},
},
- Resources: infrav1.MachineResources{
+ Resources: &infrav1.MachineResources{
Ports: []infrav1.PortStatus{
{
ID: "portID1",
@@ -475,7 +475,7 @@ var _ = Describe("OpenStackCluster controller", func() {
Expect(err).To(BeNil())
testCluster.Status = infrav1.OpenStackClusterStatus{
Bastion: &infrav1.BastionStatus{
- Resolved: infrav1.ResolvedMachineSpec{
+ Resolved: &infrav1.ResolvedMachineSpec{
ImageID: "imageID",
},
},
@@ -528,7 +528,7 @@ var _ = Describe("OpenStackCluster controller", func() {
}
testCluster.Status = infrav1.OpenStackClusterStatus{
Bastion: &infrav1.BastionStatus{
- Resources: infrav1.MachineResources{
+ Resources: &infrav1.MachineResources{
Ports: []infrav1.PortStatus{
{
ID: "port-id",
@@ -613,7 +613,7 @@ var _ = Describe("OpenStackCluster controller", func() {
}
testCluster.Status = infrav1.OpenStackClusterStatus{
Bastion: &infrav1.BastionStatus{
- Resources: infrav1.MachineResources{
+ Resources: &infrav1.MachineResources{
Ports: []infrav1.PortStatus{
{
ID: "port-id",
diff --git a/controllers/openstackmachine_controller.go b/controllers/openstackmachine_controller.go
index 246cf2bfc3..969ec5b61a 100644
--- a/controllers/openstackmachine_controller.go
+++ b/controllers/openstackmachine_controller.go
@@ -92,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)
@@ -162,9 +163,14 @@ func (r *OpenStackMachineReconciler) Reconcile(ctx context.Context, req ctrl.Req
}
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
changed, err := compute.ResolveMachineSpec(scope,
- &openStackMachine.Spec, &openStackMachine.Status.Resolved,
+ &openStackMachine.Spec, resolved,
clusterResourceName, openStackMachine.Name,
openStackCluster, getManagedSecurityGroup(openStackCluster, machine))
if err != nil {
@@ -175,8 +181,14 @@ func resolveMachineResources(scope *scope.WithLogger, clusterResourceName string
return true, nil
}
+ resources := openStackMachine.Status.Resources
+ if resources == nil {
+ resources = &infrav1.MachineResources{}
+ openStackMachine.Status.Resources = resources
+ }
+
// Adopt any existing resources
- return false, compute.AdoptMachineResources(scope, &openStackMachine.Status.Resolved, &openStackMachine.Status.Resources)
+ return false, compute.AdoptMachineResources(scope, resolved, resources)
}
func patchMachine(ctx context.Context, patchHelper *patch.Helper, openStackMachine *infrav1.OpenStackMachine, machine *clusterv1.Machine, options ...patch.Option) error {
@@ -296,7 +308,10 @@ func (r *OpenStackMachineReconciler) reconcileDelete(scope *scope.WithLogger, cl
}
}
- instanceSpec := machineToInstanceSpec(openStackCluster, machine, openStackMachine, "")
+ instanceSpec, err := machineToInstanceSpec(openStackCluster, machine, openStackMachine, "")
+ if err != nil {
+ return ctrl.Result{}, err
+ }
if err := computeService.DeleteInstance(openStackMachine, instanceStatus, instanceSpec); err != nil {
conditions.MarkFalse(openStackMachine, infrav1.InstanceReadyCondition, infrav1.InstanceDeleteFailedReason, clusterv1.ConditionSeverityError, "Deleting instance failed: %v", err)
@@ -308,10 +323,12 @@ func (r *OpenStackMachineReconciler) reconcileDelete(scope *scope.WithLogger, cl
return ctrl.Result{}, err
}
- 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)
+ 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)
+ }
}
}
@@ -485,6 +502,7 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope
}
if changed, err := resolveMachineResources(scope, clusterResourceName, openStackCluster, openStackMachine, machine); changed || err != nil {
+ scope.Logger().V(6).Info("Machine resources updated, requeuing")
return ctrl.Result{}, err
}
@@ -658,8 +676,15 @@ func (r *OpenStackMachineReconciler) reconcileAPIServerLoadBalancer(scope *scope
}
func getOrCreateMachinePorts(openStackMachine *infrav1.OpenStackMachine, networkingService *networking.Service) error {
- desiredPorts := openStackMachine.Status.Resolved.Ports
- resources := &openStackMachine.Status.Resources
+ 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
@@ -696,7 +721,11 @@ func (r *OpenStackMachineReconciler) getOrCreateInstance(logger logr.Logger, ope
return nil, nil
}
}
- instanceSpec := machineToInstanceSpec(openStackCluster, machine, openStackMachine, userData)
+ instanceSpec, err := machineToInstanceSpec(openStackCluster, machine, openStackMachine, userData)
+ if err != nil {
+ return nil, err
+ }
+
logger.Info("Machine does not exist, creating Machine", "name", openStackMachine.Name)
instanceStatus, err = computeService.CreateInstance(openStackMachine, instanceSpec, portIDs)
if err != nil {
@@ -707,7 +736,12 @@ func (r *OpenStackMachineReconciler) getOrCreateInstance(logger logr.Logger, ope
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
@@ -717,7 +751,7 @@ func machineToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, machine *
instanceSpec := compute.InstanceSpec{
Name: openStackMachine.Name,
- ImageID: openStackMachine.Status.Resolved.ImageID,
+ ImageID: resolved.ImageID,
Flavor: openStackMachine.Spec.Flavor,
SSHKeyName: openStackMachine.Spec.SSHKeyName,
UserData: userData,
@@ -725,7 +759,7 @@ func machineToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, machine *
ConfigDrive: openStackMachine.Spec.ConfigDrive != nil && *openStackMachine.Spec.ConfigDrive,
RootVolume: openStackMachine.Spec.RootVolume,
AdditionalBlockDevices: openStackMachine.Spec.AdditionalBlockDevices,
- ServerGroupID: openStackMachine.Status.Resolved.ServerGroupID,
+ ServerGroupID: resolved.ServerGroupID,
Trunk: openStackMachine.Spec.Trunk,
}
@@ -736,7 +770,7 @@ func machineToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, machine *
instanceSpec.Tags = compute.InstanceTags(&openStackMachine.Spec, openStackCluster)
- return &instanceSpec
+ return &instanceSpec, nil
}
// getManagedSecurityGroup returns the ID of the security group managed by the
diff --git a/controllers/openstackmachine_controller_test.go b/controllers/openstackmachine_controller_test.go
index bc2b4897f3..c941f11d04 100644
--- a/controllers/openstackmachine_controller_test.go
+++ b/controllers/openstackmachine_controller_test.go
@@ -95,7 +95,7 @@ func getDefaultOpenStackMachine() *infrav1.OpenStackMachine {
ServerGroup: &infrav1.ServerGroupFilter{ID: serverGroupUUID},
},
Status: infrav1.OpenStackMachineStatus{
- Resolved: infrav1.ResolvedMachineSpec{
+ Resolved: &infrav1.ResolvedMachineSpec{
ImageID: imageUUID,
ServerGroupID: serverGroupUUID,
},
@@ -160,7 +160,7 @@ func Test_machineToInstanceSpec(t *testing.T) {
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")
+ got, _ := machineToInstanceSpec(tt.openStackCluster(), tt.machine(), tt.openStackMachine(), "user-data")
wanted := tt.wantInstanceSpec()
g.Expect(got).To(Equal(wanted), cmp.Diff(got, wanted))
diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md
index fc84797f7a..c60863aaf2 100644
--- a/docs/book/src/api/v1beta1/api.md
+++ b/docs/book/src/api/v1beta1/api.md
@@ -1220,6 +1220,9 @@ ResolvedMachineSpec
+(Optional)
+ Resolved contains parts of the bastion’s machine spec with all
+external references fully resolved.
|
@@ -1232,6 +1235,8 @@ MachineResources
|
+(Optional)
+ Resources contains references to OpenStack resources created for the bastion.
|
@@ -3294,6 +3299,7 @@ ResolvedMachineSpec
+(Optional)
Resolved contains parts of the machine spec with all external
references fully resolved.
|
@@ -3308,6 +3314,7 @@ MachineResources
+(Optional)
Resources contains references to OpenStack resources created for the machine.
|
diff --git a/pkg/cloud/services/compute/machine_resources.go b/pkg/cloud/services/compute/machine_resources.go
index ced3faff76..6619d2ea72 100644
--- a/pkg/cloud/services/compute/machine_resources.go
+++ b/pkg/cloud/services/compute/machine_resources.go
@@ -22,11 +22,11 @@ import (
"sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
)
-func AdoptMachineResources(scope *scope.WithLogger, referencedResources *infrav1.ResolvedMachineSpec, resources *infrav1.MachineResources) error {
+func AdoptMachineResources(scope *scope.WithLogger, resolved *infrav1.ResolvedMachineSpec, resources *infrav1.MachineResources) error {
networkingService, err := networking.NewService(scope)
if err != nil {
return err
}
- return networkingService.AdoptPorts(scope, referencedResources.Ports, resources)
+ return networkingService.AdoptPorts(scope, resolved.Ports, resources)
}
diff --git a/pkg/cloud/services/compute/referenced_resources_test.go b/pkg/cloud/services/compute/referenced_resources_test.go
index 1f13ce5427..d2456918dc 100644
--- a/pkg/cloud/services/compute/referenced_resources_test.go
+++ b/pkg/cloud/services/compute/referenced_resources_test.go
@@ -33,7 +33,7 @@ import (
"sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
)
-func Test_ResolveReferencedMachineResources(t *testing.T) {
+func Test_ResolveMachineSpec(t *testing.T) {
const (
serverGroupID1 = "ce96e584-7ebc-46d6-9e55-987d72e3806c"
imageID1 = "de96e584-7ebc-46d6-9e55-987d72e3806c"
From 26e8c0746d931b11891ff31a477da38998102937 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Thu, 28 Mar 2024 11:23:05 +0000
Subject: [PATCH 148/180] Consolidate and fix v1beta1 fuzzer funcs
Firstly this change consolidates common fuzzer funcs for fuzzing v1beta1
between v1alpha6 and v1alpha7.
Secondly, we fix a couple of bugs where we were generating invalid
output:
In OpenStackClusterSpec we were creating a second subnet with
FuzzNoCustom, which doesn't use our custom functions for generating
valid output.
When generating filters we were appending a second tag after
validating tags, which meant we occasionally got invalid tags. We now
add tags before validation, and also add tags to all tag fields instead
of just 'Tags'. We also consolidate tag validation in a
FilterByNeutronTags func instead of individually for each Filter.
---
api/v1alpha6/conversion_test.go | 91 ++------------------------
api/v1alpha7/conversion_test.go | 111 ++------------------------------
test/helpers/fuzzerfuncs.go | 104 ++++++++++++++++++++++++++++++
3 files changed, 112 insertions(+), 194 deletions(-)
create mode 100644 test/helpers/fuzzerfuncs.go
diff --git a/api/v1alpha6/conversion_test.go b/api/v1alpha6/conversion_test.go
index 3e5484cafd..a5cacce26b 100644
--- a/api/v1alpha6/conversion_test.go
+++ b/api/v1alpha6/conversion_test.go
@@ -17,7 +17,7 @@ limitations under the License.
package v1alpha6
import (
- "strings"
+ "slices"
"testing"
"github.com/google/go-cmp/cmp"
@@ -57,19 +57,8 @@ func TestFuzzyConversion(t *testing.T) {
delete(obj.GetAnnotations(), utilconversion.DataAnnotation)
}
- filterInvalidTags := func(tags []infrav1.NeutronTag) []infrav1.NeutronTag {
- var ret []infrav1.NeutronTag
- for i := range tags {
- s := string(tags[i])
- if len(s) > 0 && !strings.Contains(s, ",") {
- ret = append(ret, tags[i])
- }
- }
- return ret
- }
-
fuzzerFuncs := func(_ runtimeserializer.CodecFactory) []interface{} {
- return []interface{}{
+ v1alpha6FuzzerFuncs := []interface{}{
func(instance *Instance, c fuzz.Continue) {
c.FuzzNoCustom(instance)
@@ -102,19 +91,6 @@ func TestFuzzyConversion(t *testing.T) {
}
},
- func(spec *infrav1.OpenStackClusterSpec, c fuzz.Continue) {
- c.FuzzNoCustom(spec)
-
- // The fuzzer only seems to generate Subnets of
- // length 1, but we need to also test length 2.
- // Ensure it is occasionally generated.
- if len(spec.Subnets) == 1 && c.RandBool() {
- subnet := infrav1.SubnetFilter{}
- c.FuzzNoCustom(&subnet)
- spec.Subnets = append(spec.Subnets, subnet)
- }
- },
-
func(spec *OpenStackMachineSpec, c fuzz.Continue) {
c.FuzzNoCustom(spec)
@@ -145,68 +121,9 @@ func TestFuzzyConversion(t *testing.T) {
}
}
},
-
- func(spec *infrav1.SubnetSpec, c fuzz.Continue) {
- c.FuzzNoCustom(spec)
-
- // CIDR is required and API validates that it's present, so
- // we force it to always be set.
- for spec.CIDR == "" {
- spec.CIDR = c.RandString()
- }
- },
-
- func(pool *infrav1.AllocationPool, c fuzz.Continue) {
- c.FuzzNoCustom(pool)
-
- // Start and End are required properties, let's make sure both are set
- for pool.Start == "" {
- pool.Start = c.RandString()
- }
-
- for pool.End == "" {
- pool.End = c.RandString()
- }
- },
-
- // v1beta1 filter tags cannot contain commas and can't be empty.
-
- func(filter *infrav1.SubnetFilter, c fuzz.Continue) {
- c.FuzzNoCustom(filter)
-
- filter.Tags = filterInvalidTags(filter.Tags)
- filter.TagsAny = filterInvalidTags(filter.TagsAny)
- filter.NotTags = filterInvalidTags(filter.NotTags)
- filter.NotTagsAny = filterInvalidTags(filter.NotTagsAny)
- },
-
- func(filter *infrav1.NetworkFilter, c fuzz.Continue) {
- c.FuzzNoCustom(filter)
-
- filter.Tags = filterInvalidTags(filter.Tags)
- filter.TagsAny = filterInvalidTags(filter.TagsAny)
- filter.NotTags = filterInvalidTags(filter.NotTags)
- filter.NotTagsAny = filterInvalidTags(filter.NotTagsAny)
- },
-
- func(filter *infrav1.RouterFilter, c fuzz.Continue) {
- c.FuzzNoCustom(filter)
-
- filter.Tags = filterInvalidTags(filter.Tags)
- filter.TagsAny = filterInvalidTags(filter.TagsAny)
- filter.NotTags = filterInvalidTags(filter.NotTags)
- filter.NotTagsAny = filterInvalidTags(filter.NotTagsAny)
- },
-
- func(filter *infrav1.SecurityGroupFilter, c fuzz.Continue) {
- c.FuzzNoCustom(filter)
-
- filter.Tags = filterInvalidTags(filter.Tags)
- filter.TagsAny = filterInvalidTags(filter.TagsAny)
- filter.NotTags = filterInvalidTags(filter.NotTags)
- filter.NotTagsAny = filterInvalidTags(filter.NotTagsAny)
- },
}
+
+ return slices.Concat(v1alpha6FuzzerFuncs, testhelpers.InfraV1FuzzerFuncs())
}
t.Run("for OpenStackCluster", runParallel(utilconversion.FuzzTestFunc(utilconversion.FuzzTestFuncInput{
diff --git a/api/v1alpha7/conversion_test.go b/api/v1alpha7/conversion_test.go
index a2c770984f..57364304b4 100644
--- a/api/v1alpha7/conversion_test.go
+++ b/api/v1alpha7/conversion_test.go
@@ -17,7 +17,7 @@ limitations under the License.
package v1alpha7
import (
- "strings"
+ "slices"
"testing"
"github.com/google/go-cmp/cmp"
@@ -57,32 +57,8 @@ func TestFuzzyConversion(t *testing.T) {
delete(obj.GetAnnotations(), utilconversion.DataAnnotation)
}
- filterInvalidTags := func(tags []infrav1.NeutronTag) []infrav1.NeutronTag {
- var ret []infrav1.NeutronTag
- for i := range tags {
- s := string(tags[i])
- if len(s) > 0 && !strings.Contains(s, ",") {
- ret = append(ret, tags[i])
- }
- }
- return ret
- }
-
fuzzerFuncs := func(_ runtimeserializer.CodecFactory) []interface{} {
- return []interface{}{
- func(spec *infrav1.OpenStackClusterSpec, c fuzz.Continue) {
- c.FuzzNoCustom(spec)
-
- // The fuzzer only seems to generate Subnets of
- // length 1, but we need to also test length 2.
- // Ensure it is occasionally generated.
- if len(spec.Subnets) == 1 && c.RandBool() {
- subnet := infrav1.SubnetFilter{}
- c.FuzzNoCustom(&subnet)
- spec.Subnets = append(spec.Subnets, subnet)
- }
- },
-
+ v1alpha7FuzzerFuncs := []interface{}{
func(spec *OpenStackMachineSpec, c fuzz.Continue) {
c.FuzzNoCustom(spec)
@@ -113,88 +89,9 @@ func TestFuzzyConversion(t *testing.T) {
}
}
},
-
- func(spec *infrav1.SubnetSpec, c fuzz.Continue) {
- c.FuzzNoCustom(spec)
-
- // CIDR is required and API validates that it's present, so
- // we force it to always be set.
- for spec.CIDR == "" {
- spec.CIDR = c.RandString()
- }
- },
-
- func(pool *infrav1.AllocationPool, c fuzz.Continue) {
- c.FuzzNoCustom(pool)
-
- // Start and End are required properties, let's make sure both are set
- for pool.Start == "" {
- pool.Start = c.RandString()
- }
-
- for pool.End == "" {
- pool.End = c.RandString()
- }
- },
-
- // v1beta1 filter tags cannot contain commas and can't be empty.
-
- func(filter *infrav1.SubnetFilter, c fuzz.Continue) {
- c.FuzzNoCustom(filter)
-
- // Sometimes add an additional tag to ensure we get test coverage of multiple tags
- if c.RandBool() {
- filter.Tags = append(filter.Tags, infrav1.NeutronTag(c.RandString()))
- }
-
- filter.Tags = filterInvalidTags(filter.Tags)
- filter.TagsAny = filterInvalidTags(filter.TagsAny)
- filter.NotTags = filterInvalidTags(filter.NotTags)
- filter.NotTagsAny = filterInvalidTags(filter.NotTagsAny)
- },
-
- func(filter *infrav1.NetworkFilter, c fuzz.Continue) {
- c.FuzzNoCustom(filter)
-
- // Sometimes add an additional tag to ensure we get test coverage of multiple tags
- if c.RandBool() {
- filter.Tags = append(filter.Tags, infrav1.NeutronTag(c.RandString()))
- }
-
- filter.Tags = filterInvalidTags(filter.Tags)
- filter.TagsAny = filterInvalidTags(filter.TagsAny)
- filter.NotTags = filterInvalidTags(filter.NotTags)
- filter.NotTagsAny = filterInvalidTags(filter.NotTagsAny)
- },
-
- func(filter *infrav1.RouterFilter, c fuzz.Continue) {
- c.FuzzNoCustom(filter)
-
- // Sometimes add an additional tag to ensure we get test coverage of multiple tags
- if c.RandBool() {
- filter.Tags = append(filter.Tags, infrav1.NeutronTag(c.RandString()))
- }
-
- filter.Tags = filterInvalidTags(filter.Tags)
- filter.TagsAny = filterInvalidTags(filter.TagsAny)
- filter.NotTags = filterInvalidTags(filter.NotTags)
- filter.NotTagsAny = filterInvalidTags(filter.NotTagsAny)
- },
-
- func(filter *infrav1.SecurityGroupFilter, c fuzz.Continue) {
- c.FuzzNoCustom(filter)
-
- // Sometimes add an additional tag to ensure we get test coverage of multiple tags
- if c.RandBool() {
- filter.Tags = append(filter.Tags, infrav1.NeutronTag(c.RandString()))
- }
-
- filter.Tags = filterInvalidTags(filter.Tags)
- filter.TagsAny = filterInvalidTags(filter.TagsAny)
- filter.NotTags = filterInvalidTags(filter.NotTags)
- filter.NotTagsAny = filterInvalidTags(filter.NotTagsAny)
- },
}
+
+ return slices.Concat(v1alpha7FuzzerFuncs, testhelpers.InfraV1FuzzerFuncs())
}
t.Run("for OpenStackCluster", runParallel(utilconversion.FuzzTestFunc(utilconversion.FuzzTestFuncInput{
diff --git a/test/helpers/fuzzerfuncs.go b/test/helpers/fuzzerfuncs.go
new file mode 100644
index 0000000000..6657ed3c73
--- /dev/null
+++ b/test/helpers/fuzzerfuncs.go
@@ -0,0 +1,104 @@
+/*
+Copyright 2024 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 helpers
+
+import (
+ "strings"
+
+ fuzz "github.com/google/gofuzz"
+
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
+)
+
+func filterInvalidTags(tags []infrav1.NeutronTag) []infrav1.NeutronTag {
+ var ret []infrav1.NeutronTag
+ for i := range tags {
+ s := string(tags[i])
+ if len(s) > 0 && !strings.Contains(s, ",") {
+ ret = append(ret, tags[i])
+ }
+ }
+ return ret
+}
+
+// InfraV1FuzzerFuncs returns fuzzer funcs for v1beta1 OpenStack types which:
+// * Constrain the output in ways which are validated by the API server
+// * Add additional test coverage where it is not generated by the default fuzzer.
+func InfraV1FuzzerFuncs() []interface{} {
+ return []interface{}{
+ func(spec *infrav1.OpenStackClusterSpec, c fuzz.Continue) {
+ c.FuzzNoCustom(spec)
+
+ // The fuzzer only seems to generate Subnets of
+ // length 1, but we need to also test length 2.
+ // Ensure it is occasionally generated.
+ if len(spec.Subnets) == 1 && c.RandBool() {
+ subnet := infrav1.SubnetFilter{}
+ c.Fuzz(&subnet)
+ spec.Subnets = append(spec.Subnets, subnet)
+ }
+ },
+
+ func(spec *infrav1.SubnetSpec, c fuzz.Continue) {
+ c.FuzzNoCustom(spec)
+
+ // CIDR is required and API validates that it's present, so
+ // we force it to always be set.
+ for spec.CIDR == "" {
+ spec.CIDR = c.RandString()
+ }
+ },
+
+ func(pool *infrav1.AllocationPool, c fuzz.Continue) {
+ c.FuzzNoCustom(pool)
+
+ // Start and End are required properties, let's make sure both are set
+ for pool.Start == "" {
+ pool.Start = c.RandString()
+ }
+
+ for pool.End == "" {
+ pool.End = c.RandString()
+ }
+ },
+
+ // v1beta1 filter tags cannot contain commas and can't be empty.
+ func(filter *infrav1.FilterByNeutronTags, c fuzz.Continue) {
+ c.FuzzNoCustom(filter)
+
+ // Sometimes add an additional tag to ensure we get test coverage of multiple tags
+ if c.RandBool() {
+ filter.Tags = append(filter.Tags, infrav1.NeutronTag(c.RandString()))
+ }
+ if c.RandBool() {
+ filter.TagsAny = append(filter.TagsAny, infrav1.NeutronTag(c.RandString()))
+ }
+ if c.RandBool() {
+ filter.NotTags = append(filter.NotTags, infrav1.NeutronTag(c.RandString()))
+ }
+ if c.RandBool() {
+ filter.NotTagsAny = append(filter.NotTagsAny, infrav1.NeutronTag(c.RandString()))
+ }
+
+ // Remove empty tags and tags with commas
+ filter.Tags = filterInvalidTags(filter.Tags)
+ filter.TagsAny = filterInvalidTags(filter.TagsAny)
+ filter.NotTags = filterInvalidTags(filter.NotTags)
+ filter.NotTagsAny = filterInvalidTags(filter.NotTagsAny)
+ },
+ }
+}
From 73c81decf84572a06669781688d6ffc77e794ef1 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Tue, 26 Mar 2024 11:59:09 +0000
Subject: [PATCH 149/180] NetworkFilter to NetworkParam
---
api/v1alpha1/openstackfloatingippool_types.go | 2 +-
api/v1alpha5/conversion.go | 54 ++-
api/v1alpha5/zz_generated.conversion.go | 47 ++-
api/v1alpha6/conversion_test.go | 40 +-
api/v1alpha6/openstackcluster_conversion.go | 31 +-
api/v1alpha6/openstackmachine_conversion.go | 10 +-
api/v1alpha6/types_conversion.go | 74 +++-
api/v1alpha6/zz_generated.conversion.go | 47 ++-
api/v1alpha7/openstackcluster_conversion.go | 35 +-
api/v1alpha7/types_conversion.go | 65 ++-
api/v1alpha7/zz_generated.conversion.go | 23 +-
api/v1beta1/openstackcluster_types.go | 4 +-
api/v1beta1/types.go | 31 +-
api/v1beta1/zz_generated.deepcopy.go | 31 +-
...re.cluster.x-k8s.io_openstackclusters.yaml | 388 +++++++++--------
...er.x-k8s.io_openstackclustertemplates.yaml | 391 ++++++++++--------
...ter.x-k8s.io_openstackfloatingippools.yaml | 129 +++---
...re.cluster.x-k8s.io_openstackmachines.yaml | 130 +++---
...er.x-k8s.io_openstackmachinetemplates.yaml | 130 +++---
controllers/openstackcluster_controller.go | 16 +-
.../openstackcluster_controller_test.go | 64 +--
.../openstackfloatingippool_controller.go | 18 +-
docs/book/src/api/v1beta1/api.md | 80 +++-
.../compute/referenced_resources_test.go | 4 +-
pkg/cloud/services/networking/network.go | 118 ++++--
pkg/cloud/services/networking/network_test.go | 173 ++++----
pkg/cloud/services/networking/port.go | 25 +-
pkg/cloud/services/networking/port_test.go | 10 +-
pkg/utils/filterconvert/convert.go | 1 -
.../externalNetworkByName/kustomization.yaml | 3 +-
.../e2e/suites/apivalidations/filters_test.go | 54 ++-
test/helpers/fuzzerfuncs.go | 33 ++
32 files changed, 1364 insertions(+), 897 deletions(-)
diff --git a/api/v1alpha1/openstackfloatingippool_types.go b/api/v1alpha1/openstackfloatingippool_types.go
index b3b0ebfc2a..931f2d503e 100644
--- a/api/v1alpha1/openstackfloatingippool_types.go
+++ b/api/v1alpha1/openstackfloatingippool_types.go
@@ -63,7 +63,7 @@ type OpenStackFloatingIPPoolSpec struct {
// 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.NetworkFilter `json:"floatingIPNetwork"`
+ FloatingIPNetwork infrav1.NetworkParam `json:"floatingIPNetwork"`
// The stratergy to use for reclaiming floating ips when they are released from a machine
// +kubebuilder:validation:Optional
diff --git a/api/v1alpha5/conversion.go b/api/v1alpha5/conversion.go
index 5c2516b891..b8190e088a 100644
--- a/api/v1alpha5/conversion.go
+++ b/api/v1alpha5/conversion.go
@@ -17,6 +17,7 @@ limitations under the License.
package v1alpha5
import (
+ "errors"
"strings"
conversion "k8s.io/apimachinery/pkg/conversion"
@@ -205,8 +206,8 @@ func Convert_v1beta1_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(in *i
return err
}
- if in.ExternalNetwork != nil && in.ExternalNetwork.ID != "" {
- out.ExternalNetworkID = in.ExternalNetwork.ID
+ if in.ExternalNetwork != nil && in.ExternalNetwork.ID != nil {
+ out.ExternalNetworkID = *in.ExternalNetwork.ID
}
if len(in.ManagedSubnets) > 0 {
@@ -246,8 +247,8 @@ func Convert_v1alpha5_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *O
}
if in.ExternalNetworkID != "" {
- out.ExternalNetwork = &infrav1.NetworkFilter{
- ID: in.ExternalNetworkID,
+ out.ExternalNetwork = &infrav1.NetworkParam{
+ ID: &in.ExternalNetworkID,
}
}
@@ -746,18 +747,49 @@ func Convert_v1beta1_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(in *inf
return nil
}
-func Convert_v1alpha5_NetworkFilter_To_v1beta1_NetworkFilter(in *NetworkFilter, out *infrav1.NetworkFilter, s conversion.Scope) error {
- if err := autoConvert_v1alpha5_NetworkFilter_To_v1beta1_NetworkFilter(in, out, s); err != 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, &out.FilterByNeutronTags)
+ infrav1.ConvertAllTagsTo(in.Tags, in.TagsAny, in.NotTags, in.NotTagsAny, &outFilter.FilterByNeutronTags)
+ if !outFilter.IsZero() {
+ out.Filter = outFilter
+ }
return nil
}
-func Convert_v1beta1_NetworkFilter_To_v1alpha5_NetworkFilter(in *infrav1.NetworkFilter, out *NetworkFilter, s conversion.Scope) error {
- if err := autoConvert_v1beta1_NetworkFilter_To_v1alpha5_NetworkFilter(in, out, s); err != nil {
- return err
+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)
}
- infrav1.ConvertAllTagsFrom(&in.FilterByNeutronTags, &out.Tags, &out.TagsAny, &out.NotTags, &out.NotTagsAny)
return nil
}
+
+// 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/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go
index f5d208397e..e8376912a3 100644
--- a/api/v1alpha5/zz_generated.conversion.go
+++ b/api/v1alpha5/zz_generated.conversion.go
@@ -252,6 +252,16 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
+ 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.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.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 {
@@ -337,6 +347,16 @@ func RegisterConversions(s *runtime.Scheme) error {
}); 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_v1alpha5_NetworkFilter(a.(*v1beta1.NetworkParam), b.(*NetworkFilter), scope)
+ }); err != nil {
+ return err
+ }
+ 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((*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 {
@@ -570,7 +590,7 @@ func autoConvert_v1alpha5_NetworkFilter_To_v1beta1_NetworkFilter(in *NetworkFilt
out.Name = in.Name
out.Description = in.Description
out.ProjectID = in.ProjectID
- out.ID = in.ID
+ // 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
@@ -582,11 +602,24 @@ func autoConvert_v1beta1_NetworkFilter_To_v1alpha5_NetworkFilter(in *v1beta1.Net
out.Name = in.Name
out.Description = in.Description
out.ProjectID = in.ProjectID
- out.ID = in.ID
// 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
+}
+
+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_v1beta1_OpenStackCluster(in *OpenStackCluster, out *v1beta1.OpenStackCluster, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
if err := Convert_v1alpha5_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(&in.Spec, &out.Spec, s); err != nil {
@@ -664,7 +697,7 @@ func Convert_v1beta1_OpenStackClusterList_To_v1alpha5_OpenStackClusterList(in *v
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.NetworkFilter)
+ // 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 {
@@ -716,7 +749,7 @@ func autoConvert_v1alpha5_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(i
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
- // WARNING: in.Network 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)
+ // 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
if in.ExternalRouterIPs != nil {
@@ -1339,8 +1372,8 @@ func Convert_v1beta1_OpenStackMachineTemplateSpec_To_v1alpha5_OpenStackMachineTe
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.NetworkFilter)
- if err := Convert_v1alpha5_NetworkFilter_To_v1beta1_NetworkFilter(*in, *out, s); err != nil {
+ *out = new(v1beta1.NetworkParam)
+ if err := Convert_v1alpha5_NetworkFilter_To_v1beta1_NetworkParam(*in, *out, s); err != nil {
return err
}
} else {
@@ -1383,7 +1416,7 @@ func autoConvert_v1beta1_PortOpts_To_v1alpha5_PortOpts(in *v1beta1.PortOpts, out
if in.Network != nil {
in, out := &in.Network, &out.Network
*out = new(NetworkFilter)
- if err := Convert_v1beta1_NetworkFilter_To_v1alpha5_NetworkFilter(*in, *out, s); err != nil {
+ if err := Convert_v1beta1_NetworkParam_To_v1alpha5_NetworkFilter(*in, *out, s); err != nil {
return err
}
} else {
diff --git a/api/v1alpha6/conversion_test.go b/api/v1alpha6/conversion_test.go
index a5cacce26b..0c1352767d 100644
--- a/api/v1alpha6/conversion_test.go
+++ b/api/v1alpha6/conversion_test.go
@@ -220,8 +220,8 @@ func TestNetworksToPorts(t *testing.T) {
afterMachineSpec: infrav1.OpenStackMachineSpec{
Ports: []infrav1.PortOpts{
{
- Network: &infrav1.NetworkFilter{
- ID: networkuuid,
+ Network: &infrav1.NetworkParam{
+ ID: pointer.String(networkuuid),
},
},
},
@@ -247,15 +247,17 @@ func TestNetworksToPorts(t *testing.T) {
afterMachineSpec: infrav1.OpenStackMachineSpec{
Ports: []infrav1.PortOpts{
{
- Network: &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"},
+ 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"},
+ },
},
},
},
@@ -279,8 +281,8 @@ func TestNetworksToPorts(t *testing.T) {
afterMachineSpec: infrav1.OpenStackMachineSpec{
Ports: []infrav1.PortOpts{
{
- Network: &infrav1.NetworkFilter{
- ID: networkuuid,
+ Network: &infrav1.NetworkParam{
+ ID: pointer.String(networkuuid),
},
FixedIPs: []infrav1.FixedIP{
{
@@ -323,8 +325,8 @@ func TestNetworksToPorts(t *testing.T) {
afterMachineSpec: infrav1.OpenStackMachineSpec{
Ports: []infrav1.PortOpts{
{
- Network: &infrav1.NetworkFilter{
- ID: networkuuid,
+ Network: &infrav1.NetworkParam{
+ ID: pointer.String(networkuuid),
},
FixedIPs: []infrav1.FixedIP{
{
@@ -383,8 +385,8 @@ func TestNetworksToPorts(t *testing.T) {
afterMachineSpec: infrav1.OpenStackMachineSpec{
Ports: []infrav1.PortOpts{
{
- Network: &infrav1.NetworkFilter{
- ID: networkuuid,
+ Network: &infrav1.NetworkParam{
+ ID: pointer.String(networkuuid),
},
FixedIPs: []infrav1.FixedIP{
{
@@ -395,8 +397,8 @@ func TestNetworksToPorts(t *testing.T) {
},
},
{
- Network: &infrav1.NetworkFilter{
- ID: networkuuid,
+ Network: &infrav1.NetworkParam{
+ ID: pointer.String(networkuuid),
},
FixedIPs: []infrav1.FixedIP{
{
diff --git a/api/v1alpha6/openstackcluster_conversion.go b/api/v1alpha6/openstackcluster_conversion.go
index 92fe7df622..68242edd8c 100644
--- a/api/v1alpha6/openstackcluster_conversion.go
+++ b/api/v1alpha6/openstackcluster_conversion.go
@@ -164,23 +164,14 @@ func restorev1alpha6ClusterSpec(previous *OpenStackClusterSpec, dst *OpenStackCl
func restorev1beta1ClusterSpec(previous *infrav1.OpenStackClusterSpec, dst *infrav1.OpenStackClusterSpec) {
// Bastion is restored separately
- if dst.Network.IsEmpty() {
- dst.Network = previous.Network
- }
+ restorev1beta1NetworkParam(previous.Network, dst.Network)
- // Restore all fields except ID, which should have been copied over in conversion
+ // ExternalNetwork by filter will be been lost in down-conversion
if previous.ExternalNetwork != nil {
if dst.ExternalNetwork == nil {
- dst.ExternalNetwork = &infrav1.NetworkFilter{}
+ dst.ExternalNetwork = &infrav1.NetworkParam{}
}
-
- dst.ExternalNetwork.Name = previous.ExternalNetwork.Name
- dst.ExternalNetwork.Description = previous.ExternalNetwork.Description
- dst.ExternalNetwork.ProjectID = previous.ExternalNetwork.ProjectID
- dst.ExternalNetwork.Tags = previous.ExternalNetwork.Tags
- dst.ExternalNetwork.TagsAny = previous.ExternalNetwork.TagsAny
- dst.ExternalNetwork.NotTags = previous.ExternalNetwork.NotTags
- dst.ExternalNetwork.NotTagsAny = previous.ExternalNetwork.NotTagsAny
+ dst.ExternalNetwork.Filter = previous.ExternalNetwork.Filter
}
// Restore fields not present in v1alpha6
@@ -227,15 +218,15 @@ func Convert_v1alpha6_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *O
}
if in.Network != (NetworkFilter{}) {
- out.Network = &infrav1.NetworkFilter{}
- if err := Convert_v1alpha6_NetworkFilter_To_v1beta1_NetworkFilter(&in.Network, out.Network, s); err != nil {
+ 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.NetworkFilter{
- ID: in.ExternalNetworkID,
+ out.ExternalNetwork = &infrav1.NetworkParam{
+ ID: &in.ExternalNetworkID,
}
}
@@ -294,13 +285,13 @@ func Convert_v1beta1_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(in *i
}
if in.Network != nil {
- if err := Convert_v1beta1_NetworkFilter_To_v1alpha6_NetworkFilter(in.Network, &out.Network, s); err != 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 != "" {
- out.ExternalNetworkID = in.ExternalNetwork.ID
+ if in.ExternalNetwork != nil && in.ExternalNetwork.ID != nil {
+ out.ExternalNetworkID = *in.ExternalNetwork.ID
}
if len(in.Subnets) >= 1 {
diff --git a/api/v1alpha6/openstackmachine_conversion.go b/api/v1alpha6/openstackmachine_conversion.go
index ad88c7afc0..9ab01741ea 100644
--- a/api/v1alpha6/openstackmachine_conversion.go
+++ b/api/v1alpha6/openstackmachine_conversion.go
@@ -179,7 +179,7 @@ func convertNetworksToPorts(networks []NetworkParam, s apiconversion.Scope) ([]i
network := networks[i]
// This will remain null if the network is not specified in NetworkParam
- var networkFilter *infrav1.NetworkFilter
+ var networkFilter *infrav1.NetworkParam
// In v1alpha6, if network.Filter resolved to multiple networks
// then we would add multiple ports. It is not possible to
@@ -189,12 +189,12 @@ func convertNetworksToPorts(networks []NetworkParam, s apiconversion.Scope) ([]i
// create the port.
switch {
case network.UUID != "":
- networkFilter = &infrav1.NetworkFilter{
- ID: network.UUID,
+ networkFilter = &infrav1.NetworkParam{
+ ID: &network.UUID,
}
case network.Filter != (NetworkFilter{}):
- networkFilter = &infrav1.NetworkFilter{}
- if err := Convert_v1alpha6_NetworkFilter_To_v1beta1_NetworkFilter(&network.Filter, networkFilter, s); err != nil {
+ networkFilter = &infrav1.NetworkParam{}
+ if err := Convert_v1alpha6_NetworkFilter_To_v1beta1_NetworkParam(&network.Filter, networkFilter, s); err != nil {
return nil, err
}
}
diff --git a/api/v1alpha6/types_conversion.go b/api/v1alpha6/types_conversion.go
index 6ec354ecee..80cefb86fc 100644
--- a/api/v1alpha6/types_conversion.go
+++ b/api/v1alpha6/types_conversion.go
@@ -17,6 +17,7 @@ limitations under the License.
package v1alpha6
import (
+ "errors"
"strings"
apiconversion "k8s.io/apimachinery/pkg/conversion"
@@ -102,27 +103,61 @@ func Convert_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(in *inf
/* 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_NetworkFilter(in *NetworkFilter, out *infrav1.NetworkFilter, s apiconversion.Scope) error {
- if err := autoConvert_v1alpha6_NetworkFilter_To_v1beta1_NetworkFilter(in, out, s); err != nil {
+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, &out.FilterByNeutronTags)
+ infrav1.ConvertAllTagsTo(in.Tags, in.TagsAny, in.NotTags, in.NotTagsAny, &outFilter.FilterByNeutronTags)
+ if !outFilter.IsZero() {
+ out.Filter = outFilter
+ }
return nil
}
-func Convert_v1beta1_NetworkFilter_To_v1alpha6_NetworkFilter(in *infrav1.NetworkFilter, out *NetworkFilter, s apiconversion.Scope) error {
- if err := autoConvert_v1beta1_NetworkFilter_To_v1alpha6_NetworkFilter(in, out, s); err != nil {
- return err
+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)
}
- infrav1.ConvertAllTagsFrom(&in.FilterByNeutronTags, &out.Tags, &out.TagsAny, &out.NotTags, &out.NotTagsAny)
return nil
}
@@ -181,9 +216,7 @@ func restorev1alpha6Port(previous *PortOpts, dst *PortOpts) {
}
}
- if dst.Network != nil && previous.Network != nil {
- restorev1alpha6NetworkFilter(previous.Network, dst.Network)
- }
+ restorev1alpha6NetworkFilter(previous.Network, dst.Network)
if len(dst.FixedIPs) == len(previous.FixedIPs) {
for i := range dst.FixedIPs {
@@ -392,3 +425,24 @@ func Convert_v1beta1_OpenStackIdentityReference_To_v1alpha6_OpenStackIdentityRef
out.Name = in.Name
return nil
}
+
+/* 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 b35e716ad4..34023deb82 100644
--- a/api/v1alpha6/zz_generated.conversion.go
+++ b/api/v1alpha6/zz_generated.conversion.go
@@ -271,6 +271,16 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
+ 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.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.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 {
@@ -346,6 +356,16 @@ func RegisterConversions(s *runtime.Scheme) error {
}); 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_v1alpha6_NetworkFilter(a.(*v1beta1.NetworkParam), b.(*NetworkFilter), scope)
+ }); err != nil {
+ return err
+ }
+ 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((*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 {
@@ -600,7 +620,7 @@ func autoConvert_v1alpha6_NetworkFilter_To_v1beta1_NetworkFilter(in *NetworkFilt
out.Name = in.Name
out.Description = in.Description
out.ProjectID = in.ProjectID
- out.ID = in.ID
+ // 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
@@ -612,11 +632,24 @@ func autoConvert_v1beta1_NetworkFilter_To_v1alpha6_NetworkFilter(in *v1beta1.Net
out.Name = in.Name
out.Description = in.Description
out.ProjectID = in.ProjectID
- out.ID = in.ID
// WARNING: in.FilterByNeutronTags requires manual conversion: does not exist in peer-type
return nil
}
+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_v1beta1_OpenStackCluster(in *OpenStackCluster, out *v1beta1.OpenStackCluster, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
if err := Convert_v1alpha6_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(&in.Spec, &out.Spec, s); err != nil {
@@ -694,7 +727,7 @@ func Convert_v1beta1_OpenStackClusterList_To_v1alpha6_OpenStackClusterList(in *v
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.NetworkFilter)
+ // 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 {
@@ -749,7 +782,7 @@ func autoConvert_v1alpha6_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(i
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
- // WARNING: in.Network 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)
+ // 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
if in.ExternalRouterIPs != nil {
@@ -1374,8 +1407,8 @@ func Convert_v1beta1_OpenStackMachineTemplateSpec_To_v1alpha6_OpenStackMachineTe
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.NetworkFilter)
- if err := Convert_v1alpha6_NetworkFilter_To_v1beta1_NetworkFilter(*in, *out, s); err != nil {
+ *out = new(v1beta1.NetworkParam)
+ if err := Convert_v1alpha6_NetworkFilter_To_v1beta1_NetworkParam(*in, *out, s); err != nil {
return err
}
} else {
@@ -1419,7 +1452,7 @@ func autoConvert_v1beta1_PortOpts_To_v1alpha6_PortOpts(in *v1beta1.PortOpts, out
if in.Network != nil {
in, out := &in.Network, &out.Network
*out = new(NetworkFilter)
- if err := Convert_v1beta1_NetworkFilter_To_v1alpha6_NetworkFilter(*in, *out, s); err != nil {
+ if err := Convert_v1beta1_NetworkParam_To_v1alpha6_NetworkFilter(*in, *out, s); err != nil {
return err
}
} else {
diff --git a/api/v1alpha7/openstackcluster_conversion.go b/api/v1alpha7/openstackcluster_conversion.go
index 3defae462a..7ff49ecdcf 100644
--- a/api/v1alpha7/openstackcluster_conversion.go
+++ b/api/v1alpha7/openstackcluster_conversion.go
@@ -169,29 +169,28 @@ func restorev1alpha7ClusterSpec(previous *OpenStackClusterSpec, dst *OpenStackCl
}
func restorev1beta1ClusterSpec(previous *infrav1.OpenStackClusterSpec, dst *infrav1.OpenStackClusterSpec) {
+ if previous == nil || dst == nil {
+ return
+ }
+
// Bastion is restored separately
- if dst.Network.IsEmpty() {
+ if dst.Network == nil {
dst.Network = previous.Network
}
- // Restore all fields except ID, which should have been copied over in conversion
+ // ExternalNetwork by filter will be been lost in down-conversion
if previous.ExternalNetwork != nil {
if dst.ExternalNetwork == nil {
- dst.ExternalNetwork = &infrav1.NetworkFilter{}
+ dst.ExternalNetwork = &infrav1.NetworkParam{}
}
-
- dst.ExternalNetwork.Name = previous.ExternalNetwork.Name
- dst.ExternalNetwork.Description = previous.ExternalNetwork.Description
- dst.ExternalNetwork.ProjectID = previous.ExternalNetwork.ProjectID
- dst.ExternalNetwork.Tags = previous.ExternalNetwork.Tags
- dst.ExternalNetwork.TagsAny = previous.ExternalNetwork.TagsAny
- dst.ExternalNetwork.NotTags = previous.ExternalNetwork.NotTags
- dst.ExternalNetwork.NotTagsAny = previous.ExternalNetwork.NotTagsAny
+ dst.ExternalNetwork.Filter = previous.ExternalNetwork.Filter
}
dst.DisableExternalNetwork = previous.DisableExternalNetwork
+ restorev1beta1NetworkParam(previous.Network, dst.Network)
+
if len(previous.Subnets) > 1 {
dst.Subnets = append(dst.Subnets, previous.Subnets[1:]...)
}
@@ -231,15 +230,15 @@ func Convert_v1alpha7_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *O
}
if in.Network != (NetworkFilter{}) {
- out.Network = &infrav1.NetworkFilter{}
- if err := Convert_v1alpha7_NetworkFilter_To_v1beta1_NetworkFilter(&in.Network, out.Network, s); err != nil {
+ 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.NetworkFilter{
- ID: in.ExternalNetworkID,
+ out.ExternalNetwork = &infrav1.NetworkParam{
+ ID: &in.ExternalNetworkID,
}
}
@@ -298,13 +297,13 @@ func Convert_v1beta1_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in *i
}
if in.Network != nil {
- if err := Convert_v1beta1_NetworkFilter_To_v1alpha7_NetworkFilter(in.Network, &out.Network, s); err != 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 != "" {
- out.ExternalNetworkID = in.ExternalNetwork.ID
+ if in.ExternalNetwork != nil && in.ExternalNetwork.ID != nil {
+ out.ExternalNetworkID = *in.ExternalNetwork.ID
}
if len(in.Subnets) >= 1 {
diff --git a/api/v1alpha7/types_conversion.go b/api/v1alpha7/types_conversion.go
index 98bdd6df26..1139ebe05a 100644
--- a/api/v1alpha7/types_conversion.go
+++ b/api/v1alpha7/types_conversion.go
@@ -63,27 +63,63 @@ func Convert_v1beta1_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in *inf
/* 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 Convert_v1alpha7_NetworkFilter_To_v1beta1_NetworkFilter(in *NetworkFilter, out *infrav1.NetworkFilter, s apiconversion.Scope) error {
- if err := autoConvert_v1alpha7_NetworkFilter_To_v1beta1_NetworkFilter(in, out, s); err != nil {
+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, &out.FilterByNeutronTags)
+ infrav1.ConvertAllTagsTo(in.Tags, in.TagsAny, in.NotTags, in.NotTagsAny, &outFilter.FilterByNeutronTags)
+ if !outFilter.IsZero() {
+ out.Filter = outFilter
+ }
return nil
}
-func Convert_v1beta1_NetworkFilter_To_v1alpha7_NetworkFilter(in *infrav1.NetworkFilter, out *NetworkFilter, s apiconversion.Scope) error {
- if err := autoConvert_v1beta1_NetworkFilter_To_v1alpha7_NetworkFilter(in, out, s); err != nil {
- return err
+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)
}
- infrav1.ConvertAllTagsFrom(&in.FilterByNeutronTags, &out.Tags, &out.TagsAny, &out.NotTags, &out.NotTagsAny)
return nil
}
@@ -167,6 +203,8 @@ func restorev1alpha7Port(previous *PortOpts, dst *PortOpts) {
}
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)
@@ -351,3 +389,16 @@ func Convert_v1beta1_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityRef
out.Name = in.Name
return nil
}
+
+/* Placeholders */
+
+// conversion-gen registers these functions so we must provider stubs, but
+// nothing should ever call them
+
+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")
+}
diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go
index 5646dbe6f8..8b070e14bf 100644
--- a/api/v1alpha7/zz_generated.conversion.go
+++ b/api/v1alpha7/zz_generated.conversion.go
@@ -336,6 +336,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); 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 {
@@ -391,6 +396,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); 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 {
@@ -754,7 +764,7 @@ func autoConvert_v1alpha7_NetworkFilter_To_v1beta1_NetworkFilter(in *NetworkFilt
out.Name = in.Name
out.Description = in.Description
out.ProjectID = in.ProjectID
- out.ID = in.ID
+ // 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
@@ -766,7 +776,6 @@ func autoConvert_v1beta1_NetworkFilter_To_v1alpha7_NetworkFilter(in *v1beta1.Net
out.Name = in.Name
out.Description = in.Description
out.ProjectID = in.ProjectID
- out.ID = in.ID
// WARNING: in.FilterByNeutronTags requires manual conversion: does not exist in peer-type
return nil
}
@@ -907,7 +916,7 @@ func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(i
} 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.NetworkFilter)
+ // 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
@@ -973,7 +982,7 @@ func autoConvert_v1beta1_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(i
} else {
out.Router = nil
}
- // WARNING: in.Network requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.NetworkFilter vs sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7.NetworkFilter)
+ // 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
@@ -1574,8 +1583,8 @@ func Convert_v1beta1_OpenStackMachineTemplateSpec_To_v1alpha7_OpenStackMachineTe
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.NetworkFilter)
- if err := Convert_v1alpha7_NetworkFilter_To_v1beta1_NetworkFilter(*in, *out, s); err != nil {
+ *out = new(v1beta1.NetworkParam)
+ if err := Convert_v1alpha7_NetworkFilter_To_v1beta1_NetworkParam(*in, *out, s); err != nil {
return err
}
} else {
@@ -1617,7 +1626,7 @@ func autoConvert_v1beta1_PortOpts_To_v1alpha7_PortOpts(in *v1beta1.PortOpts, out
if in.Network != nil {
in, out := &in.Network, &out.Network
*out = new(NetworkFilter)
- if err := Convert_v1beta1_NetworkFilter_To_v1alpha7_NetworkFilter(*in, *out, s); err != nil {
+ if err := Convert_v1beta1_NetworkParam_To_v1alpha7_NetworkFilter(*in, *out, s); err != nil {
return err
}
} else {
diff --git a/api/v1beta1/openstackcluster_types.go b/api/v1beta1/openstackcluster_types.go
index 06d23de650..35a2bf5505 100644
--- a/api/v1beta1/openstackcluster_types.go
+++ b/api/v1beta1/openstackcluster_types.go
@@ -48,7 +48,7 @@ type OpenStackClusterSpec struct {
// Network specifies an existing network to use if no ManagedSubnets
// are specified.
// +optional
- Network *NetworkFilter `json:"network,omitempty"`
+ 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.
@@ -86,7 +86,7 @@ type OpenStackClusterSpec struct {
// If ExternalNetwork is not defined and there are no external networks
// the controller will proceed as though DisableExternalNetwork was set.
// +optional
- ExternalNetwork *NetworkFilter `json:"externalNetwork,omitempty"`
+ 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
diff --git a/api/v1beta1/types.go b/api/v1beta1/types.go
index d2d90d8f6e..34633a9261 100644
--- a/api/v1beta1/types.go
+++ b/api/v1beta1/types.go
@@ -84,6 +84,10 @@ type FilterByNeutronTags struct {
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
+}
+
type SecurityGroupFilter struct {
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
@@ -93,27 +97,38 @@ type SecurityGroupFilter struct {
FilterByNeutronTags `json:",inline"`
}
+// 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"`
- ID string `json:"id,omitempty"`
FilterByNeutronTags `json:",inline"`
}
-func (networkFilter *NetworkFilter) IsEmpty() bool {
+func (networkFilter *NetworkFilter) IsZero() bool {
if networkFilter == nil {
return true
}
return networkFilter.Name == "" &&
networkFilter.Description == "" &&
networkFilter.ProjectID == "" &&
- networkFilter.ID == "" &&
- len(networkFilter.Tags) == 0 &&
- len(networkFilter.TagsAny) == 0 &&
- len(networkFilter.NotTags) == 0 &&
- len(networkFilter.NotTagsAny) == 0
+ networkFilter.FilterByNeutronTags.IsZero()
}
type SubnetFilter struct {
@@ -169,7 +184,7 @@ 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 *NetworkFilter `json:"network,omitempty"`
+ Network *NetworkParam `json:"network,omitempty"`
// Description is a human-readable description for the port.
// +optional
diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go
index b5d80bafff..bc21785a3b 100644
--- a/api/v1beta1/zz_generated.deepcopy.go
+++ b/api/v1beta1/zz_generated.deepcopy.go
@@ -417,6 +417,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
@@ -536,7 +561,7 @@ func (in *OpenStackClusterSpec) DeepCopyInto(out *OpenStackClusterSpec) {
}
if in.Network != nil {
in, out := &in.Network, &out.Network
- *out = new(NetworkFilter)
+ *out = new(NetworkParam)
(*in).DeepCopyInto(*out)
}
if in.Subnets != nil {
@@ -560,7 +585,7 @@ func (in *OpenStackClusterSpec) DeepCopyInto(out *OpenStackClusterSpec) {
}
if in.ExternalNetwork != nil {
in, out := &in.ExternalNetwork, &out.ExternalNetwork
- *out = new(NetworkFilter)
+ *out = new(NetworkParam)
(*in).DeepCopyInto(*out)
}
if in.DisableExternalNetwork != nil {
@@ -1106,7 +1131,7 @@ 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 {
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 4aa7ca14b0..f8146a4dc0 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -5234,68 +5234,80 @@ spec:
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:
- description:
- type: string
+ 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
- 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
profile:
description: |-
@@ -5663,68 +5675,79 @@ spec:
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:
- description:
- type: string
+ 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
- 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
externalRouterIPs:
description: |-
@@ -5978,68 +6001,79 @@ spec:
description: |-
Network specifies an existing network to use if no ManagedSubnets
are specified.
+ maxProperties: 1
+ minProperties: 1
properties:
- description:
- type: string
+ 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
- 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
networkMTU:
description: |-
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 66b4e12174..72e9aabe49 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -2665,68 +2665,81 @@ spec:
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:
- description:
- type: string
+ 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
- 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
profile:
description: |-
@@ -3097,68 +3110,80 @@ spec:
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:
- description:
- type: string
+ 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
- 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
externalRouterIPs:
description: |-
@@ -3414,68 +3439,80 @@ spec:
description: |-
Network specifies an existing network to use if no ManagedSubnets
are specified.
+ maxProperties: 1
+ minProperties: 1
properties:
- description:
- type: string
+ 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
- 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
networkMTU:
description: |-
diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackfloatingippools.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackfloatingippools.yaml
index 75281a6f06..de118da2df 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackfloatingippools.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackfloatingippools.yaml
@@ -45,68 +45,79 @@ spec:
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:
- description:
- type: string
+ 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
- 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
identityRef:
description: IdentityRef is a reference to a identity to be used when
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 3d866edc37..bc3d9658b0 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
@@ -2011,68 +2011,80 @@ spec:
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:
- description:
- type: string
+ 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
- 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
profile:
description: |-
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 12d3b1ea40..7c481ff2b8 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
@@ -1688,68 +1688,80 @@ spec:
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:
- description:
- type: string
+ 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
- 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
profile:
description: |-
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index 1af03280f6..9c6e091254 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -51,7 +51,6 @@ import (
"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/filterconvert"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/names"
)
@@ -665,20 +664,13 @@ func reconcilePreExistingNetworkComponents(scope *scope.WithLogger, networkingSe
openStackCluster.Status.Network = &infrav1.NetworkStatusWithSubnets{}
}
- if !openStackCluster.Spec.Network.IsEmpty() {
- netOpts := filterconvert.NetworkFilterToListOpts(openStackCluster.Spec.Network)
- networkList, err := networkingService.GetNetworksByFilter(&netOpts)
+ if openStackCluster.Spec.Network != nil {
+ network, err := networkingService.GetNetworkByParam(openStackCluster.Spec.Network)
if err != nil {
handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to find network: %w", err))
- return fmt.Errorf("error fetching networks: %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 {
- setClusterNetwork(openStackCluster, &networkList[0])
+ return fmt.Errorf("error fetching cluster network: %w", err)
}
+ setClusterNetwork(openStackCluster, network)
}
subnets, err := getClusterSubnets(networkingService, openStackCluster)
diff --git a/controllers/openstackcluster_controller_test.go b/controllers/openstackcluster_controller_test.go
index 29cfd40a21..7f2aa20f1b 100644
--- a/controllers/openstackcluster_controller_test.go
+++ b/controllers/openstackcluster_controller_test.go
@@ -26,7 +26,6 @@ import (
"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/external"
"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"
@@ -506,6 +505,7 @@ var _ = Describe("OpenStackCluster controller", func() {
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"
@@ -519,11 +519,11 @@ var _ = Describe("OpenStackCluster controller", func() {
},
DisableAPIServerFloatingIP: pointer.Bool(true),
APIServerFixedIP: pointer.String("10.0.0.1"),
- ExternalNetwork: &infrav1.NetworkFilter{
- ID: externalNetworkID,
+ ExternalNetwork: &infrav1.NetworkParam{
+ ID: pointer.String(externalNetworkID),
},
- Network: &infrav1.NetworkFilter{
- ID: clusterNetworkID,
+ Network: &infrav1.NetworkParam{
+ ID: pointer.String(clusterNetworkID),
},
}
testCluster.Status = infrav1.OpenStackClusterStatus{
@@ -550,26 +550,15 @@ var _ = Describe("OpenStackCluster controller", func() {
networkClientRecorder := mockScopeFactory.NetworkClient.EXPECT()
// Fetch external network
- networkClientRecorder.ListNetwork(external.ListOptsExt{
- ListOptsBuilder: networks.ListOpts{
- ID: externalNetworkID,
- },
- External: pointer.Bool(true),
- }).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
@@ -600,11 +589,11 @@ var _ = Describe("OpenStackCluster controller", func() {
},
DisableAPIServerFloatingIP: pointer.Bool(true),
APIServerFixedIP: pointer.String("10.0.0.1"),
- ExternalNetwork: &infrav1.NetworkFilter{
- ID: externalNetworkID,
+ ExternalNetwork: &infrav1.NetworkParam{
+ ID: pointer.String(externalNetworkID),
},
- Network: &infrav1.NetworkFilter{
- ID: clusterNetworkID,
+ Network: &infrav1.NetworkParam{
+ ID: pointer.String(clusterNetworkID),
},
Subnets: []infrav1.SubnetFilter{
{ID: clusterSubnets[0]},
@@ -635,26 +624,15 @@ var _ = Describe("OpenStackCluster controller", func() {
networkClientRecorder := mockScopeFactory.NetworkClient.EXPECT()
// Fetch external network
- networkClientRecorder.ListNetwork(external.ListOptsExt{
- ListOptsBuilder: networks.ListOpts{
- ID: externalNetworkID,
- },
- External: pointer.Bool(true),
- }).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)
networkClientRecorder.GetSubnet(clusterSubnets[0]).Return(&subnets.Subnet{
diff --git a/controllers/openstackfloatingippool_controller.go b/controllers/openstackfloatingippool_controller.go
index f002752111..01e496d636 100644
--- a/controllers/openstackfloatingippool_controller.go
+++ b/controllers/openstackfloatingippool_controller.go
@@ -22,7 +22,6 @@ import (
"fmt"
"time"
- "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -44,7 +43,6 @@ import (
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"
- "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/filterconvert"
)
const (
@@ -400,23 +398,15 @@ func (r *OpenStackFloatingIPPoolReconciler) reconcileFloatingIPNetwork(scope *sc
return err
}
- netListOpts := external.ListOptsExt{
- ListOptsBuilder: filterconvert.NetworkFilterToListOpts(&pool.Spec.FloatingIPNetwork),
- External: pointer.Bool(true),
- }
-
- networkList, err := networkingService.GetNetworksByFilter(&netListOpts)
+ network, err := networkingService.GetNetworkByParam(&pool.Spec.FloatingIPNetwork)
if err != nil {
return fmt.Errorf("failed to find network: %w", err)
}
- if len(networkList) > 1 {
- return fmt.Errorf("found multiple networks, expects filter to match one (result: %v)", networkList)
- }
pool.Status.FloatingIPNetwork = &infrav1.NetworkStatus{
- ID: networkList[0].ID,
- Name: networkList[0].Name,
- Tags: networkList[0].Tags,
+ ID: network.ID,
+ Name: network.Name,
+ Tags: network.Tags,
}
return nil
}
diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md
index c60863aaf2..527bf24ed0 100644
--- a/docs/book/src/api/v1beta1/api.md
+++ b/docs/book/src/api/v1beta1/api.md
@@ -102,8 +102,8 @@ specified. If specified, no new router will be created.
network
-
-NetworkFilter
+
+NetworkParam
|
@@ -165,8 +165,8 @@ This is necessary if the router needs a fixed ip in a specific subnet.
externalNetwork
-
-NetworkFilter
+
+NetworkParam
|
@@ -1811,10 +1811,10 @@ bool
(Appears on:
-OpenStackClusterSpec,
-PortOpts)
+NetworkParam)
+
NetworkFilter specifies a query to select an OpenStack network. At least one property must be set.
@@ -1856,27 +1856,63 @@ string
+FilterByNeutronTags
+
+
+FilterByNeutronTags
+
+
+ |
+
+
+(Members of FilterByNeutronTags are embedded into this type.)
+
+ |
+
+
+
+NetworkParam
+
+
+(Appears on:
+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.
|
-FilterByNeutronTags
+filter
-
-FilterByNeutronTags
+
+NetworkFilter
|
-
-(Members of FilterByNeutronTags are embedded into this type.)
-
+(Optional)
+Filter specifies a filter to select an OpenStack network. If provided, cannot be empty.
|
@@ -2042,8 +2078,8 @@ specified. If specified, no new router will be created.
network
-
-NetworkFilter
+
+NetworkParam
|
@@ -2105,8 +2141,8 @@ This is necessary if the router needs a fixed ip in a specific subnet.
externalNetwork
-
-NetworkFilter
+
+NetworkParam
|
@@ -2624,8 +2660,8 @@ specified. If specified, no new router will be created.
network
-
-NetworkFilter
+
+NetworkParam
|
@@ -2687,8 +2723,8 @@ This is necessary if the router needs a fixed ip in a specific subnet.
externalNetwork
-
-NetworkFilter
+
+NetworkParam
|
@@ -3661,8 +3697,8 @@ OpenStackMachineTemplateResource
network
-
-NetworkFilter
+
+NetworkParam
|
diff --git a/pkg/cloud/services/compute/referenced_resources_test.go b/pkg/cloud/services/compute/referenced_resources_test.go
index d2456918dc..035bdaf824 100644
--- a/pkg/cloud/services/compute/referenced_resources_test.go
+++ b/pkg/cloud/services/compute/referenced_resources_test.go
@@ -128,8 +128,8 @@ func Test_ResolveMachineSpec(t *testing.T) {
Image: infrav1.ImageFilter{ID: pointer.String(imageID1)},
Ports: []infrav1.PortOpts{
{
- Network: &infrav1.NetworkFilter{
- ID: networkID2,
+ Network: &infrav1.NetworkParam{
+ ID: pointer.String(networkID2),
},
},
},
diff --git a/pkg/cloud/services/networking/network.go b/pkg/cloud/services/networking/network.go
index fbee4d4b10..4192d05e35 100644
--- a/pkg/cloud/services/networking/network.go
+++ b/pkg/cloud/services/networking/network.go
@@ -17,6 +17,7 @@ limitations under the License.
package networking
import (
+ "errors"
"fmt"
"github.com/gophercloud/gophercloud"
@@ -78,42 +79,45 @@ func (c createOpts) ToNetworkCreateMap() (map[string]interface{}, error) {
// - no external network was given in the cluster spec and no external network was found
// - the user has set OpenStackCluster.Spec.DisableExternalNetwork to true.
func (s *Service) ReconcileExternalNetwork(openStackCluster *infrav1.OpenStackCluster) error {
- var listOpts external.ListOptsExt
-
if pointer.BoolDeref(openStackCluster.Spec.DisableExternalNetwork, false) {
s.scope.Logger().Info("External network is disabled - proceeding with internal network only")
openStackCluster.Status.ExternalNetwork = nil
return nil
}
- listOpts = external.ListOptsExt{
- ListOptsBuilder: filterconvert.NetworkFilterToListOpts(openStackCluster.Spec.ExternalNetwork),
- External: pointer.Bool(true),
- }
- networkList, err := s.client.ListNetwork(listOpts)
- if err != nil {
- return err
- }
+ var network *networks.Network
+ if openStackCluster.Spec.ExternalNetwork == nil {
+ // No external network specified in the cluster spec. Default behaviour: query all external networks.
+ // * If there's only one, use that.
+ // * If there's none don't use an external network.
+ // * If there's more than one it's an error.
- switch len(networkList) {
- case 0:
- if openStackCluster.Spec.ExternalNetwork == nil {
- // Not finding an external network is fine if ExternalNetwork is not set
+ // Empty NetworkFilter will query all networks
+ var err error
+ network, err = s.getNetworkByFilter(&infrav1.NetworkFilter{}, ExternalNetworksOnly)
+ if errors.Is(err, ErrNoMatches) {
openStackCluster.Status.ExternalNetwork = nil
s.scope.Logger().Info("No external network found - proceeding with internal network only")
return nil
}
- return fmt.Errorf("no external network found")
- case 1:
- openStackCluster.Status.ExternalNetwork = &infrav1.NetworkStatus{
- ID: networkList[0].ID,
- Name: networkList[0].Name,
- Tags: networkList[0].Tags,
+ if err != nil {
+ return fmt.Errorf("failed to get external network: %w", err)
}
- s.scope.Logger().Info("External network found", "id", networkList[0].ID)
- return nil
+ } else {
+ var err error
+ network, err = s.GetNetworkByParam(openStackCluster.Spec.ExternalNetwork, ExternalNetworksOnly)
+ if err != nil {
+ return fmt.Errorf("failed to get external network: %w", err)
+ }
+ }
+
+ openStackCluster.Status.ExternalNetwork = &infrav1.NetworkStatus{
+ ID: network.ID,
+ Name: network.Name,
+ Tags: network.Tags,
}
- return fmt.Errorf("found %d external networks, which should not happen", len(networkList))
+ s.scope.Logger().Info("External network found", "id", network.ID)
+ return nil
}
func (s *Service) ReconcileNetwork(openStackCluster *infrav1.OpenStackCluster, clusterResourceName string) error {
@@ -290,32 +294,66 @@ func (s *Service) getNetworkByName(networkName string) (networks.Network, error)
return networks.Network{}, fmt.Errorf("found %d networks with the name %s, which should not happen", len(networkList), networkName)
}
-// GetNetworksByFilter retrieves networks by querying openstack with filters.
-func (s *Service) GetNetworksByFilter(opts networks.ListOptsBuilder) ([]networks.Network, error) {
- if opts == nil {
- return nil, fmt.Errorf("no Filters were passed")
+type GetNetworkOpts func(networks.ListOptsBuilder) networks.ListOptsBuilder
+
+func ExternalNetworksOnly(opts networks.ListOptsBuilder) networks.ListOptsBuilder {
+ return &external.ListOptsExt{
+ ListOptsBuilder: opts,
+ External: pointer.Bool(true),
}
- networkList, err := s.client.ListNetwork(opts)
+}
+
+// getNetworksByFilter retrieves networks by querying openstack with filters.
+func (s *Service) getNetworkByFilter(filter *infrav1.NetworkFilter, opts ...GetNetworkOpts) (*networks.Network, error) {
+ var listOpts networks.ListOptsBuilder
+ listOpts = filterconvert.NetworkFilterToListOpts(filter)
+ for _, opt := range opts {
+ listOpts = opt(listOpts)
+ }
+
+ networks, err := s.client.ListNetwork(listOpts)
if err != nil {
return nil, err
}
- if len(networkList) == 0 {
- return nil, fmt.Errorf("no networks could be found with the filters provided")
+ if len(networks) == 0 {
+ return nil, ErrNoMatches
+ }
+ if len(networks) > 1 {
+ return nil, ErrMultipleMatches
}
- return networkList, nil
+ return &networks[0], nil
}
-// GetNetworkIDsByFilter retrieves network ids by querying openstack with filters.
-func (s *Service) GetNetworkIDsByFilter(opts networks.ListOptsBuilder) ([]string, error) {
- nets, err := s.GetNetworksByFilter(opts)
- if err != nil {
- return nil, err
+// GetNetworkByParam gets the network specified by the given NetworkParam.
+func (s *Service) GetNetworkByParam(param *infrav1.NetworkParam, opts ...GetNetworkOpts) (*networks.Network, error) {
+ if param.ID != nil {
+ return s.GetNetworkByID(*param.ID)
}
- ids := []string{}
- for _, network := range nets {
- ids = append(ids, network.ID)
+
+ if param.Filter == nil {
+ return nil, errors.New("no filter or ID provided")
+ }
+
+ return s.getNetworkByFilter(param.Filter, opts...)
+}
+
+// GetNetworkIDByParam returns the ID of the network specified by the given
+// NetworkParam. It does not make an OpenStack call if the network is specified
+// by ID.
+func (s *Service) GetNetworkIDByParam(param *infrav1.NetworkParam, opts ...GetNetworkOpts) (string, error) {
+ if param.ID != nil {
+ return *param.ID, nil
+ }
+
+ if param.Filter == nil {
+ return "", errors.New("no filter or ID provided")
+ }
+
+ network, err := s.getNetworkByFilter(param.Filter, opts...)
+ if err != nil {
+ return "", err
}
- return ids, nil
+ return network.ID, nil
}
// GetSubnetsByFilter gets the id of a subnet by querying openstack with filters.
diff --git a/pkg/cloud/services/networking/network_test.go b/pkg/cloud/services/networking/network_test.go
index ff772ffe76..41fa452838 100644
--- a/pkg/cloud/services/networking/network_test.go
+++ b/pkg/cloud/services/networking/network_test.go
@@ -21,6 +21,7 @@ import (
"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/networking/v2/extensions/external"
"github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
@@ -205,16 +206,26 @@ func Test_ReconcileNetwork(t *testing.T) {
}
func Test_ReconcileExternalNetwork(t *testing.T) {
- mockCtrl := gomock.NewController(t)
- defer mockCtrl.Finish()
-
fakeNetworkID := "d08803fc-2fa5-4179-b9f7-8c43d0af2fe6"
fakeNetworkname := "external-network"
+ // Use gomega to match the ListOptsBuilder argument
+ getExternalNetwork := func(g Gomega, listOpts networks.ListOpts, ret []networks.Network) func(networks.ListOptsBuilder) ([]networks.Network, error) {
+ return func(opts networks.ListOptsBuilder) ([]networks.Network, error) {
+ expected := &external.ListOptsExt{
+ ListOptsBuilder: listOpts,
+ External: pointer.Bool(true),
+ }
+ g.Expect(opts).To(Equal(expected), cmp.Diff(opts, expected))
+
+ return ret, nil
+ }
+ }
+
tests := []struct {
name string
openStackCluster *infrav1.OpenStackCluster
- expect func(m *mock.MockNetworkClientMockRecorder)
+ expect func(g Gomega, m *mock.MockNetworkClientMockRecorder)
want *infrav1.OpenStackCluster
wantErr bool
}{
@@ -222,28 +233,21 @@ func Test_ReconcileExternalNetwork(t *testing.T) {
name: "reconcile external network by ID",
openStackCluster: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
- ExternalNetwork: &infrav1.NetworkFilter{
- ID: fakeNetworkID,
+ ExternalNetwork: &infrav1.NetworkParam{
+ ID: pointer.String(fakeNetworkID),
},
},
},
- expect: func(m *mock.MockNetworkClientMockRecorder) {
- m.
- ListNetwork(external.ListOptsExt{
- ListOptsBuilder: networks.ListOpts{ID: fakeNetworkID},
- External: pointer.Bool(true),
- }).
- Return([]networks.Network{
- {
- ID: fakeNetworkID,
- Name: fakeNetworkname,
- },
- }, nil)
+ expect: func(_ Gomega, m *mock.MockNetworkClientMockRecorder) {
+ m.GetNetwork(fakeNetworkID).Return(&networks.Network{
+ ID: fakeNetworkID,
+ Name: fakeNetworkname,
+ }, nil)
},
want: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
- ExternalNetwork: &infrav1.NetworkFilter{
- ID: fakeNetworkID,
+ ExternalNetwork: &infrav1.NetworkParam{
+ ID: pointer.String(fakeNetworkID),
},
},
Status: infrav1.OpenStackClusterStatus{
@@ -259,28 +263,24 @@ func Test_ReconcileExternalNetwork(t *testing.T) {
name: "reconcile external network by name",
openStackCluster: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
- ExternalNetwork: &infrav1.NetworkFilter{
- Name: fakeNetworkname,
+ ExternalNetwork: &infrav1.NetworkParam{
+ Filter: &infrav1.NetworkFilter{Name: fakeNetworkname},
},
},
},
- expect: func(m *mock.MockNetworkClientMockRecorder) {
- m.
- ListNetwork(external.ListOptsExt{
- ListOptsBuilder: networks.ListOpts{Name: fakeNetworkname},
- External: pointer.Bool(true),
- }).
- Return([]networks.Network{
+ expect: func(g Gomega, m *mock.MockNetworkClientMockRecorder) {
+ m.ListNetwork(gomock.Any()).
+ DoAndReturn(getExternalNetwork(g, networks.ListOpts{Name: fakeNetworkname}, []networks.Network{
{
ID: fakeNetworkID,
Name: fakeNetworkname,
},
- }, nil)
+ }))
},
want: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
- ExternalNetwork: &infrav1.NetworkFilter{
- Name: fakeNetworkname,
+ ExternalNetwork: &infrav1.NetworkParam{
+ Filter: &infrav1.NetworkFilter{Name: fakeNetworkname},
},
},
Status: infrav1.OpenStackClusterStatus{
@@ -293,26 +293,43 @@ func Test_ReconcileExternalNetwork(t *testing.T) {
wantErr: false,
},
{
- name: "reconcile external network by ID when no external network found",
+ name: "reconcile external network by ID when external network by id not found",
openStackCluster: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
- ExternalNetwork: &infrav1.NetworkFilter{
- ID: fakeNetworkID,
+ ExternalNetwork: &infrav1.NetworkParam{
+ ID: pointer.String(fakeNetworkID),
},
},
},
- expect: func(m *mock.MockNetworkClientMockRecorder) {
- m.
- ListNetwork(external.ListOptsExt{
- ListOptsBuilder: networks.ListOpts{ID: fakeNetworkID},
- External: pointer.Bool(true),
- }).
- Return([]networks.Network{}, nil)
+ expect: func(g Gomega, m *mock.MockNetworkClientMockRecorder) {
+ m.GetNetwork(fakeNetworkID).Return(nil, gophercloud.ErrDefault404{})
},
want: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
- ExternalNetwork: &infrav1.NetworkFilter{
- ID: fakeNetworkID,
+ ExternalNetwork: &infrav1.NetworkParam{
+ ID: pointer.String(fakeNetworkID),
+ },
+ },
+ },
+ wantErr: true,
+ },
+ {
+ name: "reconcile external network by ID when external network by name not found",
+ openStackCluster: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ ExternalNetwork: &infrav1.NetworkParam{
+ Filter: &infrav1.NetworkFilter{Name: fakeNetworkname},
+ },
+ },
+ },
+ expect: func(g Gomega, m *mock.MockNetworkClientMockRecorder) {
+ m.ListNetwork(gomock.Any()).
+ DoAndReturn(getExternalNetwork(g, networks.ListOpts{Name: fakeNetworkname}, []networks.Network{}))
+ },
+ want: &infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ ExternalNetwork: &infrav1.NetworkParam{
+ Filter: &infrav1.NetworkFilter{Name: fakeNetworkname},
},
},
},
@@ -325,7 +342,7 @@ func Test_ReconcileExternalNetwork(t *testing.T) {
DisableExternalNetwork: pointer.Bool(true),
},
},
- expect: func(m *mock.MockNetworkClientMockRecorder) {},
+ expect: func(_ Gomega, m *mock.MockNetworkClientMockRecorder) {},
want: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
DisableExternalNetwork: pointer.Bool(true),
@@ -337,17 +354,13 @@ func Test_ReconcileExternalNetwork(t *testing.T) {
wantErr: false,
},
{
- name: "reconcile external network with no filter when zero external network found",
+ name: "reconcile external network with no filter when zero external networks found",
openStackCluster: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{},
},
- expect: func(m *mock.MockNetworkClientMockRecorder) {
- m.
- ListNetwork(external.ListOptsExt{
- ListOptsBuilder: networks.ListOpts{},
- External: pointer.Bool(true),
- }).
- Return([]networks.Network{}, nil)
+ expect: func(g Gomega, m *mock.MockNetworkClientMockRecorder) {
+ m.ListNetwork(gomock.Any()).
+ DoAndReturn(getExternalNetwork(g, networks.ListOpts{}, []networks.Network{}))
},
want: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{},
@@ -362,18 +375,14 @@ func Test_ReconcileExternalNetwork(t *testing.T) {
openStackCluster: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{},
},
- expect: func(m *mock.MockNetworkClientMockRecorder) {
- m.
- ListNetwork(external.ListOptsExt{
- ListOptsBuilder: networks.ListOpts{},
- External: pointer.Bool(true),
- }).
- Return([]networks.Network{
+ expect: func(g Gomega, m *mock.MockNetworkClientMockRecorder) {
+ m.ListNetwork(gomock.Any()).
+ DoAndReturn(getExternalNetwork(g, networks.ListOpts{}, []networks.Network{
{
ID: fakeNetworkID,
Name: fakeNetworkname,
},
- }, nil)
+ }))
},
want: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{},
@@ -391,22 +400,27 @@ func Test_ReconcileExternalNetwork(t *testing.T) {
openStackCluster: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{},
},
- expect: func(m *mock.MockNetworkClientMockRecorder) {
+ expect: func(g Gomega, m *mock.MockNetworkClientMockRecorder) {
m.
- ListNetwork(external.ListOptsExt{
- ListOptsBuilder: networks.ListOpts{},
- External: pointer.Bool(true),
- }).
- Return([]networks.Network{
- {
- ID: fakeNetworkID,
- Name: fakeNetworkname,
- },
- {
- ID: "d08803fc-2fa5-4179-b9f7-8c43d0af2fe7",
- Name: "external-network-2",
- },
- }, nil)
+ ListNetwork(gomock.Any()).
+ DoAndReturn(func(opts networks.ListOptsBuilder) ([]networks.Network, error) {
+ expected := &external.ListOptsExt{
+ ListOptsBuilder: networks.ListOpts{},
+ External: pointer.Bool(true),
+ }
+ g.Expect(opts).To(Equal(expected), cmp.Diff(opts, expected))
+
+ return []networks.Network{
+ {
+ ID: fakeNetworkID,
+ Name: fakeNetworkname,
+ },
+ {
+ ID: "d08803fc-2fa5-4179-b9f7-8c43d0af2fe7",
+ Name: "external-network-2",
+ },
+ }, nil
+ })
},
want: &infrav1.OpenStackCluster{},
wantErr: true,
@@ -415,9 +429,12 @@ func Test_ReconcileExternalNetwork(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
+ mockCtrl := gomock.NewController(t)
+ defer mockCtrl.Finish()
+
g := NewWithT(t)
mockClient := mock.NewMockNetworkClient(mockCtrl)
- tt.expect(mockClient.EXPECT())
+ tt.expect(g, mockClient.EXPECT())
scopeFactory := scope.NewMockScopeFactory(mockCtrl, "")
log := testr.New(t)
@@ -429,7 +446,7 @@ func Test_ReconcileExternalNetwork(t *testing.T) {
if (err != nil) != tt.wantErr {
t.Errorf("ReconcileExternalNetwork() error = %v, wantErr %v", err, tt.wantErr)
}
- g.Expect(tt.openStackCluster).To(Equal(tt.want))
+ g.Expect(tt.openStackCluster).To(Equal(tt.want), cmp.Diff(tt.openStackCluster, tt.want))
})
}
}
diff --git a/pkg/cloud/services/networking/port.go b/pkg/cloud/services/networking/port.go
index f1fbfef6ce..8677b87a04 100644
--- a/pkg/cloud/services/networking/port.go
+++ b/pkg/cloud/services/networking/port.go
@@ -35,7 +35,6 @@ import (
"sigs.k8s.io/cluster-api-provider-openstack/pkg/record"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
capoerrors "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/errors"
- "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/filterconvert"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/names"
)
@@ -469,8 +468,12 @@ func (s *Service) normalizePortTarget(port *infrav1.PortOpts, defaultNetwork *in
}
switch {
- case port.Network != nil && port.Network.ID != "":
- networkID = port.Network.ID
+ case port.Network != nil:
+ var err error
+ networkID, err = s.GetNetworkIDByParam(port.Network)
+ if err != nil {
+ return "", nil, err
+ }
// No network, but fixed IPs are defined(we handled the no fixed
// IPs case above): try to infer network from a subnet
@@ -513,21 +516,9 @@ func (s *Service) normalizePortTarget(port *infrav1.PortOpts, defaultNetwork *in
return "", nil, err
}
- // Network is defined by filter
default:
- networkListOpts := filterconvert.NetworkFilterToListOpts(port.Network)
- netIDs, err := s.GetNetworkIDsByFilter(networkListOpts)
- if err != nil {
- return "", nil, err
- }
-
- // TODO: These are spec errors: they should set the machine to failed
- if len(netIDs) > 1 {
- return "", nil, fmt.Errorf("network filter for port %d returns more than one result", portIdx)
- } else if len(netIDs) == 0 {
- return "", nil, fmt.Errorf("network filter for port %d returns no networks", portIdx)
- }
- networkID = netIDs[0]
+ // TODO: This is a spec errors: it should set the machine to failed
+ return "", nil, fmt.Errorf("unable to determine network for port %d", portIdx)
}
// Network ID is now known. Resolve all FixedIPs
diff --git a/pkg/cloud/services/networking/port_test.go b/pkg/cloud/services/networking/port_test.go
index 466ee35a89..8fb6e035b2 100644
--- a/pkg/cloud/services/networking/port_test.go
+++ b/pkg/cloud/services/networking/port_test.go
@@ -475,8 +475,8 @@ func TestService_ConstructPorts(t *testing.T) {
spec: infrav1.OpenStackMachineSpec{
Ports: []infrav1.PortOpts{
{
- Network: &infrav1.NetworkFilter{
- ID: networkID,
+ Network: &infrav1.NetworkParam{
+ ID: pointer.String(networkID),
},
},
},
@@ -497,8 +497,8 @@ func TestService_ConstructPorts(t *testing.T) {
spec: infrav1.OpenStackMachineSpec{
Ports: []infrav1.PortOpts{
{
- Network: &infrav1.NetworkFilter{
- Name: "test-network",
+ Network: &infrav1.NetworkParam{
+ Filter: &infrav1.NetworkFilter{Name: "test-network"},
},
},
},
@@ -858,7 +858,7 @@ func Test_getPortName(t *testing.T) {
instanceName: "test-1-instance",
spec: &infrav1.PortOpts{
NameSuffix: pointer.String("foo2"),
- Network: &infrav1.NetworkFilter{ID: "bar"},
+ Network: &infrav1.NetworkParam{ID: pointer.String("bar")},
ResolvedPortSpecFields: infrav1.ResolvedPortSpecFields{
DisablePortSecurity: pointer.Bool(true),
},
diff --git a/pkg/utils/filterconvert/convert.go b/pkg/utils/filterconvert/convert.go
index a1574cc49f..01ce2126ec 100644
--- a/pkg/utils/filterconvert/convert.go
+++ b/pkg/utils/filterconvert/convert.go
@@ -71,7 +71,6 @@ func NetworkFilterToListOpts(networkFilter *infrav1.NetworkFilter) networks.List
Name: networkFilter.Name,
Description: networkFilter.Description,
ProjectID: networkFilter.ProjectID,
- ID: networkFilter.ID,
Tags: infrav1.JoinTags(networkFilter.Tags),
TagsAny: infrav1.JoinTags(networkFilter.TagsAny),
NotTags: infrav1.JoinTags(networkFilter.NotTags),
diff --git a/test/e2e/data/kustomize/common-patches/externalNetworkByName/kustomization.yaml b/test/e2e/data/kustomize/common-patches/externalNetworkByName/kustomization.yaml
index 67b3a753a6..6c89e0ebdd 100644
--- a/test/e2e/data/kustomize/common-patches/externalNetworkByName/kustomization.yaml
+++ b/test/e2e/data/kustomize/common-patches/externalNetworkByName/kustomization.yaml
@@ -9,6 +9,7 @@ patches:
- op: "add"
path: "/spec/externalNetwork"
value:
- name: "${OPENSTACK_EXTERNAL_NETWORK_NAME}"
+ filter:
+ name: "${OPENSTACK_EXTERNAL_NETWORK_NAME}"
target:
kind: OpenStackCluster
diff --git a/test/e2e/suites/apivalidations/filters_test.go b/test/e2e/suites/apivalidations/filters_test.go
index b4e256cff8..aa8691df0e 100644
--- a/test/e2e/suites/apivalidations/filters_test.go
+++ b/test/e2e/suites/apivalidations/filters_test.go
@@ -60,7 +60,7 @@ var _ = Describe("Filter API validations", func() {
ports := make([]infrav1.PortOpts, len(tags))
for i := range tags {
port := &ports[i]
- port.Network = &infrav1.NetworkFilter{FilterByNeutronTags: tags[i]}
+ port.Network = &infrav1.NetworkParam{Filter: &infrav1.NetworkFilter{FilterByNeutronTags: tags[i]}}
port.FixedIPs = []infrav1.FixedIP{{Subnet: &infrav1.SubnetFilter{FilterByNeutronTags: tags[i]}}}
port.SecurityGroups = []infrav1.SecurityGroupFilter{{FilterByNeutronTags: tags[i]}}
}
@@ -74,8 +74,8 @@ var _ = Describe("Filter API validations", func() {
}
cluster.Spec.Subnets = subnets
if len(tags) > 0 {
- cluster.Spec.Network = &infrav1.NetworkFilter{FilterByNeutronTags: tags[0]}
- cluster.Spec.ExternalNetwork = &infrav1.NetworkFilter{FilterByNeutronTags: tags[0]}
+ cluster.Spec.Network = &infrav1.NetworkParam{Filter: &infrav1.NetworkFilter{FilterByNeutronTags: tags[0]}}
+ cluster.Spec.ExternalNetwork = &infrav1.NetworkParam{Filter: &infrav1.NetworkFilter{FilterByNeutronTags: tags[0]}}
cluster.Spec.Router = &infrav1.RouterFilter{FilterByNeutronTags: tags[0]}
}
Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
@@ -107,7 +107,7 @@ var _ = Describe("Filter API validations", func() {
{
machine := machine.DeepCopy()
machine.Spec.Ports = []infrav1.PortOpts{
- {Network: &infrav1.NetworkFilter{FilterByNeutronTags: tags[i]}},
+ {Network: &infrav1.NetworkParam{Filter: &infrav1.NetworkFilter{FilterByNeutronTags: tags[i]}}},
}
Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail with invalid port network neutron tags")
}
@@ -138,13 +138,13 @@ var _ = Describe("Filter API validations", func() {
{
cluster := cluster.DeepCopy()
- cluster.Spec.Network = &infrav1.NetworkFilter{FilterByNeutronTags: tag}
+ cluster.Spec.Network = &infrav1.NetworkParam{Filter: &infrav1.NetworkFilter{FilterByNeutronTags: tag}}
Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should fail with invalid network neutron tags")
}
{
cluster := cluster.DeepCopy()
- cluster.Spec.ExternalNetwork = &infrav1.NetworkFilter{FilterByNeutronTags: tag}
+ cluster.Spec.ExternalNetwork = &infrav1.NetworkParam{Filter: &infrav1.NetworkFilter{FilterByNeutronTags: tag}}
Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should fail with invalid external network neutron tags")
}
@@ -219,4 +219,46 @@ var _ = Describe("Filter API validations", func() {
}
Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "OpenStackMachine creation should succeed")
})
+
+ Context("NetworkParam", func() {
+ It("should allow setting ID", func() {
+ cluster.Spec.Network = &infrav1.NetworkParam{
+ ID: pointer.String("06c32c52-f207-4f6a-a769-bbcbe5a43f5c"),
+ }
+ Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
+ })
+
+ It("should allow setting non-empty Filter", func() {
+ cluster.Spec.Network = &infrav1.NetworkParam{
+ Filter: &infrav1.NetworkFilter{Name: "foo"},
+ }
+ Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
+ })
+
+ It("should not allow setting empty param", func() {
+ cluster.Spec.Network = &infrav1.NetworkParam{}
+ Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should fail")
+ })
+
+ It("should not allow setting invalid id", func() {
+ cluster.Spec.Network = &infrav1.NetworkParam{
+ ID: pointer.String("foo"),
+ }
+ Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should fail")
+ })
+
+ It("should not allow setting empty Filter", func() {
+ cluster.Spec.Network = &infrav1.NetworkParam{
+ Filter: &infrav1.NetworkFilter{},
+ }
+ Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should fail")
+ })
+
+ It("should not allow setting both ID and Filter", func() {
+ cluster.Spec.Network = &infrav1.NetworkParam{
+ ID: pointer.String("06c32c52-f207-4f6a-a769-bbcbe5a43f5c"), Filter: &infrav1.NetworkFilter{Name: "foo"},
+ }
+ Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should fail")
+ })
+ })
})
diff --git a/test/helpers/fuzzerfuncs.go b/test/helpers/fuzzerfuncs.go
index 6657ed3c73..da35973632 100644
--- a/test/helpers/fuzzerfuncs.go
+++ b/test/helpers/fuzzerfuncs.go
@@ -20,8 +20,10 @@ import (
"strings"
fuzz "github.com/google/gofuzz"
+ "k8s.io/utils/pointer"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
+ "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/optional"
)
func filterInvalidTags(tags []infrav1.NeutronTag) []infrav1.NeutronTag {
@@ -35,6 +37,32 @@ func filterInvalidTags(tags []infrav1.NeutronTag) []infrav1.NeutronTag {
return ret
}
+func nonEmptyString(c fuzz.Continue) string {
+ for {
+ if s := c.RandString(); s != "" {
+ return s
+ }
+ }
+}
+
+type isZeroer[T any] interface {
+ IsZero() bool
+ *T
+}
+
+func fuzzFilterParam[Z isZeroer[T], T any](id *optional.String, filter *Z, c fuzz.Continue) {
+ if c.RandBool() {
+ *id = pointer.String(nonEmptyString(c))
+ *filter = nil
+ } else {
+ *filter = new(T)
+ for (*filter).IsZero() {
+ c.Fuzz(*filter)
+ }
+ *id = nil
+ }
+}
+
// InfraV1FuzzerFuncs returns fuzzer funcs for v1beta1 OpenStack types which:
// * Constrain the output in ways which are validated by the API server
// * Add additional test coverage where it is not generated by the default fuzzer.
@@ -100,5 +128,10 @@ func InfraV1FuzzerFuncs() []interface{} {
filter.NotTags = filterInvalidTags(filter.NotTags)
filter.NotTagsAny = filterInvalidTags(filter.NotTagsAny)
},
+
+ // v1beta1 network param contains exactly one of ID or filter
+ func(param *infrav1.NetworkParam, c fuzz.Continue) {
+ fuzzFilterParam(¶m.ID, ¶m.Filter, c)
+ },
}
}
From 4d85f6f7a4e04e9995091cfd543725f6ca979327 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Tue, 26 Mar 2024 10:16:22 +0000
Subject: [PATCH 150/180] SubnetFilter to SubnetParam
---
api/v1alpha5/conversion.go | 55 ++-
api/v1alpha5/zz_generated.conversion.go | 43 +-
api/v1alpha6/conversion_test.go | 68 +--
api/v1alpha6/openstackcluster_conversion.go | 19 +-
api/v1alpha6/openstackmachine_conversion.go | 8 +-
api/v1alpha6/types_conversion.go | 99 +++-
api/v1alpha6/zz_generated.conversion.go | 43 +-
api/v1alpha7/openstackcluster_conversion.go | 17 +-
api/v1alpha7/types_conversion.go | 76 ++-
api/v1alpha7/zz_generated.conversion.go | 23 +-
api/v1beta1/openstackcluster_types.go | 2 +-
api/v1beta1/types.go | 38 +-
api/v1beta1/zz_generated.deepcopy.go | 29 +-
...re.cluster.x-k8s.io_openstackclusters.yaml | 449 +++++++++--------
...er.x-k8s.io_openstackclustertemplates.yaml | 451 ++++++++++--------
...re.cluster.x-k8s.io_openstackmachines.yaml | 149 +++---
...er.x-k8s.io_openstackmachinetemplates.yaml | 150 +++---
controllers/openstackcluster_controller.go | 4 +-
.../openstackcluster_controller_test.go | 24 +-
docs/book/src/api/v1beta1/api.md | 74 ++-
pkg/cloud/services/networking/network.go | 49 +-
pkg/cloud/services/networking/port.go | 4 +-
pkg/cloud/services/networking/port_test.go | 24 +-
pkg/cloud/services/networking/router.go | 10 +-
pkg/utils/filterconvert/convert.go | 1 -
.../e2e/suites/apivalidations/filters_test.go | 56 ++-
test/helpers/fuzzerfuncs.go | 8 +-
27 files changed, 1231 insertions(+), 742 deletions(-)
diff --git a/api/v1alpha5/conversion.go b/api/v1alpha5/conversion.go
index b8190e088a..19397b6956 100644
--- a/api/v1alpha5/conversion.go
+++ b/api/v1alpha5/conversion.go
@@ -217,7 +217,7 @@ func Convert_v1beta1_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(in *i
if in.Subnets != nil {
if len(in.Subnets) >= 1 {
- if err := Convert_v1beta1_SubnetFilter_To_v1alpha5_SubnetFilter(&in.Subnets[0], &out.Subnet, s); err != nil {
+ if err := Convert_v1beta1_SubnetParam_To_v1alpha5_SubnetFilter(&in.Subnets[0], &out.Subnet, s); err != nil {
return err
}
}
@@ -254,11 +254,11 @@ func Convert_v1alpha5_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *O
emptySubnet := SubnetFilter{}
if in.Subnet != emptySubnet {
- subnet := infrav1.SubnetFilter{}
- if err := Convert_v1alpha5_SubnetFilter_To_v1beta1_SubnetFilter(&in.Subnet, &subnet, s); err != nil {
+ subnet := infrav1.SubnetParam{}
+ if err := Convert_v1alpha5_SubnetFilter_To_v1beta1_SubnetParam(&in.Subnet, &subnet, s); err != nil {
return err
}
- out.Subnets = []infrav1.SubnetFilter{subnet}
+ out.Subnets = []infrav1.SubnetParam{subnet}
}
if len(in.NodeCIDR) > 0 {
@@ -547,25 +547,56 @@ func Convert_v1beta1_SecurityGroupFilter_To_v1alpha5_SecurityGroupParam(in *infr
return nil
}
-func Convert_v1alpha5_SubnetParam_To_v1beta1_SubnetFilter(in *SubnetParam, out *infrav1.SubnetFilter, s conversion.Scope) error {
- if err := Convert_v1alpha5_SubnetFilter_To_v1beta1_SubnetFilter(&in.Filter, out, s); err != nil {
+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
+ }
+ outFilter := &infrav1.SubnetFilter{}
+ if err := Convert_v1alpha5_SubnetFilter_To_v1beta1_SubnetFilter(&in.Filter, outFilter, s); err != nil {
return err
}
- if in.UUID != "" {
- out.ID = in.UUID
+ if !outFilter.IsZero() {
+ out.Filter = outFilter
}
return nil
}
-func Convert_v1beta1_SubnetFilter_To_v1alpha5_SubnetParam(in *infrav1.SubnetFilter, out *SubnetParam, s conversion.Scope) error {
- if err := Convert_v1beta1_SubnetFilter_To_v1alpha5_SubnetFilter(in, &out.Filter, s); err != nil {
- return err
+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
+ }
}
- out.UUID = in.ID
return nil
}
+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_v1beta1_BindingProfile(in map[string]string, out *infrav1.BindingProfile, _ conversion.Scope) error {
for k, v := range in {
if k == "capabilities" {
diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go
index e8376912a3..8d24ce309a 100644
--- a/api/v1alpha5/zz_generated.conversion.go
+++ b/api/v1alpha5/zz_generated.conversion.go
@@ -317,8 +317,13 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddConversionFunc((*SubnetParam)(nil), (*v1beta1.SubnetFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_SubnetParam_To_v1beta1_SubnetFilter(a.(*SubnetParam), b.(*v1beta1.SubnetFilter), 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((*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
}
@@ -417,8 +422,13 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddConversionFunc((*v1beta1.SubnetFilter)(nil), (*SubnetParam)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1beta1_SubnetFilter_To_v1alpha5_SubnetParam(a.(*v1beta1.SubnetFilter), b.(*SubnetParam), scope)
+ 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
}
@@ -496,7 +506,7 @@ func autoConvert_v1beta1_Bastion_To_v1alpha5_Bastion(in *v1beta1.Bastion, out *B
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_v1beta1_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
@@ -509,7 +519,7 @@ func Convert_v1alpha5_ExternalRouterIPParam_To_v1beta1_ExternalRouterIPParam(in
func autoConvert_v1beta1_ExternalRouterIPParam_To_v1alpha5_ExternalRouterIPParam(in *v1beta1.ExternalRouterIPParam, out *ExternalRouterIPParam, s conversion.Scope) error {
out.FixedIP = in.FixedIP
- if err := Convert_v1beta1_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
@@ -523,8 +533,8 @@ func Convert_v1beta1_ExternalRouterIPParam_To_v1alpha5_ExternalRouterIPParam(in
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.SubnetFilter)
- if err := Convert_v1alpha5_SubnetFilter_To_v1beta1_SubnetFilter(*in, *out, s); err != nil {
+ *out = new(v1beta1.SubnetParam)
+ if err := Convert_v1alpha5_SubnetFilter_To_v1beta1_SubnetParam(*in, *out, s); err != nil {
return err
}
} else {
@@ -545,7 +555,7 @@ func autoConvert_v1beta1_FixedIP_To_v1alpha5_FixedIP(in *v1beta1.FixedIP, out *F
if in.Subnet != nil {
in, out := &in.Subnet, &out.Subnet
*out = new(SubnetFilter)
- if err := Convert_v1beta1_SubnetFilter_To_v1alpha5_SubnetFilter(*in, *out, s); err != nil {
+ if err := Convert_v1beta1_SubnetParam_To_v1alpha5_SubnetFilter(*in, *out, s); err != nil {
return err
}
} else {
@@ -1567,7 +1577,7 @@ func autoConvert_v1alpha5_SubnetFilter_To_v1beta1_SubnetFilter(in *SubnetFilter,
out.CIDR = in.CIDR
out.IPv6AddressMode = in.IPv6AddressMode
out.IPv6RAMode = in.IPv6RAMode
- out.ID = in.ID
+ // 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
@@ -1584,7 +1594,18 @@ func autoConvert_v1beta1_SubnetFilter_To_v1alpha5_SubnetFilter(in *v1beta1.Subne
out.CIDR = in.CIDR
out.IPv6AddressMode = in.IPv6AddressMode
out.IPv6RAMode = in.IPv6RAMode
- out.ID = in.ID
// 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
+}
+
+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/v1alpha6/conversion_test.go b/api/v1alpha6/conversion_test.go
index 0c1352767d..1456680359 100644
--- a/api/v1alpha6/conversion_test.go
+++ b/api/v1alpha6/conversion_test.go
@@ -286,8 +286,8 @@ func TestNetworksToPorts(t *testing.T) {
},
FixedIPs: []infrav1.FixedIP{
{
- Subnet: &infrav1.SubnetFilter{
- ID: subnetuuid,
+ Subnet: &infrav1.SubnetParam{
+ ID: pointer.String(subnetuuid),
},
},
},
@@ -330,20 +330,22 @@ func TestNetworksToPorts(t *testing.T) {
},
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",
- FilterByNeutronTags: infrav1.FilterByNeutronTags{
- Tags: []infrav1.NeutronTag{"tags"},
- TagsAny: []infrav1.NeutronTag{"tags-any"},
- NotTags: []infrav1.NeutronTag{"not-tags"},
- NotTagsAny: []infrav1.NeutronTag{"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"},
+ },
},
},
},
@@ -390,8 +392,8 @@ func TestNetworksToPorts(t *testing.T) {
},
FixedIPs: []infrav1.FixedIP{
{
- Subnet: &infrav1.SubnetFilter{
- ID: subnetuuid,
+ Subnet: &infrav1.SubnetParam{
+ ID: pointer.String(subnetuuid),
},
},
},
@@ -402,20 +404,22 @@ func TestNetworksToPorts(t *testing.T) {
},
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",
- FilterByNeutronTags: infrav1.FilterByNeutronTags{
- Tags: []infrav1.NeutronTag{"tags"},
- TagsAny: []infrav1.NeutronTag{"tags-any"},
- NotTags: []infrav1.NeutronTag{"not-tags"},
- NotTagsAny: []infrav1.NeutronTag{"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"},
+ },
},
},
},
diff --git a/api/v1alpha6/openstackcluster_conversion.go b/api/v1alpha6/openstackcluster_conversion.go
index 68242edd8c..66fd5896bb 100644
--- a/api/v1alpha6/openstackcluster_conversion.go
+++ b/api/v1alpha6/openstackcluster_conversion.go
@@ -152,7 +152,7 @@ func restorev1alpha6ClusterSpec(previous *OpenStackClusterSpec, dst *OpenStackCl
if len(dst.ExternalRouterIPs) == len(previous.ExternalRouterIPs) {
for i := range dst.ExternalRouterIPs {
- restorev1alpha6SubnetFilter(&previous.ExternalRouterIPs[i].Subnet.Filter, &dst.ExternalRouterIPs[i].Subnet.Filter)
+ restorev1alpha6SubnetParam(&previous.ExternalRouterIPs[i].Subnet, &dst.ExternalRouterIPs[i].Subnet)
}
}
@@ -179,10 +179,19 @@ func restorev1beta1ClusterSpec(previous *infrav1.OpenStackClusterSpec, dst *infr
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 {
@@ -232,11 +241,11 @@ func Convert_v1alpha6_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *O
emptySubnet := SubnetFilter{}
if in.Subnet != emptySubnet {
- subnet := infrav1.SubnetFilter{}
- if err := Convert_v1alpha6_SubnetFilter_To_v1beta1_SubnetFilter(&in.Subnet, &subnet, s); err != nil {
+ subnet := infrav1.SubnetParam{}
+ if err := Convert_v1alpha6_SubnetFilter_To_v1beta1_SubnetParam(&in.Subnet, &subnet, s); err != nil {
return err
}
- out.Subnets = []infrav1.SubnetFilter{subnet}
+ out.Subnets = []infrav1.SubnetParam{subnet}
}
// DNSNameservers without NodeCIDR doesn't make sense, so we drop that.
@@ -295,7 +304,7 @@ func Convert_v1beta1_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(in *i
}
if len(in.Subnets) >= 1 {
- if err := Convert_v1beta1_SubnetFilter_To_v1alpha6_SubnetFilter(&in.Subnets[0], &out.Subnet, s); err != nil {
+ if err := Convert_v1beta1_SubnetParam_To_v1alpha6_SubnetFilter(&in.Subnets[0], &out.Subnet, s); err != nil {
return err
}
}
diff --git a/api/v1alpha6/openstackmachine_conversion.go b/api/v1alpha6/openstackmachine_conversion.go
index 9ab01741ea..d13eb5c124 100644
--- a/api/v1alpha6/openstackmachine_conversion.go
+++ b/api/v1alpha6/openstackmachine_conversion.go
@@ -223,18 +223,18 @@ func convertNetworksToPorts(networks []NetworkParam, s apiconversion.Scope) ([]i
ports = append(ports, infrav1.PortOpts{
Network: networkFilter,
FixedIPs: []infrav1.FixedIP{
- {Subnet: &infrav1.SubnetFilter{ID: subnet.UUID}},
+ {Subnet: &infrav1.SubnetParam{ID: &subnet.UUID}},
},
})
} else {
- subnetFilter := &infrav1.SubnetFilter{}
- if err := Convert_v1alpha6_SubnetFilter_To_v1beta1_SubnetFilter(&subnet.Filter, subnetFilter, s); err != nil {
+ 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: subnetFilter},
+ {Subnet: subnetParam},
},
})
}
diff --git a/api/v1alpha6/types_conversion.go b/api/v1alpha6/types_conversion.go
index 80cefb86fc..1b2a642f34 100644
--- a/api/v1alpha6/types_conversion.go
+++ b/api/v1alpha6/types_conversion.go
@@ -24,6 +24,7 @@ import (
"k8s.io/utils/pointer"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
+ optional "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/optional"
)
const trueString = "true"
@@ -164,29 +165,81 @@ func Convert_v1beta1_NetworkParam_To_v1alpha6_NetworkFilter(in *infrav1.NetworkP
/* 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 Convert_v1alpha6_SubnetParam_To_v1beta1_SubnetFilter(in *SubnetParam, out *infrav1.SubnetFilter, s apiconversion.Scope) error {
- if err := Convert_v1alpha6_SubnetFilter_To_v1beta1_SubnetFilter(&in.Filter, out, s); err != nil {
- return err
+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 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
+ 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_SubnetFilter_To_v1alpha6_SubnetParam(in *infrav1.SubnetFilter, out *SubnetParam, s apiconversion.Scope) error {
- if err := Convert_v1beta1_SubnetFilter_To_v1alpha6_SubnetFilter(in, &out.Filter, s); err != nil {
- return err
+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
+ }
}
- out.UUID = in.ID
return nil
}
@@ -207,6 +260,36 @@ func Convert_v1beta1_SubnetFilter_To_v1alpha6_SubnetFilter(in *infrav1.SubnetFil
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) {
diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go
index 34023deb82..9862d40792 100644
--- a/api/v1alpha6/zz_generated.conversion.go
+++ b/api/v1alpha6/zz_generated.conversion.go
@@ -336,8 +336,13 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddConversionFunc((*SubnetParam)(nil), (*v1beta1.SubnetFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_SubnetParam_To_v1beta1_SubnetFilter(a.(*SubnetParam), b.(*v1beta1.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.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
}
@@ -431,8 +436,13 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddConversionFunc((*v1beta1.SubnetFilter)(nil), (*SubnetParam)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1beta1_SubnetFilter_To_v1alpha6_SubnetParam(a.(*v1beta1.SubnetFilter), b.(*SubnetParam), scope)
+ 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
}
@@ -520,7 +530,7 @@ func autoConvert_v1beta1_Bastion_To_v1alpha6_Bastion(in *v1beta1.Bastion, out *B
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_v1beta1_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
@@ -533,7 +543,7 @@ func Convert_v1alpha6_ExternalRouterIPParam_To_v1beta1_ExternalRouterIPParam(in
func autoConvert_v1beta1_ExternalRouterIPParam_To_v1alpha6_ExternalRouterIPParam(in *v1beta1.ExternalRouterIPParam, out *ExternalRouterIPParam, s conversion.Scope) error {
out.FixedIP = in.FixedIP
- if err := Convert_v1beta1_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
@@ -547,8 +557,8 @@ func Convert_v1beta1_ExternalRouterIPParam_To_v1alpha6_ExternalRouterIPParam(in
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.SubnetFilter)
- if err := Convert_v1alpha6_SubnetFilter_To_v1beta1_SubnetFilter(*in, *out, s); err != nil {
+ *out = new(v1beta1.SubnetParam)
+ if err := Convert_v1alpha6_SubnetFilter_To_v1beta1_SubnetParam(*in, *out, s); err != nil {
return err
}
} else {
@@ -569,7 +579,7 @@ func autoConvert_v1beta1_FixedIP_To_v1alpha6_FixedIP(in *v1beta1.FixedIP, out *F
if in.Subnet != nil {
in, out := &in.Subnet, &out.Subnet
*out = new(SubnetFilter)
- if err := Convert_v1beta1_SubnetFilter_To_v1alpha6_SubnetFilter(*in, *out, s); err != nil {
+ if err := Convert_v1beta1_SubnetParam_To_v1alpha6_SubnetFilter(*in, *out, s); err != nil {
return err
}
} else {
@@ -1603,7 +1613,7 @@ func autoConvert_v1alpha6_SubnetFilter_To_v1beta1_SubnetFilter(in *SubnetFilter,
out.CIDR = in.CIDR
out.IPv6AddressMode = in.IPv6AddressMode
out.IPv6RAMode = in.IPv6RAMode
- out.ID = in.ID
+ // 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
@@ -1620,11 +1630,22 @@ func autoConvert_v1beta1_SubnetFilter_To_v1alpha6_SubnetFilter(in *v1beta1.Subne
out.CIDR = in.CIDR
out.IPv6AddressMode = in.IPv6AddressMode
out.IPv6RAMode = in.IPv6RAMode
- out.ID = in.ID
// 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
+}
+
+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_v1beta1_ValueSpec(in *ValueSpec, out *v1beta1.ValueSpec, s conversion.Scope) error {
out.Name = in.Name
out.Key = in.Key
diff --git a/api/v1alpha7/openstackcluster_conversion.go b/api/v1alpha7/openstackcluster_conversion.go
index 7ff49ecdcf..75e92032d1 100644
--- a/api/v1alpha7/openstackcluster_conversion.go
+++ b/api/v1alpha7/openstackcluster_conversion.go
@@ -191,10 +191,19 @@ func restorev1beta1ClusterSpec(previous *infrav1.OpenStackClusterSpec, dst *infr
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 {
@@ -244,11 +253,11 @@ func Convert_v1alpha7_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *O
emptySubnet := SubnetFilter{}
if in.Subnet != emptySubnet {
- subnet := infrav1.SubnetFilter{}
- if err := Convert_v1alpha7_SubnetFilter_To_v1beta1_SubnetFilter(&in.Subnet, &subnet, s); err != nil {
+ subnet := infrav1.SubnetParam{}
+ if err := Convert_v1alpha7_SubnetFilter_To_v1beta1_SubnetParam(&in.Subnet, &subnet, s); err != nil {
return err
}
- out.Subnets = []infrav1.SubnetFilter{subnet}
+ out.Subnets = []infrav1.SubnetParam{subnet}
}
// DNSNameservers without NodeCIDR doesn't make sense, so we drop that.
@@ -307,7 +316,7 @@ func Convert_v1beta1_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in *i
}
if len(in.Subnets) >= 1 {
- if err := Convert_v1beta1_SubnetFilter_To_v1alpha7_SubnetFilter(&in.Subnets[0], &out.Subnet, s); err != nil {
+ if err := Convert_v1beta1_SubnetParam_To_v1alpha7_SubnetFilter(&in.Subnets[0], &out.Subnet, s); err != nil {
return err
}
}
diff --git a/api/v1alpha7/types_conversion.go b/api/v1alpha7/types_conversion.go
index 1139ebe05a..a63cd212ed 100644
--- a/api/v1alpha7/types_conversion.go
+++ b/api/v1alpha7/types_conversion.go
@@ -126,27 +126,74 @@ func Convert_v1beta1_NetworkParam_To_v1alpha7_NetworkFilter(in *infrav1.NetworkP
/* 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 Convert_v1alpha7_SubnetFilter_To_v1beta1_SubnetFilter(in *SubnetFilter, out *infrav1.SubnetFilter, s apiconversion.Scope) error {
- if err := autoConvert_v1alpha7_SubnetFilter_To_v1beta1_SubnetFilter(in, out, s); err != nil {
+func restorev1beta1SubnetParam(previous *infrav1.SubnetParam, dst *infrav1.SubnetParam) {
+ if previous == nil || dst == nil {
+ return
+ }
+
+ optional.RestoreString(&previous.ID, &dst.ID)
+
+ if 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, &out.FilterByNeutronTags)
+ infrav1.ConvertAllTagsTo(in.Tags, in.TagsAny, in.NotTags, in.NotTagsAny, &filter.FilterByNeutronTags)
+
+ if !filter.IsZero() {
+ out.Filter = filter
+ }
return nil
}
-func Convert_v1beta1_SubnetFilter_To_v1alpha7_SubnetFilter(in *infrav1.SubnetFilter, out *SubnetFilter, s apiconversion.Scope) error {
- if err := autoConvert_v1beta1_SubnetFilter_To_v1alpha7_SubnetFilter(in, out, s); err != 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.FilterByNeutronTags, &out.Tags, &out.TagsAny, &out.NotTags, &out.NotTagsAny)
+ infrav1.ConvertAllTagsFrom(&in.Filter.FilterByNeutronTags, &out.Tags, &out.TagsAny, &out.NotTags, &out.NotTagsAny)
return nil
}
@@ -214,9 +261,8 @@ func restorev1beta1Port(previous *infrav1.PortOpts, dst *infrav1.PortOpts) {
prevFixedIP := &previous.FixedIPs[j]
dstFixedIP := &dst.FixedIPs[j]
- if dstFixedIP.IPAddress == nil || *dstFixedIP.IPAddress == "" {
- dstFixedIP.IPAddress = prevFixedIP.IPAddress
- }
+ optional.RestoreString(&prevFixedIP.IPAddress, &dstFixedIP.IPAddress)
+ restorev1beta1SubnetParam(prevFixedIP.Subnet, dstFixedIP.Subnet)
}
}
@@ -225,9 +271,7 @@ func restorev1beta1Port(previous *infrav1.PortOpts, dst *infrav1.PortOpts) {
prevAAP := &previous.AllowedAddressPairs[j]
dstAAP := &dst.AllowedAddressPairs[j]
- if dstAAP.MACAddress == nil || *dstAAP.MACAddress == "" {
- dstAAP.MACAddress = prevAAP.MACAddress
- }
+ optional.RestoreString(&prevAAP.MACAddress, &dstAAP.MACAddress)
}
}
@@ -395,6 +439,14 @@ func Convert_v1beta1_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityRef
// 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")
}
diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go
index 8b070e14bf..e2ae6041c7 100644
--- a/api/v1alpha7/zz_generated.conversion.go
+++ b/api/v1alpha7/zz_generated.conversion.go
@@ -381,6 +381,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); 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.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 {
@@ -451,6 +456,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); 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
}
@@ -664,7 +674,7 @@ func Convert_v1beta1_BlockDeviceVolume_To_v1alpha7_BlockDeviceVolume(in *v1beta1
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_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil {
+ if err := Convert_v1alpha7_SubnetFilter_To_v1beta1_SubnetParam(&in.Subnet, &out.Subnet, s); err != nil {
return err
}
return nil
@@ -677,7 +687,7 @@ func Convert_v1alpha7_ExternalRouterIPParam_To_v1beta1_ExternalRouterIPParam(in
func autoConvert_v1beta1_ExternalRouterIPParam_To_v1alpha7_ExternalRouterIPParam(in *v1beta1.ExternalRouterIPParam, out *ExternalRouterIPParam, s conversion.Scope) error {
out.FixedIP = in.FixedIP
- if err := Convert_v1beta1_SubnetFilter_To_v1alpha7_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil {
+ if err := Convert_v1beta1_SubnetParam_To_v1alpha7_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil {
return err
}
return nil
@@ -691,8 +701,8 @@ func Convert_v1beta1_ExternalRouterIPParam_To_v1alpha7_ExternalRouterIPParam(in
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.SubnetFilter)
- if err := Convert_v1alpha7_SubnetFilter_To_v1beta1_SubnetFilter(*in, *out, s); err != nil {
+ *out = new(v1beta1.SubnetParam)
+ if err := Convert_v1alpha7_SubnetFilter_To_v1beta1_SubnetParam(*in, *out, s); err != nil {
return err
}
} else {
@@ -713,7 +723,7 @@ func autoConvert_v1beta1_FixedIP_To_v1alpha7_FixedIP(in *v1beta1.FixedIP, out *F
if in.Subnet != nil {
in, out := &in.Subnet, &out.Subnet
*out = new(SubnetFilter)
- if err := Convert_v1beta1_SubnetFilter_To_v1alpha7_SubnetFilter(*in, *out, s); err != nil {
+ if err := Convert_v1beta1_SubnetParam_To_v1alpha7_SubnetFilter(*in, *out, s); err != nil {
return err
}
} else {
@@ -1783,7 +1793,7 @@ func autoConvert_v1alpha7_SubnetFilter_To_v1beta1_SubnetFilter(in *SubnetFilter,
out.CIDR = in.CIDR
out.IPv6AddressMode = in.IPv6AddressMode
out.IPv6RAMode = in.IPv6RAMode
- out.ID = in.ID
+ // 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
@@ -1800,7 +1810,6 @@ func autoConvert_v1beta1_SubnetFilter_To_v1alpha7_SubnetFilter(in *v1beta1.Subne
out.CIDR = in.CIDR
out.IPv6AddressMode = in.IPv6AddressMode
out.IPv6RAMode = in.IPv6RAMode
- out.ID = in.ID
// WARNING: in.FilterByNeutronTags requires manual conversion: does not exist in peer-type
return nil
}
diff --git a/api/v1beta1/openstackcluster_types.go b/api/v1beta1/openstackcluster_types.go
index 35a2bf5505..b1566c01ac 100644
--- a/api/v1beta1/openstackcluster_types.go
+++ b/api/v1beta1/openstackcluster_types.go
@@ -58,7 +58,7 @@ type OpenStackClusterSpec struct {
// +kubebuilder:validation:MaxItems=2
// +listType=atomic
// +optional
- Subnets []SubnetFilter `json:"subnets,omitempty"`
+ 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.
diff --git a/api/v1beta1/types.go b/api/v1beta1/types.go
index 34633a9261..0fe2f4a1f7 100644
--- a/api/v1beta1/types.go
+++ b/api/v1beta1/types.go
@@ -48,7 +48,7 @@ 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 SubnetFilter `json:"subnet"`
+ Subnet SubnetParam `json:"subnet"`
}
// NeutronTag represents a tag on a Neutron resource.
@@ -85,7 +85,7 @@ type FilterByNeutronTags struct {
}
func (f *FilterByNeutronTags) IsZero() bool {
- return f == nil || len(f.Tags) == 0 && len(f.TagsAny) == 0 && len(f.NotTags) == 0 && len(f.NotTagsAny) == 0
+ return f == nil || (len(f.Tags) == 0 && len(f.TagsAny) == 0 && len(f.NotTags) == 0 && len(f.NotTagsAny) == 0)
}
type SecurityGroupFilter struct {
@@ -131,6 +131,22 @@ func (networkFilter *NetworkFilter) IsZero() bool {
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"`
@@ -140,11 +156,25 @@ type SubnetFilter struct {
CIDR string `json:"cidr,omitempty"`
IPv6AddressMode string `json:"ipv6AddressMode,omitempty"`
IPv6RAMode string `json:"ipv6RAMode,omitempty"`
- ID string `json:"id,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()
+}
+
type RouterFilter struct {
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
@@ -335,7 +365,7 @@ 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 *SubnetFilter `json:"subnet,omitempty"`
+ 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
diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go
index bc21785a3b..6255ef3438 100644
--- a/api/v1beta1/zz_generated.deepcopy.go
+++ b/api/v1beta1/zz_generated.deepcopy.go
@@ -284,7 +284,7 @@ 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 {
@@ -566,7 +566,7 @@ func (in *OpenStackClusterSpec) DeepCopyInto(out *OpenStackClusterSpec) {
}
if in.Subnets != nil {
in, out := &in.Subnets, &out.Subnets
- *out = make([]SubnetFilter, len(*in))
+ *out = make([]SubnetParam, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
@@ -1551,6 +1551,31 @@ 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
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 f8146a4dc0..2a0546bb8c 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -5140,78 +5140,90 @@ spec:
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:
- cidr:
- type: string
- description:
- type: string
- gatewayIP:
- type: string
+ 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
- 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
type: object
type: array
@@ -5761,78 +5773,89 @@ spec:
subnet:
description: The subnet in which the FixedIP is used for the
Gateway of this router
+ maxProperties: 1
+ minProperties: 1
properties:
- cidr:
- type: string
- description:
- type: string
- gatewayIP:
- type: string
+ 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
- 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
required:
- subnet
@@ -6157,78 +6180,90 @@ spec:
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:
- cidr:
- type: string
- description:
- type: string
- gatewayIP:
- type: string
+ 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
- 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
maxItems: 2
type: array
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 72e9aabe49..1eaba9daf1 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -2570,78 +2570,90 @@ spec:
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:
- cidr:
- type: string
- description:
- type: string
- gatewayIP:
- type: string
+ 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
- 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
type: object
type: array
@@ -3197,78 +3209,89 @@ spec:
subnet:
description: The subnet in which the FixedIP is used
for the Gateway of this router
+ maxProperties: 1
+ minProperties: 1
properties:
- cidr:
- type: string
- description:
- type: string
- gatewayIP:
- type: string
+ 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
- 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
required:
- subnet
@@ -3596,78 +3619,92 @@ spec:
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:
- cidr:
- type: string
- description:
- type: string
- gatewayIP:
- type: string
+ 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
- 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
maxItems: 2
type: array
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 bc3d9658b0..c0463608c0 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
@@ -1918,78 +1918,89 @@ spec:
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:
- cidr:
- type: string
- description:
- type: string
- gatewayIP:
- type: string
+ 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
- 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
type: object
type: array
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 7c481ff2b8..2407fa4a06 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
@@ -1594,78 +1594,90 @@ spec:
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:
- cidr:
- type: string
- description:
- type: string
- gatewayIP:
- type: string
+ 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
- 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
type: object
type: array
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index 9c6e091254..c9283f11b7 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -885,9 +885,9 @@ func getClusterSubnets(networkingService *networking.Service, openStackCluster *
}
} else {
for subnet := range openStackClusterSubnets {
- filteredSubnet, err := networkingService.GetNetworkSubnetByFilter(networkID, &openStackClusterSubnets[subnet])
+ filteredSubnet, err := networkingService.GetNetworkSubnetByParam(networkID, &openStackClusterSubnets[subnet])
if err != nil {
- err = fmt.Errorf("failed to find subnet: %w", err)
+ err = fmt.Errorf("failed to find subnet %d in network %s: %w", subnet, networkID, err)
if errors.Is(err, networking.ErrFilterMatch) {
handleUpdateOSCError(openStackCluster, err)
}
diff --git a/controllers/openstackcluster_controller_test.go b/controllers/openstackcluster_controller_test.go
index 7f2aa20f1b..0b6fe63784 100644
--- a/controllers/openstackcluster_controller_test.go
+++ b/controllers/openstackcluster_controller_test.go
@@ -595,9 +595,9 @@ var _ = Describe("OpenStackCluster controller", func() {
Network: &infrav1.NetworkParam{
ID: pointer.String(clusterNetworkID),
},
- Subnets: []infrav1.SubnetFilter{
- {ID: clusterSubnets[0]},
- {ID: clusterSubnets[1]},
+ Subnets: []infrav1.SubnetParam{
+ {ID: &clusterSubnets[0]},
+ {ID: &clusterSubnets[1]},
},
}
testCluster.Status = infrav1.OpenStackClusterStatus{
@@ -636,15 +636,17 @@ var _ = Describe("OpenStackCluster controller", func() {
}, nil)
networkClientRecorder.GetSubnet(clusterSubnets[0]).Return(&subnets.Subnet{
- ID: clusterSubnets[0],
- Name: "cluster-subnet",
- CIDR: "192.168.0.0/24",
+ 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],
- Name: "cluster-subnet-v6",
- CIDR: "2001:db8:2222:5555::/64",
+ ID: clusterSubnets[1],
+ NetworkID: clusterNetworkID,
+ Name: "cluster-subnet-v6",
+ CIDR: "2001:db8:2222:5555::/64",
}, nil)
err = reconcileNetworkComponents(scope, capiCluster, testCluster)
@@ -661,8 +663,8 @@ var _ = Describe("OpenStackCluster controller", func() {
DisableAPIServerFloatingIP: pointer.Bool(true),
APIServerFixedIP: pointer.String("10.0.0.1"),
DisableExternalNetwork: pointer.Bool(true),
- Subnets: []infrav1.SubnetFilter{
- {ID: clusterSubnetID},
+ Subnets: []infrav1.SubnetParam{
+ {ID: pointer.String(clusterSubnetID)},
},
}
err := k8sClient.Create(ctx, testCluster)
diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md
index 527bf24ed0..24c303f15e 100644
--- a/docs/book/src/api/v1beta1/api.md
+++ b/docs/book/src/api/v1beta1/api.md
@@ -117,8 +117,8 @@ are specified.
subnets
-
-[]SubnetFilter
+
+[]SubnetParam
|
@@ -1435,8 +1435,8 @@ string
subnet
-
-SubnetFilter
+
+SubnetParam
|
@@ -1548,8 +1548,8 @@ which contain any of the given tags will be excluded from the result.
subnet
-
-SubnetFilter
+
+SubnetParam
|
@@ -2093,8 +2093,8 @@ are specified.
subnets
-
-[]SubnetFilter
+
+[]SubnetParam
|
@@ -2675,8 +2675,8 @@ are specified.
subnets
-
-[]SubnetFilter
+
+[]SubnetParam
|
@@ -4804,11 +4804,10 @@ string
(Appears on:
-ExternalRouterIPParam,
-FixedIP,
-OpenStackClusterSpec)
+SubnetParam)
+
SubnetFilter specifies a filter to select a subnet. At least one parameter must be specified.
@@ -4900,27 +4899,64 @@ string
+FilterByNeutronTags
+
+
+FilterByNeutronTags
+
+
+ |
+
+
+(Members of FilterByNeutronTags are embedded into this type.)
+
+ |
+
+
+
+SubnetParam
+
+
+(Appears on:
+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.
|
-FilterByNeutronTags
+filter
-
-FilterByNeutronTags
+
+SubnetFilter
|
-
-(Members of FilterByNeutronTags are embedded into this type.)
-
+(Optional)
+Filter specifies a filter to select the subnet. It must match exactly one subnet.
|
diff --git a/pkg/cloud/services/networking/network.go b/pkg/cloud/services/networking/network.go
index 4192d05e35..716750e026 100644
--- a/pkg/cloud/services/networking/network.go
+++ b/pkg/cloud/services/networking/network.go
@@ -371,34 +371,51 @@ func (s *Service) GetSubnetsByFilter(opts subnets.ListOptsBuilder) ([]subnets.Su
return subnetList, nil
}
-// GetSubnetByFilter gets a single subnet specified by the given SubnetFilter.
-// It returns an ErrFilterMatch if no or multiple subnets are found.
-func (s *Service) GetSubnetByFilter(filter *infrav1.SubnetFilter) (*subnets.Subnet, error) {
- listOpts := filterconvert.SubnetFilterToListOpts(filter)
- return s.getSubnetByFilter(listOpts)
+// GetSubnetIDByParam gets the id of a subnet from the given SubnetParam. It
+// does not make any OpenStack API calls if the subnet is specified by ID.
+func (s *Service) GetSubnetIDByParam(param *infrav1.SubnetParam) (string, error) {
+ if param.ID != nil {
+ return *param.ID, nil
+ }
+ subnet, err := s.GetSubnetByParam(param)
+ if err != nil {
+ return "", err
+ }
+ return subnet.ID, nil
}
-// GetNetworkSubnetByFilter gets a single subnet of the given network, specified by the given SubnetFilter.
+// GetSubnetByParam gets a single subnet specified by the given SubnetParam
// It returns an ErrFilterMatch if no or multiple subnets are found.
-func (s *Service) GetNetworkSubnetByFilter(networkID string, filter *infrav1.SubnetFilter) (*subnets.Subnet, error) {
- listOpts := filterconvert.SubnetFilterToListOpts(filter)
- listOpts.NetworkID = networkID
-
- return s.getSubnetByFilter(listOpts)
+func (s *Service) GetSubnetByParam(param *infrav1.SubnetParam) (*subnets.Subnet, error) {
+ return s.GetNetworkSubnetByParam("", param)
}
-// getSubnetByFilter gets a single subnet specified by the given gophercloud ListOpts.
+// GetNetworkSubnetByParam gets a single subnet of the given network, specified by the given SubnetParam.
// It returns an ErrFilterMatch if no or multiple subnets are found.
-func (s *Service) getSubnetByFilter(listOpts subnets.ListOpts) (*subnets.Subnet, error) {
- // If the ID is set, we can just get the subnet by ID.
- if listOpts.ID != "" {
- subnet, err := s.client.GetSubnet(listOpts.ID)
+func (s *Service) GetNetworkSubnetByParam(networkID string, param *infrav1.SubnetParam) (*subnets.Subnet, error) {
+ if param.ID != nil {
+ subnet, err := s.client.GetSubnet(*param.ID)
if capoerrors.IsNotFound(err) {
return nil, ErrNoMatches
}
+
+ if networkID != "" && subnet.NetworkID != networkID {
+ s.scope.Logger().V(4).Info("Subnet specified by ID does not belong to the given network", "subnetID", subnet.ID, "networkID", networkID)
+ return nil, ErrNoMatches
+ }
return subnet, err
}
+ if param.Filter == nil {
+ // Should have been caught by validation
+ return nil, errors.New("subnet filter: both id and filter are nil")
+ }
+
+ listOpts := filterconvert.SubnetFilterToListOpts(param.Filter)
+ if networkID != "" {
+ listOpts.NetworkID = networkID
+ }
+
subnets, err := s.GetSubnetsByFilter(listOpts)
if err != nil {
return nil, err
diff --git a/pkg/cloud/services/networking/port.go b/pkg/cloud/services/networking/port.go
index 8677b87a04..e75a650265 100644
--- a/pkg/cloud/services/networking/port.go
+++ b/pkg/cloud/services/networking/port.go
@@ -493,7 +493,7 @@ func (s *Service) normalizePortTarget(port *infrav1.PortOpts, defaultNetwork *in
continue
}
- subnet, err := s.GetSubnetByFilter(fixedIP.Subnet)
+ subnet, err := s.GetSubnetByParam(fixedIP.Subnet)
if err != nil {
// Multiple matches might be ok later when we restrict matches to a single network
if errors.Is(err, ErrMultipleMatches) {
@@ -526,7 +526,7 @@ func (s *Service) normalizePortTarget(port *infrav1.PortOpts, defaultNetwork *in
resolvedFixedIP := &resolvedFixedIPs[i]
resolvedFixedIP.IPAddress = fixedIP.IPAddress
if fixedIP.Subnet != nil && resolvedFixedIP.SubnetID == nil {
- subnet, err := s.GetNetworkSubnetByFilter(networkID, fixedIP.Subnet)
+ subnet, err := s.GetNetworkSubnetByParam(networkID, fixedIP.Subnet)
if err != nil {
return "", nil, err
}
diff --git a/pkg/cloud/services/networking/port_test.go b/pkg/cloud/services/networking/port_test.go
index 8fb6e035b2..ea0b6f3816 100644
--- a/pkg/cloud/services/networking/port_test.go
+++ b/pkg/cloud/services/networking/port_test.go
@@ -526,8 +526,8 @@ func TestService_ConstructPorts(t *testing.T) {
{
FixedIPs: []infrav1.FixedIP{
{
- Subnet: &infrav1.SubnetFilter{
- ID: subnetID1,
+ Subnet: &infrav1.SubnetParam{
+ ID: pointer.String(subnetID1),
},
},
},
@@ -558,8 +558,8 @@ func TestService_ConstructPorts(t *testing.T) {
{
FixedIPs: []infrav1.FixedIP{
{
- Subnet: &infrav1.SubnetFilter{
- Name: "test-subnet",
+ Subnet: &infrav1.SubnetParam{
+ Filter: &infrav1.SubnetFilter{Name: "test-subnet"},
},
},
},
@@ -594,8 +594,8 @@ func TestService_ConstructPorts(t *testing.T) {
{
FixedIPs: []infrav1.FixedIP{
{
- Subnet: &infrav1.SubnetFilter{
- Name: "test-subnet",
+ Subnet: &infrav1.SubnetParam{
+ Filter: &infrav1.SubnetFilter{Name: "test-subnet"},
},
},
},
@@ -614,8 +614,8 @@ func TestService_ConstructPorts(t *testing.T) {
{
FixedIPs: []infrav1.FixedIP{
{
- Subnet: &infrav1.SubnetFilter{
- Name: "test-subnet",
+ Subnet: &infrav1.SubnetParam{
+ Filter: &infrav1.SubnetFilter{Name: "test-subnet"},
},
},
},
@@ -637,13 +637,13 @@ func TestService_ConstructPorts(t *testing.T) {
{
FixedIPs: []infrav1.FixedIP{
{
- Subnet: &infrav1.SubnetFilter{
- Name: "test-subnet1",
+ Subnet: &infrav1.SubnetParam{
+ Filter: &infrav1.SubnetFilter{Name: "test-subnet1"},
},
},
{
- Subnet: &infrav1.SubnetFilter{
- Name: "test-subnet2",
+ Subnet: &infrav1.SubnetParam{
+ Filter: &infrav1.SubnetFilter{Name: "test-subnet2"},
},
},
},
diff --git a/pkg/cloud/services/networking/router.go b/pkg/cloud/services/networking/router.go
index e6267fdb30..7940222f74 100644
--- a/pkg/cloud/services/networking/router.go
+++ b/pkg/cloud/services/networking/router.go
@@ -168,13 +168,9 @@ func (s *Service) setRouterExternalIPs(openStackCluster *infrav1.OpenStackCluste
for i := range openStackCluster.Spec.ExternalRouterIPs {
externalRouterIP := openStackCluster.Spec.ExternalRouterIPs[i]
- subnetID := externalRouterIP.Subnet.ID
- if subnetID == "" {
- subnet, err := s.GetSubnetByFilter(&externalRouterIP.Subnet)
- if err != nil {
- return fmt.Errorf("failed to get subnet for external router: %w", err)
- }
- subnetID = subnet.ID
+ subnetID, err := s.GetSubnetIDByParam(&externalRouterIP.Subnet)
+ if err != nil {
+ return fmt.Errorf("failed to get subnet for external router: %w", err)
}
updateOpts.GatewayInfo.ExternalFixedIPs = append(updateOpts.GatewayInfo.ExternalFixedIPs, routers.ExternalFixedIP{
IPAddress: externalRouterIP.FixedIP,
diff --git a/pkg/utils/filterconvert/convert.go b/pkg/utils/filterconvert/convert.go
index 01ce2126ec..c1194b7880 100644
--- a/pkg/utils/filterconvert/convert.go
+++ b/pkg/utils/filterconvert/convert.go
@@ -55,7 +55,6 @@ func SubnetFilterToListOpts(subnetFilter *infrav1.SubnetFilter) subnets.ListOpts
CIDR: subnetFilter.CIDR,
IPv6AddressMode: subnetFilter.IPv6AddressMode,
IPv6RAMode: subnetFilter.IPv6RAMode,
- ID: subnetFilter.ID,
Tags: infrav1.JoinTags(subnetFilter.Tags),
TagsAny: infrav1.JoinTags(subnetFilter.TagsAny),
NotTags: infrav1.JoinTags(subnetFilter.NotTags),
diff --git a/test/e2e/suites/apivalidations/filters_test.go b/test/e2e/suites/apivalidations/filters_test.go
index aa8691df0e..ce0b38637b 100644
--- a/test/e2e/suites/apivalidations/filters_test.go
+++ b/test/e2e/suites/apivalidations/filters_test.go
@@ -61,16 +61,18 @@ var _ = Describe("Filter API validations", func() {
for i := range tags {
port := &ports[i]
port.Network = &infrav1.NetworkParam{Filter: &infrav1.NetworkFilter{FilterByNeutronTags: tags[i]}}
- port.FixedIPs = []infrav1.FixedIP{{Subnet: &infrav1.SubnetFilter{FilterByNeutronTags: tags[i]}}}
+ port.FixedIPs = []infrav1.FixedIP{{Subnet: &infrav1.SubnetParam{
+ Filter: &infrav1.SubnetFilter{FilterByNeutronTags: tags[i]},
+ }}}
port.SecurityGroups = []infrav1.SecurityGroupFilter{{FilterByNeutronTags: tags[i]}}
}
Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "OpenStackMachine creation should succeed")
// Maximum of 2 subnets are supported
nSubnets := min(len(tags), 2)
- subnets := make([]infrav1.SubnetFilter, nSubnets)
+ subnets := make([]infrav1.SubnetParam, nSubnets)
for i := 0; i < nSubnets; i++ {
- subnets[i].FilterByNeutronTags = tags[i]
+ subnets[i].Filter = &infrav1.SubnetFilter{FilterByNeutronTags: tags[i]}
}
cluster.Spec.Subnets = subnets
if len(tags) > 0 {
@@ -114,7 +116,9 @@ var _ = Describe("Filter API validations", func() {
{
machine := machine.DeepCopy()
machine.Spec.Ports = []infrav1.PortOpts{
- {FixedIPs: []infrav1.FixedIP{{Subnet: &infrav1.SubnetFilter{FilterByNeutronTags: tags[i]}}}},
+ {FixedIPs: []infrav1.FixedIP{{Subnet: &infrav1.SubnetParam{
+ Filter: &infrav1.SubnetFilter{FilterByNeutronTags: tags[i]},
+ }}}},
}
Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail with invalid port subnet neutron tags")
}
@@ -132,7 +136,7 @@ var _ = Describe("Filter API validations", func() {
{
cluster := cluster.DeepCopy()
- cluster.Spec.Subnets = []infrav1.SubnetFilter{{FilterByNeutronTags: tag}}
+ cluster.Spec.Subnets = []infrav1.SubnetParam{{Filter: &infrav1.SubnetFilter{FilterByNeutronTags: tag}}}
Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should fail with invalid subnet neutron tags")
}
@@ -261,4 +265,46 @@ var _ = Describe("Filter API validations", func() {
Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should fail")
})
})
+
+ Context("SubnetParam", func() {
+ It("should allow setting ID", func() {
+ cluster.Spec.Subnets = []infrav1.SubnetParam{
+ {ID: pointer.String("06c32c52-f207-4f6a-a769-bbcbe5a43f5c")},
+ }
+ Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
+ })
+
+ It("should allow setting non-empty Filter", func() {
+ cluster.Spec.Subnets = []infrav1.SubnetParam{
+ {Filter: &infrav1.SubnetFilter{Name: "foo"}},
+ }
+ Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
+ })
+
+ It("should not allow setting empty SubnetParam", func() {
+ cluster.Spec.Subnets = []infrav1.SubnetParam{{}}
+ Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should fail")
+ })
+
+ It("should not allow setting invalid id", func() {
+ cluster.Spec.Subnets = []infrav1.SubnetParam{
+ {ID: pointer.String("foo")},
+ }
+ Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should fail")
+ })
+
+ It("should not allow setting empty Filter", func() {
+ cluster.Spec.Subnets = []infrav1.SubnetParam{
+ {Filter: &infrav1.SubnetFilter{}},
+ }
+ Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should fail")
+ })
+
+ It("should not allow setting both ID and Filter", func() {
+ cluster.Spec.Subnets = []infrav1.SubnetParam{
+ {ID: pointer.String("06c32c52-f207-4f6a-a769-bbcbe5a43f5c"), Filter: &infrav1.SubnetFilter{Name: "foo"}},
+ }
+ Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should fail")
+ })
+ })
})
diff --git a/test/helpers/fuzzerfuncs.go b/test/helpers/fuzzerfuncs.go
index da35973632..35720fcdd1 100644
--- a/test/helpers/fuzzerfuncs.go
+++ b/test/helpers/fuzzerfuncs.go
@@ -75,7 +75,7 @@ func InfraV1FuzzerFuncs() []interface{} {
// length 1, but we need to also test length 2.
// Ensure it is occasionally generated.
if len(spec.Subnets) == 1 && c.RandBool() {
- subnet := infrav1.SubnetFilter{}
+ subnet := infrav1.SubnetParam{}
c.Fuzz(&subnet)
spec.Subnets = append(spec.Subnets, subnet)
}
@@ -129,9 +129,13 @@ func InfraV1FuzzerFuncs() []interface{} {
filter.NotTagsAny = filterInvalidTags(filter.NotTagsAny)
},
- // v1beta1 network param contains exactly one of ID or filter
+ // v1beta1 filter params contain exactly one of ID or filter
func(param *infrav1.NetworkParam, c fuzz.Continue) {
fuzzFilterParam(¶m.ID, ¶m.Filter, c)
},
+
+ func(param *infrav1.SubnetParam, c fuzz.Continue) {
+ fuzzFilterParam(¶m.ID, ¶m.Filter, c)
+ },
}
}
From 3cea05d2f3bb80d74ecd04104621a143059e9818 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Thu, 28 Mar 2024 21:02:08 +0000
Subject: [PATCH 151/180] Add fuzz tests for v1alpha5 conversion
Unlike the v1alpha6 and v1alpha7 tests, these only test if the
conversion causes a panic. It found 1 panic, which is also fixed here.
---
api/v1alpha5/conversion.go | 8 +++-
api/v1alpha5/conversion_test.go | 72 +++++++++++++++++++++++++++++++++
2 files changed, 79 insertions(+), 1 deletion(-)
diff --git a/api/v1alpha5/conversion.go b/api/v1alpha5/conversion.go
index 19397b6956..b5d0cf0ff3 100644
--- a/api/v1alpha5/conversion.go
+++ b/api/v1alpha5/conversion.go
@@ -456,6 +456,10 @@ func Convert_v1alpha5_Instance_To_v1beta1_BastionStatus(in *Instance, out *infra
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
}
@@ -468,7 +472,9 @@ func Convert_v1beta1_BastionStatus_To_v1alpha5_Instance(in *infrav1.BastionStatu
out.State = InstanceState(in.State)
out.IP = in.IP
out.FloatingIP = in.FloatingIP
- out.ServerGroupID = in.Resolved.ServerGroupID
+ if in.Resolved != nil {
+ out.ServerGroupID = in.Resolved.ServerGroupID
+ }
return nil
}
diff --git a/api/v1alpha5/conversion_test.go b/api/v1alpha5/conversion_test.go
index 7fbf79bda6..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/v1beta1"
+ testhelpers "sigs.k8s.io/cluster-api-provider-openstack/test/helpers"
)
func TestConvertFrom(t *testing.T) {
@@ -165,3 +171,69 @@ func TestConvert_v1alpha5_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(t
})
}
}
+
+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)
+}
From 865933dc4087ba80a49a3f289f2396c9d93ec2bf Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Wed, 27 Mar 2024 15:19:00 +0000
Subject: [PATCH 152/180] SecurityGroupFilter to SecurityGroupParam
---
api/v1alpha5/conversion.go | 83 +++---
api/v1alpha5/zz_generated.conversion.go | 32 ++-
api/v1alpha6/conversion_test.go | 16 +-
api/v1alpha6/openstackmachine_conversion.go | 6 +
api/v1alpha6/types_conversion.go | 99 +++----
api/v1alpha6/zz_generated.conversion.go | 40 ++-
api/v1alpha7/openstackmachine_conversion.go | 10 +
api/v1alpha7/types_conversion.go | 70 ++++-
api/v1alpha7/zz_generated.conversion.go | 19 +-
api/v1beta1/openstackmachine_types.go | 2 +-
api/v1beta1/types.go | 29 +-
api/v1beta1/zz_generated.deepcopy.go | 29 +-
...re.cluster.x-k8s.io_openstackclusters.yaml | 266 +++++++++--------
...er.x-k8s.io_openstackclustertemplates.yaml | 269 ++++++++++--------
...re.cluster.x-k8s.io_openstackmachines.yaml | 264 +++++++++--------
...er.x-k8s.io_openstackmachinetemplates.yaml | 266 +++++++++--------
.../openstackmachine_controller_test.go | 2 +-
docs/book/src/api/v1beta1/api.md | 76 +++--
pkg/cloud/services/networking/port_test.go | 12 +-
.../services/networking/securitygroups.go | 18 +-
pkg/utils/filterconvert/convert.go | 1 -
.../e2e/suites/apivalidations/filters_test.go | 54 +++-
test/e2e/suites/e2e/e2e_test.go | 2 +-
test/helpers/fuzzerfuncs.go | 4 +
24 files changed, 1015 insertions(+), 654 deletions(-)
diff --git a/api/v1alpha5/conversion.go b/api/v1alpha5/conversion.go
index b5d0cf0ff3..50944701eb 100644
--- a/api/v1alpha5/conversion.go
+++ b/api/v1alpha5/conversion.go
@@ -325,13 +325,8 @@ func Convert_v1beta1_PortOpts_To_v1alpha5_PortOpts(in *infrav1.PortOpts, out *Po
if len(in.SecurityGroups) > 0 {
out.SecurityGroupFilters = make([]SecurityGroupParam, len(in.SecurityGroups))
for i := range in.SecurityGroups {
- securityGroupParam := &out.SecurityGroupFilters[i]
- if in.SecurityGroups[i].ID != "" {
- securityGroupParam.UUID = in.SecurityGroups[i].ID
- } else {
- if err := Convert_v1beta1_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(&in.SecurityGroups[i], &securityGroupParam.Filter, s); err != nil {
- return err
- }
+ if err := Convert_v1beta1_SecurityGroupParam_To_v1alpha5_SecurityGroupParam(&in.SecurityGroups[i], &out.SecurityGroupFilters[i], s); err != nil {
+ return err
}
}
}
@@ -395,46 +390,48 @@ func Convert_v1alpha5_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *infrav1.Po
}
if len(in.SecurityGroups) > 0 || len(in.SecurityGroupFilters) > 0 {
- out.SecurityGroups = make([]infrav1.SecurityGroupFilter, 0, len(in.SecurityGroups)+len(in.SecurityGroupFilters))
+ 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.SecurityGroupFilter{ID: sgParam.UUID})
+ out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupParam{ID: &sgParam.UUID})
case sgParam.Name != "":
- out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupFilter{Name: 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.SecurityGroupFilter{})
+ out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupParam{})
outSG := &out.SecurityGroups[len(out.SecurityGroups)-1]
- if err := Convert_v1alpha5_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(&sgParam.Filter, outSG, s); err != nil {
+ outSG.Filter = &infrav1.SecurityGroupFilter{}
+ if err := Convert_v1alpha5_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(&sgParam.Filter, outSG.Filter, s); err != nil {
return err
}
}
}
- for _, id := range in.SecurityGroups {
- out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupFilter{ID: id})
+ 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.SecurityGroupFilter, 0, len(in.SecurityGroups)+len(in.SecurityGroupFilters))
+ 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.SecurityGroupFilter{ID: sgParam.UUID})
+ out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupParam{ID: &sgParam.UUID})
case sgParam.Name != "":
- out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupFilter{Name: 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.SecurityGroupFilter{})
+ out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupParam{})
outSG := &out.SecurityGroups[len(out.SecurityGroups)-1]
- if err := Convert_v1alpha5_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(&sgParam.Filter, outSG, s); err != nil {
+ outSG.Filter = &infrav1.SecurityGroupFilter{}
+ if err := Convert_v1alpha5_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(&sgParam.Filter, outSG.Filter, s); err != nil {
return err
}
}
}
- for _, id := range in.SecurityGroups {
- out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupFilter{ID: id})
+ for i := range in.SecurityGroups {
+ out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupParam{ID: &in.SecurityGroups[i]})
}
}
@@ -521,34 +518,40 @@ func Convert_v1beta1_NetworkStatus_To_v1alpha5_Network(in *infrav1.NetworkStatus
return nil
}
-func Convert_v1alpha5_SecurityGroupParam_To_v1beta1_SecurityGroupFilter(in *SecurityGroupParam, out *infrav1.SecurityGroupFilter, s conversion.Scope) error {
- // SecurityGroupParam is replaced by its contained SecurityGroupFilter in v1beta1
- err := Convert_v1alpha5_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(&in.Filter, 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
+ out.ID = &in.UUID
+ return nil
}
+
+ outFilter := &infrav1.SecurityGroupFilter{}
if in.Name != "" {
- out.Name = 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_v1beta1_SecurityGroupFilter_To_v1alpha5_SecurityGroupParam(in *infrav1.SecurityGroupFilter, out *SecurityGroupParam, s conversion.Scope) error {
- // SecurityGroupParam is replaced by its contained SecurityGroupFilter in v1beta1
- err := Convert_v1beta1_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(in, &out.Filter, 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.ID != "" {
- out.UUID = in.ID
- }
- 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
}
diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go
index 8d24ce309a..2a335b80c5 100644
--- a/api/v1alpha5/zz_generated.conversion.go
+++ b/api/v1alpha5/zz_generated.conversion.go
@@ -302,8 +302,8 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddConversionFunc((*SecurityGroupParam)(nil), (*v1beta1.SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha5_SecurityGroupParam_To_v1beta1_SecurityGroupFilter(a.(*SecurityGroupParam), b.(*v1beta1.SecurityGroupFilter), 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
}
@@ -407,8 +407,8 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddConversionFunc((*v1beta1.SecurityGroupFilter)(nil), (*SecurityGroupParam)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1beta1_SecurityGroupFilter_To_v1alpha5_SecurityGroupParam(a.(*v1beta1.SecurityGroupFilter), b.(*SecurityGroupParam), 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
}
@@ -1161,9 +1161,9 @@ func autoConvert_v1alpha5_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(i
// 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.SecurityGroupFilter, len(*in))
+ *out = make([]v1beta1.SecurityGroupParam, len(*in))
for i := range *in {
- if err := Convert_v1alpha5_SecurityGroupParam_To_v1beta1_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
}
}
@@ -1209,7 +1209,7 @@ func autoConvert_v1beta1_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(i
in, out := &in.SecurityGroups, &out.SecurityGroups
*out = make([]SecurityGroupParam, len(*in))
for i := range *in {
- if err := Convert_v1beta1_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
}
}
@@ -1453,7 +1453,7 @@ func autoConvert_v1beta1_PortOpts_To_v1alpha5_PortOpts(in *v1beta1.PortOpts, out
in, out := &in.SecurityGroups, &out.SecurityGroups
*out = make([]string, len(*in))
for i := range *in {
- if err := v1alpha6.Convert_v1beta1_SecurityGroupFilter_To_string(&(*in)[i], &(*out)[i], s); err != nil {
+ if err := v1alpha6.Convert_v1beta1_SecurityGroupParam_To_string(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -1517,7 +1517,7 @@ func Convert_v1beta1_Router_To_v1alpha5_Router(in *v1beta1.Router, out *Router,
}
func autoConvert_v1alpha5_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in *SecurityGroupFilter, out *v1beta1.SecurityGroupFilter, s conversion.Scope) error {
- out.ID = in.ID
+ // 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
@@ -1534,7 +1534,6 @@ func autoConvert_v1alpha5_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in
}
func autoConvert_v1beta1_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(in *v1beta1.SecurityGroupFilter, out *SecurityGroupFilter, s conversion.Scope) error {
- out.ID = in.ID
out.Name = in.Name
out.Description = in.Description
out.ProjectID = in.ProjectID
@@ -1542,6 +1541,19 @@ func autoConvert_v1beta1_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(in
return nil
}
+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
+}
+
+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
+}
+
func autoConvert_v1alpha5_Subnet_To_v1beta1_Subnet(in *Subnet, out *v1beta1.Subnet, s conversion.Scope) error {
out.Name = in.Name
out.ID = in.ID
diff --git a/api/v1alpha6/conversion_test.go b/api/v1alpha6/conversion_test.go
index 1456680359..4680ed9c15 100644
--- a/api/v1alpha6/conversion_test.go
+++ b/api/v1alpha6/conversion_test.go
@@ -455,19 +455,19 @@ 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: pointer.String("654cba")},
+ {ID: &uuids[0]},
+ {ID: &uuids[1]},
}
legacyPortProfile := map[string]string{
"capabilities": "[\"switchdev\"]",
diff --git a/api/v1alpha6/openstackmachine_conversion.go b/api/v1alpha6/openstackmachine_conversion.go
index d13eb5c124..d8439d19f1 100644
--- a/api/v1alpha6/openstackmachine_conversion.go
+++ b/api/v1alpha6/openstackmachine_conversion.go
@@ -170,6 +170,12 @@ func restorev1beta1MachineSpec(previous *infrav1.OpenStackMachineSpec, dst *infr
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])
+ }
+ }
}
func convertNetworksToPorts(networks []NetworkParam, s apiconversion.Scope) ([]infrav1.PortOpts, error) {
diff --git a/api/v1alpha6/types_conversion.go b/api/v1alpha6/types_conversion.go
index 1b2a642f34..7b99803d3f 100644
--- a/api/v1alpha6/types_conversion.go
+++ b/api/v1alpha6/types_conversion.go
@@ -41,55 +41,71 @@ func restorev1alpha6SecurityGroupFilter(previous *SecurityGroupFilter, dst *Secu
dst.NotTagsAny = previous.NotTagsAny
}
-func Convert_v1beta1_SecurityGroupFilter_To_string(in *infrav1.SecurityGroupFilter, out *string, _ apiconversion.Scope) error {
- if in.ID != "" {
- *out = in.ID
+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
}
- return nil
}
-func Convert_v1alpha6_SecurityGroupParam_To_v1beta1_SecurityGroupFilter(in *SecurityGroupParam, out *infrav1.SecurityGroupFilter, s apiconversion.Scope) error {
- // SecurityGroupParam is replaced by its contained SecurityGroupFilter in v1beta1
- err := Convert_v1alpha6_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(&in.Filter, out, s)
- if err != nil {
- return err
+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
+ out.ID = &in.UUID
+ return nil
}
+
+ outFilter := &infrav1.SecurityGroupFilter{}
+
if in.Name != "" {
- out.Name = 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_SecurityGroupFilter_To_v1alpha6_SecurityGroupParam(in *infrav1.SecurityGroupFilter, out *SecurityGroupParam, s apiconversion.Scope) error {
- // SecurityGroupParam is replaced by its contained SecurityGroupFilter in v1beta1
- err := Convert_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(in, &out.Filter, s)
- if err != nil {
- return err
+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.ID != "" {
- out.UUID = in.ID
- }
- if in.Name != "" {
- out.Name = in.Name
+ 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 {
- if err := autoConvert_v1alpha6_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in, out, s); err != nil {
+ 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)
-
- // 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
}
@@ -319,24 +335,14 @@ func Convert_v1alpha6_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *infrav1.Po
}
if len(in.SecurityGroups) > 0 || len(in.SecurityGroupFilters) > 0 {
- out.SecurityGroups = make([]infrav1.SecurityGroupFilter, 0, len(in.SecurityGroups)+len(in.SecurityGroupFilters))
+ out.SecurityGroups = make([]infrav1.SecurityGroupParam, 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.SecurityGroupFilter{ID: sgParam.UUID})
- case sgParam.Name != "":
- out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupFilter{Name: sgParam.Name})
- case sgParam.Filter != (SecurityGroupFilter{}):
- out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupFilter{})
- outSG := &out.SecurityGroups[len(out.SecurityGroups)-1]
- if err := Convert_v1alpha6_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(&sgParam.Filter, outSG, s); err != nil {
- return err
- }
+ if err := Convert_v1alpha6_SecurityGroupParam_To_v1beta1_SecurityGroupParam(&in.SecurityGroupFilters[i], &out.SecurityGroups[i], s); err != nil {
+ return err
}
}
- for _, id := range in.SecurityGroups {
- out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupFilter{ID: id})
+ for i := range in.SecurityGroups {
+ out.SecurityGroups[i+len(in.SecurityGroupFilters)] = infrav1.SecurityGroupParam{ID: &in.SecurityGroups[i]}
}
}
@@ -373,13 +379,8 @@ func Convert_v1beta1_PortOpts_To_v1alpha6_PortOpts(in *infrav1.PortOpts, out *Po
if len(in.SecurityGroups) > 0 {
out.SecurityGroupFilters = make([]SecurityGroupParam, len(in.SecurityGroups))
for i := range in.SecurityGroups {
- securityGroupParam := &out.SecurityGroupFilters[i]
- if in.SecurityGroups[i].ID != "" {
- securityGroupParam.UUID = in.SecurityGroups[i].ID
- } else {
- if err := Convert_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(&in.SecurityGroups[i], &securityGroupParam.Filter, s); err != nil {
- return err
- }
+ if err := Convert_v1beta1_SecurityGroupParam_To_v1alpha6_SecurityGroupParam(&in.SecurityGroups[i], &out.SecurityGroupFilters[i], s); err != nil {
+ return err
}
}
}
diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go
index 9862d40792..2b98c9a0d8 100644
--- a/api/v1alpha6/zz_generated.conversion.go
+++ b/api/v1alpha6/zz_generated.conversion.go
@@ -321,8 +321,8 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddConversionFunc((*SecurityGroupParam)(nil), (*v1beta1.SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1alpha6_SecurityGroupParam_To_v1beta1_SecurityGroupFilter(a.(*SecurityGroupParam), b.(*v1beta1.SecurityGroupFilter), 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
}
@@ -411,18 +411,18 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddConversionFunc((*v1beta1.SecurityGroupFilter)(nil), (*string)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1beta1_SecurityGroupFilter_To_string(a.(*v1beta1.SecurityGroupFilter), b.(*string), 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((*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)
+ 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.SecurityGroupFilter)(nil), (*SecurityGroupParam)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupParam(a.(*v1beta1.SecurityGroupFilter), b.(*SecurityGroupParam), scope)
+ 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
}
@@ -1196,9 +1196,9 @@ func autoConvert_v1alpha6_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(i
// 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.SecurityGroupFilter, len(*in))
+ *out = make([]v1beta1.SecurityGroupParam, len(*in))
for i := range *in {
- if err := Convert_v1alpha6_SecurityGroupParam_To_v1beta1_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
}
}
@@ -1244,7 +1244,7 @@ func autoConvert_v1beta1_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(i
in, out := &in.SecurityGroups, &out.SecurityGroups
*out = make([]SecurityGroupParam, len(*in))
for i := range *in {
- if err := Convert_v1beta1_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
}
}
@@ -1489,7 +1489,7 @@ func autoConvert_v1beta1_PortOpts_To_v1alpha6_PortOpts(in *v1beta1.PortOpts, out
in, out := &in.SecurityGroups, &out.SecurityGroups
*out = make([]string, len(*in))
for i := range *in {
- if err := Convert_v1beta1_SecurityGroupFilter_To_string(&(*in)[i], &(*out)[i], s); err != nil {
+ if err := Convert_v1beta1_SecurityGroupParam_To_string(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -1553,7 +1553,7 @@ func Convert_v1beta1_Router_To_v1alpha6_Router(in *v1beta1.Router, out *Router,
}
func autoConvert_v1alpha6_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in *SecurityGroupFilter, out *v1beta1.SecurityGroupFilter, s conversion.Scope) error {
- out.ID = in.ID
+ // 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
@@ -1570,7 +1570,6 @@ func autoConvert_v1alpha6_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in
}
func autoConvert_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(in *v1beta1.SecurityGroupFilter, out *SecurityGroupFilter, s conversion.Scope) error {
- out.ID = in.ID
out.Name = in.Name
out.Description = in.Description
out.ProjectID = in.ProjectID
@@ -1578,6 +1577,19 @@ func autoConvert_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(in
return nil
}
+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
+}
+
+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
+}
+
func autoConvert_v1alpha6_Subnet_To_v1beta1_Subnet(in *Subnet, out *v1beta1.Subnet, s conversion.Scope) error {
out.Name = in.Name
out.ID = in.ID
diff --git a/api/v1alpha7/openstackmachine_conversion.go b/api/v1alpha7/openstackmachine_conversion.go
index fa0655288c..9ce17bbbd3 100644
--- a/api/v1alpha7/openstackmachine_conversion.go
+++ b/api/v1alpha7/openstackmachine_conversion.go
@@ -137,9 +137,19 @@ func restorev1alpha7MachineSpec(previous *OpenStackMachineSpec, dst *OpenStackMa
}
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])
diff --git a/api/v1alpha7/types_conversion.go b/api/v1alpha7/types_conversion.go
index a63cd212ed..f98207a409 100644
--- a/api/v1alpha7/types_conversion.go
+++ b/api/v1alpha7/types_conversion.go
@@ -34,6 +34,13 @@ func restorev1alpha7SecurityGroupFilter(previous *SecurityGroupFilter, dst *Secu
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) {
@@ -44,19 +51,48 @@ func restorev1alpha7SecurityGroup(previous *SecurityGroup, dst *SecurityGroup) {
dst.Rules = previous.Rules
}
-func Convert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in *SecurityGroupFilter, out *infrav1.SecurityGroupFilter, s apiconversion.Scope) error {
- if err := autoConvert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in, out, s); err != nil {
+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, &out.FilterByNeutronTags)
+ infrav1.ConvertAllTagsTo(in.Tags, in.TagsAny, in.NotTags, in.NotTagsAny, &filter.FilterByNeutronTags)
+ if !filter.IsZero() {
+ out.Filter = filter
+ }
return nil
}
-func Convert_v1beta1_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in *infrav1.SecurityGroupFilter, out *SecurityGroupFilter, s apiconversion.Scope) error {
- if err := autoConvert_v1beta1_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in, out, s); err != nil {
- return err
+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)
}
- infrav1.ConvertAllTagsFrom(&in.FilterByNeutronTags, &out.Tags, &out.TagsAny, &out.NotTags, &out.NotTagsAny)
return nil
}
@@ -294,6 +330,12 @@ func restorev1beta1Port(previous *infrav1.PortOpts, dst *infrav1.PortOpts) {
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 {
@@ -334,9 +376,9 @@ func Convert_v1alpha7_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *infrav1.Po
}
if len(in.SecurityGroupFilters) > 0 {
- out.SecurityGroups = make([]infrav1.SecurityGroupFilter, len(in.SecurityGroupFilters))
+ out.SecurityGroups = make([]infrav1.SecurityGroupParam, len(in.SecurityGroupFilters))
for i := range in.SecurityGroupFilters {
- if err := Convert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(&in.SecurityGroupFilters[i], &out.SecurityGroups[i], s); err != nil {
+ if err := Convert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupParam(&in.SecurityGroupFilters[i], &out.SecurityGroups[i], s); err != nil {
return err
}
}
@@ -393,7 +435,7 @@ func Convert_v1beta1_PortOpts_To_v1alpha7_PortOpts(in *infrav1.PortOpts, out *Po
if len(in.SecurityGroups) > 0 {
out.SecurityGroupFilters = make([]SecurityGroupFilter, len(in.SecurityGroups))
for i := range in.SecurityGroups {
- if err := Convert_v1beta1_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(&in.SecurityGroups[i], &out.SecurityGroupFilters[i], s); err != nil {
+ if err := Convert_v1beta1_SecurityGroupParam_To_v1alpha7_SecurityGroupFilter(&in.SecurityGroups[i], &out.SecurityGroupFilters[i], s); err != nil {
return err
}
}
@@ -454,3 +496,11 @@ func Convert_v1alpha7_NetworkFilter_To_v1beta1_NetworkFilter(_ *NetworkFilter, _
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")
+}
diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go
index e2ae6041c7..6e00e14144 100644
--- a/api/v1alpha7/zz_generated.conversion.go
+++ b/api/v1alpha7/zz_generated.conversion.go
@@ -371,6 +371,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); 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 {
@@ -446,6 +451,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); 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 {
@@ -1371,9 +1381,9 @@ func autoConvert_v1alpha7_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(i
// 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.SecurityGroupFilter, len(*in))
+ *out = make([]v1beta1.SecurityGroupParam, len(*in))
for i := range *in {
- if err := Convert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(&(*in)[i], &(*out)[i], s); err != nil {
+ if err := Convert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupParam(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -1420,7 +1430,7 @@ func autoConvert_v1beta1_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(i
in, out := &in.SecurityGroups, &out.SecurityGroups
*out = make([]SecurityGroupFilter, len(*in))
for i := range *in {
- if err := Convert_v1beta1_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(&(*in)[i], &(*out)[i], s); err != nil {
+ if err := Convert_v1beta1_SecurityGroupParam_To_v1alpha7_SecurityGroupFilter(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
@@ -1738,7 +1748,7 @@ func autoConvert_v1beta1_RouterFilter_To_v1alpha7_RouterFilter(in *v1beta1.Route
}
func autoConvert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in *SecurityGroupFilter, out *v1beta1.SecurityGroupFilter, s conversion.Scope) error {
- out.ID = in.ID
+ // WARNING: in.ID requires manual conversion: does not exist in peer-type
out.Name = in.Name
out.Description = in.Description
out.ProjectID = in.ProjectID
@@ -1750,7 +1760,6 @@ func autoConvert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in
}
func autoConvert_v1beta1_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in *v1beta1.SecurityGroupFilter, out *SecurityGroupFilter, s conversion.Scope) error {
- out.ID = in.ID
out.Name = in.Name
out.Description = in.Description
out.ProjectID = in.ProjectID
diff --git a/api/v1beta1/openstackmachine_types.go b/api/v1beta1/openstackmachine_types.go
index f222f71761..5a7b05c319 100644
--- a/api/v1beta1/openstackmachine_types.go
+++ b/api/v1beta1/openstackmachine_types.go
@@ -55,7 +55,7 @@ type OpenStackMachineSpec struct {
Ports []PortOpts `json:"ports,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"`
diff --git a/api/v1beta1/types.go b/api/v1beta1/types.go
index 0fe2f4a1f7..ad67976e96 100644
--- a/api/v1beta1/types.go
+++ b/api/v1beta1/types.go
@@ -88,8 +88,23 @@ 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 {
- ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
ProjectID string `json:"projectID,omitempty"`
@@ -97,6 +112,16 @@ type SecurityGroupFilter struct {
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
@@ -232,7 +257,7 @@ type PortOpts struct {
// 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 []SecurityGroupFilter `json:"securityGroups,omitempty"`
+ 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.
diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go
index 6255ef3438..bbaa79118a 100644
--- a/api/v1beta1/zz_generated.deepcopy.go
+++ b/api/v1beta1/zz_generated.deepcopy.go
@@ -925,7 +925,7 @@ func (in *OpenStackMachineSpec) DeepCopyInto(out *OpenStackMachineSpec) {
}
if in.SecurityGroups != nil {
in, out := &in.SecurityGroups, &out.SecurityGroups
- *out = make([]SecurityGroupFilter, len(*in))
+ *out = make([]SecurityGroupParam, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
@@ -1153,7 +1153,7 @@ func (in *PortOpts) DeepCopyInto(out *PortOpts) {
}
if in.SecurityGroups != nil {
in, out := &in.SecurityGroups, &out.SecurityGroups
- *out = make([]SecurityGroupFilter, len(*in))
+ *out = make([]SecurityGroupParam, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
@@ -1415,6 +1415,31 @@ func (in *SecurityGroupFilter) DeepCopy() *SecurityGroupFilter {
return out
}
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+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
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 2a0546bb8c..c4adc2b0b7 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -5349,68 +5349,84 @@ spec:
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:
- description:
- type: string
+ 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
- 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
type: array
x-kubernetes-list-type: atomic
@@ -5489,68 +5505,82 @@ spec:
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:
- description:
- type: string
+ 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
- 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
type: array
serverGroup:
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 1eaba9daf1..a6943b023a 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -2782,68 +2782,85 @@ spec:
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:
- description:
- type: string
+ 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
- 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
type: array
x-kubernetes-list-type: atomic
@@ -2923,68 +2940,84 @@ spec:
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:
- description:
- type: string
+ 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
- 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
type: array
serverGroup:
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 c0463608c0..40ce3c87fd 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
@@ -2125,68 +2125,82 @@ spec:
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:
- description:
- type: string
+ 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
- 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
type: array
x-kubernetes-list-type: atomic
@@ -2263,68 +2277,82 @@ spec:
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:
- description:
- type: string
+ 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
- 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
type: array
serverGroup:
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 2407fa4a06..e2c222712a 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
@@ -1803,68 +1803,84 @@ spec:
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:
- description:
- type: string
+ 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
- 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
type: array
x-kubernetes-list-type: atomic
@@ -1943,68 +1959,82 @@ spec:
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:
- description:
- type: string
+ 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
- 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
type: array
serverGroup:
diff --git a/controllers/openstackmachine_controller_test.go b/controllers/openstackmachine_controller_test.go
index c941f11d04..d57848f80f 100644
--- a/controllers/openstackmachine_controller_test.go
+++ b/controllers/openstackmachine_controller_test.go
@@ -91,7 +91,7 @@ func getDefaultOpenStackMachine() *infrav1.OpenStackMachine {
{Key: "test-metadata", Value: "test-value"},
},
ConfigDrive: pointer.Bool(true),
- SecurityGroups: []infrav1.SecurityGroupFilter{},
+ SecurityGroups: []infrav1.SecurityGroupParam{},
ServerGroup: &infrav1.ServerGroupFilter{ID: serverGroupUUID},
},
Status: infrav1.OpenStackMachineStatus{
diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md
index 24c303f15e..ecc495a928 100644
--- a/docs/book/src/api/v1beta1/api.md
+++ b/docs/book/src/api/v1beta1/api.md
@@ -626,8 +626,8 @@ If not specified a default port will be added for the default cluster network.
securityGroups
-
-[]SecurityGroupFilter
+
+[]SecurityGroupParam
|
@@ -3140,8 +3140,8 @@ If not specified a default port will be added for the default cluster network.
securityGroups
-
-[]SecurityGroupFilter
+
+[]SecurityGroupParam
|
@@ -3512,8 +3512,8 @@ If not specified a default port will be added for the default cluster network.
securityGroups
-
-[]SecurityGroupFilter
+
+[]SecurityGroupParam
|
@@ -3750,8 +3750,8 @@ string
securityGroups
-
-[]SecurityGroupFilter
+
+[]SecurityGroupParam
|
@@ -4396,10 +4396,10 @@ FilterByNeutronTags
(Appears on:
-OpenStackMachineSpec,
-PortOpts)
+SecurityGroupParam)
+
SecurityGroupFilter specifies a query to select an OpenStack security group. At least one property must be set.
@@ -4411,16 +4411,6 @@ FilterByNeutronTags
-id
-
-string
-
- |
-
- |
-
-
-
name
string
@@ -4466,6 +4456,52 @@ FilterByNeutronTags
|
+SecurityGroupParam
+
+
+(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.
+ |
+
+
+
SecurityGroupRuleSpec
diff --git a/pkg/cloud/services/networking/port_test.go b/pkg/cloud/services/networking/port_test.go
index ea0b6f3816..501f5f39cc 100644
--- a/pkg/cloud/services/networking/port_test.go
+++ b/pkg/cloud/services/networking/port_test.go
@@ -685,8 +685,8 @@ func TestService_ConstructPorts(t *testing.T) {
{
name: "machine spec security groups added to defaults",
spec: infrav1.OpenStackMachineSpec{
- SecurityGroups: []infrav1.SecurityGroupFilter{
- {Name: "test-security-group"},
+ SecurityGroups: []infrav1.SecurityGroupParam{
+ {Filter: &infrav1.SecurityGroupFilter{Name: "test-security-group"}},
},
},
expectNetwork: func(m *mock.MockNetworkClientMockRecorder) {
@@ -710,11 +710,11 @@ func TestService_ConstructPorts(t *testing.T) {
{
name: "port security groups override machine spec security groups",
spec: infrav1.OpenStackMachineSpec{
- SecurityGroups: []infrav1.SecurityGroupFilter{
- {Name: "machine-security-group"},
+ SecurityGroups: []infrav1.SecurityGroupParam{
+ {Filter: &infrav1.SecurityGroupFilter{Name: "machine-security-group"}},
},
Ports: []infrav1.PortOpts{
- {SecurityGroups: []infrav1.SecurityGroupFilter{{Name: "port-security-group"}}},
+ {SecurityGroups: []infrav1.SecurityGroupParam{{Filter: &infrav1.SecurityGroupFilter{Name: "port-security-group"}}}},
},
},
expectNetwork: func(m *mock.MockNetworkClientMockRecorder) {
@@ -758,7 +758,7 @@ func TestService_ConstructPorts(t *testing.T) {
{
name: "managed security group and machine security groups added to port",
spec: infrav1.OpenStackMachineSpec{
- SecurityGroups: []infrav1.SecurityGroupFilter{{Name: "machine-security-group"}},
+ SecurityGroups: []infrav1.SecurityGroupParam{{Filter: &infrav1.SecurityGroupFilter{Name: "machine-security-group"}}},
},
managedSecurityGroup: pointer.String(securityGroupID1),
expectNetwork: func(m *mock.MockNetworkClientMockRecorder) {
diff --git a/pkg/cloud/services/networking/securitygroups.go b/pkg/cloud/services/networking/securitygroups.go
index ecde85fe84..5d159f52a5 100644
--- a/pkg/cloud/services/networking/securitygroups.go
+++ b/pkg/cloud/services/networking/securitygroups.go
@@ -17,6 +17,7 @@ limitations under the License.
package networking
import (
+ "errors"
"fmt"
"slices"
@@ -308,21 +309,26 @@ func validateRemoteManagedGroups(remoteManagedGroups map[string]string, ruleRemo
return nil
}
-func (s *Service) GetSecurityGroups(securityGroupParams []infrav1.SecurityGroupFilter) ([]string, error) {
+func (s *Service) GetSecurityGroups(securityGroupParams []infrav1.SecurityGroupParam) ([]string, error) {
var sgIDs []string
for i := range securityGroupParams {
sg := &securityGroupParams[i]
// Don't validate an explicit UUID if we were given one
- if sg.ID != "" {
- if isDuplicate(sgIDs, sg.ID) {
+ if sg.ID != nil {
+ if isDuplicate(sgIDs, *sg.ID) {
continue
}
- sgIDs = append(sgIDs, sg.ID)
+ sgIDs = append(sgIDs, *sg.ID)
continue
}
- listOpts := filterconvert.SecurityGroupFilterToListOpts(sg)
+ if sg.Filter == nil {
+ // Should have been caught by validation
+ return nil, errors.New("security group param must have id or filter")
+ }
+
+ listOpts := filterconvert.SecurityGroupFilterToListOpts(sg.Filter)
if listOpts.ProjectID == "" {
listOpts.ProjectID = s.scope.ProjectID()
}
@@ -332,7 +338,7 @@ func (s *Service) GetSecurityGroups(securityGroupParams []infrav1.SecurityGroupF
}
if len(SGList) == 0 {
- return nil, fmt.Errorf("security group %s not found", sg.Name)
+ return nil, fmt.Errorf("security group %d not found", i)
}
for _, group := range SGList {
diff --git a/pkg/utils/filterconvert/convert.go b/pkg/utils/filterconvert/convert.go
index c1194b7880..8ece362ab6 100644
--- a/pkg/utils/filterconvert/convert.go
+++ b/pkg/utils/filterconvert/convert.go
@@ -31,7 +31,6 @@ func SecurityGroupFilterToListOpts(securityGroupFilter *infrav1.SecurityGroupFil
return securitygroups.ListOpts{}
}
return securitygroups.ListOpts{
- ID: securityGroupFilter.ID,
Name: securityGroupFilter.Name,
Description: securityGroupFilter.Description,
ProjectID: securityGroupFilter.ProjectID,
diff --git a/test/e2e/suites/apivalidations/filters_test.go b/test/e2e/suites/apivalidations/filters_test.go
index ce0b38637b..a6001c3ab2 100644
--- a/test/e2e/suites/apivalidations/filters_test.go
+++ b/test/e2e/suites/apivalidations/filters_test.go
@@ -51,9 +51,9 @@ var _ = Describe("Filter API validations", func() {
// possible to specify them in, then create the
// resulting object. It should be valid.
- securityGroups := make([]infrav1.SecurityGroupFilter, len(tags))
+ securityGroups := make([]infrav1.SecurityGroupParam, len(tags))
for i := range tags {
- securityGroups[i].FilterByNeutronTags = tags[i]
+ securityGroups[i].Filter = &infrav1.SecurityGroupFilter{FilterByNeutronTags: tags[i]}
}
machine.Spec.SecurityGroups = securityGroups
@@ -64,7 +64,7 @@ var _ = Describe("Filter API validations", func() {
port.FixedIPs = []infrav1.FixedIP{{Subnet: &infrav1.SubnetParam{
Filter: &infrav1.SubnetFilter{FilterByNeutronTags: tags[i]},
}}}
- port.SecurityGroups = []infrav1.SecurityGroupFilter{{FilterByNeutronTags: tags[i]}}
+ port.SecurityGroups = []infrav1.SecurityGroupParam{{Filter: &infrav1.SecurityGroupFilter{FilterByNeutronTags: tags[i]}}}
}
Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "OpenStackMachine creation should succeed")
@@ -97,9 +97,9 @@ var _ = Describe("Filter API validations", func() {
DescribeTable("Disallow invalid neutron filter tags", func(tags []infrav1.FilterByNeutronTags) {
{
machine := machine.DeepCopy()
- securityGroups := make([]infrav1.SecurityGroupFilter, len(tags))
+ securityGroups := make([]infrav1.SecurityGroupParam, len(tags))
for i := range tags {
- securityGroups[i].FilterByNeutronTags = tags[i]
+ securityGroups[i].Filter = &infrav1.SecurityGroupFilter{FilterByNeutronTags: tags[i]}
}
machine.Spec.SecurityGroups = securityGroups
Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail with invalid security group neutron tags")
@@ -125,7 +125,7 @@ var _ = Describe("Filter API validations", func() {
{
machine := machine.DeepCopy()
machine.Spec.Ports = []infrav1.PortOpts{
- {SecurityGroups: []infrav1.SecurityGroupFilter{{FilterByNeutronTags: tags[i]}}},
+ {SecurityGroups: []infrav1.SecurityGroupParam{{Filter: &infrav1.SecurityGroupFilter{FilterByNeutronTags: tags[i]}}}},
}
Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail with invalid port security group neutron tags")
}
@@ -307,4 +307,46 @@ var _ = Describe("Filter API validations", func() {
Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should fail")
})
})
+
+ Context("SecurityGroupParam", func() {
+ It("should allow setting ID", func() {
+ machine.Spec.SecurityGroups = []infrav1.SecurityGroupParam{
+ {ID: pointer.String("06c32c52-f207-4f6a-a769-bbcbe5a43f5c")},
+ }
+ Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "OpenStackMachine creation should succeed")
+ })
+
+ It("should allow setting non-empty Filter", func() {
+ machine.Spec.SecurityGroups = []infrav1.SecurityGroupParam{
+ {Filter: &infrav1.SecurityGroupFilter{Name: "foo"}},
+ }
+ Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "OpenStackMachine creation should succeed")
+ })
+
+ It("should not allow setting empty param", func() {
+ machine.Spec.SecurityGroups = []infrav1.SecurityGroupParam{{}}
+ Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail")
+ })
+
+ It("should not allow setting invalid id", func() {
+ machine.Spec.SecurityGroups = []infrav1.SecurityGroupParam{
+ {ID: pointer.String("foo")},
+ }
+ Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail")
+ })
+
+ It("should not allow setting empty Filter", func() {
+ machine.Spec.SecurityGroups = []infrav1.SecurityGroupParam{
+ {Filter: &infrav1.SecurityGroupFilter{}},
+ }
+ Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail")
+ })
+
+ It("should not allow setting both ID and Filter", func() {
+ machine.Spec.SecurityGroups = []infrav1.SecurityGroupParam{
+ {ID: pointer.String("06c32c52-f207-4f6a-a769-bbcbe5a43f5c"), Filter: &infrav1.SecurityGroupFilter{Name: "foo"}},
+ }
+ Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail")
+ })
+ })
})
diff --git a/test/e2e/suites/e2e/e2e_test.go b/test/e2e/suites/e2e/e2e_test.go
index ff0cb9c7ba..fadae81131 100644
--- a/test/e2e/suites/e2e/e2e_test.go
+++ b/test/e2e/suites/e2e/e2e_test.go
@@ -379,7 +379,7 @@ var _ = Describe("e2e tests [PR-Blocking]", func() {
Trunk: pointer.Bool(true),
},
{
- SecurityGroups: []infrav1.SecurityGroupFilter{{Name: testSecurityGroupName}},
+ SecurityGroups: []infrav1.SecurityGroupParam{{Filter: &infrav1.SecurityGroupFilter{Name: testSecurityGroupName}}},
},
}
diff --git a/test/helpers/fuzzerfuncs.go b/test/helpers/fuzzerfuncs.go
index 35720fcdd1..2c3a0fe188 100644
--- a/test/helpers/fuzzerfuncs.go
+++ b/test/helpers/fuzzerfuncs.go
@@ -137,5 +137,9 @@ func InfraV1FuzzerFuncs() []interface{} {
func(param *infrav1.SubnetParam, c fuzz.Continue) {
fuzzFilterParam(¶m.ID, ¶m.Filter, c)
},
+
+ func(param *infrav1.SecurityGroupParam, c fuzz.Continue) {
+ fuzzFilterParam(¶m.ID, ¶m.Filter, c)
+ },
}
}
From 91669cf7b4348fc58e3eccecc731ccc56bb90dc5 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Wed, 27 Mar 2024 18:02:46 +0000
Subject: [PATCH 153/180] make generate generates templates
---
Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
index d23c75d8ba..8b905651da 100644
--- a/Makefile
+++ b/Makefile
@@ -248,7 +248,7 @@ modules: ## Runs go mod to ensure proper vendoring.
cd $(TOOLS_DIR); go mod tidy
.PHONY: generate
-generate: generate-controller-gen generate-conversion-gen generate-go generate-manifests generate-api-docs ## Generate all generated code
+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)
From 44be48e4f9e20eb7b31eaadb5612dcf80e9fd84c Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Mon, 25 Mar 2024 14:08:10 +0000
Subject: [PATCH 154/180] ImageFilter to ImageParam
---
api/v1alpha5/conversion.go | 16 ++--
api/v1alpha5/zz_generated.conversion.go | 4 +-
api/v1alpha6/openstackmachine_conversion.go | 16 ++--
api/v1alpha6/zz_generated.conversion.go | 4 +-
api/v1alpha7/openstackmachine_conversion.go | 16 ++--
api/v1alpha7/zz_generated.conversion.go | 4 +-
api/v1beta1/openstackmachine_types.go | 2 +-
api/v1beta1/types.go | 28 +++++-
api/v1beta1/zz_generated.deepcopy.go | 30 +++++-
...re.cluster.x-k8s.io_openstackclusters.yaml | 46 ++++++----
...er.x-k8s.io_openstackclustertemplates.yaml | 49 +++++-----
...re.cluster.x-k8s.io_openstackmachines.yaml | 43 +++++----
...er.x-k8s.io_openstackmachinetemplates.yaml | 46 ++++++----
.../openstackcluster_controller_test.go | 6 +-
.../openstackmachine_controller_test.go | 2 +-
docs/book/src/api/v1beta1/api.md | 65 ++++++++++---
.../v1beta1/default/cluster-template.yaml | 6 +-
.../v1beta1/flatcar-sysext/patch-flatcar.yaml | 6 +-
kustomize/v1beta1/flatcar/patch-flatcar.yaml | 6 +-
pkg/cloud/services/compute/instance.go | 10 +-
pkg/cloud/services/compute/instance_test.go | 38 ++++++--
.../compute/referenced_resources_test.go | 16 ++--
pkg/webhooks/openstackcluster_webhook_test.go | 24 ++++-
.../openstackmachinetemplate_webhook_test.go | 48 ++++++++--
.../cluster-template-flatcar-sysext.yaml | 6 +-
templates/cluster-template-flatcar.yaml | 6 +-
templates/cluster-template-without-lb.yaml | 6 +-
templates/cluster-template.yaml | 6 +-
templates/clusterclass-dev-test.yaml | 4 +-
.../cluster-prev1beta1/kustomization.yaml | 10 ++
.../patch-cluster.yaml | 0
.../common-patches/cluster/kustomization.yaml | 10 ++
.../common-patches/cluster/patch-cluster.yaml | 15 +++
.../common-patches/cni/kustomization.yaml | 4 -
.../data/kustomize/default/kustomization.yaml | 1 +
.../flatcar-sysext/kustomization.yaml | 1 +
.../data/kustomize/flatcar/kustomization.yaml | 1 +
.../k8s-upgrade/upgrade-from-template.yaml | 6 +-
.../k8s-upgrade/upgrade-to-template.yaml | 6 +-
.../kustomize/v1alpha6/kustomization.yaml | 1 +
.../kustomize/v1alpha7/kustomization.yaml | 1 +
.../kustomize/without-lb/kustomization.yaml | 1 +
.../e2e/suites/apivalidations/filters_test.go | 92 +++++++++++--------
.../apivalidations/openstackcluster_test.go | 18 +++-
.../apivalidations/openstackmachine_test.go | 6 +-
test/e2e/suites/e2e/e2e_test.go | 12 ++-
test/helpers/fuzzerfuncs.go | 4 +
47 files changed, 507 insertions(+), 241 deletions(-)
create mode 100644 test/e2e/data/kustomize/common-patches/cluster-prev1beta1/kustomization.yaml
rename test/e2e/data/kustomize/common-patches/{cni => cluster-prev1beta1}/patch-cluster.yaml (100%)
create mode 100644 test/e2e/data/kustomize/common-patches/cluster/kustomization.yaml
create mode 100644 test/e2e/data/kustomize/common-patches/cluster/patch-cluster.yaml
diff --git a/api/v1alpha5/conversion.go b/api/v1alpha5/conversion.go
index 50944701eb..b9439a54eb 100644
--- a/api/v1alpha5/conversion.go
+++ b/api/v1alpha5/conversion.go
@@ -356,13 +356,13 @@ func Convert_v1alpha5_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(in *O
out.ServerGroup = &infrav1.ServerGroupFilter{}
}
- imageFilter := infrav1.ImageFilter{}
+ imageParam := infrav1.ImageParam{}
if in.ImageUUID != "" {
- imageFilter.ID = &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.
- imageFilter.Name = &in.Image
+ imageParam.Filter = &infrav1.ImageFilter{Name: &in.Image}
}
- out.Image = imageFilter
+ out.Image = imageParam
if in.IdentityRef != nil {
out.IdentityRef = &infrav1.OpenStackIdentityReference{Name: in.IdentityRef.Name}
@@ -686,12 +686,10 @@ func Convert_v1beta1_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(in *i
out.ServerGroupID = in.ServerGroup.ID
}
- if in.Image.Name != nil && *in.Image.Name != "" {
- out.Image = *in.Image.Name
- }
-
- if in.Image.ID != nil && *in.Image.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 {
diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go
index 2a335b80c5..2c5a688927 100644
--- a/api/v1alpha5/zz_generated.conversion.go
+++ b/api/v1alpha5/zz_generated.conversion.go
@@ -1142,7 +1142,7 @@ func autoConvert_v1alpha5_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(i
out.InstanceID = (*string)(unsafe.Pointer(in.InstanceID))
// 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.ImageFilter)
+ // 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
@@ -1192,7 +1192,7 @@ func autoConvert_v1beta1_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(i
out.ProviderID = (*string)(unsafe.Pointer(in.ProviderID))
out.InstanceID = (*string)(unsafe.Pointer(in.InstanceID))
out.Flavor = in.Flavor
- // WARNING: in.Image requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ImageFilter vs string)
+ // 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
diff --git a/api/v1alpha6/openstackmachine_conversion.go b/api/v1alpha6/openstackmachine_conversion.go
index d8439d19f1..2b5864d818 100644
--- a/api/v1alpha6/openstackmachine_conversion.go
+++ b/api/v1alpha6/openstackmachine_conversion.go
@@ -272,13 +272,13 @@ func Convert_v1alpha6_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(in *O
out.ServerGroup = nil
}
- imageFilter := infrav1.ImageFilter{}
+ imageParam := infrav1.ImageParam{}
if in.ImageUUID != "" {
- imageFilter.ID = &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.
- imageFilter.Name = &in.Image
+ imageParam.Filter = &infrav1.ImageFilter{Name: &in.Image}
}
- out.Image = imageFilter
+ out.Image = imageParam
if len(in.ServerMetadata) > 0 {
serverMetadata := make([]infrav1.ServerMetadata, 0, len(in.ServerMetadata))
@@ -320,12 +320,10 @@ func Convert_v1beta1_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(in *i
out.ServerGroupID = in.ServerGroup.ID
}
- if in.Image.Name != nil && *in.Image.Name != "" {
- out.Image = *in.Image.Name
- }
-
- if in.Image.ID != nil && *in.Image.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 {
diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go
index 2b98c9a0d8..8e33e36df6 100644
--- a/api/v1alpha6/zz_generated.conversion.go
+++ b/api/v1alpha6/zz_generated.conversion.go
@@ -1177,7 +1177,7 @@ func autoConvert_v1alpha6_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(i
out.InstanceID = (*string)(unsafe.Pointer(in.InstanceID))
// 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.ImageFilter)
+ // 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
@@ -1227,7 +1227,7 @@ func autoConvert_v1beta1_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(i
out.ProviderID = (*string)(unsafe.Pointer(in.ProviderID))
out.InstanceID = (*string)(unsafe.Pointer(in.InstanceID))
out.Flavor = in.Flavor
- // WARNING: in.Image requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ImageFilter vs string)
+ // 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
diff --git a/api/v1alpha7/openstackmachine_conversion.go b/api/v1alpha7/openstackmachine_conversion.go
index 9ce17bbbd3..4731f7445c 100644
--- a/api/v1alpha7/openstackmachine_conversion.go
+++ b/api/v1alpha7/openstackmachine_conversion.go
@@ -170,13 +170,13 @@ func Convert_v1alpha7_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(in *O
out.ServerGroup = nil
}
- imageFilter := infrav1.ImageFilter{}
+ imageParam := infrav1.ImageParam{}
if in.ImageUUID != "" {
- imageFilter.ID = &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.
- imageFilter.Name = &in.Image
+ imageParam.Filter = &infrav1.ImageFilter{Name: &in.Image}
}
- out.Image = imageFilter
+ out.Image = imageParam
if len(in.ServerMetadata) > 0 {
serverMetadata := make([]infrav1.ServerMetadata, 0, len(in.ServerMetadata))
@@ -215,12 +215,10 @@ func Convert_v1beta1_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(in *i
out.ServerGroupID = in.ServerGroup.ID
}
- if in.Image.Name != nil && *in.Image.Name != "" {
- out.Image = *in.Image.Name
- }
-
- if in.Image.ID != nil && *in.Image.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 {
diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go
index 6e00e14144..87bb5dc328 100644
--- a/api/v1alpha7/zz_generated.conversion.go
+++ b/api/v1alpha7/zz_generated.conversion.go
@@ -1364,7 +1364,7 @@ func autoConvert_v1alpha7_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(i
out.InstanceID = (*string)(unsafe.Pointer(in.InstanceID))
// 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.ImageFilter)
+ // 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 {
@@ -1413,7 +1413,7 @@ func autoConvert_v1beta1_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(i
out.ProviderID = (*string)(unsafe.Pointer(in.ProviderID))
out.InstanceID = (*string)(unsafe.Pointer(in.InstanceID))
out.Flavor = in.Flavor
- // WARNING: in.Image requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ImageFilter vs string)
+ // 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
diff --git a/api/v1beta1/openstackmachine_types.go b/api/v1beta1/openstackmachine_types.go
index 5a7b05c319..3f20a559ff 100644
--- a/api/v1beta1/openstackmachine_types.go
+++ b/api/v1beta1/openstackmachine_types.go
@@ -45,7 +45,7 @@ type OpenStackMachineSpec struct {
// The image to use for your server instance.
// If the rootVolume is specified, this will be used when creating the root volume.
// +required
- Image ImageFilter `json:"image"`
+ Image ImageParam `json:"image"`
// The ssh key to inject in the instance
SSHKeyName string `json:"sshKeyName,omitempty"`
diff --git a/api/v1beta1/types.go b/api/v1beta1/types.go
index ad67976e96..e9b9bbb2f6 100644
--- a/api/v1beta1/types.go
+++ b/api/v1beta1/types.go
@@ -28,22 +28,42 @@ type OpenStackMachineTemplateResource struct {
Spec OpenStackMachineSpec `json:"spec"`
}
-// ImageFilter describes the data needed to identify which image to use. If ID is provided it is required that all other fields are unset.
-// +kubebuilder:validation:XValidation:rule="(has(self.id) && !has(self.name) && !has(self.tags)) || !has(self.id)",message="when ID is set you cannot set other options"
-type ImageFilter struct {
- // The ID of the desired image. If ID is provided, the other filters cannot be provided. Must be in UUID format.
+// 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"`
diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go
index bbaa79118a..9c8f75f97f 100644
--- a/api/v1beta1/zz_generated.deepcopy.go
+++ b/api/v1beta1/zz_generated.deepcopy.go
@@ -307,11 +307,6 @@ func (in *FixedIP) DeepCopy() *FixedIP {
// 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.ID != nil {
- in, out := &in.ID, &out.ID
- *out = new(string)
- **out = **in
- }
if in.Name != nil {
in, out := &in.Name, &out.Name
*out = new(string)
@@ -334,6 +329,31 @@ func (in *ImageFilter) DeepCopy() *ImageFilter {
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
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 c4adc2b0b7..1490e10a21 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -5050,31 +5050,37 @@ spec:
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: The ID of the desired image. If ID is provided,
- the other filters cannot be provided. Must be in UUID
- format.
+ description: ID is the uuid of the image. ID will not
+ be validated before use.
format: uuid
type: string
- 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
- x-kubernetes-validations:
- - message: when ID is set you cannot set other options
- rule: (has(self.id) && !has(self.name) && !has(self.tags))
- || !has(self.id)
instanceID:
description: InstanceID is the OpenStack instance ID for this
machine.
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 a6943b023a..c0a334ec4c 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -2477,33 +2477,38 @@ spec:
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: The ID of the desired image. If ID
- is provided, the other filters cannot be provided.
- Must be in UUID format.
+ description: ID is the uuid of the image. ID will
+ not be validated before use.
format: uuid
type: string
- 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
- x-kubernetes-validations:
- - message: when ID is set you cannot set other options
- rule: (has(self.id) && !has(self.name) && !has(self.tags))
- || !has(self.id)
instanceID:
description: InstanceID is the OpenStack instance
ID for this machine.
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 40ce3c87fd..1ea294dcb1 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
@@ -1831,29 +1831,36 @@ spec:
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: The ID of the desired image. If ID is provided, the
- other filters cannot be provided. Must be in UUID format.
+ description: ID is the uuid of the image. ID will not be validated
+ before use.
format: uuid
type: string
- 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
- x-kubernetes-validations:
- - message: when ID is set you cannot set other options
- rule: (has(self.id) && !has(self.name) && !has(self.tags)) || !has(self.id)
instanceID:
description: InstanceID is the OpenStack instance ID for this machine.
type: string
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 e2c222712a..4c1b1abb98 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
@@ -1504,31 +1504,37 @@ spec:
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: The ID of the desired image. If ID is provided,
- the other filters cannot be provided. Must be in UUID
- format.
+ description: ID is the uuid of the image. ID will not
+ be validated before use.
format: uuid
type: string
- 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
- x-kubernetes-validations:
- - message: when ID is set you cannot set other options
- rule: (has(self.id) && !has(self.name) && !has(self.tags))
- || !has(self.id)
instanceID:
description: InstanceID is the OpenStack instance ID for this
machine.
diff --git a/controllers/openstackcluster_controller_test.go b/controllers/openstackcluster_controller_test.go
index 0b6fe63784..c2a602ec31 100644
--- a/controllers/openstackcluster_controller_test.go
+++ b/controllers/openstackcluster_controller_test.go
@@ -62,8 +62,10 @@ var _ = Describe("OpenStackCluster controller", func() {
testClusterName := "test-cluster"
testNum := 0
bastionSpec := infrav1.OpenStackMachineSpec{
- Image: infrav1.ImageFilter{
- Name: pointer.String("fake-name"),
+ Image: infrav1.ImageParam{
+ Filter: &infrav1.ImageFilter{
+ Name: pointer.String("fake-name"),
+ },
},
}
diff --git a/controllers/openstackmachine_controller_test.go b/controllers/openstackmachine_controller_test.go
index d57848f80f..53c504e05c 100644
--- a/controllers/openstackmachine_controller_test.go
+++ b/controllers/openstackmachine_controller_test.go
@@ -84,7 +84,7 @@ func getDefaultOpenStackMachine() *infrav1.OpenStackMachine {
// FloatingIP is only used by the cluster controller for the Bastion
// TODO: Test Networks, Ports, Subnet, and Trunk separately
Flavor: flavorName,
- Image: infrav1.ImageFilter{ID: pointer.String(imageUUID)},
+ Image: infrav1.ImageParam{ID: pointer.String(imageUUID)},
SSHKeyName: sshKeyName,
Tags: []string{"test-tag"},
ServerMetadata: []infrav1.ServerMetadata{
diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md
index ecc495a928..581f7326ef 100644
--- a/docs/book/src/api/v1beta1/api.md
+++ b/docs/book/src/api/v1beta1/api.md
@@ -587,8 +587,8 @@ string
image
-
-ImageFilter
+
+ImageParam
|
@@ -1580,10 +1580,10 @@ address in any subnet of the port’s network.
(Appears on:
-OpenStackMachineSpec)
+ImageParam)
-
ImageFilter describes the data needed to identify which image to use. If ID is provided it is required that all other fields are unset.
+ImageFilter describes a query for an image.
@@ -1595,38 +1595,73 @@ address in any subnet of the port’s network.
-id
+name
string
|
(Optional)
- The ID of the desired image. If ID is provided, the other filters cannot be provided. Must be in UUID format.
+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.
|
-name
+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.
+ |
+
+
+
+ImageParam
+
+
+(Appears on:
+OpenStackMachineSpec)
+
+
+
ImageParam describes a glance image. It can be specified by ID or filter.
+
+
+
+
+| Field |
+Description |
+
+
+
+
+
+id
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.
+ID is the uuid of the image. ID will not be validated before use.
|
-tags
+filter
-[]string
+
+ImageFilter
+
|
(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.
+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.
|
@@ -3101,8 +3136,8 @@ string
image
-
-ImageFilter
+
+ImageParam
|
@@ -3473,8 +3508,8 @@ string
image
-
-ImageFilter
+
+ImageParam
|
diff --git a/kustomize/v1beta1/default/cluster-template.yaml b/kustomize/v1beta1/default/cluster-template.yaml
index 52ab6c2f88..ae7db083cf 100644
--- a/kustomize/v1beta1/default/cluster-template.yaml
+++ b/kustomize/v1beta1/default/cluster-template.yaml
@@ -97,7 +97,8 @@ spec:
spec:
flavor: ${OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR}
image:
- name: ${OPENSTACK_IMAGE_NAME}
+ filter:
+ name: ${OPENSTACK_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
---
apiVersion: cluster.x-k8s.io/v1beta1
@@ -133,7 +134,8 @@ spec:
spec:
flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR}
image:
- name: ${OPENSTACK_IMAGE_NAME}
+ filter:
+ name: ${OPENSTACK_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
---
apiVersion: bootstrap.cluster.x-k8s.io/v1beta1
diff --git a/kustomize/v1beta1/flatcar-sysext/patch-flatcar.yaml b/kustomize/v1beta1/flatcar-sysext/patch-flatcar.yaml
index 0c60d2e460..6c143c853c 100644
--- a/kustomize/v1beta1/flatcar-sysext/patch-flatcar.yaml
+++ b/kustomize/v1beta1/flatcar-sysext/patch-flatcar.yaml
@@ -170,7 +170,8 @@ spec:
template:
spec:
image:
- name: ${FLATCAR_IMAGE_NAME}
+ filter:
+ name: ${FLATCAR_IMAGE_NAME}
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
@@ -180,4 +181,5 @@ spec:
template:
spec:
image:
- name: ${FLATCAR_IMAGE_NAME}
+ filter:
+ name: ${FLATCAR_IMAGE_NAME}
diff --git a/kustomize/v1beta1/flatcar/patch-flatcar.yaml b/kustomize/v1beta1/flatcar/patch-flatcar.yaml
index d95991efc9..a702429646 100644
--- a/kustomize/v1beta1/flatcar/patch-flatcar.yaml
+++ b/kustomize/v1beta1/flatcar/patch-flatcar.yaml
@@ -94,7 +94,8 @@ spec:
template:
spec:
image:
- name: ${OPENSTACK_FLATCAR_IMAGE_NAME}
+ filter:
+ name: ${OPENSTACK_FLATCAR_IMAGE_NAME}
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: OpenStackMachineTemplate
@@ -104,4 +105,5 @@ spec:
template:
spec:
image:
- name: ${OPENSTACK_FLATCAR_IMAGE_NAME}
+ filter:
+ name: ${OPENSTACK_FLATCAR_IMAGE_NAME}
diff --git a/pkg/cloud/services/compute/instance.go b/pkg/cloud/services/compute/instance.go
index eebfd9278d..ac0b377bed 100644
--- a/pkg/cloud/services/compute/instance.go
+++ b/pkg/cloud/services/compute/instance.go
@@ -18,6 +18,7 @@ package compute
import (
"context"
+ "errors"
"fmt"
"os"
"strconv"
@@ -332,12 +333,17 @@ func applyServerGroupID(opts servers.CreateOptsBuilder, serverGroupID string) se
}
// Helper function for getting image ID from name, ID, or tags.
-func (s *Service) GetImageID(image infrav1.ImageFilter) (string, error) {
+func (s *Service) GetImageID(image infrav1.ImageParam) (string, error) {
if image.ID != nil {
return *image.ID, nil
}
- listOpts := filterconvert.ImageFilterToListOpts(&image)
+ if image.Filter == nil {
+ // Should have been caught by validation
+ return "", errors.New("image id and filter are both nil")
+ }
+
+ listOpts := filterconvert.ImageFilterToListOpts(image.Filter)
allImages, err := s.getImageClient().ListImages(listOpts)
if err != nil {
return "", err
diff --git a/pkg/cloud/services/compute/instance_test.go b/pkg/cloud/services/compute/instance_test.go
index af9214e8a7..b571b25021 100644
--- a/pkg/cloud/services/compute/instance_test.go
+++ b/pkg/cloud/services/compute/instance_test.go
@@ -47,22 +47,26 @@ func TestService_getImageID(t *testing.T) {
tests := []struct {
testName string
- image infrav1.ImageFilter
+ image infrav1.ImageParam
expect func(m *mock.MockImageClientMockRecorder)
want string
wantErr bool
}{
{
testName: "Return image ID when ID given",
- image: infrav1.ImageFilter{ID: &imageID},
+ image: infrav1.ImageParam{ID: &imageID},
want: imageID,
expect: func(m *mock.MockImageClientMockRecorder) {},
wantErr: false,
},
{
testName: "Return image ID when name given",
- image: infrav1.ImageFilter{Name: &imageName},
- want: imageID,
+ image: infrav1.ImageParam{
+ Filter: &infrav1.ImageFilter{
+ Name: &imageName,
+ },
+ },
+ want: imageID,
expect: func(m *mock.MockImageClientMockRecorder) {
m.ListImages(images.ListOpts{Name: imageName}).Return(
[]images.Image{{ID: imageID, Name: imageName}},
@@ -72,8 +76,12 @@ func TestService_getImageID(t *testing.T) {
},
{
testName: "Return image ID when tags given",
- image: infrav1.ImageFilter{Tags: imageTags},
- want: imageID,
+ image: infrav1.ImageParam{
+ Filter: &infrav1.ImageFilter{
+ Tags: imageTags,
+ },
+ },
+ want: imageID,
expect: func(m *mock.MockImageClientMockRecorder) {
m.ListImages(images.ListOpts{Tags: imageTags}).Return(
[]images.Image{{ID: imageID, Name: imageName, Tags: imageTags}},
@@ -83,7 +91,11 @@ func TestService_getImageID(t *testing.T) {
},
{
testName: "Return no results",
- image: infrav1.ImageFilter{Name: &imageName},
+ image: infrav1.ImageParam{
+ Filter: &infrav1.ImageFilter{
+ Name: &imageName,
+ },
+ },
expect: func(m *mock.MockImageClientMockRecorder) {
m.ListImages(images.ListOpts{Name: imageName}).Return(
[]images.Image{},
@@ -94,7 +106,11 @@ func TestService_getImageID(t *testing.T) {
},
{
testName: "Return multiple results",
- image: infrav1.ImageFilter{Name: &imageName},
+ image: infrav1.ImageParam{
+ Filter: &infrav1.ImageFilter{
+ Name: &imageName,
+ },
+ },
expect: func(m *mock.MockImageClientMockRecorder) {
m.ListImages(images.ListOpts{Name: "test-image"}).Return(
[]images.Image{
@@ -107,7 +123,11 @@ func TestService_getImageID(t *testing.T) {
},
{
testName: "OpenStack returns error",
- image: infrav1.ImageFilter{Name: &imageName},
+ image: infrav1.ImageParam{
+ Filter: &infrav1.ImageFilter{
+ Name: &imageName,
+ },
+ },
expect: func(m *mock.MockImageClientMockRecorder) {
m.ListImages(images.ListOpts{Name: "test-image"}).Return(
nil,
diff --git a/pkg/cloud/services/compute/referenced_resources_test.go b/pkg/cloud/services/compute/referenced_resources_test.go
index 035bdaf824..b4419b691d 100644
--- a/pkg/cloud/services/compute/referenced_resources_test.go
+++ b/pkg/cloud/services/compute/referenced_resources_test.go
@@ -68,7 +68,7 @@ func Test_ResolveMachineSpec(t *testing.T) {
testName: "Resources ID passed",
spec: infrav1.OpenStackMachineSpec{
ServerGroup: &infrav1.ServerGroupFilter{ID: serverGroupID1},
- Image: infrav1.ImageFilter{ID: pointer.String(imageID1)},
+ Image: infrav1.ImageParam{ID: pointer.String(imageID1)},
},
want: &infrav1.ResolvedMachineSpec{
ImageID: imageID1,
@@ -79,7 +79,7 @@ func Test_ResolveMachineSpec(t *testing.T) {
{
testName: "Only image ID passed: want image id and default ports",
spec: infrav1.OpenStackMachineSpec{
- Image: infrav1.ImageFilter{ID: pointer.String(imageID1)},
+ Image: infrav1.ImageParam{ID: pointer.String(imageID1)},
},
want: &infrav1.ResolvedMachineSpec{
ImageID: imageID1,
@@ -89,7 +89,7 @@ func Test_ResolveMachineSpec(t *testing.T) {
{
testName: "Server group empty",
spec: infrav1.OpenStackMachineSpec{
- Image: infrav1.ImageFilter{ID: pointer.String(imageID1)},
+ Image: infrav1.ImageParam{ID: pointer.String(imageID1)},
ServerGroup: &infrav1.ServerGroupFilter{},
},
want: &infrav1.ResolvedMachineSpec{
@@ -100,7 +100,7 @@ func Test_ResolveMachineSpec(t *testing.T) {
{
testName: "Server group by Name not found",
spec: infrav1.OpenStackMachineSpec{
- Image: infrav1.ImageFilter{ID: pointer.String(imageID1)},
+ Image: infrav1.ImageParam{ID: pointer.String(imageID1)},
ServerGroup: &infrav1.ServerGroupFilter{Name: "test-server-group"},
},
expectComputeMock: func(m *mock.MockComputeClientMockRecorder) {
@@ -114,7 +114,11 @@ func Test_ResolveMachineSpec(t *testing.T) {
{
testName: "Image by Name not found",
spec: infrav1.OpenStackMachineSpec{
- Image: infrav1.ImageFilter{Name: pointer.String("test-image")},
+ Image: infrav1.ImageParam{
+ Filter: &infrav1.ImageFilter{
+ Name: pointer.String("test-image"),
+ },
+ },
},
expectImageMock: func(m *mock.MockImageClientMockRecorder) {
m.ListImages(images.ListOpts{Name: "test-image"}).Return([]images.Image{}, nil)
@@ -125,7 +129,7 @@ func Test_ResolveMachineSpec(t *testing.T) {
{
testName: "Ports set",
spec: infrav1.OpenStackMachineSpec{
- Image: infrav1.ImageFilter{ID: pointer.String(imageID1)},
+ Image: infrav1.ImageParam{ID: pointer.String(imageID1)},
Ports: []infrav1.PortOpts{
{
Network: &infrav1.NetworkParam{
diff --git a/pkg/webhooks/openstackcluster_webhook_test.go b/pkg/webhooks/openstackcluster_webhook_test.go
index 3d65376486..09c18dcc70 100644
--- a/pkg/webhooks/openstackcluster_webhook_test.go
+++ b/pkg/webhooks/openstackcluster_webhook_test.go
@@ -85,7 +85,11 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
Bastion: &infrav1.Bastion{
Spec: &infrav1.OpenStackMachineSpec{
- Image: infrav1.ImageFilter{Name: pointer.String("foobar")},
+ Image: infrav1.ImageParam{
+ Filter: &infrav1.ImageFilter{
+ Name: pointer.String("foobar"),
+ },
+ },
Flavor: "minimal",
},
Enabled: true,
@@ -105,7 +109,11 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
Bastion: &infrav1.Bastion{
Spec: &infrav1.OpenStackMachineSpec{
- Image: infrav1.ImageFilter{Name: pointer.String("foobarbaz")},
+ Image: infrav1.ImageParam{
+ Filter: &infrav1.ImageFilter{
+ Name: pointer.String("foobarbaz"),
+ },
+ },
Flavor: "medium",
},
Enabled: true,
@@ -454,7 +462,11 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
Enabled: true,
Spec: &infrav1.OpenStackMachineSpec{
Flavor: "m1.small",
- Image: infrav1.ImageFilter{Name: pointer.String("ubuntu")},
+ Image: infrav1.ImageParam{
+ Filter: &infrav1.ImageFilter{
+ Name: pointer.String("ubuntu"),
+ },
+ },
},
},
},
@@ -481,7 +493,11 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
Enabled: false,
Spec: &infrav1.OpenStackMachineSpec{
Flavor: "m1.small",
- Image: infrav1.ImageFilter{Name: pointer.String("ubuntu")},
+ Image: infrav1.ImageParam{
+ Filter: &infrav1.ImageFilter{
+ Name: pointer.String("ubuntu"),
+ },
+ },
},
},
},
diff --git a/pkg/webhooks/openstackmachinetemplate_webhook_test.go b/pkg/webhooks/openstackmachinetemplate_webhook_test.go
index 899cf509f1..6b148f3bfa 100644
--- a/pkg/webhooks/openstackmachinetemplate_webhook_test.go
+++ b/pkg/webhooks/openstackmachinetemplate_webhook_test.go
@@ -47,7 +47,11 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) {
Template: infrav1.OpenStackMachineTemplateResource{
Spec: infrav1.OpenStackMachineSpec{
Flavor: "foo",
- Image: infrav1.ImageFilter{Name: pointer.String("bar")},
+ Image: infrav1.ImageParam{
+ Filter: &infrav1.ImageFilter{
+ Name: pointer.String("bar"),
+ },
+ },
},
},
},
@@ -57,7 +61,11 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) {
Template: infrav1.OpenStackMachineTemplateResource{
Spec: infrav1.OpenStackMachineSpec{
Flavor: "foo",
- Image: infrav1.ImageFilter{Name: pointer.String("NewImage")},
+ Image: infrav1.ImageParam{
+ Filter: &infrav1.ImageFilter{
+ Name: pointer.String("NewImage"),
+ },
+ },
},
},
},
@@ -72,7 +80,11 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) {
Template: infrav1.OpenStackMachineTemplateResource{
Spec: infrav1.OpenStackMachineSpec{
Flavor: "foo",
- Image: infrav1.ImageFilter{Name: pointer.String("bar")},
+ Image: infrav1.ImageParam{
+ Filter: &infrav1.ImageFilter{
+ Name: pointer.String("bar"),
+ },
+ },
},
},
},
@@ -85,7 +97,11 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) {
Template: infrav1.OpenStackMachineTemplateResource{
Spec: infrav1.OpenStackMachineSpec{
Flavor: "foo",
- Image: infrav1.ImageFilter{Name: pointer.String("bar")},
+ Image: infrav1.ImageParam{
+ Filter: &infrav1.ImageFilter{
+ Name: pointer.String("bar"),
+ },
+ },
},
},
},
@@ -102,7 +118,11 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) {
Template: infrav1.OpenStackMachineTemplateResource{
Spec: infrav1.OpenStackMachineSpec{
Flavor: "foo",
- Image: infrav1.ImageFilter{Name: pointer.String("bar")},
+ Image: infrav1.ImageParam{
+ Filter: &infrav1.ImageFilter{
+ Name: pointer.String("bar"),
+ },
+ },
},
},
},
@@ -112,7 +132,11 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) {
Template: infrav1.OpenStackMachineTemplateResource{
Spec: infrav1.OpenStackMachineSpec{
Flavor: "foo",
- Image: infrav1.ImageFilter{Name: pointer.String("NewImage")},
+ Image: infrav1.ImageParam{
+ Filter: &infrav1.ImageFilter{
+ Name: pointer.String("NewImage"),
+ },
+ },
},
},
},
@@ -127,7 +151,11 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) {
Template: infrav1.OpenStackMachineTemplateResource{
Spec: infrav1.OpenStackMachineSpec{
Flavor: "foo",
- Image: infrav1.ImageFilter{Name: pointer.String("bar")},
+ Image: infrav1.ImageParam{
+ Filter: &infrav1.ImageFilter{
+ Name: pointer.String("bar"),
+ },
+ },
},
},
},
@@ -142,7 +170,11 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) {
Template: infrav1.OpenStackMachineTemplateResource{
Spec: infrav1.OpenStackMachineSpec{
Flavor: "foo",
- Image: infrav1.ImageFilter{Name: pointer.String("NewImage")},
+ Image: infrav1.ImageParam{
+ Filter: &infrav1.ImageFilter{
+ Name: pointer.String("NewImage"),
+ },
+ },
},
},
},
diff --git a/templates/cluster-template-flatcar-sysext.yaml b/templates/cluster-template-flatcar-sysext.yaml
index 9cbef933cc..ec33bdeff2 100644
--- a/templates/cluster-template-flatcar-sysext.yaml
+++ b/templates/cluster-template-flatcar-sysext.yaml
@@ -268,7 +268,8 @@ spec:
spec:
flavor: ${OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR}
image:
- name: ${FLATCAR_IMAGE_NAME}
+ filter:
+ name: ${FLATCAR_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
@@ -280,5 +281,6 @@ spec:
spec:
flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR}
image:
- name: ${FLATCAR_IMAGE_NAME}
+ filter:
+ name: ${FLATCAR_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
diff --git a/templates/cluster-template-flatcar.yaml b/templates/cluster-template-flatcar.yaml
index 3d3f92ba23..4282265943 100644
--- a/templates/cluster-template-flatcar.yaml
+++ b/templates/cluster-template-flatcar.yaml
@@ -192,7 +192,8 @@ spec:
spec:
flavor: ${OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR}
image:
- name: ${OPENSTACK_FLATCAR_IMAGE_NAME}
+ filter:
+ name: ${OPENSTACK_FLATCAR_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
@@ -204,5 +205,6 @@ spec:
spec:
flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR}
image:
- name: ${OPENSTACK_FLATCAR_IMAGE_NAME}
+ filter:
+ name: ${OPENSTACK_FLATCAR_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
diff --git a/templates/cluster-template-without-lb.yaml b/templates/cluster-template-without-lb.yaml
index 35acfdbdf1..6dbf7a72d1 100644
--- a/templates/cluster-template-without-lb.yaml
+++ b/templates/cluster-template-without-lb.yaml
@@ -144,7 +144,8 @@ spec:
spec:
flavor: ${OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR}
image:
- name: ${OPENSTACK_IMAGE_NAME}
+ filter:
+ name: ${OPENSTACK_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
@@ -156,5 +157,6 @@ spec:
spec:
flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR}
image:
- name: ${OPENSTACK_IMAGE_NAME}
+ filter:
+ name: ${OPENSTACK_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
diff --git a/templates/cluster-template.yaml b/templates/cluster-template.yaml
index bc8c8aab8c..3508d37e26 100644
--- a/templates/cluster-template.yaml
+++ b/templates/cluster-template.yaml
@@ -146,7 +146,8 @@ spec:
spec:
flavor: ${OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR}
image:
- name: ${OPENSTACK_IMAGE_NAME}
+ filter:
+ name: ${OPENSTACK_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
@@ -158,5 +159,6 @@ spec:
spec:
flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR}
image:
- name: ${OPENSTACK_IMAGE_NAME}
+ filter:
+ name: ${OPENSTACK_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
diff --git a/templates/clusterclass-dev-test.yaml b/templates/clusterclass-dev-test.yaml
index 2cd3a38531..5743a6367d 100644
--- a/templates/clusterclass-dev-test.yaml
+++ b/templates/clusterclass-dev-test.yaml
@@ -43,7 +43,7 @@ spec:
controlPlane: true
jsonPatches:
- op: add
- path: /spec/template/spec/image/name
+ path: /spec/template/spec/image/filter/name
valueFrom:
template: |
ubuntu-2204-kube-{{ .builtin.controlPlane.version }}
@@ -59,7 +59,7 @@ spec:
- default-worker
jsonPatches:
- op: add
- path: /spec/template/spec/image/name
+ path: /spec/template/spec/image/filter/name
valueFrom:
template: |
ubuntu-2204-kube-{{ .builtin.machineDeployment.version }}
diff --git a/test/e2e/data/kustomize/common-patches/cluster-prev1beta1/kustomization.yaml b/test/e2e/data/kustomize/common-patches/cluster-prev1beta1/kustomization.yaml
new file mode 100644
index 0000000000..7136e9600d
--- /dev/null
+++ b/test/e2e/data/kustomize/common-patches/cluster-prev1beta1/kustomization.yaml
@@ -0,0 +1,10 @@
+# Modifications to release templates common to all e2e test scenarios
+---
+apiVersion: kustomize.config.k8s.io/v1alpha1
+kind: Component
+
+patches:
+- target:
+ kind: OpenStackCluster
+ name: \${CLUSTER_NAME}
+ path: patch-cluster.yaml
diff --git a/test/e2e/data/kustomize/common-patches/cni/patch-cluster.yaml b/test/e2e/data/kustomize/common-patches/cluster-prev1beta1/patch-cluster.yaml
similarity index 100%
rename from test/e2e/data/kustomize/common-patches/cni/patch-cluster.yaml
rename to test/e2e/data/kustomize/common-patches/cluster-prev1beta1/patch-cluster.yaml
diff --git a/test/e2e/data/kustomize/common-patches/cluster/kustomization.yaml b/test/e2e/data/kustomize/common-patches/cluster/kustomization.yaml
new file mode 100644
index 0000000000..7136e9600d
--- /dev/null
+++ b/test/e2e/data/kustomize/common-patches/cluster/kustomization.yaml
@@ -0,0 +1,10 @@
+# Modifications to release templates common to all e2e test scenarios
+---
+apiVersion: kustomize.config.k8s.io/v1alpha1
+kind: Component
+
+patches:
+- target:
+ kind: OpenStackCluster
+ name: \${CLUSTER_NAME}
+ path: patch-cluster.yaml
diff --git a/test/e2e/data/kustomize/common-patches/cluster/patch-cluster.yaml b/test/e2e/data/kustomize/common-patches/cluster/patch-cluster.yaml
new file mode 100644
index 0000000000..b6d9564506
--- /dev/null
+++ b/test/e2e/data/kustomize/common-patches/cluster/patch-cluster.yaml
@@ -0,0 +1,15 @@
+---
+- op: add
+ path: /spec/bastion
+ value:
+ enabled: true
+ spec:
+ flavor: ${OPENSTACK_BASTION_MACHINE_FLAVOR}
+ image:
+ filter:
+ name: ${OPENSTACK_BASTION_IMAGE_NAME}
+ sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
+- op: add
+ path: /spec/controlPlaneAvailabilityZones
+ value:
+ - ${OPENSTACK_FAILURE_DOMAIN}
diff --git a/test/e2e/data/kustomize/common-patches/cni/kustomization.yaml b/test/e2e/data/kustomize/common-patches/cni/kustomization.yaml
index 60fe867342..0f10084b63 100644
--- a/test/e2e/data/kustomize/common-patches/cni/kustomization.yaml
+++ b/test/e2e/data/kustomize/common-patches/cni/kustomization.yaml
@@ -7,8 +7,4 @@ resources:
- cni.yaml
patches:
-- target:
- kind: OpenStackCluster
- name: \${CLUSTER_NAME}
- path: patch-cluster.yaml
- path: patch-cni.yaml
diff --git a/test/e2e/data/kustomize/default/kustomization.yaml b/test/e2e/data/kustomize/default/kustomization.yaml
index 30f2c9d85d..e85e60a623 100644
--- a/test/e2e/data/kustomize/default/kustomization.yaml
+++ b/test/e2e/data/kustomize/default/kustomization.yaml
@@ -3,6 +3,7 @@ kind: Kustomization
resources:
- ../../../../../kustomize/v1beta1/default
components:
+- ../common-patches/cluster
- ../common-patches/cni
- ../upgrade-patches
- ../common-patches/ccm
diff --git a/test/e2e/data/kustomize/flatcar-sysext/kustomization.yaml b/test/e2e/data/kustomize/flatcar-sysext/kustomization.yaml
index 6738cde3a8..63c5035c15 100644
--- a/test/e2e/data/kustomize/flatcar-sysext/kustomization.yaml
+++ b/test/e2e/data/kustomize/flatcar-sysext/kustomization.yaml
@@ -3,6 +3,7 @@ resources:
- ../../../../../kustomize/v1beta1/flatcar-sysext
components:
+- ../common-patches/cluster
- ../common-patches/cni
- ../common-patches/ccm
- ../common-patches/externalNetworkByName
diff --git a/test/e2e/data/kustomize/flatcar/kustomization.yaml b/test/e2e/data/kustomize/flatcar/kustomization.yaml
index 2de905e98e..ca872d20cb 100644
--- a/test/e2e/data/kustomize/flatcar/kustomization.yaml
+++ b/test/e2e/data/kustomize/flatcar/kustomization.yaml
@@ -4,6 +4,7 @@ resources:
- ../../../../../kustomize/v1beta1/flatcar
components:
+- ../common-patches/cluster
- ../common-patches/cni
- ../common-patches/ccm
- ../common-patches/externalNetworkByName
diff --git a/test/e2e/data/kustomize/k8s-upgrade/upgrade-from-template.yaml b/test/e2e/data/kustomize/k8s-upgrade/upgrade-from-template.yaml
index 6e9098977b..d49208116d 100644
--- a/test/e2e/data/kustomize/k8s-upgrade/upgrade-from-template.yaml
+++ b/test/e2e/data/kustomize/k8s-upgrade/upgrade-from-template.yaml
@@ -8,7 +8,8 @@ spec:
spec:
flavor: ${OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR}
image:
- name: ${OPENSTACK_IMAGE_NAME_UPGRADE_FROM}
+ filter:
+ name: ${OPENSTACK_IMAGE_NAME_UPGRADE_FROM}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
tags:
- control-plane
@@ -22,7 +23,8 @@ spec:
spec:
flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR}
image:
- name: ${OPENSTACK_IMAGE_NAME_UPGRADE_FROM}
+ filter:
+ name: ${OPENSTACK_IMAGE_NAME_UPGRADE_FROM}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
tags:
- machine
diff --git a/test/e2e/data/kustomize/k8s-upgrade/upgrade-to-template.yaml b/test/e2e/data/kustomize/k8s-upgrade/upgrade-to-template.yaml
index 39272254fd..466cb7931b 100644
--- a/test/e2e/data/kustomize/k8s-upgrade/upgrade-to-template.yaml
+++ b/test/e2e/data/kustomize/k8s-upgrade/upgrade-to-template.yaml
@@ -15,7 +15,8 @@ spec:
spec:
flavor: ${OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR}
image:
- name: ${OPENSTACK_IMAGE_NAME}
+ filter:
+ name: ${OPENSTACK_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
tags:
- control-plane
@@ -31,7 +32,8 @@ spec:
spec:
flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR}
image:
- name: ${OPENSTACK_IMAGE_NAME}
+ filter:
+ name: ${OPENSTACK_IMAGE_NAME}
sshKeyName: ${OPENSTACK_SSH_KEY_NAME}
tags:
- machine
diff --git a/test/e2e/data/kustomize/v1alpha6/kustomization.yaml b/test/e2e/data/kustomize/v1alpha6/kustomization.yaml
index 9f7ac4445d..f2035ba071 100644
--- a/test/e2e/data/kustomize/v1alpha6/kustomization.yaml
+++ b/test/e2e/data/kustomize/v1alpha6/kustomization.yaml
@@ -4,6 +4,7 @@ resources:
- ../../../../../kustomize/v1alpha6/external-cloud-provider
components:
+- ../common-patches/cluster-prev1beta1
- ../common-patches/cni
- ../common-patches/ccm
diff --git a/test/e2e/data/kustomize/v1alpha7/kustomization.yaml b/test/e2e/data/kustomize/v1alpha7/kustomization.yaml
index ed5685505c..9bcee09929 100644
--- a/test/e2e/data/kustomize/v1alpha7/kustomization.yaml
+++ b/test/e2e/data/kustomize/v1alpha7/kustomization.yaml
@@ -4,6 +4,7 @@ resources:
- ../../../../../kustomize/v1alpha6/external-cloud-provider
components:
+- ../common-patches/cluster-prev1beta1
- ../common-patches/cni
- ../common-patches/ccm
diff --git a/test/e2e/data/kustomize/without-lb/kustomization.yaml b/test/e2e/data/kustomize/without-lb/kustomization.yaml
index 7f3842e60c..2d88085bde 100644
--- a/test/e2e/data/kustomize/without-lb/kustomization.yaml
+++ b/test/e2e/data/kustomize/without-lb/kustomization.yaml
@@ -4,6 +4,7 @@ resources:
- ../../../../../kustomize/v1beta1/without-lb
components:
+- ../common-patches/cluster
- ../common-patches/cni
- ../common-patches/ccm
- ../common-patches/externalNetworkByName
diff --git a/test/e2e/suites/apivalidations/filters_test.go b/test/e2e/suites/apivalidations/filters_test.go
index a6001c3ab2..e2bad140a5 100644
--- a/test/e2e/suites/apivalidations/filters_test.go
+++ b/test/e2e/suites/apivalidations/filters_test.go
@@ -36,7 +36,11 @@ var _ = Describe("Filter API validations", func() {
namespace = createNamespace()
// Initialise a basic machine object in the correct namespace
- machine = &infrav1.OpenStackMachine{}
+ machine = &infrav1.OpenStackMachine{
+ Spec: infrav1.OpenStackMachineSpec{
+ Image: infrav1.ImageParam{Filter: &infrav1.ImageFilter{Name: pointer.String("test-image")}},
+ },
+ }
machine.Namespace = namespace.Name
machine.GenerateName = "machine-"
@@ -179,49 +183,59 @@ var _ = Describe("Filter API validations", func() {
}),
)
- const imageUUID = "5a78f794-cdc3-48d2-8d9f-0fd472fdd743"
+ Context("ImageParam", func() {
+ const imageUUID = "5a78f794-cdc3-48d2-8d9f-0fd472fdd743"
- It("should not allow both ID and Name of ImageFilter to be set", func() {
- By("Creating a machine")
- machine.Spec.Image = infrav1.ImageFilter{
- ID: pointer.String(imageUUID),
- Name: pointer.String("bar"),
- }
- Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail")
- })
+ It("should not allow both ID and Filter to be set", func() {
+ machine.Spec.Image = infrav1.ImageParam{
+ ID: pointer.String(imageUUID),
+ Filter: &infrav1.ImageFilter{
+ Name: pointer.String("bar"),
+ },
+ }
+ Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail")
+ })
- It("should not allow both ID and Tags of ImageFilter to be set", func() {
- By("Creating a machine")
- machine.Spec.Image = infrav1.ImageFilter{
- ID: pointer.String(imageUUID),
- Tags: []string{"bar", "baz"},
- }
- Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail")
- })
+ It("should not allow both ID and Tags of ImageFilter to be set", func() {
+ machine.Spec.Image = infrav1.ImageParam{
+ ID: pointer.String(imageUUID),
+ Filter: &infrav1.ImageFilter{
+ Tags: []string{"bar", "baz"},
+ },
+ }
+ Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail")
+ })
- It("should allow UUID ID of ImageFilter to be set", func() {
- By("Creating a machine")
- machine.Spec.Image = infrav1.ImageFilter{
- ID: pointer.String(imageUUID),
- }
- Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "OpenStackMachine creation should succeed")
- })
+ It("should allow UUID ID of ImageFilter to be set", func() {
+ machine.Spec.Image = infrav1.ImageParam{
+ ID: pointer.String(imageUUID),
+ }
+ Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "OpenStackMachine creation should succeed")
+ })
- It("should not allow non-UUID ID of ImageFilter to be set", func() {
- By("Creating a machine")
- machine.Spec.Image = infrav1.ImageFilter{
- ID: pointer.String("foo"),
- }
- Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail")
- })
+ It("should not allow non-UUID ID of ImageFilter to be set", func() {
+ machine.Spec.Image = infrav1.ImageParam{
+ ID: pointer.String("foo"),
+ }
+ Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail")
+ })
- It("should allow Name and Tags of ImageFilter to be set", func() {
- By("Creating a machine")
- machine.Spec.Image = infrav1.ImageFilter{
- Name: pointer.String("bar"),
- Tags: []string{"bar", "baz"},
- }
- Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "OpenStackMachine creation should succeed")
+ It("should allow Name and Tags of ImageFilter to be set", func() {
+ machine.Spec.Image = infrav1.ImageParam{
+ Filter: &infrav1.ImageFilter{
+ Name: pointer.String("bar"),
+ Tags: []string{"bar", "baz"},
+ },
+ }
+ Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "OpenStackMachine creation should succeed")
+ })
+
+ It("should not allow a non-nil, empty image filter", func() {
+ machine.Spec.Image = infrav1.ImageParam{
+ Filter: &infrav1.ImageFilter{},
+ }
+ Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail")
+ })
})
Context("NetworkParam", func() {
diff --git a/test/e2e/suites/apivalidations/openstackcluster_test.go b/test/e2e/suites/apivalidations/openstackcluster_test.go
index f84e1d13d7..947f9b7b84 100644
--- a/test/e2e/suites/apivalidations/openstackcluster_test.go
+++ b/test/e2e/suites/apivalidations/openstackcluster_test.go
@@ -92,7 +92,11 @@ var _ = Describe("OpenStackCluster API validations", func() {
cluster.Spec.Bastion = &infrav1.Bastion{
Enabled: true,
Spec: &infrav1.OpenStackMachineSpec{
- Image: infrav1.ImageFilter{Name: pointer.String("fake-image")},
+ Image: infrav1.ImageParam{
+ Filter: &infrav1.ImageFilter{
+ Name: pointer.String("fake-image"),
+ },
+ },
},
}
Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
@@ -120,7 +124,11 @@ var _ = Describe("OpenStackCluster API validations", func() {
cluster.Spec.Bastion = &infrav1.Bastion{
Enabled: true,
Spec: &infrav1.OpenStackMachineSpec{
- Image: infrav1.ImageFilter{Name: pointer.String("fake-image")},
+ Image: infrav1.ImageParam{
+ Filter: &infrav1.ImageFilter{
+ Name: pointer.String("fake-image"),
+ },
+ },
},
FloatingIP: pointer.String("10.0.0.0"),
}
@@ -131,7 +139,11 @@ var _ = Describe("OpenStackCluster API validations", func() {
cluster.Spec.Bastion = &infrav1.Bastion{
Enabled: true,
Spec: &infrav1.OpenStackMachineSpec{
- Image: infrav1.ImageFilter{Name: pointer.String("fake-image")},
+ Image: infrav1.ImageParam{
+ Filter: &infrav1.ImageFilter{
+ Name: pointer.String("fake-image"),
+ },
+ },
},
FloatingIP: pointer.String("foobar"),
}
diff --git a/test/e2e/suites/apivalidations/openstackmachine_test.go b/test/e2e/suites/apivalidations/openstackmachine_test.go
index c984ab1e61..4e888a3a41 100644
--- a/test/e2e/suites/apivalidations/openstackmachine_test.go
+++ b/test/e2e/suites/apivalidations/openstackmachine_test.go
@@ -35,7 +35,11 @@ var _ = Describe("OpenStackMachine API validations", func() {
namespace = createNamespace()
// Initialise a basic machine object in the correct namespace
- machine = &infrav1.OpenStackMachine{}
+ machine = &infrav1.OpenStackMachine{
+ Spec: infrav1.OpenStackMachineSpec{
+ Image: infrav1.ImageParam{Filter: &infrav1.ImageFilter{Name: pointer.String("test-image")}},
+ },
+ }
machine.Namespace = namespace.Name
machine.GenerateName = "machine-"
})
diff --git a/test/e2e/suites/e2e/e2e_test.go b/test/e2e/suites/e2e/e2e_test.go
index fadae81131..37422eb33f 100644
--- a/test/e2e/suites/e2e/e2e_test.go
+++ b/test/e2e/suites/e2e/e2e_test.go
@@ -859,8 +859,10 @@ func makeOpenStackMachineTemplate(namespace, clusterName, name string) *infrav1.
Template: infrav1.OpenStackMachineTemplateResource{
Spec: infrav1.OpenStackMachineSpec{
Flavor: e2eCtx.E2EConfig.GetVariable(shared.OpenStackNodeMachineFlavor),
- Image: infrav1.ImageFilter{
- Name: pointer.String(e2eCtx.E2EConfig.GetVariable(shared.OpenStackImageName)),
+ Image: infrav1.ImageParam{
+ Filter: &infrav1.ImageFilter{
+ Name: pointer.String(e2eCtx.E2EConfig.GetVariable(shared.OpenStackImageName)),
+ },
},
SSHKeyName: shared.DefaultSSHKeyPairName,
IdentityRef: &infrav1.OpenStackIdentityReference{
@@ -883,8 +885,10 @@ func makeOpenStackMachineTemplateWithPortOptions(namespace, clusterName, name st
Template: infrav1.OpenStackMachineTemplateResource{
Spec: infrav1.OpenStackMachineSpec{
Flavor: e2eCtx.E2EConfig.GetVariable(shared.OpenStackNodeMachineFlavor),
- Image: infrav1.ImageFilter{
- Name: pointer.String(e2eCtx.E2EConfig.GetVariable(shared.OpenStackImageName)),
+ Image: infrav1.ImageParam{
+ Filter: &infrav1.ImageFilter{
+ Name: pointer.String(e2eCtx.E2EConfig.GetVariable(shared.OpenStackImageName)),
+ },
},
SSHKeyName: shared.DefaultSSHKeyPairName,
IdentityRef: &infrav1.OpenStackIdentityReference{
diff --git a/test/helpers/fuzzerfuncs.go b/test/helpers/fuzzerfuncs.go
index 2c3a0fe188..36ee8baa85 100644
--- a/test/helpers/fuzzerfuncs.go
+++ b/test/helpers/fuzzerfuncs.go
@@ -141,5 +141,9 @@ func InfraV1FuzzerFuncs() []interface{} {
func(param *infrav1.SecurityGroupParam, c fuzz.Continue) {
fuzzFilterParam(¶m.ID, ¶m.Filter, c)
},
+
+ func(param *infrav1.ImageParam, c fuzz.Continue) {
+ fuzzFilterParam(¶m.ID, ¶m.Filter, c)
+ },
}
}
From 5c3fe97e7542dc5c5c52d9a0b7f48d2168ead1fc Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Wed, 27 Mar 2024 19:45:15 +0000
Subject: [PATCH 155/180] RouterFilter to RouterParam
---
api/v1alpha7/openstackcluster_conversion.go | 1 +
api/v1alpha7/types_conversion.go | 56 ++++-
api/v1alpha7/zz_generated.conversion.go | 19 +-
api/v1beta1/openstackcluster_types.go | 2 +-
api/v1beta1/types.go | 26 ++-
api/v1beta1/zz_generated.deepcopy.go | 27 ++-
...re.cluster.x-k8s.io_openstackclusters.yaml | 129 ++++++-----
...er.x-k8s.io_openstackclustertemplates.yaml | 130 ++++++-----
docs/book/src/api/v1beta1/api.md | 69 ++++--
pkg/cloud/services/networking/router.go | 117 +++++++---
pkg/cloud/services/networking/router_test.go | 217 ++++++++++++++++++
pkg/utils/errors/errors.go | 4 +
pkg/utils/filterconvert/convert.go | 1 -
.../e2e/suites/apivalidations/filters_test.go | 47 +++-
test/helpers/fuzzerfuncs.go | 4 +
15 files changed, 658 insertions(+), 191 deletions(-)
create mode 100644 pkg/cloud/services/networking/router_test.go
diff --git a/api/v1alpha7/openstackcluster_conversion.go b/api/v1alpha7/openstackcluster_conversion.go
index 75e92032d1..4f06e21cc4 100644
--- a/api/v1alpha7/openstackcluster_conversion.go
+++ b/api/v1alpha7/openstackcluster_conversion.go
@@ -189,6 +189,7 @@ func restorev1beta1ClusterSpec(previous *infrav1.OpenStackClusterSpec, dst *infr
dst.DisableExternalNetwork = previous.DisableExternalNetwork
+ restorev1beta1RouterParam(previous.Router, dst.Router)
restorev1beta1NetworkParam(previous.Network, dst.Network)
if len(previous.Subnets) > 0 && len(dst.Subnets) > 0 {
diff --git a/api/v1alpha7/types_conversion.go b/api/v1alpha7/types_conversion.go
index f98207a409..d7c33ec3ef 100644
--- a/api/v1alpha7/types_conversion.go
+++ b/api/v1alpha7/types_conversion.go
@@ -242,21 +242,55 @@ func restorev1alpha7RouterFilter(previous *RouterFilter, dst *RouterFilter) {
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 dst.Filter != nil {
+ dst.Filter.FilterByNeutronTags = previous.Filter.FilterByNeutronTags
+ }
}
-func Convert_v1alpha7_RouterFilter_To_v1beta1_RouterFilter(in *RouterFilter, out *infrav1.RouterFilter, s apiconversion.Scope) error {
- if err := autoConvert_v1alpha7_RouterFilter_To_v1beta1_RouterFilter(in, out, s); err != nil {
+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, &out.FilterByNeutronTags)
+ infrav1.ConvertAllTagsTo(in.Tags, in.TagsAny, in.NotTags, in.NotTagsAny, &filter.FilterByNeutronTags)
+ if !filter.IsZero() {
+ out.Filter = filter
+ }
return nil
}
-func Convert_v1beta1_RouterFilter_To_v1alpha7_RouterFilter(in *infrav1.RouterFilter, out *RouterFilter, s apiconversion.Scope) error {
- if err := autoConvert_v1beta1_RouterFilter_To_v1alpha7_RouterFilter(in, out, s); err != nil {
- return err
+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)
}
- infrav1.ConvertAllTagsFrom(&in.FilterByNeutronTags, &out.Tags, &out.TagsAny, &out.NotTags, &out.NotTagsAny)
return nil
}
@@ -504,3 +538,11 @@ func Convert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(_ *Secu
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
index 87bb5dc328..c202a6787b 100644
--- a/api/v1alpha7/zz_generated.conversion.go
+++ b/api/v1alpha7/zz_generated.conversion.go
@@ -366,6 +366,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); 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 {
@@ -446,6 +451,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); 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 {
@@ -929,8 +939,8 @@ func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(i
// 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.RouterFilter)
- if err := Convert_v1alpha7_RouterFilter_To_v1beta1_RouterFilter(*in, *out, s); err != nil {
+ *out = new(v1beta1.RouterParam)
+ if err := Convert_v1alpha7_RouterFilter_To_v1beta1_RouterParam(*in, *out, s); err != nil {
return err
}
} else {
@@ -996,7 +1006,7 @@ func autoConvert_v1beta1_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(i
if in.Router != nil {
in, out := &in.Router, &out.Router
*out = new(RouterFilter)
- if err := Convert_v1beta1_RouterFilter_To_v1alpha7_RouterFilter(*in, *out, s); err != nil {
+ if err := Convert_v1beta1_RouterParam_To_v1alpha7_RouterFilter(*in, *out, s); err != nil {
return err
}
} else {
@@ -1727,7 +1737,7 @@ func Convert_v1beta1_Router_To_v1alpha7_Router(in *v1beta1.Router, out *Router,
}
func autoConvert_v1alpha7_RouterFilter_To_v1beta1_RouterFilter(in *RouterFilter, out *v1beta1.RouterFilter, s conversion.Scope) error {
- out.ID = in.ID
+ // WARNING: in.ID requires manual conversion: does not exist in peer-type
out.Name = in.Name
out.Description = in.Description
out.ProjectID = in.ProjectID
@@ -1739,7 +1749,6 @@ func autoConvert_v1alpha7_RouterFilter_To_v1beta1_RouterFilter(in *RouterFilter,
}
func autoConvert_v1beta1_RouterFilter_To_v1alpha7_RouterFilter(in *v1beta1.RouterFilter, out *RouterFilter, s conversion.Scope) error {
- out.ID = in.ID
out.Name = in.Name
out.Description = in.Description
out.ProjectID = in.ProjectID
diff --git a/api/v1beta1/openstackcluster_types.go b/api/v1beta1/openstackcluster_types.go
index b1566c01ac..d6745e5ccd 100644
--- a/api/v1beta1/openstackcluster_types.go
+++ b/api/v1beta1/openstackcluster_types.go
@@ -43,7 +43,7 @@ type OpenStackClusterSpec struct {
// 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"`
+ Router *RouterParam `json:"router,omitempty"`
// Network specifies an existing network to use if no ManagedSubnets
// are specified.
diff --git a/api/v1beta1/types.go b/api/v1beta1/types.go
index e9b9bbb2f6..492546e755 100644
--- a/api/v1beta1/types.go
+++ b/api/v1beta1/types.go
@@ -220,8 +220,22 @@ func (subnetFilter *SubnetFilter) IsZero() bool {
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 {
- ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
ProjectID string `json:"projectID,omitempty"`
@@ -229,6 +243,16 @@ type RouterFilter struct {
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.
diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go
index 9c8f75f97f..088e9c46f2 100644
--- a/api/v1beta1/zz_generated.deepcopy.go
+++ b/api/v1beta1/zz_generated.deepcopy.go
@@ -576,7 +576,7 @@ func (in *OpenStackClusterSpec) DeepCopyInto(out *OpenStackClusterSpec) {
}
if in.Router != nil {
in, out := &in.Router, &out.Router
- *out = new(RouterFilter)
+ *out = new(RouterParam)
(*in).DeepCopyInto(*out)
}
if in.Network != nil {
@@ -1419,6 +1419,31 @@ func (in *RouterFilter) DeepCopy() *RouterFilter {
return out
}
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *RouterParam) DeepCopyInto(out *RouterParam) {
+ *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 RouterParam.
+func (in *RouterParam) DeepCopy() *RouterParam {
+ if in == nil {
+ return nil
+ }
+ out := new(RouterParam)
+ in.DeepCopyInto(out)
+ return out
+}
+
// 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
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 1490e10a21..5056e60154 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -6145,68 +6145,79 @@ spec:
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:
- description:
- type: string
+ 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
- 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
subnets:
description: |-
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 c0a334ec4c..5f25ff93c1 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -3586,68 +3586,80 @@ spec:
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:
- description:
- type: string
+ 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
- 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
subnets:
description: |-
diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md
index 581f7326ef..217373dd46 100644
--- a/docs/book/src/api/v1beta1/api.md
+++ b/docs/book/src/api/v1beta1/api.md
@@ -87,8 +87,8 @@ subnet is supported. If you leave this empty, no network will be created.
router
-
-RouterFilter
+
+RouterParam
|
@@ -2098,8 +2098,8 @@ subnet is supported. If you leave this empty, no network will be created.
router
-
-RouterFilter
+
+RouterParam
|
@@ -2680,8 +2680,8 @@ subnet is supported. If you leave this empty, no network will be created.
router
-
-RouterFilter
+
+RouterParam
|
@@ -4358,9 +4358,10 @@ string
(Appears on:
-OpenStackClusterSpec)
+RouterParam)
+
RouterFilter specifies a query to select an OpenStack router. At least one property must be set.
@@ -4372,16 +4373,6 @@ string
-id
-
-string
-
- |
-
- |
-
-
-
name
string
@@ -4427,6 +4418,50 @@ FilterByNeutronTags
|
+RouterParam
+
+
+(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.
+ |
+
+
+
SecurityGroupFilter
diff --git a/pkg/cloud/services/networking/router.go b/pkg/cloud/services/networking/router.go
index 7940222f74..8afbda481c 100644
--- a/pkg/cloud/services/networking/router.go
+++ b/pkg/cloud/services/networking/router.go
@@ -17,6 +17,7 @@ limitations under the License.
package networking
import (
+ "errors"
"fmt"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/attributestags"
@@ -46,32 +47,23 @@ func (s *Service) ReconcileRouter(openStackCluster *infrav1.OpenStackCluster, cl
}
s.scope.Logger().Info("Reconciling router", "cluster", clusterResourceName)
- routerName := getRouterName(clusterResourceName)
- routerListOpts := routers.ListOpts{Name: routerName}
- existingRouter := false
- if openStackCluster.Spec.Router != nil {
- routerListOpts = filterconvert.RouterFilterToListOpts(openStackCluster.Spec.Router)
- existingRouter = true
- }
- router, err := s.getRouterByFilter(routerListOpts)
+ router, err := s.getExistingRouter(openStackCluster, clusterResourceName)
if err != nil {
- return err
+ return fmt.Errorf("fetching router: %w", err)
}
- if existingRouter && router.ID == "" {
- return fmt.Errorf("router not found by routerFilter ")
- }
+ if router == nil {
+ if openStackCluster.Spec.Router != nil {
+ // Should not happen: will have returned ErrNoMatches above
+ return fmt.Errorf("router not found")
+ }
- if router.ID == "" {
var err error
- createdRouter, err := s.createRouter(openStackCluster, clusterResourceName, routerName)
+ router, err = s.createRouter(openStackCluster, clusterResourceName, getRouterName(clusterResourceName))
if err != nil {
return err
}
- router = *createdRouter
- } else {
- s.scope.Logger().V(6).Info("Reusing existing router", "name", router.Name, "id", router.ID)
}
routerIPs := []string{}
@@ -87,7 +79,7 @@ func (s *Service) ReconcileRouter(openStackCluster *infrav1.OpenStackCluster, cl
}
if len(openStackCluster.Spec.ExternalRouterIPs) > 0 {
- if err := s.setRouterExternalIPs(openStackCluster, &router); err != nil {
+ if err := s.setRouterExternalIPs(openStackCluster, router); err != nil {
return err
}
}
@@ -125,6 +117,63 @@ func (s *Service) ReconcileRouter(openStackCluster *infrav1.OpenStackCluster, cl
return nil
}
+func (s *Service) getExistingRouter(openStackCluster *infrav1.OpenStackCluster, clusterResourceName string) (*routers.Router, error) {
+ // For an externally-managed router we always expect it to exist. We will return an error if it doesn't.
+ if openStackCluster.Spec.Router != nil {
+ return s.getExternallyManagedRouter(openStackCluster)
+ }
+
+ // A managed router may not exist either because we haven't created it
+ // or because we deleted it. Swallow NotFound errors and return nil.
+
+ if openStackCluster.Status.Router != nil {
+ router, err := s.client.GetRouter(openStackCluster.Status.Router.ID)
+ if capoerrors.IsNotFound(err) {
+ return nil, nil
+ }
+ return router, err
+ }
+
+ routerName := getRouterName(clusterResourceName)
+ listOpts := routers.ListOpts{Name: routerName}
+ if openStackCluster.Spec.Router != nil {
+ listOpts = filterconvert.RouterFilterToListOpts(openStackCluster.Spec.Router.Filter)
+ }
+
+ router, err := s.getRouterByFilter(listOpts)
+ // It's ok if our managed router doesn't exist yet, just return nil
+ if errors.Is(err, ErrNoMatches) {
+ return nil, nil
+ }
+ return router, err
+}
+
+func (s *Service) getExternallyManagedRouter(openStackCluster *infrav1.OpenStackCluster) (*routers.Router, error) {
+ if openStackCluster.Spec.Router == nil {
+ return nil, fmt.Errorf("getExternallyManagedRouter called with no external router specified")
+ }
+
+ // Fetch by ID if we previously resolved it
+ if openStackCluster.Status.Router != nil {
+ return s.client.GetRouter(openStackCluster.Status.Router.ID)
+ }
+ return s.getRouterByParam(openStackCluster.Spec.Router)
+}
+
+func (s *Service) getRouterByParam(routerParam *infrav1.RouterParam) (*routers.Router, error) {
+ if routerParam.ID != nil {
+ return s.client.GetRouter(*routerParam.ID)
+ }
+
+ if routerParam.Filter == nil {
+ // Should have been caught by validation
+ return nil, errors.New("invalid router param, either ID or Filter must be set")
+ }
+
+ listOpts := filterconvert.RouterFilterToListOpts(routerParam.Filter)
+ return s.getRouterByFilter(listOpts)
+}
+
func (s *Service) createRouter(openStackCluster *infrav1.OpenStackCluster, clusterResourceName, name string) (*routers.Router, error) {
opts := routers.CreateOpts{
Description: names.GetDescription(clusterResourceName),
@@ -189,29 +238,21 @@ func (s *Service) setRouterExternalIPs(openStackCluster *infrav1.OpenStackCluste
}
func (s *Service) DeleteRouter(openStackCluster *infrav1.OpenStackCluster, clusterResourceName string) error {
- routerName := getRouterName(clusterResourceName)
- listOpts := routers.ListOpts{Name: routerName}
- existingRouter := false
- if openStackCluster.Spec.Router != nil {
- listOpts = filterconvert.RouterFilterToListOpts(openStackCluster.Spec.Router)
- existingRouter = true
- }
-
- router, err := s.getRouterByFilter(listOpts)
+ router, err := s.getExistingRouter(openStackCluster, clusterResourceName)
if err != nil {
return err
}
+ if router == nil {
+ return nil
+ }
+
subnetName := getSubnetName(clusterResourceName)
subnet, err := s.getSubnetByName(subnetName)
if err != nil {
return err
}
- if router.ID == "" {
- return nil
- }
-
if subnet.ID != "" {
_, err = s.client.RemoveRouterInterface(router.ID, routers.RemoveInterfaceOpts{
SubnetID: subnet.ID,
@@ -226,8 +267,8 @@ func (s *Service) DeleteRouter(openStackCluster *infrav1.OpenStackCluster, clust
}
}
- if existingRouter {
- s.scope.Logger().V(4).Info("No need to delete pre-existing router", "name", router.Name)
+ if openStackCluster.Spec.Router != nil {
+ s.scope.Logger().V(4).Info("Not deleting pre-existing router", "name", router.Name)
return nil
}
@@ -247,19 +288,19 @@ func (s *Service) getRouterInterfaces(routerID string) ([]ports.Port, error) {
})
}
-func (s *Service) getRouterByFilter(opts routers.ListOpts) (routers.Router, error) {
+func (s *Service) getRouterByFilter(opts routers.ListOpts) (*routers.Router, error) {
routerList, err := s.client.ListRouter(opts)
if err != nil {
- return routers.Router{}, err
+ return nil, err
}
switch len(routerList) {
case 0:
- return routers.Router{}, nil
+ return nil, ErrNoMatches
case 1:
- return routerList[0], nil
+ return &routerList[0], nil
}
- return routers.Router{}, fmt.Errorf("found %d routers, which should not happen", len(routerList))
+ return nil, ErrMultipleMatches
}
func (s *Service) getSubnetByName(subnetName string) (subnets.Subnet, error) {
diff --git a/pkg/cloud/services/networking/router_test.go b/pkg/cloud/services/networking/router_test.go
new file mode 100644
index 0000000000..722107e62f
--- /dev/null
+++ b/pkg/cloud/services/networking/router_test.go
@@ -0,0 +1,217 @@
+/*
+Copyright 2018 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 networking
+
+import (
+ "testing"
+
+ "github.com/go-logr/logr/testr"
+ "github.com/golang/mock/gomock"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
+ . "github.com/onsi/gomega"
+
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
+ "sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/mock"
+ "sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
+)
+
+func TestService_DeleteRouter(t *testing.T) {
+ const (
+ clusterResourceName = "test-cluster"
+ resourceName = "k8s-clusterapi-cluster-test-cluster"
+
+ routerID = "38052015-5cbc-4cb4-8e45-445d53260f60"
+ subnetID = "283ee906-0072-4c81-92fb-9858e90c3c4e"
+ )
+ tests := []struct {
+ name string
+ openStackCluster infrav1.OpenStackCluster
+ expect func(g Gomega, m *mock.MockNetworkClientMockRecorder)
+ wantErr bool
+ }{
+ {
+ name: "Managed router in status exists",
+ openStackCluster: infrav1.OpenStackCluster{
+ Status: infrav1.OpenStackClusterStatus{
+ Router: &infrav1.Router{
+ ID: routerID,
+ },
+ },
+ },
+ expect: func(g Gomega, m *mock.MockNetworkClientMockRecorder) {
+ // Get by ID in status
+ // Remove subnet interfaces
+ // Delete router
+ m.GetRouter(routerID).Return(&routers.Router{ID: routerID}, nil)
+ m.ListSubnet(gomock.Any()).DoAndReturn(func(opts subnets.ListOpts) ([]subnets.Subnet, error) {
+ g.Expect(opts.Name).To(Equal(resourceName))
+ return []subnets.Subnet{
+ {ID: subnetID, Name: resourceName},
+ }, nil
+ })
+ m.RemoveRouterInterface(routerID, routers.RemoveInterfaceOpts{SubnetID: subnetID}).Return(&routers.InterfaceInfo{}, nil)
+ m.DeleteRouter(routerID).Return(nil)
+ },
+ },
+ {
+ name: "Managed router in status does not exist",
+ openStackCluster: infrav1.OpenStackCluster{
+ Status: infrav1.OpenStackClusterStatus{
+ Router: &infrav1.Router{
+ ID: routerID,
+ },
+ },
+ },
+ expect: func(g Gomega, m *mock.MockNetworkClientMockRecorder) {
+ // Get by ID in status returns 404
+ // No further action
+ m.GetRouter(routerID).Return(&routers.Router{ID: routerID}, gophercloud.ErrDefault404{})
+ },
+ },
+ {
+ name: "Managed router not in status exists",
+ openStackCluster: infrav1.OpenStackCluster{},
+ expect: func(g Gomega, m *mock.MockNetworkClientMockRecorder) {
+ // Lookup by cluster resource name
+ // Remove subnet interfaces
+ // Delete router
+ m.ListRouter(gomock.Any()).DoAndReturn(func(opts routers.ListOpts) ([]routers.Router, error) {
+ g.Expect(opts.Name).To(Equal(resourceName))
+ return []routers.Router{
+ {ID: routerID, Name: resourceName},
+ }, nil
+ })
+ m.ListSubnet(gomock.Any()).DoAndReturn(func(opts subnets.ListOpts) ([]subnets.Subnet, error) {
+ g.Expect(opts.Name).To(Equal(resourceName))
+ return []subnets.Subnet{
+ {ID: subnetID, Name: resourceName},
+ }, nil
+ })
+ m.RemoveRouterInterface(routerID, routers.RemoveInterfaceOpts{SubnetID: subnetID}).Return(&routers.InterfaceInfo{}, nil)
+ m.DeleteRouter(routerID).Return(nil)
+ },
+ },
+ {
+ name: "Managed router not in status does not exist",
+ openStackCluster: infrav1.OpenStackCluster{},
+ expect: func(g Gomega, m *mock.MockNetworkClientMockRecorder) {
+ // Lookup by cluster resource name returns 404
+ // No further action
+ m.ListRouter(gomock.Any()).DoAndReturn(func(opts routers.ListOpts) ([]routers.Router, error) {
+ g.Expect(opts.Name).To(Equal(resourceName))
+ return []routers.Router{}, nil
+ })
+ },
+ },
+ {
+ name: "Unmanaged router in status exists",
+ openStackCluster: infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ Router: &infrav1.RouterParam{
+ Filter: &infrav1.RouterFilter{
+ Name: "my-router",
+ },
+ },
+ },
+ Status: infrav1.OpenStackClusterStatus{
+ Router: &infrav1.Router{
+ ID: routerID,
+ },
+ },
+ },
+ expect: func(g Gomega, m *mock.MockNetworkClientMockRecorder) {
+ // Get by ID in status
+ // Remove subnet interfaces
+ // Don't delete unmanaged router
+ m.GetRouter(routerID).Return(&routers.Router{ID: routerID}, nil)
+ m.ListSubnet(gomock.Any()).DoAndReturn(func(opts subnets.ListOpts) ([]subnets.Subnet, error) {
+ g.Expect(opts.Name).To(Equal(resourceName))
+ return []subnets.Subnet{
+ {ID: subnetID, Name: resourceName},
+ }, nil
+ })
+ m.RemoveRouterInterface(routerID, routers.RemoveInterfaceOpts{SubnetID: subnetID}).Return(&routers.InterfaceInfo{}, nil)
+ },
+ },
+ {
+ name: "Unmanaged router in status does not exist",
+ openStackCluster: infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ Router: &infrav1.RouterParam{
+ Filter: &infrav1.RouterFilter{
+ Name: "my-router",
+ },
+ },
+ },
+ Status: infrav1.OpenStackClusterStatus{
+ Router: &infrav1.Router{
+ ID: routerID,
+ },
+ },
+ },
+ expect: func(g Gomega, m *mock.MockNetworkClientMockRecorder) {
+ // Get by ID in status returns 404
+ // Error
+ m.GetRouter(routerID).Return(nil, gophercloud.ErrDefault404{})
+ },
+ wantErr: true,
+ },
+ {
+ name: "Unmanaged router not in status does not exist",
+ openStackCluster: infrav1.OpenStackCluster{
+ Spec: infrav1.OpenStackClusterSpec{
+ Router: &infrav1.RouterParam{
+ Filter: &infrav1.RouterFilter{
+ Name: "my-router",
+ },
+ },
+ },
+ },
+ expect: func(g Gomega, m *mock.MockNetworkClientMockRecorder) {
+ // Lookup by name returns no results
+ // Error
+ m.ListRouter(gomock.Any()).DoAndReturn(func(opts routers.ListOpts) ([]routers.Router, error) {
+ g.Expect(opts.Name).To(Equal("my-router"))
+ return []routers.Router{}, nil
+ })
+ },
+ wantErr: true,
+ },
+ }
+ for i := range tests {
+ tt := &tests[i]
+ t.Run(tt.name, func(t *testing.T) {
+ mockCtrl := gomock.NewController(t)
+ defer mockCtrl.Finish()
+
+ g := NewWithT(t)
+ log := testr.New(t)
+
+ mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "")
+ s, err := NewService(scope.NewWithLogger(mockScopeFactory, log))
+ g.Expect(err).NotTo(HaveOccurred())
+
+ tt.expect(g, mockScopeFactory.NetworkClient.EXPECT())
+
+ if err := s.DeleteRouter(&tt.openStackCluster, clusterResourceName); (err != nil) != tt.wantErr {
+ t.Errorf("Service.DeleteRouter() error = %v, wantErr %v", err, tt.wantErr)
+ }
+ })
+ }
+}
diff --git a/pkg/utils/errors/errors.go b/pkg/utils/errors/errors.go
index a2ff9d67af..d8ed44a972 100644
--- a/pkg/utils/errors/errors.go
+++ b/pkg/utils/errors/errors.go
@@ -33,6 +33,10 @@ func IsRetryable(err error) bool {
}
func IsNotFound(err error) bool {
+ if err == nil {
+ return false
+ }
+
// Gophercloud is not consistent in how it returns 404 errors. Sometimes
// it returns a pointer to the error, sometimes it returns the error
// directly.
diff --git a/pkg/utils/filterconvert/convert.go b/pkg/utils/filterconvert/convert.go
index 8ece362ab6..9948722abf 100644
--- a/pkg/utils/filterconvert/convert.go
+++ b/pkg/utils/filterconvert/convert.go
@@ -81,7 +81,6 @@ func RouterFilterToListOpts(routerFilter *infrav1.RouterFilter) routers.ListOpts
return routers.ListOpts{}
}
return routers.ListOpts{
- ID: routerFilter.ID,
Name: routerFilter.Name,
Description: routerFilter.Description,
ProjectID: routerFilter.ProjectID,
diff --git a/test/e2e/suites/apivalidations/filters_test.go b/test/e2e/suites/apivalidations/filters_test.go
index e2bad140a5..c451a620e3 100644
--- a/test/e2e/suites/apivalidations/filters_test.go
+++ b/test/e2e/suites/apivalidations/filters_test.go
@@ -82,7 +82,7 @@ var _ = Describe("Filter API validations", func() {
if len(tags) > 0 {
cluster.Spec.Network = &infrav1.NetworkParam{Filter: &infrav1.NetworkFilter{FilterByNeutronTags: tags[0]}}
cluster.Spec.ExternalNetwork = &infrav1.NetworkParam{Filter: &infrav1.NetworkFilter{FilterByNeutronTags: tags[0]}}
- cluster.Spec.Router = &infrav1.RouterFilter{FilterByNeutronTags: tags[0]}
+ cluster.Spec.Router = &infrav1.RouterParam{Filter: &infrav1.RouterFilter{FilterByNeutronTags: tags[0]}}
}
Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
},
@@ -158,7 +158,7 @@ var _ = Describe("Filter API validations", func() {
{
cluster := cluster.DeepCopy()
- cluster.Spec.Router = &infrav1.RouterFilter{FilterByNeutronTags: tag}
+ cluster.Spec.Router = &infrav1.RouterParam{Filter: &infrav1.RouterFilter{FilterByNeutronTags: tag}}
Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should fail with invalid router neutron tags")
}
}
@@ -363,4 +363,47 @@ var _ = Describe("Filter API validations", func() {
Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail")
})
})
+
+ Context("RouterParam", func() {
+ It("should allow setting ID", func() {
+ cluster.Spec.Router = &infrav1.RouterParam{
+ ID: pointer.String("06c32c52-f207-4f6a-a769-bbcbe5a43f5c"),
+ }
+ Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
+ })
+
+ It("should allow setting non-empty Filter", func() {
+ cluster.Spec.Router = &infrav1.RouterParam{
+ Filter: &infrav1.RouterFilter{Name: "foo"},
+ }
+ Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
+ })
+
+ It("should not allow setting empty RouterParam", func() {
+ cluster.Spec.Router = &infrav1.RouterParam{}
+ Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should fail")
+ })
+
+ It("should not allow setting invalid id", func() {
+ cluster.Spec.Router = &infrav1.RouterParam{
+ ID: pointer.String("foo"),
+ }
+ Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should fail")
+ })
+
+ It("should not allow setting empty Filter", func() {
+ cluster.Spec.Router = &infrav1.RouterParam{
+ Filter: &infrav1.RouterFilter{},
+ }
+ Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should fail")
+ })
+
+ It("should not allow setting both ID and Filter", func() {
+ cluster.Spec.Router = &infrav1.RouterParam{
+ ID: pointer.String("06c32c52-f207-4f6a-a769-bbcbe5a43f5c"),
+ Filter: &infrav1.RouterFilter{Name: "foo"},
+ }
+ Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should fail")
+ })
+ })
})
diff --git a/test/helpers/fuzzerfuncs.go b/test/helpers/fuzzerfuncs.go
index 36ee8baa85..b181e02c45 100644
--- a/test/helpers/fuzzerfuncs.go
+++ b/test/helpers/fuzzerfuncs.go
@@ -145,5 +145,9 @@ func InfraV1FuzzerFuncs() []interface{} {
func(param *infrav1.ImageParam, c fuzz.Continue) {
fuzzFilterParam(¶m.ID, ¶m.Filter, c)
},
+
+ func(param *infrav1.RouterParam, c fuzz.Continue) {
+ fuzzFilterParam(¶m.ID, ¶m.Filter, c)
+ },
}
}
From a2ba9c52d5c4b9c1cda75612f169680c54f2bfa7 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Mon, 1 Apr 2024 10:17:12 +0100
Subject: [PATCH 156/180] Fix v1alpha7 machine restorer and test
The v1alpha7 machine spec restorer was missing the exclusion for
ProviderID and InstanceID was missing, and the test which was supposed
to ensure it worked was broken. This fixes both.
---
api/v1alpha7/conversion_test.go | 52 +++++++++++++--------
api/v1alpha7/openstackmachine_conversion.go | 13 ++++++
2 files changed, 46 insertions(+), 19 deletions(-)
diff --git a/api/v1alpha7/conversion_test.go b/api/v1alpha7/conversion_test.go
index 57364304b4..7abfc7bc91 100644
--- a/api/v1alpha7/conversion_test.go
+++ b/api/v1alpha7/conversion_test.go
@@ -166,22 +166,24 @@ func TestFuzzyConversion(t *testing.T) {
func TestMachineConversionControllerSpecFields(t *testing.T) {
// This tests that we still do field restoration when the controller modifies ProviderID and InstanceID in the spec
- g := gomega.NewWithT(t)
- scheme := runtime.NewScheme()
- g.Expect(AddToScheme(scheme)).To(gomega.Succeed())
- g.Expect(infrav1.AddToScheme(scheme)).To(gomega.Succeed())
-
+ // 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{},
+ Spec: OpenStackMachineSpec{
+ IdentityRef: &OpenStackIdentityReference{
+ Kind: "InvalidKind",
+ Name: "test-name",
+ },
+ },
}
}
tests := []struct {
- name string
- modifyUp func(*infrav1.OpenStackMachine)
- testAfter func(*OpenStackMachine)
- expectNetworkDiff bool
+ name string
+ modifyUp func(*infrav1.OpenStackMachine)
+ testAfter func(gomega.Gomega, *OpenStackMachine)
+ expectIdentityRefDiff bool
}{
{
name: "No change",
@@ -191,30 +193,30 @@ func TestMachineConversionControllerSpecFields(t *testing.T) {
modifyUp: func(up *infrav1.OpenStackMachine) {
up.Spec.Flavor = "new-flavor"
},
- testAfter: func(after *OpenStackMachine) {
+ testAfter: func(g gomega.Gomega, after *OpenStackMachine) {
g.Expect(after.Spec.Flavor).To(gomega.Equal("new-flavor"))
},
- expectNetworkDiff: true,
+ expectIdentityRefDiff: true,
},
{
name: "Set ProviderID",
modifyUp: func(up *infrav1.OpenStackMachine) {
up.Spec.ProviderID = pointer.String("new-provider-id")
},
- testAfter: func(after *OpenStackMachine) {
+ testAfter: func(g gomega.Gomega, after *OpenStackMachine) {
g.Expect(after.Spec.ProviderID).To(gomega.Equal(pointer.String("new-provider-id")))
},
- expectNetworkDiff: false,
+ expectIdentityRefDiff: false,
},
{
name: "Set InstanceID",
modifyUp: func(up *infrav1.OpenStackMachine) {
up.Spec.InstanceID = pointer.String("new-instance-id")
},
- testAfter: func(after *OpenStackMachine) {
+ testAfter: func(g gomega.Gomega, after *OpenStackMachine) {
g.Expect(after.Spec.InstanceID).To(gomega.Equal(pointer.String("new-instance-id")))
},
- expectNetworkDiff: false,
+ expectIdentityRefDiff: false,
},
{
name: "Set ProviderID and non-ignored change",
@@ -222,16 +224,21 @@ func TestMachineConversionControllerSpecFields(t *testing.T) {
up.Spec.ProviderID = pointer.String("new-provider-id")
up.Spec.Flavor = "new-flavor"
},
- testAfter: func(after *OpenStackMachine) {
+ testAfter: func(g gomega.Gomega, after *OpenStackMachine) {
g.Expect(after.Spec.ProviderID).To(gomega.Equal(pointer.String("new-provider-id")))
g.Expect(after.Spec.Flavor).To(gomega.Equal("new-flavor"))
},
- expectNetworkDiff: true,
+ 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{}
@@ -245,7 +252,14 @@ func TestMachineConversionControllerSpecFields(t *testing.T) {
g.Expect(after.ConvertFrom(&up)).To(gomega.Succeed())
if tt.testAfter != nil {
- tt.testAfter(&after)
+ 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"))
}
})
}
diff --git a/api/v1alpha7/openstackmachine_conversion.go b/api/v1alpha7/openstackmachine_conversion.go
index 4731f7445c..6547fa10e1 100644
--- a/api/v1alpha7/openstackmachine_conversion.go
+++ b/api/v1alpha7/openstackmachine_conversion.go
@@ -66,6 +66,19 @@ var v1alpha7OpenStackMachineRestorer = conversion.RestorerFor[*OpenStackMachine]
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
+ }),
),
}
From 5c1ad44dbb0de3ed6aff740a844b7ee1e511a161 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Mon, 1 Apr 2024 11:23:45 +0100
Subject: [PATCH 157/180] Move InstanceID from spec to status
---
api/v1alpha5/zz_generated.conversion.go | 4 +-
api/v1alpha6/conversion_test.go | 2 +-
api/v1alpha6/openstackcluster_conversion.go | 5 +++
api/v1alpha6/openstackmachine_conversion.go | 20 +++++++++
.../openstackmachinetemplate_conversion.go | 12 ++++-
api/v1alpha6/zz_generated.conversion.go | 34 +++++---------
api/v1alpha7/conversion_test.go | 2 +-
api/v1alpha7/openstackcluster_conversion.go | 9 +++-
api/v1alpha7/openstackmachine_conversion.go | 22 +++++++++
.../openstackmachinetemplate_conversion.go | 9 +++-
api/v1alpha7/zz_generated.conversion.go | 34 +++++---------
api/v1beta1/openstackmachine_types.go | 9 ++--
api/v1beta1/zz_generated.deepcopy.go | 10 ++---
...re.cluster.x-k8s.io_openstackclusters.yaml | 4 --
...er.x-k8s.io_openstackclustertemplates.yaml | 4 --
...re.cluster.x-k8s.io_openstackmachines.yaml | 6 +--
...er.x-k8s.io_openstackmachinetemplates.yaml | 4 --
controllers/openstackmachine_controller.go | 20 ++++-----
controllers/suite_test.go | 2 +-
docs/book/src/api/v1beta1/api.md | 45 +++++--------------
20 files changed, 138 insertions(+), 119 deletions(-)
diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go
index 2c5a688927..9c9ad2d04b 100644
--- a/api/v1alpha5/zz_generated.conversion.go
+++ b/api/v1alpha5/zz_generated.conversion.go
@@ -1139,7 +1139,7 @@ func Convert_v1beta1_OpenStackMachineList_To_v1alpha5_OpenStackMachineList(in *v
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))
+ // 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)
@@ -1190,7 +1190,6 @@ func autoConvert_v1alpha5_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(i
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.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
@@ -1253,6 +1252,7 @@ func Convert_v1alpha5_OpenStackMachineStatus_To_v1beta1_OpenStackMachineStatus(i
func autoConvert_v1beta1_OpenStackMachineStatus_To_v1alpha5_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
diff --git a/api/v1alpha6/conversion_test.go b/api/v1alpha6/conversion_test.go
index 4680ed9c15..91fdeb7c3e 100644
--- a/api/v1alpha6/conversion_test.go
+++ b/api/v1alpha6/conversion_test.go
@@ -607,7 +607,7 @@ func TestMachineConversionControllerSpecFields(t *testing.T) {
{
name: "Set InstanceID",
modifyUp: func(up *infrav1.OpenStackMachine) {
- up.Spec.InstanceID = pointer.String("new-instance-id")
+ up.Status.InstanceID = pointer.String("new-instance-id")
},
testAfter: func(after *OpenStackMachine) {
g.Expect(after.Spec.InstanceID).To(gomega.Equal(pointer.String("new-instance-id")))
diff --git a/api/v1alpha6/openstackcluster_conversion.go b/api/v1alpha6/openstackcluster_conversion.go
index 66fd5896bb..67ea87c9cd 100644
--- a/api/v1alpha6/openstackcluster_conversion.go
+++ b/api/v1alpha6/openstackcluster_conversion.go
@@ -116,6 +116,10 @@ var v1beta1OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStackC
/* OpenStackClusterSpec */
func restorev1alpha6ClusterSpec(previous *OpenStackClusterSpec, dst *OpenStackClusterSpec) {
+ if previous == nil || dst == nil {
+ return
+ }
+
for i := range previous.ExternalRouterIPs {
dstIP := &dst.ExternalRouterIPs[i]
previousIP := &previous.ExternalRouterIPs[i]
@@ -139,6 +143,7 @@ func restorev1alpha6ClusterSpec(previous *OpenStackClusterSpec, dst *OpenStackCl
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
diff --git a/api/v1alpha6/openstackmachine_conversion.go b/api/v1alpha6/openstackmachine_conversion.go
index 2b5864d818..64391ad26d 100644
--- a/api/v1alpha6/openstackmachine_conversion.go
+++ b/api/v1alpha6/openstackmachine_conversion.go
@@ -102,6 +102,26 @@ var v1beta1OpenStackMachineRestorer = conversion.RestorerFor[*infrav1.OpenStackM
),
}
+/* 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) {
diff --git a/api/v1alpha6/openstackmachinetemplate_conversion.go b/api/v1alpha6/openstackmachinetemplate_conversion.go
index 0851e5f6b1..f18681d5e3 100644
--- a/api/v1alpha6/openstackmachinetemplate_conversion.go
+++ b/api/v1alpha6/openstackmachinetemplate_conversion.go
@@ -64,7 +64,7 @@ var v1alpha6OpenStackMachineTemplateRestorer = conversion.RestorerFor[*OpenStack
func(c *OpenStackMachineTemplate) *OpenStackMachineSpec {
return &c.Spec.Template.Spec
},
- restorev1alpha6MachineSpec,
+ restorev1alpha6MachineTemplateMachineSpec,
),
}
@@ -76,3 +76,13 @@ var v1beta1OpenStackMachineTemplateRestorer = conversion.RestorerFor[*infrav1.Op
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/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go
index 8e33e36df6..8cabe14ac1 100644
--- a/api/v1alpha6/zz_generated.conversion.go
+++ b/api/v1alpha6/zz_generated.conversion.go
@@ -151,16 +151,6 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*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((*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.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 {
@@ -311,6 +301,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
+ 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.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 {
@@ -406,6 +401,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); 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_v1alpha6_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_v1alpha6_PortOpts(a.(*v1beta1.PortOpts), b.(*PortOpts), scope)
}); err != nil {
@@ -1109,11 +1109,6 @@ func autoConvert_v1alpha6_OpenStackMachine_To_v1beta1_OpenStackMachine(in *OpenS
return nil
}
-// Convert_v1alpha6_OpenStackMachine_To_v1beta1_OpenStackMachine is an autogenerated conversion function.
-func Convert_v1alpha6_OpenStackMachine_To_v1beta1_OpenStackMachine(in *OpenStackMachine, out *v1beta1.OpenStackMachine, s conversion.Scope) error {
- return autoConvert_v1alpha6_OpenStackMachine_To_v1beta1_OpenStackMachine(in, out, s)
-}
-
func autoConvert_v1beta1_OpenStackMachine_To_v1alpha6_OpenStackMachine(in *v1beta1.OpenStackMachine, out *OpenStackMachine, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
if err := Convert_v1beta1_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(&in.Spec, &out.Spec, s); err != nil {
@@ -1125,11 +1120,6 @@ func autoConvert_v1beta1_OpenStackMachine_To_v1alpha6_OpenStackMachine(in *v1bet
return nil
}
-// Convert_v1beta1_OpenStackMachine_To_v1alpha6_OpenStackMachine is an autogenerated conversion function.
-func Convert_v1beta1_OpenStackMachine_To_v1alpha6_OpenStackMachine(in *v1beta1.OpenStackMachine, out *OpenStackMachine, s conversion.Scope) error {
- return autoConvert_v1beta1_OpenStackMachine_To_v1alpha6_OpenStackMachine(in, out, s)
-}
-
func autoConvert_v1alpha6_OpenStackMachineList_To_v1beta1_OpenStackMachineList(in *OpenStackMachineList, out *v1beta1.OpenStackMachineList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
if in.Items != nil {
@@ -1174,7 +1164,7 @@ func Convert_v1beta1_OpenStackMachineList_To_v1alpha6_OpenStackMachineList(in *v
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))
+ // 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)
@@ -1225,7 +1215,6 @@ func autoConvert_v1alpha6_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(i
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.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
@@ -1288,6 +1277,7 @@ func Convert_v1alpha6_OpenStackMachineStatus_To_v1beta1_OpenStackMachineStatus(i
func autoConvert_v1beta1_OpenStackMachineStatus_To_v1alpha6_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
diff --git a/api/v1alpha7/conversion_test.go b/api/v1alpha7/conversion_test.go
index 57364304b4..06fe488396 100644
--- a/api/v1alpha7/conversion_test.go
+++ b/api/v1alpha7/conversion_test.go
@@ -209,7 +209,7 @@ func TestMachineConversionControllerSpecFields(t *testing.T) {
{
name: "Set InstanceID",
modifyUp: func(up *infrav1.OpenStackMachine) {
- up.Spec.InstanceID = pointer.String("new-instance-id")
+ up.Status.InstanceID = pointer.String("new-instance-id")
},
testAfter: func(after *OpenStackMachine) {
g.Expect(after.Spec.InstanceID).To(gomega.Equal(pointer.String("new-instance-id")))
diff --git a/api/v1alpha7/openstackcluster_conversion.go b/api/v1alpha7/openstackcluster_conversion.go
index 4f06e21cc4..204ccaf5ce 100644
--- a/api/v1alpha7/openstackcluster_conversion.go
+++ b/api/v1alpha7/openstackcluster_conversion.go
@@ -371,9 +371,14 @@ func Convert_v1beta1_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(i
/* Bastion */
func restorev1alpha7Bastion(previous **Bastion, dst **Bastion) {
- if *previous != nil && *dst != nil {
- restorev1alpha7MachineSpec(&(*previous).Instance, &(*dst).Instance)
+ if *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) {
diff --git a/api/v1alpha7/openstackmachine_conversion.go b/api/v1alpha7/openstackmachine_conversion.go
index 4731f7445c..4ebbb91774 100644
--- a/api/v1alpha7/openstackmachine_conversion.go
+++ b/api/v1alpha7/openstackmachine_conversion.go
@@ -89,6 +89,28 @@ var v1beta1OpenStackMachineRestorer = conversion.RestorerFor[*infrav1.OpenStackM
),
}
+/* 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) {
diff --git a/api/v1alpha7/openstackmachinetemplate_conversion.go b/api/v1alpha7/openstackmachinetemplate_conversion.go
index f110066467..62ee4739a1 100644
--- a/api/v1alpha7/openstackmachinetemplate_conversion.go
+++ b/api/v1alpha7/openstackmachinetemplate_conversion.go
@@ -78,5 +78,12 @@ var v1beta1OpenStackMachineTemplateRestorer = conversion.RestorerFor[*infrav1.Op
}
func restorev1alpha7MachineTemplateSpec(previous *OpenStackMachineTemplateSpec, dst *OpenStackMachineTemplateSpec) {
- restorev1alpha7MachineSpec(&previous.Template.Spec, &dst.Template.Spec)
+ 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/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go
index c202a6787b..8bd730b399 100644
--- a/api/v1alpha7/zz_generated.conversion.go
+++ b/api/v1alpha7/zz_generated.conversion.go
@@ -221,16 +221,6 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*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.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 {
@@ -356,6 +346,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); 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 {
@@ -441,6 +436,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); 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 {
@@ -1306,11 +1306,6 @@ func autoConvert_v1alpha7_OpenStackMachine_To_v1beta1_OpenStackMachine(in *OpenS
return nil
}
-// Convert_v1alpha7_OpenStackMachine_To_v1beta1_OpenStackMachine is an autogenerated conversion function.
-func Convert_v1alpha7_OpenStackMachine_To_v1beta1_OpenStackMachine(in *OpenStackMachine, out *v1beta1.OpenStackMachine, s conversion.Scope) error {
- return autoConvert_v1alpha7_OpenStackMachine_To_v1beta1_OpenStackMachine(in, out, s)
-}
-
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 {
@@ -1322,11 +1317,6 @@ func autoConvert_v1beta1_OpenStackMachine_To_v1alpha7_OpenStackMachine(in *v1bet
return nil
}
-// Convert_v1beta1_OpenStackMachine_To_v1alpha7_OpenStackMachine is an autogenerated conversion function.
-func Convert_v1beta1_OpenStackMachine_To_v1alpha7_OpenStackMachine(in *v1beta1.OpenStackMachine, out *OpenStackMachine, s conversion.Scope) error {
- return autoConvert_v1beta1_OpenStackMachine_To_v1alpha7_OpenStackMachine(in, out, s)
-}
-
func autoConvert_v1alpha7_OpenStackMachineList_To_v1beta1_OpenStackMachineList(in *OpenStackMachineList, out *v1beta1.OpenStackMachineList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
if in.Items != nil {
@@ -1371,7 +1361,7 @@ func Convert_v1beta1_OpenStackMachineList_To_v1alpha7_OpenStackMachineList(in *v
func autoConvert_v1alpha7_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))
+ // 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)
@@ -1421,7 +1411,6 @@ func autoConvert_v1alpha7_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(i
func autoConvert_v1beta1_OpenStackMachineSpec_To_v1alpha7_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.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
@@ -1484,6 +1473,7 @@ func Convert_v1alpha7_OpenStackMachineStatus_To_v1beta1_OpenStackMachineStatus(i
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
diff --git a/api/v1beta1/openstackmachine_types.go b/api/v1beta1/openstackmachine_types.go
index 3f20a559ff..3d06b70ba2 100644
--- a/api/v1beta1/openstackmachine_types.go
+++ b/api/v1beta1/openstackmachine_types.go
@@ -22,6 +22,8 @@ import (
"k8s.io/utils/pointer"
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 (
@@ -36,9 +38,6 @@ 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 flavor reference for the flavor for your server instance.
Flavor string `json:"flavor"`
@@ -119,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"`
diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go
index 088e9c46f2..be6df5d5b1 100644
--- a/api/v1beta1/zz_generated.deepcopy.go
+++ b/api/v1beta1/zz_generated.deepcopy.go
@@ -930,11 +930,6 @@ 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
@@ -1007,6 +1002,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))
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 5056e60154..30c488ddcc 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -5081,10 +5081,6 @@ spec:
format: uuid
type: string
type: object
- 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.
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 5f25ff93c1..6d2ab3fde8 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -2509,10 +2509,6 @@ spec:
format: uuid
type: string
type: object
- 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.
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 1ea294dcb1..a98a84d5da 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
@@ -1861,9 +1861,6 @@ spec:
format: uuid
type: string
type: object
- 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.
@@ -2504,6 +2501,9 @@ spec:
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.
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 4c1b1abb98..eda7548581 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
@@ -1535,10 +1535,6 @@ spec:
format: uuid
type: string
type: object
- 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.
diff --git a/controllers/openstackmachine_controller.go b/controllers/openstackmachine_controller.go
index 969ec5b61a..26691d8430 100644
--- a/controllers/openstackmachine_controller.go
+++ b/controllers/openstackmachine_controller.go
@@ -277,8 +277,8 @@ func (r *OpenStackMachineReconciler) reconcileDelete(scope *scope.WithLogger, cl
}
var instanceStatus *compute.InstanceStatus
- if openStackMachine.Spec.InstanceID != nil {
- instanceStatus, err = computeService.GetInstanceStatus(*openStackMachine.Spec.InstanceID)
+ if openStackMachine.Status.InstanceID != nil {
+ instanceStatus, err = computeService.GetInstanceStatus(*openStackMachine.Status.InstanceID)
if err != nil {
return ctrl.Result{}, err
}
@@ -545,12 +545,8 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope
return ctrl.Result{}, err
}
- // 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())
-
state := instanceStatus.State()
+ openStackMachine.Status.InstanceID = pointer.String(instanceStatus.ID())
openStackMachine.Status.InstanceState = &state
instanceNS, err := instanceStatus.NetworkStatus()
@@ -581,6 +577,9 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope
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 = pointer.String(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,
@@ -619,6 +618,7 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope
if err != nil {
return ctrl.Result{}, err
}
+
conditions.MarkTrue(openStackMachine, infrav1.APIServerIngressReadyCondition)
scope.Logger().Info("Reconciled Machine create successfully")
return ctrl.Result{}, nil
@@ -700,8 +700,8 @@ func getOrCreateMachinePorts(openStackMachine *infrav1.OpenStackMachine, network
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.Spec.InstanceID != nil {
- instanceStatus, err = computeService.GetInstanceStatus(*openStackMachine.Spec.InstanceID)
+ 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())
@@ -714,7 +714,7 @@ func (r *OpenStackMachineReconciler) getOrCreateInstance(logger logr.Logger, ope
if instanceStatus != nil {
return instanceStatus, nil
}
- if openStackMachine.Spec.InstanceID != 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"))
diff --git a/controllers/suite_test.go b/controllers/suite_test.go
index 0a49b42403..81727efa24 100644
--- a/controllers/suite_test.go
+++ b/controllers/suite_test.go
@@ -149,7 +149,7 @@ var _ = Describe("When calling getOrCreate", func() {
openStackCluster := &infrav1.OpenStackCluster{}
machine := &clusterv1.Machine{}
openStackMachine := &infrav1.OpenStackMachine{
- Spec: infrav1.OpenStackMachineSpec{
+ Status: infrav1.OpenStackMachineStatus{
InstanceID: pointer.String("machine-uuid"),
},
}
diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md
index 217373dd46..59dc5bedac 100644
--- a/docs/book/src/api/v1beta1/api.md
+++ b/docs/book/src/api/v1beta1/api.md
@@ -563,17 +563,6 @@ string
-instanceID
-
-string
-
- |
-
- InstanceID is the OpenStack instance ID for this machine.
- |
-
-
-
flavor
string
@@ -3112,17 +3101,6 @@ string
|
-instanceID
-
-string
-
- |
-
- InstanceID is the OpenStack instance ID for this machine.
- |
-
-
-
flavor
string
@@ -3337,6 +3315,18 @@ bool
|
+instanceID
+
+string
+
+ |
+
+(Optional)
+ InstanceID is the OpenStack instance ID for this machine.
+ |
+
+
+
addresses
[]Kubernetes core/v1.NodeAddress
@@ -3484,17 +3474,6 @@ string
|
-instanceID
-
-string
-
- |
-
- InstanceID is the OpenStack instance ID for this machine.
- |
-
-
-
flavor
string
From 7dd2c352a4efcebbfa8f8e2734901c111081a5e5 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Mon, 1 Apr 2024 18:07:44 +0100
Subject: [PATCH 158/180] Bastion is enabled by default if specified
Bastion.Enabled is a wart. Ideally it would not be required, but because
of limitations in how we delete the bastion we require an intermediate
'disabled' step before removal. Ultimately we intend to remove this
limitation.
Eventually we would like to be able to ignore enabled entirely. e.g. To
create a Bastion just specify it:
```yaml
spec:
bastion:
spec:
...
floatingIP: x.x.x.x
```
and to delete it just remove the bastion field.
Right now with enabled defaulting to `false`, doing the above will not
result in the creation of a bastion, because enabled must be explicitly
set to true.
Paving the way for the eventual deprecation of Bastion.Enabled, we
change the default value of enabled to be true so the above does today
what we eventually want it to do. This is also generally more intuitive:
why would you include a bastion and a spec if you didn't want to create
a bastion? Having to also set enabled to true is currently a trip
hazard.
Until we resolve the limitations of bastion deletion, though, we still
need to be able to disable the bastion. For this case enabled can be
explicitly set to false.
In the future when we remove the requirement to disable the bastion
before deletion the user can simply ignore Bastion.Enabled, which will
continue to work but without the limitations.
---
api/v1alpha5/zz_generated.conversion.go | 8 ++++--
api/v1alpha6/openstackcluster_conversion.go | 1 +
api/v1alpha6/zz_generated.conversion.go | 8 ++++--
api/v1alpha7/openstackcluster_conversion.go | 1 +
api/v1alpha7/zz_generated.conversion.go | 8 ++++--
api/v1beta1/types.go | 23 ++++++++++++----
api/v1beta1/zz_generated.deepcopy.go | 5 ++++
...re.cluster.x-k8s.io_openstackclusters.yaml | 17 +++++++-----
...er.x-k8s.io_openstackclustertemplates.yaml | 17 +++++++-----
controllers/openstackcluster_controller.go | 8 +++---
.../openstackcluster_controller_test.go | 20 +++++++-------
docs/book/src/api/v1beta1/api.md | 8 +++++-
.../topics/crd-changes/v1alpha7-to-v1beta1.md | 4 ++-
.../services/networking/securitygroups.go | 6 ++---
.../networking/securitygroups_test.go | 2 +-
pkg/webhooks/openstackcluster_webhook.go | 2 +-
pkg/webhooks/openstackcluster_webhook_test.go | 8 +++---
.../apivalidations/openstackcluster_test.go | 26 ++++++++++++++-----
test/e2e/suites/e2e/e2e_test.go | 2 +-
19 files changed, 118 insertions(+), 56 deletions(-)
diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go
index 2c5a688927..7ef2f85215 100644
--- a/api/v1alpha5/zz_generated.conversion.go
+++ b/api/v1alpha5/zz_generated.conversion.go
@@ -486,7 +486,9 @@ func Convert_v1beta1_AddressPair_To_v1alpha5_AddressPair(in *v1beta1.AddressPair
}
func autoConvert_v1alpha5_Bastion_To_v1beta1_Bastion(in *Bastion, out *v1beta1.Bastion, s conversion.Scope) error {
- out.Enabled = in.Enabled
+ 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
@@ -495,7 +497,9 @@ func autoConvert_v1alpha5_Bastion_To_v1beta1_Bastion(in *Bastion, out *v1beta1.B
}
func autoConvert_v1beta1_Bastion_To_v1alpha5_Bastion(in *v1beta1.Bastion, out *Bastion, s conversion.Scope) error {
- out.Enabled = in.Enabled
+ 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
diff --git a/api/v1alpha6/openstackcluster_conversion.go b/api/v1alpha6/openstackcluster_conversion.go
index 66fd5896bb..0cc60afb18 100644
--- a/api/v1alpha6/openstackcluster_conversion.go
+++ b/api/v1alpha6/openstackcluster_conversion.go
@@ -416,6 +416,7 @@ func restorev1beta1Bastion(previous **infrav1.Bastion, dst **infrav1.Bastion) {
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 {
diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go
index 8e33e36df6..f1ad2538c2 100644
--- a/api/v1alpha6/zz_generated.conversion.go
+++ b/api/v1alpha6/zz_generated.conversion.go
@@ -510,7 +510,9 @@ func Convert_v1beta1_AddressPair_To_v1alpha6_AddressPair(in *v1beta1.AddressPair
}
func autoConvert_v1alpha6_Bastion_To_v1beta1_Bastion(in *Bastion, out *v1beta1.Bastion, s conversion.Scope) error {
- out.Enabled = in.Enabled
+ 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
@@ -519,7 +521,9 @@ func autoConvert_v1alpha6_Bastion_To_v1beta1_Bastion(in *Bastion, out *v1beta1.B
}
func autoConvert_v1beta1_Bastion_To_v1alpha6_Bastion(in *v1beta1.Bastion, out *Bastion, s conversion.Scope) error {
- out.Enabled = in.Enabled
+ 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
diff --git a/api/v1alpha7/openstackcluster_conversion.go b/api/v1alpha7/openstackcluster_conversion.go
index 4f06e21cc4..df703c5eb7 100644
--- a/api/v1alpha7/openstackcluster_conversion.go
+++ b/api/v1alpha7/openstackcluster_conversion.go
@@ -384,6 +384,7 @@ func restorev1beta1Bastion(previous **infrav1.Bastion, dst **infrav1.Bastion) {
optional.RestoreString(&(*previous).FloatingIP, &(*dst).FloatingIP)
optional.RestoreString(&(*previous).AvailabilityZone, &(*dst).AvailabilityZone)
+ optional.RestoreBool(&(*previous).Enabled, &(*dst).Enabled)
}
}
diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go
index c202a6787b..91d95656f4 100644
--- a/api/v1alpha7/zz_generated.conversion.go
+++ b/api/v1alpha7/zz_generated.conversion.go
@@ -573,7 +573,9 @@ func Convert_v1beta1_AddressPair_To_v1alpha7_AddressPair(in *v1beta1.AddressPair
}
func autoConvert_v1alpha7_Bastion_To_v1beta1_Bastion(in *Bastion, out *v1beta1.Bastion, s conversion.Scope) error {
- out.Enabled = in.Enabled
+ 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
@@ -582,7 +584,9 @@ func autoConvert_v1alpha7_Bastion_To_v1beta1_Bastion(in *Bastion, out *v1beta1.B
}
func autoConvert_v1beta1_Bastion_To_v1alpha7_Bastion(in *v1beta1.Bastion, out *Bastion, s conversion.Scope) error {
- out.Enabled = in.Enabled
+ 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
diff --git a/api/v1beta1/types.go b/api/v1beta1/types.go
index 492546e755..bfdef09c6b 100644
--- a/api/v1beta1/types.go
+++ b/api/v1beta1/types.go
@@ -719,12 +719,18 @@ var (
)
// 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="you need to specify the spec if bastion is enabled"
+// +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. Defaults to false.
- // +kubebuilder:validation:Required
- // +kubebuilder:default:=false
- Enabled bool `json:"enabled"`
+ // 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"`
@@ -741,6 +747,13 @@ type Bastion struct {
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.
diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go
index 088e9c46f2..69d71929a1 100644
--- a/api/v1beta1/zz_generated.deepcopy.go
+++ b/api/v1beta1/zz_generated.deepcopy.go
@@ -116,6 +116,11 @@ func (in *AllocationPool) DeepCopy() *AllocationPool {
// 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
+ 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)
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 5056e60154..acdaa6eae7 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -4921,9 +4921,16 @@ spec:
be used to create the Bastion Spec.
type: string
enabled:
- default: false
- description: Enabled means that bastion is enabled. Defaults to
- false.
+ 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: |-
@@ -5639,11 +5646,9 @@ spec:
- flavor
- image
type: object
- required:
- - enabled
type: object
x-kubernetes-validations:
- - message: you need to specify the spec if bastion is enabled
+ - message: spec is required if bastion is enabled
rule: '!self.enabled || has(self.spec)'
controlPlaneAvailabilityZones:
description: |-
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 5f25ff93c1..f01e35e574 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -2345,9 +2345,16 @@ spec:
will be used to create the Bastion Spec.
type: string
enabled:
- default: false
- description: Enabled means that bastion is enabled. Defaults
- to false.
+ 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: |-
@@ -3076,11 +3083,9 @@ spec:
- flavor
- image
type: object
- required:
- - enabled
type: object
x-kubernetes-validations:
- - message: you need to specify the spec if bastion is enabled
+ - message: spec is required if bastion is enabled
rule: '!self.enabled || has(self.spec)'
controlPlaneAvailabilityZones:
description: |-
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index c9283f11b7..3823b6ec3a 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -219,7 +219,7 @@ func contains(arr []string, target string) bool {
func resolveBastionResources(scope *scope.WithLogger, clusterResourceName string, openStackCluster *infrav1.OpenStackCluster) (bool, error) {
// Resolve and store resources for the bastion
- if openStackCluster.Spec.Bastion != nil && openStackCluster.Spec.Bastion.Enabled {
+ if openStackCluster.Spec.Bastion.IsEnabled() {
if openStackCluster.Status.Bastion == nil {
openStackCluster.Status.Bastion = &infrav1.BastionStatus{}
}
@@ -406,7 +406,7 @@ func reconcileBastion(scope *scope.WithLogger, cluster *clusterv1.Cluster, openS
}
// No Bastion defined
- if openStackCluster.Spec.Bastion == nil || !openStackCluster.Spec.Bastion.Enabled {
+ if !openStackCluster.Spec.Bastion.IsEnabled() {
// Delete any existing bastion
if openStackCluster.Status.Bastion != nil {
if err := deleteBastion(scope, cluster, openStackCluster); err != nil {
@@ -440,6 +440,8 @@ func reconcileBastion(scope *scope.WithLogger, cluster *clusterv1.Cluster, openS
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 nil, err
}
@@ -544,7 +546,7 @@ func bastionAddFloatingIP(openStackCluster *infrav1.OpenStackCluster, clusterRes
func bastionToInstanceSpec(openStackCluster *infrav1.OpenStackCluster, cluster *clusterv1.Cluster) (*compute.InstanceSpec, error) {
bastion := openStackCluster.Spec.Bastion
if bastion == nil {
- return nil, fmt.Errorf("bastion spec is 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.
diff --git a/controllers/openstackcluster_controller_test.go b/controllers/openstackcluster_controller_test.go
index c2a602ec31..86fb45173d 100644
--- a/controllers/openstackcluster_controller_test.go
+++ b/controllers/openstackcluster_controller_test.go
@@ -196,10 +196,10 @@ 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{},
+ Bastion: &infrav1.Bastion{Enabled: pointer.Bool(false)},
}
err := k8sClient.Create(ctx, testCluster)
Expect(err).To(BeNil())
@@ -228,7 +228,7 @@ var _ = Describe("OpenStackCluster controller", func() {
testCluster.SetName("adopt-existing-bastion")
testCluster.Spec = infrav1.OpenStackClusterSpec{
Bastion: &infrav1.Bastion{
- Enabled: true,
+ Enabled: pointer.Bool(true),
Spec: &bastionSpec,
},
}
@@ -311,7 +311,7 @@ var _ = Describe("OpenStackCluster controller", func() {
testCluster.SetName("requeue-bastion")
testCluster.Spec = infrav1.OpenStackClusterSpec{
Bastion: &infrav1.Bastion{
- Enabled: true,
+ Enabled: pointer.Bool(true),
Spec: &bastionSpec,
},
}
@@ -393,7 +393,7 @@ var _ = Describe("OpenStackCluster controller", func() {
testCluster.SetName("requeue-bastion")
testCluster.Spec = infrav1.OpenStackClusterSpec{
Bastion: &infrav1.Bastion{
- Enabled: true,
+ Enabled: pointer.Bool(true),
Spec: &bastionSpec,
},
}
@@ -467,9 +467,7 @@ var _ = Describe("OpenStackCluster controller", func() {
})
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{
- Bastion: &infrav1.Bastion{},
- }
+ testCluster.Spec = infrav1.OpenStackClusterSpec{}
err := k8sClient.Create(ctx, testCluster)
Expect(err).To(BeNil())
err = k8sClient.Create(ctx, capiCluster)
@@ -516,7 +514,7 @@ var _ = Describe("OpenStackCluster controller", func() {
testCluster.SetName("subnet-filtering")
testCluster.Spec = infrav1.OpenStackClusterSpec{
Bastion: &infrav1.Bastion{
- Enabled: true,
+ Enabled: pointer.Bool(true),
Spec: &bastionSpec,
},
DisableAPIServerFloatingIP: pointer.Bool(true),
@@ -586,7 +584,7 @@ var _ = Describe("OpenStackCluster controller", func() {
testCluster.SetName("subnet-filtering")
testCluster.Spec = infrav1.OpenStackClusterSpec{
Bastion: &infrav1.Bastion{
- Enabled: true,
+ Enabled: pointer.Bool(true),
Spec: &bastionSpec,
},
DisableAPIServerFloatingIP: pointer.Bool(true),
diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md
index 217373dd46..b97042eec6 100644
--- a/docs/book/src/api/v1beta1/api.md
+++ b/docs/book/src/api/v1beta1/api.md
@@ -1084,7 +1084,13 @@ bool
|
- Enabled means that bastion is enabled. Defaults to false.
+(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.
|
diff --git a/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md b/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
index 36d68a5b19..7ad5cb3dab 100644
--- a/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
+++ b/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
@@ -14,7 +14,7 @@
- [Change to image](#change-to-image)
- [Removal of imageUUID](#removal-of-imageuuid)
- [Changes to ports](#changes-to-ports)
- - [Additon of floatingIPPoolRef](#additon-of-floatingippoolref)
+ - [Addition of floatingIPPoolRef](#addition-of-floatingippoolref)
- [`OpenStackCluster`](#openstackcluster)
- [Removal of cloudName](#removal-of-cloudname-1)
- [identityRef is now required](#identityref-is-now-required)
@@ -367,6 +367,8 @@ spec:
#### Changes to bastion
+In v1beta1 the Bastion is enabled by default if a bastion is specified in `OpenStackCluster.spec.bastion` but `enabled` is not included. However, it is still required to set `enabled` explicitly to `false` before removing the bastion. We intend to remove this requirement in the future at which point the `enabled` field will be redundant.
+
In v1beta1, `OpenStackCluster.spec.bastion.instance` becomes `OpenStackCluster.spec.bastion.spec`.
```yaml
diff --git a/pkg/cloud/services/networking/securitygroups.go b/pkg/cloud/services/networking/securitygroups.go
index 5d159f52a5..cc41b9423b 100644
--- a/pkg/cloud/services/networking/securitygroups.go
+++ b/pkg/cloud/services/networking/securitygroups.go
@@ -47,7 +47,7 @@ func (s *Service) ReconcileSecurityGroups(openStackCluster *infrav1.OpenStackClu
return nil
}
- bastionEnabled := openStackCluster.Spec.Bastion != nil && openStackCluster.Spec.Bastion.Enabled
+ bastionEnabled := openStackCluster.Spec.Bastion.IsEnabled()
secControlPlaneGroupName := getSecControlPlaneGroupName(clusterResourceName)
secWorkerGroupName := getSecWorkerGroupName(clusterResourceName)
@@ -212,7 +212,7 @@ func (s *Service) generateDesiredSecGroups(openStackCluster *infrav1.OpenStackCl
desiredSecGroupsBySuffix := make(map[string]securityGroupSpec)
- if openStackCluster.Spec.Bastion != nil && openStackCluster.Spec.Bastion.Enabled {
+ if openStackCluster.Spec.Bastion.IsEnabled() {
controlPlaneRules = append(controlPlaneRules, getSGControlPlaneSSH(secBastionGroupID)...)
workerRules = append(workerRules, getSGWorkerSSH(secBastionGroupID)...)
@@ -357,7 +357,7 @@ func (s *Service) DeleteSecurityGroups(openStackCluster *infrav1.OpenStackCluste
getSecWorkerGroupName(clusterResourceName),
}
- if openStackCluster.Spec.Bastion != nil && openStackCluster.Spec.Bastion.Enabled {
+ if openStackCluster.Spec.Bastion.IsEnabled() {
secGroupNames = append(secGroupNames, getSecBastionGroupName(clusterResourceName))
}
diff --git a/pkg/cloud/services/networking/securitygroups_test.go b/pkg/cloud/services/networking/securitygroups_test.go
index f40e4a5d75..487fa9bd87 100644
--- a/pkg/cloud/services/networking/securitygroups_test.go
+++ b/pkg/cloud/services/networking/securitygroups_test.go
@@ -533,7 +533,7 @@ func TestService_ReconcileSecurityGroups(t *testing.T) {
name: "Default control plane, worker, and bastion security groups",
openStackClusterSpec: infrav1.OpenStackClusterSpec{
Bastion: &infrav1.Bastion{
- Enabled: true,
+ Enabled: pointer.Bool(true),
},
ManagedSecurityGroups: &infrav1.ManagedSecurityGroups{},
},
diff --git a/pkg/webhooks/openstackcluster_webhook.go b/pkg/webhooks/openstackcluster_webhook.go
index ece642481f..d5a68c6ae5 100644
--- a/pkg/webhooks/openstackcluster_webhook.go
+++ b/pkg/webhooks/openstackcluster_webhook.go
@@ -110,7 +110,7 @@ func (*openStackClusterWebhook) ValidateUpdate(_ context.Context, oldObjRaw, new
// Allow to remove the bastion spec only if it was disabled before.
if newObj.Spec.Bastion == nil {
- if oldObj.Spec.Bastion != nil && oldObj.Spec.Bastion.Enabled {
+ if oldObj.Spec.Bastion.IsEnabled() {
allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "bastion"), "cannot be removed before disabling it"))
}
}
diff --git a/pkg/webhooks/openstackcluster_webhook_test.go b/pkg/webhooks/openstackcluster_webhook_test.go
index 09c18dcc70..d42b6eb1ce 100644
--- a/pkg/webhooks/openstackcluster_webhook_test.go
+++ b/pkg/webhooks/openstackcluster_webhook_test.go
@@ -92,7 +92,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
Flavor: "minimal",
},
- Enabled: true,
+ Enabled: pointer.Bool(true),
},
},
Status: infrav1.OpenStackClusterStatus{
@@ -116,7 +116,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
},
Flavor: "medium",
},
- Enabled: true,
+ Enabled: pointer.Bool(true),
},
},
},
@@ -459,7 +459,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
CloudName: "foobar",
},
Bastion: &infrav1.Bastion{
- Enabled: true,
+ Enabled: pointer.Bool(true),
Spec: &infrav1.OpenStackMachineSpec{
Flavor: "m1.small",
Image: infrav1.ImageParam{
@@ -490,7 +490,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
CloudName: "foobar",
},
Bastion: &infrav1.Bastion{
- Enabled: false,
+ Enabled: pointer.Bool(false),
Spec: &infrav1.OpenStackMachineSpec{
Flavor: "m1.small",
Image: infrav1.ImageParam{
diff --git a/test/e2e/suites/apivalidations/openstackcluster_test.go b/test/e2e/suites/apivalidations/openstackcluster_test.go
index 947f9b7b84..122269034b 100644
--- a/test/e2e/suites/apivalidations/openstackcluster_test.go
+++ b/test/e2e/suites/apivalidations/openstackcluster_test.go
@@ -90,7 +90,7 @@ var _ = Describe("OpenStackCluster API validations", func() {
It("should allow bastion.enabled=true with a spec", func() {
cluster.Spec.Bastion = &infrav1.Bastion{
- Enabled: true,
+ Enabled: pointer.Bool(true),
Spec: &infrav1.OpenStackMachineSpec{
Image: infrav1.ImageParam{
Filter: &infrav1.ImageFilter{
@@ -104,25 +104,38 @@ var _ = Describe("OpenStackCluster API validations", func() {
It("should not allow bastion.enabled=true without a spec", func() {
cluster.Spec.Bastion = &infrav1.Bastion{
- Enabled: true,
+ Enabled: pointer.Bool(true),
}
Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should not succeed")
})
- It("should default bastion.enabled=false", func() {
+ It("should not allow an empty Bastion", func() {
cluster.Spec.Bastion = &infrav1.Bastion{}
+ Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should not succeed")
+ })
+
+ It("should default bastion.enabled=true", func() {
+ cluster.Spec.Bastion = &infrav1.Bastion{
+ Spec: &infrav1.OpenStackMachineSpec{
+ Image: infrav1.ImageParam{
+ Filter: &infrav1.ImageFilter{
+ Name: pointer.String("fake-image"),
+ },
+ },
+ },
+ }
Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should not succeed")
// Fetch the cluster and check the defaulting
fetchedCluster := &infrav1.OpenStackCluster{}
Expect(k8sClient.Get(ctx, types.NamespacedName{Name: cluster.Name, Namespace: cluster.Namespace}, fetchedCluster)).To(Succeed(), "OpenStackCluster fetch should succeed")
-
- Expect(fetchedCluster.Spec.Bastion.Enabled).To(BeFalse(), "Bastion.Enabled should default to false")
+ Expect(fetchedCluster.Spec.Bastion.Enabled).ToNot(BeNil(), "Bastion.Enabled should have been defaulted")
+ Expect(*fetchedCluster.Spec.Bastion.Enabled).To(BeTrueBecause("Bastion.Enabled should default to true"))
})
It("should allow IPv4 as bastion floatingIP", func() {
cluster.Spec.Bastion = &infrav1.Bastion{
- Enabled: true,
+ Enabled: pointer.Bool(true),
Spec: &infrav1.OpenStackMachineSpec{
Image: infrav1.ImageParam{
Filter: &infrav1.ImageFilter{
@@ -137,7 +150,6 @@ var _ = Describe("OpenStackCluster API validations", func() {
It("should not allow non-IPv4 as bastion floating IP", func() {
cluster.Spec.Bastion = &infrav1.Bastion{
- Enabled: true,
Spec: &infrav1.OpenStackMachineSpec{
Image: infrav1.ImageParam{
Filter: &infrav1.ImageFilter{
diff --git a/test/e2e/suites/e2e/e2e_test.go b/test/e2e/suites/e2e/e2e_test.go
index 37422eb33f..78ddf8b55a 100644
--- a/test/e2e/suites/e2e/e2e_test.go
+++ b/test/e2e/suites/e2e/e2e_test.go
@@ -176,7 +176,7 @@ var _ = Describe("e2e tests [PR-Blocking]", func() {
openStackCluster, err = shared.ClusterForSpec(ctx, e2eCtx, namespace)
Expect(err).NotTo(HaveOccurred())
openStackClusterDisabledBastion := openStackCluster.DeepCopy()
- openStackClusterDisabledBastion.Spec.Bastion.Enabled = false
+ openStackClusterDisabledBastion.Spec.Bastion.Enabled = pointer.Bool(false)
Expect(e2eCtx.Environment.BootstrapClusterProxy.GetClient().Update(ctx, openStackClusterDisabledBastion)).To(Succeed())
Eventually(
func() (bool, error) {
From 8ea3ccf6d45ebf64e4e18db5002c85e72bcf6fae Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Tue, 2 Apr 2024 10:24:41 +0100
Subject: [PATCH 159/180] ServerGroupFilter to ServerGroupParam
---
api/v1alpha5/conversion.go | 8 ++-
api/v1alpha6/openstackcluster_conversion.go | 6 +--
api/v1alpha6/openstackmachine_conversion.go | 6 +--
api/v1alpha7/openstackcluster_conversion.go | 6 +--
api/v1alpha7/openstackmachine_conversion.go | 6 +--
api/v1beta1/openstackmachine_types.go | 2 +-
api/v1beta1/types.go | 25 ++++++++-
api/v1beta1/zz_generated.deepcopy.go | 34 ++++++++++++-
...re.cluster.x-k8s.io_openstackclusters.yaml | 16 +++++-
...er.x-k8s.io_openstackclustertemplates.yaml | 18 ++++++-
...re.cluster.x-k8s.io_openstackmachines.yaml | 15 +++++-
...er.x-k8s.io_openstackmachinetemplates.yaml | 16 +++++-
.../openstackmachine_controller_test.go | 2 +-
docs/book/src/api/v1beta1/api.md | 51 ++++++++++++++++---
.../compute/referenced_resources_test.go | 7 +--
pkg/cloud/services/compute/servergroup.go | 15 +++---
.../services/compute/servergroup_test.go | 39 +++++++-------
.../e2e/suites/apivalidations/filters_test.go | 35 +++++++++++++
test/helpers/fuzzerfuncs.go | 4 ++
19 files changed, 243 insertions(+), 68 deletions(-)
diff --git a/api/v1alpha5/conversion.go b/api/v1alpha5/conversion.go
index b9439a54eb..79b282dfeb 100644
--- a/api/v1alpha5/conversion.go
+++ b/api/v1alpha5/conversion.go
@@ -351,9 +351,7 @@ func Convert_v1alpha5_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(in *O
}
if in.ServerGroupID != "" {
- out.ServerGroup = &infrav1.ServerGroupFilter{ID: in.ServerGroupID}
- } else {
- out.ServerGroup = &infrav1.ServerGroupFilter{}
+ out.ServerGroup = &infrav1.ServerGroupParam{ID: &in.ServerGroupID}
}
imageParam := infrav1.ImageParam{}
@@ -682,8 +680,8 @@ func Convert_v1beta1_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(in *i
return err
}
- if in.ServerGroup != nil {
- out.ServerGroupID = in.ServerGroup.ID
+ if in.ServerGroup != nil && in.ServerGroup.ID != nil {
+ out.ServerGroupID = *in.ServerGroup.ID
}
if in.Image.ID != nil {
diff --git a/api/v1alpha6/openstackcluster_conversion.go b/api/v1alpha6/openstackcluster_conversion.go
index 0cc60afb18..912ccd16eb 100644
--- a/api/v1alpha6/openstackcluster_conversion.go
+++ b/api/v1alpha6/openstackcluster_conversion.go
@@ -434,7 +434,7 @@ func Convert_v1alpha6_Bastion_To_v1beta1_Bastion(in *Bastion, out *infrav1.Basti
}
if in.Instance.ServerGroupID != "" {
- out.Spec.ServerGroup = &infrav1.ServerGroupFilter{ID: in.Instance.ServerGroupID}
+ out.Spec.ServerGroup = &infrav1.ServerGroupParam{ID: &in.Instance.ServerGroupID}
} else {
out.Spec.ServerGroup = nil
}
@@ -464,8 +464,8 @@ func Convert_v1beta1_Bastion_To_v1alpha6_Bastion(in *infrav1.Bastion, out *Basti
return err
}
- if in.Spec.ServerGroup != nil && in.Spec.ServerGroup.ID != "" {
- out.Instance.ServerGroupID = in.Spec.ServerGroup.ID
+ if in.Spec.ServerGroup != nil && in.Spec.ServerGroup.ID != nil {
+ out.Instance.ServerGroupID = *in.Spec.ServerGroup.ID
}
}
diff --git a/api/v1alpha6/openstackmachine_conversion.go b/api/v1alpha6/openstackmachine_conversion.go
index 2b5864d818..709a8dc1d0 100644
--- a/api/v1alpha6/openstackmachine_conversion.go
+++ b/api/v1alpha6/openstackmachine_conversion.go
@@ -267,7 +267,7 @@ func Convert_v1alpha6_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(in *O
}
if in.ServerGroupID != "" {
- out.ServerGroup = &infrav1.ServerGroupFilter{ID: in.ServerGroupID}
+ out.ServerGroup = &infrav1.ServerGroupParam{ID: &in.ServerGroupID}
} else {
out.ServerGroup = nil
}
@@ -316,8 +316,8 @@ func Convert_v1beta1_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(in *i
return err
}
- if in.ServerGroup != nil {
- out.ServerGroupID = in.ServerGroup.ID
+ if in.ServerGroup != nil && in.ServerGroup.ID != nil {
+ out.ServerGroupID = *in.ServerGroup.ID
}
if in.Image.ID != nil {
diff --git a/api/v1alpha7/openstackcluster_conversion.go b/api/v1alpha7/openstackcluster_conversion.go
index df703c5eb7..6d976806dc 100644
--- a/api/v1alpha7/openstackcluster_conversion.go
+++ b/api/v1alpha7/openstackcluster_conversion.go
@@ -403,7 +403,7 @@ func Convert_v1alpha7_Bastion_To_v1beta1_Bastion(in *Bastion, out *infrav1.Basti
}
if in.Instance.ServerGroupID != "" {
- out.Spec.ServerGroup = &infrav1.ServerGroupFilter{ID: in.Instance.ServerGroupID}
+ out.Spec.ServerGroup = &infrav1.ServerGroupParam{ID: &in.Instance.ServerGroupID}
} else {
out.Spec.ServerGroup = nil
}
@@ -433,8 +433,8 @@ func Convert_v1beta1_Bastion_To_v1alpha7_Bastion(in *infrav1.Bastion, out *Basti
return err
}
- if in.Spec.ServerGroup != nil && in.Spec.ServerGroup.ID != "" {
- out.Instance.ServerGroupID = in.Spec.ServerGroup.ID
+ if in.Spec.ServerGroup != nil && in.Spec.ServerGroup.ID != nil {
+ out.Instance.ServerGroupID = *in.Spec.ServerGroup.ID
}
}
diff --git a/api/v1alpha7/openstackmachine_conversion.go b/api/v1alpha7/openstackmachine_conversion.go
index 6547fa10e1..ccca67a04c 100644
--- a/api/v1alpha7/openstackmachine_conversion.go
+++ b/api/v1alpha7/openstackmachine_conversion.go
@@ -178,7 +178,7 @@ func Convert_v1alpha7_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(in *O
}
if in.ServerGroupID != "" {
- out.ServerGroup = &infrav1.ServerGroupFilter{ID: in.ServerGroupID}
+ out.ServerGroup = &infrav1.ServerGroupParam{ID: &in.ServerGroupID}
} else {
out.ServerGroup = nil
}
@@ -224,8 +224,8 @@ func Convert_v1beta1_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(in *i
return err
}
- if in.ServerGroup != nil {
- out.ServerGroupID = in.ServerGroup.ID
+ if in.ServerGroup != nil && in.ServerGroup.ID != nil {
+ out.ServerGroupID = *in.ServerGroup.ID
}
if in.Image.ID != nil {
diff --git a/api/v1beta1/openstackmachine_types.go b/api/v1beta1/openstackmachine_types.go
index 3f20a559ff..f1c0550766 100644
--- a/api/v1beta1/openstackmachine_types.go
+++ b/api/v1beta1/openstackmachine_types.go
@@ -86,7 +86,7 @@ type OpenStackMachineSpec struct {
// The server group to assign the machine to.
// +optional
- ServerGroup *ServerGroupFilter `json:"serverGroup,omitempty"`
+ ServerGroup *ServerGroupParam `json:"serverGroup,omitempty"`
// IdentityRef is a reference to a secret holding OpenStack credentials
// to be used when reconciling this machine. If not specified, the
diff --git a/api/v1beta1/types.go b/api/v1beta1/types.go
index bfdef09c6b..9bf90d826d 100644
--- a/api/v1beta1/types.go
+++ b/api/v1beta1/types.go
@@ -547,9 +547,30 @@ type AdditionalBlockDevice struct {
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 {
- ID string `json:"id,omitempty"`
- Name string `json:"name,omitempty"`
+ // 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.
diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go
index 69d71929a1..857c85788b 100644
--- a/api/v1beta1/zz_generated.deepcopy.go
+++ b/api/v1beta1/zz_generated.deepcopy.go
@@ -984,8 +984,8 @@ func (in *OpenStackMachineSpec) DeepCopyInto(out *OpenStackMachineSpec) {
}
if in.ServerGroup != nil {
in, out := &in.ServerGroup, &out.ServerGroup
- *out = new(ServerGroupFilter)
- **out = **in
+ *out = new(ServerGroupParam)
+ (*in).DeepCopyInto(*out)
}
if in.IdentityRef != nil {
in, out := &in.IdentityRef, &out.IdentityRef
@@ -1563,6 +1563,11 @@ func (in *SecurityGroupStatus) DeepCopy() *SecurityGroupStatus {
// 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.
@@ -1575,6 +1580,31 @@ func (in *ServerGroupFilter) DeepCopy() *ServerGroupFilter {
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 ServerGroupParam.
+func (in *ServerGroupParam) DeepCopy() *ServerGroupParam {
+ if in == nil {
+ return nil
+ }
+ 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
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 acdaa6eae7..3310ca1e50 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -5598,10 +5598,22 @@ spec:
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:
- type: string
- name:
+ description: ID is the ID of the server group to use.
+ format: uuid
type: string
type: object
serverMetadata:
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 f01e35e574..136e031bb5 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -3035,10 +3035,24 @@ spec:
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:
- type: string
- name:
+ description: ID is the ID of the server group
+ to use.
+ format: uuid
type: string
type: object
serverMetadata:
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 1ea294dcb1..5257d76d04 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
@@ -2364,10 +2364,21 @@ spec:
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:
- type: string
- name:
+ description: ID is the ID of the server group to use.
+ format: uuid
type: string
type: object
serverMetadata:
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 4c1b1abb98..111b256b06 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
@@ -2045,10 +2045,22 @@ spec:
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:
- type: string
- name:
+ description: ID is the ID of the server group to use.
+ format: uuid
type: string
type: object
serverMetadata:
diff --git a/controllers/openstackmachine_controller_test.go b/controllers/openstackmachine_controller_test.go
index 53c504e05c..f40802aa98 100644
--- a/controllers/openstackmachine_controller_test.go
+++ b/controllers/openstackmachine_controller_test.go
@@ -92,7 +92,7 @@ func getDefaultOpenStackMachine() *infrav1.OpenStackMachine {
},
ConfigDrive: pointer.Bool(true),
SecurityGroups: []infrav1.SecurityGroupParam{},
- ServerGroup: &infrav1.ServerGroupFilter{ID: serverGroupUUID},
+ ServerGroup: &infrav1.ServerGroupParam{ID: pointer.String(serverGroupUUID)},
},
Status: infrav1.OpenStackMachineStatus{
Resolved: &infrav1.ResolvedMachineSpec{
diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md
index b97042eec6..10a8f3e104 100644
--- a/docs/book/src/api/v1beta1/api.md
+++ b/docs/book/src/api/v1beta1/api.md
@@ -715,8 +715,8 @@ RootVolume
serverGroup
-
-ServerGroupFilter
+
+ServerGroupParam
|
@@ -3270,8 +3270,8 @@ RootVolume
serverGroup
-
-ServerGroupFilter
+
+ServerGroupParam
|
@@ -3642,8 +3642,8 @@ RootVolume
serverGroup
-
-ServerGroupFilter
+
+ServerGroupParam
|
@@ -4778,9 +4778,40 @@ string
(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.
+ |
+
+
+
+ServerGroupParam
+
+
+(Appears on:
OpenStackMachineSpec)
+
ServerGroupParam specifies an OpenStack server group. It may be specified by ID or filter, but not both.
@@ -4798,16 +4829,20 @@ string
|
+ ID is the ID of the server group to use.
|
-name
+filter
-string
+
+ServerGroupFilter
+
|
+ Filter specifies a query to select an OpenStack server group. If provided, it cannot be empty.
|
diff --git a/pkg/cloud/services/compute/referenced_resources_test.go b/pkg/cloud/services/compute/referenced_resources_test.go
index b4419b691d..eca7468d9d 100644
--- a/pkg/cloud/services/compute/referenced_resources_test.go
+++ b/pkg/cloud/services/compute/referenced_resources_test.go
@@ -67,7 +67,7 @@ func Test_ResolveMachineSpec(t *testing.T) {
{
testName: "Resources ID passed",
spec: infrav1.OpenStackMachineSpec{
- ServerGroup: &infrav1.ServerGroupFilter{ID: serverGroupID1},
+ ServerGroup: &infrav1.ServerGroupParam{ID: pointer.String(serverGroupID1)},
Image: infrav1.ImageParam{ID: pointer.String(imageID1)},
},
want: &infrav1.ResolvedMachineSpec{
@@ -90,7 +90,7 @@ func Test_ResolveMachineSpec(t *testing.T) {
testName: "Server group empty",
spec: infrav1.OpenStackMachineSpec{
Image: infrav1.ImageParam{ID: pointer.String(imageID1)},
- ServerGroup: &infrav1.ServerGroupFilter{},
+ ServerGroup: nil,
},
want: &infrav1.ResolvedMachineSpec{
ImageID: imageID1,
@@ -101,7 +101,7 @@ func Test_ResolveMachineSpec(t *testing.T) {
testName: "Server group by Name not found",
spec: infrav1.OpenStackMachineSpec{
Image: infrav1.ImageParam{ID: pointer.String(imageID1)},
- ServerGroup: &infrav1.ServerGroupFilter{Name: "test-server-group"},
+ ServerGroup: &infrav1.ServerGroupParam{Filter: &infrav1.ServerGroupFilter{Name: pointer.String("test-server-group")}},
},
expectComputeMock: func(m *mock.MockComputeClientMockRecorder) {
m.ListServerGroups().Return(
@@ -197,6 +197,7 @@ func Test_ResolveMachineSpec(t *testing.T) {
return
}
+ g.Expect(err).To(BeNil())
g.Expect(resources).To(Equal(tt.want), cmp.Diff(resources, tt.want))
})
}
diff --git a/pkg/cloud/services/compute/servergroup.go b/pkg/cloud/services/compute/servergroup.go
index f4118da73f..e36b0edc51 100644
--- a/pkg/cloud/services/compute/servergroup.go
+++ b/pkg/cloud/services/compute/servergroup.go
@@ -17,6 +17,7 @@ limitations under the License.
package compute
import (
+ "errors"
"fmt"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/servergroups"
@@ -26,18 +27,18 @@ import (
// GetServerGroupID looks up a server group using the passed filter and returns
// its ID. It'll return an error when server group is not found or there are multiple.
-func (s *Service) GetServerGroupID(serverGroupFilter *infrav1.ServerGroupFilter) (string, error) {
- if serverGroupFilter.ID != "" {
- return serverGroupFilter.ID, nil
+func (s *Service) GetServerGroupID(serverGroupParam *infrav1.ServerGroupParam) (string, error) {
+ if serverGroupParam.ID != nil {
+ return *serverGroupParam.ID, nil
}
- if serverGroupFilter.Name == "" {
- // empty filter produced no server group, but also no error
- return "", nil
+ if serverGroupParam.Filter == nil || serverGroupParam.Filter.Name == nil {
+ // Should have been caught by validation
+ return "", errors.New("server group param is empty")
}
// otherwise fallback to looking up by name, which is slower
- serverGroup, err := s.getServerGroupByName(serverGroupFilter.Name)
+ serverGroup, err := s.getServerGroupByName(*serverGroupParam.Filter.Name)
if err != nil {
return "", err
}
diff --git a/pkg/cloud/services/compute/servergroup_test.go b/pkg/cloud/services/compute/servergroup_test.go
index 2771ccf26a..b73b496dcf 100644
--- a/pkg/cloud/services/compute/servergroup_test.go
+++ b/pkg/cloud/services/compute/servergroup_test.go
@@ -23,6 +23,7 @@ import (
"github.com/go-logr/logr/testr"
"github.com/golang/mock/gomock"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/servergroups"
+ "k8s.io/utils/pointer"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/mock"
@@ -34,31 +35,31 @@ func TestService_GetServerGroupID(t *testing.T) {
const serverGroupID2 = "8f536889-5198-42d7-8314-cb78f4f4755c"
tests := []struct {
- testName string
- serverGroupFilter *infrav1.ServerGroupFilter
- expect func(m *mock.MockComputeClientMockRecorder)
- want string
- wantErr bool
+ testName string
+ serverGroupParam *infrav1.ServerGroupParam
+ expect func(m *mock.MockComputeClientMockRecorder)
+ want string
+ wantErr bool
}{
{
- testName: "Return server group ID from filter if only filter (with ID) given",
- serverGroupFilter: &infrav1.ServerGroupFilter{ID: serverGroupID1},
+ testName: "Return server group ID from filter if only filter (with ID) given",
+ serverGroupParam: &infrav1.ServerGroupParam{ID: pointer.String(serverGroupID1)},
expect: func(m *mock.MockComputeClientMockRecorder) {
},
want: serverGroupID1,
wantErr: false,
},
{
- testName: "Return no server group if empty filter is given",
- serverGroupFilter: &infrav1.ServerGroupFilter{},
+ testName: "Return error if empty filter is given",
+ serverGroupParam: &infrav1.ServerGroupParam{},
expect: func(m *mock.MockComputeClientMockRecorder) {
},
want: "",
- wantErr: false,
+ wantErr: true,
},
{
- testName: "Return server group ID from filter if only filter (with name) given",
- serverGroupFilter: &infrav1.ServerGroupFilter{Name: "test-server-group"},
+ testName: "Return server group ID from filter if only filter (with name) given",
+ serverGroupParam: &infrav1.ServerGroupParam{Filter: &infrav1.ServerGroupFilter{Name: pointer.String("test-server-group")}},
expect: func(m *mock.MockComputeClientMockRecorder) {
m.ListServerGroups().Return(
[]servergroups.ServerGroup{{ID: serverGroupID1, Name: "test-server-group"}},
@@ -68,8 +69,8 @@ func TestService_GetServerGroupID(t *testing.T) {
wantErr: false,
},
{
- testName: "Return no results",
- serverGroupFilter: &infrav1.ServerGroupFilter{Name: "test-server-group"},
+ testName: "Return no results",
+ serverGroupParam: &infrav1.ServerGroupParam{Filter: &infrav1.ServerGroupFilter{Name: pointer.String("test-server-group")}},
expect: func(m *mock.MockComputeClientMockRecorder) {
m.ListServerGroups().Return(
[]servergroups.ServerGroup{},
@@ -79,8 +80,8 @@ func TestService_GetServerGroupID(t *testing.T) {
wantErr: true,
},
{
- testName: "Return multiple results",
- serverGroupFilter: &infrav1.ServerGroupFilter{Name: "test-server-group"},
+ testName: "Return multiple results",
+ serverGroupParam: &infrav1.ServerGroupParam{Filter: &infrav1.ServerGroupFilter{Name: pointer.String("test-server-group")}},
expect: func(m *mock.MockComputeClientMockRecorder) {
m.ListServerGroups().Return(
[]servergroups.ServerGroup{
@@ -93,8 +94,8 @@ func TestService_GetServerGroupID(t *testing.T) {
wantErr: true,
},
{
- testName: "OpenStack returns error",
- serverGroupFilter: &infrav1.ServerGroupFilter{Name: "test-server-group"},
+ testName: "OpenStack returns error",
+ serverGroupParam: &infrav1.ServerGroupParam{Filter: &infrav1.ServerGroupFilter{Name: pointer.String("test-server-group")}},
expect: func(m *mock.MockComputeClientMockRecorder) {
m.ListServerGroups().Return(
nil,
@@ -116,7 +117,7 @@ func TestService_GetServerGroupID(t *testing.T) {
}
tt.expect(mockScopeFactory.ComputeClient.EXPECT())
- got, err := s.GetServerGroupID(tt.serverGroupFilter)
+ got, err := s.GetServerGroupID(tt.serverGroupParam)
if (err != nil) != tt.wantErr {
t.Errorf("Service.getServerGroupID() error = %v, wantErr %v", err, tt.wantErr)
return
diff --git a/test/e2e/suites/apivalidations/filters_test.go b/test/e2e/suites/apivalidations/filters_test.go
index c451a620e3..08b8cdfccd 100644
--- a/test/e2e/suites/apivalidations/filters_test.go
+++ b/test/e2e/suites/apivalidations/filters_test.go
@@ -406,4 +406,39 @@ var _ = Describe("Filter API validations", func() {
Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should fail")
})
})
+
+ Context("ServerGroupParam", func() {
+ It("should allow setting ID", func() {
+ machine.Spec.ServerGroup = &infrav1.ServerGroupParam{ID: pointer.String("06c32c52-f207-4f6a-a769-bbcbe5a43f5c")}
+ Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "OpenStackMachine creation should succeed")
+ })
+
+ It("should allow setting non-empty Filter", func() {
+ machine.Spec.ServerGroup = &infrav1.ServerGroupParam{Filter: &infrav1.ServerGroupFilter{Name: pointer.String("foo")}}
+ Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "OpenStackMachine creation should succeed")
+ })
+
+ It("should not allow setting empty param", func() {
+ machine.Spec.ServerGroup = &infrav1.ServerGroupParam{}
+ Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail")
+ })
+
+ It("should not allow setting invalid id", func() {
+ machine.Spec.ServerGroup = &infrav1.ServerGroupParam{ID: pointer.String("foo")}
+ Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail")
+ })
+
+ It("should not allow setting empty Filter", func() {
+ machine.Spec.ServerGroup = &infrav1.ServerGroupParam{Filter: &infrav1.ServerGroupFilter{}}
+ Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail")
+ })
+
+ It("should not allow setting both ID and Filter", func() {
+ machine.Spec.ServerGroup = &infrav1.ServerGroupParam{
+ ID: pointer.String("06c32c52-f207-4f6a-a769-bbcbe5a43f5c"),
+ Filter: &infrav1.ServerGroupFilter{Name: pointer.String("foo")},
+ }
+ Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail")
+ })
+ })
})
diff --git a/test/helpers/fuzzerfuncs.go b/test/helpers/fuzzerfuncs.go
index b181e02c45..063bfe9b58 100644
--- a/test/helpers/fuzzerfuncs.go
+++ b/test/helpers/fuzzerfuncs.go
@@ -149,5 +149,9 @@ func InfraV1FuzzerFuncs() []interface{} {
func(param *infrav1.RouterParam, c fuzz.Continue) {
fuzzFilterParam(¶m.ID, ¶m.Filter, c)
},
+
+ func(param *infrav1.SecurityGroupParam, c fuzz.Continue) {
+ fuzzFilterParam(¶m.ID, ¶m.Filter, c)
+ },
}
}
From de0dffa5ff0fa07a82b81769e342f8d8a953ce91 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Mon, 1 Apr 2024 12:29:36 +0100
Subject: [PATCH 160/180] Fuzz test conversion restore functions
---
api/v1alpha6/conversion_test.go | 31 ++++++++++++
api/v1alpha6/openstackcluster_conversion.go | 30 ++++++------
api/v1alpha6/types_conversion.go | 2 +-
api/v1alpha7/conversion_test.go | 35 +++++++++++++
api/v1alpha7/openstackcluster_conversion.go | 20 ++++----
api/v1alpha7/types_conversion.go | 4 +-
test/helpers/fuzz_restorer.go | 54 +++++++++++++++++++++
7 files changed, 148 insertions(+), 28 deletions(-)
create mode 100644 test/helpers/fuzz_restorer.go
diff --git a/api/v1alpha6/conversion_test.go b/api/v1alpha6/conversion_test.go
index 91fdeb7c3e..67a394d801 100644
--- a/api/v1alpha6/conversion_test.go
+++ b/api/v1alpha6/conversion_test.go
@@ -763,3 +763,34 @@ func TestConvert_v1alpha6_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(t
})
}
}
+
+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, "restorev1alpha6SecurityGroup", restorev1alpha6SecurityGroup)
+}
diff --git a/api/v1alpha6/openstackcluster_conversion.go b/api/v1alpha6/openstackcluster_conversion.go
index 55fdcddf76..1da12e3587 100644
--- a/api/v1alpha6/openstackcluster_conversion.go
+++ b/api/v1alpha6/openstackcluster_conversion.go
@@ -120,17 +120,19 @@ func restorev1alpha6ClusterSpec(previous *OpenStackClusterSpec, dst *OpenStackCl
return
}
- 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 = ""
+ 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 = ""
+ }
}
}
@@ -199,7 +201,7 @@ func restorev1beta1ClusterSpec(previous *infrav1.OpenStackClusterSpec, dst *infr
dst.ManagedSubnets = previous.ManagedSubnets
- if previous.ManagedSecurityGroups != nil {
+ if previous.ManagedSecurityGroups != nil && dst.ManagedSecurityGroups != nil {
dst.ManagedSecurityGroups.AllNodesSecurityGroupRules = previous.ManagedSecurityGroups.AllNodesSecurityGroupRules
}
@@ -345,13 +347,13 @@ func Convert_v1beta1_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(in *i
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 {
+ 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 {
+ if previous.Bastion != nil && previous.Bastion.Networks != nil && dst.Bastion != nil {
dst.Bastion.Networks = previous.Bastion.Networks
}
diff --git a/api/v1alpha6/types_conversion.go b/api/v1alpha6/types_conversion.go
index 7b99803d3f..b855b9e473 100644
--- a/api/v1alpha6/types_conversion.go
+++ b/api/v1alpha6/types_conversion.go
@@ -224,7 +224,7 @@ func restorev1beta1SubnetParam(previous *infrav1.SubnetParam, dst *infrav1.Subne
optional.RestoreString(&previous.ID, &dst.ID)
- if dst.Filter != nil {
+ if previous.Filter != nil && dst.Filter != nil {
dst.Filter.FilterByNeutronTags = previous.Filter.FilterByNeutronTags
}
}
diff --git a/api/v1alpha7/conversion_test.go b/api/v1alpha7/conversion_test.go
index f7e33a8a70..d44eabf604 100644
--- a/api/v1alpha7/conversion_test.go
+++ b/api/v1alpha7/conversion_test.go
@@ -371,3 +371,38 @@ func TestConvert_v1alpha7_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(t
})
}
}
+
+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)
+}
diff --git a/api/v1alpha7/openstackcluster_conversion.go b/api/v1alpha7/openstackcluster_conversion.go
index 69b2f58164..7ad0ed7cee 100644
--- a/api/v1alpha7/openstackcluster_conversion.go
+++ b/api/v1alpha7/openstackcluster_conversion.go
@@ -207,7 +207,7 @@ func restorev1beta1ClusterSpec(previous *infrav1.OpenStackClusterSpec, dst *infr
dst.ManagedSubnets = previous.ManagedSubnets
- if previous.ManagedSecurityGroups != nil {
+ if previous.ManagedSecurityGroups != nil && dst.ManagedSecurityGroups != nil {
dst.ManagedSecurityGroups.AllNodesSecurityGroupRules = previous.ManagedSecurityGroups.AllNodesSecurityGroupRules
}
@@ -371,10 +371,9 @@ func Convert_v1beta1_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus(i
/* Bastion */
func restorev1alpha7Bastion(previous **Bastion, dst **Bastion) {
- if *previous == nil || *dst == nil {
+ if previous == nil || dst == nil || *previous == nil || *dst == nil {
return
}
-
prevMachineSpec := &(*previous).Instance
dstMachineSpec := &(*dst).Instance
restorev1alpha7MachineSpec(prevMachineSpec, dstMachineSpec)
@@ -382,15 +381,14 @@ func restorev1alpha7Bastion(previous **Bastion, dst **Bastion) {
}
func restorev1beta1Bastion(previous **infrav1.Bastion, dst **infrav1.Bastion) {
- if *previous != nil {
- 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)
+ 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 {
diff --git a/api/v1alpha7/types_conversion.go b/api/v1alpha7/types_conversion.go
index d7c33ec3ef..aeb1c756a6 100644
--- a/api/v1alpha7/types_conversion.go
+++ b/api/v1alpha7/types_conversion.go
@@ -193,7 +193,7 @@ func restorev1beta1SubnetParam(previous *infrav1.SubnetParam, dst *infrav1.Subne
optional.RestoreString(&previous.ID, &dst.ID)
- if dst.Filter != nil {
+ if previous.Filter != nil && dst.Filter != nil {
dst.Filter.FilterByNeutronTags = previous.Filter.FilterByNeutronTags
}
}
@@ -257,7 +257,7 @@ func restorev1beta1RouterParam(previous *infrav1.RouterParam, dst *infrav1.Route
}
optional.RestoreString(&previous.ID, &dst.ID)
- if dst.Filter != nil {
+ if previous.Filter != nil && dst.Filter != nil {
dst.Filter.FilterByNeutronTags = previous.Filter.FilterByNeutronTags
}
}
diff --git a/test/helpers/fuzz_restorer.go b/test/helpers/fuzz_restorer.go
new file mode 100644
index 0000000000..bfe3775006
--- /dev/null
+++ b/test/helpers/fuzz_restorer.go
@@ -0,0 +1,54 @@
+/*
+Copyright 2024 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 helpers
+
+import (
+ "runtime/debug"
+ "testing"
+
+ "github.com/onsi/gomega/format"
+ "k8s.io/client-go/kubernetes/scheme"
+ utilconversion "sigs.k8s.io/cluster-api/util/conversion"
+)
+
+// FuzzRestorer fuzzes the inputs to a restore function and ensures that the function does not panic.
+func FuzzRestorer[T any](t *testing.T, name string, f func(*T, *T)) {
+ t.Helper()
+ fuzz := utilconversion.GetFuzzer(scheme.Scheme)
+
+ t.Run(name, func(t *testing.T) {
+ for i := 0; i < 1000; i++ {
+ previous := new(T)
+ dst := new(T)
+ fuzz.Fuzz(previous)
+ fuzz.Fuzz(dst)
+
+ func() {
+ defer func() {
+ if r := recover(); r != nil {
+ t.Errorf("PANIC with arguments\nPrevious: %s\nDest: %s\nStack: %s",
+ format.Object(previous, 1),
+ format.Object(dst, 1),
+ debug.Stack())
+ t.FailNow()
+ }
+ }()
+ f(previous, dst)
+ }()
+ }
+ })
+}
From 2901efed3daf7637fd9cf0a4bf508e17da4329e3 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Thu, 28 Mar 2024 15:03:10 +0000
Subject: [PATCH 161/180] Document changes of Filters to Params
---
.../topics/crd-changes/v1alpha7-to-v1beta1.md | 96 +++++++++++++++----
1 file changed, 80 insertions(+), 16 deletions(-)
diff --git a/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md b/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
index 7ad5cb3dab..2066d24937 100644
--- a/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
+++ b/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
@@ -30,6 +30,7 @@
- [Changes to apiServerLoadBalancer](#changes-to-apiserverloadbalancer)
- [Changes to bastion](#changes-to-bastion)
- [Changes to filters](#changes-to-filters)
+ - [Filters are replaced by params with separate id and filter](#filters-are-replaced-by-params-with-separate-id-and-filter)
- [Changes to filter tags](#changes-to-filter-tags)
- [Field capitalization consistency](#field-capitalization-consistency)
@@ -65,9 +66,9 @@ This has moved to `identityRef.cloudName`.
#### Change to serverGroupID
-The field `serverGroupID` has been renamed to `serverGroup` and is now a `ServerGroupFilter` object rather than a string ID.
+The field `serverGroupID` has been renamed to `serverGroup` and is now a `ServerGroupParam` object rather than a string ID.
-The `ServerGroupFilter` object allows selection of a server group by name or by ID.
+The `ServerGroupParam` object allows selection of a server group by name or by ID.
```yaml
serverGroupID: "e60f19e7-cb37-49f9-a2ee-0a1281f6e03e"
@@ -84,16 +85,18 @@ To select a server group by name instead of ID:
```yaml
serverGroup:
- name: "workers"
+ filter:
+ name: "workers"
```
-If a server group is provided and found, it'll be added to `OpenStackMachine.Status.ReferencedResources.ServerGroupID`. If the server group can't be found or filter matches multiple server groups, an error will be returned.
-If empty object or null is provided, Machine will not be added to any server group and `OpenStackMachine.Status.ReferencedResources.ServerGroupID` will be empty.
+If a server group is provided and found, it will be added to `OpenStackMachine.Status.ReferencedResources.ServerGroupID`. If the server group can't be found or filter matches multiple server groups, an error will be returned.
+If no serverGroup is provided, Machine will not be added to any server group and `OpenStackMachine.Status.ReferencedResources.ServerGroupID` will be empty.
+It is an error to provide an empty serverGroup.
#### Change to image
-The field `image` is now an `ImageFilter` object rather than a string name.
-The `ImageFilter` object allows selection of an image by ID or by name and tags. If ID is set, no other fields can be set in the object.
+The field `image` is now an `ImageParam` object rather than a string name.
+The `ImageParam` object allows selection of an image by ID or by filter. Either ID or a filter may be set, but not both.
```yaml
image: "test-image"
@@ -103,7 +106,8 @@ becomes
```yaml
image:
- name: "test-image"
+ filter:
+ name: "test-image"
```
The image ID will be added to `OpenStackMachine.Status.ReferencedResources.ImageID`. If the image can't be found or filter matches multiple images, an error will be returned.
@@ -171,8 +175,8 @@ Note that this is in contrast `identityRef` in `OpenStackMachine`, which remains
#### Change to externalNetworkID
-The field `externalNetworkID` has been renamed to `externalNetwork` and is now a `NetworkFilter` object rather than a string ID.
-The `NetworkFilter` object allows selection of a network by name, by ID or by tags.
+The field `externalNetworkID` has been renamed to `externalNetwork` and is now a `NetworkParam` object rather than a string ID.
+The `NetworkParam` object allows selection of a network by id or filter parameters.
```yaml
externalNetworkID: "e60f19e7-cb37-49f9-a2ee-0a1281f6e03e"
@@ -185,14 +189,15 @@ externalNetwork:
id: "e60f19e7-cb37-49f9-a2ee-0a1281f6e03e"
```
-It is now possible to specify a `NetworkFilter` object to select the external network to use for the cluster. The `NetworkFilter` object allows to select the network by name, by ID or by tags.
+It is now possible to specify a `NetworkParam` object to select the external network to use for the cluster. The `NetworkParam` object allows to select the network by id or by filter, which can select by name, ID or tags.
```yaml
externalNetwork:
- name: "public"
+ filter:
+ name: "public"
```
-If a network is provided, it'll be added to `OpenStackCluster.Status.ExternalNetwork`. If the network can't be found, an error will be returned.
+If a network is provided, it will be added to `OpenStackCluster.Status.ExternalNetwork`. If the network can't be found, an error will be returned.
If no network is provided, CAPO will try to find network marked "External" and add it to `OpenStackCluster.Status.ExternalNetwork`. If it can't find a network marked "External",
`OpenStackCluster.Status.ExternalNetwork` will be set to nil.
If more than one network is found, an error will be returned.
@@ -239,7 +244,7 @@ The new field has IPv4 validation added.
#### Change to subnet
-In v1beta1, `Subnet` of `OpenStackCluster` is modified to `Subnets` to allow specification of two existent subnets for the dual-stack scenario.
+In v1beta1, `Subnet` of `OpenStackCluster` is modified to `Subnets` to allow specification of two existing subnets for the dual-stack scenario.
```yaml
subnet:
@@ -253,10 +258,12 @@ In v1beta1, this will be automatically converted to:
- id: a532beb0-c73a-4b5d-af66-3ad05b73d063
```
-`Subnets` allows specifications of maximum two `SubnetFilter` one being IPv4 and the other IPv6. Both subnets must be on the same network. Any filtered subnets will be added to `OpenStackCluster.Status.Network.Subnets`.
+`Subnets` allows specifications of maximum two `SubnetParam`s one being IPv4 and the other IPv6. Both subnets must be on the same network. Any filtered subnets will be added to `OpenStackCluster.Status.Network.Subnets`.
When subnets are not specified on `OpenStackCluster` and only the network is, the network is used to identify the subnets to use. If more than two subnets exist in the network, the user must specify which ones to use by defining the `OpenStackCluster.Spec.Subnets` field.
+See [Filters are replaced by params with separate id and filter](#filters-are-replaced-by-params-with-separate-id-and-filter) for changes to the `SubnetFilter`.
+
#### Change to nodeCidr and dnsNameservers
In v1beta1, `OpenStackCluster.Spec.ManagedSubnets` array field is introduced. The `NodeCIDR` and `DNSNameservers` fields of `OpenStackCluster.Spec` are moved into that structure (renaming `NodeCIDR` to `CIDR`). For example:
@@ -388,11 +395,68 @@ spec:
bastion:
spec:
image:
- name: foobar
+ filter:
+ name: foobar
```
### Changes to filters
+#### Filters are replaced by params with separate id and filter
+
+We previously defined filters for specifying each of the following:
+* Images
+* Networks
+* Subnets
+* Security Groups
+* Routers
+
+In addition, ServerGroupParam is new in v1beta1, but works in the same way.
+
+Taking Images as an example, in `OpenStackMachineSpec` the `image` parameter accepted the following fields:
+* id
+* name
+* tags
+
+However, there were 2 different behaviours here depending on which fields were specified. If `id` was specified we both ignored all other fields, and made no attempt to validate the id because it cannot be known unless it exists. If `id` was not specified we performed an OpenStack query using the other parameters to determine the id. This behaviour is both difficult to describe and validate, so in v1beta1 we have separated the 2 different behaviours into different fields. The `id` field remains, but all other fields become part of a new `filter` parameter. It is required to specify either `id` or `filter`. Specifying both, neither, or an empty filter, will now result in an admission failure (the API server will reject the operation immediately).
+
+We have also added validation to the id field, which must now parse as a uuid. An id field which does not parse as a uuid will also result in an admission failure.
+
+Specifying a filter object by id remains unchanged.
+```yaml
+ image:
+ id: 02e31c38-d5ba-4c57-addb-00fc71eb5b19
+```
+
+Specifying a filter object by a filter parameter must now move filter parameters into the filter field:
+```yaml
+ image:
+ name: my-image
+ tags:
+ - my-tag
+```
+becomes:
+```yaml
+ image:
+ filter:
+ name: my-image
+ tags:
+ - my-tag
+```
+
+The same principle applies to all the filter types. For example:
+
+To specify `externalNetwork` by id in `OpenStackClusterSpec`:
+```yaml
+ externalNetwork:
+ id: 0a5d4e3d-0a2c-4bed-9172-72544db1f8da
+```
+or by name:
+```yaml
+ externalNetwork:
+ filter:
+ name: my-external-network
+```
+
#### Changes to filter tags
We currently define filters on 4 different Neutron resources which are used throughout the API:
From 7c0d7410ddbf5e61b627efec133486e09bc5bc40 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Tue, 2 Apr 2024 13:23:49 +0100
Subject: [PATCH 162/180] Remove legacy v1alpha7 filterconvert utils
---
pkg/utils/filterconvert/v1alpha7/convert.go | 38 ---------------------
1 file changed, 38 deletions(-)
delete mode 100644 pkg/utils/filterconvert/v1alpha7/convert.go
diff --git a/pkg/utils/filterconvert/v1alpha7/convert.go b/pkg/utils/filterconvert/v1alpha7/convert.go
deleted file mode 100644
index 545811d5fb..0000000000
--- a/pkg/utils/filterconvert/v1alpha7/convert.go
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
-Copyright 2024 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 convert
-
-import (
- "github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
-
- infrav1alpha7 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
-)
-
-// NetworkFilterToListOpt converts a v1alpha7.NetworkFilter to a networks.ListOpts
-// Still used by the Floating IP IPAM controller until we bump it to v1beta1.
-func NetworkFilterToListOpt(networkFilter *infrav1alpha7.NetworkFilter) 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,
- }
-}
From 8fe2114d1a97d17668341211f050458c9d96b854 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Tue, 2 Apr 2024 14:27:51 +0100
Subject: [PATCH 163/180] Add API docs for v1alpha1
---
Makefile | 2 +-
api/v1alpha1/doc.go | 3 +
.../gen-crd-api-reference-docs/config.json | 12 +-
docs/book/src/SUMMARY.md | 1 +
docs/book/src/api/v1alpha1/api.md | 317 ++++++++++++++++++
docs/book/src/api/v1alpha6/api.md | 10 +-
docs/book/src/api/v1alpha7/api.md | 10 +-
docs/book/src/api/v1beta1/api.md | 10 +-
8 files changed, 343 insertions(+), 22 deletions(-)
create mode 100644 docs/book/src/api/v1alpha1/api.md
diff --git a/Makefile b/Makefile
index 8b905651da..67f5b6ac16 100644
--- a/Makefile
+++ b/Makefile
@@ -289,7 +289,7 @@ generate-manifests: $(CONTROLLER_GEN) ## Generate manifests e.g. CRD, RBAC etc.
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: 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/$* \
diff --git a/api/v1alpha1/doc.go b/api/v1alpha1/doc.go
index 7fff087c61..367506620a 100644
--- a/api/v1alpha1/doc.go
+++ b/api/v1alpha1/doc.go
@@ -14,4 +14,7 @@ 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/docs/book/gen-crd-api-reference-docs/config.json b/docs/book/gen-crd-api-reference-docs/config.json
index 5c4e964917..840ab6b56d 100644
--- a/docs/book/gen-crd-api-reference-docs/config.json
+++ b/docs/book/gen-crd-api-reference-docs/config.json
@@ -17,15 +17,15 @@
},
{
"typeMatchPrefix": "^sigs\\.k8s\\.io/cluster-api/api/v1beta1",
- "docsURLTemplate": "https://doc.crds.dev/github.com/kubernetes-sigs/cluster-api@v1.5.1"
- },
- {
- "typeMatchPrefix": "^sigs\\.k8s\\.io/cluster-api/api/v1beta1",
- "docsURLTemplate": "https://doc.crds.dev/github.com/kubernetes-sigs/cluster-api@v1.5.1"
+ "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": {
@@ -33,4 +33,4 @@
"k8s.io/apimachinery/pkg/apis/": "Kubernetes "
},
"markdownDisabled": false
- }
\ No newline at end of file
+ }
diff --git a/docs/book/src/SUMMARY.md b/docs/book/src/SUMMARY.md
index 9df5f2f500..90a9ddb8b5 100644
--- a/docs/book/src/SUMMARY.md
+++ b/docs/book/src/SUMMARY.md
@@ -13,6 +13,7 @@
- [v1alpha6 to v1alpha7](./topics/crd-changes/v1alpha6-to-v1alpha7.md)
- [v1alpha7 to v1beta1](./topics/crd-changes/v1alpha7-to-v1beta1.md)
- [API reference](./api/index.md)
+ - [v1alpha1](./api/v1alpha1/api.md)
- [v1alpha6](./api/v1alpha6/api.md)
- [v1alpha7](./api/v1alpha7/api.md)
- [v1beta1](./api/v1beta1/api.md)
diff --git a/docs/book/src/api/v1alpha1/api.md b/docs/book/src/api/v1alpha1/api.md
new file mode 100644
index 0000000000..fa456a74f9
--- /dev/null
+++ b/docs/book/src/api/v1alpha1/api.md
@@ -0,0 +1,317 @@
+infrastructure.cluster.x-k8s.io/v1alpha1
+
+
package v1alpha1 contains API Schema definitions for the infrastructure v1alpha1 API group
+
+Resource Types:
+
+OpenStackFloatingIPPool
+
+
+
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
+
+
+ |
+
+
+
+
+
+
+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
+ |
+
+
+ |
+
+
+
+status
+
+
+OpenStackFloatingIPPoolStatus
+
+
+ |
+
+ |
+
+
+
+OpenStackFloatingIPPoolSpec
+
+
+(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
+ |
+
+
+
+OpenStackFloatingIPPoolStatus
+
+
+(Appears on:
+OpenStackFloatingIPPool)
+
+
+
OpenStackFloatingIPPoolStatus defines the observed state of OpenStackFloatingIPPool.
+
+
+ReclaimPolicy
+(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.
+
diff --git a/docs/book/src/api/v1alpha6/api.md b/docs/book/src/api/v1alpha6/api.md
index 16ec7522c5..142b07a083 100644
--- a/docs/book/src/api/v1alpha6/api.md
+++ b/docs/book/src/api/v1alpha6/api.md
@@ -299,7 +299,7 @@ Kubernetes cluster, which also disables SecurityGroups
controlPlaneEndpoint
-
+
sigs.k8s.io/cluster-api/api/v1beta1.APIEndpoint
@@ -1897,7 +1897,7 @@ Kubernetes cluster, which also disables SecurityGroups
|
controlPlaneEndpoint
-
+
sigs.k8s.io/cluster-api/api/v1beta1.APIEndpoint
@@ -2021,7 +2021,7 @@ Network
|
failureDomains
-
+
sigs.k8s.io/cluster-api/api/v1beta1.FailureDomains
@@ -2398,7 +2398,7 @@ Kubernetes cluster, which also disables SecurityGroups
|
controlPlaneEndpoint
-
+
sigs.k8s.io/cluster-api/api/v1beta1.APIEndpoint
@@ -2887,7 +2887,7 @@ controller’s output.
|
conditions
-
+
sigs.k8s.io/cluster-api/api/v1beta1.Conditions
diff --git a/docs/book/src/api/v1alpha7/api.md b/docs/book/src/api/v1alpha7/api.md
index 9e4dbbeb16..45d2b60038 100644
--- a/docs/book/src/api/v1alpha7/api.md
+++ b/docs/book/src/api/v1alpha7/api.md
@@ -328,7 +328,7 @@ Kubernetes cluster, which also disables SecurityGroups
|
controlPlaneEndpoint
-
+
sigs.k8s.io/cluster-api/api/v1beta1.APIEndpoint
@@ -1948,7 +1948,7 @@ Kubernetes cluster, which also disables SecurityGroups
|
controlPlaneEndpoint
-
+
sigs.k8s.io/cluster-api/api/v1beta1.APIEndpoint
@@ -2097,7 +2097,7 @@ LoadBalancer
|
failureDomains
-
+
sigs.k8s.io/cluster-api/api/v1beta1.FailureDomains
@@ -2504,7 +2504,7 @@ Kubernetes cluster, which also disables SecurityGroups
|
controlPlaneEndpoint
-
+
sigs.k8s.io/cluster-api/api/v1beta1.APIEndpoint
@@ -2983,7 +2983,7 @@ controller’s output.
|
conditions
-
+
sigs.k8s.io/cluster-api/api/v1beta1.Conditions
diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md
index c29f255954..715cdc5b94 100644
--- a/docs/book/src/api/v1beta1/api.md
+++ b/docs/book/src/api/v1beta1/api.md
@@ -331,7 +331,7 @@ Kubernetes cluster, which also disables SecurityGroups
|
controlPlaneEndpoint
-
+
sigs.k8s.io/cluster-api/api/v1beta1.APIEndpoint
@@ -2337,7 +2337,7 @@ Kubernetes cluster, which also disables SecurityGroups
|
controlPlaneEndpoint
-
+
sigs.k8s.io/cluster-api/api/v1beta1.APIEndpoint
@@ -2502,7 +2502,7 @@ LoadBalancer
|
failureDomains
-
+
sigs.k8s.io/cluster-api/api/v1beta1.FailureDomains
@@ -2919,7 +2919,7 @@ Kubernetes cluster, which also disables SecurityGroups
|
controlPlaneEndpoint
-
+
sigs.k8s.io/cluster-api/api/v1beta1.APIEndpoint
@@ -3426,7 +3426,7 @@ controller’s output.
|
conditions
-
+
sigs.k8s.io/cluster-api/api/v1beta1.Conditions
From ed829b35a764ac199a36b9fb720d5033b8dbe28d Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Tue, 2 Apr 2024 15:17:36 +0100
Subject: [PATCH 164/180] Bump version artifacts for release-0.10
---
metadata.yaml | 3 +++
test/e2e/data/e2e_conf.yaml | 2 +-
test/e2e/data/shared/v1beta1_provider/metadata.yaml | 3 +++
3 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/metadata.yaml b/metadata.yaml
index 29d1e357ff..9b291fbe02 100644
--- a/metadata.yaml
+++ b/metadata.yaml
@@ -16,3 +16,6 @@ releaseSeries:
- major: 0
minor: 9
contract: v1beta1
+- major: 0
+ minor: 10
+ contract: v1beta1
diff --git a/test/e2e/data/e2e_conf.yaml b/test/e2e/data/e2e_conf.yaml
index e7e4581c49..f7aa4214e0 100644
--- a/test/e2e/data/e2e_conf.yaml
+++ b/test/e2e/data/e2e_conf.yaml
@@ -153,7 +153,7 @@ providers:
new: "--v=4"
- old: "--leader-elect"
new: "--leader-elect=false\n - --sync-period=1m"
- - name: v0.9.99
+ - name: v0.10.99
value: ../../../config/default
# This is the upcoming version.
# Specify no contract so that upgrade tests that start from a specific contract won't pick it up.
diff --git a/test/e2e/data/shared/v1beta1_provider/metadata.yaml b/test/e2e/data/shared/v1beta1_provider/metadata.yaml
index 29d1e357ff..9b291fbe02 100644
--- a/test/e2e/data/shared/v1beta1_provider/metadata.yaml
+++ b/test/e2e/data/shared/v1beta1_provider/metadata.yaml
@@ -16,3 +16,6 @@ releaseSeries:
- major: 0
minor: 9
contract: v1beta1
+- major: 0
+ minor: 10
+ contract: v1beta1
From 9c66684e516187c6387bc939a67ccd76ec7592da Mon Sep 17 00:00:00 2001
From: bilbo
Date: Wed, 3 Apr 2024 17:41:04 +0200
Subject: [PATCH 165/180] make floatingIPNetwork a pointer and if there's only
one external network use it as default
---
api/v1alpha1/conditions_consts.go | 3 +++
api/v1alpha1/openstackfloatingippool_types.go | 3 +--
api/v1alpha1/zz_generated.deepcopy.go | 6 +++++-
api/v1beta1/conditions_consts.go | 2 ++
...e.cluster.x-k8s.io_openstackfloatingippools.yaml | 1 +
controllers/openstackfloatingippool_controller.go | 13 ++++++++++++-
6 files changed, 24 insertions(+), 4 deletions(-)
diff --git a/api/v1alpha1/conditions_consts.go b/api/v1alpha1/conditions_consts.go
index bc1627604a..e40c728ff8 100644
--- a/api/v1alpha1/conditions_consts.go
+++ b/api/v1alpha1/conditions_consts.go
@@ -22,4 +22,7 @@ const (
// MaxIPsReachedReason is set when the maximum number of floating IPs has been reached.
MaxIPsReachedReason = "MaxIPsReached"
+
+ // UnableToFindFloatingIPNetworkReason is used when the floating ip network is not found.
+ UnableToFindNetwork = "UnableToFindNetwork"
)
diff --git a/api/v1alpha1/openstackfloatingippool_types.go b/api/v1alpha1/openstackfloatingippool_types.go
index 931f2d503e..c3ecff3de1 100644
--- a/api/v1alpha1/openstackfloatingippool_types.go
+++ b/api/v1alpha1/openstackfloatingippool_types.go
@@ -63,10 +63,9 @@ type OpenStackFloatingIPPoolSpec struct {
// 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"`
+ FloatingIPNetwork *infrav1.NetworkParam `json:"floatingIPNetwork"`
// The stratergy to use for reclaiming floating ips when they are released from a machine
- // +kubebuilder:validation:Optional
// +kubebuilder:validation:Enum=Retain;Delete
ReclaimPolicy ReclaimPolicy `json:"reclaimPolicy"`
}
diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go
index 558d53bde3..113ac8664f 100644
--- a/api/v1alpha1/zz_generated.deepcopy.go
+++ b/api/v1alpha1/zz_generated.deepcopy.go
@@ -99,7 +99,11 @@ func (in *OpenStackFloatingIPPoolSpec) DeepCopyInto(out *OpenStackFloatingIPPool
**out = **in
}
out.IdentityRef = in.IdentityRef
- in.FloatingIPNetwork.DeepCopyInto(&out.FloatingIPNetwork)
+ 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.
diff --git a/api/v1beta1/conditions_consts.go b/api/v1beta1/conditions_consts.go
index df2da634ec..cbddf42077 100644
--- a/api/v1beta1/conditions_consts.go
+++ b/api/v1beta1/conditions_consts.go
@@ -61,4 +61,6 @@ const (
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/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackfloatingippools.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackfloatingippools.yaml
index de118da2df..6de7b10f5a 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackfloatingippools.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackfloatingippools.yaml
@@ -158,6 +158,7 @@ spec:
type: string
required:
- identityRef
+ - reclaimPolicy
type: object
status:
description: OpenStackFloatingIPPoolStatus defines the observed state
diff --git a/controllers/openstackfloatingippool_controller.go b/controllers/openstackfloatingippool_controller.go
index 01e496d636..209c9338b9 100644
--- a/controllers/openstackfloatingippool_controller.go
+++ b/controllers/openstackfloatingippool_controller.go
@@ -398,8 +398,19 @@ func (r *OpenStackFloatingIPPoolReconciler) reconcileFloatingIPNetwork(scope *sc
return err
}
- network, err := networkingService.GetNetworkByParam(&pool.Spec.FloatingIPNetwork)
+ // 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)
}
From df19807006a01aa65a684ae152d922ba8ec09a46 Mon Sep 17 00:00:00 2001
From: bilbo
Date: Wed, 3 Apr 2024 13:22:25 +0200
Subject: [PATCH 166/180] Looks for more device_owners when looking for a port
for external network #1985
---
pkg/cloud/services/networking/port.go | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/pkg/cloud/services/networking/port.go b/pkg/cloud/services/networking/port.go
index e75a650265..9b736cd4d4 100644
--- a/pkg/cloud/services/networking/port.go
+++ b/pkg/cloud/services/networking/port.go
@@ -24,6 +24,7 @@ import (
"strings"
"time"
+ "github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/portsbinding"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/portsecurity"
"github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
@@ -58,6 +59,19 @@ func (s *Service) GetPortFromInstanceIP(instanceID string, ip string) ([]ports.P
return s.client.ListPort(portOpts)
}
+type PortListOpts struct {
+ DeviceOwner []string `q:"device_owner"`
+ NetworkID string `q:"network_id"`
+}
+
+func (p *PortListOpts) ToPortListQuery() (string, error) {
+ q, err := gophercloud.BuildQueryString(p)
+ if err != nil {
+ return "", err
+ }
+ return q.String(), nil
+}
+
func (s *Service) GetPortForExternalNetwork(instanceID string, externalNetworkID string) (*ports.Port, error) {
instancePortsOpts := ports.ListOpts{
DeviceID: instanceID,
@@ -68,9 +82,9 @@ func (s *Service) GetPortForExternalNetwork(instanceID string, externalNetworkID
}
for _, instancePort := range instancePorts {
- networkPortsOpts := ports.ListOpts{
+ networkPortsOpts := &PortListOpts{
NetworkID: instancePort.NetworkID,
- DeviceOwner: "network:router_interface",
+ DeviceOwner: []string{"network:router_interface", "network:router_interface_distributed", "network:ha_router_replicated_interface", "network:router_ha_interface"},
}
networkPorts, err := s.client.ListPort(networkPortsOpts)
From f7474561dc06a2057bf19c4cab4040562cfdca5f Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Thu, 4 Apr 2024 10:28:21 +0100
Subject: [PATCH 167/180] Rules are optional in security group rules before
v1beta1
Rules were removed from the security group status in v1beta1. If the
status is modified then an up-converted v1alphaN object will not have
its security group rules restored on down-conversion. As the CRD
requires rules, this results in an API error.
---
api/v1alpha5/types.go | 2 +-
api/v1alpha6/types.go | 2 +-
api/v1alpha7/types.go | 2 +-
...nfrastructure.cluster.x-k8s.io_openstackclusters.yaml | 9 ---------
4 files changed, 3 insertions(+), 12 deletions(-)
diff --git a/api/v1alpha5/types.go b/api/v1alpha5/types.go
index 2138b47560..5c1a37ac7d 100644
--- a/api/v1alpha5/types.go
+++ b/api/v1alpha5/types.go
@@ -241,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
diff --git a/api/v1alpha6/types.go b/api/v1alpha6/types.go
index d37136490c..d93cde281a 100644
--- a/api/v1alpha6/types.go
+++ b/api/v1alpha6/types.go
@@ -253,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
diff --git a/api/v1alpha7/types.go b/api/v1alpha7/types.go
index dd14b84877..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
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 6211a5157b..fab0297af8 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -1112,7 +1112,6 @@ spec:
required:
- id
- name
- - rules
type: object
controlPlaneSecurityGroup:
description: |-
@@ -1166,7 +1165,6 @@ spec:
required:
- id
- name
- - rules
type: object
externalNetwork:
description: External Network contains information about the created
@@ -1785,7 +1783,6 @@ spec:
required:
- id
- name
- - rules
type: object
required:
- ready
@@ -2969,7 +2966,6 @@ spec:
required:
- id
- name
- - rules
type: object
controlPlaneSecurityGroup:
description: |-
@@ -3023,7 +3019,6 @@ spec:
required:
- id
- name
- - rules
type: object
externalNetwork:
description: External Network contains information about the created
@@ -3712,7 +3707,6 @@ spec:
required:
- id
- name
- - rules
type: object
required:
- ready
@@ -4539,7 +4533,6 @@ spec:
required:
- id
- name
- - rules
type: object
controlPlaneSecurityGroup:
description: |-
@@ -4593,7 +4586,6 @@ spec:
required:
- id
- name
- - rules
type: object
externalNetwork:
description: externalNetwork contains information about the external
@@ -4784,7 +4776,6 @@ spec:
required:
- id
- name
- - rules
type: object
required:
- ready
From 55918b14af477470e5352320d4521dd911e7b2f2 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Thu, 4 Apr 2024 11:07:06 +0100
Subject: [PATCH 168/180] Tidy up makefile rules for KUBEBUILDER_ASSETS
---
Makefile | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/Makefile b/Makefile
index 67f5b6ac16..197fb71297 100644
--- a/Makefile
+++ b/Makefile
@@ -133,14 +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_PATHS ?= ./...
-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_PATHS) $(TEST_ARGS)
+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
From 038c11f5df3ae0419a2b494dcf9f3e0448cb647c Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Thu, 4 Apr 2024 11:57:24 +0100
Subject: [PATCH 169/180] API validations: cleanup objects after creation
* Adds a helper function which registers a cleanup helper if an object
was created
* Moves infrav1 tests under a separate context in anticipation of adding
other version tests.
---
.../apivalidations/openstackcluster_test.go | 253 ++++++++++--------
1 file changed, 135 insertions(+), 118 deletions(-)
diff --git a/test/e2e/suites/apivalidations/openstackcluster_test.go b/test/e2e/suites/apivalidations/openstackcluster_test.go
index 122269034b..6ef30c3461 100644
--- a/test/e2e/suites/apivalidations/openstackcluster_test.go
+++ b/test/e2e/suites/apivalidations/openstackcluster_test.go
@@ -23,142 +23,159 @@ import (
"k8s.io/apimachinery/pkg/types"
"k8s.io/utils/pointer"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
+ "sigs.k8s.io/controller-runtime/pkg/client"
+ "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
)
var _ = Describe("OpenStackCluster API validations", func() {
- var cluster *infrav1.OpenStackCluster
var namespace *corev1.Namespace
- BeforeEach(func() {
- namespace = createNamespace()
-
- // Initialise a basic cluster object in the correct namespace
- cluster = &infrav1.OpenStackCluster{}
- cluster.Namespace = namespace.Name
- cluster.GenerateName = "cluster-"
- })
-
- It("should allow the smallest permissible cluster spec", func() {
- Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
- })
-
- It("should only allow controlPlaneEndpoint to be set once", func() {
- By("Creating a bare cluster")
- Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
-
- By("Setting the control plane endpoint")
- cluster.Spec.ControlPlaneEndpoint = &clusterv1.APIEndpoint{
- Host: "foo",
- Port: 1234,
+ create := func(obj client.Object) error {
+ err := k8sClient.Create(ctx, obj)
+ if err == nil {
+ DeferCleanup(func() error {
+ return k8sClient.Delete(ctx, obj)
+ })
}
- Expect(k8sClient.Update(ctx, cluster)).To(Succeed(), "Setting control plane endpoint should succeed")
-
- By("Modifying the control plane endpoint")
- cluster.Spec.ControlPlaneEndpoint.Host = "bar"
- Expect(k8sClient.Update(ctx, cluster)).NotTo(Succeed(), "Updating control plane endpoint should fail")
- })
-
- It("should allow an empty managed security groups definition", func() {
- cluster.Spec.ManagedSecurityGroups = &infrav1.ManagedSecurityGroups{}
- Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
- })
-
- It("should default enabled to true if APIServerLoadBalancer is specified without enabled=true", func() {
- cluster.Spec.APIServerLoadBalancer = &infrav1.APIServerLoadBalancer{}
- Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
-
- // Fetch the cluster and check the defaulting
- fetchedCluster := &infrav1.OpenStackCluster{}
- Expect(k8sClient.Get(ctx, types.NamespacedName{Name: cluster.Name, Namespace: cluster.Namespace}, fetchedCluster)).To(Succeed(), "OpenStackCluster fetch should succeed")
-
- Expect(fetchedCluster.Spec.APIServerLoadBalancer.Enabled).ToNot(BeNil(), "APIServerLoadBalancer.Enabled should have been defaulted")
- Expect(*fetchedCluster.Spec.APIServerLoadBalancer.Enabled).To(BeTrue(), "APIServerLoadBalancer.Enabled should default to true")
- })
-
- It("should not default APIServerLoadBalancer if it is not specifid", func() {
- Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
-
- // Fetch the cluster and check the defaulting
- fetchedCluster := &infrav1.OpenStackCluster{}
- Expect(k8sClient.Get(ctx, types.NamespacedName{Name: cluster.Name, Namespace: cluster.Namespace}, fetchedCluster)).To(Succeed(), "OpenStackCluster fetch should succeed")
+ return err
+ }
- Expect(fetchedCluster.Spec.APIServerLoadBalancer).To(BeNil(), "APIServerLoadBalancer should not have been defaulted")
- Expect(fetchedCluster.Spec.APIServerLoadBalancer.IsEnabled()).To(BeFalse(), "APIServerLoadBalancer.Enabled should not have been defaulted")
+ BeforeEach(func() {
+ namespace = createNamespace()
})
- It("should allow bastion.enabled=true with a spec", func() {
- cluster.Spec.Bastion = &infrav1.Bastion{
- Enabled: pointer.Bool(true),
- Spec: &infrav1.OpenStackMachineSpec{
- Image: infrav1.ImageParam{
- Filter: &infrav1.ImageFilter{
- Name: pointer.String("fake-image"),
+ Context("infrav1", func() {
+ var cluster *infrav1.OpenStackCluster
+
+ BeforeEach(func() {
+ // Initialise a basic cluster object in the correct namespace
+ cluster = &infrav1.OpenStackCluster{}
+ cluster.Namespace = namespace.Name
+ cluster.GenerateName = "cluster-"
+ })
+
+ It("should allow the smallest permissible cluster spec", func() {
+ Expect(create(cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
+ })
+
+ It("should only allow controlPlaneEndpoint to be set once", func() {
+ By("Creating a bare cluster")
+ Expect(create(cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
+
+ By("Setting the control plane endpoint")
+ cluster.Spec.ControlPlaneEndpoint = &clusterv1.APIEndpoint{
+ Host: "foo",
+ Port: 1234,
+ }
+ Expect(k8sClient.Update(ctx, cluster)).To(Succeed(), "Setting control plane endpoint should succeed")
+
+ By("Modifying the control plane endpoint")
+ cluster.Spec.ControlPlaneEndpoint.Host = "bar"
+ Expect(k8sClient.Update(ctx, cluster)).NotTo(Succeed(), "Updating control plane endpoint should fail")
+ })
+
+ It("should allow an empty managed security groups definition", func() {
+ cluster.Spec.ManagedSecurityGroups = &infrav1.ManagedSecurityGroups{}
+ Expect(create(cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
+ })
+
+ It("should default enabled to true if APIServerLoadBalancer is specified without enabled=true", func() {
+ cluster.Spec.APIServerLoadBalancer = &infrav1.APIServerLoadBalancer{}
+ Expect(create(cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
+
+ // Fetch the cluster and check the defaulting
+ fetchedCluster := &infrav1.OpenStackCluster{}
+ Expect(k8sClient.Get(ctx, types.NamespacedName{Name: cluster.Name, Namespace: cluster.Namespace}, fetchedCluster)).To(Succeed(), "OpenStackCluster fetch should succeed")
+
+ Expect(fetchedCluster.Spec.APIServerLoadBalancer.Enabled).ToNot(BeNil(), "APIServerLoadBalancer.Enabled should have been defaulted")
+ Expect(*fetchedCluster.Spec.APIServerLoadBalancer.Enabled).To(BeTrue(), "APIServerLoadBalancer.Enabled should default to true")
+ })
+
+ It("should not default APIServerLoadBalancer if it is not specifid", func() {
+ Expect(create(cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
+
+ // Fetch the cluster and check the defaulting
+ fetchedCluster := &infrav1.OpenStackCluster{}
+ Expect(k8sClient.Get(ctx, types.NamespacedName{Name: cluster.Name, Namespace: cluster.Namespace}, fetchedCluster)).To(Succeed(), "OpenStackCluster fetch should succeed")
+
+ Expect(fetchedCluster.Spec.APIServerLoadBalancer).To(BeNil(), "APIServerLoadBalancer should not have been defaulted")
+ Expect(fetchedCluster.Spec.APIServerLoadBalancer.IsEnabled()).To(BeFalse(), "APIServerLoadBalancer.Enabled should not have been defaulted")
+ })
+
+ It("should allow bastion.enabled=true with a spec", func() {
+ cluster.Spec.Bastion = &infrav1.Bastion{
+ Enabled: pointer.Bool(true),
+ Spec: &infrav1.OpenStackMachineSpec{
+ Image: infrav1.ImageParam{
+ Filter: &infrav1.ImageFilter{
+ Name: pointer.String("fake-image"),
+ },
},
},
- },
- }
- Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
- })
-
- It("should not allow bastion.enabled=true without a spec", func() {
- cluster.Spec.Bastion = &infrav1.Bastion{
- Enabled: pointer.Bool(true),
- }
- Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should not succeed")
- })
-
- It("should not allow an empty Bastion", func() {
- cluster.Spec.Bastion = &infrav1.Bastion{}
- Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should not succeed")
- })
-
- It("should default bastion.enabled=true", func() {
- cluster.Spec.Bastion = &infrav1.Bastion{
- Spec: &infrav1.OpenStackMachineSpec{
- Image: infrav1.ImageParam{
- Filter: &infrav1.ImageFilter{
- Name: pointer.String("fake-image"),
+ }
+ Expect(create(cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
+ })
+
+ It("should not allow bastion.enabled=true without a spec", func() {
+ cluster.Spec.Bastion = &infrav1.Bastion{
+ Enabled: pointer.Bool(true),
+ }
+ Expect(create(cluster)).NotTo(Succeed(), "OpenStackCluster creation should not succeed")
+ })
+
+ It("should not allow an empty Bastion", func() {
+ cluster.Spec.Bastion = &infrav1.Bastion{}
+ Expect(create(cluster)).NotTo(Succeed(), "OpenStackCluster creation should not succeed")
+ })
+
+ It("should default bastion.enabled=true", func() {
+ cluster.Spec.Bastion = &infrav1.Bastion{
+ Spec: &infrav1.OpenStackMachineSpec{
+ Image: infrav1.ImageParam{
+ Filter: &infrav1.ImageFilter{
+ Name: pointer.String("fake-image"),
+ },
},
},
- },
- }
- Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should not succeed")
-
- // Fetch the cluster and check the defaulting
- fetchedCluster := &infrav1.OpenStackCluster{}
- Expect(k8sClient.Get(ctx, types.NamespacedName{Name: cluster.Name, Namespace: cluster.Namespace}, fetchedCluster)).To(Succeed(), "OpenStackCluster fetch should succeed")
- Expect(fetchedCluster.Spec.Bastion.Enabled).ToNot(BeNil(), "Bastion.Enabled should have been defaulted")
- Expect(*fetchedCluster.Spec.Bastion.Enabled).To(BeTrueBecause("Bastion.Enabled should default to true"))
- })
-
- It("should allow IPv4 as bastion floatingIP", func() {
- cluster.Spec.Bastion = &infrav1.Bastion{
- Enabled: pointer.Bool(true),
- Spec: &infrav1.OpenStackMachineSpec{
- Image: infrav1.ImageParam{
- Filter: &infrav1.ImageFilter{
- Name: pointer.String("fake-image"),
+ }
+ Expect(create(cluster)).To(Succeed(), "OpenStackCluster creation should not succeed")
+
+ // Fetch the cluster and check the defaulting
+ fetchedCluster := &infrav1.OpenStackCluster{}
+ Expect(k8sClient.Get(ctx, types.NamespacedName{Name: cluster.Name, Namespace: cluster.Namespace}, fetchedCluster)).To(Succeed(), "OpenStackCluster fetch should succeed")
+ Expect(fetchedCluster.Spec.Bastion.Enabled).ToNot(BeNil(), "Bastion.Enabled should have been defaulted")
+ Expect(*fetchedCluster.Spec.Bastion.Enabled).To(BeTrueBecause("Bastion.Enabled should default to true"))
+ })
+
+ It("should allow IPv4 as bastion floatingIP", func() {
+ cluster.Spec.Bastion = &infrav1.Bastion{
+ Enabled: pointer.Bool(true),
+ Spec: &infrav1.OpenStackMachineSpec{
+ Image: infrav1.ImageParam{
+ Filter: &infrav1.ImageFilter{
+ Name: pointer.String("fake-image"),
+ },
},
},
- },
- FloatingIP: pointer.String("10.0.0.0"),
- }
- Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
- })
-
- It("should not allow non-IPv4 as bastion floating IP", func() {
- cluster.Spec.Bastion = &infrav1.Bastion{
- Spec: &infrav1.OpenStackMachineSpec{
- Image: infrav1.ImageParam{
- Filter: &infrav1.ImageFilter{
- Name: pointer.String("fake-image"),
+ FloatingIP: pointer.String("10.0.0.0"),
+ }
+ Expect(create(cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
+ })
+
+ It("should not allow non-IPv4 as bastion floating IP", func() {
+ cluster.Spec.Bastion = &infrav1.Bastion{
+ Spec: &infrav1.OpenStackMachineSpec{
+ Image: infrav1.ImageParam{
+ Filter: &infrav1.ImageFilter{
+ Name: pointer.String("fake-image"),
+ },
},
},
- },
- FloatingIP: pointer.String("foobar"),
- }
- Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should not succeed")
+ FloatingIP: pointer.String("foobar"),
+ }
+ Expect(create(cluster)).NotTo(Succeed(), "OpenStackCluster creation should not succeed")
+ })
})
})
From c59ee802c72a9918df021df7726903fca687436f Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Thu, 4 Apr 2024 16:55:44 +0100
Subject: [PATCH 170/180] Fix API conversion webhooks in the apivalidation
tests
API versions must be registered in the scheme before starting the
envtest in order for conversion webhooks to be registered.
---
.../apivalidations/openstackcluster_test.go | 1 -
test/e2e/suites/apivalidations/suite_test.go | 29 +++++++++----------
2 files changed, 14 insertions(+), 16 deletions(-)
diff --git a/test/e2e/suites/apivalidations/openstackcluster_test.go b/test/e2e/suites/apivalidations/openstackcluster_test.go
index 6ef30c3461..d05a21c732 100644
--- a/test/e2e/suites/apivalidations/openstackcluster_test.go
+++ b/test/e2e/suites/apivalidations/openstackcluster_test.go
@@ -25,7 +25,6 @@ import (
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
"sigs.k8s.io/controller-runtime/pkg/client"
- "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
)
diff --git a/test/e2e/suites/apivalidations/suite_test.go b/test/e2e/suites/apivalidations/suite_test.go
index 6705a96aa5..b042930e53 100644
--- a/test/e2e/suites/apivalidations/suite_test.go
+++ b/test/e2e/suites/apivalidations/suite_test.go
@@ -63,12 +63,21 @@ func TestAPIs(t *testing.T) {
}
var _ = BeforeSuite(func() {
+ testScheme = scheme.Scheme
+ for _, f := range []func(*runtime.Scheme) error{
+ infrav1alpha1.AddToScheme,
+ infrav1alpha5.AddToScheme,
+ infrav1alpha6.AddToScheme,
+ infrav1alpha7.AddToScheme,
+ infrav1.AddToScheme,
+ } {
+ Expect(f(testScheme)).To(Succeed())
+ }
+
By("bootstrapping test environment")
+ testCRDs := filepath.Join("..", "..", "..", "..", "config", "crd", "bases")
testEnv = &envtest.Environment{
- CRDDirectoryPaths: []string{
- // NOTE: These are the bare CRDs without conversion webhooks
- filepath.Join("..", "..", "..", "..", "config", "crd", "bases"),
- },
+ CRDDirectoryPaths: []string{testCRDs},
ErrorIfCRDPathMissing: true,
WebhookInstallOptions: envtest.WebhookInstallOptions{
Paths: []string{
@@ -86,17 +95,6 @@ var _ = BeforeSuite(func() {
return testEnv.Stop()
})
- testScheme = scheme.Scheme
- for _, f := range []func(*runtime.Scheme) error{
- infrav1alpha1.AddToScheme,
- infrav1alpha5.AddToScheme,
- infrav1alpha6.AddToScheme,
- infrav1alpha7.AddToScheme,
- infrav1.AddToScheme,
- } {
- Expect(f(testScheme)).To(Succeed())
- }
-
k8sClient, err = client.New(cfg, client.Options{Scheme: testScheme})
Expect(err).NotTo(HaveOccurred())
Expect(k8sClient).NotTo(BeNil())
@@ -128,6 +126,7 @@ var _ = BeforeSuite(func() {
Host: testEnv.WebhookInstallOptions.LocalServingHost,
CertDir: testEnv.WebhookInstallOptions.LocalServingCertDir,
}),
+ Logger: GinkgoLogr,
})
Expect(err).ToNot(HaveOccurred(), "Manager setup should succeed")
Expect(webhooks.RegisterAllWithManager(mgr)).To(BeEmpty(), "Failed to register webhooks")
From fe80a3f3babe51b4047895038c093e27d30e9303 Mon Sep 17 00:00:00 2001
From: Pierre Prinetti
Date: Fri, 5 Apr 2024 10:08:44 +0200
Subject: [PATCH 171/180] docs: Document the change of instanceID in v1beta1
---
docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md b/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
index 2066d24937..598873cb0d 100644
--- a/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
+++ b/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
@@ -13,6 +13,7 @@
- [Change to serverGroupID](#change-to-servergroupid)
- [Change to image](#change-to-image)
- [Removal of imageUUID](#removal-of-imageuuid)
+ - [Change to instanceID](#change-to-instanceid)
- [Changes to ports](#changes-to-ports)
- [Addition of floatingIPPoolRef](#addition-of-floatingippoolref)
- [`OpenStackCluster`](#openstackcluster)
@@ -127,6 +128,10 @@ image:
id: "72a6a1e6-3e0a-4a8b-9b4c-2d6f9e3e5f0a"
```
+#### Change to instanceID
+
+In v1beta1, the field `instanceID` moves from `spec` to `status`.
+
#### Changes to ports
These changes apply to ports specified in both OpenStackMachines and the Bastion.
From e2897fb1fe495a2c7697c6e926717da7264868ab Mon Sep 17 00:00:00 2001
From: Ondrej Blazek
Date: Mon, 4 Mar 2024 15:01:26 +0100
Subject: [PATCH 172/180] feat: add configurable loadbalancer network
Previously when loadbalacer was created it used the same network/subnet as the
control plane nodes for the VIP. This was not always the right assumption as some
users might want to be able to customize this according to their env.
This commit fixes the above by adding two fields into
OpenStackClusterSpec/Status two fields `network` and `subnets` under
`APIServerLoadBalancer` so that user can define which network/subnet
to use for allocation of the loadbalancer.
Signed-off-by: Ondrej Blazek
---
api/v1alpha5/zz_generated.conversion.go | 3 +
api/v1alpha6/openstackcluster_conversion.go | 45 +++-
api/v1alpha6/zz_generated.conversion.go | 48 ++--
api/v1alpha7/openstackcluster_conversion.go | 24 ++
api/v1alpha7/zz_generated.conversion.go | 68 +++---
api/v1beta1/types.go | 17 ++
api/v1beta1/zz_generated.deepcopy.go | 17 ++
...re.cluster.x-k8s.io_openstackclusters.yaml | 216 ++++++++++++++++++
...er.x-k8s.io_openstackclustertemplates.yaml | 174 ++++++++++++++
controllers/openstackcluster_controller.go | 57 +++++
docs/book/src/api/v1beta1/api.md | 51 +++++
.../services/loadbalancer/loadbalancer.go | 42 +++-
.../loadbalancer/loadbalancer_test.go | 50 +++-
13 files changed, 738 insertions(+), 74 deletions(-)
diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go
index cc9d3ff4cc..999c555fb4 100644
--- a/api/v1alpha5/zz_generated.conversion.go
+++ b/api/v1alpha5/zz_generated.conversion.go
@@ -456,6 +456,8 @@ func autoConvert_v1beta1_APIServerLoadBalancer_To_v1alpha5_APIServerLoadBalancer
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
return nil
}
@@ -597,6 +599,7 @@ func autoConvert_v1beta1_LoadBalancer_To_v1alpha5_LoadBalancer(in *v1beta1.LoadB
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
}
diff --git a/api/v1alpha6/openstackcluster_conversion.go b/api/v1alpha6/openstackcluster_conversion.go
index d9c7070f66..16375c2c07 100644
--- a/api/v1alpha6/openstackcluster_conversion.go
+++ b/api/v1alpha6/openstackcluster_conversion.go
@@ -210,6 +210,13 @@ func restorev1beta1ClusterSpec(previous *infrav1.OpenStackClusterSpec, dst *infr
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
@@ -294,6 +301,18 @@ func Convert_v1alpha6_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *O
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 {
@@ -375,6 +394,10 @@ func restorev1beta1ClusterStatus(previous *infrav1.OpenStackClusterStatus, dst *
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 {
@@ -390,7 +413,16 @@ func Convert_v1beta1_OpenStackClusterStatus_To_v1alpha6_OpenStackClusterStatus(i
}
out.Network.Router = (*Router)(in.Router)
- out.Network.APIServerLoadBalancer = (*LoadBalancer)(in.APIServerLoadBalancer)
+ 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
@@ -405,7 +437,16 @@ func Convert_v1alpha6_OpenStackClusterStatus_To_v1beta1_OpenStackClusterStatus(i
// Router and APIServerLoadBalancer have been moved out of Network in v1beta1
if in.Network != nil {
out.Router = (*infrav1.Router)(in.Network.Router)
- out.APIServerLoadBalancer = (*infrav1.LoadBalancer)(in.Network.APIServerLoadBalancer)
+ 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
diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go
index 046dfa05fe..93dfea061a 100644
--- a/api/v1alpha6/zz_generated.conversion.go
+++ b/api/v1alpha6/zz_generated.conversion.go
@@ -41,16 +41,6 @@ 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), (*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((*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.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 {
@@ -86,11 +76,6 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*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.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 {
@@ -246,6 +231,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
+ 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.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 {
@@ -341,6 +331,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); 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_v1alpha6_APIServerLoadBalancer(a.(*v1beta1.APIServerLoadBalancer), b.(*APIServerLoadBalancer), scope)
+ }); err != nil {
+ return err
+ }
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 {
@@ -351,6 +346,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); 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_v1alpha6_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_v1alpha6_NetworkFilter(a.(*v1beta1.NetworkFilter), b.(*NetworkFilter), scope)
}); err != nil {
@@ -461,11 +461,6 @@ func autoConvert_v1alpha6_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer
return nil
}
-// Convert_v1alpha6_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer is an autogenerated conversion function.
-func Convert_v1alpha6_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer(in *APIServerLoadBalancer, out *v1beta1.APIServerLoadBalancer, s conversion.Scope) error {
- return autoConvert_v1alpha6_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer(in, out, s)
-}
-
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
@@ -475,14 +470,11 @@ func autoConvert_v1beta1_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalancer
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
return nil
}
-// Convert_v1beta1_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalancer is an autogenerated conversion function.
-func Convert_v1beta1_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalancer(in *v1beta1.APIServerLoadBalancer, out *APIServerLoadBalancer, s conversion.Scope) error {
- return autoConvert_v1beta1_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalancer(in, out, s)
-}
-
func autoConvert_v1alpha6_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 {
@@ -622,14 +614,10 @@ func autoConvert_v1beta1_LoadBalancer_To_v1alpha6_LoadBalancer(in *v1beta1.LoadB
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_v1beta1_LoadBalancer_To_v1alpha6_LoadBalancer is an autogenerated conversion function.
-func Convert_v1beta1_LoadBalancer_To_v1alpha6_LoadBalancer(in *v1beta1.LoadBalancer, out *LoadBalancer, s conversion.Scope) error {
- return autoConvert_v1beta1_LoadBalancer_To_v1alpha6_LoadBalancer(in, out, s)
-}
-
func autoConvert_v1alpha6_NetworkFilter_To_v1beta1_NetworkFilter(in *NetworkFilter, out *v1beta1.NetworkFilter, s conversion.Scope) error {
out.Name = in.Name
out.Description = in.Description
diff --git a/api/v1alpha7/openstackcluster_conversion.go b/api/v1alpha7/openstackcluster_conversion.go
index 09d641f5ab..f273d98760 100644
--- a/api/v1alpha7/openstackcluster_conversion.go
+++ b/api/v1alpha7/openstackcluster_conversion.go
@@ -216,6 +216,14 @@ func restorev1beta1ClusterSpec(previous *infrav1.OpenStackClusterSpec, dst *infr
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
@@ -300,6 +308,18 @@ func Convert_v1alpha7_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *O
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 {
@@ -362,6 +382,10 @@ func restorev1beta1ClusterStatus(previous *infrav1.OpenStackClusterStatus, dst *
}
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 {
diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go
index ca0e36a024..407c862a75 100644
--- a/api/v1alpha7/zz_generated.conversion.go
+++ b/api/v1alpha7/zz_generated.conversion.go
@@ -41,16 +41,6 @@ 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), (*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.AddGeneratedConversionFunc((*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.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 {
@@ -131,11 +121,6 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*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.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 {
@@ -316,6 +301,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); 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 {
@@ -391,6 +381,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); 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 {
@@ -401,6 +396,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); 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 {
@@ -496,11 +496,6 @@ func autoConvert_v1alpha7_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer
return nil
}
-// Convert_v1alpha7_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer is an autogenerated conversion function.
-func Convert_v1alpha7_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer(in *APIServerLoadBalancer, out *v1beta1.APIServerLoadBalancer, s conversion.Scope) error {
- return autoConvert_v1alpha7_APIServerLoadBalancer_To_v1beta1_APIServerLoadBalancer(in, out, s)
-}
-
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
@@ -510,14 +505,11 @@ func autoConvert_v1beta1_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer
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
return nil
}
-// Convert_v1beta1_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer is an autogenerated conversion function.
-func Convert_v1beta1_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer(in *v1beta1.APIServerLoadBalancer, out *APIServerLoadBalancer, s conversion.Scope) error {
- return autoConvert_v1beta1_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer(in, out, s)
-}
-
func autoConvert_v1alpha7_AdditionalBlockDevice_To_v1beta1_AdditionalBlockDevice(in *AdditionalBlockDevice, out *v1beta1.AdditionalBlockDevice, s conversion.Scope) error {
out.Name = in.Name
out.SizeGiB = in.SizeGiB
@@ -786,14 +778,10 @@ func autoConvert_v1beta1_LoadBalancer_To_v1alpha7_LoadBalancer(in *v1beta1.LoadB
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_v1beta1_LoadBalancer_To_v1alpha7_LoadBalancer is an autogenerated conversion function.
-func Convert_v1beta1_LoadBalancer_To_v1alpha7_LoadBalancer(in *v1beta1.LoadBalancer, out *LoadBalancer, s conversion.Scope) error {
- return autoConvert_v1beta1_LoadBalancer_To_v1alpha7_LoadBalancer(in, out, s)
-}
-
func autoConvert_v1alpha7_NetworkFilter_To_v1beta1_NetworkFilter(in *NetworkFilter, out *v1beta1.NetworkFilter, s conversion.Scope) error {
out.Name = in.Name
out.Description = in.Description
@@ -1075,7 +1063,15 @@ func autoConvert_v1alpha7_OpenStackClusterStatus_To_v1beta1_OpenStackClusterStat
out.Network = (*v1beta1.NetworkStatusWithSubnets)(unsafe.Pointer(in.Network))
out.ExternalNetwork = (*v1beta1.NetworkStatus)(unsafe.Pointer(in.ExternalNetwork))
out.Router = (*v1beta1.Router)(unsafe.Pointer(in.Router))
- out.APIServerLoadBalancer = (*v1beta1.LoadBalancer)(unsafe.Pointer(in.APIServerLoadBalancer))
+ 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
@@ -1128,7 +1124,15 @@ func autoConvert_v1beta1_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStat
out.Network = (*NetworkStatusWithSubnets)(unsafe.Pointer(in.Network))
out.ExternalNetwork = (*NetworkStatus)(unsafe.Pointer(in.ExternalNetwork))
out.Router = (*Router)(unsafe.Pointer(in.Router))
- out.APIServerLoadBalancer = (*LoadBalancer)(unsafe.Pointer(in.APIServerLoadBalancer))
+ 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
diff --git a/api/v1beta1/types.go b/api/v1beta1/types.go
index 9bf90d826d..b141d2731b 100644
--- a/api/v1beta1/types.go
+++ b/api/v1beta1/types.go
@@ -632,6 +632,12 @@ type LoadBalancer struct {
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
@@ -802,6 +808,17 @@ type APIServerLoadBalancer struct {
// 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"`
}
func (s *APIServerLoadBalancer) IsZero() bool {
diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go
index c75e06db9e..c1a66427d4 100644
--- a/api/v1beta1/zz_generated.deepcopy.go
+++ b/api/v1beta1/zz_generated.deepcopy.go
@@ -50,6 +50,18 @@ func (in *APIServerLoadBalancer) DeepCopyInto(out *APIServerLoadBalancer) {
*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])
+ }
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIServerLoadBalancer.
@@ -372,6 +384,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.
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 6211a5157b..37e4f575e3 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -4893,12 +4893,185 @@ spec:
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
@@ -6355,6 +6528,49 @@ spec:
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:
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 ccc9da38b0..cebc2b2a04 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -2317,12 +2317,186 @@ spec:
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
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index 3823b6ec3a..56831c714a 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -619,6 +619,57 @@ func bastionHashHasChanged(computeHash string, clusterAnnotations map[string]str
return latestHash != computeHash
}
+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)
@@ -647,6 +698,12 @@ func reconcileNetworkComponents(scope *scope.WithLogger, cluster *clusterv1.Clus
return fmt.Errorf("failed to reconcile network: ManagedSubnets only supports one element, %d provided", len(openStackCluster.Spec.ManagedSubnets))
}
+ 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)
+ }
+
err = networkingService.ReconcileSecurityGroups(openStackCluster, clusterResourceName)
if err != nil {
handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to reconcile security groups: %w", err))
diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md
index 51eccf2f6c..087efc5310 100644
--- a/docs/book/src/api/v1beta1/api.md
+++ b/docs/book/src/api/v1beta1/api.md
@@ -902,6 +902,37 @@ 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
+ |
+
AdditionalBlockDevice
@@ -1750,6 +1781,23 @@ 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.
+ |
+
MachineResources
@@ -1905,6 +1953,7 @@ FilterByNeutronTags
(Appears on:
+APIServerLoadBalancer,
OpenStackClusterSpec,
PortOpts)
@@ -2002,6 +2051,7 @@ string
(Appears on:
+LoadBalancer,
OpenStackClusterStatus)
@@ -5044,6 +5094,7 @@ FilterByNeutronTags
(Appears on:
+APIServerLoadBalancer,
ExternalRouterIPParam,
FixedIP,
OpenStackClusterSpec)
diff --git a/pkg/cloud/services/loadbalancer/loadbalancer.go b/pkg/cloud/services/loadbalancer/loadbalancer.go
index 2de72c81d6..cd309221b4 100644
--- a/pkg/cloud/services/loadbalancer/loadbalancer.go
+++ b/pkg/cloud/services/loadbalancer/loadbalancer.go
@@ -270,9 +270,34 @@ func (s *Service) getOrCreateAPILoadBalancer(openStackCluster *infrav1.OpenStack
return nil, fmt.Errorf("network is not yet available in OpenStackCluster.Status")
}
- // Create the VIP on the first cluster subnet
- subnetID := openStackCluster.Status.Network.Subnets[0].ID
- s.scope.Logger().Info("Creating load balancer in subnet", "subnetID", subnetID, "name", loadBalancerName)
+ if openStackCluster.Status.APIServerLoadBalancer == nil {
+ return nil, fmt.Errorf("apiserver loadbalancer network is not yet available in OpenStackCluster.Status")
+ }
+
+ lbNetwork := openStackCluster.Status.APIServerLoadBalancer.LoadBalancerNetwork
+ if lbNetwork == nil {
+ lbNetwork = &infrav1.NetworkStatusWithSubnets{}
+ openStackCluster.Status.APIServerLoadBalancer.LoadBalancerNetwork = lbNetwork
+ }
+
+ var vipNetworkID, vipSubnetID string
+ if lbNetwork.ID != "" {
+ vipNetworkID = lbNetwork.ID
+ }
+
+ if len(lbNetwork.Subnets) > 0 {
+ // Currently only the first subnet is taken into account.
+ // This can be fixed as soon as we switch over to gophercloud release that
+ // contains AdditionalVips field.
+ vipSubnetID = lbNetwork.Subnets[0].ID
+ }
+
+ if vipNetworkID == "" && vipSubnetID == "" {
+ // keep the default and create the VIP on the first cluster subnet
+ vipSubnetID = openStackCluster.Status.Network.Subnets[0].ID
+ }
+
+ s.scope.Logger().Info("Creating load balancer in subnet", "subnetID", vipSubnetID, "name", loadBalancerName)
providers, err := s.loadbalancerClient.ListLoadBalancerProviders()
if err != nil {
@@ -300,11 +325,12 @@ func (s *Service) getOrCreateAPILoadBalancer(openStackCluster *infrav1.OpenStack
}
lbCreateOpts := loadbalancers.CreateOpts{
- Name: loadBalancerName,
- VipSubnetID: subnetID,
- Description: names.GetDescription(clusterResourceName),
- Provider: lbProvider,
- Tags: openStackCluster.Spec.Tags,
+ Name: loadBalancerName,
+ VipSubnetID: vipSubnetID,
+ VipNetworkID: vipNetworkID,
+ Description: names.GetDescription(clusterResourceName),
+ Provider: lbProvider,
+ Tags: openStackCluster.Spec.Tags,
}
if vipAddress != nil {
lbCreateOpts.VipAddress = *vipAddress
diff --git a/pkg/cloud/services/loadbalancer/loadbalancer_test.go b/pkg/cloud/services/loadbalancer/loadbalancer_test.go
index ce46235d82..3768884adb 100644
--- a/pkg/cloud/services/loadbalancer/loadbalancer_test.go
+++ b/pkg/cloud/services/loadbalancer/loadbalancer_test.go
@@ -475,17 +475,63 @@ func Test_getOrCreateAPILoadBalancer(t *testing.T) {
{ID: "aaaaaaaa-bbbb-cccc-dddd-333333333333"},
},
},
+ APIServerLoadBalancer: &infrav1.LoadBalancer{
+ LoadBalancerNetwork: nil,
+ },
},
},
expectLoadBalancer: func(m *mock.MockLbClientMockRecorder) {
m.ListLoadBalancers(gomock.Any()).Return([]loadbalancers.LoadBalancer{}, nil)
m.ListLoadBalancerProviders().Return(octaviaProviders, nil)
m.CreateLoadBalancer(gomock.Any()).Return(&loadbalancers.LoadBalancer{
- ID: "AAAAA",
+ ID: "AAAAA",
+ VipSubnetID: "aaaaaaaa-bbbb-cccc-dddd-222222222222",
}, nil)
},
want: &loadbalancers.LoadBalancer{
- ID: "AAAAA",
+ ID: "AAAAA",
+ VipSubnetID: "aaaaaaaa-bbbb-cccc-dddd-222222222222",
+ },
+ },
+ {
+ name: "loadbalancer on a specific network created",
+ openStackCluster: &infrav1.OpenStackCluster{
+ Status: infrav1.OpenStackClusterStatus{
+ Network: &infrav1.NetworkStatusWithSubnets{
+ Subnets: []infrav1.Subnet{
+ {ID: "aaaaaaaa-bbbb-cccc-dddd-222222222222"},
+ },
+ },
+ APIServerLoadBalancer: &infrav1.LoadBalancer{
+ LoadBalancerNetwork: &infrav1.NetworkStatusWithSubnets{
+ NetworkStatus: infrav1.NetworkStatus{
+ Name: "VIPNET",
+ ID: "VIPNET",
+ },
+ Subnets: []infrav1.Subnet{
+ {
+ Name: "vip-subnet",
+ CIDR: "10.0.0.0/24",
+ ID: "VIPSUBNET",
+ },
+ },
+ },
+ },
+ },
+ },
+ expectLoadBalancer: func(m *mock.MockLbClientMockRecorder) {
+ m.ListLoadBalancers(gomock.Any()).Return([]loadbalancers.LoadBalancer{}, nil)
+ m.ListLoadBalancerProviders().Return(octaviaProviders, nil)
+ m.CreateLoadBalancer(gomock.Any()).Return(&loadbalancers.LoadBalancer{
+ ID: "AAAAA",
+ VipSubnetID: "VIPSUBNET",
+ VipNetworkID: "VIPNET",
+ }, nil)
+ },
+ want: &loadbalancers.LoadBalancer{
+ ID: "AAAAA",
+ VipSubnetID: "VIPSUBNET",
+ VipNetworkID: "VIPNET",
},
},
}
From 9ebb70689e191c8c658c526c5f3e0e142c03909d Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Tue, 9 Apr 2024 15:01:25 +0100
Subject: [PATCH 173/180] Don't try to resolve machine on delete if cluster not
ready
This fixes a bug where if we created a machine for a cluster which never
became ready, we would never be able to 'resolve' the machine and
therefore never delete it. We address this situation in several layers:
Firstly, we move the point in the machine controller at which we add the
finalizer in the first place. We don't add the finalizer until we're
writing resolved, so this situation can never occur for newly created
machines. This makes sense because we don't create resources until we've
observed that both the finalizer has been added and resolved is up to
date, so we don't need the finalizer to protect resources which can't
have been created yet.
Secondly, we shortcut the delete flow if the cluster is not ready. This
is safe for the same reason as above, but is only relevant to machines
created before v0.10.
Lastly we surface and restrict the circumstances in which 'Resolved' is
required on delete anyway. On closer inspection, this is only required
in the very specific circumstance that the machine has volumes defined,
and we are deleting it without the machine having been created. To make
this more obvious we split volume deletion out of DeleteInstance and
only resolve the machine spec in the event that it's required.
2 other factors make this change larger than it might otherwise be.
We hit a cyclomatic complexity limit in reconcileDelete(), requiring a
refactor.
We remove the DeleteInstance tests which, after separating out
DeleteVolumes, are quite trivial, and replace them with much more
comprehensive set of tests for reconcileDelete.
---
controllers/openstackcluster_controller.go | 19 +-
.../openstackcluster_controller_test.go | 5 +-
controllers/openstackmachine_controller.go | 209 ++++++----
.../openstackmachine_controller_test.go | 365 ++++++++++++++++++
pkg/cloud/services/compute/instance.go | 100 ++---
pkg/cloud/services/compute/instance_test.go | 97 -----
.../services/loadbalancer/loadbalancer.go | 8 +-
7 files changed, 576 insertions(+), 227 deletions(-)
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index 3823b6ec3a..dfe56c8a9d 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -290,7 +290,18 @@ func deleteBastion(scope *scope.WithLogger, cluster *clusterv1.Cluster, openStac
}
}
- if instanceStatus != nil {
+ // If no instance was created we currently need to check for orphaned
+ // volumes. This requires resolving the instance spec.
+ // TODO: write volumes to status resources on creation so this is no longer required.
+ if instanceStatus == nil {
+ instanceSpec, err := bastionToInstanceSpec(openStackCluster, cluster)
+ if err != nil {
+ return err
+ }
+ if err := computeService.DeleteVolumes(instanceSpec); err != nil {
+ return fmt.Errorf("delete volumes: %w", err)
+ }
+ } else {
instanceNS, err := instanceStatus.NetworkStatus()
if err != nil {
return err
@@ -307,11 +318,7 @@ func deleteBastion(scope *scope.WithLogger, cluster *clusterv1.Cluster, openStac
}
}
- instanceSpec, err := bastionToInstanceSpec(openStackCluster, cluster)
- if err != nil {
- return err
- }
- if err = computeService.DeleteInstance(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)
}
diff --git a/controllers/openstackcluster_controller_test.go b/controllers/openstackcluster_controller_test.go
index 86fb45173d..62a7f6fcfa 100644
--- a/controllers/openstackcluster_controller_test.go
+++ b/controllers/openstackcluster_controller_test.go
@@ -208,6 +208,9 @@ var _ = Describe("OpenStackCluster controller", func() {
testCluster.Status = infrav1.OpenStackClusterStatus{
Bastion: &infrav1.BastionStatus{
ID: "bastion-uuid",
+ Resolved: &infrav1.ResolvedMachineSpec{
+ ImageID: "imageID",
+ },
},
}
err = k8sClient.Status().Update(ctx, testCluster)
@@ -221,8 +224,8 @@ var _ = Describe("OpenStackCluster controller", func() {
computeClientRecorder.GetServer("bastion-uuid").Return(nil, gophercloud.ErrResourceNotFound{})
err = deleteBastion(scope, capiCluster, testCluster)
- Expect(testCluster.Status.Bastion).To(BeNil())
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")
diff --git a/controllers/openstackmachine_controller.go b/controllers/openstackmachine_controller.go
index 26691d8430..12eb53d465 100644
--- a/controllers/openstackmachine_controller.go
+++ b/controllers/openstackmachine_controller.go
@@ -169,18 +169,13 @@ func resolveMachineResources(scope *scope.WithLogger, clusterResourceName string
openStackMachine.Status.Resolved = resolved
}
// Resolve and store resources
- changed, err := compute.ResolveMachineSpec(scope,
+ return compute.ResolveMachineSpec(scope,
&openStackMachine.Spec, resolved,
clusterResourceName, openStackMachine.Name,
openStackCluster, getManagedSecurityGroup(openStackCluster, machine))
- if err != nil {
- return false, err
- }
- if changed {
- // If the resolved machine spec changed we need to start the reconcile again to prevent inconsistency between reconciles.
- return true, nil
- }
+}
+func adoptMachineResources(scope *scope.WithLogger, openStackMachine *infrav1.OpenStackMachine) error {
resources := openStackMachine.Status.Resources
if resources == nil {
resources = &infrav1.MachineResources{}
@@ -188,7 +183,7 @@ func resolveMachineResources(scope *scope.WithLogger, clusterResourceName string
}
// Adopt any existing resources
- return false, compute.AdoptMachineResources(scope, resolved, 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 {
@@ -256,66 +251,72 @@ func (r *OpenStackMachineReconciler) reconcileDelete(scope *scope.WithLogger, cl
return ctrl.Result{}, err
}
- // We may have resources to adopt if the cluster is ready
- if openStackCluster.Status.Ready && openStackCluster.Status.Network != nil {
- if _, err := resolveMachineResources(scope, clusterResourceName, openStackCluster, openStackMachine, machine); err != nil {
- return ctrl.Result{}, err
- }
+ // 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
}
- if openStackCluster.Spec.APIServerLoadBalancer.IsEnabled() {
- loadBalancerService, err := loadbalancer.NewService(scope)
- if err != nil {
- return ctrl.Result{}, err
- }
+ // 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
+ }
- err = loadBalancerService.DeleteLoadBalancerMember(openStackCluster, machine, 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 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)
}
- var instanceStatus *compute.InstanceStatus
- if openStackMachine.Status.InstanceID != nil {
- instanceStatus, err = computeService.GetInstanceStatus(*openStackMachine.Status.InstanceID)
- if err != nil {
- return ctrl.Result{}, err
- }
- } else if instanceStatus, err = computeService.GetInstanceStatusByName(openStackMachine, openStackMachine.Name); err != nil {
+ instanceStatus, err := getInstanceStatus(openStackMachine, computeService)
+ if err != nil {
return ctrl.Result{}, err
}
- if !openStackCluster.Spec.APIServerLoadBalancer.IsEnabled() && util.IsControlPlaneMachine(machine) && openStackCluster.Spec.APIServerFloatingIP == nil {
- 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 util.IsControlPlaneMachine(machine) {
+ if err := removeAPIServerEndpoint(scope, openStackCluster, openStackMachine, instanceStatus, clusterResourceName); err != nil {
+ return ctrl.Result{}, err
}
}
- instanceSpec, err := machineToInstanceSpec(openStackCluster, machine, openStackMachine, "")
- if err != nil {
- return ctrl.Result{}, err
+ // If no instance was created we currently need to check for orphaned
+ // volumes. This requires resolving the instance spec.
+ // TODO: write volumes to status resources on creation so this is no longer required.
+ if instanceStatus == nil && openStackMachine.Status.Resolved != nil {
+ instanceSpec, err := machineToInstanceSpec(openStackCluster, machine, openStackMachine, "")
+ if err != nil {
+ return ctrl.Result{}, err
+ }
+ if err := computeService.DeleteVolumes(instanceSpec); err != nil {
+ return ctrl.Result{}, fmt.Errorf("delete volumes: %w", err)
+ }
}
- if err := computeService.DeleteInstance(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 instanceStatus != nil {
+ 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)
+ }
}
trunkSupported, err := networkingService.IsTrunkExtSupported()
@@ -341,6 +342,62 @@ func (r *OpenStackMachineReconciler) reconcileDelete(scope *scope.WithLogger, cl
return ctrl.Result{}, nil
}
+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))
@@ -489,34 +546,50 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope
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 !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
}
- if changed, err := resolveMachineResources(scope, clusterResourceName, openStackCluster, openStackMachine, machine); changed || err != nil {
- scope.Logger().V(6).Info("Machine resources updated, requeuing")
- return ctrl.Result{}, err
- }
-
// Make sure bootstrap data is available and populated.
if machine.Spec.Bootstrap.DataSecretName == nil {
scope.Logger().Info("Bootstrap data secret reference is not yet available")
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
}
+
+ // 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 {
diff --git a/controllers/openstackmachine_controller_test.go b/controllers/openstackmachine_controller_test.go
index f40802aa98..c77220bc4c 100644
--- a/controllers/openstackmachine_controller_test.go
+++ b/controllers/openstackmachine_controller_test.go
@@ -17,17 +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"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
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 (
@@ -206,3 +219,355 @@ func TestGetPortIDs(t *testing.T) {
})
}
}
+
+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: pointer.String(imageName),
+ },
+ }
+
+ defaultResolvedPorts := []infrav1.ResolvedPortSpec{
+ {
+ 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,
+ },
+ }, 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: pointer.String(instanceUUID),
+ Resolved: &infrav1.ResolvedMachineSpec{
+ ImageID: imageUUID,
+ Ports: defaultResolvedPorts,
+ },
+ Resources: &infrav1.MachineResources{
+ Ports: defaultPortsStatus,
+ },
+ },
+ },
+ expect: func(r *recorders) {
+ deleteServerByID(r)
+ deleteDefaultPorts(r)
+ },
+ wantRemoveFinalizer: true,
+ },
+ {
+ name: "Root volume, resolved and resources populated",
+ osMachine: infrav1.OpenStackMachine{
+ Spec: infrav1.OpenStackMachineSpec{
+ Image: defaultImage,
+ RootVolume: &infrav1.RootVolume{
+ Size: 50,
+ },
+ },
+ Status: infrav1.OpenStackMachineStatus{
+ InstanceID: pointer.String(instanceUUID),
+ Resolved: &infrav1.ResolvedMachineSpec{
+ ImageID: imageUUID,
+ Ports: defaultResolvedPorts,
+ },
+ Resources: &infrav1.MachineResources{
+ Ports: defaultPortsStatus,
+ },
+ },
+ },
+ expect: func(r *recorders) {
+ // Server exists, so we don't delete root volume explicitly
+ deleteServerByID(r)
+ deleteDefaultPorts(r)
+ },
+ wantRemoveFinalizer: true,
+ },
+ {
+ name: "Root volume, machine not created, resolved and resources populated",
+ osMachine: infrav1.OpenStackMachine{
+ Spec: infrav1.OpenStackMachineSpec{
+ Image: defaultImage,
+ RootVolume: &infrav1.RootVolume{
+ Size: 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: pointer.String(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 i := range tests {
+ tt := &tests[i]
+ t.Run(tt.name, func(t *testing.T) {
+ 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/pkg/cloud/services/compute/instance.go b/pkg/cloud/services/compute/instance.go
index ac0b377bed..ee808c05d6 100644
--- a/pkg/cloud/services/compute/instance.go
+++ b/pkg/cloud/services/compute/instance.go
@@ -383,33 +383,63 @@ func (s *Service) GetManagementPort(openStackCluster *infrav1.OpenStackCluster,
return &allPorts[0], nil
}
-func (s *Service) DeleteInstance(eventObject runtime.Object, instanceStatus *InstanceStatus, instanceSpec *InstanceSpec) error {
- if instanceStatus == nil {
- /*
- Attaching volumes to an instance is a two-step process:
+func (s *Service) DeleteInstance(eventObject runtime.Object, instanceStatus *InstanceStatus) error {
+ instance := instanceStatus.InstanceIdentifier()
- 1. Create the volume
- 2. Create the instance with the created volumes in RootVolume and AdditionalBlockDevices fields with DeleteOnTermination=true
+ err := s.getComputeClient().DeleteServer(instance.ID)
+ if err != nil {
+ if capoerrors.IsNotFound(err) {
+ record.Eventf(eventObject, "SuccessfulDeleteServer", "Server %s with id %s did not exist", instance.Name, instance.ID)
+ return nil
+ }
+ record.Warnf(eventObject, "FailedDeleteServer", "Failed to delete server %s with id %s: %v", instance.Name, instance.ID, err)
+ return err
+ }
+
+ err = wait.PollUntilContextTimeout(context.TODO(), retryIntervalInstanceStatus, timeoutInstanceDelete, true, func(_ context.Context) (bool, error) {
+ i, err := s.GetInstanceStatus(instance.ID)
+ if err != nil {
+ return false, err
+ }
+ if i != nil {
+ return false, nil
+ }
+ return true, nil
+ })
+ if err != nil {
+ record.Warnf(eventObject, "FailedDeleteServer", "Failed to delete server %s with id %s: %v", instance.Name, instance.ID, err)
+ return err
+ }
- This has a possible failure mode where creating the volume succeeds but creating the instance
- fails. In this case, we want to make sure that the dangling volumes are cleaned up.
+ record.Eventf(eventObject, "SuccessfulDeleteServer", "Deleted server %s with id %s", instance.Name, instance.ID)
+ return nil
+}
- To handle this safely, we ensure that we never remove a machine finalizer until all resources
- associated with the instance, including volumes, have been deleted. To achieve this:
+// DeleteVolumes deletes any cinder volumes which were created for the instance.
+// Note that this must only be called when the server was not successfully
+// created. If the server was created the volume will have been added with
+// DeleteOnTermination=true, and will be automatically cleaned up with the
+// server.
+func (s *Service) DeleteVolumes(instanceSpec *InstanceSpec) error {
+ /*
+ Attaching volumes to an instance is a two-step process:
- * We always call DeleteInstance when reconciling a delete, even if the instance does not exist
- * If the instance was already deleted we check that the volumes are also gone
+ 1. Create the volume
+ 2. Create the instance with the created volumes in RootVolume and AdditionalBlockDevices fields with DeleteOnTermination=true
- Note that we don't need to separately delete the volumes when deleting the instance because
- DeleteOnTermination will ensure it is deleted in that case.
- */
- return s.deleteVolumes(instanceSpec)
- }
+ This has a possible failure mode where creating the volume succeeds but creating the instance
+ fails. In this case, we want to make sure that the dangling volumes are cleaned up.
- return s.deleteInstance(eventObject, instanceStatus.InstanceIdentifier())
-}
+ To handle this safely, we ensure that we never remove a machine finalizer until all resources
+ associated with the instance, including volumes, have been deleted. To achieve this:
+
+ * We always call DeleteInstance when reconciling a delete, even if the instance does not exist
+ * If the instance was already deleted we check that the volumes are also gone
+
+ Note that we don't need to separately delete the volumes when deleting the instance because
+ DeleteOnTermination will ensure it is deleted in that case.
+ */
-func (s *Service) deleteVolumes(instanceSpec *InstanceSpec) error {
if hasRootVolume(instanceSpec) {
if err := s.deleteVolume(instanceSpec.Name, "root"); err != nil {
return err
@@ -437,36 +467,6 @@ func (s *Service) deleteVolume(instanceName string, nameSuffix string) error {
return s.getVolumeClient().DeleteVolume(volume.ID, volumes.DeleteOpts{})
}
-func (s *Service) deleteInstance(eventObject runtime.Object, instance *InstanceIdentifier) error {
- err := s.getComputeClient().DeleteServer(instance.ID)
- if err != nil {
- if capoerrors.IsNotFound(err) {
- record.Eventf(eventObject, "SuccessfulDeleteServer", "Server %s with id %s did not exist", instance.Name, instance.ID)
- return nil
- }
- record.Warnf(eventObject, "FailedDeleteServer", "Failed to delete server %s with id %s: %v", instance.Name, instance.ID, err)
- return err
- }
-
- err = wait.PollUntilContextTimeout(context.TODO(), retryIntervalInstanceStatus, timeoutInstanceDelete, true, func(_ context.Context) (bool, error) {
- i, err := s.GetInstanceStatus(instance.ID)
- if err != nil {
- return false, err
- }
- if i != nil {
- return false, nil
- }
- return true, nil
- })
- if err != nil {
- record.Warnf(eventObject, "FailedDeleteServer", "Failed to delete server %s with id %s: %v", instance.Name, instance.ID, err)
- return err
- }
-
- record.Eventf(eventObject, "SuccessfulDeleteServer", "Deleted server %s with id %s", instance.Name, instance.ID)
- return nil
-}
-
func (s *Service) GetInstanceStatus(resourceID string) (instance *InstanceStatus, err error) {
if resourceID == "" {
return nil, fmt.Errorf("resourceId should be specified to get detail")
diff --git a/pkg/cloud/services/compute/instance_test.go b/pkg/cloud/services/compute/instance_test.go
index b571b25021..54677279aa 100644
--- a/pkg/cloud/services/compute/instance_test.go
+++ b/pkg/cloud/services/compute/instance_test.go
@@ -24,14 +24,12 @@ import (
"github.com/go-logr/logr/testr"
"github.com/golang/mock/gomock"
- "github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/availabilityzones"
"github.com/gophercloud/gophercloud/openstack/compute/v2/flavors"
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
"github.com/gophercloud/gophercloud/openstack/imageservice/v2/images"
. "github.com/onsi/gomega"
- "k8s.io/apimachinery/pkg/runtime"
"k8s.io/utils/pointer"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
@@ -710,98 +708,3 @@ func TestService_ReconcileInstance(t *testing.T) {
})
}
}
-
-func TestService_DeleteInstance(t *testing.T) {
- RegisterTestingT(t)
-
- getDefaultInstanceStatus := func() *InstanceStatus {
- return &InstanceStatus{
- server: &clients.ServerExt{
- Server: servers.Server{
- ID: instanceUUID,
- },
- },
- }
- }
-
- // *******************
- // START OF TEST CASES
- // *******************
-
- type recorders struct {
- compute *mock.MockComputeClientMockRecorder
- network *mock.MockNetworkClientMockRecorder
- volume *mock.MockVolumeClientMockRecorder
- }
-
- tests := []struct {
- name string
- eventObject runtime.Object
- instanceStatus func() *InstanceStatus
- rootVolume *infrav1.RootVolume
- expect func(r *recorders)
- wantErr bool
- }{
- {
- name: "Defaults",
- eventObject: &infrav1.OpenStackMachine{},
- instanceStatus: getDefaultInstanceStatus,
- expect: func(r *recorders) {
- r.compute.DeleteServer(instanceUUID).Return(nil)
- r.compute.GetServer(instanceUUID).Return(nil, gophercloud.ErrDefault404{})
- },
- wantErr: false,
- },
- {
- name: "Dangling volume",
- eventObject: &infrav1.OpenStackMachine{},
- instanceStatus: func() *InstanceStatus { return nil },
- rootVolume: &infrav1.RootVolume{
- Size: 50,
- },
- expect: 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)
- },
- wantErr: false,
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- mockCtrl := gomock.NewController(t)
- log := testr.New(t)
- mockScopeFactory := scope.NewMockScopeFactory(mockCtrl, "")
-
- computeRecorder := mockScopeFactory.ComputeClient.EXPECT()
- networkRecorder := mockScopeFactory.NetworkClient.EXPECT()
- volumeRecorder := mockScopeFactory.VolumeClient.EXPECT()
-
- tt.expect(&recorders{computeRecorder, networkRecorder, volumeRecorder})
-
- s, err := NewService(scope.NewWithLogger(mockScopeFactory, log))
- if err != nil {
- t.Fatalf("Failed to create service: %v", err)
- }
-
- instanceSpec := &InstanceSpec{
- Name: openStackMachineName,
- RootVolume: tt.rootVolume,
- }
-
- if err := s.DeleteInstance(tt.eventObject, tt.instanceStatus(), instanceSpec); (err != nil) != tt.wantErr {
- t.Errorf("Service.DeleteInstance() error = %v, wantErr %v", err, tt.wantErr)
- }
- })
- }
-}
diff --git a/pkg/cloud/services/loadbalancer/loadbalancer.go b/pkg/cloud/services/loadbalancer/loadbalancer.go
index 2de72c81d6..fdff5e58ec 100644
--- a/pkg/cloud/services/loadbalancer/loadbalancer.go
+++ b/pkg/cloud/services/loadbalancer/loadbalancer.go
@@ -31,8 +31,6 @@ import (
"k8s.io/apimachinery/pkg/util/wait"
utilsnet "k8s.io/utils/net"
"k8s.io/utils/pointer"
- clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
- "sigs.k8s.io/cluster-api/util"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/record"
@@ -645,9 +643,9 @@ func (s *Service) DeleteLoadBalancer(openStackCluster *infrav1.OpenStackCluster,
return nil
}
-func (s *Service) DeleteLoadBalancerMember(openStackCluster *infrav1.OpenStackCluster, machine *clusterv1.Machine, openStackMachine *infrav1.OpenStackMachine, clusterResourceName string) error {
- if openStackMachine == nil || !util.IsControlPlaneMachine(machine) {
- return nil
+func (s *Service) DeleteLoadBalancerMember(openStackCluster *infrav1.OpenStackCluster, openStackMachine *infrav1.OpenStackMachine, clusterResourceName string) error {
+ if openStackMachine == nil {
+ return errors.New("openStackMachine is nil")
}
loadBalancerName := getLoadBalancerName(clusterResourceName)
From 6d74e98d694b67592da03cb7f4982409ddaa5296 Mon Sep 17 00:00:00 2001
From: root
Date: Thu, 28 Mar 2024 06:09:24 +0000
Subject: [PATCH 174/180] Add opt to use AZ for APISeverLoadBalancer
---
api/v1alpha5/zz_generated.conversion.go | 1 +
api/v1alpha6/conversion_test.go | 1 +
api/v1alpha6/openstackcluster_conversion.go | 2 ++
api/v1alpha6/types_conversion.go | 12 ++++++++-
api/v1alpha6/zz_generated.conversion.go | 1 +
api/v1alpha7/conversion_test.go | 1 +
api/v1alpha7/openstackcluster_conversion.go | 2 ++
api/v1alpha7/types_conversion.go | 11 ++++++++
api/v1alpha7/zz_generated.conversion.go | 1 +
api/v1beta1/types.go | 5 ++++
api/v1beta1/zz_generated.deepcopy.go | 5 ++++
...re.cluster.x-k8s.io_openstackclusters.yaml | 4 +++
...er.x-k8s.io_openstackclustertemplates.yaml | 4 +++
docs/book/src/api/v1beta1/api.md | 12 +++++++++
.../services/loadbalancer/loadbalancer.go | 25 ++++++++++++-------
15 files changed, 77 insertions(+), 10 deletions(-)
diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go
index 999c555fb4..95f181a279 100644
--- a/api/v1alpha5/zz_generated.conversion.go
+++ b/api/v1alpha5/zz_generated.conversion.go
@@ -458,6 +458,7 @@ func autoConvert_v1beta1_APIServerLoadBalancer_To_v1alpha5_APIServerLoadBalancer
// 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
}
diff --git a/api/v1alpha6/conversion_test.go b/api/v1alpha6/conversion_test.go
index 67a394d801..c451091929 100644
--- a/api/v1alpha6/conversion_test.go
+++ b/api/v1alpha6/conversion_test.go
@@ -793,4 +793,5 @@ func Test_FuzzRestorers(t *testing.T) {
testhelpers.FuzzRestorer(t, "restorev1beta1SubnetParam", restorev1beta1SubnetParam)
testhelpers.FuzzRestorer(t, "restorev1alpha6Port", restorev1alpha6Port)
testhelpers.FuzzRestorer(t, "restorev1alpha6SecurityGroup", restorev1alpha6SecurityGroup)
+ testhelpers.FuzzRestorer(t, "restorev1beta1APIServerLoadBalancer", restorev1beta1APIServerLoadBalancer)
}
diff --git a/api/v1alpha6/openstackcluster_conversion.go b/api/v1alpha6/openstackcluster_conversion.go
index 16375c2c07..626ffd198c 100644
--- a/api/v1alpha6/openstackcluster_conversion.go
+++ b/api/v1alpha6/openstackcluster_conversion.go
@@ -232,6 +232,8 @@ func restorev1beta1ClusterSpec(previous *infrav1.OpenStackClusterSpec, dst *infr
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 {
diff --git a/api/v1alpha6/types_conversion.go b/api/v1alpha6/types_conversion.go
index b855b9e473..e9f1ea72a9 100644
--- a/api/v1alpha6/types_conversion.go
+++ b/api/v1alpha6/types_conversion.go
@@ -497,7 +497,6 @@ func Convert_v1alpha6_SecurityGroup_To_v1beta1_SecurityGroupStatus(in *SecurityG
}
/* SecurityGroupRule */
-/* APIServerLoadBalancer */
/* ValueSpec */
/* OpenStackIdentityReference */
@@ -510,6 +509,17 @@ func Convert_v1beta1_OpenStackIdentityReference_To_v1alpha6_OpenStackIdentityRef
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
diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go
index 93dfea061a..541bef18aa 100644
--- a/api/v1alpha6/zz_generated.conversion.go
+++ b/api/v1alpha6/zz_generated.conversion.go
@@ -472,6 +472,7 @@ func autoConvert_v1beta1_APIServerLoadBalancer_To_v1alpha6_APIServerLoadBalancer
}
// 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
}
diff --git a/api/v1alpha7/conversion_test.go b/api/v1alpha7/conversion_test.go
index d44eabf604..ac3d00cddf 100644
--- a/api/v1alpha7/conversion_test.go
+++ b/api/v1alpha7/conversion_test.go
@@ -405,4 +405,5 @@ func Test_FuzzRestorers(t *testing.T) {
testhelpers.FuzzRestorer(t, "restorev1beta1RouterParam", restorev1beta1RouterParam)
testhelpers.FuzzRestorer(t, "restorev1alpha7Port", restorev1alpha7Port)
testhelpers.FuzzRestorer(t, "restorev1beta1Port", restorev1beta1Port)
+ testhelpers.FuzzRestorer(t, "restorev1beta1APIServerLoadBalancer", restorev1beta1APIServerLoadBalancer)
}
diff --git a/api/v1alpha7/openstackcluster_conversion.go b/api/v1alpha7/openstackcluster_conversion.go
index f273d98760..4183ad9a84 100644
--- a/api/v1alpha7/openstackcluster_conversion.go
+++ b/api/v1alpha7/openstackcluster_conversion.go
@@ -239,6 +239,8 @@ func restorev1beta1ClusterSpec(previous *infrav1.OpenStackClusterSpec, dst *infr
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 {
diff --git a/api/v1alpha7/types_conversion.go b/api/v1alpha7/types_conversion.go
index aeb1c756a6..ac09a5d3dc 100644
--- a/api/v1alpha7/types_conversion.go
+++ b/api/v1alpha7/types_conversion.go
@@ -510,6 +510,17 @@ func Convert_v1beta1_OpenStackIdentityReference_To_v1alpha7_OpenStackIdentityRef
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
diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go
index 407c862a75..554345da6c 100644
--- a/api/v1alpha7/zz_generated.conversion.go
+++ b/api/v1alpha7/zz_generated.conversion.go
@@ -507,6 +507,7 @@ func autoConvert_v1beta1_APIServerLoadBalancer_To_v1alpha7_APIServerLoadBalancer
}
// 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
}
diff --git a/api/v1beta1/types.go b/api/v1beta1/types.go
index b141d2731b..b6789489d1 100644
--- a/api/v1beta1/types.go
+++ b/api/v1beta1/types.go
@@ -812,6 +812,7 @@ type APIServerLoadBalancer struct {
// 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.
@@ -819,6 +820,10 @@ type APIServerLoadBalancer struct {
// +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 {
diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go
index c1a66427d4..fe06c1285c 100644
--- a/api/v1beta1/zz_generated.deepcopy.go
+++ b/api/v1beta1/zz_generated.deepcopy.go
@@ -62,6 +62,11 @@ func (in *APIServerLoadBalancer) DeepCopyInto(out *APIServerLoadBalancer) {
(*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.
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 eca9ad728f..10074be068 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -4873,6 +4873,10 @@ spec:
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: |-
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 cebc2b2a04..956f46dc3a 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -2306,6 +2306,10 @@ spec:
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: |-
diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md
index 087efc5310..19dfeb31e3 100644
--- a/docs/book/src/api/v1beta1/api.md
+++ b/docs/book/src/api/v1beta1/api.md
@@ -933,6 +933,18 @@ 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.
+ |
+
AdditionalBlockDevice
diff --git a/pkg/cloud/services/loadbalancer/loadbalancer.go b/pkg/cloud/services/loadbalancer/loadbalancer.go
index cd309221b4..b4dac30d6b 100644
--- a/pkg/cloud/services/loadbalancer/loadbalancer.go
+++ b/pkg/cloud/services/loadbalancer/loadbalancer.go
@@ -306,17 +306,21 @@ func (s *Service) getOrCreateAPILoadBalancer(openStackCluster *infrav1.OpenStack
// Choose the selected provider if it is set in cluster spec, if not, omit the field and Octavia will use the default provider.
lbProvider := ""
- if openStackCluster.Spec.APIServerLoadBalancer != nil && openStackCluster.Spec.APIServerLoadBalancer.Provider != nil {
- for _, v := range providers {
- if v.Name == *openStackCluster.Spec.APIServerLoadBalancer.Provider {
- lbProvider = v.Name
- break
+ var availabilityZone *string
+ if openStackCluster.Spec.APIServerLoadBalancer != nil {
+ if openStackCluster.Spec.APIServerLoadBalancer.Provider != nil {
+ for _, v := range providers {
+ if v.Name == *openStackCluster.Spec.APIServerLoadBalancer.Provider {
+ lbProvider = v.Name
+ break
+ }
+ }
+ if lbProvider == "" {
+ record.Warnf(openStackCluster, "OctaviaProviderNotFound", "Provider specified for Octavia not found.")
+ record.Eventf(openStackCluster, "OctaviaProviderNotFound", "Provider %s specified for Octavia not found, using the default provider.", openStackCluster.Spec.APIServerLoadBalancer.Provider)
}
}
- if lbProvider == "" {
- record.Warnf(openStackCluster, "OctaviaProviderNotFound", "Provider specified for Octavia not found.")
- record.Eventf(openStackCluster, "OctaviaProviderNotFound", "Provider %s specified for Octavia not found, using the default provider.", openStackCluster.Spec.APIServerLoadBalancer.Provider)
- }
+ availabilityZone = openStackCluster.Spec.APIServerLoadBalancer.AvailabilityZone
}
vipAddress, err := getAPIServerVIPAddress(openStackCluster)
@@ -332,6 +336,9 @@ func (s *Service) getOrCreateAPILoadBalancer(openStackCluster *infrav1.OpenStack
Provider: lbProvider,
Tags: openStackCluster.Spec.Tags,
}
+ if availabilityZone != nil {
+ lbCreateOpts.AvailabilityZone = *availabilityZone
+ }
if vipAddress != nil {
lbCreateOpts.VipAddress = *vipAddress
}
From 43d24995c3ddfd0ad8e73b4611faf3119be9dfdc Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Wed, 10 Apr 2024 21:59:36 +0100
Subject: [PATCH 175/180] Cleanup security group created by e2e test
---
test/e2e/shared/openstack.go | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/test/e2e/shared/openstack.go b/test/e2e/shared/openstack.go
index 2fd5f95d56..e7e3ff73d1 100644
--- a/test/e2e/shared/openstack.go
+++ b/test/e2e/shared/openstack.go
@@ -494,10 +494,16 @@ func CreateOpenStackSecurityGroup(e2eCtx *E2EContext, securityGroupName, descrip
Description: description,
}
- _, err = groups.Create(networkClient, createOpts).Extract()
+ group, err := groups.Create(networkClient, createOpts).Extract()
if err != nil {
return err
}
+ // Ensure the group is deleted after the test
+ DeferCleanup(func() error {
+ By(fmt.Sprintf("Deleting test security group %s(%s)", group.Name, group.ID))
+ return groups.Delete(networkClient, group.ID).ExtractErr()
+ })
+
return nil
}
From 4ce032d0498da6c85f1454416a47aa7878421975 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Thu, 11 Apr 2024 10:13:43 +0100
Subject: [PATCH 176/180] Fix idempotent restore when setting
ControlPlaneEndpoint
---
api/v1alpha6/openstackcluster_conversion.go | 12 +++
api/v1alpha7/openstackcluster_conversion.go | 8 +-
.../e2e/suites/apivalidations/filters_test.go | 2 +-
.../apivalidations/openstackcluster_test.go | 78 ++++++++++++++++++-
test/e2e/suites/apivalidations/suite_test.go | 7 +-
5 files changed, 101 insertions(+), 6 deletions(-)
diff --git a/api/v1alpha6/openstackcluster_conversion.go b/api/v1alpha6/openstackcluster_conversion.go
index 16375c2c07..1dd692eeda 100644
--- a/api/v1alpha6/openstackcluster_conversion.go
+++ b/api/v1alpha6/openstackcluster_conversion.go
@@ -72,6 +72,18 @@ var v1alpha6OpenStackClusterRestorer = conversion.RestorerFor[*OpenStackCluster]
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 {
diff --git a/api/v1alpha7/openstackcluster_conversion.go b/api/v1alpha7/openstackcluster_conversion.go
index f273d98760..aaccf098ae 100644
--- a/api/v1alpha7/openstackcluster_conversion.go
+++ b/api/v1alpha7/openstackcluster_conversion.go
@@ -78,12 +78,14 @@ var v1alpha7OpenStackClusterRestorer = conversion.RestorerFor[*OpenStackCluster]
return &c.Spec
},
restorev1alpha7ClusterSpec,
- // Filter out Bastion, which is restored separately
- conversion.HashedFilterField[*OpenStackCluster, OpenStackClusterSpec](
+ // 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 {
+ if s.Bastion != nil || s.ControlPlaneEndpoint != (clusterv1.APIEndpoint{}) {
f := *s
f.Bastion = nil
+ f.ControlPlaneEndpoint = clusterv1.APIEndpoint{}
return &f
}
return s
diff --git a/test/e2e/suites/apivalidations/filters_test.go b/test/e2e/suites/apivalidations/filters_test.go
index 08b8cdfccd..83b13103e0 100644
--- a/test/e2e/suites/apivalidations/filters_test.go
+++ b/test/e2e/suites/apivalidations/filters_test.go
@@ -47,7 +47,7 @@ var _ = Describe("Filter API validations", func() {
// Initialise a basic cluster object in the correct namespace
cluster = &infrav1.OpenStackCluster{}
cluster.Namespace = namespace.Name
- cluster.GenerateName = "cluster-"
+ cluster.GenerateName = clusterNamePrefix
})
DescribeTable("Allow valid neutron filter tags", func(tags []infrav1.FilterByNeutronTags) {
diff --git a/test/e2e/suites/apivalidations/openstackcluster_test.go b/test/e2e/suites/apivalidations/openstackcluster_test.go
index d05a21c732..e58acfcc4b 100644
--- a/test/e2e/suites/apivalidations/openstackcluster_test.go
+++ b/test/e2e/suites/apivalidations/openstackcluster_test.go
@@ -25,6 +25,8 @@ import (
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
"sigs.k8s.io/controller-runtime/pkg/client"
+ infrav1alpha6 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha6"
+ infrav1alpha7 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
)
@@ -52,7 +54,7 @@ var _ = Describe("OpenStackCluster API validations", func() {
// Initialise a basic cluster object in the correct namespace
cluster = &infrav1.OpenStackCluster{}
cluster.Namespace = namespace.Name
- cluster.GenerateName = "cluster-"
+ cluster.GenerateName = clusterNamePrefix
})
It("should allow the smallest permissible cluster spec", func() {
@@ -177,4 +179,78 @@ var _ = Describe("OpenStackCluster API validations", func() {
Expect(create(cluster)).NotTo(Succeed(), "OpenStackCluster creation should not succeed")
})
})
+
+ Context("v1alpha7", func() {
+ var cluster *infrav1alpha7.OpenStackCluster
+
+ BeforeEach(func() {
+ // Initialise a basic cluster object in the correct namespace
+ cluster = &infrav1alpha7.OpenStackCluster{}
+ cluster.Namespace = namespace.Name
+ cluster.GenerateName = clusterNamePrefix
+ })
+
+ It("should restore cluster spec idempotently after controller writes to controlPlaneEndpoint", func() {
+ // Set identityRef.Kind, as it will be lost if the restorer does not execute
+ cluster.Spec.IdentityRef = &infrav1alpha7.OpenStackIdentityReference{
+ Kind: "FakeKind",
+ Name: "identity-ref",
+ }
+ Expect(create(cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
+
+ // Fetch the infrav1 version of the cluster
+ infrav1Cluster := &infrav1.OpenStackCluster{}
+ Expect(k8sClient.Get(ctx, types.NamespacedName{Name: cluster.Name, Namespace: cluster.Namespace}, infrav1Cluster)).To(Succeed(), "OpenStackCluster fetch should succeed")
+
+ // Update the infrav1 cluster to set the control plane endpoint
+ infrav1Cluster.Spec.ControlPlaneEndpoint = &clusterv1.APIEndpoint{
+ Host: "foo",
+ Port: 1234,
+ }
+ Expect(k8sClient.Update(ctx, infrav1Cluster)).To(Succeed(), "Setting control plane endpoint should succeed")
+
+ // Fetch the v1alpha7 version of the cluster and ensure that both the new control plane endpoint and the identityRef.Kind are present
+ cluster = &infrav1alpha7.OpenStackCluster{}
+ Expect(k8sClient.Get(ctx, types.NamespacedName{Name: infrav1Cluster.Name, Namespace: infrav1Cluster.Namespace}, cluster)).To(Succeed(), "OpenStackCluster fetch should succeed")
+ Expect(cluster.Spec.ControlPlaneEndpoint).To(Equal(*infrav1Cluster.Spec.ControlPlaneEndpoint), "Control plane endpoint should be restored")
+ Expect(cluster.Spec.IdentityRef.Kind).To(Equal("FakeKind"), "IdentityRef.Kind should be restored")
+ })
+ })
+
+ Context("v1alpha6", func() {
+ var cluster *infrav1alpha6.OpenStackCluster //nolint:staticcheck
+
+ BeforeEach(func() {
+ // Initialise a basic cluster object in the correct namespace
+ cluster = &infrav1alpha6.OpenStackCluster{} //nolint:staticcheck
+ cluster.Namespace = namespace.Name
+ cluster.GenerateName = clusterNamePrefix
+ })
+
+ It("should restore cluster spec idempotently after controller writes to controlPlaneEndpoint", func() {
+ // Set identityRef.Kind, as it will be lost if the restorer does not execute
+ cluster.Spec.IdentityRef = &infrav1alpha6.OpenStackIdentityReference{
+ Kind: "FakeKind",
+ Name: "identity-ref",
+ }
+ Expect(create(cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
+
+ // Fetch the infrav1 version of the cluster
+ infrav1Cluster := &infrav1.OpenStackCluster{}
+ Expect(k8sClient.Get(ctx, types.NamespacedName{Name: cluster.Name, Namespace: cluster.Namespace}, infrav1Cluster)).To(Succeed(), "OpenStackCluster fetch should succeed")
+
+ // Update the infrav1 cluster to set the control plane endpoint
+ infrav1Cluster.Spec.ControlPlaneEndpoint = &clusterv1.APIEndpoint{
+ Host: "foo",
+ Port: 1234,
+ }
+ Expect(k8sClient.Update(ctx, infrav1Cluster)).To(Succeed(), "Setting control plane endpoint should succeed")
+
+ // Fetch the v1alpha6 version of the cluster and ensure that both the new control plane endpoint and the identityRef.Kind are present
+ cluster = &infrav1alpha6.OpenStackCluster{} //nolint:staticcheck
+ Expect(k8sClient.Get(ctx, types.NamespacedName{Name: infrav1Cluster.Name, Namespace: infrav1Cluster.Namespace}, cluster)).To(Succeed(), "OpenStackCluster fetch should succeed")
+ Expect(cluster.Spec.ControlPlaneEndpoint).To(Equal(*infrav1Cluster.Spec.ControlPlaneEndpoint), "Control plane endpoint should be restored")
+ Expect(cluster.Spec.IdentityRef.Kind).To(Equal("FakeKind"), "IdentityRef.Kind should be restored")
+ })
+ })
})
diff --git a/test/e2e/suites/apivalidations/suite_test.go b/test/e2e/suites/apivalidations/suite_test.go
index b042930e53..beac7d11aa 100644
--- a/test/e2e/suites/apivalidations/suite_test.go
+++ b/test/e2e/suites/apivalidations/suite_test.go
@@ -22,6 +22,7 @@ import (
"path/filepath"
"strconv"
"testing"
+ "time"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
@@ -56,6 +57,10 @@ var (
mgrDone chan struct{}
)
+const (
+ clusterNamePrefix = "cluster-"
+)
+
func TestAPIs(t *testing.T) {
RegisterFailHandler(Fail)
@@ -144,7 +149,7 @@ var _ = BeforeSuite(func() {
DeferCleanup(func() {
By("Tearing down manager")
mgrCancel()
- Eventually(mgrDone).Should(BeClosed(), "Manager should stop")
+ Eventually(mgrDone).WithTimeout(time.Second*5).Should(BeClosed(), "Manager should stop")
})
})
From d04c4d5616201ee8864f8a0f19fd6d286ba594ca Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Thu, 11 Apr 2024 16:52:17 +0100
Subject: [PATCH 177/180] Bump k8s dep to 0.29.3
This deprecates k8s.io/util/pointer, which we replace with
k8s.io/util/ptr to keep the linter happy.
---
api/v1alpha5/conversion.go | 20 ++--
api/v1alpha6/conversion_test.go | 34 +++----
api/v1alpha6/openstackmachine_types.go | 4 +-
api/v1alpha6/types_conversion.go | 14 +--
api/v1alpha7/conversion_test.go | 14 +--
api/v1alpha7/openstackmachine_types.go | 4 +-
api/v1beta1/conversion.go | 18 ++--
api/v1beta1/openstackmachine_types.go | 4 +-
api/v1beta1/types.go | 4 +-
controllers/openstackcluster_controller.go | 8 +-
.../openstackcluster_controller_test.go | 42 ++++----
.../openstackfloatingippool_controller.go | 6 +-
controllers/openstackmachine_controller.go | 8 +-
.../openstackmachine_controller_test.go | 22 ++---
controllers/suite_test.go | 4 +-
go.mod | 34 +++----
go.sum | 98 +++++++++----------
pkg/cloud/services/compute/instance_test.go | 6 +-
.../compute/referenced_resources_test.go | 22 ++---
.../services/compute/servergroup_test.go | 12 +--
.../services/loadbalancer/loadbalancer.go | 6 +-
.../loadbalancer/loadbalancer_test.go | 26 ++---
pkg/cloud/services/networking/floatingip.go | 4 +-
.../services/networking/floatingip_test.go | 4 +-
pkg/cloud/services/networking/network.go | 8 +-
pkg/cloud/services/networking/network_test.go | 24 ++---
pkg/cloud/services/networking/port.go | 24 ++---
pkg/cloud/services/networking/port_test.go | 94 +++++++++---------
.../networking/securitygroups_test.go | 46 ++++-----
pkg/webhooks/openstackcluster_webhook.go | 8 +-
pkg/webhooks/openstackcluster_webhook_test.go | 86 ++++++++--------
.../openstackmachinetemplate_webhook_test.go | 22 ++---
.../e2e/suites/apivalidations/filters_test.go | 50 +++++-----
.../apivalidations/openstackcluster_test.go | 20 ++--
.../apivalidations/openstackmachine_test.go | 8 +-
.../suites/conformance/conformance_test.go | 6 +-
test/e2e/suites/e2e/e2e_test.go | 44 ++++-----
test/e2e/suites/e2e/remediations_test.go | 4 +-
test/helpers/external/cluster.go | 6 +-
test/helpers/fuzzerfuncs.go | 4 +-
40 files changed, 433 insertions(+), 439 deletions(-)
diff --git a/api/v1alpha5/conversion.go b/api/v1alpha5/conversion.go
index 79b282dfeb..b0e0d9eea6 100644
--- a/api/v1alpha5/conversion.go
+++ b/api/v1alpha5/conversion.go
@@ -21,7 +21,7 @@ import (
"strings"
conversion "k8s.io/apimachinery/pkg/conversion"
- "k8s.io/utils/pointer"
+ "k8s.io/utils/ptr"
utilconversion "sigs.k8s.io/cluster-api/util/conversion"
ctrlconversion "sigs.k8s.io/controller-runtime/pkg/conversion"
@@ -301,7 +301,7 @@ func Convert_v1alpha5_OpenStackClusterSpec_To_v1beta1_OpenStackClusterSpec(in *O
}
if in.APIServerPort != 0 {
- out.APIServerPort = pointer.Int(in.APIServerPort)
+ out.APIServerPort = ptr.To(in.APIServerPort)
}
return nil
@@ -333,10 +333,10 @@ func Convert_v1beta1_PortOpts_To_v1alpha5_PortOpts(in *infrav1.PortOpts, out *Po
if in.Profile != nil {
out.Profile = make(map[string]string)
- if pointer.BoolDeref(in.Profile.OVSHWOffload, false) {
+ if ptr.Deref(in.Profile.OVSHWOffload, false) {
(out.Profile)["capabilities"] = "[\"switchdev\"]"
}
- if pointer.BoolDeref(in.Profile.TrustedVF, false) {
+ if ptr.Deref(in.Profile.TrustedVF, false) {
(out.Profile)["trusted"] = trueString
}
}
@@ -435,10 +435,10 @@ func Convert_v1alpha5_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *infrav1.Po
// Profile is now a struct in v1beta1.
if strings.Contains(in.Profile["capabilities"], "switchdev") {
- out.Profile.OVSHWOffload = pointer.Bool(true)
+ out.Profile.OVSHWOffload = ptr.To(true)
}
if in.Profile["trusted"] == trueString {
- out.Profile.TrustedVF = pointer.Bool(true)
+ out.Profile.TrustedVF = ptr.To(true)
}
return nil
}
@@ -608,21 +608,21 @@ func Convert_Map_string_To_Interface_To_v1beta1_BindingProfile(in map[string]str
for k, v := range in {
if k == "capabilities" {
if strings.Contains(v, "switchdev") {
- out.OVSHWOffload = pointer.Bool(true)
+ out.OVSHWOffload = ptr.To(true)
}
}
if k == "trusted" && v == trueString {
- out.TrustedVF = pointer.Bool(true)
+ out.TrustedVF = ptr.To(true)
}
}
return nil
}
func Convert_v1beta1_BindingProfile_To_Map_string_To_Interface(in *infrav1.BindingProfile, out map[string]string, _ conversion.Scope) error {
- if pointer.BoolDeref(in.OVSHWOffload, false) {
+ if ptr.Deref(in.OVSHWOffload, false) {
(out)["capabilities"] = "[\"switchdev\"]"
}
- if pointer.BoolDeref(in.TrustedVF, false) {
+ if ptr.Deref(in.TrustedVF, false) {
(out)["trusted"] = trueString
}
return nil
diff --git a/api/v1alpha6/conversion_test.go b/api/v1alpha6/conversion_test.go
index 67a394d801..d5f500e0b1 100644
--- a/api/v1alpha6/conversion_test.go
+++ b/api/v1alpha6/conversion_test.go
@@ -27,7 +27,7 @@ import (
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"
@@ -221,7 +221,7 @@ func TestNetworksToPorts(t *testing.T) {
Ports: []infrav1.PortOpts{
{
Network: &infrav1.NetworkParam{
- ID: pointer.String(networkuuid),
+ ID: ptr.To(networkuuid),
},
},
},
@@ -282,12 +282,12 @@ func TestNetworksToPorts(t *testing.T) {
Ports: []infrav1.PortOpts{
{
Network: &infrav1.NetworkParam{
- ID: pointer.String(networkuuid),
+ ID: ptr.To(networkuuid),
},
FixedIPs: []infrav1.FixedIP{
{
Subnet: &infrav1.SubnetParam{
- ID: pointer.String(subnetuuid),
+ ID: ptr.To(subnetuuid),
},
},
},
@@ -326,7 +326,7 @@ func TestNetworksToPorts(t *testing.T) {
Ports: []infrav1.PortOpts{
{
Network: &infrav1.NetworkParam{
- ID: pointer.String(networkuuid),
+ ID: ptr.To(networkuuid),
},
FixedIPs: []infrav1.FixedIP{
{
@@ -388,19 +388,19 @@ func TestNetworksToPorts(t *testing.T) {
Ports: []infrav1.PortOpts{
{
Network: &infrav1.NetworkParam{
- ID: pointer.String(networkuuid),
+ ID: ptr.To(networkuuid),
},
FixedIPs: []infrav1.FixedIP{
{
Subnet: &infrav1.SubnetParam{
- ID: pointer.String(subnetuuid),
+ ID: ptr.To(subnetuuid),
},
},
},
},
{
Network: &infrav1.NetworkParam{
- ID: pointer.String(networkuuid),
+ ID: ptr.To(networkuuid),
},
FixedIPs: []infrav1.FixedIP{
{
@@ -465,7 +465,7 @@ func TestPortOptsConvertTo(t *testing.T) {
}
securityGroupFilterMerged := []infrav1.SecurityGroupParam{
{Filter: &infrav1.SecurityGroupFilter{Name: "one"}},
- {ID: pointer.String("654cba")},
+ {ID: ptr.To("654cba")},
{ID: &uuids[0]},
{ID: &uuids[1]},
}
@@ -474,8 +474,8 @@ func TestPortOptsConvertTo(t *testing.T) {
"trusted": "true",
}
convertedPortProfile := infrav1.BindingProfile{
- OVSHWOffload: pointer.Bool(true),
- TrustedVF: pointer.Bool(true),
+ OVSHWOffload: ptr.To(true),
+ TrustedVF: ptr.To(true),
}
tests := []struct {
@@ -597,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.Status.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,
diff --git a/api/v1alpha6/openstackmachine_types.go b/api/v1alpha6/openstackmachine_types.go
index 9048c181ca..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"
)
@@ -184,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/types_conversion.go b/api/v1alpha6/types_conversion.go
index b855b9e473..ce7d2030c9 100644
--- a/api/v1alpha6/types_conversion.go
+++ b/api/v1alpha6/types_conversion.go
@@ -21,7 +21,7 @@ import (
"strings"
apiconversion "k8s.io/apimachinery/pkg/conversion"
- "k8s.io/utils/pointer"
+ "k8s.io/utils/ptr"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
optional "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/optional"
@@ -387,10 +387,10 @@ func Convert_v1beta1_PortOpts_To_v1alpha6_PortOpts(in *infrav1.PortOpts, out *Po
if in.Profile != nil {
out.Profile = make(map[string]string)
- if pointer.BoolDeref(in.Profile.OVSHWOffload, false) {
+ if ptr.Deref(in.Profile.OVSHWOffload, false) {
(out.Profile)["capabilities"] = "[\"switchdev\"]"
}
- if pointer.BoolDeref(in.Profile.TrustedVF, false) {
+ if ptr.Deref(in.Profile.TrustedVF, false) {
(out.Profile)["trusted"] = trueString
}
}
@@ -402,21 +402,21 @@ func Convert_Map_string_To_Interface_To_v1beta1_BindingProfile(in map[string]str
for k, v := range in {
if k == "capabilities" {
if strings.Contains(v, "switchdev") {
- out.OVSHWOffload = pointer.Bool(true)
+ out.OVSHWOffload = ptr.To(true)
}
}
if k == "trusted" && v == trueString {
- out.TrustedVF = pointer.Bool(true)
+ 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 pointer.BoolDeref(in.OVSHWOffload, false) {
+ if ptr.Deref(in.OVSHWOffload, false) {
(out)["capabilities"] = "[\"switchdev\"]"
}
- if pointer.BoolDeref(in.TrustedVF, false) {
+ if ptr.Deref(in.TrustedVF, false) {
(out)["trusted"] = trueString
}
return nil
diff --git a/api/v1alpha7/conversion_test.go b/api/v1alpha7/conversion_test.go
index d44eabf604..cf3606ce5b 100644
--- a/api/v1alpha7/conversion_test.go
+++ b/api/v1alpha7/conversion_test.go
@@ -27,7 +27,7 @@ import (
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"
@@ -201,31 +201,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(g gomega.Gomega, 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")))
},
expectIdentityRefDiff: false,
},
{
name: "Set InstanceID",
modifyUp: func(up *infrav1.OpenStackMachine) {
- up.Status.InstanceID = pointer.String("new-instance-id")
+ up.Status.InstanceID = ptr.To("new-instance-id")
},
testAfter: func(g gomega.Gomega, 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")))
},
expectIdentityRefDiff: 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(g gomega.Gomega, 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"))
},
expectIdentityRefDiff: true,
diff --git a/api/v1alpha7/openstackmachine_types.go b/api/v1alpha7/openstackmachine_types.go
index 1cc5378573..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"
)
@@ -179,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/v1beta1/conversion.go b/api/v1beta1/conversion.go
index 250483a0f0..d442dc0f1d 100644
--- a/api/v1beta1/conversion.go
+++ b/api/v1beta1/conversion.go
@@ -19,7 +19,7 @@ package v1beta1
import (
"strings"
- "k8s.io/utils/pointer"
+ "k8s.io/utils/ptr"
)
// Hub marks OpenStackCluster as a conversion hub.
@@ -53,20 +53,20 @@ func LegacyCalicoSecurityGroupRules() []SecurityGroupRuleSpec {
return []SecurityGroupRuleSpec{
{
Name: "BGP (calico)",
- Description: pointer.String("Created by cluster-api-provider-openstack API conversion - BGP (calico)"),
+ Description: ptr.To("Created by cluster-api-provider-openstack API conversion - BGP (calico)"),
Direction: "ingress",
- EtherType: pointer.String("IPv4"),
- PortRangeMin: pointer.Int(179),
- PortRangeMax: pointer.Int(179),
- Protocol: pointer.String("tcp"),
+ 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: pointer.String("Created by cluster-api-provider-openstack API conversion - IP-in-IP (calico)"),
+ Description: ptr.To("Created by cluster-api-provider-openstack API conversion - IP-in-IP (calico)"),
Direction: "ingress",
- EtherType: pointer.String("IPv4"),
- Protocol: pointer.String("4"),
+ EtherType: ptr.To("IPv4"),
+ Protocol: ptr.To("4"),
RemoteManagedGroups: []ManagedSecurityGroupName{"controlplane", "worker"},
},
}
diff --git a/api/v1beta1/openstackmachine_types.go b/api/v1beta1/openstackmachine_types.go
index 2dc57b4312..4a6e798426 100644
--- a/api/v1beta1/openstackmachine_types.go
+++ b/api/v1beta1/openstackmachine_types.go
@@ -19,7 +19,7 @@ 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"
@@ -206,7 +206,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/v1beta1/types.go b/api/v1beta1/types.go
index b141d2731b..46dba26406 100644
--- a/api/v1beta1/types.go
+++ b/api/v1beta1/types.go
@@ -17,7 +17,7 @@ limitations under the License.
package v1beta1
import (
- "k8s.io/utils/pointer"
+ "k8s.io/utils/ptr"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/optional"
)
@@ -822,7 +822,7 @@ type APIServerLoadBalancer struct {
}
func (s *APIServerLoadBalancer) IsZero() bool {
- return s == nil || ((s.Enabled == nil || !*s.Enabled) && len(s.AdditionalPorts) == 0 && len(s.AllowedCIDRs) == 0 && pointer.StringDeref(s.Provider, "") == "")
+ 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 {
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index 58ab0d00d4..7ba565cb90 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -29,7 +29,7 @@ import (
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"
@@ -382,7 +382,7 @@ func reconcileNormal(scope *scope.WithLogger, cluster *clusterv1.Cluster, openSt
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 := !pointer.BoolDeref(openStackCluster.Spec.ControlPlaneOmitAvailabilityZone, false)
+ 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)
@@ -838,7 +838,7 @@ func reconcileControlPlaneEndpoint(scope *scope.WithLogger, networkingService *n
// 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 !pointer.BoolDeref(openStackCluster.Spec.DisableAPIServerFloatingIP, false):
+ 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))
@@ -916,7 +916,7 @@ 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.
diff --git a/controllers/openstackcluster_controller_test.go b/controllers/openstackcluster_controller_test.go
index 62a7f6fcfa..21dc0dbe3d 100644
--- a/controllers/openstackcluster_controller_test.go
+++ b/controllers/openstackcluster_controller_test.go
@@ -34,7 +34,7 @@ import (
. "github.com/onsi/gomega"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
- "k8s.io/utils/pointer"
+ "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"
@@ -64,7 +64,7 @@ var _ = Describe("OpenStackCluster controller", func() {
bastionSpec := infrav1.OpenStackMachineSpec{
Image: infrav1.ImageParam{
Filter: &infrav1.ImageFilter{
- Name: pointer.String("fake-name"),
+ Name: ptr.To("fake-name"),
},
},
}
@@ -199,7 +199,7 @@ var _ = Describe("OpenStackCluster controller", func() {
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: pointer.Bool(false)},
+ Bastion: &infrav1.Bastion{Enabled: ptr.To(false)},
}
err := k8sClient.Create(ctx, testCluster)
Expect(err).To(BeNil())
@@ -231,7 +231,7 @@ var _ = Describe("OpenStackCluster controller", func() {
testCluster.SetName("adopt-existing-bastion")
testCluster.Spec = infrav1.OpenStackClusterSpec{
Bastion: &infrav1.Bastion{
- Enabled: pointer.Bool(true),
+ Enabled: ptr.To(true),
Spec: &bastionSpec,
},
}
@@ -314,7 +314,7 @@ var _ = Describe("OpenStackCluster controller", func() {
testCluster.SetName("requeue-bastion")
testCluster.Spec = infrav1.OpenStackClusterSpec{
Bastion: &infrav1.Bastion{
- Enabled: pointer.Bool(true),
+ Enabled: ptr.To(true),
Spec: &bastionSpec,
},
}
@@ -396,7 +396,7 @@ var _ = Describe("OpenStackCluster controller", func() {
testCluster.SetName("requeue-bastion")
testCluster.Spec = infrav1.OpenStackClusterSpec{
Bastion: &infrav1.Bastion{
- Enabled: pointer.Bool(true),
+ Enabled: ptr.To(true),
Spec: &bastionSpec,
},
}
@@ -517,16 +517,16 @@ var _ = Describe("OpenStackCluster controller", func() {
testCluster.SetName("subnet-filtering")
testCluster.Spec = infrav1.OpenStackClusterSpec{
Bastion: &infrav1.Bastion{
- Enabled: pointer.Bool(true),
+ Enabled: ptr.To(true),
Spec: &bastionSpec,
},
- DisableAPIServerFloatingIP: pointer.Bool(true),
- APIServerFixedIP: pointer.String("10.0.0.1"),
+ DisableAPIServerFloatingIP: ptr.To(true),
+ APIServerFixedIP: ptr.To("10.0.0.1"),
ExternalNetwork: &infrav1.NetworkParam{
- ID: pointer.String(externalNetworkID),
+ ID: ptr.To(externalNetworkID),
},
Network: &infrav1.NetworkParam{
- ID: pointer.String(clusterNetworkID),
+ ID: ptr.To(clusterNetworkID),
},
}
testCluster.Status = infrav1.OpenStackClusterStatus{
@@ -587,16 +587,16 @@ var _ = Describe("OpenStackCluster controller", func() {
testCluster.SetName("subnet-filtering")
testCluster.Spec = infrav1.OpenStackClusterSpec{
Bastion: &infrav1.Bastion{
- Enabled: pointer.Bool(true),
+ Enabled: ptr.To(true),
Spec: &bastionSpec,
},
- DisableAPIServerFloatingIP: pointer.Bool(true),
- APIServerFixedIP: pointer.String("10.0.0.1"),
+ DisableAPIServerFloatingIP: ptr.To(true),
+ APIServerFixedIP: ptr.To("10.0.0.1"),
ExternalNetwork: &infrav1.NetworkParam{
- ID: pointer.String(externalNetworkID),
+ ID: ptr.To(externalNetworkID),
},
Network: &infrav1.NetworkParam{
- ID: pointer.String(clusterNetworkID),
+ ID: ptr.To(clusterNetworkID),
},
Subnets: []infrav1.SubnetParam{
{ID: &clusterSubnets[0]},
@@ -663,11 +663,11 @@ var _ = Describe("OpenStackCluster controller", func() {
testCluster.SetName("subnet-filtering")
testCluster.Spec = infrav1.OpenStackClusterSpec{
- DisableAPIServerFloatingIP: pointer.Bool(true),
- APIServerFixedIP: pointer.String("10.0.0.1"),
- DisableExternalNetwork: pointer.Bool(true),
+ DisableAPIServerFloatingIP: ptr.To(true),
+ APIServerFixedIP: ptr.To("10.0.0.1"),
+ DisableExternalNetwork: ptr.To(true),
Subnets: []infrav1.SubnetParam{
- {ID: pointer.String(clusterSubnetID)},
+ {ID: ptr.To(clusterSubnetID)},
},
}
err := k8sClient.Create(ctx, testCluster)
@@ -758,7 +758,7 @@ func Test_getAPIServerPort(t *testing.T) {
name: "with API server port",
openStackCluster: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
- APIServerPort: pointer.Int(6445),
+ APIServerPort: ptr.To(6445),
},
},
want: 6445,
diff --git a/controllers/openstackfloatingippool_controller.go b/controllers/openstackfloatingippool_controller.go
index 209c9338b9..b739fb25e7 100644
--- a/controllers/openstackfloatingippool_controller.go
+++ b/controllers/openstackfloatingippool_controller.go
@@ -28,7 +28,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/tools/record"
- "k8s.io/utils/pointer"
+ "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"
@@ -168,7 +168,7 @@ func (r *OpenStackFloatingIPPoolReconciler) Reconcile(ctx context.Context, req c
Name: claim.Name,
},
PoolRef: corev1.TypedLocalObjectReference{
- APIGroup: pointer.String(infrav1alpha1.GroupVersion.Group),
+ APIGroup: ptr.To(infrav1alpha1.GroupVersion.Group),
Kind: pool.Kind,
Name: pool.Name,
},
@@ -352,7 +352,7 @@ func (r *OpenStackFloatingIPPoolReconciler) getIP(ctx context.Context, scope *sc
}
pool.Status.FailedIPs = append(pool.Status.FailedIPs, ip)
}
- maxIPs := pointer.IntDeref(pool.Spec.MaxIPs, -1)
+ 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)
diff --git a/controllers/openstackmachine_controller.go b/controllers/openstackmachine_controller.go
index 12eb53d465..a1869e3b51 100644
--- a/controllers/openstackmachine_controller.go
+++ b/controllers/openstackmachine_controller.go
@@ -30,7 +30,7 @@ import (
"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"
@@ -619,7 +619,7 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope
}
state := instanceStatus.State()
- openStackMachine.Status.InstanceID = pointer.String(instanceStatus.ID())
+ openStackMachine.Status.InstanceID = ptr.To(instanceStatus.ID())
openStackMachine.Status.InstanceState = &state
instanceNS, err := instanceStatus.NetworkStatus()
@@ -652,7 +652,7 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope
conditions.MarkTrue(openStackMachine, infrav1.InstanceReadyCondition)
// Set properties required by CAPI machine controller
- openStackMachine.Spec.ProviderID = pointer.String(fmt.Sprintf("openstack:///%s", instanceStatus.ID()))
+ 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,
@@ -715,7 +715,7 @@ func (r *OpenStackMachineReconciler) reconcileAPIServerLoadBalancer(scope *scope
conditions.MarkFalse(openStackMachine, infrav1.APIServerIngressReadyCondition, infrav1.LoadBalancerMemberErrorReason, clusterv1.ConditionSeverityError, "Reconciling load balancer member failed: %v", err)
return fmt.Errorf("reconcile load balancer member: %w", err)
}
- } else if !pointer.BoolDeref(openStackCluster.Spec.DisableAPIServerFloatingIP, false) {
+ } else if !ptr.Deref(openStackCluster.Spec.DisableAPIServerFloatingIP, false) {
var floatingIPAddress *string
switch {
case openStackCluster.Spec.ControlPlaneEndpoint != nil && openStackCluster.Spec.ControlPlaneEndpoint.IsValid():
diff --git a/controllers/openstackmachine_controller_test.go b/controllers/openstackmachine_controller_test.go
index c77220bc4c..6197dca779 100644
--- a/controllers/openstackmachine_controller_test.go
+++ b/controllers/openstackmachine_controller_test.go
@@ -33,7 +33,7 @@ import (
"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/v1beta1"
@@ -80,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),
},
}
}
@@ -97,15 +97,15 @@ func getDefaultOpenStackMachine() *infrav1.OpenStackMachine {
// FloatingIP is only used by the cluster controller for the Bastion
// TODO: Test Networks, Ports, Subnet, and Trunk separately
Flavor: flavorName,
- Image: infrav1.ImageParam{ID: pointer.String(imageUUID)},
+ Image: infrav1.ImageParam{ID: ptr.To(imageUUID)},
SSHKeyName: sshKeyName,
Tags: []string{"test-tag"},
ServerMetadata: []infrav1.ServerMetadata{
{Key: "test-metadata", Value: "test-value"},
},
- ConfigDrive: pointer.Bool(true),
+ ConfigDrive: ptr.To(true),
SecurityGroups: []infrav1.SecurityGroupParam{},
- ServerGroup: &infrav1.ServerGroupParam{ID: pointer.String(serverGroupUUID)},
+ ServerGroup: &infrav1.ServerGroupParam{ID: ptr.To(serverGroupUUID)},
},
Status: infrav1.OpenStackMachineStatus{
Resolved: &infrav1.ResolvedMachineSpec{
@@ -126,8 +126,8 @@ func getDefaultInstanceSpec() *compute.InstanceSpec {
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"},
}
@@ -243,7 +243,7 @@ func Test_reconcileDelete(t *testing.T) {
defaultImage := infrav1.ImageParam{
Filter: &infrav1.ImageFilter{
- Name: pointer.String(imageName),
+ Name: ptr.To(imageName),
},
}
@@ -344,7 +344,7 @@ func Test_reconcileDelete(t *testing.T) {
Image: defaultImage,
},
Status: infrav1.OpenStackMachineStatus{
- InstanceID: pointer.String(instanceUUID),
+ InstanceID: ptr.To(instanceUUID),
Resolved: &infrav1.ResolvedMachineSpec{
ImageID: imageUUID,
Ports: defaultResolvedPorts,
@@ -370,7 +370,7 @@ func Test_reconcileDelete(t *testing.T) {
},
},
Status: infrav1.OpenStackMachineStatus{
- InstanceID: pointer.String(instanceUUID),
+ InstanceID: ptr.To(instanceUUID),
Resolved: &infrav1.ResolvedMachineSpec{
ImageID: imageUUID,
Ports: defaultResolvedPorts,
@@ -426,7 +426,7 @@ func Test_reconcileDelete(t *testing.T) {
// Unlike resolved and resources,
// instanceID will have been converted
// from the previous API version.
- InstanceID: pointer.String(instanceUUID),
+ InstanceID: ptr.To(instanceUUID),
},
},
expect: func(r *recorders) {
diff --git a/controllers/suite_test.go b/controllers/suite_test.go
index 81727efa24..d4497275b7 100644
--- a/controllers/suite_test.go
+++ b/controllers/suite_test.go
@@ -31,7 +31,7 @@ import (
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/rest"
- "k8s.io/utils/pointer"
+ "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"
@@ -150,7 +150,7 @@ var _ = Describe("When calling getOrCreate", func() {
machine := &clusterv1.Machine{}
openStackMachine := &infrav1.OpenStackMachine{
Status: infrav1.OpenStackMachineStatus{
- InstanceID: pointer.String("machine-uuid"),
+ InstanceID: ptr.To("machine-uuid"),
},
}
diff --git a/go.mod b/go.mod
index c2bfc1a442..917ee16d17 100644
--- a/go.mod
+++ b/go.mod
@@ -19,14 +19,14 @@ require (
golang.org/x/crypto v0.16.0
golang.org/x/text v0.14.0
gopkg.in/ini.v1 v1.67.0
- k8s.io/api v0.28.4
- k8s.io/apiextensions-apiserver v0.28.4
- k8s.io/apimachinery v0.28.4
- k8s.io/client-go v0.28.4
- k8s.io/component-base v0.28.4
- k8s.io/klog/v2 v2.100.1
+ k8s.io/api v0.29.3
+ k8s.io/apiextensions-apiserver v0.29.3
+ k8s.io/apimachinery v0.29.3
+ k8s.io/client-go v0.29.3
+ k8s.io/component-base v0.29.3
+ k8s.io/klog/v2 v2.110.1
k8s.io/kubernetes v1.28.3
- k8s.io/utils v0.0.0-20230406110748-d93618cff8a2
+ k8s.io/utils v0.0.0-20230726121419-3b25d923346b
sigs.k8s.io/cluster-api v1.6.0
sigs.k8s.io/cluster-api/test v1.6.0
sigs.k8s.io/controller-runtime v0.16.3
@@ -64,7 +64,7 @@ require (
github.com/evanphx/json-patch v5.6.0+incompatible // indirect
github.com/evanphx/json-patch/v5 v5.7.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
- github.com/fsnotify/fsnotify v1.6.0 // indirect
+ github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-logr/zapr v1.2.4 // indirect
github.com/go-openapi/jsonpointer v0.19.6 // indirect
@@ -74,8 +74,8 @@ require (
github.com/gobuffalo/flect v1.0.2 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
- github.com/golang/protobuf v1.5.3 // indirect
- github.com/google/cel-go v0.16.1 // indirect
+ github.com/golang/protobuf v1.5.4 // indirect
+ github.com/google/cel-go v0.17.7 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/go-github/v53 v53.2.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
@@ -149,17 +149,17 @@ require (
google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 // indirect
google.golang.org/grpc v1.59.0 // indirect
- google.golang.org/protobuf v1.31.0 // indirect
+ google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
- k8s.io/apiserver v0.28.4 // indirect
- k8s.io/cluster-bootstrap v0.28.4 // indirect
- k8s.io/kms v0.28.4 // indirect
- k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect
- sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.1.2 // indirect
+ k8s.io/apiserver v0.29.3 // indirect
+ k8s.io/cluster-bootstrap v0.29.3 // indirect
+ k8s.io/kms v0.29.3 // indirect
+ k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect
+ sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.28.0 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/kind v0.20.0 // indirect
- sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
+ sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
)
diff --git a/go.sum b/go.sum
index 3da2fa64fd..ef8fbd603c 100644
--- a/go.sum
+++ b/go.sum
@@ -142,12 +142,11 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
-github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
-github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
+github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
+github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
-github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=
@@ -202,15 +201,14 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
-github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
-github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
-github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
+github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
-github.com/google/cel-go v0.16.1 h1:3hZfSNiAU3KOiNtxuFXVp5WFy4hf/Ly3Sa4/7F8SXNo=
-github.com/google/cel-go v0.16.1/go.mod h1:HXZKzB0LXqer5lHHgfWAnlYwJaQBDKMjxjulNQzhwhY=
+github.com/google/cel-go v0.17.7 h1:6ebJFzu1xO2n7TLtN+UBqShGBhlD85bhvglh5DpcfqQ=
+github.com/google/cel-go v0.17.7/go.mod h1:HXZKzB0LXqer5lHHgfWAnlYwJaQBDKMjxjulNQzhwhY=
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@@ -222,7 +220,6 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
@@ -263,8 +260,8 @@ github.com/gophercloud/gophercloud v1.7.0 h1:fyJGKh0LBvIZKLvBWvQdIgkaV5yTM3Jh9EY
github.com/gophercloud/gophercloud v1.7.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM=
github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56 h1:sH7xkTfYzxIEgzq1tDHIMKRh1vThOEOGNsettdEeLbE=
github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56/go.mod h1:VSalo4adEk+3sNkmVJLnhHoOyOYYS8sTWLG4mv5BKto=
-github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
-github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
+github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw=
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=
@@ -431,22 +428,22 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
-go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ=
-go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
+go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA=
+go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
go.etcd.io/etcd/api/v3 v3.5.10 h1:szRajuUUbLyppkhs9K6BRtjY37l66XQQmw7oZRANE4k=
go.etcd.io/etcd/api/v3 v3.5.10/go.mod h1:TidfmT4Uycad3NM/o25fG3J07odo4GBB9hoxaodFCtI=
go.etcd.io/etcd/client/pkg/v3 v3.5.10 h1:kfYIdQftBnbAq8pUWFXfpuuxFSKzlmM5cSn76JByiT0=
go.etcd.io/etcd/client/pkg/v3 v3.5.10/go.mod h1:DYivfIviIuQ8+/lCq4vcxuseg2P2XbHygkKwFo9fc8U=
-go.etcd.io/etcd/client/v2 v2.305.9 h1:YZ2OLi0OvR0H75AcgSUajjd5uqKDKocQUqROTG11jIo=
-go.etcd.io/etcd/client/v2 v2.305.9/go.mod h1:0NBdNx9wbxtEQLwAQtrDHwx58m02vXpDcgSYI2seohQ=
+go.etcd.io/etcd/client/v2 v2.305.10 h1:MrmRktzv/XF8CvtQt+P6wLUlURaNpSDJHFZhe//2QE4=
+go.etcd.io/etcd/client/v2 v2.305.10/go.mod h1:m3CKZi69HzilhVqtPDcjhSGp+kA1OmbNn0qamH80xjA=
go.etcd.io/etcd/client/v3 v3.5.10 h1:W9TXNZ+oB3MCd/8UjxHTWK5J9Nquw9fQBLJd5ne5/Ao=
go.etcd.io/etcd/client/v3 v3.5.10/go.mod h1:RVeBnDz2PUEZqTpgqwAtUd8nAPf5kjyFyND7P1VkOKc=
-go.etcd.io/etcd/pkg/v3 v3.5.9 h1:6R2jg/aWd/zB9+9JxmijDKStGJAPFsX3e6BeJkMi6eQ=
-go.etcd.io/etcd/pkg/v3 v3.5.9/go.mod h1:BZl0SAShQFk0IpLWR78T/+pyt8AruMHhTNNX73hkNVY=
-go.etcd.io/etcd/raft/v3 v3.5.9 h1:ZZ1GIHoUlHsn0QVqiRysAm3/81Xx7+i2d7nSdWxlOiI=
-go.etcd.io/etcd/raft/v3 v3.5.9/go.mod h1:WnFkqzFdZua4LVlVXQEGhmooLeyS7mqzS4Pf4BCVqXg=
-go.etcd.io/etcd/server/v3 v3.5.9 h1:vomEmmxeztLtS5OEH7d0hBAg4cjVIu9wXuNzUZx2ZA0=
-go.etcd.io/etcd/server/v3 v3.5.9/go.mod h1:GgI1fQClQCFIzuVjlvdbMxNbnISt90gdfYyqiAIt65g=
+go.etcd.io/etcd/pkg/v3 v3.5.10 h1:WPR8K0e9kWl1gAhB5A7gEa5ZBTNkT9NdNWrR8Qpo1CM=
+go.etcd.io/etcd/pkg/v3 v3.5.10/go.mod h1:TKTuCKKcF1zxmfKWDkfz5qqYaE3JncKKZPFf8c1nFUs=
+go.etcd.io/etcd/raft/v3 v3.5.10 h1:cgNAYe7xrsrn/5kXMSaH8kM/Ky8mAdMqGOxyYwpP0LA=
+go.etcd.io/etcd/raft/v3 v3.5.10/go.mod h1:odD6kr8XQXTy9oQnyMPBOr0TVe+gT0neQhElQ6jbGRc=
+go.etcd.io/etcd/server/v3 v3.5.10 h1:4NOGyOwD5sUZ22PiWYKmfxqoeh72z6EhYjNosKGLmZg=
+go.etcd.io/etcd/server/v3 v3.5.10/go.mod h1:gBplPHfs6YI0L+RpGkTQO7buDbHv5HJGG/Bst0/zIPo=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
@@ -637,7 +634,6 @@ golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
@@ -820,10 +816,8 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
-google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
-google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
-google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
+google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -853,35 +847,35 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
-k8s.io/api v0.28.4 h1:8ZBrLjwosLl/NYgv1P7EQLqoO8MGQApnbgH8tu3BMzY=
-k8s.io/api v0.28.4/go.mod h1:axWTGrY88s/5YE+JSt4uUi6NMM+gur1en2REMR7IRj0=
-k8s.io/apiextensions-apiserver v0.28.4 h1:AZpKY/7wQ8n+ZYDtNHbAJBb+N4AXXJvyZx6ww6yAJvU=
-k8s.io/apiextensions-apiserver v0.28.4/go.mod h1:pgQIZ1U8eJSMQcENew/0ShUTlePcSGFq6dxSxf2mwPM=
-k8s.io/apimachinery v0.28.4 h1:zOSJe1mc+GxuMnFzD4Z/U1wst50X28ZNsn5bhgIIao8=
-k8s.io/apimachinery v0.28.4/go.mod h1:wI37ncBvfAoswfq626yPTe6Bz1c22L7uaJ8dho83mgg=
-k8s.io/apiserver v0.28.4 h1:BJXlaQbAU/RXYX2lRz+E1oPe3G3TKlozMMCZWu5GMgg=
-k8s.io/apiserver v0.28.4/go.mod h1:Idq71oXugKZoVGUUL2wgBCTHbUR+FYTWa4rq9j4n23w=
-k8s.io/client-go v0.28.4 h1:Np5ocjlZcTrkyRJ3+T3PkXDpe4UpatQxj85+xjaD2wY=
-k8s.io/client-go v0.28.4/go.mod h1:0VDZFpgoZfelyP5Wqu0/r/TRYcLYuJ2U1KEeoaPa1N4=
-k8s.io/cluster-bootstrap v0.28.4 h1:4MKNy1Qd9QY7pl47rSMGIORF+tm3CUaqC1M8U9bjn4Q=
-k8s.io/cluster-bootstrap v0.28.4/go.mod h1:/c4ro/R4yf4EtJgFgFtvnHkbDOHwubeKJXh5R1c89Bc=
-k8s.io/component-base v0.28.4 h1:c/iQLWPdUgI90O+T9TeECg8o7N3YJTiuz2sKxILYcYo=
-k8s.io/component-base v0.28.4/go.mod h1:m9hR0uvqXDybiGL2nf/3Lf0MerAfQXzkfWhUY58JUbU=
-k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg=
-k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
-k8s.io/kms v0.28.4 h1:PMgY/3CQTWP9eIKmNQiTgjLIZ0ns6O+voagzD2/4mSg=
-k8s.io/kms v0.28.4/go.mod h1:HL4/lR/bhjAJPbqycKtfhWiKh1Sp21cpHOL8P4oo87w=
-k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 h1:LyMgNKD2P8Wn1iAwQU5OhxCKlKJy0sHc+PcDwFB24dQ=
-k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9/go.mod h1:wZK2AVp1uHCp4VamDVgBP2COHZjqD1T68Rf0CM3YjSM=
+k8s.io/api v0.29.3 h1:2ORfZ7+bGC3YJqGpV0KSDDEVf8hdGQ6A03/50vj8pmw=
+k8s.io/api v0.29.3/go.mod h1:y2yg2NTyHUUkIoTC+phinTnEa3KFM6RZ3szxt014a80=
+k8s.io/apiextensions-apiserver v0.29.3 h1:9HF+EtZaVpFjStakF4yVufnXGPRppWFEQ87qnO91YeI=
+k8s.io/apiextensions-apiserver v0.29.3/go.mod h1:po0XiY5scnpJfFizNGo6puNU6Fq6D70UJY2Cb2KwAVc=
+k8s.io/apimachinery v0.29.3 h1:2tbx+5L7RNvqJjn7RIuIKu9XTsIZ9Z5wX2G22XAa5EU=
+k8s.io/apimachinery v0.29.3/go.mod h1:hx/S4V2PNW4OMg3WizRrHutyB5la0iCUbZym+W0EQIU=
+k8s.io/apiserver v0.29.3 h1:xR7ELlJ/BZSr2n4CnD3lfA4gzFivh0wwfNfz9L0WZcE=
+k8s.io/apiserver v0.29.3/go.mod h1:hrvXlwfRulbMbBgmWRQlFru2b/JySDpmzvQwwk4GUOs=
+k8s.io/client-go v0.29.3 h1:R/zaZbEAxqComZ9FHeQwOh3Y1ZUs7FaHKZdQtIc2WZg=
+k8s.io/client-go v0.29.3/go.mod h1:tkDisCvgPfiRpxGnOORfkljmS+UrW+WtXAy2fTvXJB0=
+k8s.io/cluster-bootstrap v0.29.3 h1:DIMDZSN8gbFMy9CS2mAS2Iqq/fIUG783WN/1lqi5TF8=
+k8s.io/cluster-bootstrap v0.29.3/go.mod h1:aPAg1VtXx3uRrx5qU2jTzR7p1rf18zLXWS+pGhiqPto=
+k8s.io/component-base v0.29.3 h1:Oq9/nddUxlnrCuuR2K/jp6aflVvc0uDvxMzAWxnGzAo=
+k8s.io/component-base v0.29.3/go.mod h1:Yuj33XXjuOk2BAaHsIGHhCKZQAgYKhqIxIjIr2UXYio=
+k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0=
+k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo=
+k8s.io/kms v0.29.3 h1:ReljsAUhYlm2spdT4yXmY+9a8x8dc/OT4mXvwQPPteQ=
+k8s.io/kms v0.29.3/go.mod h1:TBGbJKpRUMk59neTMDMddjIDL+D4HuFUbpuiuzmOPg0=
+k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780=
+k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA=
k8s.io/kubernetes v1.28.3 h1:XTci6gzk+JR51UZuZQCFJ4CsyUkfivSjLI4O1P9z6LY=
k8s.io/kubernetes v1.28.3/go.mod h1:NhAysZWvHtNcJFFHic87ofxQN7loylCQwg3ZvXVDbag=
-k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 h1:qY1Ad8PODbnymg2pRbkyMT/ylpTrCM8P2RJ0yroCyIk=
-k8s.io/utils v0.0.0-20230406110748-d93618cff8a2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
+k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI=
+k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
-sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.1.2 h1:trsWhjU5jZrx6UvFu4WzQDrN7Pga4a7Qg+zcfcj64PA=
-sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.1.2/go.mod h1:+qG7ISXqCDVVcyO8hLn12AKVYYUjM7ftlqsqmrhMZE0=
+sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.28.0 h1:TgtAeesdhpm2SGwkQasmbeqDo8th5wOBA5h/AjTKA4I=
+sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.28.0/go.mod h1:VHVDI/KrK4fjnV61bE2g3sA7tiETLn8sooImelsCx3Y=
sigs.k8s.io/cluster-api v1.6.0 h1:2bhVSnUbtWI8taCjd9lGiHExsRUpKf7Z1fXqi/IwYx4=
sigs.k8s.io/cluster-api v1.6.0/go.mod h1:LB7u/WxiWj4/bbpHNOa1oQ8nq0MQ5iYlD0pGfRSBGLI=
sigs.k8s.io/cluster-api/test v1.6.0 h1:hvqUpSYxXCvs4FiEfsDpFZAfZ7i4kkP/59mVdFHlzSI=
@@ -892,8 +886,8 @@ sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMm
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
sigs.k8s.io/kind v0.20.0 h1:f0sc3v9mQbGnjBUaqSFST1dwIuiikKVGgoTwpoP33a8=
sigs.k8s.io/kind v0.20.0/go.mod h1:aBlbxg08cauDgZ612shr017/rZwqd7AS563FvpWKPVs=
-sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE=
-sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E=
+sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
+sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
diff --git a/pkg/cloud/services/compute/instance_test.go b/pkg/cloud/services/compute/instance_test.go
index 54677279aa..74a2773efe 100644
--- a/pkg/cloud/services/compute/instance_test.go
+++ b/pkg/cloud/services/compute/instance_test.go
@@ -30,7 +30,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
"github.com/gophercloud/gophercloud/openstack/imageservice/v2/images"
. "github.com/onsi/gomega"
- "k8s.io/utils/pointer"
+ "k8s.io/utils/ptr"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients"
@@ -193,8 +193,8 @@ func getDefaultInstanceSpec() *InstanceSpec {
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"},
}
diff --git a/pkg/cloud/services/compute/referenced_resources_test.go b/pkg/cloud/services/compute/referenced_resources_test.go
index eca7468d9d..4d9ae11ec7 100644
--- a/pkg/cloud/services/compute/referenced_resources_test.go
+++ b/pkg/cloud/services/compute/referenced_resources_test.go
@@ -26,7 +26,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/servergroups"
"github.com/gophercloud/gophercloud/openstack/imageservice/v2/images"
. "github.com/onsi/gomega"
- "k8s.io/utils/pointer"
+ "k8s.io/utils/ptr"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/mock"
@@ -48,7 +48,7 @@ func Test_ResolveMachineSpec(t *testing.T) {
Description: "Created by cluster-api-provider-openstack cluster test-cluster",
NetworkID: networkID1,
FixedIPs: []infrav1.ResolvedFixedIP{
- {SubnetID: pointer.String(subnetID)},
+ {SubnetID: ptr.To(subnetID)},
},
},
}
@@ -67,8 +67,8 @@ func Test_ResolveMachineSpec(t *testing.T) {
{
testName: "Resources ID passed",
spec: infrav1.OpenStackMachineSpec{
- ServerGroup: &infrav1.ServerGroupParam{ID: pointer.String(serverGroupID1)},
- Image: infrav1.ImageParam{ID: pointer.String(imageID1)},
+ ServerGroup: &infrav1.ServerGroupParam{ID: ptr.To(serverGroupID1)},
+ Image: infrav1.ImageParam{ID: ptr.To(imageID1)},
},
want: &infrav1.ResolvedMachineSpec{
ImageID: imageID1,
@@ -79,7 +79,7 @@ func Test_ResolveMachineSpec(t *testing.T) {
{
testName: "Only image ID passed: want image id and default ports",
spec: infrav1.OpenStackMachineSpec{
- Image: infrav1.ImageParam{ID: pointer.String(imageID1)},
+ Image: infrav1.ImageParam{ID: ptr.To(imageID1)},
},
want: &infrav1.ResolvedMachineSpec{
ImageID: imageID1,
@@ -89,7 +89,7 @@ func Test_ResolveMachineSpec(t *testing.T) {
{
testName: "Server group empty",
spec: infrav1.OpenStackMachineSpec{
- Image: infrav1.ImageParam{ID: pointer.String(imageID1)},
+ Image: infrav1.ImageParam{ID: ptr.To(imageID1)},
ServerGroup: nil,
},
want: &infrav1.ResolvedMachineSpec{
@@ -100,8 +100,8 @@ func Test_ResolveMachineSpec(t *testing.T) {
{
testName: "Server group by Name not found",
spec: infrav1.OpenStackMachineSpec{
- Image: infrav1.ImageParam{ID: pointer.String(imageID1)},
- ServerGroup: &infrav1.ServerGroupParam{Filter: &infrav1.ServerGroupFilter{Name: pointer.String("test-server-group")}},
+ Image: infrav1.ImageParam{ID: ptr.To(imageID1)},
+ ServerGroup: &infrav1.ServerGroupParam{Filter: &infrav1.ServerGroupFilter{Name: ptr.To("test-server-group")}},
},
expectComputeMock: func(m *mock.MockComputeClientMockRecorder) {
m.ListServerGroups().Return(
@@ -116,7 +116,7 @@ func Test_ResolveMachineSpec(t *testing.T) {
spec: infrav1.OpenStackMachineSpec{
Image: infrav1.ImageParam{
Filter: &infrav1.ImageFilter{
- Name: pointer.String("test-image"),
+ Name: ptr.To("test-image"),
},
},
},
@@ -129,11 +129,11 @@ func Test_ResolveMachineSpec(t *testing.T) {
{
testName: "Ports set",
spec: infrav1.OpenStackMachineSpec{
- Image: infrav1.ImageParam{ID: pointer.String(imageID1)},
+ Image: infrav1.ImageParam{ID: ptr.To(imageID1)},
Ports: []infrav1.PortOpts{
{
Network: &infrav1.NetworkParam{
- ID: pointer.String(networkID2),
+ ID: ptr.To(networkID2),
},
},
},
diff --git a/pkg/cloud/services/compute/servergroup_test.go b/pkg/cloud/services/compute/servergroup_test.go
index b73b496dcf..5a8e757075 100644
--- a/pkg/cloud/services/compute/servergroup_test.go
+++ b/pkg/cloud/services/compute/servergroup_test.go
@@ -23,7 +23,7 @@ import (
"github.com/go-logr/logr/testr"
"github.com/golang/mock/gomock"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/servergroups"
- "k8s.io/utils/pointer"
+ "k8s.io/utils/ptr"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/mock"
@@ -43,7 +43,7 @@ func TestService_GetServerGroupID(t *testing.T) {
}{
{
testName: "Return server group ID from filter if only filter (with ID) given",
- serverGroupParam: &infrav1.ServerGroupParam{ID: pointer.String(serverGroupID1)},
+ serverGroupParam: &infrav1.ServerGroupParam{ID: ptr.To(serverGroupID1)},
expect: func(m *mock.MockComputeClientMockRecorder) {
},
want: serverGroupID1,
@@ -59,7 +59,7 @@ func TestService_GetServerGroupID(t *testing.T) {
},
{
testName: "Return server group ID from filter if only filter (with name) given",
- serverGroupParam: &infrav1.ServerGroupParam{Filter: &infrav1.ServerGroupFilter{Name: pointer.String("test-server-group")}},
+ serverGroupParam: &infrav1.ServerGroupParam{Filter: &infrav1.ServerGroupFilter{Name: ptr.To("test-server-group")}},
expect: func(m *mock.MockComputeClientMockRecorder) {
m.ListServerGroups().Return(
[]servergroups.ServerGroup{{ID: serverGroupID1, Name: "test-server-group"}},
@@ -70,7 +70,7 @@ func TestService_GetServerGroupID(t *testing.T) {
},
{
testName: "Return no results",
- serverGroupParam: &infrav1.ServerGroupParam{Filter: &infrav1.ServerGroupFilter{Name: pointer.String("test-server-group")}},
+ serverGroupParam: &infrav1.ServerGroupParam{Filter: &infrav1.ServerGroupFilter{Name: ptr.To("test-server-group")}},
expect: func(m *mock.MockComputeClientMockRecorder) {
m.ListServerGroups().Return(
[]servergroups.ServerGroup{},
@@ -81,7 +81,7 @@ func TestService_GetServerGroupID(t *testing.T) {
},
{
testName: "Return multiple results",
- serverGroupParam: &infrav1.ServerGroupParam{Filter: &infrav1.ServerGroupFilter{Name: pointer.String("test-server-group")}},
+ serverGroupParam: &infrav1.ServerGroupParam{Filter: &infrav1.ServerGroupFilter{Name: ptr.To("test-server-group")}},
expect: func(m *mock.MockComputeClientMockRecorder) {
m.ListServerGroups().Return(
[]servergroups.ServerGroup{
@@ -95,7 +95,7 @@ func TestService_GetServerGroupID(t *testing.T) {
},
{
testName: "OpenStack returns error",
- serverGroupParam: &infrav1.ServerGroupParam{Filter: &infrav1.ServerGroupFilter{Name: pointer.String("test-server-group")}},
+ serverGroupParam: &infrav1.ServerGroupParam{Filter: &infrav1.ServerGroupFilter{Name: ptr.To("test-server-group")}},
expect: func(m *mock.MockComputeClientMockRecorder) {
m.ListServerGroups().Return(
nil,
diff --git a/pkg/cloud/services/loadbalancer/loadbalancer.go b/pkg/cloud/services/loadbalancer/loadbalancer.go
index 8fdea9fefb..97f7fe81fa 100644
--- a/pkg/cloud/services/loadbalancer/loadbalancer.go
+++ b/pkg/cloud/services/loadbalancer/loadbalancer.go
@@ -30,7 +30,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/pools"
"k8s.io/apimachinery/pkg/util/wait"
utilsnet "k8s.io/utils/net"
- "k8s.io/utils/pointer"
+ "k8s.io/utils/ptr"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/record"
@@ -98,7 +98,7 @@ func (s *Service) ReconcileLoadBalancer(openStackCluster *infrav1.OpenStackClust
}
}
- if !pointer.BoolDeref(openStackCluster.Spec.DisableAPIServerFloatingIP, false) {
+ if !ptr.Deref(openStackCluster.Spec.DisableAPIServerFloatingIP, false) {
floatingIPAddress, err := getAPIServerFloatingIP(openStackCluster)
if err != nil {
return false, err
@@ -155,7 +155,7 @@ func getAPIServerVIPAddress(openStackCluster *infrav1.OpenStackCluster) (*string
return openStackCluster.Spec.APIServerFixedIP, nil
// If we are using the VIP as the control plane endpoint, use any value explicitly set on the control plane endpoint
- case pointer.BoolDeref(openStackCluster.Spec.DisableAPIServerFloatingIP, false) && openStackCluster.Spec.ControlPlaneEndpoint != nil && openStackCluster.Spec.ControlPlaneEndpoint.IsValid():
+ case ptr.Deref(openStackCluster.Spec.DisableAPIServerFloatingIP, false) && openStackCluster.Spec.ControlPlaneEndpoint != nil && openStackCluster.Spec.ControlPlaneEndpoint.IsValid():
fixedIPAddress, err := lookupHost(openStackCluster.Spec.ControlPlaneEndpoint.Host)
if err != nil {
return nil, fmt.Errorf("lookup host: %w", err)
diff --git a/pkg/cloud/services/loadbalancer/loadbalancer_test.go b/pkg/cloud/services/loadbalancer/loadbalancer_test.go
index 3768884adb..bc8317e61e 100644
--- a/pkg/cloud/services/loadbalancer/loadbalancer_test.go
+++ b/pkg/cloud/services/loadbalancer/loadbalancer_test.go
@@ -31,7 +31,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/pools"
"github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/providers"
. "github.com/onsi/gomega"
- "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/v1beta1"
@@ -59,9 +59,9 @@ func Test_ReconcileLoadBalancer(t *testing.T) {
openStackCluster := &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
APIServerLoadBalancer: &infrav1.APIServerLoadBalancer{
- Enabled: pointer.Bool(true),
+ Enabled: ptr.To(true),
},
- DisableAPIServerFloatingIP: pointer.Bool(true),
+ DisableAPIServerFloatingIP: ptr.To(true),
ControlPlaneEndpoint: &clusterv1.APIEndpoint{
Host: apiHostname,
Port: 6443,
@@ -193,38 +193,38 @@ func Test_getAPIServerVIPAddress(t *testing.T) {
},
},
},
- want: pointer.String("1.2.3.4"),
+ want: ptr.To("1.2.3.4"),
wantError: false,
},
{
name: "API server VIP is API Server Fixed IP",
openStackCluster: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
- APIServerFixedIP: pointer.String("1.2.3.4"),
+ APIServerFixedIP: ptr.To("1.2.3.4"),
},
},
- want: pointer.String("1.2.3.4"),
+ want: ptr.To("1.2.3.4"),
wantError: false,
},
{
name: "API server VIP with valid control plane endpoint",
openStackCluster: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
- DisableAPIServerFloatingIP: pointer.Bool(true),
+ DisableAPIServerFloatingIP: ptr.To(true),
ControlPlaneEndpoint: &clusterv1.APIEndpoint{
Host: apiHostname,
Port: 6443,
},
},
},
- want: pointer.String("192.168.100.10"),
+ want: ptr.To("192.168.100.10"),
wantError: false,
},
{
name: "API server VIP with invalid control plane endpoint",
openStackCluster: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
- DisableAPIServerFloatingIP: pointer.Bool(true),
+ DisableAPIServerFloatingIP: ptr.To(true),
ControlPlaneEndpoint: &clusterv1.APIEndpoint{
Host: "invalid-api.test-cluster.test",
Port: 6443,
@@ -282,17 +282,17 @@ func Test_getAPIServerFloatingIP(t *testing.T) {
},
},
},
- want: pointer.String("1.2.3.4"),
+ want: ptr.To("1.2.3.4"),
wantError: false,
},
{
name: "API server FIP is API Server Floating IP",
openStackCluster: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
- APIServerFloatingIP: pointer.String("1.2.3.4"),
+ APIServerFloatingIP: ptr.To("1.2.3.4"),
},
},
- want: pointer.String("1.2.3.4"),
+ want: ptr.To("1.2.3.4"),
wantError: false,
},
{
@@ -305,7 +305,7 @@ func Test_getAPIServerFloatingIP(t *testing.T) {
},
},
},
- want: pointer.String("192.168.100.10"),
+ want: ptr.To("192.168.100.10"),
wantError: false,
},
{
diff --git a/pkg/cloud/services/networking/floatingip.go b/pkg/cloud/services/networking/floatingip.go
index 3e495e77d0..4e611f7fe0 100644
--- a/pkg/cloud/services/networking/floatingip.go
+++ b/pkg/cloud/services/networking/floatingip.go
@@ -24,7 +24,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/wait"
- "k8s.io/utils/pointer"
+ "k8s.io/utils/ptr"
"sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha1"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
@@ -38,7 +38,7 @@ func (s *Service) GetOrCreateFloatingIP(eventObject runtime.Object, openStackClu
var err error
var fpCreateOpts floatingips.CreateOpts
- if pointer.StringDeref(ip, "") != "" {
+ if ptr.Deref(ip, "") != "" {
fp, err = s.GetFloatingIP(*ip)
if err != nil {
return nil, err
diff --git a/pkg/cloud/services/networking/floatingip_test.go b/pkg/cloud/services/networking/floatingip_test.go
index 60a9db4300..11148e88e4 100644
--- a/pkg/cloud/services/networking/floatingip_test.go
+++ b/pkg/cloud/services/networking/floatingip_test.go
@@ -23,7 +23,7 @@ import (
"github.com/golang/mock/gomock"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips"
. "github.com/onsi/gomega"
- "k8s.io/utils/pointer"
+ "k8s.io/utils/ptr"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/mock"
@@ -86,7 +86,7 @@ func Test_GetOrCreateFloatingIP(t *testing.T) {
client: mockClient,
}
eventObject := infrav1.OpenStackMachine{}
- got, err := s.GetOrCreateFloatingIP(&eventObject, openStackCluster, "test-cluster", pointer.String(tt.ip))
+ got, err := s.GetOrCreateFloatingIP(&eventObject, openStackCluster, "test-cluster", ptr.To(tt.ip))
g.Expect(err).ShouldNot(HaveOccurred())
g.Expect(got).To(Equal(tt.want))
})
diff --git a/pkg/cloud/services/networking/network.go b/pkg/cloud/services/networking/network.go
index 716750e026..f5602a2436 100644
--- a/pkg/cloud/services/networking/network.go
+++ b/pkg/cloud/services/networking/network.go
@@ -25,7 +25,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external"
"github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
"github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
- "k8s.io/utils/pointer"
+ "k8s.io/utils/ptr"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/metrics"
@@ -79,7 +79,7 @@ func (c createOpts) ToNetworkCreateMap() (map[string]interface{}, error) {
// - no external network was given in the cluster spec and no external network was found
// - the user has set OpenStackCluster.Spec.DisableExternalNetwork to true.
func (s *Service) ReconcileExternalNetwork(openStackCluster *infrav1.OpenStackCluster) error {
- if pointer.BoolDeref(openStackCluster.Spec.DisableExternalNetwork, false) {
+ if ptr.Deref(openStackCluster.Spec.DisableExternalNetwork, false) {
s.scope.Logger().Info("External network is disabled - proceeding with internal network only")
openStackCluster.Status.ExternalNetwork = nil
return nil
@@ -144,7 +144,7 @@ func (s *Service) ReconcileNetwork(openStackCluster *infrav1.OpenStackCluster, c
Name: networkName,
}
- if pointer.BoolDeref(openStackCluster.Spec.DisablePortSecurity, false) {
+ if ptr.Deref(openStackCluster.Spec.DisablePortSecurity, false) {
opts.PortSecurityEnabled = gophercloud.Disabled
}
@@ -299,7 +299,7 @@ type GetNetworkOpts func(networks.ListOptsBuilder) networks.ListOptsBuilder
func ExternalNetworksOnly(opts networks.ListOptsBuilder) networks.ListOptsBuilder {
return &external.ListOptsExt{
ListOptsBuilder: opts,
- External: pointer.Bool(true),
+ External: ptr.To(true),
}
}
diff --git a/pkg/cloud/services/networking/network_test.go b/pkg/cloud/services/networking/network_test.go
index 41fa452838..3a3c519743 100644
--- a/pkg/cloud/services/networking/network_test.go
+++ b/pkg/cloud/services/networking/network_test.go
@@ -27,7 +27,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
"github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
. "github.com/onsi/gomega"
- "k8s.io/utils/pointer"
+ "k8s.io/utils/ptr"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/mock"
@@ -117,7 +117,7 @@ func Test_ReconcileNetwork(t *testing.T) {
name: "creation with disabled port security",
openStackCluster: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
- DisablePortSecurity: pointer.Bool(true),
+ DisablePortSecurity: ptr.To(true),
},
},
expect: func(m *mock.MockNetworkClientMockRecorder) {
@@ -153,7 +153,7 @@ func Test_ReconcileNetwork(t *testing.T) {
name: "creation with mtu set",
openStackCluster: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
- NetworkMTU: pointer.Int(1500),
+ NetworkMTU: ptr.To(1500),
},
},
expect: func(m *mock.MockNetworkClientMockRecorder) {
@@ -165,7 +165,7 @@ func Test_ReconcileNetwork(t *testing.T) {
CreateNetwork(createOpts{
AdminStateUp: gophercloud.Enabled,
Name: expectedNetworkName,
- MTU: pointer.Int(1500),
+ MTU: ptr.To(1500),
}).
Return(&networks.Network{
ID: fakeNetworkID,
@@ -214,7 +214,7 @@ func Test_ReconcileExternalNetwork(t *testing.T) {
return func(opts networks.ListOptsBuilder) ([]networks.Network, error) {
expected := &external.ListOptsExt{
ListOptsBuilder: listOpts,
- External: pointer.Bool(true),
+ External: ptr.To(true),
}
g.Expect(opts).To(Equal(expected), cmp.Diff(opts, expected))
@@ -234,7 +234,7 @@ func Test_ReconcileExternalNetwork(t *testing.T) {
openStackCluster: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
ExternalNetwork: &infrav1.NetworkParam{
- ID: pointer.String(fakeNetworkID),
+ ID: ptr.To(fakeNetworkID),
},
},
},
@@ -247,7 +247,7 @@ func Test_ReconcileExternalNetwork(t *testing.T) {
want: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
ExternalNetwork: &infrav1.NetworkParam{
- ID: pointer.String(fakeNetworkID),
+ ID: ptr.To(fakeNetworkID),
},
},
Status: infrav1.OpenStackClusterStatus{
@@ -297,7 +297,7 @@ func Test_ReconcileExternalNetwork(t *testing.T) {
openStackCluster: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
ExternalNetwork: &infrav1.NetworkParam{
- ID: pointer.String(fakeNetworkID),
+ ID: ptr.To(fakeNetworkID),
},
},
},
@@ -307,7 +307,7 @@ func Test_ReconcileExternalNetwork(t *testing.T) {
want: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
ExternalNetwork: &infrav1.NetworkParam{
- ID: pointer.String(fakeNetworkID),
+ ID: ptr.To(fakeNetworkID),
},
},
},
@@ -339,13 +339,13 @@ func Test_ReconcileExternalNetwork(t *testing.T) {
name: "not reconcile external network when external network disabled",
openStackCluster: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
- DisableExternalNetwork: pointer.Bool(true),
+ DisableExternalNetwork: ptr.To(true),
},
},
expect: func(_ Gomega, m *mock.MockNetworkClientMockRecorder) {},
want: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
- DisableExternalNetwork: pointer.Bool(true),
+ DisableExternalNetwork: ptr.To(true),
},
Status: infrav1.OpenStackClusterStatus{
ExternalNetwork: nil,
@@ -406,7 +406,7 @@ func Test_ReconcileExternalNetwork(t *testing.T) {
DoAndReturn(func(opts networks.ListOptsBuilder) ([]networks.Network, error) {
expected := &external.ListOptsExt{
ListOptsBuilder: networks.ListOpts{},
- External: pointer.Bool(true),
+ External: ptr.To(true),
}
g.Expect(opts).To(Equal(expected), cmp.Diff(opts, expected))
diff --git a/pkg/cloud/services/networking/port.go b/pkg/cloud/services/networking/port.go
index 9b736cd4d4..9d740ae3ff 100644
--- a/pkg/cloud/services/networking/port.go
+++ b/pkg/cloud/services/networking/port.go
@@ -30,7 +30,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/wait"
- "k8s.io/utils/pointer"
+ "k8s.io/utils/ptr"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/record"
@@ -125,11 +125,11 @@ func (s *Service) GetPortForExternalNetwork(instanceID string, externalNetworkID
func (s *Service) CreatePort(eventObject runtime.Object, portSpec *infrav1.ResolvedPortSpec) (*ports.Port, error) {
var addressPairs []ports.AddressPair
- if !pointer.BoolDeref(portSpec.DisablePortSecurity, false) {
+ if !ptr.Deref(portSpec.DisablePortSecurity, false) {
for _, ap := range portSpec.AllowedAddressPairs {
addressPairs = append(addressPairs, ports.AddressPair{
IPAddress: ap.IPAddress,
- MACAddress: pointer.StringDeref(ap.MACAddress, ""),
+ MACAddress: ptr.Deref(ap.MACAddress, ""),
})
}
}
@@ -139,8 +139,8 @@ func (s *Service) CreatePort(eventObject runtime.Object, portSpec *infrav1.Resol
fixedIPs = make([]ports.IP, len(portSpec.FixedIPs))
for i, fixedIP := range portSpec.FixedIPs {
fixedIPs[i] = ports.IP{
- SubnetID: pointer.StringDeref(fixedIP.SubnetID, ""),
- IPAddress: pointer.StringDeref(fixedIP.IPAddress, ""),
+ SubnetID: ptr.Deref(fixedIP.SubnetID, ""),
+ IPAddress: ptr.Deref(fixedIP.IPAddress, ""),
}
}
}
@@ -160,7 +160,7 @@ func (s *Service) CreatePort(eventObject runtime.Object, portSpec *infrav1.Resol
NetworkID: portSpec.NetworkID,
Description: portSpec.Description,
AdminStateUp: portSpec.AdminStateUp,
- MACAddress: pointer.StringDeref(portSpec.MACAddress, ""),
+ MACAddress: ptr.Deref(portSpec.MACAddress, ""),
AllowedAddressPairs: addressPairs,
ValueSpecs: valueSpecs,
PropagateUplinkStatus: portSpec.PropagateUplinkStatus,
@@ -184,8 +184,8 @@ func (s *Service) CreatePort(eventObject runtime.Object, portSpec *infrav1.Resol
portsBindingOpts := portsbinding.CreateOptsExt{
CreateOptsBuilder: builder,
- HostID: pointer.StringDeref(portSpec.HostID, ""),
- VNICType: pointer.StringDeref(portSpec.VNICType, ""),
+ HostID: ptr.Deref(portSpec.HostID, ""),
+ VNICType: ptr.Deref(portSpec.VNICType, ""),
Profile: getPortProfile(portSpec.Profile),
}
builder = portsBindingOpts
@@ -203,7 +203,7 @@ func (s *Service) CreatePort(eventObject runtime.Object, portSpec *infrav1.Resol
}
}
record.Eventf(eventObject, "SuccessfulCreatePort", "Created port %s with id %s", port.Name, port.ID)
- if pointer.BoolDeref(portSpec.Trunk, false) {
+ if ptr.Deref(portSpec.Trunk, false) {
trunk, err := s.getOrCreateTrunkForPort(eventObject, port)
if err != nil {
record.Warnf(eventObject, "FailedCreateTrunk", "Failed to create trunk for port %s: %v", port.Name, err)
@@ -227,10 +227,10 @@ func getPortProfile(p *infrav1.BindingProfile) map[string]interface{} {
// if p.OVSHWOffload is true, we need to set the profile
// to enable hardware offload for the port
- if pointer.BoolDeref(p.OVSHWOffload, false) {
+ if ptr.Deref(p.OVSHWOffload, false) {
portProfile["capabilities"] = []string{"switchdev"}
}
- if pointer.BoolDeref(p.TrustedVF, false) {
+ if ptr.Deref(p.TrustedVF, false) {
portProfile["trusted"] = true
}
@@ -384,7 +384,7 @@ func (s *Service) ConstructPorts(spec *infrav1.OpenStackMachineSpec, clusterReso
// trunk support is required if any port has trunk enabled
portUsesTrunk := func() bool {
for _, port := range resolvedPorts {
- if pointer.BoolDeref(port.Trunk, false) {
+ if ptr.Deref(port.Trunk, false) {
return true
}
}
diff --git a/pkg/cloud/services/networking/port_test.go b/pkg/cloud/services/networking/port_test.go
index 501f5f39cc..bbdc1cd018 100644
--- a/pkg/cloud/services/networking/port_test.go
+++ b/pkg/cloud/services/networking/port_test.go
@@ -33,7 +33,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/types"
- "k8s.io/utils/pointer"
+ "k8s.io/utils/ptr"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/mock"
@@ -72,36 +72,36 @@ func Test_CreatePort(t *testing.T) {
NetworkID: netID,
FixedIPs: []infrav1.ResolvedFixedIP{
{
- SubnetID: pointer.String(subnetID1),
- IPAddress: pointer.String(ipAddress1),
+ SubnetID: ptr.To(subnetID1),
+ IPAddress: ptr.To(ipAddress1),
},
{
- IPAddress: pointer.String(ipAddress2),
+ IPAddress: ptr.To(ipAddress2),
},
{
- SubnetID: pointer.String(subnetID2),
+ SubnetID: ptr.To(subnetID2),
},
},
SecurityGroups: []string{portSecurityGroupID},
ResolvedPortSpecFields: infrav1.ResolvedPortSpecFields{
- AdminStateUp: pointer.Bool(true),
- MACAddress: pointer.String(macAddress),
+ AdminStateUp: ptr.To(true),
+ MACAddress: ptr.To(macAddress),
AllowedAddressPairs: []infrav1.AddressPair{
{
IPAddress: ipAddress1,
- MACAddress: pointer.String(macAddress),
+ MACAddress: ptr.To(macAddress),
},
{
IPAddress: ipAddress2,
},
},
- HostID: pointer.String(hostID),
- VNICType: pointer.String("normal"),
+ HostID: ptr.To(hostID),
+ VNICType: ptr.To("normal"),
Profile: &infrav1.BindingProfile{
- OVSHWOffload: pointer.Bool(true),
- TrustedVF: pointer.Bool(true),
+ OVSHWOffload: ptr.To(true),
+ TrustedVF: ptr.To(true),
},
- PropagateUplinkStatus: pointer.Bool(true),
+ PropagateUplinkStatus: ptr.To(true),
ValueSpecs: []infrav1.ValueSpec{
{
Name: "test-valuespec",
@@ -117,7 +117,7 @@ func Test_CreatePort(t *testing.T) {
Name: "foo-port-1",
Description: "Created by cluster-api-provider-openstack cluster test-cluster",
NetworkID: netID,
- AdminStateUp: pointer.Bool(true),
+ AdminStateUp: ptr.To(true),
MACAddress: macAddress,
FixedIPs: []ports.IP{
{
@@ -141,7 +141,7 @@ func Test_CreatePort(t *testing.T) {
IPAddress: ipAddress2,
},
},
- PropagateUplinkStatus: pointer.Bool(true),
+ PropagateUplinkStatus: ptr.To(true),
ValueSpecs: &map[string]string{
"test-key": "test-value",
},
@@ -197,11 +197,11 @@ func Test_CreatePort(t *testing.T) {
Name: "test-port",
NetworkID: netID,
ResolvedPortSpecFields: infrav1.ResolvedPortSpecFields{
- DisablePortSecurity: pointer.Bool(true),
+ DisablePortSecurity: ptr.To(true),
AllowedAddressPairs: []infrav1.AddressPair{
{
IPAddress: ipAddress1,
- MACAddress: pointer.String(macAddress),
+ MACAddress: ptr.To(macAddress),
},
},
},
@@ -214,7 +214,7 @@ func Test_CreatePort(t *testing.T) {
}
expectedCreateOpts = portsecurity.PortCreateOptsExt{
CreateOptsBuilder: expectedCreateOpts,
- PortSecurityEnabled: pointer.Bool(false),
+ PortSecurityEnabled: ptr.To(false),
}
expectedCreateOpts = portsbinding.CreateOptsExt{
CreateOptsBuilder: expectedCreateOpts,
@@ -233,11 +233,11 @@ func Test_CreatePort(t *testing.T) {
Name: "test-port",
NetworkID: netID,
ResolvedPortSpecFields: infrav1.ResolvedPortSpecFields{
- DisablePortSecurity: pointer.Bool(false),
+ DisablePortSecurity: ptr.To(false),
AllowedAddressPairs: []infrav1.AddressPair{
{
IPAddress: ipAddress1,
- MACAddress: pointer.String(macAddress),
+ MACAddress: ptr.To(macAddress),
},
},
},
@@ -256,7 +256,7 @@ func Test_CreatePort(t *testing.T) {
}
expectedCreateOpts = portsecurity.PortCreateOptsExt{
CreateOptsBuilder: expectedCreateOpts,
- PortSecurityEnabled: pointer.Bool(true),
+ PortSecurityEnabled: ptr.To(true),
}
expectedCreateOpts = portsbinding.CreateOptsExt{
CreateOptsBuilder: expectedCreateOpts,
@@ -275,7 +275,7 @@ func Test_CreatePort(t *testing.T) {
Name: "test-port",
NetworkID: netID,
Tags: []string{"tag1", "tag2"},
- Trunk: pointer.Bool(true),
+ Trunk: ptr.To(true),
},
expect: func(m *mock.MockNetworkClientMockRecorder, g types.Gomega) {
var expectedCreateOpts ports.CreateOptsBuilder
@@ -385,7 +385,7 @@ func TestService_ConstructPorts(t *testing.T) {
Tags: []string{"test-tag"},
NetworkID: defaultNetworkID,
FixedIPs: []infrav1.ResolvedFixedIP{
- {SubnetID: pointer.String(defaultSubnetID)},
+ {SubnetID: ptr.To(defaultSubnetID)},
},
},
},
@@ -395,7 +395,7 @@ func TestService_ConstructPorts(t *testing.T) {
spec: infrav1.OpenStackMachineSpec{
Ports: []infrav1.PortOpts{
{
- NameSuffix: pointer.String("custom"),
+ NameSuffix: ptr.To("custom"),
Network: nil,
FixedIPs: nil,
},
@@ -408,7 +408,7 @@ func TestService_ConstructPorts(t *testing.T) {
NetworkID: defaultNetworkID,
FixedIPs: []infrav1.ResolvedFixedIP{
{
- SubnetID: pointer.String(defaultSubnetID),
+ SubnetID: ptr.To(defaultSubnetID),
},
},
Tags: []string{"test-tag"},
@@ -420,7 +420,7 @@ func TestService_ConstructPorts(t *testing.T) {
spec: infrav1.OpenStackMachineSpec{
Ports: []infrav1.PortOpts{
{
- NameSuffix: pointer.String("custom"),
+ NameSuffix: ptr.To("custom"),
Network: nil,
FixedIPs: nil,
},
@@ -436,10 +436,10 @@ func TestService_ConstructPorts(t *testing.T) {
Description: defaultDescription,
NetworkID: defaultNetworkID,
FixedIPs: []infrav1.ResolvedFixedIP{
- {SubnetID: pointer.String(defaultSubnetID)},
+ {SubnetID: ptr.To(defaultSubnetID)},
},
Tags: []string{"test-tag"},
- Trunk: pointer.Bool(true),
+ Trunk: ptr.To(true),
},
},
wantErr: false,
@@ -449,7 +449,7 @@ func TestService_ConstructPorts(t *testing.T) {
spec: infrav1.OpenStackMachineSpec{
Ports: []infrav1.PortOpts{
{
- Trunk: pointer.Bool(true),
+ Trunk: ptr.To(true),
},
},
Trunk: false,
@@ -463,10 +463,10 @@ func TestService_ConstructPorts(t *testing.T) {
Description: defaultDescription,
NetworkID: defaultNetworkID,
FixedIPs: []infrav1.ResolvedFixedIP{
- {SubnetID: pointer.String(defaultSubnetID)},
+ {SubnetID: ptr.To(defaultSubnetID)},
},
Tags: []string{"test-tag"},
- Trunk: pointer.Bool(true),
+ Trunk: ptr.To(true),
},
},
},
@@ -476,7 +476,7 @@ func TestService_ConstructPorts(t *testing.T) {
Ports: []infrav1.PortOpts{
{
Network: &infrav1.NetworkParam{
- ID: pointer.String(networkID),
+ ID: ptr.To(networkID),
},
},
},
@@ -527,7 +527,7 @@ func TestService_ConstructPorts(t *testing.T) {
FixedIPs: []infrav1.FixedIP{
{
Subnet: &infrav1.SubnetParam{
- ID: pointer.String(subnetID1),
+ ID: ptr.To(subnetID1),
},
},
},
@@ -541,7 +541,7 @@ func TestService_ConstructPorts(t *testing.T) {
{
NetworkID: networkID,
FixedIPs: []infrav1.ResolvedFixedIP{
- {SubnetID: pointer.String(subnetID1)},
+ {SubnetID: ptr.To(subnetID1)},
},
// Defaults
@@ -576,7 +576,7 @@ func TestService_ConstructPorts(t *testing.T) {
NetworkID: networkID,
FixedIPs: []infrav1.ResolvedFixedIP{
{
- SubnetID: pointer.String(subnetID1),
+ SubnetID: ptr.To(subnetID1),
},
},
@@ -668,10 +668,10 @@ func TestService_ConstructPorts(t *testing.T) {
NetworkID: networkID,
FixedIPs: []infrav1.ResolvedFixedIP{
{
- SubnetID: pointer.String(subnetID1),
+ SubnetID: ptr.To(subnetID1),
},
{
- SubnetID: pointer.String(subnetID2),
+ SubnetID: ptr.To(subnetID2),
},
},
@@ -699,7 +699,7 @@ func TestService_ConstructPorts(t *testing.T) {
Name: "test-instance-0",
NetworkID: defaultNetworkID,
FixedIPs: []infrav1.ResolvedFixedIP{
- {SubnetID: pointer.String(defaultSubnetID)},
+ {SubnetID: ptr.To(defaultSubnetID)},
},
Description: defaultDescription,
Tags: []string{"test-tag"},
@@ -730,7 +730,7 @@ func TestService_ConstructPorts(t *testing.T) {
Name: "test-instance-0",
NetworkID: defaultNetworkID,
FixedIPs: []infrav1.ResolvedFixedIP{
- {SubnetID: pointer.String(defaultSubnetID)},
+ {SubnetID: ptr.To(defaultSubnetID)},
},
Description: defaultDescription,
Tags: []string{"test-tag"},
@@ -741,13 +741,13 @@ func TestService_ConstructPorts(t *testing.T) {
{
name: "managed security group added to port",
spec: infrav1.OpenStackMachineSpec{},
- managedSecurityGroup: pointer.String(securityGroupID1),
+ managedSecurityGroup: ptr.To(securityGroupID1),
want: []infrav1.ResolvedPortSpec{
{
Name: "test-instance-0",
NetworkID: defaultNetworkID,
FixedIPs: []infrav1.ResolvedFixedIP{
- {SubnetID: pointer.String(defaultSubnetID)},
+ {SubnetID: ptr.To(defaultSubnetID)},
},
Description: defaultDescription,
Tags: []string{"test-tag"},
@@ -760,7 +760,7 @@ func TestService_ConstructPorts(t *testing.T) {
spec: infrav1.OpenStackMachineSpec{
SecurityGroups: []infrav1.SecurityGroupParam{{Filter: &infrav1.SecurityGroupFilter{Name: "machine-security-group"}}},
},
- managedSecurityGroup: pointer.String(securityGroupID1),
+ managedSecurityGroup: ptr.To(securityGroupID1),
expectNetwork: func(m *mock.MockNetworkClientMockRecorder) {
m.ListSecGroup(groups.ListOpts{Name: "machine-security-group"}).Return([]groups.SecGroup{
{ID: securityGroupID2},
@@ -771,7 +771,7 @@ func TestService_ConstructPorts(t *testing.T) {
Name: "test-instance-0",
NetworkID: defaultNetworkID,
FixedIPs: []infrav1.ResolvedFixedIP{
- {SubnetID: pointer.String(defaultSubnetID)},
+ {SubnetID: ptr.To(defaultSubnetID)},
},
Description: defaultDescription,
Tags: []string{"test-tag"},
@@ -841,7 +841,7 @@ func Test_getPortName(t *testing.T) {
name: "with PortOpts name suffix",
instanceName: "test-1-instance",
spec: &infrav1.PortOpts{
- NameSuffix: pointer.String("foo"),
+ NameSuffix: ptr.To("foo"),
},
netIndex: 4,
want: "test-1-instance-foo",
@@ -857,10 +857,10 @@ func Test_getPortName(t *testing.T) {
name: "with PortOpts name suffix",
instanceName: "test-1-instance",
spec: &infrav1.PortOpts{
- NameSuffix: pointer.String("foo2"),
- Network: &infrav1.NetworkParam{ID: pointer.String("bar")},
+ NameSuffix: ptr.To("foo2"),
+ Network: &infrav1.NetworkParam{ID: ptr.To("bar")},
ResolvedPortSpecFields: infrav1.ResolvedPortSpecFields{
- DisablePortSecurity: pointer.Bool(true),
+ DisablePortSecurity: ptr.To(true),
},
},
netIndex: 4,
diff --git a/pkg/cloud/services/networking/securitygroups_test.go b/pkg/cloud/services/networking/securitygroups_test.go
index 487fa9bd87..a9f0ca3163 100644
--- a/pkg/cloud/services/networking/securitygroups_test.go
+++ b/pkg/cloud/services/networking/securitygroups_test.go
@@ -27,7 +27,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules"
. "github.com/onsi/gomega"
- "k8s.io/utils/pointer"
+ "k8s.io/utils/ptr"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/mock"
@@ -51,9 +51,9 @@ func TestValidateRemoteManagedGroups(t *testing.T) {
{
name: "Valid rule with missing remoteManagedGroups",
rule: infrav1.SecurityGroupRuleSpec{
- PortRangeMin: pointer.Int(22),
- PortRangeMax: pointer.Int(22),
- Protocol: pointer.String("tcp"),
+ PortRangeMin: ptr.To(22),
+ PortRangeMax: ptr.To(22),
+ Protocol: ptr.To("tcp"),
},
remoteManagedGroups: map[string]string{
"self": "self",
@@ -123,9 +123,9 @@ func TestGetAllNodesRules(t *testing.T) {
},
allNodesSecurityGroupRules: []infrav1.SecurityGroupRuleSpec{
{
- Protocol: pointer.String("tcp"),
- PortRangeMin: pointer.Int(22),
- PortRangeMax: pointer.Int(22),
+ Protocol: ptr.To("tcp"),
+ PortRangeMin: ptr.To(22),
+ PortRangeMax: ptr.To(22),
RemoteManagedGroups: []infrav1.ManagedSecurityGroupName{
"controlplane",
"worker",
@@ -156,9 +156,9 @@ func TestGetAllNodesRules(t *testing.T) {
},
allNodesSecurityGroupRules: []infrav1.SecurityGroupRuleSpec{
{
- Protocol: pointer.String("tcp"),
- PortRangeMin: pointer.Int(22),
- PortRangeMax: pointer.Int(22),
+ Protocol: ptr.To("tcp"),
+ PortRangeMin: ptr.To(22),
+ PortRangeMax: ptr.To(22),
RemoteManagedGroups: []infrav1.ManagedSecurityGroupName{"controlplane"},
},
},
@@ -179,9 +179,9 @@ func TestGetAllNodesRules(t *testing.T) {
},
allNodesSecurityGroupRules: []infrav1.SecurityGroupRuleSpec{
{
- Protocol: pointer.String("tcp"),
- PortRangeMin: pointer.Int(22),
- PortRangeMax: pointer.Int(22),
+ Protocol: ptr.To("tcp"),
+ PortRangeMin: ptr.To(22),
+ PortRangeMax: ptr.To(22),
RemoteManagedGroups: []infrav1.ManagedSecurityGroupName{
"controlplanezzz",
"worker",
@@ -199,9 +199,9 @@ func TestGetAllNodesRules(t *testing.T) {
},
allNodesSecurityGroupRules: []infrav1.SecurityGroupRuleSpec{
{
- Protocol: pointer.String("tcp"),
- PortRangeMin: pointer.Int(22),
- PortRangeMax: pointer.Int(22),
+ Protocol: ptr.To("tcp"),
+ PortRangeMin: ptr.To(22),
+ PortRangeMax: ptr.To(22),
RemoteManagedGroups: []infrav1.ManagedSecurityGroupName{
"bastion",
},
@@ -274,9 +274,9 @@ func TestGenerateDesiredSecGroups(t *testing.T) {
ManagedSecurityGroups: &infrav1.ManagedSecurityGroups{
AllNodesSecurityGroupRules: []infrav1.SecurityGroupRuleSpec{
{
- Protocol: pointer.String("tcp"),
- PortRangeMin: pointer.Int(22),
- PortRangeMax: pointer.Int(22),
+ Protocol: ptr.To("tcp"),
+ PortRangeMin: ptr.To(22),
+ PortRangeMax: ptr.To(22),
RemoteManagedGroups: []infrav1.ManagedSecurityGroupName{"controlplane", "worker"},
},
},
@@ -293,9 +293,9 @@ func TestGenerateDesiredSecGroups(t *testing.T) {
ManagedSecurityGroups: &infrav1.ManagedSecurityGroups{
AllNodesSecurityGroupRules: []infrav1.SecurityGroupRuleSpec{
{
- Protocol: pointer.String("tcp"),
- PortRangeMin: pointer.Int(22),
- PortRangeMax: pointer.Int(22),
+ Protocol: ptr.To("tcp"),
+ PortRangeMin: ptr.To(22),
+ PortRangeMax: ptr.To(22),
RemoteManagedGroups: []infrav1.ManagedSecurityGroupName{"controlplane", "worker", "unknownGroup"},
},
},
@@ -533,7 +533,7 @@ func TestService_ReconcileSecurityGroups(t *testing.T) {
name: "Default control plane, worker, and bastion security groups",
openStackClusterSpec: infrav1.OpenStackClusterSpec{
Bastion: &infrav1.Bastion{
- Enabled: pointer.Bool(true),
+ Enabled: ptr.To(true),
},
ManagedSecurityGroups: &infrav1.ManagedSecurityGroups{},
},
diff --git a/pkg/webhooks/openstackcluster_webhook.go b/pkg/webhooks/openstackcluster_webhook.go
index d5a68c6ae5..194933c3d6 100644
--- a/pkg/webhooks/openstackcluster_webhook.go
+++ b/pkg/webhooks/openstackcluster_webhook.go
@@ -23,7 +23,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
- "k8s.io/utils/pointer"
+ "k8s.io/utils/ptr"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/manager"
"sigs.k8s.io/controller-runtime/pkg/webhook"
@@ -98,13 +98,13 @@ func (*openStackClusterWebhook) ValidateUpdate(_ context.Context, oldObjRaw, new
}
// Allow change only for the first time.
- if pointer.BoolDeref(oldObj.Spec.DisableAPIServerFloatingIP, false) && pointer.StringDeref(oldObj.Spec.APIServerFixedIP, "") == "" {
+ if ptr.Deref(oldObj.Spec.DisableAPIServerFloatingIP, false) && ptr.Deref(oldObj.Spec.APIServerFixedIP, "") == "" {
oldObj.Spec.APIServerFixedIP = nil
newObj.Spec.APIServerFixedIP = nil
}
// If API Server floating IP is disabled, allow the change of the API Server port only for the first time.
- if pointer.BoolDeref(oldObj.Spec.DisableAPIServerFloatingIP, false) && oldObj.Spec.APIServerPort == nil && newObj.Spec.APIServerPort != nil {
+ if ptr.Deref(oldObj.Spec.DisableAPIServerFloatingIP, false) && oldObj.Spec.APIServerPort == nil && newObj.Spec.APIServerPort != nil {
newObj.Spec.APIServerPort = nil
}
@@ -145,7 +145,7 @@ func (*openStackClusterWebhook) ValidateUpdate(_ context.Context, oldObjRaw, new
newObj.Spec.ControlPlaneOmitAvailabilityZone = nil
// Allow change on the spec.APIServerFloatingIP only if it matches the current api server loadbalancer IP.
- if oldObj.Status.APIServerLoadBalancer != nil && pointer.StringDeref(newObj.Spec.APIServerFloatingIP, "") == oldObj.Status.APIServerLoadBalancer.IP {
+ if oldObj.Status.APIServerLoadBalancer != nil && ptr.Deref(newObj.Spec.APIServerFloatingIP, "") == oldObj.Status.APIServerLoadBalancer.IP {
newObj.Spec.APIServerFloatingIP = nil
oldObj.Spec.APIServerFloatingIP = nil
}
diff --git a/pkg/webhooks/openstackcluster_webhook_test.go b/pkg/webhooks/openstackcluster_webhook_test.go
index d42b6eb1ce..edd60296a3 100644
--- a/pkg/webhooks/openstackcluster_webhook_test.go
+++ b/pkg/webhooks/openstackcluster_webhook_test.go
@@ -21,7 +21,7 @@ import (
"testing"
. "github.com/onsi/gomega"
- "k8s.io/utils/pointer"
+ "k8s.io/utils/ptr"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
)
@@ -87,12 +87,12 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
Spec: &infrav1.OpenStackMachineSpec{
Image: infrav1.ImageParam{
Filter: &infrav1.ImageFilter{
- Name: pointer.String("foobar"),
+ Name: ptr.To("foobar"),
},
},
Flavor: "minimal",
},
- Enabled: pointer.Bool(true),
+ Enabled: ptr.To(true),
},
},
Status: infrav1.OpenStackClusterStatus{
@@ -111,12 +111,12 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
Spec: &infrav1.OpenStackMachineSpec{
Image: infrav1.ImageParam{
Filter: &infrav1.ImageFilter{
- Name: pointer.String("foobarbaz"),
+ Name: ptr.To("foobarbaz"),
},
},
Flavor: "medium",
},
- Enabled: pointer.Bool(true),
+ Enabled: ptr.To(true),
},
},
},
@@ -134,10 +134,10 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
AllNodesSecurityGroupRules: []infrav1.SecurityGroupRuleSpec{
{
Name: "foobar",
- Description: pointer.String("foobar"),
- PortRangeMin: pointer.Int(80),
- PortRangeMax: pointer.Int(80),
- Protocol: pointer.String("tcp"),
+ Description: ptr.To("foobar"),
+ PortRangeMin: ptr.To(80),
+ PortRangeMax: ptr.To(80),
+ Protocol: ptr.To("tcp"),
RemoteManagedGroups: []infrav1.ManagedSecurityGroupName{"controlplane"},
},
},
@@ -154,10 +154,10 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
AllNodesSecurityGroupRules: []infrav1.SecurityGroupRuleSpec{
{
Name: "foobar",
- Description: pointer.String("foobar"),
- PortRangeMin: pointer.Int(80),
- PortRangeMax: pointer.Int(80),
- Protocol: pointer.String("tcp"),
+ Description: ptr.To("foobar"),
+ PortRangeMin: ptr.To(80),
+ PortRangeMax: ptr.To(80),
+ Protocol: ptr.To("tcp"),
RemoteManagedGroups: []infrav1.ManagedSecurityGroupName{"controlplane", "worker"},
},
},
@@ -175,7 +175,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
CloudName: "foobar",
},
APIServerLoadBalancer: &infrav1.APIServerLoadBalancer{
- Enabled: pointer.Bool(true),
+ Enabled: ptr.To(true),
AllowedCIDRs: []string{
"0.0.0.0/0",
"192.168.10.0/24",
@@ -190,7 +190,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
CloudName: "foobar",
},
APIServerLoadBalancer: &infrav1.APIServerLoadBalancer{
- Enabled: pointer.Bool(true),
+ Enabled: ptr.To(true),
AllowedCIDRs: []string{
"0.0.0.0/0",
"192.168.10.0/24",
@@ -294,7 +294,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
Name: "foobar",
CloudName: "foobar",
},
- ControlPlaneOmitAvailabilityZone: pointer.Bool(true),
+ ControlPlaneOmitAvailabilityZone: ptr.To(true),
},
},
wantErr: false,
@@ -307,7 +307,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
Name: "foobar",
CloudName: "foobar",
},
- DisableAPIServerFloatingIP: pointer.Bool(true),
+ DisableAPIServerFloatingIP: ptr.To(true),
},
},
newTemplate: &infrav1.OpenStackCluster{
@@ -316,8 +316,8 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
Name: "foobar",
CloudName: "foobar",
},
- DisableAPIServerFloatingIP: pointer.Bool(true),
- APIServerFixedIP: pointer.String("20.1.56.1"),
+ DisableAPIServerFloatingIP: ptr.To(true),
+ APIServerFixedIP: ptr.To("20.1.56.1"),
},
},
wantErr: false,
@@ -330,7 +330,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
Name: "foobar",
CloudName: "foobar",
},
- DisableAPIServerFloatingIP: pointer.Bool(false),
+ DisableAPIServerFloatingIP: ptr.To(false),
},
},
newTemplate: &infrav1.OpenStackCluster{
@@ -339,8 +339,8 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
Name: "foobar",
CloudName: "foobar",
},
- DisableAPIServerFloatingIP: pointer.Bool(false),
- APIServerFixedIP: pointer.String("20.1.56.1"),
+ DisableAPIServerFloatingIP: ptr.To(false),
+ APIServerFixedIP: ptr.To("20.1.56.1"),
},
},
wantErr: true,
@@ -354,13 +354,13 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
Name: "foobar",
CloudName: "foobar",
},
- DisableAPIServerFloatingIP: pointer.Bool(true),
+ DisableAPIServerFloatingIP: ptr.To(true),
},
},
newTemplate: &infrav1.OpenStackCluster{
Spec: infrav1.OpenStackClusterSpec{
- DisableAPIServerFloatingIP: pointer.Bool(true),
- APIServerPort: pointer.Int(8443),
+ DisableAPIServerFloatingIP: ptr.To(true),
+ APIServerPort: ptr.To(8443),
},
},
wantErr: false,
@@ -373,7 +373,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
Name: "foobar",
CloudName: "foobar",
},
- DisableAPIServerFloatingIP: pointer.Bool(false),
+ DisableAPIServerFloatingIP: ptr.To(false),
},
},
newTemplate: &infrav1.OpenStackCluster{
@@ -382,8 +382,8 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
Name: "foobar",
CloudName: "foobar",
},
- DisableAPIServerFloatingIP: pointer.Bool(false),
- APIServerPort: pointer.Int(8443),
+ DisableAPIServerFloatingIP: ptr.To(false),
+ APIServerPort: ptr.To(8443),
},
},
wantErr: true,
@@ -409,7 +409,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
Name: "foobar",
CloudName: "foobar",
},
- APIServerFloatingIP: pointer.String("1.2.3.4"),
+ APIServerFloatingIP: ptr.To("1.2.3.4"),
},
Status: infrav1.OpenStackClusterStatus{
APIServerLoadBalancer: &infrav1.LoadBalancer{
@@ -440,7 +440,7 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
Name: "foobar",
CloudName: "foobar",
},
- APIServerFloatingIP: pointer.String("5.6.7.8"),
+ APIServerFloatingIP: ptr.To("5.6.7.8"),
},
Status: infrav1.OpenStackClusterStatus{
APIServerLoadBalancer: &infrav1.LoadBalancer{
@@ -459,12 +459,12 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
CloudName: "foobar",
},
Bastion: &infrav1.Bastion{
- Enabled: pointer.Bool(true),
+ Enabled: ptr.To(true),
Spec: &infrav1.OpenStackMachineSpec{
Flavor: "m1.small",
Image: infrav1.ImageParam{
Filter: &infrav1.ImageFilter{
- Name: pointer.String("ubuntu"),
+ Name: ptr.To("ubuntu"),
},
},
},
@@ -490,12 +490,12 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) {
CloudName: "foobar",
},
Bastion: &infrav1.Bastion{
- Enabled: pointer.Bool(false),
+ Enabled: ptr.To(false),
Spec: &infrav1.OpenStackMachineSpec{
Flavor: "m1.small",
Image: infrav1.ImageParam{
Filter: &infrav1.ImageFilter{
- Name: pointer.String("ubuntu"),
+ Name: ptr.To("ubuntu"),
},
},
},
@@ -561,10 +561,10 @@ func TestOpenStackCluster_ValidateCreate(t *testing.T) {
AllNodesSecurityGroupRules: []infrav1.SecurityGroupRuleSpec{
{
Name: "foobar",
- Description: pointer.String("foobar"),
- PortRangeMin: pointer.Int(80),
- PortRangeMax: pointer.Int(80),
- Protocol: pointer.String("tcp"),
+ Description: ptr.To("foobar"),
+ PortRangeMin: ptr.To(80),
+ PortRangeMax: ptr.To(80),
+ Protocol: ptr.To("tcp"),
},
},
},
@@ -584,12 +584,12 @@ func TestOpenStackCluster_ValidateCreate(t *testing.T) {
AllNodesSecurityGroupRules: []infrav1.SecurityGroupRuleSpec{
{
Name: "foobar",
- Description: pointer.String("foobar"),
- PortRangeMin: pointer.Int(80),
- PortRangeMax: pointer.Int(80),
- Protocol: pointer.String("tcp"),
+ Description: ptr.To("foobar"),
+ PortRangeMin: ptr.To(80),
+ PortRangeMax: ptr.To(80),
+ Protocol: ptr.To("tcp"),
RemoteManagedGroups: []infrav1.ManagedSecurityGroupName{"controlplane"},
- RemoteGroupID: pointer.String("foobar"),
+ RemoteGroupID: ptr.To("foobar"),
},
},
},
diff --git a/pkg/webhooks/openstackmachinetemplate_webhook_test.go b/pkg/webhooks/openstackmachinetemplate_webhook_test.go
index 6b148f3bfa..1d767c1142 100644
--- a/pkg/webhooks/openstackmachinetemplate_webhook_test.go
+++ b/pkg/webhooks/openstackmachinetemplate_webhook_test.go
@@ -23,7 +23,7 @@ import (
. "github.com/onsi/gomega"
admissionv1 "k8s.io/api/admission/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/controller-runtime/pkg/webhook/admission"
@@ -49,7 +49,7 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) {
Flavor: "foo",
Image: infrav1.ImageParam{
Filter: &infrav1.ImageFilter{
- Name: pointer.String("bar"),
+ Name: ptr.To("bar"),
},
},
},
@@ -63,7 +63,7 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) {
Flavor: "foo",
Image: infrav1.ImageParam{
Filter: &infrav1.ImageFilter{
- Name: pointer.String("NewImage"),
+ Name: ptr.To("NewImage"),
},
},
},
@@ -82,7 +82,7 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) {
Flavor: "foo",
Image: infrav1.ImageParam{
Filter: &infrav1.ImageFilter{
- Name: pointer.String("bar"),
+ Name: ptr.To("bar"),
},
},
},
@@ -99,7 +99,7 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) {
Flavor: "foo",
Image: infrav1.ImageParam{
Filter: &infrav1.ImageFilter{
- Name: pointer.String("bar"),
+ Name: ptr.To("bar"),
},
},
},
@@ -120,7 +120,7 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) {
Flavor: "foo",
Image: infrav1.ImageParam{
Filter: &infrav1.ImageFilter{
- Name: pointer.String("bar"),
+ Name: ptr.To("bar"),
},
},
},
@@ -134,14 +134,14 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) {
Flavor: "foo",
Image: infrav1.ImageParam{
Filter: &infrav1.ImageFilter{
- Name: pointer.String("NewImage"),
+ Name: ptr.To("NewImage"),
},
},
},
},
},
},
- req: &admission.Request{AdmissionRequest: admissionv1.AdmissionRequest{DryRun: pointer.Bool(true)}},
+ req: &admission.Request{AdmissionRequest: admissionv1.AdmissionRequest{DryRun: ptr.To(true)}},
wantErr: true,
},
{
@@ -153,7 +153,7 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) {
Flavor: "foo",
Image: infrav1.ImageParam{
Filter: &infrav1.ImageFilter{
- Name: pointer.String("bar"),
+ Name: ptr.To("bar"),
},
},
},
@@ -172,14 +172,14 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) {
Flavor: "foo",
Image: infrav1.ImageParam{
Filter: &infrav1.ImageFilter{
- Name: pointer.String("NewImage"),
+ Name: ptr.To("NewImage"),
},
},
},
},
},
},
- req: &admission.Request{AdmissionRequest: admissionv1.AdmissionRequest{DryRun: pointer.Bool(true)}},
+ req: &admission.Request{AdmissionRequest: admissionv1.AdmissionRequest{DryRun: ptr.To(true)}},
},
}
diff --git a/test/e2e/suites/apivalidations/filters_test.go b/test/e2e/suites/apivalidations/filters_test.go
index 08b8cdfccd..d51bb924bb 100644
--- a/test/e2e/suites/apivalidations/filters_test.go
+++ b/test/e2e/suites/apivalidations/filters_test.go
@@ -20,7 +20,7 @@ import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
- "k8s.io/utils/pointer"
+ "k8s.io/utils/ptr"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
)
@@ -38,7 +38,7 @@ var _ = Describe("Filter API validations", func() {
// Initialise a basic machine object in the correct namespace
machine = &infrav1.OpenStackMachine{
Spec: infrav1.OpenStackMachineSpec{
- Image: infrav1.ImageParam{Filter: &infrav1.ImageFilter{Name: pointer.String("test-image")}},
+ Image: infrav1.ImageParam{Filter: &infrav1.ImageFilter{Name: ptr.To("test-image")}},
},
}
machine.Namespace = namespace.Name
@@ -188,9 +188,9 @@ var _ = Describe("Filter API validations", func() {
It("should not allow both ID and Filter to be set", func() {
machine.Spec.Image = infrav1.ImageParam{
- ID: pointer.String(imageUUID),
+ ID: ptr.To(imageUUID),
Filter: &infrav1.ImageFilter{
- Name: pointer.String("bar"),
+ Name: ptr.To("bar"),
},
}
Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail")
@@ -198,7 +198,7 @@ var _ = Describe("Filter API validations", func() {
It("should not allow both ID and Tags of ImageFilter to be set", func() {
machine.Spec.Image = infrav1.ImageParam{
- ID: pointer.String(imageUUID),
+ ID: ptr.To(imageUUID),
Filter: &infrav1.ImageFilter{
Tags: []string{"bar", "baz"},
},
@@ -208,14 +208,14 @@ var _ = Describe("Filter API validations", func() {
It("should allow UUID ID of ImageFilter to be set", func() {
machine.Spec.Image = infrav1.ImageParam{
- ID: pointer.String(imageUUID),
+ ID: ptr.To(imageUUID),
}
Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "OpenStackMachine creation should succeed")
})
It("should not allow non-UUID ID of ImageFilter to be set", func() {
machine.Spec.Image = infrav1.ImageParam{
- ID: pointer.String("foo"),
+ ID: ptr.To("foo"),
}
Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail")
})
@@ -223,7 +223,7 @@ var _ = Describe("Filter API validations", func() {
It("should allow Name and Tags of ImageFilter to be set", func() {
machine.Spec.Image = infrav1.ImageParam{
Filter: &infrav1.ImageFilter{
- Name: pointer.String("bar"),
+ Name: ptr.To("bar"),
Tags: []string{"bar", "baz"},
},
}
@@ -241,7 +241,7 @@ var _ = Describe("Filter API validations", func() {
Context("NetworkParam", func() {
It("should allow setting ID", func() {
cluster.Spec.Network = &infrav1.NetworkParam{
- ID: pointer.String("06c32c52-f207-4f6a-a769-bbcbe5a43f5c"),
+ ID: ptr.To("06c32c52-f207-4f6a-a769-bbcbe5a43f5c"),
}
Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
})
@@ -260,7 +260,7 @@ var _ = Describe("Filter API validations", func() {
It("should not allow setting invalid id", func() {
cluster.Spec.Network = &infrav1.NetworkParam{
- ID: pointer.String("foo"),
+ ID: ptr.To("foo"),
}
Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should fail")
})
@@ -274,7 +274,7 @@ var _ = Describe("Filter API validations", func() {
It("should not allow setting both ID and Filter", func() {
cluster.Spec.Network = &infrav1.NetworkParam{
- ID: pointer.String("06c32c52-f207-4f6a-a769-bbcbe5a43f5c"), Filter: &infrav1.NetworkFilter{Name: "foo"},
+ ID: ptr.To("06c32c52-f207-4f6a-a769-bbcbe5a43f5c"), Filter: &infrav1.NetworkFilter{Name: "foo"},
}
Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should fail")
})
@@ -283,7 +283,7 @@ var _ = Describe("Filter API validations", func() {
Context("SubnetParam", func() {
It("should allow setting ID", func() {
cluster.Spec.Subnets = []infrav1.SubnetParam{
- {ID: pointer.String("06c32c52-f207-4f6a-a769-bbcbe5a43f5c")},
+ {ID: ptr.To("06c32c52-f207-4f6a-a769-bbcbe5a43f5c")},
}
Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
})
@@ -302,7 +302,7 @@ var _ = Describe("Filter API validations", func() {
It("should not allow setting invalid id", func() {
cluster.Spec.Subnets = []infrav1.SubnetParam{
- {ID: pointer.String("foo")},
+ {ID: ptr.To("foo")},
}
Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should fail")
})
@@ -316,7 +316,7 @@ var _ = Describe("Filter API validations", func() {
It("should not allow setting both ID and Filter", func() {
cluster.Spec.Subnets = []infrav1.SubnetParam{
- {ID: pointer.String("06c32c52-f207-4f6a-a769-bbcbe5a43f5c"), Filter: &infrav1.SubnetFilter{Name: "foo"}},
+ {ID: ptr.To("06c32c52-f207-4f6a-a769-bbcbe5a43f5c"), Filter: &infrav1.SubnetFilter{Name: "foo"}},
}
Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should fail")
})
@@ -325,7 +325,7 @@ var _ = Describe("Filter API validations", func() {
Context("SecurityGroupParam", func() {
It("should allow setting ID", func() {
machine.Spec.SecurityGroups = []infrav1.SecurityGroupParam{
- {ID: pointer.String("06c32c52-f207-4f6a-a769-bbcbe5a43f5c")},
+ {ID: ptr.To("06c32c52-f207-4f6a-a769-bbcbe5a43f5c")},
}
Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "OpenStackMachine creation should succeed")
})
@@ -344,7 +344,7 @@ var _ = Describe("Filter API validations", func() {
It("should not allow setting invalid id", func() {
machine.Spec.SecurityGroups = []infrav1.SecurityGroupParam{
- {ID: pointer.String("foo")},
+ {ID: ptr.To("foo")},
}
Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail")
})
@@ -358,7 +358,7 @@ var _ = Describe("Filter API validations", func() {
It("should not allow setting both ID and Filter", func() {
machine.Spec.SecurityGroups = []infrav1.SecurityGroupParam{
- {ID: pointer.String("06c32c52-f207-4f6a-a769-bbcbe5a43f5c"), Filter: &infrav1.SecurityGroupFilter{Name: "foo"}},
+ {ID: ptr.To("06c32c52-f207-4f6a-a769-bbcbe5a43f5c"), Filter: &infrav1.SecurityGroupFilter{Name: "foo"}},
}
Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail")
})
@@ -367,7 +367,7 @@ var _ = Describe("Filter API validations", func() {
Context("RouterParam", func() {
It("should allow setting ID", func() {
cluster.Spec.Router = &infrav1.RouterParam{
- ID: pointer.String("06c32c52-f207-4f6a-a769-bbcbe5a43f5c"),
+ ID: ptr.To("06c32c52-f207-4f6a-a769-bbcbe5a43f5c"),
}
Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
})
@@ -386,7 +386,7 @@ var _ = Describe("Filter API validations", func() {
It("should not allow setting invalid id", func() {
cluster.Spec.Router = &infrav1.RouterParam{
- ID: pointer.String("foo"),
+ ID: ptr.To("foo"),
}
Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should fail")
})
@@ -400,7 +400,7 @@ var _ = Describe("Filter API validations", func() {
It("should not allow setting both ID and Filter", func() {
cluster.Spec.Router = &infrav1.RouterParam{
- ID: pointer.String("06c32c52-f207-4f6a-a769-bbcbe5a43f5c"),
+ ID: ptr.To("06c32c52-f207-4f6a-a769-bbcbe5a43f5c"),
Filter: &infrav1.RouterFilter{Name: "foo"},
}
Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should fail")
@@ -409,12 +409,12 @@ var _ = Describe("Filter API validations", func() {
Context("ServerGroupParam", func() {
It("should allow setting ID", func() {
- machine.Spec.ServerGroup = &infrav1.ServerGroupParam{ID: pointer.String("06c32c52-f207-4f6a-a769-bbcbe5a43f5c")}
+ machine.Spec.ServerGroup = &infrav1.ServerGroupParam{ID: ptr.To("06c32c52-f207-4f6a-a769-bbcbe5a43f5c")}
Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "OpenStackMachine creation should succeed")
})
It("should allow setting non-empty Filter", func() {
- machine.Spec.ServerGroup = &infrav1.ServerGroupParam{Filter: &infrav1.ServerGroupFilter{Name: pointer.String("foo")}}
+ machine.Spec.ServerGroup = &infrav1.ServerGroupParam{Filter: &infrav1.ServerGroupFilter{Name: ptr.To("foo")}}
Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "OpenStackMachine creation should succeed")
})
@@ -424,7 +424,7 @@ var _ = Describe("Filter API validations", func() {
})
It("should not allow setting invalid id", func() {
- machine.Spec.ServerGroup = &infrav1.ServerGroupParam{ID: pointer.String("foo")}
+ machine.Spec.ServerGroup = &infrav1.ServerGroupParam{ID: ptr.To("foo")}
Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail")
})
@@ -435,8 +435,8 @@ var _ = Describe("Filter API validations", func() {
It("should not allow setting both ID and Filter", func() {
machine.Spec.ServerGroup = &infrav1.ServerGroupParam{
- ID: pointer.String("06c32c52-f207-4f6a-a769-bbcbe5a43f5c"),
- Filter: &infrav1.ServerGroupFilter{Name: pointer.String("foo")},
+ ID: ptr.To("06c32c52-f207-4f6a-a769-bbcbe5a43f5c"),
+ Filter: &infrav1.ServerGroupFilter{Name: ptr.To("foo")},
}
Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail")
})
diff --git a/test/e2e/suites/apivalidations/openstackcluster_test.go b/test/e2e/suites/apivalidations/openstackcluster_test.go
index d05a21c732..33657eb00d 100644
--- a/test/e2e/suites/apivalidations/openstackcluster_test.go
+++ b/test/e2e/suites/apivalidations/openstackcluster_test.go
@@ -21,7 +21,7 @@ import (
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
- "k8s.io/utils/pointer"
+ "k8s.io/utils/ptr"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -105,11 +105,11 @@ var _ = Describe("OpenStackCluster API validations", func() {
It("should allow bastion.enabled=true with a spec", func() {
cluster.Spec.Bastion = &infrav1.Bastion{
- Enabled: pointer.Bool(true),
+ Enabled: ptr.To(true),
Spec: &infrav1.OpenStackMachineSpec{
Image: infrav1.ImageParam{
Filter: &infrav1.ImageFilter{
- Name: pointer.String("fake-image"),
+ Name: ptr.To("fake-image"),
},
},
},
@@ -119,7 +119,7 @@ var _ = Describe("OpenStackCluster API validations", func() {
It("should not allow bastion.enabled=true without a spec", func() {
cluster.Spec.Bastion = &infrav1.Bastion{
- Enabled: pointer.Bool(true),
+ Enabled: ptr.To(true),
}
Expect(create(cluster)).NotTo(Succeed(), "OpenStackCluster creation should not succeed")
})
@@ -134,7 +134,7 @@ var _ = Describe("OpenStackCluster API validations", func() {
Spec: &infrav1.OpenStackMachineSpec{
Image: infrav1.ImageParam{
Filter: &infrav1.ImageFilter{
- Name: pointer.String("fake-image"),
+ Name: ptr.To("fake-image"),
},
},
},
@@ -150,15 +150,15 @@ var _ = Describe("OpenStackCluster API validations", func() {
It("should allow IPv4 as bastion floatingIP", func() {
cluster.Spec.Bastion = &infrav1.Bastion{
- Enabled: pointer.Bool(true),
+ Enabled: ptr.To(true),
Spec: &infrav1.OpenStackMachineSpec{
Image: infrav1.ImageParam{
Filter: &infrav1.ImageFilter{
- Name: pointer.String("fake-image"),
+ Name: ptr.To("fake-image"),
},
},
},
- FloatingIP: pointer.String("10.0.0.0"),
+ FloatingIP: ptr.To("10.0.0.0"),
}
Expect(create(cluster)).To(Succeed(), "OpenStackCluster creation should succeed")
})
@@ -168,11 +168,11 @@ var _ = Describe("OpenStackCluster API validations", func() {
Spec: &infrav1.OpenStackMachineSpec{
Image: infrav1.ImageParam{
Filter: &infrav1.ImageFilter{
- Name: pointer.String("fake-image"),
+ Name: ptr.To("fake-image"),
},
},
},
- FloatingIP: pointer.String("foobar"),
+ FloatingIP: ptr.To("foobar"),
}
Expect(create(cluster)).NotTo(Succeed(), "OpenStackCluster creation should not succeed")
})
diff --git a/test/e2e/suites/apivalidations/openstackmachine_test.go b/test/e2e/suites/apivalidations/openstackmachine_test.go
index 4e888a3a41..f8ad67970a 100644
--- a/test/e2e/suites/apivalidations/openstackmachine_test.go
+++ b/test/e2e/suites/apivalidations/openstackmachine_test.go
@@ -22,7 +22,7 @@ import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
- "k8s.io/utils/pointer"
+ "k8s.io/utils/ptr"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
)
@@ -37,7 +37,7 @@ var _ = Describe("OpenStackMachine API validations", func() {
// Initialise a basic machine object in the correct namespace
machine = &infrav1.OpenStackMachine{
Spec: infrav1.OpenStackMachineSpec{
- Image: infrav1.ImageParam{Filter: &infrav1.ImageFilter{Name: pointer.String("test-image")}},
+ Image: infrav1.ImageParam{Filter: &infrav1.ImageFilter{Name: ptr.To("test-image")}},
},
}
machine.Namespace = namespace.Name
@@ -53,11 +53,11 @@ var _ = Describe("OpenStackMachine API validations", func() {
Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "OpenStackMachine creation should succeed")
By("Setting the providerID")
- machine.Spec.ProviderID = pointer.String("foo")
+ machine.Spec.ProviderID = ptr.To("foo")
Expect(k8sClient.Update(ctx, machine)).To(Succeed(), "Setting providerID should succeed")
By("Modifying the providerID")
- machine.Spec.ProviderID = pointer.String("bar")
+ machine.Spec.ProviderID = ptr.To("bar")
Expect(k8sClient.Update(ctx, machine)).NotTo(Succeed(), "Updating providerID should fail")
})
diff --git a/test/e2e/suites/conformance/conformance_test.go b/test/e2e/suites/conformance/conformance_test.go
index 02019422fc..25a5cc2f22 100644
--- a/test/e2e/suites/conformance/conformance_test.go
+++ b/test/e2e/suites/conformance/conformance_test.go
@@ -28,7 +28,7 @@ import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
- "k8s.io/utils/pointer"
+ "k8s.io/utils/ptr"
"sigs.k8s.io/cluster-api/test/framework/clusterctl"
"sigs.k8s.io/cluster-api/test/framework/kubernetesversions"
"sigs.k8s.io/cluster-api/test/framework/kubetest"
@@ -81,8 +81,8 @@ var _ = Describe("conformance tests", func() {
Namespace: namespace.Name,
ClusterName: name,
KubernetesVersion: kubernetesVersion,
- ControlPlaneMachineCount: pointer.Int64(controlPlaneMachineCount),
- WorkerMachineCount: pointer.Int64(workerMachineCount),
+ ControlPlaneMachineCount: ptr.To(controlPlaneMachineCount),
+ WorkerMachineCount: ptr.To(workerMachineCount),
},
WaitForClusterIntervals: e2eCtx.E2EConfig.GetIntervals(specName, "wait-cluster"),
WaitForControlPlaneIntervals: e2eCtx.E2EConfig.GetIntervals(specName, "wait-control-plane"),
diff --git a/test/e2e/suites/e2e/e2e_test.go b/test/e2e/suites/e2e/e2e_test.go
index 78ddf8b55a..09ee609346 100644
--- a/test/e2e/suites/e2e/e2e_test.go
+++ b/test/e2e/suites/e2e/e2e_test.go
@@ -45,7 +45,7 @@ import (
apimachinerytypes "k8s.io/apimachinery/pkg/types"
utilrand "k8s.io/apimachinery/pkg/util/rand"
"k8s.io/apimachinery/pkg/util/sets"
- "k8s.io/utils/pointer"
+ "k8s.io/utils/ptr"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
bootstrapv1 "sigs.k8s.io/cluster-api/bootstrap/kubeadm/api/v1beta1"
"sigs.k8s.io/cluster-api/controllers/noderefutil"
@@ -85,8 +85,8 @@ var _ = Describe("e2e tests [PR-Blocking]", func() {
shared.Logf("Creating a cluster")
clusterName := fmt.Sprintf("cluster-%s", namespace.Name)
configCluster := defaultConfigCluster(clusterName, namespace.Name)
- configCluster.ControlPlaneMachineCount = pointer.Int64(1)
- configCluster.WorkerMachineCount = pointer.Int64(1)
+ configCluster.ControlPlaneMachineCount = ptr.To(int64(1))
+ configCluster.WorkerMachineCount = ptr.To(int64(1))
configCluster.Flavor = shared.FlavorDefault
createCluster(ctx, configCluster, clusterResources)
md := clusterResources.MachineDeployments
@@ -176,7 +176,7 @@ var _ = Describe("e2e tests [PR-Blocking]", func() {
openStackCluster, err = shared.ClusterForSpec(ctx, e2eCtx, namespace)
Expect(err).NotTo(HaveOccurred())
openStackClusterDisabledBastion := openStackCluster.DeepCopy()
- openStackClusterDisabledBastion.Spec.Bastion.Enabled = pointer.Bool(false)
+ openStackClusterDisabledBastion.Spec.Bastion.Enabled = ptr.To(false)
Expect(e2eCtx.Environment.BootstrapClusterProxy.GetClient().Update(ctx, openStackClusterDisabledBastion)).To(Succeed())
Eventually(
func() (bool, error) {
@@ -253,8 +253,8 @@ var _ = Describe("e2e tests [PR-Blocking]", func() {
shared.Logf("Creating a cluster")
clusterName := fmt.Sprintf("cluster-%s", namespace.Name)
configCluster := defaultConfigCluster(clusterName, namespace.Name)
- configCluster.ControlPlaneMachineCount = pointer.Int64(1)
- configCluster.WorkerMachineCount = pointer.Int64(1)
+ configCluster.ControlPlaneMachineCount = ptr.To(int64(1))
+ configCluster.WorkerMachineCount = ptr.To(int64(1))
configCluster.Flavor = shared.FlavorFlatcar
createCluster(ctx, configCluster, clusterResources)
md := clusterResources.MachineDeployments
@@ -298,8 +298,8 @@ var _ = Describe("e2e tests [PR-Blocking]", func() {
shared.Logf("Creating a cluster")
clusterName := fmt.Sprintf("cluster-%s", namespace.Name)
configCluster := defaultConfigCluster(clusterName, namespace.Name)
- configCluster.ControlPlaneMachineCount = pointer.Int64(1)
- configCluster.WorkerMachineCount = pointer.Int64(1)
+ configCluster.ControlPlaneMachineCount = ptr.To(int64(1))
+ configCluster.WorkerMachineCount = ptr.To(int64(1))
configCluster.Flavor = shared.FlavorFlatcarSysext
createCluster(ctx, configCluster, clusterResources)
md := clusterResources.MachineDeployments
@@ -340,8 +340,8 @@ var _ = Describe("e2e tests [PR-Blocking]", func() {
shared.Logf("Creating a cluster")
clusterName := fmt.Sprintf("cluster-%s", namespace.Name)
configCluster := defaultConfigCluster(clusterName, namespace.Name)
- configCluster.ControlPlaneMachineCount = pointer.Int64(1)
- configCluster.WorkerMachineCount = pointer.Int64(1)
+ configCluster.ControlPlaneMachineCount = ptr.To(int64(1))
+ configCluster.WorkerMachineCount = ptr.To(int64(1))
configCluster.Flavor = shared.FlavorWithoutLB
createCluster(ctx, configCluster, clusterResources)
md := clusterResources.MachineDeployments
@@ -372,11 +372,11 @@ var _ = Describe("e2e tests [PR-Blocking]", func() {
customPortOptions := &[]infrav1.PortOpts{
{
- Description: pointer.String("primary"),
+ Description: ptr.To("primary"),
},
{
- Description: pointer.String("trunked"),
- Trunk: pointer.Bool(true),
+ Description: ptr.To("trunked"),
+ Trunk: ptr.To(true),
},
{
SecurityGroups: []infrav1.SecurityGroupParam{{Filter: &infrav1.SecurityGroupFilter{Name: testSecurityGroupName}}},
@@ -474,8 +474,8 @@ var _ = Describe("e2e tests [PR-Blocking]", func() {
shared.Logf("Creating a cluster")
clusterName = fmt.Sprintf("cluster-%s", namespace.Name)
configCluster = defaultConfigCluster(clusterName, namespace.Name)
- configCluster.ControlPlaneMachineCount = pointer.Int64(1)
- configCluster.WorkerMachineCount = pointer.Int64(1)
+ configCluster.ControlPlaneMachineCount = ptr.To(int64(1))
+ configCluster.WorkerMachineCount = ptr.To(int64(1))
configCluster.Flavor = shared.FlavorMultiNetwork
createCluster(ctx, configCluster, clusterResources)
md = clusterResources.MachineDeployments
@@ -559,8 +559,8 @@ var _ = Describe("e2e tests [PR-Blocking]", func() {
shared.Logf("Creating a cluster")
clusterName := fmt.Sprintf("cluster-%s", namespace.Name)
configCluster := defaultConfigCluster(clusterName, namespace.Name)
- configCluster.ControlPlaneMachineCount = pointer.Int64(1)
- configCluster.WorkerMachineCount = pointer.Int64(0)
+ configCluster.ControlPlaneMachineCount = ptr.To(int64(1))
+ configCluster.WorkerMachineCount = ptr.To(int64(0))
configCluster.Flavor = shared.FlavorWithoutLB
createCluster(ctx, configCluster, clusterResources)
@@ -612,8 +612,8 @@ var _ = Describe("e2e tests [PR-Blocking]", func() {
shared.Logf("Creating a cluster")
clusterName = fmt.Sprintf("cluster-%s", namespace.Name)
configCluster := defaultConfigCluster(clusterName, namespace.Name)
- configCluster.ControlPlaneMachineCount = pointer.Int64(3)
- configCluster.WorkerMachineCount = pointer.Int64(2)
+ configCluster.ControlPlaneMachineCount = ptr.To(int64(3))
+ configCluster.WorkerMachineCount = ptr.To(int64(2))
configCluster.Flavor = shared.FlavorMultiAZ
createCluster(ctx, configCluster, clusterResources)
md = clusterResources.MachineDeployments
@@ -861,7 +861,7 @@ func makeOpenStackMachineTemplate(namespace, clusterName, name string) *infrav1.
Flavor: e2eCtx.E2EConfig.GetVariable(shared.OpenStackNodeMachineFlavor),
Image: infrav1.ImageParam{
Filter: &infrav1.ImageFilter{
- Name: pointer.String(e2eCtx.E2EConfig.GetVariable(shared.OpenStackImageName)),
+ Name: ptr.To(e2eCtx.E2EConfig.GetVariable(shared.OpenStackImageName)),
},
},
SSHKeyName: shared.DefaultSSHKeyPairName,
@@ -887,7 +887,7 @@ func makeOpenStackMachineTemplateWithPortOptions(namespace, clusterName, name st
Flavor: e2eCtx.E2EConfig.GetVariable(shared.OpenStackNodeMachineFlavor),
Image: infrav1.ImageParam{
Filter: &infrav1.ImageFilter{
- Name: pointer.String(e2eCtx.E2EConfig.GetVariable(shared.OpenStackImageName)),
+ Name: ptr.To(e2eCtx.E2EConfig.GetVariable(shared.OpenStackImageName)),
},
},
SSHKeyName: shared.DefaultSSHKeyPairName,
@@ -976,7 +976,7 @@ func makeMachineDeployment(namespace, mdName, clusterName string, failureDomain
Name: mdName,
Namespace: namespace,
},
- Version: pointer.String(e2eCtx.E2EConfig.GetVariable(shared.KubernetesVersion)),
+ Version: ptr.To(e2eCtx.E2EConfig.GetVariable(shared.KubernetesVersion)),
},
},
},
diff --git a/test/e2e/suites/e2e/remediations_test.go b/test/e2e/suites/e2e/remediations_test.go
index e047dd498f..c4a4e0d1f8 100644
--- a/test/e2e/suites/e2e/remediations_test.go
+++ b/test/e2e/suites/e2e/remediations_test.go
@@ -23,7 +23,7 @@ import (
"context"
. "github.com/onsi/ginkgo/v2"
- "k8s.io/utils/pointer"
+ "k8s.io/utils/ptr"
capi_e2e "sigs.k8s.io/cluster-api/test/e2e"
"sigs.k8s.io/cluster-api-provider-openstack/test/e2e/shared"
@@ -39,7 +39,7 @@ var _ = Describe("When testing unhealthy machines remediation", func() {
BootstrapClusterProxy: e2eCtx.Environment.BootstrapClusterProxy,
ArtifactFolder: e2eCtx.Settings.ArtifactFolder,
SkipCleanup: false,
- Flavor: pointer.String(shared.FlavorMDRemediation),
+ Flavor: ptr.To(shared.FlavorMDRemediation),
}
})
})
diff --git a/test/helpers/external/cluster.go b/test/helpers/external/cluster.go
index 6a697f0d17..25e8f9bebd 100644
--- a/test/helpers/external/cluster.go
+++ b/test/helpers/external/cluster.go
@@ -21,7 +21,7 @@ import (
"golang.org/x/text/language"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
- "k8s.io/utils/pointer"
+ "k8s.io/utils/ptr"
)
const (
@@ -67,11 +67,11 @@ func generateTestClusterAPICRD(kind, pluralKind string) *apiextensionsv1.CustomR
Properties: map[string]apiextensionsv1.JSONSchemaProps{
"spec": {
Type: "object",
- XPreserveUnknownFields: pointer.Bool(true),
+ XPreserveUnknownFields: ptr.To(true),
},
"status": {
Type: "object",
- XPreserveUnknownFields: pointer.Bool(true),
+ XPreserveUnknownFields: ptr.To(true),
},
},
},
diff --git a/test/helpers/fuzzerfuncs.go b/test/helpers/fuzzerfuncs.go
index 063bfe9b58..b5648eae6d 100644
--- a/test/helpers/fuzzerfuncs.go
+++ b/test/helpers/fuzzerfuncs.go
@@ -20,7 +20,7 @@ import (
"strings"
fuzz "github.com/google/gofuzz"
- "k8s.io/utils/pointer"
+ "k8s.io/utils/ptr"
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/optional"
@@ -52,7 +52,7 @@ type isZeroer[T any] interface {
func fuzzFilterParam[Z isZeroer[T], T any](id *optional.String, filter *Z, c fuzz.Continue) {
if c.RandBool() {
- *id = pointer.String(nonEmptyString(c))
+ *id = ptr.To(nonEmptyString(c))
*filter = nil
} else {
*filter = new(T)
From 9aa449c186b9cf1c5d2f4cb12bda0c622fe7e598 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Wed, 10 Apr 2024 13:24:15 +0100
Subject: [PATCH 178/180] Allow explicitly empty volume AZ
Replaces an AvailabilityZone string for volumes with a
VolumeAvailabilityZone struct which allows more flexibility in
defaulting behaviour. Specifically it enables us to express both the
current default behaviour where we take the volume AZ from the Machine,
and a new default behaviour where to don't specify a volume AZ at all.
In making this change to both RootVolume and AdditionalBlockDevices we
use common code for both APIs. This has the result of updating
RootVolume to be consistent with AdditionalBlockDevices.
---
.golangci.yml | 4 +
Makefile | 1 +
api/v1alpha5/conversion.go | 13 ++
api/v1alpha5/zz_generated.conversion.go | 61 +++---
api/v1alpha6/conversion_test.go | 1 +
api/v1alpha6/openstackmachine_conversion.go | 16 ++
api/v1alpha6/types_conversion.go | 28 +++
api/v1alpha6/zz_generated.conversion.go | 61 +++---
api/v1alpha7/conversion_test.go | 1 +
api/v1alpha7/openstackmachine_conversion.go | 16 ++
api/v1alpha7/types_conversion.go | 29 +++
api/v1alpha7/zz_generated.conversion.go | 114 +++++++---
api/v1beta1/types.go | 56 ++++-
api/v1beta1/zz_generated.deepcopy.go | 30 ++-
...re.cluster.x-k8s.io_openstackclusters.yaml | 82 ++++++-
...er.x-k8s.io_openstackclustertemplates.yaml | 83 +++++++-
...re.cluster.x-k8s.io_openstackmachines.yaml | 81 ++++++-
...er.x-k8s.io_openstackmachinetemplates.yaml | 82 ++++++-
.../openstackmachine_controller_test.go | 4 +-
docs/book/src/api/v1beta1/api.md | 124 +++++++++--
.../topics/crd-changes/v1alpha7-to-v1beta1.md | 97 +++++++++
pkg/cloud/services/compute/instance.go | 71 ++++---
pkg/cloud/services/compute/instance_test.go | 114 +++++++---
.../volumeavailabilityzone.go | 62 ++++++
.../patch-machine-template-control-plane.yaml | 7 +-
.../patch-machine-template-worker.yaml | 10 +-
.../apivalidations/openstackmachine_test.go | 201 +++++++++++++++++-
test/helpers/fuzzerfuncs.go | 30 +++
28 files changed, 1247 insertions(+), 232 deletions(-)
create mode 100644 pkg/utils/conversioncommon/volumeavailabilityzone.go
diff --git a/.golangci.yml b/.golangci.yml
index 944b2ad9fc..7e3d5aac16 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -172,6 +172,10 @@ issues:
- stylecheck
text: "ST1003: should not use underscores in Go names;"
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/Makefile b/Makefile
index 197fb71297..1e9b096730 100644
--- a/Makefile
+++ b/Makefile
@@ -269,6 +269,7 @@ generate-conversion-gen: $(CONVERSION_GEN)
--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
diff --git a/api/v1alpha5/conversion.go b/api/v1alpha5/conversion.go
index 79b282dfeb..153adebd4e 100644
--- a/api/v1alpha5/conversion.go
+++ b/api/v1alpha5/conversion.go
@@ -26,6 +26,7 @@ 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/conversioncommon"
)
var _ ctrlconversion.Convertible = &OpenStackCluster{}
@@ -813,6 +814,18 @@ func Convert_v1beta1_NetworkParam_To_v1alpha5_NetworkFilter(in *infrav1.NetworkP
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")
diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go
index 95f181a279..a77967fb5a 100644
--- a/api/v1alpha5/zz_generated.conversion.go
+++ b/api/v1alpha5/zz_generated.conversion.go
@@ -207,16 +207,6 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*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((*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.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 {
@@ -297,6 +287,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
+ 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.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 {
@@ -402,6 +397,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); 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_v1alpha5_RootVolume(a.(*v1beta1.RootVolume), b.(*RootVolume), 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_v1alpha5_SecurityGroupFilter(a.(*v1beta1.SecurityGroupFilter), b.(*SecurityGroupFilter), scope)
}); err != nil {
@@ -1182,7 +1182,15 @@ func autoConvert_v1alpha5_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(i
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))
- out.RootVolume = (*v1beta1.RootVolume)(unsafe.Pointer(in.RootVolume))
+ 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
@@ -1227,7 +1235,15 @@ func autoConvert_v1beta1_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(i
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))
- 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
// WARNING: in.ServerGroup requires manual conversion: does not exist in peer-type
if in.IdentityRef != nil {
@@ -1475,29 +1491,18 @@ func autoConvert_v1beta1_PortOpts_To_v1alpha5_PortOpts(in *v1beta1.PortOpts, out
}
func autoConvert_v1alpha5_RootVolume_To_v1beta1_RootVolume(in *RootVolume, out *v1beta1.RootVolume, s conversion.Scope) error {
- out.Size = in.Size
- out.VolumeType = in.VolumeType
- out.AvailabilityZone = in.AvailabilityZone
+ // 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_v1beta1_RootVolume is an autogenerated conversion function.
-func Convert_v1alpha5_RootVolume_To_v1beta1_RootVolume(in *RootVolume, out *v1beta1.RootVolume, s conversion.Scope) error {
- return autoConvert_v1alpha5_RootVolume_To_v1beta1_RootVolume(in, out, s)
-}
-
func autoConvert_v1beta1_RootVolume_To_v1alpha5_RootVolume(in *v1beta1.RootVolume, out *RootVolume, s conversion.Scope) error {
- out.Size = in.Size
- out.VolumeType = in.VolumeType
- out.AvailabilityZone = in.AvailabilityZone
+ // 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_v1beta1_RootVolume_To_v1alpha5_RootVolume is an autogenerated conversion function.
-func Convert_v1beta1_RootVolume_To_v1alpha5_RootVolume(in *v1beta1.RootVolume, out *RootVolume, s conversion.Scope) error {
- return autoConvert_v1beta1_RootVolume_To_v1alpha5_RootVolume(in, out, s)
-}
-
func autoConvert_v1alpha5_Router_To_v1beta1_Router(in *Router, out *v1beta1.Router, s conversion.Scope) error {
out.Name = in.Name
out.ID = in.ID
diff --git a/api/v1alpha6/conversion_test.go b/api/v1alpha6/conversion_test.go
index c451091929..ffbe779937 100644
--- a/api/v1alpha6/conversion_test.go
+++ b/api/v1alpha6/conversion_test.go
@@ -792,6 +792,7 @@ func Test_FuzzRestorers(t *testing.T) {
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/openstackmachine_conversion.go b/api/v1alpha6/openstackmachine_conversion.go
index 7df76db0c5..aed2d3b7d4 100644
--- a/api/v1alpha6/openstackmachine_conversion.go
+++ b/api/v1alpha6/openstackmachine_conversion.go
@@ -196,6 +196,22 @@ func restorev1beta1MachineSpec(previous *infrav1.OpenStackMachineSpec, dst *infr
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) {
diff --git a/api/v1alpha6/types_conversion.go b/api/v1alpha6/types_conversion.go
index e9f1ea72a9..634e7c0194 100644
--- a/api/v1alpha6/types_conversion.go
+++ b/api/v1alpha6/types_conversion.go
@@ -24,6 +24,7 @@ import (
"k8s.io/utils/pointer"
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"
)
@@ -426,6 +427,33 @@ func Convert_v1beta1_BindingProfile_To_Map_string_To_Interface(in *infrav1.Bindi
/* 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 {
diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go
index 541bef18aa..59dba6198a 100644
--- a/api/v1alpha6/zz_generated.conversion.go
+++ b/api/v1alpha6/zz_generated.conversion.go
@@ -191,16 +191,6 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*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((*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.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 {
@@ -301,6 +291,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
+ 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.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 {
@@ -411,6 +406,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); 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_v1alpha6_RootVolume(a.(*v1beta1.RootVolume), b.(*RootVolume), 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_v1alpha6_SecurityGroupFilter(a.(*v1beta1.SecurityGroupFilter), b.(*SecurityGroupFilter), scope)
}); err != nil {
@@ -1192,7 +1192,15 @@ func autoConvert_v1alpha6_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(i
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))
- out.RootVolume = (*v1beta1.RootVolume)(unsafe.Pointer(in.RootVolume))
+ 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
@@ -1237,7 +1245,15 @@ func autoConvert_v1beta1_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(i
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))
- 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
// WARNING: in.ServerGroup requires manual conversion: does not exist in peer-type
if in.IdentityRef != nil {
@@ -1486,29 +1502,18 @@ func autoConvert_v1beta1_PortOpts_To_v1alpha6_PortOpts(in *v1beta1.PortOpts, out
}
func autoConvert_v1alpha6_RootVolume_To_v1beta1_RootVolume(in *RootVolume, out *v1beta1.RootVolume, s conversion.Scope) error {
- out.Size = in.Size
- out.VolumeType = in.VolumeType
- out.AvailabilityZone = in.AvailabilityZone
+ // 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_v1beta1_RootVolume is an autogenerated conversion function.
-func Convert_v1alpha6_RootVolume_To_v1beta1_RootVolume(in *RootVolume, out *v1beta1.RootVolume, s conversion.Scope) error {
- return autoConvert_v1alpha6_RootVolume_To_v1beta1_RootVolume(in, out, s)
-}
-
func autoConvert_v1beta1_RootVolume_To_v1alpha6_RootVolume(in *v1beta1.RootVolume, out *RootVolume, s conversion.Scope) error {
- out.Size = in.Size
- out.VolumeType = in.VolumeType
- out.AvailabilityZone = in.AvailabilityZone
+ // 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_v1beta1_RootVolume_To_v1alpha6_RootVolume is an autogenerated conversion function.
-func Convert_v1beta1_RootVolume_To_v1alpha6_RootVolume(in *v1beta1.RootVolume, out *RootVolume, s conversion.Scope) error {
- return autoConvert_v1beta1_RootVolume_To_v1alpha6_RootVolume(in, out, s)
-}
-
func autoConvert_v1alpha6_Router_To_v1beta1_Router(in *Router, out *v1beta1.Router, s conversion.Scope) error {
out.Name = in.Name
out.ID = in.ID
diff --git a/api/v1alpha7/conversion_test.go b/api/v1alpha7/conversion_test.go
index ac3d00cddf..8a7e9559b6 100644
--- a/api/v1alpha7/conversion_test.go
+++ b/api/v1alpha7/conversion_test.go
@@ -406,4 +406,5 @@ func Test_FuzzRestorers(t *testing.T) {
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/openstackmachine_conversion.go b/api/v1alpha7/openstackmachine_conversion.go
index 35a2cf6d83..5183b3fae2 100644
--- a/api/v1alpha7/openstackmachine_conversion.go
+++ b/api/v1alpha7/openstackmachine_conversion.go
@@ -191,6 +191,22 @@ func restorev1beta1MachineSpec(previous *infrav1.OpenStackMachineSpec, dst *infr
}
}
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 {
diff --git a/api/v1alpha7/types_conversion.go b/api/v1alpha7/types_conversion.go
index ac09a5d3dc..806e145806 100644
--- a/api/v1alpha7/types_conversion.go
+++ b/api/v1alpha7/types_conversion.go
@@ -22,6 +22,7 @@ import (
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"
)
@@ -484,6 +485,34 @@ func Convert_v1beta1_PortOpts_To_v1alpha7_PortOpts(in *infrav1.PortOpts, out *Po
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 {
diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go
index 554345da6c..f67c228983 100644
--- a/api/v1alpha7/zz_generated.conversion.go
+++ b/api/v1alpha7/zz_generated.conversion.go
@@ -29,6 +29,7 @@ import (
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"
@@ -261,16 +262,6 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
- if err := s.AddGeneratedConversionFunc((*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.AddGeneratedConversionFunc((*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.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 {
@@ -346,6 +337,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); 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 {
@@ -446,6 +442,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); 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 {
@@ -647,7 +648,15 @@ func Convert_v1beta1_BindingProfile_To_v1alpha7_BindingProfile(in *v1beta1.Bindi
func autoConvert_v1alpha7_BlockDeviceStorage_To_v1beta1_BlockDeviceStorage(in *BlockDeviceStorage, out *v1beta1.BlockDeviceStorage, s conversion.Scope) error {
out.Type = v1beta1.BlockDeviceType(in.Type)
- out.Volume = (*v1beta1.BlockDeviceVolume)(unsafe.Pointer(in.Volume))
+ 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
}
@@ -658,7 +667,15 @@ func Convert_v1alpha7_BlockDeviceStorage_To_v1beta1_BlockDeviceStorage(in *Block
func autoConvert_v1beta1_BlockDeviceStorage_To_v1alpha7_BlockDeviceStorage(in *v1beta1.BlockDeviceStorage, out *BlockDeviceStorage, s conversion.Scope) error {
out.Type = BlockDeviceType(in.Type)
- out.Volume = (*BlockDeviceVolume)(unsafe.Pointer(in.Volume))
+ 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
}
@@ -669,7 +686,9 @@ func Convert_v1beta1_BlockDeviceStorage_To_v1alpha7_BlockDeviceStorage(in *v1bet
func autoConvert_v1alpha7_BlockDeviceVolume_To_v1beta1_BlockDeviceVolume(in *BlockDeviceVolume, out *v1beta1.BlockDeviceVolume, s conversion.Scope) error {
out.Type = in.Type
- out.AvailabilityZone = in.AvailabilityZone
+ if err := conversioncommon.Convert_string_To_Pointer_v1beta1_VolumeAvailabilityZone(&in.AvailabilityZone, &out.AvailabilityZone, s); err != nil {
+ return err
+ }
return nil
}
@@ -680,7 +699,9 @@ func Convert_v1alpha7_BlockDeviceVolume_To_v1beta1_BlockDeviceVolume(in *BlockDe
func autoConvert_v1beta1_BlockDeviceVolume_To_v1alpha7_BlockDeviceVolume(in *v1beta1.BlockDeviceVolume, out *BlockDeviceVolume, s conversion.Scope) error {
out.Type = in.Type
- out.AvailabilityZone = in.AvailabilityZone
+ if err := conversioncommon.Convert_Pointer_v1beta1_VolumeAvailabilityZone_To_string(&in.AvailabilityZone, &out.AvailabilityZone, s); err != nil {
+ return err
+ }
return nil
}
@@ -1403,8 +1424,26 @@ func autoConvert_v1alpha7_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(i
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))
- out.RootVolume = (*v1beta1.RootVolume)(unsafe.Pointer(in.RootVolume))
- out.AdditionalBlockDevices = *(*[]v1beta1.AdditionalBlockDevice)(unsafe.Pointer(&in.AdditionalBlockDevices))
+ 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
@@ -1449,8 +1488,26 @@ func autoConvert_v1beta1_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(i
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))
- out.RootVolume = (*RootVolume)(unsafe.Pointer(in.RootVolume))
- out.AdditionalBlockDevices = *(*[]AdditionalBlockDevice)(unsafe.Pointer(&in.AdditionalBlockDevices))
+ 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
@@ -1686,29 +1743,18 @@ func autoConvert_v1beta1_PortOpts_To_v1alpha7_PortOpts(in *v1beta1.PortOpts, out
}
func autoConvert_v1alpha7_RootVolume_To_v1beta1_RootVolume(in *RootVolume, out *v1beta1.RootVolume, s conversion.Scope) error {
- out.Size = in.Size
- out.VolumeType = in.VolumeType
- out.AvailabilityZone = in.AvailabilityZone
+ // 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_v1alpha7_RootVolume_To_v1beta1_RootVolume is an autogenerated conversion function.
-func Convert_v1alpha7_RootVolume_To_v1beta1_RootVolume(in *RootVolume, out *v1beta1.RootVolume, s conversion.Scope) error {
- return autoConvert_v1alpha7_RootVolume_To_v1beta1_RootVolume(in, out, s)
-}
-
func autoConvert_v1beta1_RootVolume_To_v1alpha7_RootVolume(in *v1beta1.RootVolume, out *RootVolume, s conversion.Scope) error {
- out.Size = in.Size
- out.VolumeType = in.VolumeType
- out.AvailabilityZone = in.AvailabilityZone
+ // 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_v1beta1_RootVolume_To_v1alpha7_RootVolume is an autogenerated conversion function.
-func Convert_v1beta1_RootVolume_To_v1alpha7_RootVolume(in *v1beta1.RootVolume, out *RootVolume, s conversion.Scope) error {
- return autoConvert_v1beta1_RootVolume_To_v1alpha7_RootVolume(in, out, s)
-}
-
func autoConvert_v1alpha7_Router_To_v1beta1_Router(in *Router, out *v1beta1.Router, s conversion.Scope) error {
out.Name = in.Name
out.ID = in.ID
diff --git a/api/v1beta1/types.go b/api/v1beta1/types.go
index b6789489d1..3500482fdf 100644
--- a/api/v1beta1/types.go
+++ b/api/v1beta1/types.go
@@ -490,9 +490,12 @@ type BastionStatus struct {
}
type RootVolume struct {
- Size int `json:"diskSize,omitempty"`
- VolumeType string `json:"volumeType,omitempty"`
- AvailabilityZone string `json:"availabilityZone,omitempty"`
+ // 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
@@ -520,13 +523,44 @@ type BlockDeviceVolume struct {
// +optional
Type string `json:"type,omitempty"`
- // 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.
+ // 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 string `json:"availabilityZone,omitempty"`
+ 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.
@@ -537,9 +571,13 @@ type AdditionalBlockDevice struct {
// 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
diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go
index fe06c1285c..e0e7e28ad2 100644
--- a/api/v1beta1/zz_generated.deepcopy.go
+++ b/api/v1beta1/zz_generated.deepcopy.go
@@ -221,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)
}
}
@@ -238,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.
@@ -990,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
@@ -1393,6 +1398,7 @@ func (in *ResolvedPortSpecFields) DeepCopy() *ResolvedPortSpecFields {
// 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.
@@ -1742,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 10074be068..fd240c51f5 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml
@@ -5125,10 +5125,12 @@ spec:
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: |-
@@ -5146,12 +5148,36 @@ spec:
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.
- type: string
+ 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.
@@ -5672,11 +5698,49 @@ spec:
description: The volume metadata to boot from
properties:
availabilityZone:
- type: string
- diskSize:
+ 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
- volumeType:
+ 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
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 956f46dc3a..96680265b6 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml
@@ -2560,10 +2560,12 @@ spec:
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: |-
@@ -2581,12 +2583,36 @@ spec:
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.
- type: string
+ 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.
@@ -3116,11 +3142,50 @@ spec:
description: The volume metadata to boot from
properties:
availabilityZone:
- type: string
- diskSize:
+ 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
- volumeType:
+ 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
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 b518044f8f..243087e475 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
@@ -1732,10 +1732,12 @@ spec:
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: |-
@@ -1753,12 +1755,35 @@ spec:
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.
- type: string
+ 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.
@@ -2272,11 +2297,49 @@ spec:
description: The volume metadata to boot from
properties:
availabilityZone:
- type: string
- diskSize:
+ 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
- volumeType:
+ 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
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 b6d3d4d62a..7e5c5bbe6f 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
@@ -1404,10 +1404,12 @@ spec:
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: |-
@@ -1425,12 +1427,36 @@ spec:
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.
- type: string
+ 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.
@@ -1951,11 +1977,49 @@ spec:
description: The volume metadata to boot from
properties:
availabilityZone:
- type: string
- diskSize:
+ 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
- volumeType:
+ 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
diff --git a/controllers/openstackmachine_controller_test.go b/controllers/openstackmachine_controller_test.go
index c77220bc4c..b191111702 100644
--- a/controllers/openstackmachine_controller_test.go
+++ b/controllers/openstackmachine_controller_test.go
@@ -366,7 +366,7 @@ func Test_reconcileDelete(t *testing.T) {
Spec: infrav1.OpenStackMachineSpec{
Image: defaultImage,
RootVolume: &infrav1.RootVolume{
- Size: 50,
+ SizeGiB: 50,
},
},
Status: infrav1.OpenStackMachineStatus{
@@ -393,7 +393,7 @@ func Test_reconcileDelete(t *testing.T) {
Spec: infrav1.OpenStackMachineSpec{
Image: defaultImage,
RootVolume: &infrav1.RootVolume{
- Size: 50,
+ SizeGiB: 50,
},
},
Status: infrav1.OpenStackMachineStatus{
diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md
index 19dfeb31e3..8646bdebfa 100644
--- a/docs/book/src/api/v1beta1/api.md
+++ b/docs/book/src/api/v1beta1/api.md
@@ -977,7 +977,8 @@ 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.
+metadata API or the config drive.
+Name cannot be ‘root’, which is reserved for the root volume.
@@ -1397,7 +1398,8 @@ BlockDeviceVolume
(Appears on:
-BlockDeviceStorage)
+BlockDeviceStorage,
+RootVolume)
BlockDeviceVolume contains additional storage options for a volume block device.
@@ -1428,16 +1430,16 @@ will be used.
availabilityZone
-string
+
+VolumeAvailabilityZone
+
|
(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.
+AvailabilityZone is the volume availability zone to create the volume
+in. If not specified, the volume will be created without an explicit
+availability zone.
|
@@ -4310,32 +4312,28 @@ depends on the specific OpenStack implementation.
-diskSize
+sizeGiB
int
|
+ SizeGiB is the size of the block device in gibibytes (GiB).
|
-volumeType
-
-string
-
- |
-
- |
-
-
-
-availabilityZone
+BlockDeviceVolume
-string
+
+BlockDeviceVolume
+
|
+
+(Members of BlockDeviceVolume are embedded into this type.)
+
|
@@ -5260,6 +5258,90 @@ string
+VolumeAZName
+(string alias)
+
+(Appears on:
+VolumeAvailabilityZone)
+
+
+
VolumeAZName is the name of a volume availability zone. It may not contain spaces.
+
+VolumeAZSource
+(string alias)
+
+(Appears on:
+VolumeAvailabilityZone)
+
+
+
VolumeAZSource specifies where to obtain the availability zone for a volume.
+
+
+
+
+| Value |
+Description |
+
+
+"Machine" |
+ |
+
"Name" |
+ |
+
+
+VolumeAvailabilityZone
+
+
+(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.
diff --git a/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md b/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
index 598873cb0d..975d226275 100644
--- a/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
+++ b/docs/book/src/topics/crd-changes/v1alpha7-to-v1beta1.md
@@ -15,6 +15,8 @@
- [Removal of imageUUID](#removal-of-imageuuid)
- [Change to instanceID](#change-to-instanceid)
- [Changes to ports](#changes-to-ports)
+ - [Change to `availabilityZone` for `additionalBlockDevices`](#change-to-availabilityzone-for-additionalblockdevices)
+ - [Changes to rootVolume](#changes-to-rootvolume)
- [Addition of floatingIPPoolRef](#addition-of-floatingippoolref)
- [`OpenStackCluster`](#openstackcluster)
- [Removal of cloudName](#removal-of-cloudname-1)
@@ -149,6 +151,101 @@ The following fields in `PortOpts` are renamed in order to keep them consistent
* `hostId` becomes `hostID`
* `allowedCidrs` becomes `allowedCIDRs`
+#### Change to `availabilityZone` for `additionalBlockDevices`
+
+Prior to v1beta1 it was not possible to specify a volume with no availability zone, allowing Cinder to allocate the volume according to its default policy. Previously, if no availability zone was given CAPO would use the value of `failureDomain` from the associated `Machine`.
+
+In v1beta1 this default changes. In v1beta1, if no `availabilityZone` is specified, CAPO will not specify an availability zone for the created volume.
+
+To support this whilst continuing to support the previous behaviour, `availabilityZone` becomes a struct with 2 fields:
+
+`from` specifies where we get the availability zone from. It can be either `Name`, or `Machine`. It can be omitted, and the default is `Name`, in which case the value of the `name` field will be used. Specifying `Machine` provides the previous default behaviour.
+
+`name` is a specific availability zone to use.
+
+For example, a volume with an explicit AZ in:
+* v1alpha7
+ ```yaml
+ - name: extra
+ sizeGiB: 1000
+ storage:
+ type: volume
+ volume:
+ type: ceph
+ availabilityZone: az1
+ ```
+* v1beta1
+ ```yaml
+ - name: extra
+ sizeGiB: 1000
+ storage:
+ type: volume
+ volume:
+ type: ceph
+ availabilityZone:
+ name: az1
+ ```
+
+A volume which uses the value of `failureDomain` from the `Machine`:
+* v1alpha7
+ ```yaml
+ - name: extra
+ sizeGiB: 1000
+ storage:
+ type: volume
+ volume:
+ type: ceph
+ ```
+* v1beta1
+ ```yaml
+ - name: extra
+ sizeGiB: 1000
+ storage:
+ type: volume
+ volume:
+ type: ceph
+ availabilityZone:
+ from: Machine
+ ```
+
+A volume which explicitly has no availability zone:
+* v1alpha7: Not possible
+* v1beta1
+ ```yaml
+ - name: extra
+ sizeGiB: 1000
+ storage:
+ type: volume
+ volume:
+ type: ceph
+ ```
+
+Volumes upgraded from prior versions will retain their current semantics, so volumes which previously specified no availabilityZone will have an availabilityZone with `from: Machine` added.
+
+#### Changes to rootVolume
+
+The `rootVolume` field has been updated to be consistent with the volume specification for `additionalBlockDevices`. Specifically:
+
+* `rootVolume.diskSize` becomes `rootVolume.sizeGiB`
+* `rootVolume.volumeType` becomes `rootVolume.Type`
+* `rootVolume.availabilityZone` becomes a struct with the same semantics as `availabilityZone` in `additionalBlockDevices`, described above.
+
+For example:
+* v1alpha7
+ ```yaml
+ rootVolume:
+ diskSize: 50
+ volumeType: ceph
+ ```
+* v1beta1
+ ```yaml
+ rootVolume:
+ sizeGiB: 50
+ type: ceph
+ availabilityZone:
+ from: Machine
+ ```
+
#### Addition of floatingIPPoolRef
A new field, FloatingIPPoolRef, has been introduced. It is important to note that this feature requires the existence of an IPPool to operate seamlessly. This new field references an IPPool whice will be used for floating IP allocation.
diff --git a/pkg/cloud/services/compute/instance.go b/pkg/cloud/services/compute/instance.go
index ee808c05d6..cb7146ca4d 100644
--- a/pkg/cloud/services/compute/instance.go
+++ b/pkg/cloud/services/compute/instance.go
@@ -131,7 +131,7 @@ func volumeName(instanceName string, nameSuffix string) string {
}
func hasRootVolume(instanceSpec *InstanceSpec) bool {
- return instanceSpec.RootVolume != nil && instanceSpec.RootVolume.Size > 0
+ return instanceSpec.RootVolume != nil && instanceSpec.RootVolume.SizeGiB > 0
}
func (s *Service) getVolumeByName(name string) (*volumes.Volume, error) {
@@ -204,30 +204,46 @@ func (s *Service) waitForVolume(volumeID string, timeout time.Duration, retryInt
// getOrCreateVolumeBuilder gets or creates a volume with the given options. It returns the volume that already exists or the newly created one.
// It returns an error if the volume creation failed or if the expected volume is different from the one that already exists.
-func (s *Service) getOrCreateVolumeBuilder(eventObject runtime.Object, instanceSpec *InstanceSpec, blockDevice infrav1.AdditionalBlockDevice, imageID string, description string) (*volumes.Volume, error) {
- var volumeType string
- availabilityZone := instanceSpec.FailureDomain
-
- if blockDevice.Storage.Volume != nil {
- if blockDevice.Storage.Volume.AvailabilityZone != "" {
- availabilityZone = blockDevice.Storage.Volume.AvailabilityZone
- }
- volumeType = blockDevice.Storage.Volume.Type
- }
+func (s *Service) getOrCreateVolumeBuilder(eventObject runtime.Object, instanceSpec *InstanceSpec, blockDeviceSpec *infrav1.AdditionalBlockDevice, imageID string, description string) (*volumes.Volume, error) {
+ availabilityZone, volType := resolveVolumeOpts(instanceSpec, blockDeviceSpec.Storage.Volume)
createOpts := volumes.CreateOpts{
- Name: volumeName(instanceSpec.Name, blockDevice.Name),
+ Name: volumeName(instanceSpec.Name, blockDeviceSpec.Name),
Description: description,
- Size: blockDevice.SizeGiB,
+ Size: blockDeviceSpec.SizeGiB,
ImageID: imageID,
Multiattach: false,
AvailabilityZone: availabilityZone,
- VolumeType: volumeType,
+ VolumeType: volType,
}
return s.getOrCreateVolume(eventObject, createOpts)
}
+func resolveVolumeOpts(instanceSpec *InstanceSpec, volumeOpts *infrav1.BlockDeviceVolume) (az, volType string) {
+ if volumeOpts == nil {
+ return
+ }
+
+ volType = volumeOpts.Type
+
+ volumeAZ := volumeOpts.AvailabilityZone
+ if volumeAZ == nil {
+ return
+ }
+
+ switch volumeAZ.From {
+ case "", infrav1.VolumeAZFromName:
+ // volumeAZ.Name is nil case should have been caught by validation
+ if volumeAZ.Name != nil {
+ az = string(*volumeAZ.Name)
+ }
+ case infrav1.VolumeAZFromMachine:
+ az = instanceSpec.FailureDomain
+ }
+ return
+}
+
// getBlockDevices returns a list of block devices that were created and attached to the instance. It returns an error
// if the root volume or any of the additional block devices could not be created.
func (s *Service) getBlockDevices(eventObject runtime.Object, instanceSpec *InstanceSpec, imageID string, timeout time.Duration, retryInterval time.Duration) ([]bootfromvolume.BlockDevice, error) {
@@ -236,18 +252,15 @@ func (s *Service) getBlockDevices(eventObject runtime.Object, instanceSpec *Inst
if hasRootVolume(instanceSpec) {
rootVolumeToBlockDevice := infrav1.AdditionalBlockDevice{
Name: "root",
- SizeGiB: instanceSpec.RootVolume.Size,
+ SizeGiB: instanceSpec.RootVolume.SizeGiB,
Storage: infrav1.BlockDeviceStorage{
- Type: infrav1.VolumeBlockDevice,
- Volume: &infrav1.BlockDeviceVolume{
- AvailabilityZone: instanceSpec.RootVolume.AvailabilityZone,
- Type: instanceSpec.RootVolume.VolumeType,
- },
+ Type: infrav1.VolumeBlockDevice,
+ Volume: &instanceSpec.RootVolume.BlockDeviceVolume,
},
}
- rootVolume, err := s.getOrCreateVolumeBuilder(eventObject, instanceSpec, rootVolumeToBlockDevice, imageID, fmt.Sprintf("Root volume for %s", instanceSpec.Name))
+ rootVolume, err := s.getOrCreateVolumeBuilder(eventObject, instanceSpec, &rootVolumeToBlockDevice, imageID, fmt.Sprintf("Root volume for %s", instanceSpec.Name))
if err != nil {
- return []bootfromvolume.BlockDevice{}, err
+ return nil, err
}
blockDevices = append(blockDevices, bootfromvolume.BlockDevice{
SourceType: bootfromvolume.SourceVolume,
@@ -266,7 +279,9 @@ func (s *Service) getBlockDevices(eventObject runtime.Object, instanceSpec *Inst
})
}
- for _, blockDeviceSpec := range instanceSpec.AdditionalBlockDevices {
+ for i := range instanceSpec.AdditionalBlockDevices {
+ blockDeviceSpec := instanceSpec.AdditionalBlockDevices[i]
+
var bdUUID string
var localDiskSizeGiB int
var sourceType bootfromvolume.SourceType
@@ -274,13 +289,13 @@ func (s *Service) getBlockDevices(eventObject runtime.Object, instanceSpec *Inst
// There is also a validation in the openstackmachine webhook.
if blockDeviceSpec.Name == "root" {
- return []bootfromvolume.BlockDevice{}, fmt.Errorf("block device name 'root' is reserved")
+ return nil, fmt.Errorf("block device name 'root' is reserved")
}
if blockDeviceSpec.Storage.Type == infrav1.VolumeBlockDevice {
- blockDevice, err := s.getOrCreateVolumeBuilder(eventObject, instanceSpec, blockDeviceSpec, "", fmt.Sprintf("Additional block device for %s", instanceSpec.Name))
+ blockDevice, err := s.getOrCreateVolumeBuilder(eventObject, instanceSpec, &blockDeviceSpec, "", fmt.Sprintf("Additional block device for %s", instanceSpec.Name))
if err != nil {
- return []bootfromvolume.BlockDevice{}, err
+ return nil, err
}
bdUUID = blockDevice.ID
sourceType = bootfromvolume.SourceVolume
@@ -290,7 +305,7 @@ func (s *Service) getBlockDevices(eventObject runtime.Object, instanceSpec *Inst
destinationType = bootfromvolume.DestinationLocal
localDiskSizeGiB = blockDeviceSpec.SizeGiB
} else {
- return []bootfromvolume.BlockDevice{}, fmt.Errorf("invalid block device type %s", blockDeviceSpec.Storage.Type)
+ return nil, fmt.Errorf("invalid block device type %s", blockDeviceSpec.Storage.Type)
}
blockDevices = append(blockDevices, bootfromvolume.BlockDevice{
@@ -309,7 +324,7 @@ func (s *Service) getBlockDevices(eventObject runtime.Object, instanceSpec *Inst
for _, bd := range blockDevices {
if bd.SourceType == bootfromvolume.SourceVolume {
if err := s.waitForVolume(bd.UUID, timeout, retryInterval); err != nil {
- return []bootfromvolume.BlockDevice{}, fmt.Errorf("volume %s did not become available: %w", bd.UUID, err)
+ return nil, fmt.Errorf("volume %s did not become available: %w", bd.UUID, err)
}
}
}
diff --git a/pkg/cloud/services/compute/instance_test.go b/pkg/cloud/services/compute/instance_test.go
index 54677279aa..cc6335027e 100644
--- a/pkg/cloud/services/compute/instance_test.go
+++ b/pkg/cloud/services/compute/instance_test.go
@@ -331,7 +331,7 @@ func TestService_ReconcileInstance(t *testing.T) {
getInstanceSpec: func() *InstanceSpec {
s := getDefaultInstanceSpec()
s.RootVolume = &infrav1.RootVolume{
- Size: 50,
+ SizeGiB: 50,
}
return s
},
@@ -341,12 +341,11 @@ func TestService_ReconcileInstance(t *testing.T) {
r.volume.ListVolumes(volumes.ListOpts{Name: fmt.Sprintf("%s-root", openStackMachineName)}).
Return([]volumes.Volume{}, nil)
r.volume.CreateVolume(volumes.CreateOpts{
- Size: 50,
- AvailabilityZone: failureDomain,
- Description: fmt.Sprintf("Root volume for %s", openStackMachineName),
- Name: fmt.Sprintf("%s-root", openStackMachineName),
- ImageID: imageUUID,
- Multiattach: false,
+ Size: 50,
+ Description: fmt.Sprintf("Root volume for %s", openStackMachineName),
+ Name: fmt.Sprintf("%s-root", openStackMachineName),
+ ImageID: imageUUID,
+ Multiattach: false,
}).Return(&volumes.Volume{ID: rootVolumeUUID}, nil)
expectVolumePollSuccess(r.volume, rootVolumeUUID)
@@ -373,10 +372,13 @@ func TestService_ReconcileInstance(t *testing.T) {
getInstanceSpec: func() *InstanceSpec {
s := getDefaultInstanceSpec()
s.RootVolume = &infrav1.RootVolume{
- Size: 50,
- AvailabilityZone: "test-alternate-az",
- VolumeType: "test-volume-type",
+ SizeGiB: 50,
}
+ azName := infrav1.VolumeAZName("test-alternate-az")
+ s.RootVolume.AvailabilityZone = &infrav1.VolumeAvailabilityZone{
+ Name: &azName,
+ }
+ s.RootVolume.Type = "test-volume-type"
return s
},
expect: func(r *recorders) {
@@ -414,12 +416,16 @@ func TestService_ReconcileInstance(t *testing.T) {
wantErr: false,
},
{
- name: "Boot from volume failure cleans up ports",
+ name: "Boot from volume with AZ from machine",
getInstanceSpec: func() *InstanceSpec {
s := getDefaultInstanceSpec()
s.RootVolume = &infrav1.RootVolume{
- Size: 50,
+ SizeGiB: 50,
}
+ s.RootVolume.AvailabilityZone = &infrav1.VolumeAvailabilityZone{
+ From: infrav1.VolumeAZFromMachine,
+ }
+ s.RootVolume.Type = "test-volume-type"
return s
},
expect: func(r *recorders) {
@@ -430,11 +436,53 @@ func TestService_ReconcileInstance(t *testing.T) {
r.volume.CreateVolume(volumes.CreateOpts{
Size: 50,
AvailabilityZone: failureDomain,
+ VolumeType: "test-volume-type",
Description: fmt.Sprintf("Root volume for %s", openStackMachineName),
Name: fmt.Sprintf("%s-root", openStackMachineName),
ImageID: imageUUID,
Multiattach: false,
}).Return(&volumes.Volume{ID: rootVolumeUUID}, nil)
+ expectVolumePollSuccess(r.volume, rootVolumeUUID)
+
+ createMap := getDefaultServerMap()
+ serverMap := createMap["server"].(map[string]interface{})
+ serverMap["imageRef"] = ""
+ serverMap["block_device_mapping_v2"] = []map[string]interface{}{
+ {
+ "delete_on_termination": true,
+ "destination_type": "volume",
+ "source_type": "volume",
+ "uuid": rootVolumeUUID,
+ "boot_index": float64(0),
+ },
+ }
+ expectCreateServer(r.compute, createMap, false)
+
+ // Don't delete ports because the server is created: DeleteInstance will do it
+ },
+ wantErr: false,
+ },
+ {
+ name: "Boot from volume failure cleans up ports",
+ getInstanceSpec: func() *InstanceSpec {
+ s := getDefaultInstanceSpec()
+ s.RootVolume = &infrav1.RootVolume{
+ SizeGiB: 50,
+ }
+ return s
+ },
+ expect: func(r *recorders) {
+ expectDefaultFlavor(r.compute)
+
+ r.volume.ListVolumes(volumes.ListOpts{Name: fmt.Sprintf("%s-root", openStackMachineName)}).
+ Return([]volumes.Volume{}, nil)
+ r.volume.CreateVolume(volumes.CreateOpts{
+ Size: 50,
+ Description: fmt.Sprintf("Root volume for %s", openStackMachineName),
+ Name: fmt.Sprintf("%s-root", openStackMachineName),
+ ImageID: imageUUID,
+ Multiattach: false,
+ }).Return(&volumes.Volume{ID: rootVolumeUUID}, nil)
expectVolumePoll(r.volume, rootVolumeUUID, []string{"creating", "error"})
},
wantErr: true,
@@ -444,7 +492,7 @@ func TestService_ReconcileInstance(t *testing.T) {
getInstanceSpec: func() *InstanceSpec {
s := getDefaultInstanceSpec()
s.RootVolume = &infrav1.RootVolume{
- Size: 50,
+ SizeGiB: 50,
}
s.AdditionalBlockDevices = []infrav1.AdditionalBlockDevice{
{
@@ -473,24 +521,22 @@ func TestService_ReconcileInstance(t *testing.T) {
r.volume.ListVolumes(volumes.ListOpts{Name: fmt.Sprintf("%s-root", openStackMachineName)}).
Return([]volumes.Volume{}, nil)
r.volume.CreateVolume(volumes.CreateOpts{
- Size: 50,
- AvailabilityZone: failureDomain,
- Description: fmt.Sprintf("Root volume for %s", openStackMachineName),
- Name: fmt.Sprintf("%s-root", openStackMachineName),
- ImageID: imageUUID,
- Multiattach: false,
+ Size: 50,
+ Description: fmt.Sprintf("Root volume for %s", openStackMachineName),
+ Name: fmt.Sprintf("%s-root", openStackMachineName),
+ ImageID: imageUUID,
+ Multiattach: false,
}).Return(&volumes.Volume{ID: rootVolumeUUID}, nil)
expectVolumePollSuccess(r.volume, rootVolumeUUID)
r.volume.ListVolumes(volumes.ListOpts{Name: fmt.Sprintf("%s-etcd", openStackMachineName)}).
Return([]volumes.Volume{}, nil)
r.volume.CreateVolume(volumes.CreateOpts{
- Size: 50,
- AvailabilityZone: failureDomain,
- Description: fmt.Sprintf("Additional block device for %s", openStackMachineName),
- Name: fmt.Sprintf("%s-etcd", openStackMachineName),
- Multiattach: false,
- VolumeType: "test-volume-type",
+ Size: 50,
+ Description: fmt.Sprintf("Additional block device for %s", openStackMachineName),
+ Name: fmt.Sprintf("%s-etcd", openStackMachineName),
+ Multiattach: false,
+ VolumeType: "test-volume-type",
}).Return(&volumes.Volume{ID: additionalBlockDeviceVolumeUUID}, nil)
expectVolumePollSuccess(r.volume, additionalBlockDeviceVolumeUUID)
@@ -559,12 +605,11 @@ func TestService_ReconcileInstance(t *testing.T) {
r.volume.ListVolumes(volumes.ListOpts{Name: fmt.Sprintf("%s-etcd", openStackMachineName)}).
Return([]volumes.Volume{}, nil)
r.volume.CreateVolume(volumes.CreateOpts{
- Size: 50,
- AvailabilityZone: failureDomain,
- Description: fmt.Sprintf("Additional block device for %s", openStackMachineName),
- Name: fmt.Sprintf("%s-etcd", openStackMachineName),
- Multiattach: false,
- VolumeType: "test-volume-type",
+ Size: 50,
+ Description: fmt.Sprintf("Additional block device for %s", openStackMachineName),
+ Name: fmt.Sprintf("%s-etcd", openStackMachineName),
+ Multiattach: false,
+ VolumeType: "test-volume-type",
}).Return(&volumes.Volume{ID: additionalBlockDeviceVolumeUUID}, nil)
expectVolumePollSuccess(r.volume, additionalBlockDeviceVolumeUUID)
@@ -605,6 +650,7 @@ func TestService_ReconcileInstance(t *testing.T) {
name: "Additional block device success with explicit AZ",
getInstanceSpec: func() *InstanceSpec {
s := getDefaultInstanceSpec()
+ azName := infrav1.VolumeAZName("test-alternate-az")
s.AdditionalBlockDevices = []infrav1.AdditionalBlockDevice{
{
Name: "etcd",
@@ -612,8 +658,10 @@ func TestService_ReconcileInstance(t *testing.T) {
Storage: infrav1.BlockDeviceStorage{
Type: "Volume",
Volume: &infrav1.BlockDeviceVolume{
- AvailabilityZone: "test-alternate-az",
- Type: "test-volume-type",
+ Type: "test-volume-type",
+ AvailabilityZone: &infrav1.VolumeAvailabilityZone{
+ Name: &azName,
+ },
},
},
},
diff --git a/pkg/utils/conversioncommon/volumeavailabilityzone.go b/pkg/utils/conversioncommon/volumeavailabilityzone.go
new file mode 100644
index 0000000000..520a213a01
--- /dev/null
+++ b/pkg/utils/conversioncommon/volumeavailabilityzone.go
@@ -0,0 +1,62 @@
+/*
+Copyright 2024 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 conversioncommon
+
+import (
+ "k8s.io/apimachinery/pkg/conversion"
+
+ infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
+)
+
+func Convert_string_To_Pointer_v1beta1_VolumeAvailabilityZone(in *string, out **infrav1.VolumeAvailabilityZone, _ conversion.Scope) error {
+ switch *in {
+ case "":
+ *out = &infrav1.VolumeAvailabilityZone{
+ From: infrav1.VolumeAZFromMachine,
+ }
+ default:
+ azName := infrav1.VolumeAZName(*in)
+ *out = &infrav1.VolumeAvailabilityZone{
+ From: infrav1.VolumeAZFromName,
+ Name: &azName,
+ }
+ }
+
+ return nil
+}
+
+func Convert_Pointer_v1beta1_VolumeAvailabilityZone_To_string(in **infrav1.VolumeAvailabilityZone, out *string, _ conversion.Scope) error {
+ // This is a lossy: can't specify no AZ prior to v1beta1
+ if *in == nil {
+ *out = ""
+ return nil
+ }
+
+ switch (*in).From {
+ case "", infrav1.VolumeAZFromName:
+ name := (*in).Name
+ if name != nil {
+ *out = string(*name)
+ } else {
+ *out = ""
+ }
+ case infrav1.VolumeAZFromMachine:
+ *out = ""
+ }
+
+ return nil
+}
diff --git a/test/e2e/data/kustomize/multi-az/patch-machine-template-control-plane.yaml b/test/e2e/data/kustomize/multi-az/patch-machine-template-control-plane.yaml
index fe803f27af..9db70c86a6 100644
--- a/test/e2e/data/kustomize/multi-az/patch-machine-template-control-plane.yaml
+++ b/test/e2e/data/kustomize/multi-az/patch-machine-template-control-plane.yaml
@@ -2,7 +2,9 @@
- op: add
path: /spec/template/spec/rootVolume
value:
- diskSize: 25
+ sizeGiB: 25
+ availabilityZone:
+ from: Machine
- op: add
path: /spec/template/spec/additionalBlockDevices
value:
@@ -10,6 +12,9 @@
sizeGiB: 1
storage:
type: Volume
+ volume:
+ availabilityZone:
+ from: Machine
- name: etcd
sizeGiB: 1
storage:
diff --git a/test/e2e/data/kustomize/multi-az/patch-machine-template-worker.yaml b/test/e2e/data/kustomize/multi-az/patch-machine-template-worker.yaml
index 83029a10f6..6d46c42e35 100644
--- a/test/e2e/data/kustomize/multi-az/patch-machine-template-worker.yaml
+++ b/test/e2e/data/kustomize/multi-az/patch-machine-template-worker.yaml
@@ -2,9 +2,10 @@
- op: add
path: /spec/template/spec/rootVolume
value:
- diskSize: 25
- volumeType: ${OPENSTACK_VOLUME_TYPE_ALT}
- availabilityZone: ${OPENSTACK_FAILURE_DOMAIN}
+ sizeGiB: 25
+ type: ${OPENSTACK_VOLUME_TYPE_ALT}
+ availabilityZone:
+ name: ${OPENSTACK_FAILURE_DOMAIN}
- op: add
path: /spec/template/spec/additionalBlockDevices
value:
@@ -14,7 +15,8 @@
type: Volume
volume:
type: ${OPENSTACK_VOLUME_TYPE_ALT}
- availabilityZone: ${OPENSTACK_FAILURE_DOMAIN}
+ availabilityZone:
+ name: ${OPENSTACK_FAILURE_DOMAIN}
- name: etcd
sizeGiB: 1
storage:
diff --git a/test/e2e/suites/apivalidations/openstackmachine_test.go b/test/e2e/suites/apivalidations/openstackmachine_test.go
index 4e888a3a41..49a59444fe 100644
--- a/test/e2e/suites/apivalidations/openstackmachine_test.go
+++ b/test/e2e/suites/apivalidations/openstackmachine_test.go
@@ -29,26 +29,30 @@ import (
var _ = Describe("OpenStackMachine API validations", func() {
var namespace *corev1.Namespace
- var machine *infrav1.OpenStackMachine
-
- BeforeEach(func() {
- namespace = createNamespace()
+ defaultMachine := func() *infrav1.OpenStackMachine {
// Initialise a basic machine object in the correct namespace
- machine = &infrav1.OpenStackMachine{
+ machine := &infrav1.OpenStackMachine{
Spec: infrav1.OpenStackMachineSpec{
Image: infrav1.ImageParam{Filter: &infrav1.ImageFilter{Name: pointer.String("test-image")}},
},
}
machine.Namespace = namespace.Name
machine.GenerateName = "machine-"
+ return machine
+ }
+
+ BeforeEach(func() {
+ namespace = createNamespace()
})
It("should allow the smallest permissible machine spec", func() {
- Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "OpenStackMachine creation should succeed")
+ Expect(k8sClient.Create(ctx, defaultMachine())).To(Succeed(), "OpenStackMachine creation should succeed")
})
It("should only allow the providerID to be set once", func() {
+ machine := defaultMachine()
+
By("Creating a bare machine")
Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "OpenStackMachine creation should succeed")
@@ -62,6 +66,8 @@ var _ = Describe("OpenStackMachine API validations", func() {
})
It("should not allow server metadata to exceed 255 characters", func() {
+ machine := defaultMachine()
+
By("Creating a machine with a metadata key that is too long")
machine.Spec.ServerMetadata = []infrav1.ServerMetadata{
{
@@ -89,4 +95,187 @@ var _ = Describe("OpenStackMachine API validations", func() {
}
Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "Creating a machine with max metadata key and value should succeed")
})
+
+ Context("volumes", func() {
+ It("should not allow volume with zero size", func() {
+ machine := defaultMachine()
+ machine.Spec.RootVolume = &infrav1.RootVolume{
+ SizeGiB: 0,
+ }
+ Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "Creating a machine with a zero size root volume should fail")
+
+ machine = defaultMachine()
+ machine.Spec.AdditionalBlockDevices = []infrav1.AdditionalBlockDevice{
+ {
+ Name: "test-volume",
+ SizeGiB: 0,
+ },
+ }
+ Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "Creating a machine with a zero size additional block device should fail")
+ })
+
+ /* FIXME: These tests are failing
+ It("should not allow additional volume with empty name", func() {
+ machine.Spec.AdditionalBlockDevices = []infrav1.AdditionalBlockDevice{
+ {
+ Name: "",
+ SizeGiB: 1,
+ },
+ }
+ Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "Creating a machine with an empty name additional block device should fail")
+ })
+
+ It("should not allow additional volume with name root", func() {
+ machine.Spec.AdditionalBlockDevices = []infrav1.AdditionalBlockDevice{
+ {
+ Name: "root",
+ SizeGiB: 1,
+ },
+ }
+ Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "Creating a machine with a root named additional block device should fail")
+ })
+ */
+
+ It("should not allow additional volume with duplicate name", func() {
+ machine := defaultMachine()
+ machine.Spec.AdditionalBlockDevices = []infrav1.AdditionalBlockDevice{
+ {
+ Name: "test-volume",
+ SizeGiB: 1,
+ },
+ {
+ Name: "test-volume",
+ SizeGiB: 2,
+ },
+ }
+ Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "Creating a machine with duplicate named additional block device should fail")
+ })
+
+ defaultMachineWithRootVolumeAZ := func(az *infrav1.VolumeAvailabilityZone) *infrav1.OpenStackMachine {
+ machine := defaultMachine()
+ machine.Spec.RootVolume = &infrav1.RootVolume{
+ SizeGiB: 1,
+ }
+ machine.Spec.RootVolume.AvailabilityZone = az
+ return machine
+ }
+
+ defaultMachineWithAdditionBlockDeviceAZ := func(az *infrav1.VolumeAvailabilityZone) *infrav1.OpenStackMachine {
+ machine := defaultMachine()
+ machine.Spec.AdditionalBlockDevices = []infrav1.AdditionalBlockDevice{
+ {
+ Name: "test-volume",
+ SizeGiB: 1,
+ Storage: infrav1.BlockDeviceStorage{
+ Type: infrav1.VolumeBlockDevice,
+ Volume: &infrav1.BlockDeviceVolume{
+ AvailabilityZone: az,
+ },
+ },
+ },
+ }
+ return machine
+ }
+
+ It("should allow volume with defaulted AZ from", func() {
+ azName := infrav1.VolumeAZName("test-az")
+ az := infrav1.VolumeAvailabilityZone{
+ Name: &azName,
+ }
+
+ machine := defaultMachineWithRootVolumeAZ(&az)
+ Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "Creating a machine with a root volume with an availability zone should succeed")
+
+ machine = defaultMachineWithAdditionBlockDeviceAZ(&az)
+ Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "Creating a machine with an additional block device with an availability zone should succeed")
+ })
+
+ It("should allow volume with AZ from Name", func() {
+ azName := infrav1.VolumeAZName("test-az")
+ az := infrav1.VolumeAvailabilityZone{
+ From: infrav1.VolumeAZFromName,
+ Name: &azName,
+ }
+
+ machine := defaultMachineWithRootVolumeAZ(&az)
+ Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "Creating a machine with a root volume with an availability zone should succeed")
+
+ machine = defaultMachineWithAdditionBlockDeviceAZ(&az)
+ Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "Creating a machine with an additional block device with an availability zone should succeed")
+ })
+
+ It("should allow volume AZ from Machine", func() {
+ az := infrav1.VolumeAvailabilityZone{
+ From: infrav1.VolumeAZFromMachine,
+ }
+
+ machine := defaultMachineWithRootVolumeAZ(&az)
+ Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "Creating a machine with a root volume with an availability zone should succeed")
+
+ machine = defaultMachineWithAdditionBlockDeviceAZ(&az)
+ Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "Creating a machine with an additional block device with an availability zone should succeed")
+ })
+
+ It("should not allow volume AZ with invalid from", func() {
+ az := infrav1.VolumeAvailabilityZone{
+ From: "invalid",
+ }
+
+ machine := defaultMachineWithRootVolumeAZ(&az)
+ Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "Creating a machine with a root volume with an invalid availability zone should fail")
+
+ machine = defaultMachineWithAdditionBlockDeviceAZ(&az)
+ Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "Creating a machine with an additional block device with an invalid availability zone should fail")
+ })
+
+ It("should not allow empty volume AZ", func() {
+ az := infrav1.VolumeAvailabilityZone{}
+
+ machine := defaultMachineWithRootVolumeAZ(&az)
+ Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "Creating a machine with a root volume with an empty availability zone should fail")
+
+ machine = defaultMachineWithAdditionBlockDeviceAZ(&az)
+ Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "Creating a machine with an additional block device with an empty availability zone should fail")
+ })
+
+ It("should not allow volume AZ from Name with missing name", func() {
+ az := infrav1.VolumeAvailabilityZone{
+ From: infrav1.VolumeAZFromName,
+ }
+
+ machine := defaultMachineWithRootVolumeAZ(&az)
+ Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "Creating a machine with a root volume with a missing name availability zone should fail")
+
+ machine = defaultMachineWithAdditionBlockDeviceAZ(&az)
+ Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "Creating a machine with an additional block device with a missing name availability zone should fail")
+ })
+
+ It("should not allow volume AZ from Machine with name", func() {
+ azName := infrav1.VolumeAZName("test-az")
+ az := infrav1.VolumeAvailabilityZone{
+ From: infrav1.VolumeAZFromMachine,
+ Name: &azName,
+ }
+
+ machine := defaultMachineWithRootVolumeAZ(&az)
+ Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "Creating a machine with a root volume with a name availability zone should fail")
+
+ machine = defaultMachineWithAdditionBlockDeviceAZ(&az)
+ Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "Creating a machine with an additional block device with a name availability zone should fail")
+ })
+
+ It("should not allow volume AZ from Name with empty name", func() {
+ azName := infrav1.VolumeAZName("")
+ az := infrav1.VolumeAvailabilityZone{
+ From: infrav1.VolumeAZFromName,
+ Name: &azName,
+ }
+
+ machine := defaultMachineWithRootVolumeAZ(&az)
+ Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "Creating a machine with a root volume with an empty name availability zone should fail")
+
+ machine = defaultMachineWithAdditionBlockDeviceAZ(&az)
+ Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "Creating a machine with an additional block device with an empty name availability zone should fail")
+ })
+ })
})
diff --git a/test/helpers/fuzzerfuncs.go b/test/helpers/fuzzerfuncs.go
index 063bfe9b58..8f40656831 100644
--- a/test/helpers/fuzzerfuncs.go
+++ b/test/helpers/fuzzerfuncs.go
@@ -153,5 +153,35 @@ func InfraV1FuzzerFuncs() []interface{} {
func(param *infrav1.SecurityGroupParam, c fuzz.Continue) {
fuzzFilterParam(¶m.ID, ¶m.Filter, c)
},
+
+ // Ensure VolumeAZ type is valid
+ func(az *infrav1.VolumeAvailabilityZone, c fuzz.Continue) {
+ stringWithoutSpaces := func() string {
+ for {
+ s := c.RandString()
+ if !strings.Contains(s, " ") && len(s) > 0 {
+ return s
+ }
+ }
+ }
+
+ // From is defaulted
+ if c.RandBool() {
+ name := infrav1.VolumeAZName(stringWithoutSpaces())
+ az.Name = &name
+ return
+ }
+
+ // From is Name
+ if c.RandBool() {
+ az.From = infrav1.VolumeAZFromName
+ name := infrav1.VolumeAZName(stringWithoutSpaces())
+ az.Name = &name
+ return
+ }
+
+ // From is Machine
+ az.From = infrav1.VolumeAZFromMachine
+ },
}
}
From 2837b29535bb85fc07b04f98a59c112b93d99fad Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Fri, 12 Apr 2024 15:13:39 +0100
Subject: [PATCH 179/180] Add a No Bastion e2e test
---
Makefile | 3 +-
.../kustomize/no-bastion/kustomization.yaml | 11 +++
.../no-bastion/patch-no-bastion.yaml | 3 +
test/e2e/shared/common.go | 92 ++++++++++---------
test/e2e/shared/defaults.go | 1 +
test/e2e/suites/e2e/e2e_test.go | 36 ++++++++
6 files changed, 101 insertions(+), 45 deletions(-)
create mode 100644 test/e2e/data/kustomize/no-bastion/kustomization.yaml
create mode 100644 test/e2e/data/kustomize/no-bastion/patch-no-bastion.yaml
diff --git a/Makefile b/Makefile
index 1e9b096730..a0991f0ed4 100644
--- a/Makefile
+++ b/Makefile
@@ -161,7 +161,8 @@ e2e-templates: $(addprefix $(E2E_NO_ARTIFACT_TEMPLATES_DIR)/, \
cluster-template.yaml \
cluster-template-flatcar.yaml \
cluster-template-k8s-upgrade.yaml \
- cluster-template-flatcar-sysext.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) \
diff --git a/test/e2e/data/kustomize/no-bastion/kustomization.yaml b/test/e2e/data/kustomize/no-bastion/kustomization.yaml
new file mode 100644
index 0000000000..0c05231807
--- /dev/null
+++ b/test/e2e/data/kustomize/no-bastion/kustomization.yaml
@@ -0,0 +1,11 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+
+resources:
+- ../default
+
+patches:
+- path: patch-no-bastion.yaml
+ target:
+ kind: OpenStackCluster
+ name: \${CLUSTER_NAME}
diff --git a/test/e2e/data/kustomize/no-bastion/patch-no-bastion.yaml b/test/e2e/data/kustomize/no-bastion/patch-no-bastion.yaml
new file mode 100644
index 0000000000..15704bc138
--- /dev/null
+++ b/test/e2e/data/kustomize/no-bastion/patch-no-bastion.yaml
@@ -0,0 +1,3 @@
+---
+- op: remove
+ path: /spec/bastion
diff --git a/test/e2e/shared/common.go b/test/e2e/shared/common.go
index b8ad587b90..8bef9e9964 100644
--- a/test/e2e/shared/common.go
+++ b/test/e2e/shared/common.go
@@ -214,51 +214,55 @@ func (o OpenStackLogCollector) CollectMachineLog(ctx context.Context, management
return fmt.Errorf("error writing server JSON %s: %s", serverJSON, err)
}
- srvUser := o.E2EContext.E2EConfig.GetVariable(SSHUserMachine)
- executeCommands(
- ctx,
- o.E2EContext.Settings.ArtifactFolder,
- o.E2EContext.Settings.Debug,
- outputPath,
- ip,
- openStackCluster.Status.Bastion.FloatingIP,
- srvUser,
- []command{
- // don't do this for now, it just takes to long
- // {
- // title: "systemd",
- // cmd: "journalctl --no-pager --output=short-precise | grep -v 'audit:\\|audit\\['",
- // },
- {
- title: "kern",
- cmd: "journalctl --no-pager --output=short-precise -k",
+ if openStackCluster.Status.Bastion == nil {
+ Logf("Skipping log collection for machine %q since no bastion is available", m.Name)
+ } else {
+ srvUser := o.E2EContext.E2EConfig.GetVariable(SSHUserMachine)
+ executeCommands(
+ ctx,
+ o.E2EContext.Settings.ArtifactFolder,
+ o.E2EContext.Settings.Debug,
+ outputPath,
+ ip,
+ openStackCluster.Status.Bastion.FloatingIP,
+ srvUser,
+ []command{
+ // don't do this for now, it just takes to long
+ // {
+ // title: "systemd",
+ // cmd: "journalctl --no-pager --output=short-precise | grep -v 'audit:\\|audit\\['",
+ // },
+ {
+ title: "kern",
+ cmd: "journalctl --no-pager --output=short-precise -k",
+ },
+ {
+ title: "containerd-info",
+ cmd: "crictl --runtime-endpoint unix:///run/containerd/containerd.sock info",
+ },
+ {
+ title: "containerd-containers",
+ cmd: "crictl --runtime-endpoint unix:///run/containerd/containerd.sock ps",
+ },
+ {
+ title: "containerd-pods",
+ cmd: "crictl --runtime-endpoint unix:///run/containerd/containerd.sock pods",
+ },
+ {
+ title: "cloud-final",
+ cmd: "journalctl --no-pager -u cloud-final",
+ },
+ {
+ title: "kubelet",
+ cmd: "journalctl --no-pager -u kubelet.service",
+ },
+ {
+ title: "containerd",
+ cmd: "journalctl --no-pager -u containerd.service",
+ },
},
- {
- title: "containerd-info",
- cmd: "crictl --runtime-endpoint unix:///run/containerd/containerd.sock info",
- },
- {
- title: "containerd-containers",
- cmd: "crictl --runtime-endpoint unix:///run/containerd/containerd.sock ps",
- },
- {
- title: "containerd-pods",
- cmd: "crictl --runtime-endpoint unix:///run/containerd/containerd.sock pods",
- },
- {
- title: "cloud-final",
- cmd: "journalctl --no-pager -u cloud-final",
- },
- {
- title: "kubelet",
- cmd: "journalctl --no-pager -u kubelet.service",
- },
- {
- title: "containerd",
- cmd: "journalctl --no-pager -u containerd.service",
- },
- },
- )
+ )
+ }
return nil
}
diff --git a/test/e2e/shared/defaults.go b/test/e2e/shared/defaults.go
index 3c0f32c56e..5caa6eb8e1 100644
--- a/test/e2e/shared/defaults.go
+++ b/test/e2e/shared/defaults.go
@@ -46,6 +46,7 @@ const (
OpenStackNodeMachineFlavor = "OPENSTACK_NODE_MACHINE_FLAVOR"
SSHUserMachine = "SSH_USER_MACHINE"
FlavorDefault = ""
+ FlavorNoBastion = "no-bastion"
FlavorWithoutLB = "without-lb"
FlavorMultiNetwork = "multi-network"
FlavorMultiAZ = "multi-az"
diff --git a/test/e2e/suites/e2e/e2e_test.go b/test/e2e/suites/e2e/e2e_test.go
index 09ee609346..45423af394 100644
--- a/test/e2e/suites/e2e/e2e_test.go
+++ b/test/e2e/suites/e2e/e2e_test.go
@@ -245,6 +245,42 @@ var _ = Describe("e2e tests [PR-Blocking]", func() {
})
})
+ Describe("Workload cluster (no bastion)", func() {
+ It("should be creatable and deletable", func() {
+ shared.Logf("Creating a cluster")
+ clusterName := fmt.Sprintf("cluster-%s", namespace.Name)
+ configCluster := defaultConfigCluster(clusterName, namespace.Name)
+ configCluster.ControlPlaneMachineCount = ptr.To(int64(1))
+ configCluster.WorkerMachineCount = ptr.To(int64(1))
+ configCluster.Flavor = shared.FlavorNoBastion
+ createCluster(ctx, configCluster, clusterResources)
+ md := clusterResources.MachineDeployments
+
+ workerMachines := framework.GetMachinesByMachineDeployments(ctx, framework.GetMachinesByMachineDeploymentsInput{
+ Lister: e2eCtx.Environment.BootstrapClusterProxy.GetClient(),
+ ClusterName: clusterName,
+ Namespace: namespace.Name,
+ MachineDeployment: *md[0],
+ })
+ controlPlaneMachines := framework.GetControlPlaneMachinesByCluster(ctx, framework.GetControlPlaneMachinesByClusterInput{
+ Lister: e2eCtx.Environment.BootstrapClusterProxy.GetClient(),
+ ClusterName: clusterName,
+ Namespace: namespace.Name,
+ })
+ Expect(workerMachines).To(HaveLen(1))
+ Expect(controlPlaneMachines).To(HaveLen(1))
+
+ shared.Logf("Waiting for worker nodes to be in Running phase")
+ statusChecks := []framework.MachineStatusCheck{framework.MachinePhaseCheck(string(clusterv1.MachinePhaseRunning))}
+ machineStatusInput := framework.WaitForMachineStatusCheckInput{
+ Getter: e2eCtx.Environment.BootstrapClusterProxy.GetClient(),
+ Machine: &workerMachines[0],
+ StatusChecks: statusChecks,
+ }
+ framework.WaitForMachineStatusCheck(ctx, machineStatusInput, e2eCtx.E2EConfig.GetIntervals(specName, "wait-machine-status")...)
+ })
+ })
+
Describe("Workload cluster (flatcar)", func() {
It("should be creatable and deletable", func() {
// Flatcar default user is "core"
From 118f715ca3544f20798d5e68c29c539751e85fa6 Mon Sep 17 00:00:00 2001
From: Matthew Booth
Date: Fri, 12 Apr 2024 15:14:07 +0100
Subject: [PATCH 180/180] Fix crash on delete with no bastion
---
controllers/openstackcluster_controller.go | 14 ++++++--------
controllers/openstackmachine_controller.go | 15 ++++-----------
pkg/cloud/services/compute/instance.go | 15 +++++++++------
3 files changed, 19 insertions(+), 25 deletions(-)
diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go
index 7ba565cb90..d310aced6a 100644
--- a/controllers/openstackcluster_controller.go
+++ b/controllers/openstackcluster_controller.go
@@ -291,15 +291,13 @@ func deleteBastion(scope *scope.WithLogger, cluster *clusterv1.Cluster, openStac
}
// If no instance was created we currently need to check for orphaned
- // volumes. This requires resolving the instance spec.
- // TODO: write volumes to status resources on creation so this is no longer required.
+ // volumes.
if instanceStatus == nil {
- instanceSpec, err := bastionToInstanceSpec(openStackCluster, cluster)
- if err != nil {
- return err
- }
- if err := computeService.DeleteVolumes(instanceSpec); err != nil {
- return fmt.Errorf("delete volumes: %w", err)
+ 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()
diff --git a/controllers/openstackmachine_controller.go b/controllers/openstackmachine_controller.go
index a1869e3b51..ee923ec812 100644
--- a/controllers/openstackmachine_controller.go
+++ b/controllers/openstackmachine_controller.go
@@ -300,19 +300,12 @@ func (r *OpenStackMachineReconciler) reconcileDelete(scope *scope.WithLogger, cl
}
// If no instance was created we currently need to check for orphaned
- // volumes. This requires resolving the instance spec.
- // TODO: write volumes to status resources on creation so this is no longer required.
- if instanceStatus == nil && openStackMachine.Status.Resolved != nil {
- instanceSpec, err := machineToInstanceSpec(openStackCluster, machine, openStackMachine, "")
- if err != nil {
- return ctrl.Result{}, err
- }
- if err := computeService.DeleteVolumes(instanceSpec); err != nil {
+ // 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)
}
- }
-
- if instanceStatus != nil {
+ } 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)
diff --git a/pkg/cloud/services/compute/instance.go b/pkg/cloud/services/compute/instance.go
index cb7146ca4d..aa8d6e5ca2 100644
--- a/pkg/cloud/services/compute/instance.go
+++ b/pkg/cloud/services/compute/instance.go
@@ -431,11 +431,14 @@ func (s *Service) DeleteInstance(eventObject runtime.Object, instanceStatus *Ins
}
// DeleteVolumes deletes any cinder volumes which were created for the instance.
-// Note that this must only be called when the server was not successfully
+// Note that this need only be called when the server was not successfully
// created. If the server was created the volume will have been added with
// DeleteOnTermination=true, and will be automatically cleaned up with the
// server.
-func (s *Service) DeleteVolumes(instanceSpec *InstanceSpec) error {
+// We don't pass InstanceSpec here because we only require instance name,
+// rootVolume, and additionalBlockDevices, and resolving the whole InstanceSpec
+// introduces unnecessary failure modes.
+func (s *Service) DeleteVolumes(instanceName string, rootVolume *infrav1.RootVolume, additionalBlockDevices []infrav1.AdditionalBlockDevice) error {
/*
Attaching volumes to an instance is a two-step process:
@@ -455,13 +458,13 @@ func (s *Service) DeleteVolumes(instanceSpec *InstanceSpec) error {
DeleteOnTermination will ensure it is deleted in that case.
*/
- if hasRootVolume(instanceSpec) {
- if err := s.deleteVolume(instanceSpec.Name, "root"); err != nil {
+ if rootVolume != nil && rootVolume.SizeGiB > 0 {
+ if err := s.deleteVolume(instanceName, "root"); err != nil {
return err
}
}
- for _, volumeSpec := range instanceSpec.AdditionalBlockDevices {
- if err := s.deleteVolume(instanceSpec.Name, volumeSpec.Name); err != nil {
+ for _, volumeSpec := range additionalBlockDevices {
+ if err := s.deleteVolume(instanceName, volumeSpec.Name); err != nil {
return err
}
}