Skip to content

Commit

Permalink
Add NamingStrategy to MachineDeployment
Browse files Browse the repository at this point in the history
Signed-off-by: Muhammad Adil Ghaffar <[email protected]>
  • Loading branch information
adilGhaffarDev committed Oct 29, 2024
1 parent 6c04105 commit 6c5de96
Show file tree
Hide file tree
Showing 12 changed files with 403 additions and 69 deletions.
22 changes: 22 additions & 0 deletions api/v1beta1/machinedeployment_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,11 @@ type MachineDeploymentSpec struct {
// +optional
Strategy *MachineDeploymentStrategy `json:"strategy,omitempty"`

// MachineNamingStrategy allows changing the naming pattern used when creating Machines.
// Note: InfraMachines will use the same name as the corresponding Machines.
// +optional
MachineNamingStrategy *MachineNamingStrategy `json:"machineNamingStrategy,omitempty"`

// MinReadySeconds is the minimum number of seconds for which a Node for a newly created machine should be ready before considering the replica available.
// Defaults to 0 (machine will be considered available as soon as the Node is ready)
// +optional
Expand Down Expand Up @@ -250,6 +255,23 @@ type RemediationStrategy struct {

// ANCHOR_END: RemediationStrategy

// MachineNamingStrategy allows changing the naming pattern used when creating Machines.
// Note: InfraMachines will use the same name as the corresponding Machines.
type MachineNamingStrategy struct {
// Template defines the template to use for generating the names of the Machine objects.
// If not defined, it will fallback to `{{ .machineDeployment.name }}-{{ .random }}`.
// If the generated name string exceeds 63 characters, it will be trimmed to 58 characters and will
// get concatenated with a random suffix of length 5.
// Length of the template string must not exceed 256 characters.
// The template allows the following variables `.cluster.name`, `.machineDeployment.name` and `.random`.
// The variable `.cluster.name` retrieves the name of the cluster object that owns the Machines being created.
// The variable `.machineDeployment.name` retrieves the name of the MachineDeployment object that owns the Machines being created.
// The variable `.random` is substituted with random alphanumeric string, without vowels, of length 5.
// +optional
// +kubebuilder:validation:MaxLength=256
Template string `json:"template,omitempty"`
}

// ANCHOR: MachineDeploymentStatus

// MachineDeploymentStatus defines the observed state of MachineDeployment.
Expand Down
20 changes: 20 additions & 0 deletions api/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 28 additions & 1 deletion api/v1beta1/zz_generated.openapi.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions config/crd/bases/cluster.x-k8s.io_machinedeployments.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions internal/apis/core/v1alpha3/conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,10 @@ func (src *MachineDeployment) ConvertTo(dstRaw conversion.Hub) error {
dst.Spec.Strategy.Remediation = restored.Spec.Strategy.Remediation
}

if restored.Spec.MachineNamingStrategy != nil {
dst.Spec.MachineNamingStrategy = restored.Spec.MachineNamingStrategy
}

dst.Spec.Template.Spec.ReadinessGates = restored.Spec.Template.Spec.ReadinessGates
dst.Spec.Template.Spec.NodeDeletionTimeout = restored.Spec.Template.Spec.NodeDeletionTimeout
dst.Spec.Template.Spec.NodeVolumeDetachTimeout = restored.Spec.Template.Spec.NodeVolumeDetachTimeout
Expand Down
1 change: 1 addition & 0 deletions internal/apis/core/v1alpha3/zz_generated.conversion.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions internal/apis/core/v1alpha4/conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,11 @@ func (src *MachineDeployment) ConvertTo(dstRaw conversion.Hub) error {
}
dst.Spec.Strategy.Remediation = restored.Spec.Strategy.Remediation
}

if restored.Spec.MachineNamingStrategy != nil {
dst.Spec.MachineNamingStrategy = restored.Spec.MachineNamingStrategy
}

dst.Status.V1Beta2 = restored.Status.V1Beta2

return nil
Expand Down
1 change: 1 addition & 0 deletions internal/apis/core/v1alpha4/zz_generated.conversion.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

41 changes: 35 additions & 6 deletions internal/controllers/machineset/machineset_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import (
"sigs.k8s.io/cluster-api/controllers/noderefutil"
"sigs.k8s.io/cluster-api/internal/contract"
"sigs.k8s.io/cluster-api/internal/controllers/machine"
topologynames "sigs.k8s.io/cluster-api/internal/topology/names"
"sigs.k8s.io/cluster-api/internal/util/ssa"
"sigs.k8s.io/cluster-api/util"
"sigs.k8s.io/cluster-api/util/collections"
Expand Down Expand Up @@ -518,8 +519,11 @@ func (r *Reconciler) syncMachines(ctx context.Context, s *scope) (ctrl.Result, e
}

// Update Machine to propagate in-place mutable fields from the MachineSet.
updatedMachine := r.computeDesiredMachine(machineSet, m)
err := ssa.Patch(ctx, r.Client, machineSetManagerName, updatedMachine, ssa.WithCachingProxy{Cache: r.ssaCache, Original: m})
updatedMachine, err := r.computeDesiredMachine(ctx, machineSet, m)
if err != nil {
return ctrl.Result{}, errors.Wrap(err, "failed to update Machine: failed to compute desired Machine")
}
err = ssa.Patch(ctx, r.Client, machineSetManagerName, updatedMachine, ssa.WithCachingProxy{Cache: r.ssaCache, Original: m})
if err != nil {
log.Error(err, "Failed to update Machine", "Machine", klog.KObj(updatedMachine))
return ctrl.Result{}, errors.Wrapf(err, "failed to update Machine %q", klog.KObj(updatedMachine))
Expand Down Expand Up @@ -612,7 +616,10 @@ func (r *Reconciler) syncReplicas(ctx context.Context, s *scope) (ctrl.Result, e
for i := range diff {
// Create a new logger so the global logger is not modified.
log := log
machine := r.computeDesiredMachine(ms, nil)
machine, computeMachineErr := r.computeDesiredMachine(ctx, ms, nil)
if computeMachineErr != nil {
return ctrl.Result{}, errors.Wrap(computeMachineErr, "failed to create Machine: failed to compute desired Machine")
}
// Clone and set the infrastructure and bootstrap references.
var (
infraRef, bootstrapRef *corev1.ObjectReference
Expand Down Expand Up @@ -747,14 +754,36 @@ func (r *Reconciler) syncReplicas(ctx context.Context, s *scope) (ctrl.Result, e
// There are small differences in how we calculate the Machine depending on if it
// is a create or update. Example: for a new Machine we have to calculate a new name,
// while for an existing Machine we have to use the name of the existing Machine.
func (r *Reconciler) computeDesiredMachine(machineSet *clusterv1.MachineSet, existingMachine *clusterv1.Machine) *clusterv1.Machine {
func (r *Reconciler) computeDesiredMachine(ctx context.Context, machineSet *clusterv1.MachineSet, existingMachine *clusterv1.Machine) (*clusterv1.Machine, error) {
machineName := names.SimpleNameGenerator.GenerateName(fmt.Sprintf("%s-", machineSet.Name))
// If the MachineSet is part of a MachineDeployment, check MachineNamingStrategy
// and name Machine accordingly.
if isDeploymentChild(machineSet) {
owner, err := r.getOwnerMachineDeployment(ctx, machineSet)
if err != nil {
return nil, err
}
nameTemplate := "{{ .machineDeployment.name }}-{{ .random }}"
if owner.Spec.MachineNamingStrategy != nil && owner.Spec.MachineNamingStrategy.Template != "" {
nameTemplate = owner.Spec.MachineNamingStrategy.Template
if !strings.Contains(nameTemplate, "{{ .random }}") {
return nil, errors.New("cannot generate MachineDeployment machine name: {{ .random }} is missing in machineNamingStrategy.template")
}
}
generatedMachineName, err := topologynames.MachineDeploymentMachineNameGenerator(nameTemplate, machineSet.Spec.ClusterName, owner.Name).GenerateName()
if err != nil {
return nil, errors.Wrap(err, "failed to generate name for MachineDeployment machine")
}
machineName = generatedMachineName
}

desiredMachine := &clusterv1.Machine{
TypeMeta: metav1.TypeMeta{
APIVersion: clusterv1.GroupVersion.String(),
Kind: "Machine",
},
ObjectMeta: metav1.ObjectMeta{
Name: names.SimpleNameGenerator.GenerateName(fmt.Sprintf("%s-", machineSet.Name)),
Name: machineName,
Namespace: machineSet.Namespace,
// Note: By setting the ownerRef on creation we signal to the Machine controller that this is not a stand-alone Machine.
OwnerReferences: []metav1.OwnerReference{*metav1.NewControllerRef(machineSet, machineSetKind)},
Expand Down Expand Up @@ -812,7 +841,7 @@ func (r *Reconciler) computeDesiredMachine(machineSet *clusterv1.MachineSet, exi
desiredMachine.Spec.NodeDeletionTimeout = machineSet.Spec.Template.Spec.NodeDeletionTimeout
desiredMachine.Spec.NodeVolumeDetachTimeout = machineSet.Spec.Template.Spec.NodeVolumeDetachTimeout

return desiredMachine
return desiredMachine, nil
}

// updateExternalObject updates the external object passed in with the
Expand Down
Loading

0 comments on commit 6c5de96

Please sign in to comment.