Skip to content

Commit 4fd9458

Browse files
authored
🌱 Add Namingstrategy to InfraCluster (#11898)
* Add Namingstrategy to infracluster * address review comments * address review comment * address review comments * address review comment
1 parent d9c2199 commit 4fd9458

File tree

13 files changed

+164
-2
lines changed

13 files changed

+164
-2
lines changed

api/v1beta1/clusterclass_types.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,10 @@ type ClusterClassSpec struct {
104104
// +optional
105105
Infrastructure LocalObjectTemplate `json:"infrastructure,omitempty"`
106106

107+
// infrastructureNamingStrategy allows changing the naming pattern used when creating the infrastructure object.
108+
// +optional
109+
InfrastructureNamingStrategy *InfrastructureNamingStrategy `json:"infrastructureNamingStrategy,omitempty"`
110+
107111
// controlPlane is a reference to a local struct that holds the details
108112
// for provisioning the Control Plane for the Cluster.
109113
// +optional
@@ -211,6 +215,19 @@ type ControlPlaneClassNamingStrategy struct {
211215
Template *string `json:"template,omitempty"`
212216
}
213217

218+
// InfrastructureNamingStrategy defines the naming strategy for infrastructure objects.
219+
type InfrastructureNamingStrategy struct {
220+
// template defines the template to use for generating the name of the Infrastructure object.
221+
// If not defined, it will fallback to `{{ .cluster.name }}-{{ .random }}`.
222+
// If the templated string exceeds 63 characters, it will be trimmed to 58 characters and will
223+
// get concatenated with a random suffix of length 5.
224+
// The templating mechanism provides the following arguments:
225+
// * `.cluster.name`: The name of the cluster object.
226+
// * `.random`: A random alphanumeric string, without vowels, of length 5.
227+
// +optional
228+
Template *string `json:"template,omitempty"`
229+
}
230+
214231
// WorkersClass is a collection of deployment classes.
215232
type WorkersClass struct {
216233
// machineDeployments is a list of machine deployment classes that can be used to create

api/v1beta1/zz_generated.deepcopy.go

Lines changed: 25 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/v1beta1/zz_generated.openapi.go

Lines changed: 28 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/cluster.x-k8s.io_clusterclasses.yaml

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

exp/topology/desiredstate/desired_state.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,11 +193,16 @@ func computeInfrastructureCluster(_ context.Context, s *scope.Scope) (*unstructu
193193
cluster := s.Current.Cluster
194194
currentRef := cluster.Spec.InfrastructureRef
195195

196+
nameTemplate := "{{ .cluster.name }}-{{ .random }}"
197+
if s.Blueprint.ClusterClass.Spec.InfrastructureNamingStrategy != nil && s.Blueprint.ClusterClass.Spec.InfrastructureNamingStrategy.Template != nil {
198+
nameTemplate = *s.Blueprint.ClusterClass.Spec.InfrastructureNamingStrategy.Template
199+
}
200+
196201
infrastructureCluster, err := templateToObject(templateToInput{
197202
template: template,
198203
templateClonedFromRef: templateClonedFromRef,
199204
cluster: cluster,
200-
nameGenerator: topologynames.SimpleNameGenerator(fmt.Sprintf("%s-", cluster.Name)),
205+
nameGenerator: topologynames.InfraClusterNameGenerator(nameTemplate, cluster.Name),
201206
currentObjectRef: currentRef,
202207
// Note: It is not possible to add an ownerRef to Cluster at this stage, otherwise the provisioning
203208
// of the infrastructure cluster starts no matter of the object being actually referenced by the Cluster itself.

internal/apis/core/v1alpha4/conversion.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ func (src *ClusterClass) ConvertTo(dstRaw conversion.Hub) error {
133133
dst.Spec.ControlPlane.MachineHealthCheck = restored.Spec.ControlPlane.MachineHealthCheck
134134
dst.Spec.ControlPlane.ReadinessGates = restored.Spec.ControlPlane.ReadinessGates
135135
dst.Spec.ControlPlane.NamingStrategy = restored.Spec.ControlPlane.NamingStrategy
136+
dst.Spec.InfrastructureNamingStrategy = restored.Spec.InfrastructureNamingStrategy
136137
dst.Spec.ControlPlane.NodeDrainTimeout = restored.Spec.ControlPlane.NodeDrainTimeout
137138
dst.Spec.ControlPlane.NodeVolumeDetachTimeout = restored.Spec.ControlPlane.NodeVolumeDetachTimeout
138139
dst.Spec.ControlPlane.NodeDeletionTimeout = restored.Spec.ControlPlane.NodeDeletionTimeout

internal/apis/core/v1alpha4/zz_generated.conversion.go

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/topology/names/names.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,12 @@ func MachineSetMachineNameGenerator(templateString, clusterName, machineSetName
106106
})
107107
}
108108

109+
// InfraClusterNameGenerator returns a generator for creating a infrastructure cluster name.
110+
func InfraClusterNameGenerator(templateString, clusterName string) NameGenerator {
111+
return newTemplateGenerator(templateString, clusterName,
112+
map[string]interface{}{})
113+
}
114+
109115
// templateGenerator parses the template string as text/template and executes it using
110116
// the passed data to generate a name.
111117
type templateGenerator struct {

internal/webhooks/clusterclass.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,23 @@ func validateMachineHealthCheckClasses(clusterClass *clusterv1.ClusterClass) fie
435435
func validateNamingStrategies(clusterClass *clusterv1.ClusterClass) field.ErrorList {
436436
var allErrs field.ErrorList
437437

438+
if clusterClass.Spec.InfrastructureNamingStrategy != nil && clusterClass.Spec.InfrastructureNamingStrategy.Template != nil {
439+
name, err := topologynames.InfraClusterNameGenerator(*clusterClass.Spec.InfrastructureNamingStrategy.Template, "cluster").GenerateName()
440+
templateFldPath := field.NewPath("spec", "infrastructureNamingStrategy", "template")
441+
if err != nil {
442+
allErrs = append(allErrs,
443+
field.Invalid(
444+
templateFldPath,
445+
*clusterClass.Spec.InfrastructureNamingStrategy.Template,
446+
fmt.Sprintf("invalid InfraCluster name template: %v", err),
447+
))
448+
} else {
449+
for _, err := range validation.IsDNS1123Subdomain(name) {
450+
allErrs = append(allErrs, field.Invalid(templateFldPath, *clusterClass.Spec.InfrastructureNamingStrategy.Template, err))
451+
}
452+
}
453+
}
454+
438455
if clusterClass.Spec.ControlPlane.NamingStrategy != nil && clusterClass.Spec.ControlPlane.NamingStrategy.Template != nil {
439456
name, err := topologynames.ControlPlaneNameGenerator(*clusterClass.Spec.ControlPlane.NamingStrategy.Template, "cluster").GenerateName()
440457
templateFldPath := field.NewPath("spec", "controlPlane", "namingStrategy", "template")

internal/webhooks/clusterclass_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1644,6 +1644,7 @@ func TestClusterClassValidation(t *testing.T) {
16441644
in: builder.ClusterClass(metav1.NamespaceDefault, "class1").
16451645
WithInfrastructureClusterTemplate(
16461646
builder.InfrastructureClusterTemplate(metav1.NamespaceDefault, "infra1").Build()).
1647+
WithInfraClusterStrategy(&clusterv1.InfrastructureNamingStrategy{Template: ptr.To("{{ .cluster.name }}-infra-{{ .random }}")}).
16471648
WithControlPlaneTemplate(
16481649
builder.ControlPlaneTemplate(metav1.NamespaceDefault, "cp1").
16491650
Build()).
@@ -1670,6 +1671,36 @@ func TestClusterClassValidation(t *testing.T) {
16701671
Build(),
16711672
expectErr: false,
16721673
},
1674+
{
1675+
name: "should return error for invalid InfraCluster InfrastructureNamingStrategy.template",
1676+
in: builder.ClusterClass(metav1.NamespaceDefault, "class1").
1677+
WithInfrastructureClusterTemplate(
1678+
builder.InfrastructureClusterTemplate(metav1.NamespaceDefault, "infra1").Build()).
1679+
WithInfraClusterStrategy(&clusterv1.InfrastructureNamingStrategy{Template: ptr.To("template-infra-{{ .invalidkey }}")}).
1680+
WithControlPlaneTemplate(
1681+
builder.ControlPlaneTemplate(metav1.NamespaceDefault, "cp1").
1682+
Build()).
1683+
WithControlPlaneInfrastructureMachineTemplate(
1684+
builder.InfrastructureMachineTemplate(metav1.NamespaceDefault, "cpInfra1").
1685+
Build()).
1686+
Build(),
1687+
expectErr: true,
1688+
},
1689+
{
1690+
name: "should return error for invalid InfraCluster InfrastructureNamingStrategy.template when the generated name does not conform to RFC 1123",
1691+
in: builder.ClusterClass(metav1.NamespaceDefault, "class1").
1692+
WithInfrastructureClusterTemplate(
1693+
builder.InfrastructureClusterTemplate(metav1.NamespaceDefault, "infra1").Build()).
1694+
WithInfraClusterStrategy(&clusterv1.InfrastructureNamingStrategy{Template: ptr.To("template-infra-{{ .cluster.name }}-")}).
1695+
WithControlPlaneTemplate(
1696+
builder.ControlPlaneTemplate(metav1.NamespaceDefault, "cp1").
1697+
Build()).
1698+
WithControlPlaneInfrastructureMachineTemplate(
1699+
builder.InfrastructureMachineTemplate(metav1.NamespaceDefault, "cpInfra1").
1700+
Build()).
1701+
Build(),
1702+
expectErr: true,
1703+
},
16731704
{
16741705
name: "should return error for invalid ControlPlane namingStrategy.template",
16751706
in: builder.ClusterClass(metav1.NamespaceDefault, "class1").

0 commit comments

Comments
 (0)