From de5bac267c261b043d103b1d6bfad5ea03da5b3a Mon Sep 17 00:00:00 2001 From: Joel Speed Date: Wed, 17 Nov 2021 17:56:57 +0000 Subject: [PATCH] Add LifecycleHooks to Machine spec --- machine/v1beta1/0000_10_machine.crd.yaml | 36 ++++++++++++++++ machine/v1beta1/0000_10_machineset.crd.yaml | 36 ++++++++++++++++ machine/v1beta1/types_machine.go | 39 +++++++++++++++++ machine/v1beta1/zz_generated.deepcopy.go | 43 +++++++++++++++++++ .../zz_generated.swagger_doc_generated.go | 31 ++++++++++--- 5 files changed, 180 insertions(+), 5 deletions(-) diff --git a/machine/v1beta1/0000_10_machine.crd.yaml b/machine/v1beta1/0000_10_machine.crd.yaml index 0e4fb4c5c95..e2da996b9c4 100644 --- a/machine/v1beta1/0000_10_machine.crd.yaml +++ b/machine/v1beta1/0000_10_machine.crd.yaml @@ -70,6 +70,42 @@ spec: description: MachineSpec defines the desired state of Machine type: object properties: + lifecycleHooks: + description: LifecycleHooks allow users to pause operations on the machine at certain predefined points within the machine lifecycle. + type: object + properties: + preDrain: + description: PreDrain hooks prevent the machine from being drained. This also blocks further lifecycle events, such as termination. + type: array + items: + description: LifecycleHook represents a single instance of a lifecycle hook + type: object + properties: + name: + description: Name defines a unique name for the lifcycle hook. The name should be unique and descriptive, ideally 1-3 words, in CamelCase with no spaces. Names must be unique and should only be managed by a single entity. + type: string + maxLength: 256 + minLength: 3 + pattern: '[A-Za-z]+' + owner: + description: Owner defines the owner of the lifecycle hook. This should be descriptive enough so that users can identify who/what is responsible for blocking the lifecycle. This could be the name of a controller (e.g. clusteroperator/etcd) or an administrator managing the hook. + type: string + preTerminate: + description: PreTerminate hooks prevent the machine from being terminated. PreTerminate hooks be actioned after the Machine has been drained. + type: array + items: + description: LifecycleHook represents a single instance of a lifecycle hook + type: object + properties: + name: + description: Name defines a unique name for the lifcycle hook. The name should be unique and descriptive, ideally 1-3 words, in CamelCase with no spaces. Names must be unique and should only be managed by a single entity. + type: string + maxLength: 256 + minLength: 3 + pattern: '[A-Za-z]+' + owner: + description: Owner defines the owner of the lifecycle hook. This should be descriptive enough so that users can identify who/what is responsible for blocking the lifecycle. This could be the name of a controller (e.g. clusteroperator/etcd) or an administrator managing the hook. + type: string metadata: description: ObjectMeta will autopopulate the Node created. Use this to indicate what labels, annotations, name prefix, etc., should be used when creating the Node. type: object diff --git a/machine/v1beta1/0000_10_machineset.crd.yaml b/machine/v1beta1/0000_10_machineset.crd.yaml index 8bc57660de4..b831a142d8f 100644 --- a/machine/v1beta1/0000_10_machineset.crd.yaml +++ b/machine/v1beta1/0000_10_machineset.crd.yaml @@ -163,6 +163,42 @@ spec: description: 'Specification of the desired behavior of the machine. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status' type: object properties: + lifecycleHooks: + description: LifecycleHooks allow users to pause operations on the machine at certain predefined points within the machine lifecycle. + type: object + properties: + preDrain: + description: PreDrain hooks prevent the machine from being drained. This also blocks further lifecycle events, such as termination. + type: array + items: + description: LifecycleHook represents a single instance of a lifecycle hook + type: object + properties: + name: + description: Name defines a unique name for the lifcycle hook. The name should be unique and descriptive, ideally 1-3 words, in CamelCase with no spaces. Names must be unique and should only be managed by a single entity. + type: string + maxLength: 256 + minLength: 3 + pattern: '[A-Za-z]+' + owner: + description: Owner defines the owner of the lifecycle hook. This should be descriptive enough so that users can identify who/what is responsible for blocking the lifecycle. This could be the name of a controller (e.g. clusteroperator/etcd) or an administrator managing the hook. + type: string + preTerminate: + description: PreTerminate hooks prevent the machine from being terminated. PreTerminate hooks be actioned after the Machine has been drained. + type: array + items: + description: LifecycleHook represents a single instance of a lifecycle hook + type: object + properties: + name: + description: Name defines a unique name for the lifcycle hook. The name should be unique and descriptive, ideally 1-3 words, in CamelCase with no spaces. Names must be unique and should only be managed by a single entity. + type: string + maxLength: 256 + minLength: 3 + pattern: '[A-Za-z]+' + owner: + description: Owner defines the owner of the lifecycle hook. This should be descriptive enough so that users can identify who/what is responsible for blocking the lifecycle. This could be the name of a controller (e.g. clusteroperator/etcd) or an administrator managing the hook. + type: string metadata: description: ObjectMeta will autopopulate the Node created. Use this to indicate what labels, annotations, name prefix, etc., should be used when creating the Node. type: object diff --git a/machine/v1beta1/types_machine.go b/machine/v1beta1/types_machine.go index 73c33e44d31..1f179693070 100644 --- a/machine/v1beta1/types_machine.go +++ b/machine/v1beta1/types_machine.go @@ -167,6 +167,11 @@ type MachineSpec struct { // +optional ObjectMeta `json:"metadata,omitempty"` + // LifecycleHooks allow users to pause operations on the machine at + // certain predefined points within the machine lifecycle. + // +optional + LifecycleHooks LifecycleHooks `json:"lifecycleHooks,omitempty"` + // The list of the taints to be applied to the corresponding Node in additive // manner. This list will not overwrite any other taints added to the Node on // an ongoing basis by other entities. These taints should be actively reconciled @@ -194,6 +199,40 @@ type MachineSpec struct { ProviderID *string `json:"providerID,omitempty"` } +// LifecycleHooks allow users to pause operations on the machine at +// certain prefedined points within the machine lifecycle. +type LifecycleHooks struct { + // PreDrain hooks prevent the machine from being drained. + // This also blocks further lifecycle events, such as termination. + // +optional + PreDrain []LifecycleHook `json:"preDrain,omitempty"` + + // PreTerminate hooks prevent the machine from being terminated. + // PreTerminate hooks be actioned after the Machine has been drained. + // +optional + PreTerminate []LifecycleHook `json:"preTerminate,omitempty"` +} + +// LifecycleHook represents a single instance of a lifecycle hook +type LifecycleHook struct { + // Name defines a unique name for the lifcycle hook. + // The name should be unique and descriptive, ideally 1-3 words, in CamelCase with no spaces. + // Names must be unique and should only be managed by a single entity. + // +kubebuilder:validation:Pattern:="[A-Za-z]+" + // +kubebuilder:validation:MinLength:=3 + // +kubebuilder:validation:MaxLength:=256 + // +required + Name string `json:"name"` + + // Owner defines the owner of the lifecycle hook. + // This should be descriptive enough so that users can identify + // who/what is responsible for blocking the lifecycle. + // This could be the name of a controller (e.g. clusteroperator/etcd) + // or an administrator managing the hook. + // +required + Owner string `json:"owner"` +} + // MachineStatus defines the observed state of Machine type MachineStatus struct { // NodeRef will point to the corresponding Node if it exists. diff --git a/machine/v1beta1/zz_generated.deepcopy.go b/machine/v1beta1/zz_generated.deepcopy.go index fb98815aa79..7c8506a7134 100644 --- a/machine/v1beta1/zz_generated.deepcopy.go +++ b/machine/v1beta1/zz_generated.deepcopy.go @@ -801,6 +801,48 @@ func (in *LastOperation) DeepCopy() *LastOperation { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LifecycleHook) DeepCopyInto(out *LifecycleHook) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LifecycleHook. +func (in *LifecycleHook) DeepCopy() *LifecycleHook { + if in == nil { + return nil + } + out := new(LifecycleHook) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LifecycleHooks) DeepCopyInto(out *LifecycleHooks) { + *out = *in + if in.PreDrain != nil { + in, out := &in.PreDrain, &out.PreDrain + *out = make([]LifecycleHook, len(*in)) + copy(*out, *in) + } + if in.PreTerminate != nil { + in, out := &in.PreTerminate, &out.PreTerminate + *out = make([]LifecycleHook, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LifecycleHooks. +func (in *LifecycleHooks) DeepCopy() *LifecycleHooks { + if in == nil { + return nil + } + out := new(LifecycleHooks) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *LoadBalancerReference) DeepCopyInto(out *LoadBalancerReference) { *out = *in @@ -1123,6 +1165,7 @@ func (in *MachineSetStatus) DeepCopy() *MachineSetStatus { func (in *MachineSpec) DeepCopyInto(out *MachineSpec) { *out = *in in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.LifecycleHooks.DeepCopyInto(&out.LifecycleHooks) if in.Taints != nil { in, out := &in.Taints, &out.Taints *out = make([]v1.Taint, len(*in)) diff --git a/machine/v1beta1/zz_generated.swagger_doc_generated.go b/machine/v1beta1/zz_generated.swagger_doc_generated.go index 6b569f4aaa3..434b3550ac1 100644 --- a/machine/v1beta1/zz_generated.swagger_doc_generated.go +++ b/machine/v1beta1/zz_generated.swagger_doc_generated.go @@ -399,6 +399,26 @@ func (LastOperation) SwaggerDoc() map[string]string { return map_LastOperation } +var map_LifecycleHook = map[string]string{ + "": "LifecycleHook represents a single instance of a lifecycle hook", + "name": "Name defines a unique name for the lifcycle hook. The name should be unique and descriptive, ideally 1-3 words, in CamelCase with no spaces. Names must be unique and should only be managed by a single entity.", + "owner": "Owner defines the owner of the lifecycle hook. This should be descriptive enough so that users can identify who/what is responsible for blocking the lifecycle. This could be the name of a controller (e.g. clusteroperator/etcd) or an administrator managing the hook.", +} + +func (LifecycleHook) SwaggerDoc() map[string]string { + return map_LifecycleHook +} + +var map_LifecycleHooks = map[string]string{ + "": "LifecycleHooks allow users to pause operations on the machine at certain prefedined points within the machine lifecycle.", + "preDrain": "PreDrain hooks prevent the machine from being drained. This also blocks further lifecycle events, such as termination.", + "preTerminate": "PreTerminate hooks prevent the machine from being terminated. PreTerminate hooks be actioned after the Machine has been drained.", +} + +func (LifecycleHooks) SwaggerDoc() map[string]string { + return map_LifecycleHooks +} + var map_Machine = map[string]string{ "": "Machine is the Schema for the machines API Compatibility level 2: Stable within a major release for a minimum of 9 months or 3 minor releases (whichever is longer).", } @@ -416,11 +436,12 @@ func (MachineList) SwaggerDoc() map[string]string { } var map_MachineSpec = map[string]string{ - "": "MachineSpec defines the desired state of Machine", - "metadata": "ObjectMeta will autopopulate the Node created. Use this to indicate what labels, annotations, name prefix, etc., should be used when creating the Node.", - "taints": "The list of the taints to be applied to the corresponding Node in additive manner. This list will not overwrite any other taints added to the Node on an ongoing basis by other entities. These taints should be actively reconciled e.g. if you ask the machine controller to apply a taint and then manually remove the taint the machine controller will put it back) but not have the machine controller remove any taints", - "providerSpec": "ProviderSpec details Provider-specific configuration to use during node creation.", - "providerID": "ProviderID is the identification ID of the machine provided by the provider. This field must match the provider ID as seen on the node object corresponding to this machine. This field is required by higher level consumers of cluster-api. Example use case is cluster autoscaler with cluster-api as provider. Clean-up logic in the autoscaler compares machines to nodes to find out machines at provider which could not get registered as Kubernetes nodes. With cluster-api as a generic out-of-tree provider for autoscaler, this field is required by autoscaler to be able to have a provider view of the list of machines. Another list of nodes is queried from the k8s apiserver and then a comparison is done to find out unregistered machines and are marked for delete. This field will be set by the actuators and consumed by higher level entities like autoscaler that will be interfacing with cluster-api as generic provider.", + "": "MachineSpec defines the desired state of Machine", + "metadata": "ObjectMeta will autopopulate the Node created. Use this to indicate what labels, annotations, name prefix, etc., should be used when creating the Node.", + "lifecycleHooks": "LifecycleHooks allow users to pause operations on the machine at certain predefined points within the machine lifecycle.", + "taints": "The list of the taints to be applied to the corresponding Node in additive manner. This list will not overwrite any other taints added to the Node on an ongoing basis by other entities. These taints should be actively reconciled e.g. if you ask the machine controller to apply a taint and then manually remove the taint the machine controller will put it back) but not have the machine controller remove any taints", + "providerSpec": "ProviderSpec details Provider-specific configuration to use during node creation.", + "providerID": "ProviderID is the identification ID of the machine provided by the provider. This field must match the provider ID as seen on the node object corresponding to this machine. This field is required by higher level consumers of cluster-api. Example use case is cluster autoscaler with cluster-api as provider. Clean-up logic in the autoscaler compares machines to nodes to find out machines at provider which could not get registered as Kubernetes nodes. With cluster-api as a generic out-of-tree provider for autoscaler, this field is required by autoscaler to be able to have a provider view of the list of machines. Another list of nodes is queried from the k8s apiserver and then a comparison is done to find out unregistered machines and are marked for delete. This field will be set by the actuators and consumed by higher level entities like autoscaler that will be interfacing with cluster-api as generic provider.", } func (MachineSpec) SwaggerDoc() map[string]string {