package integration_test import ( "fmt" "github.com/udacity/graphb" "edge-infra.dev/pkg/edge/api/graph/mapper" "edge-infra.dev/pkg/edge/api/graph/model" "edge-infra.dev/pkg/edge/api/services" "edge-infra.dev/pkg/edge/api/utils" "edge-infra.dev/pkg/edge/constants" "edge-infra.dev/test/framework/integration" ) var ( clusterNetworkServiceEdgeID = "3396a52c-6a22-4049-9593-5a63b596a200" clusterCreateConfigEdgeID = "5bc12c67-d9b0-4f13-a6d4-4852b0c11291" k8sServiceEdgeID = "3396a52c-6a22-4049-9593-5a63b596a210" dnsNetworkServiceID = "bc51dae7-f4cb-4b20-b2c9-508bf9089b3e" dnsNetworkServiceID2 = "f79165b7-ebb7-426e-a91c-0d3bf2a148b5" podNetworkServiceID = "1c67eeb0-e1c4-4a8a-b9e1-46233ef5ad33" serviceNetworkServiceID = "d79dabaf-afc3-4a44-9031-e06a2512b1de" testFamily = "inet" testIP = "8.8.8.8" testIP2 = "9.9.9.9" testIP3 = "10.10.10.10" testServiceType = "dns" falseValue = false trueValue = true ) func (s *Suite) TestSiteEU() { integration.SkipIf(s.Framework) clusterEdgeID := clusterCreateConfigEdgeID siteQuery := siteQuery(clusterEdgeID) var getStoresSiteResponse struct{ Site *model.StoreSiteInfo } ResolverClient.MustPost(siteQuery, &getStoresSiteResponse) s.NotNil(getStoresSiteResponse) s.Equal(getStoresSiteResponse.Site.SiteName, "test-store") s.Equal(getStoresSiteResponse.Site.EnterpriseUnitName, "test-enterprise-unit-name") s.Equal(getStoresSiteResponse.Site.Status, services.ActiveStatus) s.Equal(*getStoresSiteResponse.Site.ID, "test_bsl_site_id-3") s.Equal(getStoresSiteResponse.Site.Coordinates.Latitude, services.DefaultLatitude) s.Equal(getStoresSiteResponse.Site.Coordinates.Longitude, services.DefaultLongitude) } func (s *Suite) TestSiteWithMismatches() { clusterEdgeID := testClusterEdgeID siteQuery := siteQuery(clusterEdgeID) var getStoresSiteResponse struct{ Site *model.StoreSiteInfo } err := ResolverClient.Post(siteQuery, &getStoresSiteResponse) s.NoError(err) s.NotNil(getStoresSiteResponse) s.Equal(getStoresSiteResponse.Site.SiteName, "test-store") s.Equal(getStoresSiteResponse.Site.EnterpriseUnitName, "test-enterprise-unit-name") s.Equal(getStoresSiteResponse.Site.Status, services.ActiveStatus) s.Equal(*getStoresSiteResponse.Site.ID, "test_bsl_site_id") s.Equal(getStoresSiteResponse.Site.Coordinates.Latitude, services.DefaultLatitude) s.Equal(getStoresSiteResponse.Site.Coordinates.Longitude, services.DefaultLongitude) } func (s *Suite) TestSiteORG() { integration.SkipIf(s.Framework) siteQuery := siteQuery(testClusterEdgeID2) var getStoresSiteResponse struct{ Site *model.StoreSiteInfo } ResolverClient.MustPost(siteQuery, &getStoresSiteResponse) s.NotNil(getStoresSiteResponse) s.Equal(getStoresSiteResponse.Site.SiteName, "test-store") s.Equal(getStoresSiteResponse.Site.EnterpriseUnitName, "test-enterprise-unit-name") s.Equal(getStoresSiteResponse.Site.Status, services.ActiveStatus) s.Equal(*getStoresSiteResponse.Site.ID, "test_bsl_site_id-2") s.Equal(getStoresSiteResponse.Site.Coordinates.Latitude, services.DefaultLatitude) s.Equal(getStoresSiteResponse.Site.Coordinates.Longitude, services.DefaultLongitude) } func (s *Suite) TestUpdateSite() { integration.SkipIf(s.Framework) updateSiteQuery := updateSiteQuery(testClusterEdgeID2) var updateSiteResponse struct{ UpdateSite *model.StoreSiteInfo } ResolverClient.MustPost(updateSiteQuery, &updateSiteResponse) s.NotNil(updateSiteResponse) s.Equal(updateSiteResponse.UpdateSite.SiteName, "test-store") s.Equal(updateSiteResponse.UpdateSite.EnterpriseUnitName, "test-enterprise-unit-name") s.Equal(updateSiteResponse.UpdateSite.Status, services.ActiveStatus) s.Equal(*updateSiteResponse.UpdateSite.ID, "test-site-id") s.Equal(updateSiteResponse.UpdateSite.Coordinates.Latitude, services.DefaultLatitude) s.Equal(updateSiteResponse.UpdateSite.Coordinates.Longitude, services.DefaultLongitude) } func (s *Suite) TestDeleteCluster() { integration.SkipIf(s.Framework) clusterEdgeID := "3d589401-8e64-4845-ad7b-0466e8e65f13" deleteSite := false deleteClusterQuery := deleteClusterQuery(clusterEdgeID, deleteSite) var deleteClusterResponse struct{ DeleteCluster *bool } ResolverClient.MustPost(deleteClusterQuery, &deleteClusterResponse) s.NotNil(deleteClusterQuery) } func (s *Suite) TestDeleteClusters1() { type test struct { testName string clusterEdgeIDs []string deleteSite bool } tests := []test{ { testName: "DeleteClustersWithoutBslSite", clusterEdgeIDs: []string{"2a589401-8e64-4845-ad7b-0466e8e65f13", "2b589401-8e64-4845-ad7b-0466e8e65f13"}, deleteSite: false, }, { testName: "DeleteClustersAndBslSite", clusterEdgeIDs: []string{"2c589401-8e64-4845-ad7b-0466e8e65f13", "2d589401-8e64-4845-ad7b-0466e8e65f13"}, deleteSite: true, }, } for _, tc := range tests { integration.SkipIf(s.Framework) clusterEdgeIDs := tc.clusterEdgeIDs deleteSite := tc.deleteSite deleteClustersQuery := deleteClustersQuery(clusterEdgeIDs, deleteSite) var deleteClustersResponse struct{ DeleteClusters *bool } ResolverClient.MustPost(deleteClustersQuery, &deleteClustersResponse) s.NotNil(deleteClustersQuery) } } func (s *Suite) TestGetClusters() { integration.SkipIf(s.Framework) query := clustersQuery(testOrgBannerEdgeID, []string{}) var clustersResponse struct{ Clusters []*model.Cluster } ResolverClient.MustPost(query, &clustersResponse) } func (s *Suite) TestGetClustersWithLabels() { integration.SkipIf(s.Framework) query := clustersQuery(testOrgBannerEdgeID, []string{"store", "basic-store"}) var clustersResponse struct{ Clusters []*model.Cluster } ResolverClient.MustPost(query, &clustersResponse) } func (s *Suite) TestUpdateClusterName() { clusterEdgeID := "3d589401-0000-1111-2222-0466e8e65f13" updatedName := "new-name" query := clusterQuery(clusterEdgeID) var clusterResponse struct{ Cluster *model.Cluster } ResolverClient.MustPost(query, &clusterResponse) s.NotNil(clusterResponse.Cluster) s.NotEqual(updatedName, clusterResponse.Cluster.Name) mutation := updateClusterName(clusterEdgeID, updatedName) var response struct{ UpdateClusterName *model.Cluster } ResolverClient.MustPost(mutation, &response) s.NotNil(response.UpdateClusterName) s.Equal(updatedName, response.UpdateClusterName.Name) } func (s *Suite) TestUpdateClusteFleetVersion() { integration.SkipIf(s.Framework) clusterEdgeID := "dc8e59c3-6338-4c28-a776-f54e93a19ff4" updatedFleetVersion := "0.16.0" query := clusterQuery(clusterEdgeID) var clusterResponse struct{ Cluster *model.Cluster } ResolverClient.MustPost(query, &clusterResponse) s.NotNil(clusterResponse.Cluster) s.NotEqual(updatedFleetVersion, clusterResponse.Cluster.FleetVersion) mutation := updateClusterFleetVersion(clusterEdgeID, updatedFleetVersion) var response struct{ UpdateClusterFleetVersion *model.Cluster } ResolverClient.MustPost(mutation, &response) s.NotNil(response.UpdateClusterFleetVersion) s.Equal(updatedFleetVersion, response.UpdateClusterFleetVersion.FleetVersion) } func (s *Suite) TestStoreStatusActive() { integration.SkipIf(s.Framework) q := storeStatus(testClusterEdgeID) var response struct{ StoreStatus *model.StoreStatusInfo } ResolverClient.MustPost(q, &response) s.NotNil(response.StoreStatus) s.Equal("test_cluster", response.StoreStatus.Name) s.Equal(testOrgBannerEdgeID, response.StoreStatus.BannerEdgeID) s.NotNil(response.StoreStatus.KubeVersion) s.NotNil(response.StoreStatus.Status) s.Equal("v1.23.6", *response.StoreStatus.KubeVersion) s.Equal("Ready", response.StoreStatus.Status.Status) s.Equal("Edge Syncing", response.StoreStatus.Status.Message) s.Equal(1, len(response.StoreStatus.BucketStatus)) s.Equal("test-bucket-name", response.StoreStatus.BucketStatus[0].BucketName) s.Equal(true, response.StoreStatus.BucketStatus[0].FluxStatus.Suspended) s.Equal("test-bucket-1", response.StoreStatus.BucketStatus[0].FluxStatus.Name) s.Equal(2, len(response.StoreStatus.KustomizationStatus)) s.Contains("test-kustomization-1 test-kustomization-2", response.StoreStatus.KustomizationStatus[0].FluxStatus.Name) s.Contains("test-kustomization-1 test-kustomization-2", response.StoreStatus.KustomizationStatus[1].FluxStatus.Name) } func (s *Suite) TestStoreStatusNotActive() { integration.SkipIf(s.Framework) if !integration.IsIntegrationTest() { s.NoError( setUpTestBannerAndClusterStatus("3396a52c-6a22-4049-9593-5a63b596a104", "3396a52c-6a22-4049-9593-5a63b596a202")) } q := storeStatus("3396a52c-6a22-4049-9593-5a63b596a202") var response struct{ StoreStatus *model.StoreStatusInfo } ResolverClient.MustPost(q, &response) s.NotNil(response.StoreStatus) s.Equal("status not found", response.StoreStatus.Status.Message) s.Equal(mapper.Provisioning, response.StoreStatus.Status.Status) } func (s *Suite) TestDeleteClusterAndBslSite() { integration.SkipIf(s.Framework) clusterEdgeID := "25980ab2-cb78-46ab-bf8f-9a7b78239b7f" deleteBslSite := true deleteClusterQuery := deleteClusterQuery(clusterEdgeID, deleteBslSite) var deleteClusterResponse struct{ DeleteCluster *bool } ResolverClient.MustPost(deleteClusterQuery, &deleteClusterResponse) s.NotNil(deleteClusterResponse) } func (s *Suite) TestGetClusterNetworkService() { clusterEdgeID := clusterNetworkServiceEdgeID getCluster := getClusterNetworkServices(clusterEdgeID) var getClusterResponse struct { Cluster *model.Cluster } err := ResolverClient.Post(getCluster, &getClusterResponse) s.NoError(err) s.NotNil(getClusterResponse) var dnsService *model.ClusterNetworkServiceInfo for _, service := range getClusterResponse.Cluster.ClusterNetworkServices { if service.ServiceType == "dns" && service.NetworkServiceID == dnsNetworkServiceID { dnsService = service } } searchDNSServers := []string{"8.8.8.8"} s.Equal(getClusterResponse.Cluster.ClusterEdgeID, clusterEdgeID) s.Equal(dnsService.ServiceType, "dns") s.Equal(dnsService.Family, testFamily) s.Equal(dnsService.ServiceType, testServiceType) s.Contains(searchDNSServers, dnsService.IP) s.Equal(*dnsService.Priority, 100) } func (s *Suite) TestCreateClusterNetworkService() { clusterEdgeID := clusterNetworkServiceEdgeID // Use a different IP here since dns services with the following IP's, [8.8.8.8, 9.9.9.9, 10.10.10.10], already exist for this cluster testNewIP := "0.0.0.0" networkServiceCreate := createNetworkServiceInput(testNewIP, testFamily, testServiceType, 100) allNetworkServices := []*model.CreateNetworkServiceInfo{networkServiceCreate} createClusterNetworkServiceQuery := createClusterNetworkServiceQuery(clusterEdgeID, allNetworkServices) var createClusterNetworkServiceResponse struct { CreateClusterNetworkServices []*model.ClusterNetworkServiceInfo } err := ResolverClient.Post(createClusterNetworkServiceQuery, &createClusterNetworkServiceResponse) s.NoError(err) s.NotNil(createClusterNetworkServiceResponse) } func (s *Suite) TestCreateClusterNetworkServiceInvalidIP() { clusterEdgeID := clusterNetworkServiceEdgeID testIP := "...." // Invalid IP networkServiceCreate := createNetworkServiceInput(testIP, testFamily, testServiceType, 100) allNetworkServices := []*model.CreateNetworkServiceInfo{networkServiceCreate} createClusterNetworkServiceQuery := createClusterNetworkServiceQuery(clusterEdgeID, allNetworkServices) var createClusterNetworkServiceResponse struct { CreateClusterNetworkServices []*model.ClusterNetworkServiceInfo } err := ResolverClient.Post(createClusterNetworkServiceQuery, &createClusterNetworkServiceResponse) s.Error(err) s.NotNil(createClusterNetworkServiceResponse) } func (s *Suite) TestCreateClusterNetworkServiceInvalidServiceType() { clusterEdgeID := clusterNetworkServiceEdgeID testServiceType := "domainnameserver" // Invalid service type networkServiceCreate := createNetworkServiceInput(testIP, testFamily, testServiceType, 100) allNetworkServices := []*model.CreateNetworkServiceInfo{networkServiceCreate} createClusterNetworkServiceQuery := createClusterNetworkServiceQuery(clusterEdgeID, allNetworkServices) var createClusterNetworkServiceResponse struct { CreateClusterNetworkServices []*model.ClusterNetworkServiceInfo } err := ResolverClient.Post(createClusterNetworkServiceQuery, &createClusterNetworkServiceResponse) s.Error(err) s.NotNil(createClusterNetworkServiceResponse) } func (s *Suite) TestCreateClusterNetworkServiceDuplicateIP() { clusterEdgeID := clusterNetworkServiceEdgeID // Use testIP2 since the combination [ServiceType: dns, IP: 9.9.9.9] already exists for this cluster networkServiceCreate := createNetworkServiceInput(testIP2, testFamily, testServiceType, 100) allNetworkServices := []*model.CreateNetworkServiceInfo{networkServiceCreate} createClusterNetworkServiceQuery := createClusterNetworkServiceQuery(clusterEdgeID, allNetworkServices) var createClusterNetworkServiceResponse struct { CreateClusterNetworkServices []*model.ClusterNetworkServiceInfo } err := ResolverClient.Post(createClusterNetworkServiceQuery, &createClusterNetworkServiceResponse) s.Error(err) s.NotNil(createClusterNetworkServiceResponse) } func (s *Suite) TestUpdateAndDeleteClusterNetworkService() { clusterEdgeID := clusterNetworkServiceEdgeID getCluster := getClusterNetworkServices(clusterEdgeID) var getClusterResponse struct { Cluster *model.Cluster } err := ResolverClient.Post(getCluster, &getClusterResponse) s.NoError(err) networkServiceID := getClusterResponse.Cluster.ClusterNetworkServices[0].NetworkServiceID testNewIP := "216.239.35.4" testNewFamily := testFamily testNewPriority := 99 networkServiceUpdate := updateNetworkServiceInput(testNewIP, testNewFamily, networkServiceID, testNewPriority) allNetworkServices := []*model.UpdateNetworkServiceInfo{networkServiceUpdate} updateClusterNetworkServiceQuery := updateClusterNetworkServiceQuery(clusterEdgeID, allNetworkServices) var updateClusterNetworkServiceResponse struct { UpdateClusterNetworkServices []*model.ClusterNetworkServiceInfo } err = ResolverClient.Post(updateClusterNetworkServiceQuery, &updateClusterNetworkServiceResponse) s.NoError(err) s.NotNil(updateClusterNetworkServiceResponse) s.Equal(updateClusterNetworkServiceResponse.UpdateClusterNetworkServices[0].NetworkServiceID, networkServiceID) s.Equal(updateClusterNetworkServiceResponse.UpdateClusterNetworkServices[0].Family, testNewFamily) s.Equal(updateClusterNetworkServiceResponse.UpdateClusterNetworkServices[0].IP, testNewIP) s.Equal(*updateClusterNetworkServiceResponse.UpdateClusterNetworkServices[0].Priority, 99) deleteClusterNetworkServiceQuery := deleteClusterNetworkServiceQuery(clusterEdgeID, networkServiceID) var deleteClusterNetworkServiceResponse struct{ DeleteClusterNetworkService *bool } err = ResolverClient.Post(deleteClusterNetworkServiceQuery, &deleteClusterNetworkServiceResponse) s.NoError(err) s.NotNil(deleteClusterNetworkServiceResponse) s.True(*deleteClusterNetworkServiceResponse.DeleteClusterNetworkService) } func (s *Suite) TestUpdateAndDeleteK8sServiceSubnetWhenClusterActive() { clusterEdgeID := clusterNetworkServiceEdgeID // cluster.Active = True networkServiceID := "f20e75ea-28b9-4f1d-8e79-ad871601261b" cidr := "10.96.0.0/17" networkServiceUpdate := updateNetworkServiceInput(cidr, testFamily, networkServiceID, 100) allNetworkServices := []*model.UpdateNetworkServiceInfo{networkServiceUpdate} updateClusterNetworkServiceQuery := updateClusterNetworkServiceQuery(clusterEdgeID, allNetworkServices) var updateClusterNetworkServiceResponse struct { UpdateClusterNetworkServices []*model.ClusterNetworkServiceInfo } err := ResolverClient.Post(updateClusterNetworkServiceQuery, &updateClusterNetworkServiceResponse) s.ErrorContains(err, "cluster network service service-network-cidr cannot be updated after bootstrapping the first") } func (s *Suite) TestUpdateK8sServiceSubnetInvalidRangeLowerBound() { clusterEdgeID := k8sServiceEdgeID networkServiceID := serviceNetworkServiceID cidr := "10.96.0.0/15" networkServiceUpdate := updateNetworkServiceInput(cidr, testFamily, networkServiceID, 100) allNetworkServices := []*model.UpdateNetworkServiceInfo{networkServiceUpdate} updateClusterNetworkServiceQuery := updateClusterNetworkServiceQuery(clusterEdgeID, allNetworkServices) var updateClusterNetworkServiceResponse struct { UpdateClusterNetworkServices []*model.ClusterNetworkServiceInfo } err := ResolverClient.Post(updateClusterNetworkServiceQuery, &updateClusterNetworkServiceResponse) s.ErrorContains(err, "invalid prefix length. Prefix length must be between /16 and /22 for k8s service network") } func (s *Suite) TestUpdateK8sServiceSubnetInvalidRangeUpperBound() { clusterEdgeID := k8sServiceEdgeID networkServiceID := serviceNetworkServiceID cidr := "10.96.0.0/23" networkServiceUpdate := updateNetworkServiceInput(cidr, testFamily, networkServiceID, 100) allNetworkServices := []*model.UpdateNetworkServiceInfo{networkServiceUpdate} updateClusterNetworkServiceQuery := updateClusterNetworkServiceQuery(clusterEdgeID, allNetworkServices) var updateClusterNetworkServiceResponse struct { UpdateClusterNetworkServices []*model.ClusterNetworkServiceInfo } err := ResolverClient.Post(updateClusterNetworkServiceQuery, &updateClusterNetworkServiceResponse) s.ErrorContains(err, "invalid prefix length. Prefix length must be between /16 and /22 for k8s service network") } func (s *Suite) TestUpdateK8sPodSubnetInvalidRangeLowerBound() { clusterEdgeID := k8sServiceEdgeID networkServiceID := podNetworkServiceID cidr := "100.127.0.0/15" networkServiceUpdate := updateNetworkServiceInput(cidr, testFamily, networkServiceID, 100) allNetworkServices := []*model.UpdateNetworkServiceInfo{networkServiceUpdate} updateClusterNetworkServiceQuery := updateClusterNetworkServiceQuery(clusterEdgeID, allNetworkServices) var updateClusterNetworkServiceResponse struct { UpdateClusterNetworkServices []*model.ClusterNetworkServiceInfo } err := ResolverClient.Post(updateClusterNetworkServiceQuery, &updateClusterNetworkServiceResponse) s.ErrorContains(err, "invalid prefix length. Prefix length must be between /16 and /21 for k8s pod network") } func (s *Suite) TestUpdateK8sPodSubnetInvalidRangeUpperBound() { clusterEdgeID := k8sServiceEdgeID networkServiceID := podNetworkServiceID cidr := "100.127.0.0/22" networkServiceUpdate := updateNetworkServiceInput(cidr, testFamily, networkServiceID, 100) allNetworkServices := []*model.UpdateNetworkServiceInfo{networkServiceUpdate} updateClusterNetworkServiceQuery := updateClusterNetworkServiceQuery(clusterEdgeID, allNetworkServices) var updateClusterNetworkServiceResponse struct { UpdateClusterNetworkServices []*model.ClusterNetworkServiceInfo } err := ResolverClient.Post(updateClusterNetworkServiceQuery, &updateClusterNetworkServiceResponse) s.ErrorContains(err, "invalid prefix length. Prefix length must be between /16 and /21 for k8s pod network") } func (s *Suite) TestUpdateClusterPodNetworkService() { clusterEdgeID := k8sServiceEdgeID networkServiceID := podNetworkServiceID podCidr := "100.156.0.0/16" networkServiceUpdate := updateNetworkServiceInput(podCidr, testFamily, networkServiceID, 100) allNetworkServices := []*model.UpdateNetworkServiceInfo{networkServiceUpdate} updateClusterNetworkServiceQuery := updateClusterNetworkServiceQuery(clusterEdgeID, allNetworkServices) var updateClusterNetworkServiceResponse struct { UpdateClusterNetworkServices []*model.ClusterNetworkServiceInfo } err = ResolverClient.Post(updateClusterNetworkServiceQuery, &updateClusterNetworkServiceResponse) s.NoError(err) s.NotNil(updateClusterNetworkServiceResponse) } func (s *Suite) TestForbiddenNetServiceDeletion() { clusterEdgeID := k8sServiceEdgeID networkServiceID := podNetworkServiceID deleteClusterNetworkServiceQuery := deleteClusterNetworkServiceQuery(clusterEdgeID, networkServiceID) var deleteClusterNetworkServiceResponse struct{ DeleteClusterNetworkService *bool } err = ResolverClient.Post(deleteClusterNetworkServiceQuery, &deleteClusterNetworkServiceResponse) s.ErrorContains(err, fmt.Sprintf("adhoc deletion of the %s is forbidden", constants.ServiceTypePodNetworkCIDR)) } func (s *Suite) TestInvalidK8sSubnetOverlap() { clusterEdgeID := k8sServiceEdgeID podNetworkServiceType := constants.ServiceTypePodNetworkCIDR serviceNetworkServiceType := constants.ServiceTypeServiceNetworkCIDR networkServiceID := podNetworkServiceID podCidr := "10.96.0.0/16" networkServiceUpdate := updateNetworkServiceInput(podCidr, testFamily, networkServiceID, 100) allNetworkServices := []*model.UpdateNetworkServiceInfo{networkServiceUpdate} updateClusterNetworkServiceQuery := updateClusterNetworkServiceQuery(clusterEdgeID, allNetworkServices) var updateClusterNetworkServiceResponse struct { UpdateClusterNetworkServices []*model.ClusterNetworkServiceInfo } err = ResolverClient.Post(updateClusterNetworkServiceQuery, &updateClusterNetworkServiceResponse) s.ErrorContains(err, fmt.Sprintf("invalid subnet - %s must not overlap with %s", podNetworkServiceType, serviceNetworkServiceType)) } func (s *Suite) TestValidIPNotASubnet() { clusterEdgeID := k8sServiceEdgeID serviceType := constants.ServiceTypeServiceNetworkCIDR networkServiceID := serviceNetworkServiceID serviceCidr := "10.96.0.0" networkServiceUpdate := updateNetworkServiceInput(serviceCidr, testFamily, networkServiceID, 100) allNetworkServices := []*model.UpdateNetworkServiceInfo{networkServiceUpdate} updateClusterNetworkServiceQuery := updateClusterNetworkServiceQuery(clusterEdgeID, allNetworkServices) var updateClusterNetworkServiceResponse struct { UpdateClusterNetworkServices []*model.ClusterNetworkServiceInfo } err = ResolverClient.Post(updateClusterNetworkServiceQuery, &updateClusterNetworkServiceResponse) s.ErrorContains(err, fmt.Sprintf("invalid CIDR address %s for %s", serviceCidr, serviceType)) } func (s *Suite) TestUpdateK8sNetworkServiceInvalid() { clusterEdgeID := k8sServiceEdgeID networkServiceID := "1c67eeb0-e1c4-4a8a-b9e1-46233ef5ad33" serviceType := constants.ServiceTypePodNetworkCIDR cidr := "not-a-cidr-subnet" networkServiceUpdate := updateNetworkServiceInput(cidr, testFamily, networkServiceID, 100) allNetworkServices := []*model.UpdateNetworkServiceInfo{networkServiceUpdate} updateClusterNetworkServiceQuery := updateClusterNetworkServiceQuery(clusterEdgeID, allNetworkServices) var updateClusterNetworkServiceResponse struct { UpdateClusterNetworkServices []*model.ClusterNetworkServiceInfo } err := ResolverClient.Post(updateClusterNetworkServiceQuery, &updateClusterNetworkServiceResponse) s.ErrorContains(err, fmt.Sprintf("invalid CIDR address %s for %s", cidr, serviceType)) } func (s *Suite) TestUpdateK8sClusterDNSNotPermitted() { clusterEdgeID := k8sServiceEdgeID networkServiceID := "7fa65f85-1856-4c8e-90e5-a68c410a6c0d" serviceType := constants.ServiceTypeClusterDNS cidr := "100.127.0.0/23" networkServiceUpdate := updateNetworkServiceInput(cidr, testFamily, networkServiceID, 100) allNetworkServices := []*model.UpdateNetworkServiceInfo{networkServiceUpdate} updateClusterNetworkServiceQuery := updateClusterNetworkServiceQuery(clusterEdgeID, allNetworkServices) var updateClusterNetworkServiceResponse struct { UpdateClusterNetworkServices []*model.ClusterNetworkServiceInfo } err := ResolverClient.Post(updateClusterNetworkServiceQuery, &updateClusterNetworkServiceResponse) s.ErrorContains(err, fmt.Sprintf("cluster network service %s is not configurable", serviceType)) } func (s *Suite) TestUpdateClusterNetworkServiceDuplicateIP() { clusterEdgeID := clusterNetworkServiceEdgeID testExistingIP := testIP3 networkServiceUpdate := updateNetworkServiceInput(testExistingIP, testFamily, dnsNetworkServiceID2, 100) allNetworkServicesUpdate := []*model.UpdateNetworkServiceInfo{networkServiceUpdate} updateClusterNetworkServiceQuery := updateClusterNetworkServiceQuery(clusterEdgeID, allNetworkServicesUpdate) var updateClusterNetworkServiceResponse struct { UpdateClusterNetworkServices []*model.ClusterNetworkServiceInfo } err = ResolverClient.Post(updateClusterNetworkServiceQuery, &updateClusterNetworkServiceResponse) s.Error(err) s.ErrorContains(err, fmt.Sprintf("IP address %s already exists for %s", testExistingIP, testServiceType)) } func (s *Suite) TestCreateUpdateDeleteGetClusterConfig() { configClusterEdgeID := "3396a52c-6a22-4049-9593-5a63b596a201" var responseCreate struct { CreateClusterConfig model.ClusterConfig } createClusterConfig := model.CreateClusterConfig{ AcRelay: &trueValue, PxeEnabled: &falseValue, BootstrapAck: &falseValue, VpnEnabled: &trueValue, ThickPos: &trueValue, EgressGatewayEnabled: &trueValue, } createClusterConfigMutation := createClusterConfigMutation(configClusterEdgeID, createClusterConfig) err := ResolverClient.Post(createClusterConfigMutation, &responseCreate) s.NoError(err) s.NotEmpty(responseCreate.CreateClusterConfig) s.True(responseCreate.CreateClusterConfig.AcRelay) s.False(responseCreate.CreateClusterConfig.PxeEnabled) s.False(responseCreate.CreateClusterConfig.BootstrapAck) s.True(responseCreate.CreateClusterConfig.VpnEnabled) s.True(responseCreate.CreateClusterConfig.ThickPos) s.True(responseCreate.CreateClusterConfig.EgressGatewayEnabled) var responseUpdate struct { UpdateClusterConfig model.ClusterConfig } config := model.UpdateClusterConfig{ AcRelay: &falseValue, PxeEnabled: &trueValue, BootstrapAck: &falseValue, ThickPos: &falseValue, VpnEnabled: &trueValue, EgressGatewayEnabled: &falseValue, } updateClusterConfig := updateClusterConfigMutation(configClusterEdgeID, config) err = ResolverClient.Post(updateClusterConfig, &responseUpdate) s.NoError(err) s.False(responseUpdate.UpdateClusterConfig.AcRelay) s.True(responseUpdate.UpdateClusterConfig.PxeEnabled) s.False(responseUpdate.UpdateClusterConfig.BootstrapAck) s.False(responseUpdate.UpdateClusterConfig.ThickPos) s.True(responseUpdate.UpdateClusterConfig.VpnEnabled) s.False(responseUpdate.UpdateClusterConfig.EgressGatewayEnabled) var responseGet struct { ClusterConfig *model.ClusterConfig } getClusterConfigQuery := getClusterConfigQuery(configClusterEdgeID) err = ResolverClient.Post(getClusterConfigQuery, &responseGet) s.NoError(err) s.NotEmpty(responseGet.ClusterConfig) s.False(responseGet.ClusterConfig.AcRelay) s.True(responseGet.ClusterConfig.PxeEnabled) s.False(responseGet.ClusterConfig.BootstrapAck) s.False(responseGet.ClusterConfig.ThickPos) s.True(responseGet.ClusterConfig.VpnEnabled) s.False(responseGet.ClusterConfig.EgressGatewayEnabled) } func (s *Suite) TestGetEventsForCluster() { integration.SkipIf(s.Framework) // Query for cluster with events query := clusterQuery("3396a52c-6a22-4049-9593-5a63b596a200") var response struct{ Cluster *model.Cluster } ResolverClient.MustPost(query, &response) err := ResolverClient.Post(query, &response) s.NoError(err) s.NotNil(response.Cluster.Status.Events) s.Equal(2, len(response.Cluster.Status.Events)) for _, event := range response.Cluster.Status.Events { s.NotEmpty(event.EventEdgeID) s.NotEmpty(event.Name) s.NotNil(event.InvolvedObject) s.NotEmpty(event.InvolvedObject.Kind) s.NotEmpty(event.InvolvedObject.Name) s.NotEmpty(event.Reason) s.NotEmpty(event.Message) s.NotEmpty(event.Source) s.NotEmpty(event.Status) s.NotEmpty(event.ClusterEdgeID) s.NotEmpty(event.CreatedAt) } } func siteQuery(clusterEdgeID string) string { args := []graphb.Argument{ graphb.ArgumentString("clusterEdgeID", clusterEdgeID), } return MustParse(graphb.Query{ Type: graphb.TypeQuery, Fields: []*graphb.Field{ { Name: "site", Arguments: args, Fields: []*graphb.Field{ graphb.NewField("organizationName"), graphb.NewField("id"), graphb.NewField("status"), graphb.NewField("siteName"), graphb.NewField("enterpriseUnitName"), graphb.NewField("coordinates", graphb.OfFields( "latitude", "longitude", )), graphb.NewField("enterpriseSettings", graphb.OfFields( "enterpriseUnitId", )), graphb.NewField("dayparts", graphb.OfFields( "description", "startTime", "endTime", "name", )), }, }, }, }) } func updateSiteQuery(clusterEdgeID string) string { args := []graphb.Argument{ graphb.ArgumentString("clusterEdgeId", clusterEdgeID), graphb.ArgumentCustomType("site", graphb.ArgumentString("siteName", "test-store"), graphb.ArgumentString("status", "ACTIVE"), graphb.ArgumentString("enterpriseUnitName", "test-enterprise-unit-name"), graphb.ArgumentString("description", "test site description"), graphb.ArgumentCustomType("coordinates", graphb.ArgumentInt("latitude", 90.0), graphb.ArgumentInt("longitude", 180.0), ), ), } return MustParse(graphb.Query{ Type: graphb.TypeMutation, Fields: []*graphb.Field{ { Name: "updateSite", Arguments: args, Fields: []*graphb.Field{ graphb.NewField("organizationName"), graphb.NewField("id"), graphb.NewField("status"), graphb.NewField("siteName"), graphb.NewField("enterpriseUnitName"), graphb.NewField("coordinates", graphb.OfFields( "latitude", "longitude", )), graphb.NewField("enterpriseSettings", graphb.OfFields( "enterpriseUnitId", )), graphb.NewField("dayparts", graphb.OfFields( "description", "startTime", "endTime", "name", )), }, }, }, }) } func storeStatus(clusterEdgeID string) string { args := []graphb.Argument{ graphb.ArgumentString("clusterEdgeId", clusterEdgeID), } return MustParse(graphb.Query{ Type: graphb.TypeQuery, Fields: []*graphb.Field{ { Name: "storeStatus", Arguments: args, Fields: []*graphb.Field{ graphb.NewField("name"), graphb.NewField("bannerEdgeId"), graphb.NewField("status", graphb.OfFields( "status", "message", )), graphb.NewField("kubeVersion"), { Name: "bucketStatus", Fields: []*graphb.Field{ graphb.NewField("excludes"), graphb.NewField("bucketName"), graphb.NewField("fluxStatus", graphb.OfFields("name", "error", "lastUpdated", "revision", "statusMessage", "suspended"))}, }, { Name: "kustomizationStatus", Fields: []*graphb.Field{ graphb.NewField("path"), graphb.NewField("source"), graphb.NewField("fluxStatus", graphb.OfFields("name", "error", "lastUpdated", "revision", "statusMessage", "suspended"))}, }, }, }, }, }) } func deleteClusterQuery(clusterEdgeID string, deleteBslSite bool) string { args := []graphb.Argument{ graphb.ArgumentString("clusterEdgeId", clusterEdgeID), graphb.ArgumentBool("deleteBSLSite", deleteBslSite), } return MustParse(graphb.Query{ Type: graphb.TypeMutation, Fields: []*graphb.Field{ { Name: "deleteCluster", Arguments: args, }, }, }) } func deleteClustersQuery(clusterEdgeIDs []string, deleteBslSite bool) string { args := []graphb.Argument{ graphb.ArgumentStringSlice("clusterEdgeIds", clusterEdgeIDs...), graphb.ArgumentBool("deleteBSLSite", deleteBslSite), } return MustParse(graphb.Query{ Type: graphb.TypeMutation, Fields: []*graphb.Field{ { Name: "deleteClusters", Arguments: args, }, }, }) } func deleteClusterNetworkServiceQuery(clusterEdgeID, networkServiceID string) string { args := []graphb.Argument{ graphb.ArgumentString("clusterEdgeId", clusterEdgeID), graphb.ArgumentString("networkServiceId", networkServiceID), } return MustParse(graphb.Query{ Type: graphb.TypeMutation, Fields: []*graphb.Field{ { Name: "deleteClusterNetworkService", Arguments: args, }, }, }) } func createNetworkServiceInput(ip, family, serviceType string, priority int) *model.CreateNetworkServiceInfo { // nolint: unparam return &model.CreateNetworkServiceInfo{ IP: ip, Family: family, ServiceType: serviceType, Priority: &priority, } } func createClusterNetworkServiceQuery(clusterEdgeID string, clusterNetworkServices []*model.CreateNetworkServiceInfo) string { arguments := make([][]graphb.Argument, 0, len(clusterNetworkServices)) for _, networkService := range clusterNetworkServices { newNetworkServiceArgument := graphb.ArgumentCustomTypeSliceElem( graphb.ArgumentString("serviceType", networkService.ServiceType), graphb.ArgumentString("ip", networkService.IP), graphb.ArgumentString("family", networkService.Family), graphb.ArgumentInt("priority", *networkService.Priority), ) arguments = append(arguments, newNetworkServiceArgument) } args := []graphb.Argument{ graphb.ArgumentString("clusterEdgeId", clusterEdgeID), graphb.ArgumentCustomTypeSlice("networkServicesInfo", arguments...), } return MustParse(graphb.Query{ Type: graphb.TypeMutation, Fields: []*graphb.Field{ { Name: "createClusterNetworkServices", Arguments: args, Fields: []*graphb.Field{ graphb.NewField("serviceType"), graphb.NewField("ip"), graphb.NewField("family"), graphb.NewField("priority"), }, }, }, }) } func getClusterNetworkServices(clusterEdgeID string) string { args := []graphb.Argument{ graphb.ArgumentString("clusterEdgeId", clusterEdgeID), } return MustParse(graphb.Query{ Type: graphb.TypeQuery, Fields: []*graphb.Field{ { Name: "cluster", Arguments: args, Fields: []*graphb.Field{ { Name: "clusterNetworkServices", Fields: []*graphb.Field{ graphb.NewField("networkServiceId"), graphb.NewField("ip"), graphb.NewField("family"), graphb.NewField("serviceType"), graphb.NewField("priority")}, }, { Name: "clusterEdgeId", }, { Name: "name", }, }, }, }, }) } func updateNetworkServiceInput(ip, family, networkServiceID string, priority int) *model.UpdateNetworkServiceInfo { return &model.UpdateNetworkServiceInfo{ NetworkServiceID: networkServiceID, IP: ip, Family: family, Priority: &priority, } } func updateClusterNetworkServiceQuery(clusterEdgeID string, clusterNetworkServices []*model.UpdateNetworkServiceInfo) string { arguments := make([][]graphb.Argument, 0, len(clusterNetworkServices)) for _, networkService := range clusterNetworkServices { newNetworkServiceArgument := graphb.ArgumentCustomTypeSliceElem( graphb.ArgumentString("networkServiceId", networkService.NetworkServiceID), graphb.ArgumentString("ip", networkService.IP), graphb.ArgumentString("family", networkService.Family), graphb.ArgumentInt("priority", *networkService.Priority), ) arguments = append(arguments, newNetworkServiceArgument) } args := []graphb.Argument{ graphb.ArgumentString("clusterEdgeId", clusterEdgeID), graphb.ArgumentCustomTypeSlice("networkServicesInfo", arguments...), } return MustParse(graphb.Query{ Type: graphb.TypeMutation, Fields: []*graphb.Field{ { Name: "updateClusterNetworkServices", Arguments: args, Fields: []*graphb.Field{ graphb.NewField("networkServiceId"), graphb.NewField("serviceType"), graphb.NewField("ip"), graphb.NewField("family"), graphb.NewField("priority"), }, }, }, }) } func updateClusterName(clusterEdgeID string, name string) string { args := []graphb.Argument{ graphb.ArgumentString("clusterEdgeId", clusterEdgeID), graphb.ArgumentString("name", name), } return MustParse(graphb.Query{ Type: graphb.TypeMutation, Fields: []*graphb.Field{ { Name: "updateClusterName", Arguments: args, Fields: []*graphb.Field{ graphb.NewField("clusterEdgeId"), graphb.NewField("name"), graphb.NewField("projectId"), graphb.NewField("bannerEdgeId"), graphb.NewField("registered"), graphb.NewField("active"), graphb.NewField("labels", graphb.OfFields( "labelEdgeId", "key", "type", )), graphb.NewField("bslSiteID"), }, }, }, }) } func updateClusterFleetVersion(clusterEdgeID, fleetVersion string) string { args := []graphb.Argument{ graphb.ArgumentString("clusterEdgeId", clusterEdgeID), graphb.ArgumentString("fleetVersion", fleetVersion), } return MustParse(graphb.Query{ Type: graphb.TypeMutation, Fields: []*graphb.Field{ { Name: "updateClusterFleetVersion", Arguments: args, Fields: []*graphb.Field{ graphb.NewField("clusterEdgeId"), graphb.NewField("name"), graphb.NewField("projectId"), graphb.NewField("bannerEdgeId"), graphb.NewField("registered"), graphb.NewField("active"), graphb.NewField("labels", graphb.OfFields( "labelEdgeId", "key", "type", )), graphb.NewField("bslSiteID"), graphb.NewField("fleetVersion"), }, }, }, }) } func clusterQuery(clusterEdgeID string) string { return MustParse(graphb.Query{ Type: graphb.TypeQuery, Fields: []*graphb.Field{ { Name: "cluster", Arguments: []graphb.Argument{ graphb.ArgumentString("clusterEdgeId", clusterEdgeID), }, Fields: []*graphb.Field{ graphb.NewField("clusterEdgeId"), graphb.NewField("name"), graphb.NewField("projectId"), graphb.NewField("bannerEdgeId"), graphb.NewField("registered"), graphb.NewField("active"), graphb.NewField("labels", graphb.OfFields( "labelEdgeId", "key", "type", )), graphb.NewField("bslSiteID"), graphb.NewField("status").SetFields( graphb.NewField("events").SetFields( graphb.NewField("involvedObject", graphb.OfFields("kind", "name")), graphb.NewField("eventEdgeID"), graphb.NewField("name"), graphb.NewField("clusterEdgeID"), graphb.NewField("reason"), graphb.NewField("message"), graphb.NewField("status"), graphb.NewField("source"), graphb.NewField("createdAt"), ), ), }, }, }, }) } func clustersQuery(bannerEdgeID string, labels []string) string { return MustParse(graphb.Query{ Type: graphb.TypeQuery, Fields: []*graphb.Field{ { Name: "clusters", Arguments: []graphb.Argument{ graphb.ArgumentString("bannerEdgeId", bannerEdgeID), graphb.ArgumentStringSlice("labels", labels...), }, Fields: []*graphb.Field{ graphb.NewField("clusterEdgeId"), graphb.NewField("name"), graphb.NewField("projectId"), graphb.NewField("bannerEdgeId"), graphb.NewField("registered"), graphb.NewField("active"), graphb.NewField("labels", graphb.OfFields( "labelEdgeId", "key", "type", )), graphb.NewField("bslSiteID"), }, }, }, }) } func createClusterConfigMutation(clusterEdgeID string, createClusterConfig model.CreateClusterConfig) string { config := graphb.ArgumentCustomTypeSliceElem( graphb.ArgumentBool("acRelay", *createClusterConfig.AcRelay), graphb.ArgumentBool("pxeEnabled", *createClusterConfig.PxeEnabled), graphb.ArgumentBool("bootstrapAck", *createClusterConfig.BootstrapAck), graphb.ArgumentBool("vpnEnabled", *createClusterConfig.VpnEnabled), graphb.ArgumentBool("thickPos", *createClusterConfig.ThickPos), graphb.ArgumentBool("egressGatewayEnabled", *createClusterConfig.EgressGatewayEnabled), ) args := []graphb.Argument{ graphb.ArgumentString("clusterEdgeId", clusterEdgeID), graphb.ArgumentCustomType("createClusterConfig", config...), } return MustParse(graphb.Query{ Type: graphb.TypeMutation, Fields: []*graphb.Field{ { Name: "createClusterConfig", Arguments: args, Fields: []*graphb.Field{ graphb.NewField("clusterEdgeId"), graphb.NewField("acRelay"), graphb.NewField("pxeEnabled"), graphb.NewField("bootstrapAck"), graphb.NewField("vpnEnabled"), graphb.NewField("thickPos"), graphb.NewField("egressGatewayEnabled"), }, }, }, }) } func updateClusterConfigMutation(clusterEdgeID string, updateClusterConfig model.UpdateClusterConfig) string { config := graphb.ArgumentCustomTypeSliceElem( graphb.ArgumentBool("acRelay", utils.ConvertToBool(updateClusterConfig.AcRelay)), graphb.ArgumentBool("pxeEnabled", utils.ConvertToBool(updateClusterConfig.PxeEnabled)), graphb.ArgumentBool("bootstrapAck", utils.ConvertToBool(updateClusterConfig.BootstrapAck)), graphb.ArgumentBool("vpnEnabled", utils.ConvertToBool(updateClusterConfig.VpnEnabled)), graphb.ArgumentBool("thickPos", utils.ConvertToBool(updateClusterConfig.ThickPos)), graphb.ArgumentBool("egressGatewayEnabled", utils.ConvertToBool(updateClusterConfig.EgressGatewayEnabled)), ) args := []graphb.Argument{ graphb.ArgumentString("clusterEdgeId", clusterEdgeID), graphb.ArgumentCustomType("updateClusterConfig", config...), } return MustParse(graphb.Query{ Type: graphb.TypeMutation, Fields: []*graphb.Field{ { Name: "updateClusterConfig", Arguments: args, Fields: []*graphb.Field{ graphb.NewField("clusterEdgeId"), graphb.NewField("acRelay"), graphb.NewField("pxeEnabled"), graphb.NewField("bootstrapAck"), graphb.NewField("vpnEnabled"), graphb.NewField("thickPos"), graphb.NewField("egressGatewayEnabled"), }, }, }, }) } func getClusterConfigQuery(clusterEdgeID string) string { args := []graphb.Argument{ graphb.ArgumentString("clusterEdgeId", clusterEdgeID), } return MustParse(graphb.Query{ Type: graphb.TypeQuery, Fields: []*graphb.Field{ { Name: "clusterConfig", Arguments: args, Fields: []*graphb.Field{ graphb.NewField("clusterEdgeId"), graphb.NewField("acRelay"), graphb.NewField("pxeEnabled"), graphb.NewField("bootstrapAck"), graphb.NewField("vpnEnabled"), graphb.NewField("thickPos"), graphb.NewField("egressGatewayEnabled"), }, }, }, }) }