-
Notifications
You must be signed in to change notification settings - Fork 296
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
✨ add VM naming strategy for VMs in govmomi mode #3286
base: main
Are you sure you want to change the base?
Changes from all commits
0deb41a
782c264
bd815fd
dd8faee
05bb39b
4882411
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -68,6 +68,30 @@ type VSphereMachineSpec struct { | |||||||||
// | ||||||||||
// +optional | ||||||||||
GuestSoftPowerOffTimeout *metav1.Duration `json:"guestSoftPowerOffTimeout,omitempty"` | ||||||||||
|
||||||||||
// NamingStrategy allows configuring the naming strategy used when calculating the name of the VSphereVM. | ||||||||||
// +optional | ||||||||||
NamingStrategy *VSphereVMNamingStrategy `json:"namingStrategy,omitempty"` | ||||||||||
} | ||||||||||
|
||||||||||
// VSphereVMNamingStrategy defines the naming strategy for the VSphereVMs. | ||||||||||
type VSphereVMNamingStrategy struct { | ||||||||||
Comment on lines
+77
to
+78
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should this be named |
||||||||||
// Template defines the template to use for generating the name of the VSphereVM object. | ||||||||||
// If not defined, it will fall back to `{{ .machine.name }}`. | ||||||||||
// The templating has the following data available: | ||||||||||
// * `.machine.name`: The name of the Machine object. | ||||||||||
// The templating also has the following funcs available: | ||||||||||
// * `trimSuffix`: same as strings.TrimSuffix | ||||||||||
// * `trunc`: truncates a string, e.g. `trunc 2 "hello"` or `trunc -2 "hello"` | ||||||||||
// Notes: | ||||||||||
// * While the template offers some flexibility, we would like the name to link to the Machine name | ||||||||||
// to ensure better user experience when troubleshooting | ||||||||||
Comment on lines
+87
to
+88
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
personalization should not be present in official docs (ideally). EDIT: seems consistent with the supervisor PR. so you can leave it as is. |
||||||||||
// * Generated names must be valid Kubernetes names as they are used to create a VSphereVM object | ||||||||||
// and usually also as the name of the Node object. | ||||||||||
// * Names are automatically truncated at 63 characters. Please note that this can lead to name conflicts, | ||||||||||
// so we highly recommend to use a template which leads to a name shorter than 63 characters. | ||||||||||
// +optional | ||||||||||
Template *string `json:"template,omitempty"` | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no need for *string, just string? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. EDIT: seems consistent with the supervisor PR. so you can leave it as is. |
||||||||||
} | ||||||||||
|
||||||||||
// VSphereMachineStatus defines the observed state of VSphereMachine. | ||||||||||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,13 +24,15 @@ import ( | |
|
||
apierrors "k8s.io/apimachinery/pkg/api/errors" | ||
"k8s.io/apimachinery/pkg/runtime" | ||
"k8s.io/apimachinery/pkg/util/validation" | ||
"k8s.io/apimachinery/pkg/util/validation/field" | ||
"sigs.k8s.io/cluster-api/util/topology" | ||
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-vsphere/apis/v1beta1" | ||
"sigs.k8s.io/cluster-api-provider-vsphere/pkg/services" | ||
) | ||
|
||
const machineTemplateImmutableMsg = "VSphereMachineTemplate spec.template.spec field is immutable. Please create a new resource instead." | ||
|
@@ -50,7 +52,7 @@ func (webhook *VSphereMachineTemplateWebhook) SetupWebhookWithManager(mgr ctrl.M | |
} | ||
|
||
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type. | ||
func (webhook *VSphereMachineTemplateWebhook) ValidateCreate(_ context.Context, raw runtime.Object) (admission.Warnings, error) { | ||
func (webhook *VSphereMachineTemplateWebhook) ValidateCreate(ctx context.Context, raw runtime.Object) (admission.Warnings, error) { | ||
obj, ok := raw.(*infrav1.VSphereMachineTemplate) | ||
if !ok { | ||
return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a VSphereMachineTemplate but got a %T", raw)) | ||
|
@@ -87,6 +89,10 @@ func (webhook *VSphereMachineTemplateWebhook) ValidateCreate(_ context.Context, | |
pciErrs := validatePCIDevices(spec.PciDevices) | ||
allErrs = append(allErrs, pciErrs...) | ||
|
||
templateErrs := validateVSphereVMNamingTemplate(ctx, obj) | ||
if len(templateErrs) > 0 { | ||
allErrs = append(allErrs, templateErrs...) | ||
} | ||
return nil, AggregateObjErrors(obj.GroupVersionKind().GroupKind(), obj.Name, allErrs) | ||
} | ||
|
||
|
@@ -111,10 +117,45 @@ func (webhook *VSphereMachineTemplateWebhook) ValidateUpdate(ctx context.Context | |
!reflect.DeepEqual(newTyped.Spec.Template.Spec, oldTyped.Spec.Template.Spec) { | ||
allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "template", "spec"), newTyped, machineTemplateImmutableMsg)) | ||
} | ||
|
||
templateErrs := validateVSphereVMNamingTemplate(ctx, newTyped) | ||
if len(templateErrs) > 0 { | ||
allErrs = append(allErrs, templateErrs...) | ||
} | ||
return nil, AggregateObjErrors(newTyped.GroupVersionKind().GroupKind(), newTyped.Name, allErrs) | ||
} | ||
|
||
// ValidateDelete implements webhook.Validator so a webhook will be registered for the type. | ||
func (webhook *VSphereMachineTemplateWebhook) ValidateDelete(_ context.Context, _ runtime.Object) (admission.Warnings, error) { | ||
return nil, nil | ||
} | ||
|
||
func validateVSphereVMNamingTemplate(_ context.Context, vsphereMachineTemplate *infrav1.VSphereMachineTemplate) field.ErrorList { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is this following some code that core CAPI already has or is this done from scratch as a use case for CAPV? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is based on this MR which was added to support this in supervisor mode #3099 In supervisor mode, the object is called VirtualMachine which drives the creation of vSphere VMs while in govami mode this object is called VSphereVM. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. looks like a lot comes from that PR. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can do that if we prefer that. I just to wanted to call it what it is being used for. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. that would be my preference. not sure what other reviewers will comment on this. |
||
var allErrs field.ErrorList | ||
namingStrategy := vsphereMachineTemplate.Spec.Template.Spec.NamingStrategy | ||
if namingStrategy != nil && namingStrategy.Template != nil { | ||
name, err := services.GenerateVSphereVMName("machine", namingStrategy) | ||
templateFldPath := field.NewPath("spec", "template", "spec", "namingStrategy", "template") | ||
if err != nil { | ||
allErrs = append(allErrs, | ||
field.Invalid( | ||
templateFldPath, | ||
*namingStrategy.Template, | ||
fmt.Sprintf("invalid VSphereVM name template: %v", err), | ||
), | ||
) | ||
} else { | ||
// Note: This validates that the resulting name is a valid Kubernetes object name. | ||
for _, err := range validation.IsDNS1123Subdomain(name) { | ||
allErrs = append(allErrs, | ||
field.Invalid( | ||
templateFldPath, | ||
*namingStrategy.Template, | ||
fmt.Sprintf("invalid VSphereVM name template, generated name is not a valid Kubernetes object name: %v", err), | ||
), | ||
) | ||
} | ||
} | ||
} | ||
return allErrs | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
calculating -> preparing
as it's not a math calculation.
EDIT: seems consistent with the supervisor PR. so you can leave it as is.
this field is inside VSphereMachineSpec not VSphereVMSpec