diff --git a/deploy/crds/atlassian.com_cyclenoderequests_crd.yaml b/deploy/crds/atlassian.com_cyclenoderequests_crd.yaml index da37872..d6225e5 100644 --- a/deploy/crds/atlassian.com_cyclenoderequests_crd.yaml +++ b/deploy/crds/atlassian.com_cyclenoderequests_crd.yaml @@ -103,13 +103,6 @@ spec: - Drain - Wait type: string - strictValidation: - description: StrictValidation is a boolean which determines whether - named nodes selected in a CNR must exist and be valid nodes - before cycling can begin. If set to true when invalid nodes - are selected the CNR will be transitioned to the "Failed" phase - before cycling can begin again. - type: boolean required: - method type: object @@ -336,6 +329,19 @@ spec: description: SkipPreTerminationChecks is an optional flag to skip pre-termination checks during cycling type: boolean + validationOptions: + description: ValidationOptions stores the settings to use for validating + state of nodegroups in kube and the cloud provider for cycling the + nodes. + properties: + skipMissingNamedNodes: + description: SkipMissingNodeNames is a boolean which determines + whether named nodes selected in a CNR must exist and be valid + nodes before cycling can begin. If set to true named nodes which + don't exist will be ignored rather than transitioning the CNR + to the failed phase. + type: boolean + type: object required: - cycleSettings - nodeGroupName diff --git a/deploy/crds/atlassian.com_cyclenodestatuses_crd.yaml b/deploy/crds/atlassian.com_cyclenodestatuses_crd.yaml index 358ea72..f53d3e4 100644 --- a/deploy/crds/atlassian.com_cyclenodestatuses_crd.yaml +++ b/deploy/crds/atlassian.com_cyclenodestatuses_crd.yaml @@ -101,13 +101,6 @@ spec: - Drain - Wait type: string - strictValidation: - description: StrictValidation is a boolean which determines whether - named nodes selected in a CNR must exist and be valid nodes - before cycling can begin. If set to true when invalid nodes - are selected the CNR will be transitioned to the "Failed" phase - before cycling can begin again. - type: boolean required: - method type: object diff --git a/deploy/crds/atlassian.com_nodegroups_crd.yaml b/deploy/crds/atlassian.com_nodegroups_crd.yaml index 08b822c..d75ee73 100644 --- a/deploy/crds/atlassian.com_nodegroups_crd.yaml +++ b/deploy/crds/atlassian.com_nodegroups_crd.yaml @@ -93,13 +93,6 @@ spec: - Drain - Wait type: string - strictValidation: - description: StrictValidation is a boolean which determines whether - named nodes selected in a CNR must exist and be valid nodes - before cycling can begin. If set to true when invalid nodes - are selected the CNR will be transitioned to the "Failed" phase - before cycling can begin again. - type: boolean required: - method type: object diff --git a/pkg/apis/atlassian/v1/common_types.go b/pkg/apis/atlassian/v1/common_types.go index 98e71f6..09236dc 100644 --- a/pkg/apis/atlassian/v1/common_types.go +++ b/pkg/apis/atlassian/v1/common_types.go @@ -46,11 +46,6 @@ type CycleSettings struct { // in-progress CNS request timeout from the time it's worked on by the controller. // If no cyclingTimeout is provided, CNS will use the default controller CNS cyclingTimeout. CyclingTimeout *metav1.Duration `json:"cyclingTimeout,omitempty"` - - // StrictValidation is a boolean which determines whether named nodes selected in a CNR must - // exist and be valid nodes before cycling can begin. If set to true when invalid nodes are - // selected the CNR will be transitioned to the "Failed" phase before cycling can begin again. - StrictValidation bool `json:"strictValidation,omitempty"` } // HealthCheck defines the health check configuration for the NodeGroup diff --git a/pkg/apis/atlassian/v1/cyclenoderequest_types.go b/pkg/apis/atlassian/v1/cyclenoderequest_types.go index c6009af..5d13c74 100644 --- a/pkg/apis/atlassian/v1/cyclenoderequest_types.go +++ b/pkg/apis/atlassian/v1/cyclenoderequest_types.go @@ -26,6 +26,10 @@ type CycleNodeRequestSpec struct { // CycleSettings stores the settings to use for cycling the nodes. CycleSettings CycleSettings `json:"cycleSettings"` + // ValidationOptions stores the settings to use for validating state of nodegroups + // in kube and the cloud provider for cycling the nodes. + ValidationOptions ValidationOptions `json:"validationOptions,omitempty"` + // HealthChecks stores the settings to configure instance custom health checks HealthChecks []HealthCheck `json:"healthChecks,omitempty"` @@ -107,6 +111,15 @@ type CycleNodeRequestNode struct { PrivateIP string `json:"privateIp,omitempty"` } +// ValidationOptions stores the settings to use for validating state of nodegroups +// in kube and the cloud provider for cycling the nodes. +type ValidationOptions struct { + // SkipMissingNodeNames is a boolean which determines whether named nodes selected in a CNR must + // exist and be valid nodes before cycling can begin. If set to true named nodes which don't exist + // will be ignored rather than transitioning the CNR to the failed phase. + SkipMissingNamedNodes bool `json:"skipMissingNamedNodes,omitempty"` +} + // HealthCheckStatus groups all health checks status information for a node type HealthCheckStatus struct { // Ready keeps track of the first timestamp at which the node status was reported as "ready" diff --git a/pkg/apis/atlassian/v1/zz_generated.deepcopy.go b/pkg/apis/atlassian/v1/zz_generated.deepcopy.go index 5df3ee0..09dfe35 100644 --- a/pkg/apis/atlassian/v1/zz_generated.deepcopy.go +++ b/pkg/apis/atlassian/v1/zz_generated.deepcopy.go @@ -102,6 +102,7 @@ func (in *CycleNodeRequestSpec) DeepCopyInto(out *CycleNodeRequestSpec) { copy(*out, *in) } in.CycleSettings.DeepCopyInto(&out.CycleSettings) + out.ValidationOptions = in.ValidationOptions if in.HealthChecks != nil { in, out := &in.HealthChecks, &out.HealthChecks *out = make([]HealthCheck, len(*in)) @@ -585,3 +586,19 @@ func (in *TLSConfig) DeepCopy() *TLSConfig { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ValidationOptions) DeepCopyInto(out *ValidationOptions) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ValidationOptions. +func (in *ValidationOptions) DeepCopy() *ValidationOptions { + if in == nil { + return nil + } + out := new(ValidationOptions) + in.DeepCopyInto(out) + return out +} diff --git a/pkg/controller/cyclenoderequest/transitioner/node.go b/pkg/controller/cyclenoderequest/transitioner/node.go index dc9ad11..d6b7b53 100644 --- a/pkg/controller/cyclenoderequest/transitioner/node.go +++ b/pkg/controller/cyclenoderequest/transitioner/node.go @@ -118,10 +118,11 @@ func (t *CycleNodeRequestTransitioner) addNamedNodesToTerminate(kubeNodes map[st if !found { t.rm.Logger.Info("could not find node by name, skipping", "nodeName", namedNode) - if t.cycleNodeRequest.Spec.CycleSettings.StrictValidation { + if !t.cycleNodeRequest.Spec.ValidationOptions.SkipMissingNamedNodes { return fmt.Errorf("could not find node by name: %v", namedNode) } + t.rm.LogEvent(t.cycleNodeRequest, "SkipMissingNamedNode", "Named node %s not found", namedNode) continue } diff --git a/pkg/controller/cyclenoderequest/transitioner/transitions_pending_test.go b/pkg/controller/cyclenoderequest/transitioner/transitions_pending_test.go index a5cccdd..c95ccaa 100644 --- a/pkg/controller/cyclenoderequest/transitioner/transitions_pending_test.go +++ b/pkg/controller/cyclenoderequest/transitioner/transitions_pending_test.go @@ -114,7 +114,7 @@ func TestPendingWithNamedNode(t *testing.T) { // does not match any of the nodes matching the node selector if strict // validation is not enabled. It will just select the select the nodes that // exist. -func TestPendingWrongNamedNode(t *testing.T) { +func TestPendingWrongNamedNodeSkipMissingNamedNodes(t *testing.T) { nodegroup, err := mock.NewNodegroup("ng-1", 2) if err != nil { assert.NoError(t, err) @@ -131,6 +131,9 @@ func TestPendingWrongNamedNode(t *testing.T) { Concurrency: 1, Method: v1.CycleNodeRequestMethodDrain, }, + ValidationOptions: v1.ValidationOptions{ + SkipMissingNamedNodes: true, + }, Selector: metav1.LabelSelector{ MatchLabels: map[string]string{ "customer": "kitt", @@ -166,7 +169,7 @@ func TestPendingWrongNamedNode(t *testing.T) { // Test to ensure the Pending phase will reject a CNR with a named node that // does not match any of the nodes matching the node selector if strict // validation is enabled. It should error out immediately. -func TestPendingWrongNamedNodeStrictValidation(t *testing.T) { +func TestPendingWrongNamedNode(t *testing.T) { nodegroup, err := mock.NewNodegroup("ng-1", 2) if err != nil { assert.NoError(t, err) @@ -180,9 +183,8 @@ func TestPendingWrongNamedNodeStrictValidation(t *testing.T) { Spec: v1.CycleNodeRequestSpec{ NodeGroupsList: []string{"ng-1"}, CycleSettings: v1.CycleSettings{ - Concurrency: 1, - Method: v1.CycleNodeRequestMethodDrain, - StrictValidation: true, + Concurrency: 1, + Method: v1.CycleNodeRequestMethodDrain, }, Selector: metav1.LabelSelector{ MatchLabels: map[string]string{