diff --git a/pkg/model/openstackmodel/servergroup_test.go b/pkg/model/openstackmodel/servergroup_test.go index d56de6d63d..90ce81d396 100644 --- a/pkg/model/openstackmodel/servergroup_test.go +++ b/pkg/model/openstackmodel/servergroup_test.go @@ -19,8 +19,6 @@ package openstackmodel import ( "fmt" "path/filepath" - "reflect" - "sort" "strings" "testing" @@ -40,7 +38,6 @@ type serverGroupModelBuilderTestInput struct { cluster *kops.Cluster instanceGroups []*kops.InstanceGroup expectedTasksBuilder func(cluster *kops.Cluster, instanceGroups []*kops.InstanceGroup) map[string]fi.Task - expectedError error } func getServerGroupModelBuilderTestInput() []serverGroupModelBuilderTestInput { @@ -2918,112 +2915,6 @@ func getServerGroupModelBuilderTestInput() []serverGroupModelBuilderTestInput { } } -func Test_ServerGroupModelBuilder(t *testing.T) { - tests := getServerGroupModelBuilderTestInput() - - for _, testCase := range tests { - t.Run(testCase.desc, func(t *testing.T) { - clusterLifecycle := fi.LifecycleSync - bootstrapScriptBuilder := &model.BootstrapScriptBuilder{ - NodeUpConfigBuilder: &nodeupConfigBuilder{}, - NodeUpSource: map[architectures.Architecture]string{ - architectures.ArchitectureAmd64: "source-amd64", - architectures.ArchitectureArm64: "source-arm64", - }, - NodeUpSourceHash: map[architectures.Architecture]string{ - architectures.ArchitectureAmd64: "source-hash-amd64", - architectures.ArchitectureArm64: "source-hash-arm64", - }, - } - - builder := createBuilderForCluster(testCase.cluster, testCase.instanceGroups, clusterLifecycle, bootstrapScriptBuilder) - - context := &fi.ModelBuilderContext{ - Tasks: make(map[string]fi.Task), - LifecycleOverrides: map[string]fi.Lifecycle{}, - } - - err := builder.Build(context) - - compareErrors(t, err, testCase.expectedError) - - expectedTasks := testCase.expectedTasksBuilder(testCase.cluster, testCase.instanceGroups) - for _, ig := range testCase.instanceGroups { - expectedTasks["BootstrapScript/"+ig.Name] = &model.BootstrapScript{Name: ig.Name} - } - - if len(expectedTasks) != len(context.Tasks) { - t.Errorf("expected %d tasks, got %d tasks", len(expectedTasks), len(context.Tasks)) - } - - for taskName, task := range context.Tasks { - if strings.HasPrefix(taskName, "BootstrapScript/") { - err = task.Run(&fi.Context{Cluster: testCase.cluster}) - if err != nil { - t.Errorf("failed to run BootstrapScript task: %v", err) - } - } - } - - for taskName, task := range expectedTasks { - actual, ok := context.Tasks[taskName] - if !ok { - t.Errorf("did not find a task for key %q", taskName) - continue - } - switch expected := task.(type) { - case *openstacktasks.ServerGroup: - t.Run("creates a task for "+taskName, func(t *testing.T) { - compareServerGroups(t, actual, expected) - }) - case *openstacktasks.Port: - t.Run("creates a task for "+taskName, func(t *testing.T) { - comparePorts(t, actual, expected) - }) - case *openstacktasks.FloatingIP: - t.Run("creates a task for "+taskName, func(t *testing.T) { - compareFloatingIPs(t, actual, expected) - }) - case *openstacktasks.Instance: - t.Run("creates a task for "+taskName, func(t *testing.T) { - compareInstances(t, actual, expected) - }) - case *openstacktasks.LB: - t.Run("creates a task for "+taskName, func(t *testing.T) { - compareLoadbalancers(t, actual, expected) - }) - case *openstacktasks.LBPool: - t.Run("creates a task for "+taskName, func(t *testing.T) { - compareLBPools(t, actual, expected) - }) - case *openstacktasks.PoolAssociation: - t.Run("creates a task for "+taskName, func(t *testing.T) { - comparePoolAssociations(t, actual, expected) - }) - case *openstacktasks.LBListener: - t.Run("creates a task for "+taskName, func(t *testing.T) { - compareLBListeners(t, actual, expected) - }) - case *openstacktasks.SecurityGroup: - t.Run("creates a task for "+taskName, func(t *testing.T) { - compareSecurityGroups(t, actual, expected) - }) - case *model.BootstrapScript: - // ignore - default: - t.Errorf("found a task with name %q and type %T", taskName, expected) - } - } - if t.Failed() { - t.Logf("created tasks:") - for k := range context.Tasks { - t.Logf("- %v", k) - } - } - }) - } -} - func createBuilderForCluster(cluster *kops.Cluster, instanceGroups []*kops.InstanceGroup, clusterLifecycle fi.Lifecycle, bootstrapScriptBuilder *model.BootstrapScriptBuilder) *ServerGroupModelBuilder { sshPublicKey := []byte("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDF2sghZsClUBXJB4mBMIw8rb0hJWjg1Vz4eUeXwYmTdi92Gf1zNc5xISSip9Y+PWX/jJokPB7tgPnMD/2JOAKhG1bi4ZqB15pYRmbbBekVpM4o4E0dx+czbqjiAm6wlccTrINK5LYenbucAAQt19eH+D0gJwzYUK9SYz1hWnlGS+qurt2bz7rrsG73lN8E2eiNvGtIXqv3GabW/Hea3acOBgCUJQWUDTRu0OmmwxzKbFN/UpNKeRaHlCqwZWjVAsmqA8TX8LIocq7Np7MmIBwt7EpEeZJxThcmC8DEJs9ClAjD+jlLIvMPXKC3JWCPgwCLGxHjy7ckSGFCSzbyPduh") @@ -3043,368 +2934,6 @@ func createBuilderForCluster(cluster *kops.Cluster, instanceGroups []*kops.Insta } } -func comparePorts(t *testing.T, actualTask fi.Task, expected *openstacktasks.Port) { - t.Helper() - if pointersAreBothNil(t, "Port", actualTask, expected) { - return - } - actual, ok := actualTask.(*openstacktasks.Port) - if !ok { - t.Fatalf("task is not a port task, got %T", actualTask) - } - - compareStrings(t, "Name", actual.Name, expected.Name) - compareSecurityGroupLists(t, actual.SecurityGroups, expected.SecurityGroups) - sort.Strings(actual.AdditionalSecurityGroups) - sort.Strings(expected.AdditionalSecurityGroups) - actualSgs := strings.Join(actual.AdditionalSecurityGroups, " ") - expectedSgs := strings.Join(expected.AdditionalSecurityGroups, " ") - if actualSgs != expectedSgs { - t.Errorf("AdditionalSecurityGroups differ: %q instead of %q", actualSgs, expectedSgs) - } - compareLifecycles(t, actual.Lifecycle, expected.Lifecycle) - if actual.Network == nil { - t.Fatal("Network is nil") - } - compareStrings(t, "Network name", actual.Network.Name, expected.Network.Name) - if len(actual.Subnets) == len(expected.Subnets) { - for i, subnet := range expected.Subnets { - compareSubnets(t, actual.Subnets[i], subnet) - } - } else { - compareNamedTasks(t, "Subnets", asHasName(actual.Subnets), asHasName(expected.Subnets)) - } -} - -func asHasName(tasks interface{}) []fi.HasName { - var namedTasks []fi.HasName - rType := reflect.TypeOf(tasks) - if rType.Kind() != reflect.Array && rType.Kind() != reflect.Slice { - fmt.Printf("type is not an array or slice: %v\n", rType.Kind()) - return namedTasks - } - rVal := reflect.ValueOf(tasks) - for i := 0; i < rVal.Len(); i++ { - elem := rVal.Index(i) - if named, ok := elem.Interface().(fi.HasName); ok { - namedTasks = append(namedTasks, named) - } - } - return namedTasks -} - -func compareNamedTasks(t *testing.T, name string, actual, expected []fi.HasName) { - actualTaskNames := make([]string, len(actual)) - for i, task := range actual { - actualTaskNames[i] = *task.GetName() - } - sort.Strings(actualTaskNames) - expectedTaskNames := make([]string, len(expected)) - for i, task := range expected { - if task.GetName() == nil { - expectedTaskNames[i] = "" - } else { - expectedTaskNames[i] = *task.GetName() - } - } - sort.Strings(expectedTaskNames) - if !reflect.DeepEqual(expectedTaskNames, actualTaskNames) { - t.Errorf("%s differ: %v instead of %v", name, actualTaskNames, expectedTaskNames) - } -} - -func compareSubnets(t *testing.T, actualTask fi.Task, expected *openstacktasks.Subnet) { - t.Helper() - if pointersAreBothNil(t, "Subnet", actualTask, expected) { - return - } - actual, ok := actualTask.(*openstacktasks.Subnet) - if !ok { - t.Fatalf("task is not an Subnet task, got %T", actualTask) - } - - compareStrings(t, "Name", actual.Name, expected.Name) -} - -func compareInstances(t *testing.T, actualTask fi.Task, expected *openstacktasks.Instance) { - t.Helper() - if pointersAreBothNil(t, "Instance", actualTask, expected) { - return - } - actual, ok := actualTask.(*openstacktasks.Instance) - if !ok { - t.Fatalf("task is not an instance task, got %T", actualTask) - } - - compareStrings(t, "Name", actual.Name, expected.Name) - compareStrings(t, "Region", actual.Region, expected.Region) - compareStrings(t, "Flavor", actual.Flavor, expected.Flavor) - compareStrings(t, "Image", actual.Image, expected.Image) - compareStrings(t, "SSHKey", actual.SSHKey, expected.SSHKey) - compareStrings(t, "Role", actual.Role, expected.Role) - compareUserData(t, actual.UserData, expected.UserData) - compareStrings(t, "AvailabilityZone", actual.AvailabilityZone, expected.AvailabilityZone) - comparePorts(t, actual.Port, expected.Port) - compareServerGroups(t, actual.ServerGroup, expected.ServerGroup) - if !reflect.DeepEqual(actual.Metadata, expected.Metadata) { - t.Errorf("Metadata differ:\n%v\n\tinstead of\n%v", actual.Metadata, expected.Metadata) - } - sort.Strings(actual.SecurityGroups) - sort.Strings(expected.SecurityGroups) - actualSgs := strings.Join(actual.SecurityGroups, " ") - expectedSgs := strings.Join(expected.SecurityGroups, " ") - if actualSgs != expectedSgs { - t.Errorf("SecurityGroups differ: %q instead of %q", actualSgs, expectedSgs) - } -} - -func compareLoadbalancers(t *testing.T, actualTask fi.Task, expected *openstacktasks.LB) { - t.Helper() - if pointersAreBothNil(t, "Loadbalancer", actualTask, expected) { - return - } - actual, ok := actualTask.(*openstacktasks.LB) - if !ok { - t.Fatalf("task is not a loadbalancer task, got %T", actualTask) - } - compareStrings(t, "Name", actual.Name, expected.Name) - compareLifecycles(t, actual.Lifecycle, expected.Lifecycle) - compareStrings(t, "Subnet", actual.Subnet, expected.Subnet) - compareSecurityGroupLists(t, []*openstacktasks.SecurityGroup{actual.SecurityGroup}, []*openstacktasks.SecurityGroup{expected.SecurityGroup}) -} - -func compareLBPools(t *testing.T, actualTask fi.Task, expected *openstacktasks.LBPool) { - t.Helper() - if pointersAreBothNil(t, "LBPool", actualTask, expected) { - return - } - actual, ok := actualTask.(*openstacktasks.LBPool) - if !ok { - t.Fatalf("task is not a LBPool task, got %T", actualTask) - } - compareStrings(t, "Name", actual.Name, expected.Name) - compareLifecycles(t, actual.Lifecycle, expected.Lifecycle) - compareLoadbalancers(t, actual.Loadbalancer, expected.Loadbalancer) -} - -func compareLBListeners(t *testing.T, actualTask fi.Task, expected *openstacktasks.LBListener) { - t.Helper() - if pointersAreBothNil(t, "LBListener", actualTask, expected) { - return - } - actual, ok := actualTask.(*openstacktasks.LBListener) - if !ok { - t.Fatalf("task is not a LBListener task, got %T", actualTask) - } - compareStrings(t, "Name", actual.Name, expected.Name) - compareLifecycles(t, actual.Lifecycle, expected.Lifecycle) - compareLBPools(t, actual.Pool, expected.Pool) -} - -func comparePoolAssociations(t *testing.T, actualTask fi.Task, expected *openstacktasks.PoolAssociation) { - t.Helper() - if pointersAreBothNil(t, "PoolAssociation", actualTask, expected) { - return - } - actual, ok := actualTask.(*openstacktasks.PoolAssociation) - if !ok { - t.Fatalf("task is not a PoolAssociation task, got %T", actualTask) - } - compareStrings(t, "Name", actual.Name, expected.Name) - compareLifecycles(t, actual.Lifecycle, expected.Lifecycle) - compareLBPools(t, actual.Pool, expected.Pool) - compareInts(t, "ProtocolPort", actual.ProtocolPort, expected.ProtocolPort) - compareStrings(t, "InterfaceName", actual.InterfaceName, expected.InterfaceName) - compareServerGroups(t, actual.ServerGroup, expected.ServerGroup) -} - -func compareServerGroups(t *testing.T, actualTask fi.Task, expected *openstacktasks.ServerGroup) { - t.Helper() - if pointersAreBothNil(t, "ServerGroup", actualTask, expected) { - return - } - actual, ok := actualTask.(*openstacktasks.ServerGroup) - if !ok { - t.Fatalf("task is not a server group task, got %T", actualTask) - } - compareStrings(t, "Name", actual.Name, expected.Name) - compareStrings(t, "ClusterName", actual.ClusterName, expected.ClusterName) - compareStrings(t, "IGName", actual.IGName, expected.IGName) - compareLifecycles(t, actual.Lifecycle, expected.Lifecycle) - if !reflect.DeepEqual(actual.Policies, expected.Policies) { - t.Errorf("Policies differ:\n%v\n\tinstead of\n%v", actual.Policies, expected.Policies) - } - compareInt32s(t, "MaxSize", actual.MaxSize, expected.MaxSize) -} - -func compareFloatingIPs(t *testing.T, actualTask fi.Task, expected *openstacktasks.FloatingIP) { - t.Helper() - if pointersAreBothNil(t, "FloatingIP", actualTask, expected) { - return - } - actual, ok := actualTask.(*openstacktasks.FloatingIP) - if !ok { - t.Fatalf("task is not a floating ip task, got %T", actualTask) - } - - compareStrings(t, "Name", actual.Name, expected.Name) - compareLifecycles(t, actual.Lifecycle, expected.Lifecycle) - compareLoadbalancers(t, actual.LB, expected.LB) -} - -func compareLifecycles(t *testing.T, actual, expected *fi.Lifecycle) { - t.Helper() - if pointersAreBothNil(t, "Lifecycle", actual, expected) { - return - } - if !reflect.DeepEqual(actual, expected) { - var a, e string - if actual != nil { - a = string(*actual) - } - if expected != nil { - e = string(*expected) - } - t.Errorf("Lifecycle differs: %+v instead of %+v", a, e) - } -} - -func compareSecurityGroups(t *testing.T, actualTask fi.Task, expected *openstacktasks.SecurityGroup) { - t.Helper() - if pointersAreBothNil(t, "SecurityGroup", actualTask, expected) { - return - } - actual, ok := actualTask.(*openstacktasks.SecurityGroup) - if !ok { - t.Fatalf("task is not a security group task, got %T", actualTask) - } - - compareStrings(t, "Name", actual.Name, expected.Name) - compareLifecycles(t, actual.Lifecycle, expected.Lifecycle) - compareStrings(t, "Description", actual.Description, expected.Description) -} - -func compareSecurityGroupLists(t *testing.T, actual, expected []*openstacktasks.SecurityGroup) { - sgs := make([]string, len(actual)) - for i, sg := range actual { - sgs[i] = *sg.Name - } - sort.Strings(sgs) - expectedSgs := make([]string, len(expected)) - for i, sg := range expected { - if sg.Name == nil { - expectedSgs[i] = "" - } else { - expectedSgs[i] = *sg.Name - } - } - sort.Strings(expectedSgs) - if !reflect.DeepEqual(expectedSgs, sgs) { - t.Errorf("SecurityGroups differ: %v instead of %v", sgs, expectedSgs) - } -} - -func compareStrings(t *testing.T, name string, actual, expected *string) { - t.Helper() - if !reflect.DeepEqual(actual, expected) { - var a, e string - if actual != nil { - a = *actual - } - if expected != nil { - e = *expected - } - t.Errorf("%s differs: %+v instead of %+v", name, a, e) - } -} - -func compareUserData(t *testing.T, actual, expected *fi.ResourceHolder) { - t.Helper() - if pointersAreBothNil(t, "UserData", actual, expected) { - return - } - if !reflect.DeepEqual(actual, expected) { - var a, e string - var err error - if actual != nil { - a, err = actual.AsString() - if err != nil { - t.Errorf("error getting actual: %v", err) - } - } - if expected != nil { - e, err = expected.AsString() - if err != nil { - t.Errorf("error getting actual: %v", err) - } - } - aLines := strings.Split(a, "\n") - eLines := strings.Split(e, "\n") - sort.Strings(aLines) - sort.Strings(eLines) - if !reflect.DeepEqual(aLines, eLines) { - t.Errorf("UserData differ: %+v instead of %+v", a, e) - } - } -} - -func compareInts(t *testing.T, name string, actual, expected *int) { - t.Helper() - if !reflect.DeepEqual(actual, expected) { - var a, e int - if actual != nil { - a = *actual - } - if expected != nil { - e = *expected - } - t.Errorf("%s differs: %+v instead of %+v", name, a, e) - } -} - -func compareInt32s(t *testing.T, name string, actual, expected *int32) { - t.Helper() - if !reflect.DeepEqual(actual, expected) { - var a, e int32 - if actual != nil { - a = *actual - } - if expected != nil { - e = *expected - } - t.Errorf("%s differs: %+v instead of %+v", name, a, e) - } -} - -func pointersAreBothNil(t *testing.T, name string, actual, expected interface{}) bool { - t.Helper() - if actual == nil && expected == nil { - return true - } - if reflect.ValueOf(actual).IsNil() && reflect.ValueOf(expected).IsNil() { - return true - } - if actual == nil && expected != nil { - t.Errorf("%s differ: actual is nil, expected is not", name) - } - if actual != nil && expected == nil { - t.Errorf("%s differ: expected is nil, actual is not", name) - } - return false -} - -func compareErrors(t *testing.T, actual, expected error) { - t.Helper() - if pointersAreBothNil(t, "errors", actual, expected) { - return - } - a := fmt.Sprintf("%v", actual) - e := fmt.Sprintf("%v", expected) - if a != e { - t.Errorf("error differs: %+v instead of %+v", actual, expected) - } -} - type nodeupConfigBuilder struct { }