diff --git a/core/server/fluxruntime.go b/core/server/fluxruntime.go index c594295bee..a631884b35 100644 --- a/core/server/fluxruntime.go +++ b/core/server/fluxruntime.go @@ -13,7 +13,6 @@ import ( "github.com/weaveworks/weave-gitops/core/logger" coretypes "github.com/weaveworks/weave-gitops/core/server/types" pb "github.com/weaveworks/weave-gitops/pkg/api/core" - "github.com/weaveworks/weave-gitops/pkg/featureflags" "github.com/weaveworks/weave-gitops/pkg/server/auth" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" @@ -67,6 +66,20 @@ func lookupEnv(envVar, fallback string) string { func (cs *coreServer) ListFluxRuntimeObjects(ctx context.Context, msg *pb.ListFluxRuntimeObjectsRequest) (*pb.ListFluxRuntimeObjectsResponse, error) { respErrors := []*pb.ListError{} + respErrors, results := listRuntimeObjectsByLabels(ctx, cs, respErrors, FluxRuntimeLabels) + + return &pb.ListFluxRuntimeObjectsResponse{Deployments: results, Errors: respErrors}, nil +} + +func (cs *coreServer) ListRuntimeObjects(ctx context.Context, msg *pb.ListRuntimeObjectsRequest) (*pb.ListRuntimeObjectsResponse, error) { + respErrors := []*pb.ListError{} + + respErrors, results := listRuntimeObjectsByLabels(ctx, cs, respErrors, WeaveGitopsRuntimeLabels) + + return &pb.ListRuntimeObjectsResponse{Deployments: results, Errors: respErrors}, nil +} + +func listRuntimeObjectsByLabels(ctx context.Context, cs *coreServer, respErrors []*pb.ListError, labels []string) ([]*pb.ListError, []*pb.Deployment) { clustersClient, err := cs.clustersManager.GetImpersonatedClient(ctx, auth.Principal(ctx)) if err != nil { if merr, ok := err.(*multierror.Error); ok { @@ -80,7 +93,7 @@ func (cs *coreServer) ListFluxRuntimeObjects(ctx context.Context, msg *pb.ListFl var results []*pb.Deployment - for _, runtimeLabel := range getRuntimeLabels() { + for _, runtimeLabel := range labels { for clusterName, nss := range cs.clustersManager.GetClustersNamespaces() { fluxNamespaces := filterFluxNamespace(nss) if len(fluxNamespaces) == 0 { @@ -128,23 +141,31 @@ func (cs *coreServer) ListFluxRuntimeObjects(ctx context.Context, msg *pb.ListFl } } } + return respErrors, results +} + +func (cs *coreServer) ListFluxCrds(ctx context.Context, msg *pb.ListFluxCrdsRequest) (*pb.ListFluxCrdsResponse, error) { + respErrors, results, err2 := listRuntimeCrdsByLabel(ctx, cs, FluxRuntimeLabels) + if err2 != nil { + return nil, err2 + } - return &pb.ListFluxRuntimeObjectsResponse{Deployments: results, Errors: respErrors}, nil + return &pb.ListFluxCrdsResponse{Crds: results, Errors: respErrors}, nil } -// getRuntimeLabels returns the labels that are used to identify the runtime objects based on -// whether the user has enabled `WEAVE_GITOPS_FEATURE_GITOPS_RUNTIME` or not -func getRuntimeLabels() []string { - if featureflags.Get(GitopsRuntimeFeatureFlag) == "true" { - return WeaveGitopsRuntimeLabels +func (cs *coreServer) ListRuntimeCrds(ctx context.Context, msg *pb.ListRuntimeCrdsRequest) (*pb.ListRuntimeCrdsResponse, error) { + respErrors, results, err2 := listRuntimeCrdsByLabel(ctx, cs, WeaveGitopsRuntimeLabels) + if err2 != nil { + return nil, err2 } - return FluxRuntimeLabels + + return &pb.ListRuntimeCrdsResponse{Crds: results, Errors: respErrors}, nil } -func (cs *coreServer) ListFluxCrds(ctx context.Context, msg *pb.ListFluxCrdsRequest) (*pb.ListFluxCrdsResponse, error) { +func listRuntimeCrdsByLabel(ctx context.Context, cs *coreServer, labels []string) ([]*pb.ListError, []*pb.Crd, error) { clustersClient, err := cs.clustersManager.GetImpersonatedClient(ctx, auth.Principal(ctx)) if err != nil { - return nil, fmt.Errorf("error getting impersonating client: %w", err) + return nil, nil, fmt.Errorf("error getting impersonating client: %w", err) } clist := clustersmngr.NewClusteredList(func() client.ObjectList { @@ -153,7 +174,7 @@ func (cs *coreServer) ListFluxCrds(ctx context.Context, msg *pb.ListFluxCrdsRequ respErrors := []*pb.ListError{} - for _, runtimeLabel := range getRuntimeLabels() { + for _, runtimeLabel := range labels { opts := client.MatchingLabels{ coretypes.PartOfLabel: runtimeLabel, } @@ -161,7 +182,7 @@ func (cs *coreServer) ListFluxCrds(ctx context.Context, msg *pb.ListFluxCrdsRequ var errs clustersmngr.ClusteredListError if !errors.As(err, &errs) { - return nil, fmt.Errorf("CRDs clustered list: %w", errs) + return nil, nil, fmt.Errorf("CRDs clustered list: %w", errs) } for _, e := range errs.Errors { @@ -208,8 +229,7 @@ func (cs *coreServer) ListFluxCrds(ctx context.Context, msg *pb.ListFluxCrdsRequ } } } - - return &pb.ListFluxCrdsResponse{Crds: results, Errors: respErrors}, nil + return respErrors, results, nil } func filterFluxNamespace(nss []v1.Namespace) []v1.Namespace { diff --git a/core/server/fluxruntime_internal_test.go b/core/server/fluxruntime_internal_test.go deleted file mode 100644 index 45ed651ad8..0000000000 --- a/core/server/fluxruntime_internal_test.go +++ /dev/null @@ -1,52 +0,0 @@ -package server - -import ( - "os" - "testing" - - "github.com/google/go-cmp/cmp" - "github.com/weaveworks/weave-gitops/pkg/featureflags" -) - -func Test_getRuntimeLabels(t *testing.T) { - tests := []struct { - name string - gitopsRuntimeFeatureFlag string - wantRuntimeLabels []string - }{ - { - name: "should return flux if not feature flag exists", - wantRuntimeLabels: FluxRuntimeLabels, - }, - { - name: "should return flux if feature flag exists but empty", - wantRuntimeLabels: FluxRuntimeLabels, - gitopsRuntimeFeatureFlag: "", - }, - { - name: "should return flux if feature flag exists and false", - wantRuntimeLabels: FluxRuntimeLabels, - gitopsRuntimeFeatureFlag: "false", - }, - { - name: "should return weave gitops if feature flag exists and true", - wantRuntimeLabels: WeaveGitopsRuntimeLabels, - gitopsRuntimeFeatureFlag: "true", - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.gitopsRuntimeFeatureFlag != "" { - _ = os.Setenv(GitopsRuntimeFeatureFlag, tt.gitopsRuntimeFeatureFlag) - } - defer func() { - _ = os.Unsetenv(GitopsRuntimeFeatureFlag) - }() - featureflags.SetFromEnv(os.Environ()) - gotLabels := getRuntimeLabels() - if diff := cmp.Diff(tt.wantRuntimeLabels, gotLabels); diff != "" { - t.Fatalf("unexpected labels:\n%s", diff) - } - }) - } -} diff --git a/core/server/fluxruntime_test.go b/core/server/fluxruntime_test.go index ae840377ca..80295a14f9 100644 --- a/core/server/fluxruntime_test.go +++ b/core/server/fluxruntime_test.go @@ -387,14 +387,14 @@ func TestListFluxRuntimeObjects(t *testing.T) { coretypes.PartOfLabel: server.Flux, }}}, newDeployment("kustomize-controller", "flux-ns", map[string]string{coretypes.PartOfLabel: server.Flux}), - newDeployment("weave-gitops-enterprise-mccp-cluster-service", "flux-ns", map[string]string{coretypes.PartOfLabel: server.WeaveGitops}), + newDeployment("policy-agent", "flux-ns", map[string]string{coretypes.PartOfLabel: server.WeaveGitops}), newDeployment("other-controller-in-flux-ns", "flux-ns", map[string]string{}), }, "true", func(res *pb.ListFluxRuntimeObjectsResponse) { g.Expect(res.Deployments).To(HaveLen(2), "expected deployments in the flux namespace to be returned") g.Expect(res.Deployments[0].Name).To(Equal("kustomize-controller")) - g.Expect(res.Deployments[1].Name).To(Equal("weave-gitops-enterprise-mccp-cluster-service")) + g.Expect(res.Deployments[1].Name).To(Equal("policy-agent")) }, }, } @@ -420,6 +420,79 @@ func TestListFluxRuntimeObjects(t *testing.T) { } } +func TestListRuntimeObjects(t *testing.T) { + g := NewGomegaWithT(t) + + ctx := context.Background() + + tests := []struct { + description string + objects []runtime.Object + assertions func(*pb.ListRuntimeObjectsResponse) + }{ + { + "no runtime", + []runtime.Object{ + &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "ns1"}}, + }, + func(res *pb.ListRuntimeObjectsResponse) { + g.Expect(res.Errors[0].Message).To(Equal(server.ErrFluxNamespaceNotFound.Error())) + g.Expect(res.Errors[0].Namespace).To(BeEmpty()) + g.Expect(res.Errors[0].ClusterName).To(Equal(cluster.DefaultCluster)) + }, + }, + { + "return weave gitops", + []runtime.Object{ + &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "flux-ns", Labels: map[string]string{ + coretypes.PartOfLabel: server.Flux, + }}}, + newDeployment("kustomize-controller", "flux-ns", map[string]string{coretypes.PartOfLabel: server.Flux}), + newDeployment("policy-agent", "flux-ns", map[string]string{coretypes.PartOfLabel: server.WeaveGitops}), + newDeployment("other-controller-in-flux-ns", "flux-ns", map[string]string{}), + }, + func(res *pb.ListRuntimeObjectsResponse) { + g.Expect(res.Deployments).To(HaveLen(2), "expected deployments in the flux namespace to be returned") + g.Expect(res.Deployments[0].Name).To(Equal("kustomize-controller")) + g.Expect(res.Deployments[1].Name).To(Equal("policy-agent")) + }, + }, + { + "use flux-system namespace when no namespace label available", + []runtime.Object{ + &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "flux-system"}}, + newDeployment("kustomize-controller", "flux-system", map[string]string{coretypes.PartOfLabel: server.Flux}), + newDeployment("policy-agent", "flux-system", map[string]string{coretypes.PartOfLabel: server.WeaveGitops}), + newDeployment("other-controller-in-flux-ns", "flux-system", map[string]string{}), + }, + func(res *pb.ListRuntimeObjectsResponse) { + g.Expect(res.Deployments).To(HaveLen(2), "expected deployments in the default flux namespace to be returned") + g.Expect(res.Deployments[0].Name).To(Equal("kustomize-controller")) + g.Expect(res.Deployments[1].Name).To(Equal("policy-agent")) + }, + }, + } + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + _ = os.Setenv(server.GitopsRuntimeFeatureFlag, "true") + defer func() { + _ = os.Unsetenv(server.GitopsRuntimeFeatureFlag) + }() + featureflags.SetFromEnv(os.Environ()) + scheme, err := kube.CreateScheme() + g.Expect(err).To(BeNil()) + client := fake.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(tt.objects...).Build() + cfg := makeServerConfig(client, t, "") + c := makeServer(cfg, t) + + res, err := c.ListRuntimeObjects(ctx, &pb.ListRuntimeObjectsRequest{}) + + g.Expect(err).NotTo(HaveOccurred()) + tt.assertions(res) + }) + } +} + func newDeployment(name, ns string, labels map[string]string) *appsv1.Deployment { return &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{