...

Source file src/edge-infra.dev/pkg/edge/api/graph/integration/registration_queries.resolvers_test.go

Documentation: edge-infra.dev/pkg/edge/api/graph/integration

     1  package integration_test
     2  
     3  import (
     4  	"context"
     5  	"strings"
     6  
     7  	"github.com/udacity/graphb"
     8  
     9  	"edge-infra.dev/pkg/edge/api/graph/model"
    10  	testApi "edge-infra.dev/pkg/edge/api/graph/test"
    11  	"edge-infra.dev/pkg/edge/api/services"
    12  	"edge-infra.dev/pkg/edge/api/types"
    13  	"edge-infra.dev/pkg/edge/api/utils"
    14  	"edge-infra.dev/pkg/edge/constants/api/cluster"
    15  	"edge-infra.dev/pkg/edge/constants/api/fleet"
    16  	"edge-infra.dev/pkg/lib/runtime/version"
    17  	"edge-infra.dev/test/framework/integration"
    18  )
    19  
    20  func (s *Suite) TestRegisterCluster() {
    21  	integration.SkipIf(s.Framework)
    22  	createSite := true
    23  	var response struct{ RegisterCluster *model.RegistrationResponse }
    24  	mutation := registerClusterMutation(&model.RegistrationPayload{
    25  		Name:        testStore,
    26  		Fleet:       fleet.Store,
    27  		ClusterType: cluster.GKE,
    28  		StoreInfo: &model.StoreInfo{
    29  			StoreID:    &testStoreID, //using store name as store id, until store id is properly defined
    30  			CreateSite: &createSite,
    31  		},
    32  		BannerName: testOrg,
    33  		ClusterInfo: &model.ClusterInfo{
    34  			Location:    testLocation,
    35  			NodeVersion: &testClusterVersion,
    36  			MachineType: testClusterMachineType,
    37  			NumNodes:    testClusterNumNodes,
    38  		},
    39  	})
    40  	ResolverClient.MustPost(mutation, &response)
    41  	s.NotNil(response.RegisterCluster)
    42  	s.NotEmpty(response.RegisterCluster.ClusterEdgeID)
    43  	s.Equal(*response.RegisterCluster.SiteID, testSiteID)
    44  }
    45  
    46  func (s *Suite) TestRegisterDSDSCluster() {
    47  	store := "dsds-cluster"
    48  	testDSDSCluster(s, store, cluster.DSDS)
    49  }
    50  
    51  func testDSDSCluster(s *Suite, store, clusterProvider string) {
    52  	integration.SkipIf(s.Framework)
    53  	createSite := true
    54  	var response struct{ RegisterCluster *model.RegistrationResponse }
    55  	mutation := registerClusterMutation(&model.RegistrationPayload{
    56  		Name:        store,
    57  		Fleet:       fleet.Store,
    58  		ClusterType: clusterProvider,
    59  		StoreInfo: &model.StoreInfo{
    60  			StoreID:    &testStoreID, //using store name as store id, until store id is properly defined
    61  			CreateSite: &createSite,
    62  		},
    63  		BannerName: testOrg,
    64  		ClusterInfo: &model.ClusterInfo{
    65  			Location:    testLocation,
    66  			NodeVersion: &testClusterVersion,
    67  			MachineType: testClusterMachineType,
    68  			NumNodes:    testClusterNumNodes,
    69  		},
    70  	})
    71  	err := ResolverClient.Post(mutation, &response)
    72  	s.NoError(err)
    73  	s.NotNil(response)
    74  	s.NotNil(response.RegisterCluster)
    75  	s.NotEmpty(response.RegisterCluster.ClusterEdgeID)
    76  	s.Equal(*response.RegisterCluster.SiteID, testSiteID)
    77  
    78  	clusterEdgeID := response.RegisterCluster.ClusterEdgeID
    79  	var clusterConfigResponse struct{ ClusterConfig *model.ClusterConfig }
    80  	query := getClusterConfigQuery(clusterEdgeID)
    81  	err = ResolverClient.Post(query, &clusterConfigResponse)
    82  	s.NoError(err)
    83  	s.NotNil(clusterConfigResponse)
    84  	s.NotNil(clusterConfigResponse.ClusterConfig)
    85  	s.Equal(model.ClusterConfig{
    86  		ClusterEdgeID:        clusterEdgeID,
    87  		AcRelay:              false,
    88  		VpnEnabled:           false,
    89  		BootstrapAck:         true,
    90  		PxeEnabled:           false,
    91  		ThickPos:             true,
    92  		EgressGatewayEnabled: false,
    93  	}, *clusterConfigResponse.ClusterConfig)
    94  }
    95  
    96  func (s *Suite) TestRegisterClusterByBannerEdgeID() {
    97  	integration.SkipIf(s.Framework)
    98  	createSite := true
    99  	var response struct{ RegisterCluster *model.RegistrationResponse }
   100  	mutation := registerClusterMutation(&model.RegistrationPayload{
   101  		Name:        "banner_edge_id_store",
   102  		Fleet:       fleet.Store,
   103  		ClusterType: cluster.GKE,
   104  		StoreInfo: &model.StoreInfo{
   105  			StoreID:    &testStoreID, //using store name as store id, until store id is properly defined
   106  			CreateSite: &createSite,
   107  		},
   108  		BannerName:   testOrg,
   109  		BannerEdgeID: &testApi.TestOrgEdgeID,
   110  		ClusterInfo: &model.ClusterInfo{
   111  			Location:    testLocation,
   112  			NodeVersion: &testClusterVersion,
   113  			MachineType: testClusterMachineType,
   114  			NumNodes:    testClusterNumNodes,
   115  		},
   116  	})
   117  	ResolverClient.MustPost(mutation, &response)
   118  	s.NotNil(response.RegisterCluster)
   119  	s.NotEmpty(response.RegisterCluster.ClusterEdgeID)
   120  	s.Equal(*response.RegisterCluster.SiteID, testSiteID)
   121  }
   122  
   123  func (s *Suite) TestRegisterExistingCluster() {
   124  	integration.SkipIf(s.Framework)
   125  	createSite := true
   126  	var response struct{ RegisterCluster *model.RegistrationResponse }
   127  	mutation := registerClusterMutation(&model.RegistrationPayload{
   128  		Name:        "test_cluster-status",
   129  		Fleet:       fleet.Store,
   130  		ClusterType: cluster.GKE,
   131  		StoreInfo: &model.StoreInfo{
   132  			StoreID:    &testStoreID,
   133  			CreateSite: &createSite,
   134  		},
   135  		BannerName: "store-status-banner",
   136  		ClusterInfo: &model.ClusterInfo{
   137  			Location:    testLocation,
   138  			NodeVersion: &testClusterVersion,
   139  			MachineType: testClusterMachineType,
   140  			NumNodes:    testClusterNumNodes,
   141  		},
   142  	})
   143  	err := ResolverClient.Post(mutation, &response)
   144  	s.Error(err)
   145  	s.ErrorContains(err, "[{\"message\":\"cluster already registered, please try again with a different name. cluster name: test_cluster-status\",\"path\":[\"registerCluster\"]}]")
   146  }
   147  
   148  func (s *Suite) TestRegister_ReuseClusterName() {
   149  	integration.SkipIf(s.Framework)
   150  	createSite := true
   151  	request := &model.RegistrationPayload{
   152  		Name:        "test-register-reuse-name",
   153  		Fleet:       fleet.Store,
   154  		ClusterType: cluster.DSDS,
   155  		StoreInfo: &model.StoreInfo{
   156  			StoreID:    &testStoreID,
   157  			CreateSite: &createSite,
   158  		},
   159  		BannerName:   testOrg,
   160  		BannerEdgeID: &testApi.TestOrgEdgeID,
   161  		ClusterInfo: &model.ClusterInfo{
   162  			Location:    testLocation,
   163  			NodeVersion: &testClusterVersion,
   164  			MachineType: testClusterMachineType,
   165  			NumNodes:    testClusterNumNodes,
   166  		},
   167  	}
   168  
   169  	// register cluster named "test-register-reuse-name"
   170  	var response1 struct{ RegisterCluster *model.RegistrationResponse }
   171  	s.NoError(
   172  		ResolverClient.Post(registerClusterMutation(request), &response1),
   173  		"unexpected error registering cluster. first registration with unique name should succeed",
   174  	)
   175  	clusterID1 := response1.RegisterCluster.ClusterEdgeID
   176  
   177  	// registering cluster again with same name should fail
   178  	var response2 struct{ RegisterCluster *model.RegistrationResponse }
   179  	s.Error(
   180  		ResolverClient.Post(registerClusterMutation(request), &response2),
   181  		"error registering cluster. second registration with same name should fail",
   182  	)
   183  	s.Equal(clusterID1, response2.RegisterCluster.ClusterEdgeID, "expected registration response to return id of existing cluster")
   184  
   185  	// delete the cluster to free up name
   186  	var deleteResponse struct{ DeleteCluster *bool }
   187  	s.NoError(
   188  		ResolverClient.Post(deleteClusterQuery(clusterID1, false), &deleteResponse),
   189  		"unexpected error deleting cluster",
   190  	)
   191  	s.Require().NotNil(deleteResponse.DeleteCluster, "expected deleteCluster to return true, was nil")
   192  	s.True(*deleteResponse.DeleteCluster, "expected deleteCluster to return true")
   193  
   194  	// registering cluster named "test-register-reuse-name" again should now succeed
   195  	var response3 struct{ RegisterCluster *model.RegistrationResponse }
   196  	s.NoError(
   197  		ResolverClient.Post(registerClusterMutation(request), &response3),
   198  		"unexpected error registering cluster. registration should succeed when reusing deleted cluster name",
   199  	)
   200  	clusterID3 := response3.RegisterCluster.ClusterEdgeID
   201  
   202  	s.NotEqual(clusterID1, clusterID3, "cluster_edge_ids should differ when reusing old cluster name for new registration")
   203  }
   204  
   205  func (s *Suite) TestRegisterClusterCreateSQLEntryError() {
   206  	integration.SkipIf(s.Framework)
   207  	createSite := true
   208  	var response struct{ RegisterCluster *model.RegistrationResponse }
   209  	mutation := registerClusterMutation(&model.RegistrationPayload{
   210  		Name:        "test-store-2",
   211  		Fleet:       fleet.Store,
   212  		ClusterType: "unknown type",
   213  		StoreInfo: &model.StoreInfo{
   214  			StoreID:    &testStoreID,
   215  			CreateSite: &createSite,
   216  		},
   217  		BannerName: testOrg,
   218  		ClusterInfo: &model.ClusterInfo{
   219  			Location:    testLocation,
   220  			NodeVersion: &testClusterVersion,
   221  			MachineType: testClusterMachineType,
   222  			NumNodes:    testClusterNumNodes,
   223  		},
   224  	})
   225  	err := ResolverClient.Post(mutation, &response)
   226  	s.Error(err)
   227  	s.False(strings.Contains(err.Error(), "rollback errors"))
   228  
   229  	// test if the previous site has been rolled back
   230  	createSite = true
   231  	mutation = registerClusterMutation(&model.RegistrationPayload{
   232  		Name:        "test-store-2",
   233  		Fleet:       fleet.Store,
   234  		ClusterType: cluster.GKE,
   235  		StoreInfo: &model.StoreInfo{
   236  			StoreID:    &testStoreID,
   237  			CreateSite: &createSite,
   238  		},
   239  		BannerName: testOrg,
   240  		ClusterInfo: &model.ClusterInfo{
   241  			Location:    testLocation,
   242  			NodeVersion: &testClusterVersion,
   243  			MachineType: testClusterMachineType,
   244  			NumNodes:    testClusterNumNodes,
   245  		},
   246  	})
   247  	ResolverClient.MustPost(mutation, &response)
   248  	s.NotNil(response.RegisterCluster)
   249  	s.NotEmpty(response.RegisterCluster.ClusterEdgeID)
   250  	s.Equal(*response.RegisterCluster.SiteID, testSiteID)
   251  }
   252  
   253  func (s *Suite) TestRegisterClusterCreateBanner() {
   254  	integration.SkipIf(s.Framework)
   255  	createSite := false
   256  	var response struct{ RegisterCluster *model.RegistrationResponse }
   257  	mutation := registerClusterMutation(&model.RegistrationPayload{
   258  		Name:        "test-store-3",
   259  		Fleet:       fleet.Cluster,
   260  		ClusterType: cluster.GKE,
   261  		StoreInfo: &model.StoreInfo{
   262  			StoreID:    &testStoreID,
   263  			CreateSite: &createSite,
   264  		},
   265  		BannerName: testOrg,
   266  		ClusterInfo: &model.ClusterInfo{
   267  			Location:    testLocation,
   268  			NodeVersion: &testClusterVersion,
   269  			MachineType: testClusterMachineType,
   270  			NumNodes:    testClusterNumNodes,
   271  		},
   272  	})
   273  	err := ResolverClient.Post(mutation, &response)
   274  	s.NoError(err)
   275  	s.NotNil(response.RegisterCluster)
   276  	s.NotEmpty(response.RegisterCluster.ClusterEdgeID)
   277  	s.Equal(*response.RegisterCluster.SiteID, "")
   278  }
   279  
   280  func (s *Suite) TestRegisterCluster_AutoUpdateBackCompat() {
   281  	integration.SkipIf(s.Framework)
   282  	createSite := false
   283  	var response struct{ RegisterCluster *model.RegistrationResponse }
   284  	latest := types.DefaultVersionTag
   285  	mutation := registerClusterMutation(&model.RegistrationPayload{
   286  		Name:         "test-store-4",
   287  		Fleet:        fleet.Store,
   288  		FleetVersion: &latest,
   289  		ClusterType:  cluster.Generic,
   290  		StoreInfo: &model.StoreInfo{
   291  			StoreID:    &testStoreID,
   292  			CreateSite: &createSite,
   293  		},
   294  		BannerName: testOrg,
   295  		ClusterInfo: &model.ClusterInfo{
   296  			Location:    testLocation,
   297  			NodeVersion: &testClusterVersion,
   298  			MachineType: testClusterMachineType,
   299  			NumNodes:    testClusterNumNodes,
   300  		},
   301  	})
   302  	err := ResolverClient.Post(mutation, &response)
   303  	s.NoError(err)
   304  	s.NotNil(response.RegisterCluster)
   305  
   306  	newClusterQuery := graphb.Query{
   307  		Type: graphb.TypeQuery,
   308  		Fields: []*graphb.Field{
   309  			{
   310  				Name: "cluster",
   311  				Arguments: []graphb.Argument{
   312  					graphb.ArgumentString("clusterEdgeId", response.RegisterCluster.ClusterEdgeID),
   313  				},
   314  				Fields: []*graphb.Field{
   315  					graphb.NewField("fleetVersion"),
   316  				},
   317  			},
   318  		},
   319  	}
   320  	var clusterResponse struct{ Cluster *model.Cluster }
   321  	s.NoError(ResolverClient.Post(MustParse(newClusterQuery), &clusterResponse))
   322  	s.NotNil(clusterResponse.Cluster)
   323  	s.Equal(version.New().SemVer, clusterResponse.Cluster.FleetVersion)
   324  }
   325  
   326  func registerClusterMutation(payload *model.RegistrationPayload) string {
   327  	if payload.FleetVersion == nil {
   328  		version := types.DefaultVersionTag
   329  		payload.FleetVersion = &version
   330  	}
   331  	if payload.AutoUpdateEnabled == nil {
   332  		autoUpdate := false
   333  		payload.AutoUpdateEnabled = &autoUpdate
   334  	}
   335  	return MustParse(graphb.Query{
   336  		Type: graphb.TypeMutation,
   337  		Fields: []*graphb.Field{
   338  			{
   339  				Name: "registerCluster",
   340  				Arguments: []graphb.Argument{
   341  					graphb.ArgumentCustomType("payload",
   342  						graphb.ArgumentString("name", payload.Name),
   343  						graphb.ArgumentString("fleet", payload.Fleet),
   344  						graphb.ArgumentString("fleetVersion", *payload.FleetVersion),
   345  						graphb.ArgumentBool("autoUpdateEnabled", *payload.AutoUpdateEnabled),
   346  						graphb.ArgumentString("clusterType", payload.ClusterType),
   347  						graphb.ArgumentString("bannerName", payload.BannerName),
   348  						graphb.ArgumentCustomType("clusterInfo",
   349  							graphb.ArgumentString("location", payload.ClusterInfo.Location),
   350  							graphb.ArgumentString("machineType", payload.ClusterInfo.MachineType),
   351  							graphb.ArgumentString("nodeVersion", *payload.ClusterInfo.NodeVersion),
   352  							graphb.ArgumentInt("numNodes", payload.ClusterInfo.NumNodes),
   353  							graphb.ArgumentBool("autoscale", payload.ClusterInfo.Autoscale),
   354  							graphb.ArgumentInt("minNodes", utils.ConvertToInt(payload.ClusterInfo.MinNodes)),
   355  							graphb.ArgumentInt("maxNodes", utils.ConvertToInt(payload.ClusterInfo.MaxNodes)),
   356  						),
   357  						graphb.ArgumentCustomType("storeInfo",
   358  							graphb.ArgumentString("storeID", *payload.StoreInfo.StoreID),
   359  							graphb.ArgumentBool("createSite", *payload.StoreInfo.CreateSite),
   360  						),
   361  					),
   362  				},
   363  				Fields: graphb.Fields("clusterEdgeId", "siteId"),
   364  			},
   365  		},
   366  	})
   367  }
   368  
   369  const (
   370  	// for use in registration_queries.resolvers_test.go (cluster reset)
   371  	resetClusterEdgeID = "076b3f30-7c78-4b19-9d43-f8f476ab0d58"
   372  )
   373  
   374  func (s *Suite) TestResetStoreClusterForce() {
   375  	integration.SkipIf(s.Framework)
   376  
   377  	var response struct{ ResetCluster bool }
   378  	mutation := resetClusterMutation(resetClusterEdgeID, true)
   379  	err := ResolverClient.Post(mutation, &response)
   380  	s.NoError(err)
   381  	cluster, err := s.Resolver.StoreClusterService.GetCluster(context.Background(), resetClusterEdgeID)
   382  	s.NoError(err)
   383  	s.NotNil(cluster.Active)
   384  	s.False(*cluster.Active) // cluster should be marked inactive
   385  }
   386  
   387  func (s *Suite) TestResetStoreClusterNoForce() {
   388  	integration.SkipIf(s.Framework)
   389  
   390  	var response struct{ ResetCluster bool }
   391  	mutation := resetClusterMutation(resetClusterEdgeID, false)
   392  	err := ResolverClient.Post(mutation, &response)
   393  	s.ErrorContains(err, services.ErrMustForceClusterReset.Error())
   394  }
   395  
   396  func (s *Suite) TestResetNonStoreClusterForce() {
   397  	integration.SkipIf(s.Framework)
   398  
   399  	clusterInfraID := "3396a52c-6a22-4049-9593-5a63b596a200"
   400  	var response struct{ ResetCluster bool }
   401  	mutation := resetClusterMutation(clusterInfraID, true)
   402  	err := ResolverClient.Post(mutation, &response)
   403  	s.ErrorContains(err, services.ErrCanOnlyResetStore.Error())
   404  }
   405  
   406  func resetClusterMutation(clusterEdgeID string, force bool) string {
   407  	return MustParse(graphb.Query{
   408  		Type: graphb.TypeMutation,
   409  		Fields: []*graphb.Field{
   410  			{
   411  				Name: "resetCluster",
   412  				Arguments: []graphb.Argument{
   413  					graphb.ArgumentString("clusterEdgeId", clusterEdgeID),
   414  					graphb.ArgumentBool("force", force),
   415  				},
   416  			},
   417  		},
   418  	})
   419  }
   420  

View as plain text