1 package integration_test
2
3 import (
4 "context"
5 "encoding/base64"
6 "encoding/json"
7 "fmt"
8 "net/http"
9 "time"
10
11 pubSub "cloud.google.com/go/pubsub"
12 "cloud.google.com/go/secretmanager/apiv1/secretmanagerpb"
13 "github.com/99designs/gqlgen/client"
14 "github.com/99designs/gqlgen/graphql"
15 "github.com/99designs/gqlgen/graphql/handler"
16 "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/k8s/v1alpha1"
17 resourceApi "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/resourcemanager/v1beta1"
18 helmApi "github.com/fluxcd/helm-controller/api/v2"
19 "github.com/gin-gonic/gin"
20 "github.com/golang/mock/gomock"
21 "github.com/google/go-containerregistry/pkg/name"
22 _ "github.com/lib/pq"
23 "google.golang.org/api/compute/v1"
24 "google.golang.org/api/container/v1"
25 "google.golang.org/api/option"
26 corev1 "k8s.io/api/core/v1"
27 k8sErrors "k8s.io/apimachinery/pkg/api/errors"
28 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
29 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
30 "k8s.io/apimachinery/pkg/labels"
31 "k8s.io/apimachinery/pkg/runtime/schema"
32 "k8s.io/apimachinery/pkg/selection"
33 "k8s.io/apimachinery/pkg/util/wait"
34 "k8s.io/client-go/kubernetes/scheme"
35 "k8s.io/client-go/rest"
36 runtimeclient "sigs.k8s.io/controller-runtime/pkg/client"
37 "sigs.k8s.io/controller-runtime/pkg/client/fake"
38
39 "edge-infra.dev/pkg/edge/api/apierror"
40 bsltypes "edge-infra.dev/pkg/edge/api/bsl/types"
41 "edge-infra.dev/pkg/edge/api/clients"
42 "edge-infra.dev/pkg/edge/api/graph/generated"
43 "edge-infra.dev/pkg/edge/api/graph/mapper"
44 "edge-infra.dev/pkg/edge/api/graph/model"
45 "edge-infra.dev/pkg/edge/api/graph/resolver"
46 testApi "edge-infra.dev/pkg/edge/api/graph/test"
47 "edge-infra.dev/pkg/edge/api/middleware"
48 "edge-infra.dev/pkg/edge/api/mocks"
49 "edge-infra.dev/pkg/edge/api/services"
50 "edge-infra.dev/pkg/edge/api/services/artifacts"
51 clustersvc "edge-infra.dev/pkg/edge/api/services/cluster"
52 "edge-infra.dev/pkg/edge/api/services/clustersecrets"
53 "edge-infra.dev/pkg/edge/api/services/edgenode"
54 "edge-infra.dev/pkg/edge/api/services/kinform"
55 "edge-infra.dev/pkg/edge/api/services/virtualmachine"
56 edgesql "edge-infra.dev/pkg/edge/api/sql"
57 "edge-infra.dev/pkg/edge/api/testutils"
58 "edge-infra.dev/pkg/edge/api/testutils/seededpostgres"
59 "edge-infra.dev/pkg/edge/api/types"
60 "edge-infra.dev/pkg/edge/api/utils"
61 "edge-infra.dev/pkg/edge/bsl"
62 chariotAPI "edge-infra.dev/pkg/edge/chariot/client"
63 "edge-infra.dev/pkg/edge/constants/api/fleet"
64 "edge-infra.dev/pkg/edge/ctlfish"
65 "edge-infra.dev/pkg/edge/ctlfish/monitor"
66 edgeAgentClientApi "edge-infra.dev/pkg/edge/edgeagent/model"
67 "edge-infra.dev/pkg/edge/info"
68 "edge-infra.dev/pkg/edge/okta"
69 "edge-infra.dev/pkg/f8n/warehouse/pallet"
70 unstructuredutil "edge-infra.dev/pkg/k8s/unstructured"
71 fftest "edge-infra.dev/pkg/lib/featureflag/testutil"
72 iamutils "edge-infra.dev/pkg/lib/gcp/iam/utils"
73 "edge-infra.dev/pkg/lib/runtime/version"
74 "edge-infra.dev/test/fixtures"
75 "edge-infra.dev/test/framework"
76 chariotClientApiTestutils "edge-infra.dev/test/framework/gcp/pubsub"
77 )
78
79 const (
80 topLevelProjectID = "topLevelProjectId"
81 testProject = "test-org"
82 testServiceAccountEmail = "test-app@appspot.gserviceaccount.com"
83 testOauth2ClientID = "test-oauth-2-client-id"
84 testChariotPubsubTopic = "chariot-pubsub-topic"
85 testChariotPubsubSubscription = "chariot-pubsub-subscription"
86 testClusterEdgeID = "3396a52c-6a22-4049-9593-5a63b596a200"
87 testClusterEdgeID2 = "3396a52c-6a22-4049-9593-5a63b596a201"
88 testResetURL = "https://www.example.com"
89 )
90
91 var (
92 ClusterDeletedCount = 0
93 testOrgBannerEdgeID = "3396a52c-6a22-4049-9593-5a63b596a101"
94
95 MockCtrl *gomock.Controller
96 runtimeClient runtimeclient.Client
97 seededPostgres *seededpostgres.SeededPostgres
98
99 defaultCfg = &types.Config{}
100 )
101
102 func cleanupUnitTest() {
103 if seededPostgres != nil {
104 err := seededPostgres.Close()
105 if err != nil {
106 panic(err)
107 }
108 }
109 }
110
111 func setupUnitTest(config *types.TestConfig) (*Suite, error) {
112 runtimeClient = fake.NewClientBuilder().WithScheme(scheme.Scheme).Build()
113
114 defaultRetry = wait.Backoff{
115 Steps: 2,
116 Duration: 2 * time.Second,
117 Factor: 1.1,
118 Jitter: 0.1,
119 }
120
121 chariotClient, err := createChariotV2TestTopic()
122 if err != nil {
123 panic(err)
124 }
125
126
127 fftest.MustInitTestFeatureFlags(map[string]bool{})
128
129 bspMockServer := services.GetMockBspServer(testOrg, testApi.TestOrgID, testUser, testUserRole, testEmail, testResetURL)
130 mockGkeClient := createGKEMockClient()
131 mockContainer := mockeGKEContainer()
132 mockCompute := createMockComputeService()
133 mockSecretManager := createMockForSecretManager()
134 mockBigQuery := createMockBigQuery()
135 mockCompatibility := createMockCompatibilityService()
136
137 mockGCP := mocks.NewMockGcpClientService(MockCtrl)
138 mockGCP.EXPECT().GetSecretClient(gomock.Any(), gomock.Any()).Return(mockSecretManager, nil).AnyTimes()
139 mockGCP.EXPECT().GetContainerClient(gomock.Any(), gomock.Any()).Return(mockContainer, nil).AnyTimes()
140 mockGCP.EXPECT().GetComputeClient(gomock.Any(), gomock.Any()).Return(mockCompute, nil).AnyTimes()
141
142 appConfig := types.Config{
143 BSP: bsltypes.BSPConfig{
144 Root: "/customers/",
145 Endpoint: bspMockServer.URL,
146 ResetURL: testResetURL,
147 },
148 Bff: types.BffConfig{TopLevelProjectID: "test-org"},
149 Chariot: types.ChariotConfig{},
150 Okta: types.OktaConfig{
151 OktaIssuer: "",
152 ClientID: "abc123",
153 },
154 }
155
156 mockOktaServer := okta.MockServer(&appConfig.Okta)
157
158 hc, _ := iamutils.NewIAMTestServer("projects/test-org", testProject, testServiceAccountEmail, testOauth2ClientID)
159 iamHTTPClient := option.WithHTTPClient(hc)
160
161 seededPostgres, err = seededpostgres.New()
162 if err != nil {
163 mockOktaServer.Close()
164 return nil, err
165 }
166 db, err := seededPostgres.DB()
167 if err != nil {
168 _ = seededPostgres.Close()
169 mockOktaServer.Close()
170 return nil, err
171 }
172
173
174 versionTag := version.New().SemVer
175 major, minor, patch, err := version.New().SemVerMajorMinorPatch()
176 if err != nil {
177 _ = seededPostgres.Close()
178 mockOktaServer.Close()
179 return nil, err
180 }
181 if _, err = db.Exec(edgesql.AddCurrentVersionToAvailableArtifacts, fleet.Store, versionTag, major, minor, patch); err != nil {
182 _ = seededPostgres.Close()
183 mockOktaServer.Close()
184 return nil, err
185 }
186 if _, err = db.Exec(edgesql.UpdateLatestAvailableArtifact, fleet.Store, major, minor, patch); err != nil {
187 _ = seededPostgres.Close()
188 mockOktaServer.Close()
189 return nil, err
190 }
191 if _, err = db.Exec(edgesql.UpdateClusterFleetVersion, testBootstrapClusterID, versionTag); err != nil {
192 _ = seededPostgres.Close()
193 mockOktaServer.Close()
194 return nil, err
195 }
196 if _, err = db.Exec(edgesql.UpdateClusterFleetVersion, testBootstrapInactiveClusterID, versionTag); err != nil {
197 _ = seededPostgres.Close()
198 mockOktaServer.Close()
199 return nil, err
200 }
201
202 secret := &bsl.AccessKey{SecretKey: "testPassword", SharedKey: "testUsername"}
203 bslClient := bsl.NewBSLClient(appConfig.BSP, func(_ context.Context, _ string) (*bsl.AccessKey, error) { return secret, nil })
204 oktaClient := okta.New(appConfig.Okta)
205 ac := mocks.NewMockArtifactRegistryClient(MockCtrl)
206 path, err := fixtures.Layout()
207 if err != nil {
208 mockOktaServer.Close()
209 return nil, err
210 }
211 bsl, err := path.Get(name.MustParseReference("edge-bsl:latest"))
212 if err != nil {
213 mockOktaServer.Close()
214 return nil, err
215 }
216 p, err := pallet.New(bsl)
217 if err != nil {
218 mockOktaServer.Close()
219 return nil, err
220 }
221 ac.EXPECT().
222 Get(gomock.Any(), gomock.Any(), gomock.Any()).
223 Return(p, nil).AnyTimes()
224
225 clusterLabelSvc := clustersvc.NewLabelService(db)
226 gcpService := services.NewGcpService(mockGCP, "top-level-project", mockBigQuery)
227 chariotService := services.NewChariotService(topLevelProjectID, testChariotPubsubTopic, chariotClient)
228 roleService := services.NewRoleService(appConfig.BSP, bslClient)
229 bannerService := services.NewBannerService(mockGkeClient, chariotService, bslClient, "top-level-project", db, defaultCfg)
230 userManagementService := services.NewUserManagementService(appConfig, bslClient, oktaClient, roleService, bannerService)
231 secretService := services.NewSecretService(mockGkeClient, chariotService, gcpService, mockBigQuery)
232 iamService := services.NewIAMService(iamHTTPClient)
233 bslSiteService := services.NewBSLSiteService(bslClient, db)
234 artifactsService := artifacts.NewArtifactsService(db, clusterLabelSvc)
235 labelService := services.NewLabelService(artifactsService, db)
236 tenantService := services.NewTenantService(db, bslClient, &appConfig.BSP)
237 clusterConfigService := services.NewClusterConfigService(db)
238 terminalService := services.NewTerminalServiceBQ(db, mockBigQuery, labelService)
239 compatibilityService := services.NewCompatibilityService(db)
240 storeClusterService := services.NewStoreClusterService(mockGkeClient, mockBigQuery, db, chariotService, terminalService, compatibilityService)
241 bootstrapService := services.NewBootstrapService("top-level-project", ac, db)
242 terminalLabelService := services.NewTerminalLabelService(db, chariotService, terminalService, storeClusterService, labelService)
243 activationCodeService := edgenode.NewActivationCodeService(db, terminalService, storeClusterService, clusterConfigService, secretService, gcpService, bannerService)
244 registrationService := services.NewRegistrationService(mockGkeClient, topLevelProjectID, secretService, gcpService, bslSiteService, iamService, db, chariotService, terminalService, activationCodeService, clusterLabelSvc, labelService)
245 helmService := services.NewHelmService(&appConfig, chariotService, gcpService, db, mockBigQuery, mockCompatibility)
246 edgeAgentService := services.NewEdgeAgentService(edgeAgentClientApi.EdgeAgentTopicAndOwner)
247 virtualMachineService := services.NewVirtualMachineService(db)
248 namespaceService := services.NewNamespaceService(db)
249 artifactRegistryService := services.NewArtifactRegistryService(db)
250 clusterSecretService := clustersecrets.NewClusterSecretService(db, gcpService, &config.Config)
251 kinformService := kinform.New(db)
252 vmStatusService := virtualmachine.NewVirtualMachineStatusService(db, kinformService)
253
254 resolver := &resolver.Resolver{
255 GKEClient: mockGkeClient,
256 UserManagementService: userManagementService,
257 SecretService: secretService,
258 RoleService: roleService,
259 HelmService: helmService,
260 GCPService: gcpService,
261 GCPClientService: mockGCP,
262 BannerService: bannerService,
263 RegistrationService: registrationService,
264 StoreClusterService: storeClusterService,
265 BSLSiteService: bslSiteService,
266 IAMService: iamService,
267 BootstrapService: bootstrapService,
268 ChariotService: chariotService,
269 LabelService: labelService,
270 TenantService: tenantService,
271 Config: &appConfig,
272 TerminalService: terminalService,
273 ClusterConfigService: clusterConfigService,
274 TerminalLabelService: terminalLabelService,
275 VirtualMachineService: virtualMachineService,
276 ArtifactsService: artifactsService,
277 NamespaceService: namespaceService,
278 CompatibilityService: compatibilityService,
279 ArtifactRegistryService: artifactRegistryService,
280 ActivationCodeService: activationCodeService,
281 VirtualMachineStatusService: vmStatusService,
282 KinformService: kinformService,
283 ClusterSecretService: clusterSecretService,
284 EdgeAgentService: edgeAgentService,
285 }
286
287 noAuthTest := func(ctx context.Context, _ interface{}, next graphql.Resolver, _ string) (res interface{}, err error) {
288 return next(ctx)
289 }
290
291 gqlConfig := generated.Config{Resolvers: resolver}
292 gqlConfig.Directives.HasRole = resolver.HasRole()
293 gqlConfig.Directives.HasBannerAccess = noAuthTest
294 gqlConfig.Directives.HasBannerAccessInput = noAuthTest
295 gqlConfig.Directives.HasClusterAccess = noAuthTest
296 gqlConfig.Directives.HasClusterAccessInput = noAuthTest
297 gqlConfig.Directives.HasHelmWorkloadAccess = noAuthTest
298 gqlConfig.Directives.HasHelmWorkloadAccessInput = noAuthTest
299 gqlConfig.Directives.HasLabelAccessInput = noAuthTest
300 gqlConfig.Directives.HasLabelAccess = noAuthTest
301 gqlConfig.Directives.HasTerminalAccess = noAuthTest
302 gqlConfig.Directives.HasTerminalAccessInput = noAuthTest
303 gqlConfig.Directives.CanAssignRole = resolver.CanAssignRole()
304 srv := handler.NewDefaultServer(generated.NewExecutableSchema(gqlConfig))
305 srv.Use(&apierror.Extension{})
306
307
308 testHelmChart = "test-helm-chart1"
309
310
311 token, err := middleware.CreateToken(testUser, testEmail, testOrg, jwtSecret, []string{superAdminRole, edgeLeadsRole}, "bslToken", "bsl", "")
312 if err != nil {
313 _ = seededPostgres.Close()
314 mockOktaServer.Close()
315 return nil, err
316 }
317 if err = testSetup(); err != nil {
318 _ = seededPostgres.Close()
319 mockOktaServer.Close()
320 return nil, err
321 }
322
323 unWrap := func(f gin.HandlerFunc) func(http.Handler) http.Handler {
324 return func(h http.Handler) http.Handler {
325 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
326 c, _ := gin.CreateTestContext(w)
327 c.Request = r
328 f(c)
329 h.ServeHTTP(w, r.WithContext(c.Request.Context()))
330 })
331 }
332 }
333 handler := unWrap(middleware.AuthMiddleware(jwtSecret, totpSecret, db))(srv)
334 ResolverClient = client.New(handler, client.AddHeader("Authorization", "Bearer "+token))
335 testTime := fmt.Sprintf("%d", time.Now().UnixNano())
336 f := framework.New("edge-backend-unit")
337 return &Suite{
338 Framework: f,
339 client: runtimeClient,
340 ctx: context.Background(),
341 projectID: projectID,
342 testBannerEU: &testApi.TestBannerEU,
343 testTime: testTime,
344 ChariotClient: chariotClient,
345 Resolver: resolver,
346 DB: db,
347 Config: config,
348 }, nil
349 }
350
351 func createChariotV2TestTopic() (option.ClientOption, error) {
352 chariotPubsubClient, err := chariotClientApiTestutils.NewMockPubsubServer()
353 if err != nil {
354 return nil, err
355 }
356 _, err = chariotClientApiTestutils.CreateMockTopic(context.Background(), topLevelProjectID, testChariotPubsubTopic, chariotPubsubClient)
357 if err != nil {
358 return nil, err
359 }
360 go func() {
361 err := chariotClientApiTestutils.CreateMockSubscription(context.Background(), nil, topLevelProjectID, testChariotPubsubTopic, testChariotPubsubSubscription, 20*time.Second, "", func(msg *pubSub.Message) {
362 message := &chariotAPI.ChariotMessage{}
363 err := json.Unmarshal(msg.Data, message)
364 if err != nil {
365 fmt.Println(err)
366 }
367 fmt.Printf("Chariot Message: %v\n", message)
368 for _, t := range message.Objects {
369 rawDecodedText, _ := base64.StdEncoding.DecodeString(t)
370 resource := &unstructured.Unstructured{}
371 _ = resource.UnmarshalJSON(rawDecodedText)
372 err = chariotAction(context.Background(), message.Operation, resource)
373 fmt.Println("PublishMessage", resource.GetKind(), resource.GetNamespace(), resource.GetName(), resource.GetLabels(), resource.GetResourceVersion())
374 if err != nil {
375 fmt.Println(err)
376 }
377 if resource.GetKind() == "Cluster" && message.Operation == "DELETE" {
378 ClusterDeletedCount++
379 }
380 }
381 }, chariotPubsubClient)
382 if err != nil {
383 fmt.Println(err)
384 }
385 }()
386 return chariotPubsubClient, nil
387 }
388
389 func chariotAction(ctx context.Context, operation string, un *unstructured.Unstructured) error {
390 switch operation {
391 case "update", "UPDATE":
392 un.SetCreationTimestamp(metav1.Time{})
393
394
395
396
397 err = runtimeClient.Update(ctx, un)
398 case "delete", "DELETE":
399 err = runtimeClient.Delete(ctx, un)
400 default:
401 err = runtimeClient.Create(ctx, un)
402 }
403 return err
404 }
405
406 func createMockBigQuery() clients.BQClient {
407 mockBigQuery := mocks.NewMockBQClient(MockCtrl)
408
409
410
411
412 mockBigQuery.EXPECT().GetKubeResource(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(ctx context.Context, _ string, cluster *model.Cluster, input model.LoqRequest) ([]string, error) {
413 return bigQueryDataRetrieval(ctx, cluster, input)
414 }).AnyTimes()
415 return mockBigQuery
416 }
417
418 func createMockComputeService() *mocks.MockComputeService {
419 mockCompute := mocks.NewMockComputeService(MockCtrl)
420 mockCompute.EXPECT().GetZones(gomock.Any()).Return(&compute.ZoneList{Items: []*compute.Zone{{Name: testClusterZone}, {Name: "us-east1-c"}}}, nil).AnyTimes()
421 mockCompute.EXPECT().GetMachineTypes(gomock.Any(), testClusterZone).Return(&compute.MachineTypeList{
422 Items: []*compute.MachineType{{Name: testClusterMachineType, GuestCpus: 16, MemoryMb: 64 * 1024}, {Name: "c2-standard-8", GuestCpus: 8, MemoryMb: 32 * 1024}},
423 }, nil).AnyTimes()
424 mockCompute.EXPECT().GetMachineTypes(gomock.Any(), "bad-zone").Return(nil, k8sErrors.NewNotFound(schema.GroupResource{}, "")).AnyTimes()
425 mockCompute.EXPECT().GetMachineType(gomock.Any(), testClusterZone, testClusterMachineType).Return(&compute.MachineType{Name: testClusterMachineType, GuestCpus: 16, MemoryMb: 64 * 1024}, nil).AnyTimes()
426 mockCompute.EXPECT().GetMachineType(gomock.Any(), testClusterZone, "bad-machine-type").Return(nil, k8sErrors.NewNotFound(schema.GroupResource{}, "")).AnyTimes()
427 return mockCompute
428 }
429
430 func mockeGKEContainer() *mocks.MockContainerService {
431 mockContainer := mocks.NewMockContainerService(MockCtrl)
432 mockContainer.EXPECT().GetServerConfig(gomock.Any(), testClusterZone).Return(&container.ServerConfig{ValidMasterVersions: []string{"1.19.10-gke.1600", "1.19.10-gke.1000"}}, nil).AnyTimes()
433 mockContainer.EXPECT().GetServerConfig(gomock.Any(), "bad-zone").Return(nil, k8sErrors.NewNotFound(schema.GroupResource{}, "")).AnyTimes()
434 return mockContainer
435 }
436
437 func createGKEMockClient() *mocks.MockGkeClient {
438 mockGkeClient := mocks.NewMockGkeClient(MockCtrl)
439 mockGkeClient.EXPECT().GetConfigForCluster(gomock.Any(), mapper.CreateGKECluster(&testRegion, &testOrg)).Return(&rest.Config{
440 Host: "http://localhost:8080",
441 TLSClientConfig: rest.TLSClientConfig{
442 CAData: []byte("CAData"),
443 },
444 }, nil).AnyTimes()
445 mockGkeClient.EXPECT().GetRuntimeClient(gomock.Any(), mapper.CreateGKECluster(&badCluster, &testOrg)).Return(nil, k8sErrors.NewNotFound(schema.GroupResource{}, "")).AnyTimes()
446 mockGkeClient.EXPECT().GetRuntimeClient(gomock.Any(), gomock.Any()).Return(runtimeClient, nil).AnyTimes()
447 return mockGkeClient
448 }
449
450 func createMockCompatibilityService() *mocks.MockCompatibilityService {
451 mockCompatibility := mocks.NewMockCompatibilityService(MockCtrl)
452 mockCompatibility.EXPECT().IsCompatible(gomock.Any(), gomock.Any(), gomock.Any()).Return(true, nil).AnyTimes()
453 return mockCompatibility
454 }
455
456 func createMockForSecretManager() *mocks.MockSecretManagerService {
457 mockSecretManager := mocks.NewMockSecretManagerService(MockCtrl)
458 mockSecretManager.EXPECT().AddSecret(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
459 DoAndReturn(func(_ context.Context, secretID string, secretValue []byte, labels map[string]string, _ bool, _ *time.Time, _ string) error {
460 return testutils.AddToSecretManager(secretValue, secretID, testOrg, labels)
461 }).AnyTimes()
462 mockSecretManager.EXPECT().GetSecret(gomock.Any(), gomock.Any()).
463 DoAndReturn(func(_ context.Context, name string) (*secretmanagerpb.Secret, error) {
464 result, err := testutils.GetFromSecretManager(testOrg, name)
465 if err != nil {
466 return nil, err
467 }
468 return result[0], err
469 }).AnyTimes()
470 mockSecretManager.EXPECT().DeleteSecret(gomock.Any(), gomock.Any()).
471 DoAndReturn(func(_ context.Context, name string) error {
472 return testutils.DeleteFromSecretManager(testOrg, name)
473 }).AnyTimes()
474 mockSecretManager.EXPECT().GetLatestSecretValue(gomock.Any(), gomock.Any()).
475 DoAndReturn(func(_ context.Context, secretID string) ([]byte, error) {
476 s, err := testutils.GetSecretInfoFromSecretManager(testOrg, secretID)
477 return s[0].SecretValue, err
478 }).AnyTimes()
479 mockSecretManager.EXPECT().GetLatestSecretValueInfo(gomock.Any(), gomock.Any()).
480 DoAndReturn(func(_ context.Context, secretID string) (*secretmanagerpb.SecretVersion, error) {
481 s, err := testutils.GetSecretInfoFromSecretManager(testOrg, secretID)
482 if err != nil {
483 return nil, err
484 }
485 return s[0].SecretVersion, err
486 }).AnyTimes()
487 mockSecretManager.EXPECT().ListSecrets(gomock.Any(), gomock.Any()).
488 DoAndReturn(func(_ context.Context, pageToken string) ([]*secretmanagerpb.Secret, string, error) {
489 result, err := testutils.GetFromSecretManager(testOrg, pageToken)
490 return result, projectID, err
491 }).AnyTimes()
492 mockSecretManager.EXPECT().GetProjectID().Return(testOrg).AnyTimes()
493 return mockSecretManager
494 }
495
496 func testSetup() error {
497 if err := runtimeClient.Create(context.Background(), &corev1.Namespace{
498 ObjectMeta: metav1.ObjectMeta{Name: "flux-system"},
499 }); err != nil {
500 return err
501 }
502 if err := runtimeClient.Create(context.Background(), getDefaultServiceAccountSecret()); err != nil {
503 return err
504 }
505 if err := runtimeClient.Create(context.Background(), getHelmRelease()); err != nil {
506 return err
507 }
508 if err := runtimeClient.Create(context.Background(), newBSLUserSecret("edge-system", testOrg)); err != nil {
509 return err
510 }
511 if err := runtimeClient.Create(context.Background(), getTestProject(testOrg)); err != nil {
512 return err
513 }
514 if err := runtimeClient.Create(context.Background(), getEdgeInfoConfigmap()); err != nil {
515 return err
516 }
517 return err
518 }
519
520 func getEdgeInfoConfigmap() *corev1.ConfigMap {
521 return info.BuildConfigMap("test-org", testStore, "store", testRegion, "test-org", "fleet", topLevelProjectID, "3396a52c-6a22-4049-9593-5a63b596a100", "3396a52c-6a22-4049-9593-5a63b596a201", "test-env-url")
522 }
523
524
525 func getDefaultServiceAccountSecret() *corev1.Secret {
526 data := make(map[string][]byte)
527 sa, _ := json.Marshal(&model.ServiceAccount{
528 ProjectID: &projectID,
529 })
530 data["key.json"] = sa
531 return &corev1.Secret{
532 TypeMeta: metav1.TypeMeta{
533 APIVersion: "v1",
534 Kind: "Secret",
535 },
536 ObjectMeta: metav1.ObjectMeta{
537 Namespace: mapper.SANamespace,
538 Name: mapper.SAName,
539 CreationTimestamp: metav1.Now(),
540 },
541 Data: data,
542 }
543 }
544
545 func getHelmRelease() *helmApi.HelmRelease {
546 return &helmApi.HelmRelease{
547 ObjectMeta: metav1.ObjectMeta{
548 Name: "test-helm-release",
549 Namespace: "flux-system",
550 },
551 Spec: helmApi.HelmReleaseSpec{
552 Interval: metav1.Duration{
553 Duration: time.Duration(2) * time.Minute,
554 },
555 ReleaseName: "test-helm-release",
556 TargetNamespace: "flux-system",
557 Chart: &helmApi.HelmChartTemplate{
558 Spec: helmApi.HelmChartTemplateSpec{
559 Chart: "podinfo",
560 Version: "1.0",
561 SourceRef: helmApi.CrossNamespaceObjectReference{
562 Kind: "HelmRepository",
563 Name: "test-repo",
564 },
565 },
566 },
567 },
568 }
569 }
570
571
572 func newBSLUserSecret(ns, name string) *corev1.Secret {
573 return &corev1.Secret{
574 TypeMeta: metav1.TypeMeta{
575 APIVersion: "v1",
576 Kind: "Secret",
577 },
578 ObjectMeta: metav1.ObjectMeta{
579 Namespace: ns,
580 Name: name,
581 },
582 Data: map[string][]byte{
583 bsl.SharedKey: []byte("testSharedKey"),
584 bsl.SecretKey: []byte("testSecretKey"),
585 },
586 }
587 }
588
589
590 func getTestProject(name string) *resourceApi.Project {
591 return &resourceApi.Project{
592 ObjectMeta: metav1.ObjectMeta{
593 Name: name,
594 Namespace: name,
595 },
596 Spec: resourceApi.ProjectSpec{
597 BillingAccountRef: &v1alpha1.ResourceRef{
598 Name: "billingAccount",
599 },
600 FolderRef: &v1alpha1.ResourceRef{
601 Name: "folderRef",
602 },
603 Name: name,
604 ResourceID: &name,
605 },
606 }
607 }
608
609 func bigQueryDataRetrieval(ctx context.Context, cluster *model.Cluster, query model.LoqRequest) ([]string, error) {
610
611 key := &runtimeclient.ObjectKey{}
612 if query.Name == nil && query.Namespace == nil {
613 key = nil
614 }
615 if query.Namespace != nil {
616 key.Namespace = *query.Namespace
617 }
618 if query.Name != nil {
619 key.Name = *query.Name
620 }
621 gvk := &schema.GroupVersionKind{
622 Kind: query.Kind,
623 Group: query.Group,
624 Version: query.Version,
625 }
626 excludedLabels := []string{"delete"}
627 newReq, err := labels.NewRequirement("type", selection.NotIn, excludedLabels)
628 if err != nil {
629 return nil, err
630 }
631 newSelector := labels.NewSelector()
632 newSelector.Add(*newReq)
633 matcher := runtimeclient.MatchingLabelsSelector{Selector: newSelector}
634 switch {
635 case (key == nil || (query.Namespace == nil && query.Name == nil)) && query.Kind != "HelmRelease":
636 list := &unstructured.UnstructuredList{}
637 list.SetGroupVersionKind(*gvk)
638 if err := runtimeClient.List(ctx, list, matcher); err != nil {
639 return nil, err
640 }
641 return unstructuredutil.UnstructuredListToStrings(list)
642 case query.Kind == "ClusterStatus":
643 return handleStoreStatusQuery(key)
644 case query.Kind == "HelmRelease":
645 list := &unstructured.UnstructuredList{}
646 list.SetGroupVersionKind(*gvk)
647 if err := runtimeClient.List(ctx, list, runtimeclient.InNamespace("flux-system"), matcher); err != nil {
648 return nil, err
649 }
650 return unstructuredutil.UnstructuredListToStrings(list)
651 case query.Kind == "ConfigMap" && key.Name == bsl.BSLInfoConfigMapName:
652 return handleConfigMapQuery(cluster.ClusterEdgeID, cluster.Name)
653 case utils.Contains([]string{"Banner", "GKECluster", "Cluster", "ConfigMap"}, gvk.GroupKind().Kind):
654 fmt.Println("Cluster Scope", gvk, key, "delete")
655 fallthrough
656 case key.Name == "" && key.Namespace != "":
657 list := &unstructured.UnstructuredList{}
658 list.SetGroupVersionKind(*gvk)
659 if err := runtimeClient.List(ctx, list, runtimeclient.InNamespace(key.Namespace), matcher); err != nil {
660 return nil, err
661 }
662 return unstructuredutil.UnstructuredListToStrings(list)
663 default:
664 un := &unstructured.Unstructured{}
665 un.SetGroupVersionKind(*gvk)
666 if err := runtimeClient.Get(ctx, *key, un); err != nil {
667 return nil, err
668 }
669 data, err := un.MarshalJSON()
670 return []string{string(data)}, err
671 }
672 }
673
674 func handleStoreStatusQuery(key *runtimeclient.ObjectKey) ([]string, error) {
675 nodeVersion := "v1.23.6"
676 if key.Name == ctlfish.ClusterStatusName {
677 testSyncInfo := monitor.SyncInfo{
678 LastUpdated: "test-last-updated",
679 Revision: "test-revision",
680 StatusMessage: "test-status-message",
681 Error: false,
682 Suspended: true,
683 }
684 buckets := map[string]monitor.BucketInfo{
685 "test-bucket-1": {
686 Excludes: "test-excludes",
687 BucketName: "test-bucket-name",
688 FluxStatus: testSyncInfo,
689 },
690 }
691 kustomizations := map[string]monitor.KustomizationInfo{
692 "test-kustomization-1": {Path: "test-path-1", Source: "test-source-1", FluxStatus: testSyncInfo},
693 "test-kustomization-2": {Path: "test-path-2", Source: "test-source-2", FluxStatus: testSyncInfo},
694 }
695 status := &monitor.ClusterStatus{
696 Status: "Ready",
697 NodeVersion: nodeVersion,
698 Buckets: buckets,
699 Kustomizations: kustomizations,
700 }
701 data, err := json.Marshal(status)
702 return []string{string(data)}, err
703 }
704 return []string{}, fmt.Errorf("%v store status not found", key)
705 }
706
707 func handleConfigMapQuery(clusterEdgeID, clusterName string) ([]string, error) {
708 if clusterEdgeID == "5bc12c67-d9b0-4f13-a6d4-4852b0c11291" || clusterName == "test_cluster-3" {
709 return getConfigMap("test_bsl_site_id-3", "")
710 } else if clusterEdgeID == testClusterEdgeID2 || clusterName == "test_cluster-2" {
711 return getConfigMap("test_bsl_site_id-2", "")
712 } else if clusterEdgeID == testClusterEdgeID || clusterName == "test_cluster02" {
713 return getConfigMap("test_bsl_site_id", "test mismatch in site description")
714 }
715 return []string{}, fmt.Errorf("bsl-info config map not found, cluster: %s, %s", clusterEdgeID, clusterName)
716 }
717
718 func getConfigMap(bslSiteID, description string) ([]string, error) {
719 configMap := bsl.BuildConfigMap("test-store", "test-enterprise-unit-name", "", services.DefaultLatitude, services.DefaultLongitude, &bslSiteID)
720 if description != "" {
721 configMap.Data[bsl.BSLSiteDescription] = description
722 }
723 data, err := json.Marshal(configMap)
724 return []string{string(data)}, err
725 }
726
View as plain text