Skip to content

Commit ddb58eb

Browse files
authored
Merge pull request #2355 from fabriziopandini/clusterctl-map-uxname-to-manifestlabels
🐛clusterctl: allows usage providers with the same name but different type
2 parents a81c040 + 201c5b8 commit ddb58eb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+1037
-572
lines changed

cmd/clusterctl/api/v1alpha3/labels.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ limitations under the License.
1616

1717
package v1alpha3
1818

19+
import "fmt"
20+
1921
const (
2022
// ClusterctlLabelName defines the label that is applied to all the components managed by clusterctl.
2123
ClusterctlLabelName = "clusterctl.cluster.x-k8s.io"
@@ -38,3 +40,21 @@ const (
3840
// if an instance of the provider is deleted.
3941
ResourceLifecycleShared = ResourceLifecycle("shared")
4042
)
43+
44+
// ManifestLabel returns the cluster.x-k8s.io/provider label value for a provider/type.
45+
// Please note that this label uniquely identifies the provider, e.g. bootstrap-kubeadm, but not the instances of
46+
// the provider, e.g. namespace-1/bootstrap-kubeadm and namespace-2/bootstrap-kubeadm.
47+
func ManifestLabel(name string, providerType ProviderType) string {
48+
switch providerType {
49+
case CoreProviderType:
50+
return name
51+
case BootstrapProviderType:
52+
return fmt.Sprintf("bootstrap-%s", name)
53+
case ControlPlaneProviderType:
54+
return fmt.Sprintf("control-plane-%s", name)
55+
case InfrastructureProviderType:
56+
return fmt.Sprintf("infrastructure-%s", name)
57+
default:
58+
return fmt.Sprintf("unknown-type-%s", name)
59+
}
60+
}

cmd/clusterctl/api/v1alpha3/provider_type.go

Lines changed: 74 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,20 @@ import (
2424
// +kubebuilder:resource:path=providers,scope=Namespaced,categories=cluster-api
2525
// +kubebuilder:storageversion
2626
// +kubebuilder:object:root=true
27-
// +kubebuilder:printcolumn:name="Type",type="string",JSONPath=".type"
27+
// +kubebuilder:printcolumn:name="Type",type="string",JSONPath=".provider"
28+
// +kubebuilder:printcolumn:name="Provider",type="string",JSONPath=".type"
2829
// +kubebuilder:printcolumn:name="Version",type="string",JSONPath=".version"
2930
// +kubebuilder:printcolumn:name="Watch Namespace",type="string",JSONPath=".watchedNamespace"
3031

31-
// Provider is the Schema for the providers API
32+
// Provider defines an entry in the provider inventory.
3233
type Provider struct {
3334
metav1.TypeMeta `json:",inline"`
3435
metav1.ObjectMeta `json:"metadata,omitempty"`
3536

37+
// Provider indicates the name of the provider.
38+
// +optional
39+
Provider string `json:"provider,omitempty"`
40+
3641
// Type indicates the type of the provider.
3742
// See ProviderType for a list of supported values
3843
// +optional
@@ -48,7 +53,57 @@ type Provider struct {
4853
WatchedNamespace string `json:"watchedNamespace,omitempty"`
4954
}
5055

51-
// ProviderType is a string representation of a TaskGroup create policy.
56+
// ManifestLabel returns the cluster.x-k8s.io/provider label value for an entry in the provider inventory.
57+
// Please note that this label uniquely identifies the provider, e.g. bootstrap-kubeadm, but not the instances of
58+
// the provider, e.g. namespace-1/bootstrap-kubeadm and namespace-2/bootstrap-kubeadm
59+
func (p *Provider) ManifestLabel() string {
60+
return ManifestLabel(p.Provider, p.GetProviderType())
61+
}
62+
63+
// InstanceName return the a name that uniquely identifies an entry in the provider inventory.
64+
// The instanceName is composed by the ManifestLabel and by the namespace where the provider is installed;
65+
// the resulting value uniquely identify a provider instance because clusterctl does not support multiple
66+
//instances of the same provider to be installed in the same namespace.
67+
func (p *Provider) InstanceName() string {
68+
return types.NamespacedName{Namespace: p.Namespace, Name: p.ManifestLabel()}.String()
69+
}
70+
71+
// HasWatchingOverlapWith returns true if the provider has an overlapping watching namespace with another provider.
72+
func (p *Provider) HasWatchingOverlapWith(other Provider) bool {
73+
return p.WatchedNamespace == "" || p.WatchedNamespace == other.WatchedNamespace || other.WatchedNamespace == ""
74+
}
75+
76+
// SameAs returns true if two providers have the same Provider and type.
77+
// Please note that there could be many instances of the same provider.
78+
func (p *Provider) SameAs(other Provider) bool {
79+
return p.Provider == other.Provider && p.Type == other.Type
80+
}
81+
82+
// Equals returns true if two providers are identical (same name, type, version etc.).
83+
func (p *Provider) Equals(other Provider) bool {
84+
return p.Name == other.Name &&
85+
p.Namespace == other.Namespace &&
86+
p.Provider == other.Provider &&
87+
p.Type == other.Type &&
88+
p.WatchedNamespace == other.WatchedNamespace &&
89+
p.Version == other.Version
90+
}
91+
92+
// GetProviderType parse the Provider.Type string field and return the typed representation.
93+
func (p *Provider) GetProviderType() ProviderType {
94+
switch t := ProviderType(p.Type); t {
95+
case
96+
CoreProviderType,
97+
BootstrapProviderType,
98+
InfrastructureProviderType,
99+
ControlPlaneProviderType:
100+
return t
101+
default:
102+
return ProviderTypeUnknown
103+
}
104+
}
105+
106+
// ProviderType is a string representation of a Provider type..
52107
type ProviderType string
53108

54109
const (
@@ -68,42 +123,22 @@ const (
68123
ProviderTypeUnknown = ProviderType("")
69124
)
70125

71-
// GetProviderType attempts to parse the ProviderType field and return
72-
// the typed ProviderType representation.
73-
func (p *Provider) GetProviderType() ProviderType {
74-
switch t := ProviderType(p.Type); t {
75-
case
76-
CoreProviderType,
77-
BootstrapProviderType,
78-
InfrastructureProviderType,
79-
ControlPlaneProviderType:
80-
return t
126+
// Order return an integer that can be used to sort ProviderType values.
127+
func (p ProviderType) Order() int {
128+
switch p {
129+
case CoreProviderType:
130+
return 0
131+
case BootstrapProviderType:
132+
return 1
133+
case ControlPlaneProviderType:
134+
return 2
135+
case InfrastructureProviderType:
136+
return 3
81137
default:
82-
return ProviderTypeUnknown
138+
return 4
83139
}
84140
}
85141

86-
// InstanceName return the instance name for the provider, that is composed by the provider name and the namespace
87-
// where the provider is installed (nb. clusterctl does not support multiple instances of the same provider to be
88-
// installed in the same namespace)
89-
func (p *Provider) InstanceName() string {
90-
return types.NamespacedName{Namespace: p.Namespace, Name: p.Name}.String()
91-
}
92-
93-
// HasWatchingOverlapWith returns true if the provider has an overlapping watching namespace with another provider.
94-
func (p *Provider) HasWatchingOverlapWith(other Provider) bool {
95-
return p.WatchedNamespace == "" || p.WatchedNamespace == other.WatchedNamespace || other.WatchedNamespace == ""
96-
}
97-
98-
// Equals returns true if two providers are exactly the same.
99-
func (p *Provider) Equals(other Provider) bool {
100-
return p.Name == other.Name &&
101-
p.Namespace == other.Namespace &&
102-
p.Type == other.Type &&
103-
p.WatchedNamespace == other.WatchedNamespace &&
104-
p.Version == other.Version
105-
}
106-
107142
// +kubebuilder:object:root=true
108143

109144
// ProviderList contains a list of Provider
@@ -113,15 +148,15 @@ type ProviderList struct {
113148
Items []Provider `json:"items"`
114149
}
115150

116-
func (l *ProviderList) FilterByName(name string) []Provider {
151+
func (l *ProviderList) FilterByNamespace(namespace string) []Provider {
117152
return l.filterBy(func(p Provider) bool {
118-
return p.Name == name
153+
return p.Namespace == namespace
119154
})
120155
}
121156

122-
func (l *ProviderList) FilterByNamespace(namespace string) []Provider {
157+
func (l *ProviderList) FilterByProviderAndType(provider string, providerType ProviderType) []Provider {
123158
return l.filterBy(func(p Provider) bool {
124-
return p.Namespace == namespace
159+
return p.Provider == provider && p.Type == string(providerType)
125160
})
126161
}
127162

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/*
2+
Copyright 2020 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package v1alpha3
18+
19+
import (
20+
"testing"
21+
)
22+
23+
func Test_Provider_ManifestLabel(t *testing.T) {
24+
type fields struct {
25+
provider string
26+
providerType ProviderType
27+
}
28+
tests := []struct {
29+
name string
30+
fields fields
31+
want string
32+
}{
33+
{
34+
name: "core provider remains the same",
35+
fields: fields{
36+
provider: "cluster-api",
37+
providerType: CoreProviderType,
38+
},
39+
want: "cluster-api",
40+
},
41+
{
42+
name: "kubeadm bootstrap",
43+
fields: fields{
44+
provider: "kubeadm",
45+
providerType: BootstrapProviderType,
46+
},
47+
want: "bootstrap-kubeadm",
48+
},
49+
{
50+
name: "other bootstrap providers gets prefix",
51+
fields: fields{
52+
provider: "xx",
53+
providerType: BootstrapProviderType,
54+
},
55+
want: "bootstrap-xx",
56+
},
57+
{
58+
name: "kubeadm control-plane",
59+
fields: fields{
60+
provider: "kubeadm",
61+
providerType: ControlPlaneProviderType,
62+
},
63+
want: "control-plane-kubeadm",
64+
},
65+
{
66+
name: "other control-plane providers gets prefix",
67+
fields: fields{
68+
provider: "xx",
69+
providerType: ControlPlaneProviderType,
70+
},
71+
want: "control-plane-xx",
72+
},
73+
{
74+
name: "infrastructure providers gets prefix",
75+
fields: fields{
76+
provider: "xx",
77+
providerType: InfrastructureProviderType,
78+
},
79+
want: "infrastructure-xx",
80+
},
81+
}
82+
for _, tt := range tests {
83+
t.Run(tt.name, func(t *testing.T) {
84+
p := &Provider{
85+
Provider: tt.fields.provider,
86+
Type: string(tt.fields.providerType),
87+
}
88+
if got := p.ManifestLabel(); got != tt.want {
89+
t.Errorf("got %v, want %v", got, tt.want)
90+
}
91+
})
92+
}
93+
}

0 commit comments

Comments
 (0)