From a26757bfc2e63ade3e48e13d44b924a0eeb714ab Mon Sep 17 00:00:00 2001 From: John Gardiner Myers Date: Mon, 11 May 2020 20:55:38 -0700 Subject: [PATCH] Return cluster validation failure if ASG missing --- pkg/validation/validate_cluster.go | 17 ++++++++++++-- pkg/validation/validate_cluster_test.go | 31 +++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/pkg/validation/validate_cluster.go b/pkg/validation/validate_cluster.go index 58ac90df61622..3a190be7566b0 100644 --- a/pkg/validation/validate_cluster.go +++ b/pkg/validation/validate_cluster.go @@ -166,7 +166,7 @@ func (v *clusterValidatorImpl) Validate() (*ValidationCluster, error) { if err != nil { return nil, err } - readyNodes := validation.validateNodes(cloudGroups) + readyNodes := validation.validateNodes(cloudGroups, v.instanceGroups) if err := validation.collectComponentFailures(ctx, v.k8sClient); err != nil { return nil, fmt.Errorf("cannot get component status for %q: %v", clusterName, err) @@ -286,13 +286,16 @@ func (v *ValidationCluster) collectPodFailures(ctx context.Context, client kuber return nil } -func (v *ValidationCluster) validateNodes(cloudGroups map[string]*cloudinstances.CloudInstanceGroup) []v1.Node { +func (v *ValidationCluster) validateNodes(cloudGroups map[string]*cloudinstances.CloudInstanceGroup, groups []*kops.InstanceGroup) []v1.Node { var readyNodes []v1.Node + groupsSeen := map[string]bool{} + for _, cloudGroup := range cloudGroups { var allMembers []*cloudinstances.CloudInstanceGroupMember allMembers = append(allMembers, cloudGroup.Ready...) allMembers = append(allMembers, cloudGroup.NeedUpdate...) + groupsSeen[cloudGroup.InstanceGroup.Name] = true numNodes := 0 for _, m := range allMembers { if !m.Detached { @@ -374,5 +377,15 @@ func (v *ValidationCluster) validateNodes(cloudGroups map[string]*cloudinstances } } + for _, ig := range groups { + if !groupsSeen[ig.Name] { + v.addError(&ValidationError{ + Kind: "InstanceGroup", + Name: ig.Name, + Message: fmt.Sprintf("InstanceGroup %q is missing from the cloud provider", ig.Name), + }) + } + } + return readyNodes } diff --git a/pkg/validation/validate_cluster_test.go b/pkg/validation/validate_cluster_test.go index 8829148876782..dc5680654b73e 100644 --- a/pkg/validation/validate_cluster_test.go +++ b/pkg/validation/validate_cluster_test.go @@ -113,6 +113,37 @@ func testValidate(t *testing.T, groups map[string]*cloudinstances.CloudInstanceG return validator.Validate() } +func Test_ValidateCloudGroupMissing(t *testing.T) { + cluster := &kopsapi.Cluster{ + ObjectMeta: metav1.ObjectMeta{Name: "testcluster.k8s.local"}, + } + instanceGroups := []kopsapi.InstanceGroup{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "node-1", + }, + Spec: kopsapi.InstanceGroupSpec{ + Role: kopsapi.InstanceGroupRoleNode, + }, + }, + } + + mockcloud := BuildMockCloud(t, nil, cluster, instanceGroups) + + validator, err := NewClusterValidator(cluster, mockcloud, &kopsapi.InstanceGroupList{Items: instanceGroups}, fake.NewSimpleClientset()) + require.NoError(t, err) + v, err := validator.Validate() + require.NoError(t, err) + if !assert.Len(t, v.Failures, 1) || + !assert.Equal(t, &ValidationError{ + Kind: "InstanceGroup", + Name: "node-1", + Message: "InstanceGroup \"node-1\" is missing from the cloud provider", + }, v.Failures[0]) { + printDebug(t, v) + } +} + func Test_ValidateNodesNotEnough(t *testing.T) { groups := make(map[string]*cloudinstances.CloudInstanceGroup) groups["node-1"] = &cloudinstances.CloudInstanceGroup{