From 41e65bc56bbae6329dcd9d0242656ae0848cbc13 Mon Sep 17 00:00:00 2001 From: Carlos Salguero Date: Wed, 14 Dec 2022 08:48:27 -0300 Subject: [PATCH] PMM-10705 Use OLM to install / upgrade operators (#1391) * Added OLM methods * Register cluster using OLM * Updated deps * Switched to OLM to install operators * Ran format * Updated deps * Fixed files generation * Fixed install plan approval * Removed dead code * Updated deps * Ran tidy * Fixed vm operator installation * Updated code to handle the default NS * Updated deps * Minor fix using a variable instead of hardcoded value * Fixed upgrade * Ran make gen * Ran make gen & format * Fixed test * Fixed OLM test * Fixed tests * Updated test Co-authored-by: Iaroslavna Soloveva <90199600+solovevayaroslavna@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 +- managed/services/dbaas/dbaas_client.go | 39 ++++ .../management/dbaas/components_service.go | 104 ++++----- .../dbaas/components_service_test.go | 46 +++- .../dbaas/db_cluster_service_test.go | 13 +- managed/services/management/dbaas/deps.go | 13 ++ .../management/dbaas/kubernetes_server.go | 217 ++++++++++++++---- .../dbaas/kubernetes_server_test.go | 27 ++- .../dbaas/mock_dbaas_client_test.go | 180 +++++++++++++++ .../dbaas/psmdb_cluster_service_test.go | 10 +- .../dbaas/pxc_cluster_service_test.go | 11 +- managed/services/supervisord/logs_test.go | 8 +- managed/utils/tests/fuzz.go | 1 - 14 files changed, 556 insertions(+), 119 deletions(-) diff --git a/go.mod b/go.mod index 7015b2d54f..c733ffbe44 100644 --- a/go.mod +++ b/go.mod @@ -48,7 +48,7 @@ require ( github.com/lib/pq v1.10.6 github.com/minio/minio-go/v7 v7.0.45 github.com/mwitkow/go-proto-validators v0.3.2 - github.com/percona-platform/dbaas-api v0.0.0-20221019084503-3649d46509df + github.com/percona-platform/dbaas-api v0.0.0-20221124165531-bd24900964a7 github.com/percona-platform/saas v0.0.0-20221014123257-4fa7a15ce672 github.com/percona/dbaas-operator v0.0.4 github.com/percona/exporter_shared v0.7.3 diff --git a/go.sum b/go.sum index 64ed66d11b..6c4ff23021 100644 --- a/go.sum +++ b/go.sum @@ -675,8 +675,8 @@ github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAv github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/percona-lab/crypto v0.0.0-20220811043533-d164de3c7f08 h1:NprWeXddFZJSgtN8hmf/hhIgiZwB3GNaKnI88iAFgEc= github.com/percona-lab/crypto v0.0.0-20220811043533-d164de3c7f08/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -github.com/percona-platform/dbaas-api v0.0.0-20221019084503-3649d46509df h1:CodeejNzVTI7j8sHfYfaxRW0YkMif66FS0x6RK4RGcc= -github.com/percona-platform/dbaas-api v0.0.0-20221019084503-3649d46509df/go.mod h1:/jgle33awfHq1va/T6NnNS5wWAETSnl6wUZ1bew+CJ0= +github.com/percona-platform/dbaas-api v0.0.0-20221124165531-bd24900964a7 h1:3gxQBFdAtRFvqxG24CpWtc5AZoec99ASqCtKfGStbDo= +github.com/percona-platform/dbaas-api v0.0.0-20221124165531-bd24900964a7/go.mod h1:/jgle33awfHq1va/T6NnNS5wWAETSnl6wUZ1bew+CJ0= github.com/percona-platform/saas v0.0.0-20221014123257-4fa7a15ce672 h1:dwot2L8nFLdnGcvdpK3AdoTykDM1Qr2odQJbq/KrZoM= github.com/percona-platform/saas v0.0.0-20221014123257-4fa7a15ce672/go.mod h1:gFUwaFp6Ugu5qsBwiOVJYbDlzgZ77tmXdXGO7tG5xVI= github.com/percona/dbaas-operator v0.0.4 h1:cFlVdFMiB52sm4gli6WXDynJ7hMa+B9w65LwGAJ53CI= diff --git a/managed/services/dbaas/dbaas_client.go b/managed/services/dbaas/dbaas_client.go index 18c15f0722..5a7365124b 100644 --- a/managed/services/dbaas/dbaas_client.go +++ b/managed/services/dbaas/dbaas_client.go @@ -43,6 +43,7 @@ type Client struct { logsClient controllerv1beta1.LogsAPIClient pxcOperatorClient controllerv1beta1.PXCOperatorAPIClient psmdbOperatorClient controllerv1beta1.PSMDBOperatorAPIClient + olmOperatorClient controllerv1beta1.OLMOperatorAPIClient connM sync.RWMutex conn *grpc.ClientConn dbaasControllerAPIAddress string @@ -87,6 +88,7 @@ func (c *Client) Connect(ctx context.Context) error { c.logsClient = controllerv1beta1.NewLogsAPIClient(conn) c.psmdbOperatorClient = controllerv1beta1.NewPSMDBOperatorAPIClient(conn) c.pxcOperatorClient = controllerv1beta1.NewPXCOperatorAPIClient(conn) + c.olmOperatorClient = controllerv1beta1.NewOLMOperatorAPIClient(conn) c.l.Info("Connected to dbaas-controller API.") return nil @@ -262,3 +264,40 @@ func (c *Client) GetKubeConfig(ctx context.Context, _ *controllerv1beta1.GetKube Kubeconfig: kubeConfig, }, err } + +// InstallOLMOperator installs the OLM operator. +func (c *Client) InstallOLMOperator(ctx context.Context, in *controllerv1beta1.InstallOLMOperatorRequest, opts ...grpc.CallOption) (*controllerv1beta1.InstallOLMOperatorResponse, error) { + c.connM.RLock() + defer c.connM.RUnlock() + return c.olmOperatorClient.InstallOLMOperator(ctx, in, opts...) +} + +func (c *Client) InstallOperator(ctx context.Context, in *controllerv1beta1.InstallOperatorRequest, opts ...grpc.CallOption) (*controllerv1beta1.InstallOperatorResponse, error) { + c.connM.RLock() + defer c.connM.RUnlock() + return c.olmOperatorClient.InstallOperator(ctx, in, opts...) +} + +func (c *Client) ListInstallPlans(ctx context.Context, in *controllerv1beta1.ListInstallPlansRequest, opts ...grpc.CallOption) (*controllerv1beta1.ListInstallPlansResponse, error) { + c.connM.RLock() + defer c.connM.RUnlock() + return c.olmOperatorClient.ListInstallPlans(ctx, in, opts...) +} + +func (c *Client) ApproveInstallPlan(ctx context.Context, in *controllerv1beta1.ApproveInstallPlanRequest, opts ...grpc.CallOption) (*controllerv1beta1.ApproveInstallPlanResponse, error) { + c.connM.RLock() + defer c.connM.RUnlock() + return c.olmOperatorClient.ApproveInstallPlan(ctx, in, opts...) +} + +func (c *Client) ListSubscriptions(ctx context.Context, in *controllerv1beta1.ListSubscriptionsRequest, opts ...grpc.CallOption) (*controllerv1beta1.ListSubscriptionsResponse, error) { + c.connM.RLock() + defer c.connM.RUnlock() + return c.olmOperatorClient.ListSubscriptions(ctx, in, opts...) +} + +func (c *Client) GetSubscription(ctx context.Context, in *controllerv1beta1.GetSubscriptionRequest, opts ...grpc.CallOption) (*controllerv1beta1.GetSubscriptionResponse, error) { + c.connM.RLock() + defer c.connM.RUnlock() + return c.olmOperatorClient.GetSubscription(ctx, in, opts...) +} diff --git a/managed/services/management/dbaas/components_service.go b/managed/services/management/dbaas/components_service.go index c35a3b9a1e..4ca115951d 100644 --- a/managed/services/management/dbaas/components_service.go +++ b/managed/services/management/dbaas/components_service.go @@ -18,10 +18,11 @@ package dbaas import ( "context" "fmt" + "regexp" "sync" goversion "github.com/hashicorp/go-version" - controllerv1beta1 "github.com/percona-platform/dbaas-api/gen/controller" + dbaascontrollerv1beta1 "github.com/percona-platform/dbaas-api/gen/controller" "github.com/pkg/errors" "github.com/sirupsen/logrus" "google.golang.org/grpc/codes" @@ -34,6 +35,12 @@ import ( pmmversion "github.com/percona/pmm/version" ) +const ( + psmdbOperatorName = "percona-server-mongodb-operator" + pxcOperatorName = "percona-xtradb-cluster-operator" + defaultNamespace = "default" +) + type ComponentsService struct { l *logrus.Entry db *reform.DB @@ -239,56 +246,46 @@ func (c ComponentsService) CheckForOperatorUpdate(ctx context.Context, _ *dbaasv close(responseCh) }() - pmmVersion, err := goversion.NewVersion(pmmversion.PMMVersion) - if err != nil { - return nil, status.Error(codes.Internal, err.Error()) - } resp := &dbaasv1beta1.CheckForOperatorUpdateResponse{ ClusterToComponents: make(map[string]*dbaasv1beta1.ComponentsUpdateInformation), } - latestPXCOperatorVersion, latestPSMDBOperatorVersion, err := c.versionServiceClient.LatestOperatorVersion(ctx, pmmVersion.Core().String()) - if err != nil { - return nil, status.Error(codes.Internal, err.Error()) - } - - // Some of the requests to kuberenetes clusters for getting operators versions should be done. - // Go through them and decide what operator needs update. - for operatorsVersion := range responseCh { - // Get next operators version, don't take compatibility into account, we need to go through all versions. - nextPXCOperatorVersion, err := c.versionServiceClient.NextOperatorVersion(ctx, pxcOperator, operatorsVersion.pxcOperatorVersion) - if err != nil { - return nil, status.Error(codes.Internal, err.Error()) - } - nextPSMDBOperatorVersion, err := c.versionServiceClient.NextOperatorVersion(ctx, psmdbOperator, operatorsVersion.psmdbOperatorVersion) + for _, cluster := range clusters { + subscriptions, err := c.dbaasClient.ListSubscriptions(ctx, &dbaascontrollerv1beta1.ListSubscriptionsRequest{ + KubeAuth: &dbaascontrollerv1beta1.KubeAuth{ + Kubeconfig: cluster.KubeConfig, + }, + }) if err != nil { - return nil, status.Error(codes.Internal, err.Error()) + continue } - - resp.ClusterToComponents[operatorsVersion.kuberentesClusterName] = &dbaasv1beta1.ComponentsUpdateInformation{ - ComponentToUpdateInformation: make(map[string]*dbaasv1beta1.ComponentUpdateInformation), + resp.ClusterToComponents[cluster.KubernetesClusterName] = &dbaasv1beta1.ComponentsUpdateInformation{ + ComponentToUpdateInformation: map[string]*dbaasv1beta1.ComponentUpdateInformation{ + psmdbOperator: {}, + pxcOperator: {}, + }, } - // Don't offer upgrade for the version that is not compatible and is not on the way to the latest version! - if latestPXCOperatorVersion != nil && nextPXCOperatorVersion != nil && nextPXCOperatorVersion.LessThanOrEqual(latestPXCOperatorVersion) { - resp.ClusterToComponents[operatorsVersion.kuberentesClusterName].ComponentToUpdateInformation[pxcOperator] = &dbaasv1beta1.ComponentUpdateInformation{ - AvailableVersion: nextPXCOperatorVersion.String(), - } - } else { - resp.ClusterToComponents[operatorsVersion.kuberentesClusterName].ComponentToUpdateInformation[pxcOperator] = &dbaasv1beta1.ComponentUpdateInformation{ - AvailableVersion: "", - } - } - if latestPSMDBOperatorVersion != nil && nextPSMDBOperatorVersion != nil && nextPSMDBOperatorVersion.LessThanOrEqual(latestPSMDBOperatorVersion) { - resp.ClusterToComponents[operatorsVersion.kuberentesClusterName].ComponentToUpdateInformation[psmdbOperator] = &dbaasv1beta1.ComponentUpdateInformation{ - AvailableVersion: nextPSMDBOperatorVersion.String(), - } - } else { - resp.ClusterToComponents[operatorsVersion.kuberentesClusterName].ComponentToUpdateInformation[psmdbOperator] = &dbaasv1beta1.ComponentUpdateInformation{ - AvailableVersion: "", + for _, item := range subscriptions.Items { + if item.CurrentCsv != item.InstalledCsv { + re := regexp.MustCompile(`v(\d+\.\d+\.\d+)$`) + matches := re.FindStringSubmatch(item.CurrentCsv) + if len(matches) == 2 { + switch item.Package { + case psmdbOperatorName: + resp.ClusterToComponents[cluster.KubernetesClusterName].ComponentToUpdateInformation[psmdbOperator] = &dbaasv1beta1.ComponentUpdateInformation{ + AvailableVersion: matches[1], + } + case pxcOperatorName: + resp.ClusterToComponents[cluster.KubernetesClusterName].ComponentToUpdateInformation[pxcOperator] = &dbaasv1beta1.ComponentUpdateInformation{ + AvailableVersion: matches[1], + } + } + } } } } + return resp, nil } @@ -409,30 +406,27 @@ func (c ComponentsService) InstallOperator(ctx context.Context, req *dbaasv1beta if err != nil { return nil, status.Error(codes.Internal, err.Error()) } - var component *models.Component var installFunc func() error switch req.OperatorType { case pxcOperator: installFunc = func() error { - _, err := c.dbaasClient.InstallPXCOperator(ctx, &controllerv1beta1.InstallPXCOperatorRequest{ - KubeAuth: &controllerv1beta1.KubeAuth{ - Kubeconfig: kubernetesCluster.KubeConfig, - }, - Version: req.Version, - }) - return err + installPlanName, err := getInstallPlanForSubscription(ctx, c.dbaasClient, kubernetesCluster.KubeConfig, defaultNamespace, pxcOperatorName) + if err != nil { + return errors.Wrapf(err, "cannot get install plan for subscription %q", pxcOperatorName) + } + + return approveInstallPlan(ctx, c.dbaasClient, kubernetesCluster.KubeConfig, "default", installPlanName) } component = kubernetesCluster.PXC case psmdbOperator: installFunc = func() error { - _, err := c.dbaasClient.InstallPSMDBOperator(ctx, &controllerv1beta1.InstallPSMDBOperatorRequest{ - KubeAuth: &controllerv1beta1.KubeAuth{ - Kubeconfig: kubernetesCluster.KubeConfig, - }, - Version: req.Version, - }) - return err + installPlanName, err := getInstallPlanForSubscription(ctx, c.dbaasClient, kubernetesCluster.KubeConfig, defaultNamespace, psmdbOperatorName) + if err != nil { + return errors.Wrapf(err, "cannot get install plan for subscription %q", psmdbOperatorName) + } + + return approveInstallPlan(ctx, c.dbaasClient, kubernetesCluster.KubeConfig, "default", installPlanName) } component = kubernetesCluster.Mongod default: diff --git a/managed/services/management/dbaas/components_service_test.go b/managed/services/management/dbaas/components_service_test.go index 1293d44dcf..7d2466972e 100644 --- a/managed/services/management/dbaas/components_service_test.go +++ b/managed/services/management/dbaas/components_service_test.go @@ -601,8 +601,13 @@ func TestInstallOperator(t *testing.T) { } db, c, dbaasClient := setup(t, clusterName, response, port, defaultPXCVersion, defaultPSMDBVersion) - dbaasClient.On("InstallPXCOperator", mock.Anything, mock.Anything).Return(&controllerv1beta1.InstallPXCOperatorResponse{}, nil) - dbaasClient.On("InstallPSMDBOperator", mock.Anything, mock.Anything).Return(&controllerv1beta1.InstallPSMDBOperatorResponse{}, nil) + mockGetSubscriptionResponse := &controllerv1beta1.GetSubscriptionResponse{ + Subscription: &controllerv1beta1.Subscription{ + InstallPlanName: "mocked-install-plan", + }, + } + dbaasClient.On("GetSubscription", mock.Anything, mock.Anything).Return(mockGetSubscriptionResponse, nil) + dbaasClient.On("ApproveInstallPlan", mock.Anything, mock.Anything).Return(&controllerv1beta1.ApproveInstallPlanResponse{}, nil) ctx, cancel := context.WithTimeout(context.TODO(), time.Second*5) defer cancel() @@ -654,7 +659,6 @@ func TestInstallOperator(t *testing.T) { } func TestCheckForOperatorUpdate(t *testing.T) { - t.Parallel() response := &VersionServiceResponse{ Versions: []Version{ { @@ -705,13 +709,38 @@ func TestCheckForOperatorUpdate(t *testing.T) { t.Run("Update available", func(t *testing.T) { clusterName := "update-available" _, cs, dbaasClient := setup(t, clusterName, response, "9873", defaultPXCVersion, defaultPSMDBVersion) - dbaasClient.On("CheckKubernetesClusterConnection", ctx, "{}").Return(&controllerv1beta1.CheckKubernetesClusterConnectionResponse{ + dbaasClient.On("CheckKubernetesClusterConnection", mock.Anything, mock.Anything).Return(&controllerv1beta1.CheckKubernetesClusterConnectionResponse{ Operators: &controllerv1beta1.Operators{ PsmdbOperatorVersion: onePointSeven, PxcOperatorVersion: onePointSeven, + OlmOperatorVersion: onePointSeven, }, }, nil) + mockSubscriptions := &controllerv1beta1.ListSubscriptionsResponse{ + Items: []*controllerv1beta1.Subscription{ + { + Namespace: "space-x", + Name: "psmdb-operator", + Package: "percona-server-mongodb-operator", + Source: "src", + Channel: "nat-geo", + CurrentCsv: "percona-server-mongodb-operator-v1.8.0", + InstalledCsv: "percona-server-mongodb-operator-v1.2.2", + }, + { + Namespace: "space-x", + Name: "pxc-operator", + Package: "percona-xtradb-cluster-operator", + Source: "src", + Channel: "nat-geo", + CurrentCsv: "percona-xtradb-cluster-operator-v1.8.0", + InstalledCsv: "percona-xtradb-cluster-operator-v1.2.2", + }, + }, + } + dbaasClient.On("ListSubscriptions", mock.Anything, mock.Anything).WaitUntil(time.After(time.Second)).Return(mockSubscriptions, nil) + resp, err := cs.CheckForOperatorUpdate(ctx, &dbaasv1beta1.CheckForOperatorUpdateRequest{}) require.NoError(t, err) cluster := resp.ClusterToComponents[clusterName] @@ -732,6 +761,7 @@ func TestCheckForOperatorUpdate(t *testing.T) { }, }, nil) + dbaasClient.On("ListSubscriptions", mock.Anything, mock.Anything).WaitUntil(time.After(time.Second)).Return(&controllerv1beta1.ListSubscriptionsResponse{}, nil) resp, err := cs.CheckForOperatorUpdate(ctx, &dbaasv1beta1.CheckForOperatorUpdateRequest{}) require.NoError(t, err) cluster := resp.ClusterToComponents[clusterName] @@ -742,16 +772,22 @@ func TestCheckForOperatorUpdate(t *testing.T) { assert.Equal(t, "", cluster.ComponentToUpdateInformation[psmdbOperator].AvailableVersion) assert.Equal(t, "", cluster.ComponentToUpdateInformation[pxcOperator].AvailableVersion) }) + t.Run("User's operators version is ahead of version service", func(t *testing.T) { clusterName := "update-available-pmm-update" _, cs, dbaasClient := setup(t, clusterName, response, "5863", defaultPXCVersion, defaultPSMDBVersion) - dbaasClient.On("CheckKubernetesClusterConnection", ctx, "{}").Return(&controllerv1beta1.CheckKubernetesClusterConnectionResponse{ + dbaasClient.On("CheckKubernetesClusterConnection", mock.Anything, "{}").Return(&controllerv1beta1.CheckKubernetesClusterConnectionResponse{ Operators: &controllerv1beta1.Operators{ PsmdbOperatorVersion: onePointNine, PxcOperatorVersion: onePointNine, }, }, nil) + mockSubscriptions := &controllerv1beta1.ListSubscriptionsResponse{ + Items: []*controllerv1beta1.Subscription{}, + } + dbaasClient.On("ListSubscriptions", mock.Anything, mock.Anything).WaitUntil(time.After(time.Second)).Return(mockSubscriptions, nil) + resp, err := cs.CheckForOperatorUpdate(ctx, &dbaasv1beta1.CheckForOperatorUpdateRequest{}) require.NoError(t, err) cluster := resp.ClusterToComponents[clusterName] diff --git a/managed/services/management/dbaas/db_cluster_service_test.go b/managed/services/management/dbaas/db_cluster_service_test.go index c6bee03c98..1e6bd2e0d0 100644 --- a/managed/services/management/dbaas/db_cluster_service_test.go +++ b/managed/services/management/dbaas/db_cluster_service_test.go @@ -103,10 +103,15 @@ func TestDBClusterService(t *testing.T) { }, Status: controllerv1beta1.KubernetesClusterStatus_KUBERNETES_CLUSTER_STATUS_OK, }, nil) - - dbaasClient.On("InstallPXCOperator", mock.Anything, mock.Anything).Return(&controllerv1beta1.InstallPXCOperatorResponse{}, nil) - dbaasClient.On("InstallPSMDBOperator", mock.Anything, mock.Anything).Return(&controllerv1beta1.InstallPSMDBOperatorResponse{}, nil) - + dbaasClient.On("InstallOLMOperator", mock.Anything, mock.Anything).Return(&controllerv1beta1.InstallOLMOperatorResponse{}, nil) + dbaasClient.On("InstallOperator", mock.Anything, mock.Anything).Return(&controllerv1beta1.InstallOperatorResponse{}, nil) + mockGetSubscriptionResponse := &controllerv1beta1.GetSubscriptionResponse{ + Subscription: &controllerv1beta1.Subscription{ + InstallPlanName: "mocked-install-plan", + }, + } + dbaasClient.On("GetSubscription", mock.Anything, mock.Anything).Return(mockGetSubscriptionResponse, nil) + dbaasClient.On("ApproveInstallPlan", mock.Anything, mock.Anything).Return(&controllerv1beta1.ApproveInstallPlanResponse{}, nil) registerKubernetesClusterResponse, err := ks.RegisterKubernetesCluster(ctx, &dbaasv1beta1.RegisterKubernetesClusterRequest{ KubernetesClusterName: dbKubernetesClusterNameTest, KubeAuth: &dbaasv1beta1.KubeAuth{Kubeconfig: dbKubeconfigTest}, diff --git a/managed/services/management/dbaas/deps.go b/managed/services/management/dbaas/deps.go index d48637b2b1..259919828f 100644 --- a/managed/services/management/dbaas/deps.go +++ b/managed/services/management/dbaas/deps.go @@ -68,6 +68,10 @@ type dbaasClient interface { GetLogs(ctx context.Context, in *controllerv1beta1.GetLogsRequest, opts ...grpc.CallOption) (*controllerv1beta1.GetLogsResponse, error) // GetResources returns all and available resources of a Kubernetes cluster. GetResources(ctx context.Context, in *controllerv1beta1.GetResourcesRequest, opts ...grpc.CallOption) (*controllerv1beta1.GetResourcesResponse, error) + // InstallOLMOperator installs the OLM operator. + InstallOLMOperator(ctx context.Context, in *controllerv1beta1.InstallOLMOperatorRequest, opts ...grpc.CallOption) (*controllerv1beta1.InstallOLMOperatorResponse, error) + // InstallOperator installs an operator via OLM. + InstallOperator(ctx context.Context, in *controllerv1beta1.InstallOperatorRequest, opts ...grpc.CallOption) (*controllerv1beta1.InstallOperatorResponse, error) // InstallPXCOperator installs kubernetes pxc operator. InstallPXCOperator(ctx context.Context, in *controllerv1beta1.InstallPXCOperatorRequest, opts ...grpc.CallOption) (*controllerv1beta1.InstallPXCOperatorResponse, error) // InstallPSMDBOperator installs kubernetes psmdb operator. @@ -78,6 +82,15 @@ type dbaasClient interface { StopMonitoring(ctx context.Context, in *controllerv1beta1.StopMonitoringRequest, opts ...grpc.CallOption) (*controllerv1beta1.StopMonitoringResponse, error) // GetKubeConfig gets inluster config and converts it to kubeConfig GetKubeConfig(ctx context.Context, in *controllerv1beta1.GetKubeconfigRequest, opts ...grpc.CallOption) (*controllerv1beta1.GetKubeconfigResponse, error) + // ListInstallPlans list all available install plans. + ListInstallPlans(ctx context.Context, in *controllerv1beta1.ListInstallPlansRequest, opts ...grpc.CallOption) (*controllerv1beta1.ListInstallPlansResponse, error) + // ApproveInstallPlan approves an install plan. + ApproveInstallPlan(ctx context.Context, in *controllerv1beta1.ApproveInstallPlanRequest, opts ...grpc.CallOption) (*controllerv1beta1.ApproveInstallPlanResponse, error) + // ListSubscriptions list all available subscriptions. Used to check if there are updates. If installed crv is different than current csv (latest) + // there is an update available. + ListSubscriptions(ctx context.Context, in *controllerv1beta1.ListSubscriptionsRequest, opts ...grpc.CallOption) (*controllerv1beta1.ListSubscriptionsResponse, error) + // GetSubscription retrieves a subscription by namespace and name. + GetSubscription(ctx context.Context, in *controllerv1beta1.GetSubscriptionRequest, opts ...grpc.CallOption) (*controllerv1beta1.GetSubscriptionResponse, error) } type versionService interface { diff --git a/managed/services/management/dbaas/kubernetes_server.go b/managed/services/management/dbaas/kubernetes_server.go index ef40418383..d03a8a68c9 100644 --- a/managed/services/management/dbaas/kubernetes_server.go +++ b/managed/services/management/dbaas/kubernetes_server.go @@ -22,8 +22,10 @@ import ( "regexp" "strings" "sync" + "time" goversion "github.com/hashicorp/go-version" + controllerv1beta1 "github.com/percona-platform/dbaas-api/gen/controller" dbaascontrollerv1beta1 "github.com/percona-platform/dbaas-api/gen/controller" "github.com/percona/promconfig" "github.com/pkg/errors" @@ -43,6 +45,7 @@ var ( resourceDoesntExistsRegexp = regexp.MustCompile(`the server doesn't have a resource type "(PerconaXtraDBCluster|PerconaServerMongoDB)"`) errKubeconfigIsEmpty = errors.New("kubeconfig is empty") errMissingRequiredKubeconfigEnvVar = errors.New("required environment variable is not defined in kubeconfig") + errNoInstallPlanToApprove = errors.New("there are no install plans to approve") flagClusterName = "--cluster-name" flagRegion = "--region" @@ -261,6 +264,34 @@ func replaceAWSAuthIfPresent(kubeconfig string, keyID, key string) (string, erro return string(c), err } +func installOLMOperator(ctx context.Context, client dbaasClient, kubeconfig, version string) error { + installOLMOperatorReq := &dbaascontrollerv1beta1.InstallOLMOperatorRequest{ + KubeAuth: &dbaascontrollerv1beta1.KubeAuth{ + Kubeconfig: kubeconfig, + }, + Version: version, + } + + if _, err := client.InstallOLMOperator(ctx, installOLMOperatorReq); err != nil { + return errors.Wrap(err, "cannot install OLM operator") + } + + return nil +} + +func approveInstallPlan(ctx context.Context, client dbaasClient, kubeConfig, namespace, name string) error { + req := &dbaascontrollerv1beta1.ApproveInstallPlanRequest{ + KubeAuth: &dbaascontrollerv1beta1.KubeAuth{ + Kubeconfig: kubeConfig, + }, + Name: name, + Namespace: namespace, + } + _, err := client.ApproveInstallPlan(ctx, req) + + return err +} + // RegisterKubernetesCluster registers an existing Kubernetes cluster in PMM. func (k kubernetesServer) RegisterKubernetesCluster(ctx context.Context, req *dbaasv1beta1.RegisterKubernetesClusterRequest) (*dbaasv1beta1.RegisterKubernetesClusterResponse, error) { //nolint:lll var err error @@ -274,6 +305,7 @@ func (k kubernetesServer) RegisterKubernetesCluster(ctx context.Context, req *db k.l.Errorf("Replacing `aws` with `aim-authenticator` failed: %s", err) return nil, status.Error(codes.Internal, "Internal server error") } + var clusterInfo *dbaascontrollerv1beta1.CheckKubernetesClusterConnectionResponse err = k.db.InTransaction(func(t *reform.TX) error { var e error @@ -291,6 +323,7 @@ func (k kubernetesServer) RegisterKubernetesCluster(ctx context.Context, req *db if err != nil { return nil, err } + pmmVersion, err := goversion.NewVersion(pmmversion.PMMVersion) if err != nil { return nil, status.Error(codes.Internal, err.Error()) @@ -300,64 +333,160 @@ func (k kubernetesServer) RegisterKubernetesCluster(ctx context.Context, req *db if err != nil { return nil, err } - if pxcOperatorVersion != nil && (clusterInfo.Operators == nil || clusterInfo.Operators.PxcOperatorVersion == "") { - _, err = k.dbaasClient.InstallPXCOperator(ctx, &dbaascontrollerv1beta1.InstallPXCOperatorRequest{ - KubeAuth: &dbaascontrollerv1beta1.KubeAuth{ - Kubeconfig: req.KubeAuth.Kubeconfig, - }, - Version: pxcOperatorVersion.String(), - }) - if err != nil { - return nil, err + + go func() { + ctx := context.TODO() + + if clusterInfo.Operators == nil || clusterInfo.Operators.OlmOperatorVersion == "" { + _, err = k.dbaasClient.InstallOLMOperator(ctx, &dbaascontrollerv1beta1.InstallOLMOperatorRequest{ + KubeAuth: &dbaascontrollerv1beta1.KubeAuth{ + Kubeconfig: req.KubeAuth.Kubeconfig, + }, + Version: "", // Use dbaas-controller default. + }) + if err != nil { + k.l.Errorf("cannot install OLM operator to register the Kubernetes cluster: %s", err) + } } - } - if psmdbOperatorVersion != nil && (clusterInfo.Operators == nil || clusterInfo.Operators.PsmdbOperatorVersion == "") { - _, err = k.dbaasClient.InstallPSMDBOperator(ctx, &dbaascontrollerv1beta1.InstallPSMDBOperatorRequest{ - KubeAuth: &dbaascontrollerv1beta1.KubeAuth{ - Kubeconfig: req.KubeAuth.Kubeconfig, - }, - Version: psmdbOperatorVersion.String(), - }) - if err != nil { - return nil, err + + namespace := "default" + + if pxcOperatorVersion != nil && (clusterInfo.Operators == nil || clusterInfo.Operators.PxcOperatorVersion == "") { + operator := "percona-xtradb-cluster-operator" + + if err := k.installOperator(ctx, operator, namespace, "", "stable", req.KubeAuth.Kubeconfig); err != nil { + k.l.Errorf("cannot instal PXC operator in the new cluster: %s", err) + } + + installPlanName, err := getInstallPlanForSubscription(ctx, k.dbaasClient, req.KubeAuth.Kubeconfig, namespace, operator) + if err != nil { + k.l.Errorf("cannot get install plan for subscription %q: %s", operator, err) + } + + if err := approveInstallPlan(ctx, k.dbaasClient, req.KubeAuth.Kubeconfig, namespace, installPlanName); err != nil { + k.l.Errorf("cannot approve the PXC install plan: %s", err) + } } - } - settings, err := models.GetSettings(k.db.Querier) - if err != nil { - return nil, err - } - if settings.PMMPublicAddress != "" { - var apiKeyID int64 - var apiKey string - apiKeyName := fmt.Sprintf("pmm-vmagent-%s-%d", req.KubernetesClusterName, rand.Int63()) - apiKeyID, apiKey, err = k.grafanaClient.CreateAdminAPIKey(ctx, apiKeyName) + if psmdbOperatorVersion != nil && (clusterInfo.Operators == nil || clusterInfo.Operators.PsmdbOperatorVersion == "") { + operator := "percona-server-mongodb-operator" + + if err := k.installOperator(ctx, operator, namespace, "percona-server-mongodb-operator.v1.11.0", "stable", req.KubeAuth.Kubeconfig); err != nil { + k.l.Errorf("cannot install PSMDB operator in the new cluster: %s", err) + } + + installPlanName, err := getInstallPlanForSubscription(ctx, k.dbaasClient, req.KubeAuth.Kubeconfig, namespace, operator) + if err != nil { + k.l.Errorf("cannot get install plan for subscription %q: %s", operator, err) + } + + if err := approveInstallPlan(ctx, k.dbaasClient, req.KubeAuth.Kubeconfig, namespace, installPlanName); err != nil { + k.l.Errorf("cannot approve the PSMDB install plan: %s", err) + } + } + + if clusterInfo.Operators == nil || clusterInfo.Operators.OlmOperatorVersion == "" { + operator := "victoriametrics-operator" + + if err := k.installOperator(ctx, operator, namespace, "", "beta", req.KubeAuth.Kubeconfig); err != nil { + k.l.Errorf("cannot install victoria metrics operator: %s", err) + return + } + + installPlanName, err := getInstallPlanForSubscription(ctx, k.dbaasClient, req.KubeAuth.Kubeconfig, namespace, operator) + if err != nil { + k.l.Errorf("cannot get install plan for subscription %q: %s", operator, err) + } + + if err := approveInstallPlan(ctx, k.dbaasClient, req.KubeAuth.Kubeconfig, namespace, installPlanName); err != nil { + k.l.Errorf("cannot approve the PSMDB install plan: %s", err) + } + } + + settings, err := models.GetSettings(k.db.Querier) if err != nil { - return nil, err + k.l.Errorf("cannot get PMM settings to start Victoria Metrics: %s", err) + return } - pmmParams := &dbaascontrollerv1beta1.PMMParams{ - PublicAddress: fmt.Sprintf("https://%s", settings.PMMPublicAddress), - Login: "api_key", - Password: apiKey, + if settings.PMMPublicAddress != "" { + var apiKeyID int64 + var apiKey string + apiKeyName := fmt.Sprintf("pmm-vmagent-%s-%d", req.KubernetesClusterName, rand.Int63()) + apiKeyID, apiKey, err = k.grafanaClient.CreateAdminAPIKey(ctx, apiKeyName) + if err != nil { + k.l.Errorf("cannot create Grafana admin API key: %s", err) + return + } + pmmParams := &dbaascontrollerv1beta1.PMMParams{ + PublicAddress: fmt.Sprintf("https://%s", settings.PMMPublicAddress), + Login: "api_key", + Password: apiKey, + } + + _, err := k.dbaasClient.StartMonitoring(ctx, &dbaascontrollerv1beta1.StartMonitoringRequest{ + KubeAuth: &dbaascontrollerv1beta1.KubeAuth{ + Kubeconfig: req.KubeAuth.Kubeconfig, + }, + Pmm: pmmParams, + }) + if err != nil { + e := k.grafanaClient.DeleteAPIKeyByID(ctx, apiKeyID) + if e != nil { + k.l.Warnf("couldn't delete created API Key %v: %s", apiKeyID, e) + } + k.l.Errorf("couldn't start monitoring of the kubernetes cluster: %s", err) + return + } } + }() - _, err := k.dbaasClient.StartMonitoring(ctx, &dbaascontrollerv1beta1.StartMonitoringRequest{ + return &dbaasv1beta1.RegisterKubernetesClusterResponse{}, nil +} + +func (k kubernetesServer) installOperator(ctx context.Context, name, namespace, startingCSV, channel, kubeConfig string) error { + catalosSourceNamespace := "olm" + catalogSource := "operatorhubio-catalog" + + _, err := k.dbaasClient.InstallOperator(ctx, &dbaascontrollerv1beta1.InstallOperatorRequest{ + KubeAuth: &dbaascontrollerv1beta1.KubeAuth{ + Kubeconfig: kubeConfig, + }, + Namespace: namespace, + Name: name, + OperatorGroup: "percona-operators-group", + CatalogSource: catalogSource, + CatalogSourceNamespace: catalosSourceNamespace, + Channel: channel, + InstallPlanApproval: "Manual", + StartingCsv: startingCSV, + }) + + return err +} + +func getInstallPlanForSubscription(ctx context.Context, client dbaasClient, kubeConfig, namespace, name string) (string, error) { + var subscription *controllerv1beta1.GetSubscriptionResponse + var err error + for i := 0; i < 6; i++ { + subscription, err = client.GetSubscription(ctx, &dbaascontrollerv1beta1.GetSubscriptionRequest{ KubeAuth: &dbaascontrollerv1beta1.KubeAuth{ - Kubeconfig: req.KubeAuth.Kubeconfig, + Kubeconfig: kubeConfig, }, - Pmm: pmmParams, + Namespace: namespace, + Name: name, }) if err != nil { - e := k.grafanaClient.DeleteAPIKeyByID(ctx, apiKeyID) - if e != nil { - k.l.Warnf("couldn't delete created API Key %v: %s", apiKeyID, e) - } - k.l.Warnf("couldn't start monitoring of the kubernetes cluster: %s", err) - return nil, status.Errorf(codes.Internal, "couldn't start monitoring of the kubernetes cluster: %s", err.Error()) + return "", errors.Wrap(err, "cannot list subscriptions") + } + + if subscription.Subscription.InstallPlanName != "" { + break } + + time.Sleep(5 * time.Second) } - return &dbaasv1beta1.RegisterKubernetesClusterResponse{}, nil + return subscription.Subscription.InstallPlanName, nil } // UnregisterKubernetesCluster removes a registered Kubernetes cluster from PMM. diff --git a/managed/services/management/dbaas/kubernetes_server_test.go b/managed/services/management/dbaas/kubernetes_server_test.go index d5798ae2b8..7bdd37bd6f 100644 --- a/managed/services/management/dbaas/kubernetes_server_test.go +++ b/managed/services/management/dbaas/kubernetes_server_test.go @@ -34,6 +34,7 @@ import ( "github.com/percona/pmm/managed/utils/logger" "github.com/percona/pmm/managed/utils/testdb" "github.com/percona/pmm/managed/utils/tests" + pmmversion "github.com/percona/pmm/version" ) func TestKubernetesServer(t *testing.T) { @@ -57,6 +58,19 @@ func TestKubernetesServer(t *testing.T) { ks = NewKubernetesServer(db, dbaasClient, versionService, grafanaClient) return } + + // This is for local testing. When running local tests, if pmmversion.PMMVersion is empty + // these lines in kubernetes_server.go will throw an error and tests won't finish. + // + // pmmVersion, err := goversion.NewVersion(pmmversion.PMMVersion) + // if err != nil { + // return nil, status.Error(codes.Internal, err.Error()) + // } + // + if pmmversion.PMMVersion == "" { + pmmversion.PMMVersion = "2.30.0" + } + t.Run("Basic", func(t *testing.T) { ctx, ks, dc, teardown := setup(t) defer teardown(t) @@ -73,8 +87,15 @@ func TestKubernetesServer(t *testing.T) { require.NoError(t, err) require.Empty(t, clusters.KubernetesClusters) - dc.On("InstallPXCOperator", mock.Anything, mock.Anything).Return(&controllerv1beta1.InstallPXCOperatorResponse{}, nil) - + dc.On("InstallOLMOperator", mock.Anything, mock.Anything).Return(&controllerv1beta1.InstallOLMOperatorResponse{}, nil) + dc.On("InstallOperator", mock.Anything, mock.Anything).Return(&controllerv1beta1.InstallOperatorResponse{}, nil) + mockGetSubscriptionResponse := &controllerv1beta1.GetSubscriptionResponse{ + Subscription: &controllerv1beta1.Subscription{ + InstallPlanName: "mocked-install-plan", + }, + } + dc.On("GetSubscription", mock.Anything, mock.Anything).Return(mockGetSubscriptionResponse, nil) + dc.On("ApproveInstallPlan", mock.Anything, mock.Anything).Return(&controllerv1beta1.ApproveInstallPlanResponse{}, nil) dc.On("StopMonitoring", mock.Anything, mock.Anything).Return(&controllerv1beta1.StopMonitoringResponse{}, nil) kubernetesClusterName := "test-cluster" @@ -101,7 +122,7 @@ func TestKubernetesServer(t *testing.T) { KubernetesClusterName: kubernetesClusterName, Operators: &dbaasv1beta1.Operators{ Pxc: &dbaasv1beta1.Operator{Status: dbaasv1beta1.OperatorsStatus_OPERATORS_STATUS_NOT_INSTALLED}, - Psmdb: &dbaasv1beta1.Operator{Version: onePointEight, Status: dbaasv1beta1.OperatorsStatus_OPERATORS_STATUS_OK}, + Psmdb: &dbaasv1beta1.Operator{Version: onePointEight, Status: dbaasv1beta1.OperatorsStatus_OPERATORS_STATUS_UNSUPPORTED}, }, Status: dbaasv1beta1.KubernetesClusterStatus_KUBERNETES_CLUSTER_STATUS_OK, }, diff --git a/managed/services/management/dbaas/mock_dbaas_client_test.go b/managed/services/management/dbaas/mock_dbaas_client_test.go index bbda322854..bd07e987c7 100644 --- a/managed/services/management/dbaas/mock_dbaas_client_test.go +++ b/managed/services/management/dbaas/mock_dbaas_client_test.go @@ -15,6 +15,36 @@ type mockDbaasClient struct { mock.Mock } +// ApproveInstallPlan provides a mock function with given fields: ctx, in, opts +func (_m *mockDbaasClient) ApproveInstallPlan(ctx context.Context, in *controllerv1beta1.ApproveInstallPlanRequest, opts ...grpc.CallOption) (*controllerv1beta1.ApproveInstallPlanResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *controllerv1beta1.ApproveInstallPlanResponse + if rf, ok := ret.Get(0).(func(context.Context, *controllerv1beta1.ApproveInstallPlanRequest, ...grpc.CallOption) *controllerv1beta1.ApproveInstallPlanResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*controllerv1beta1.ApproveInstallPlanResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *controllerv1beta1.ApproveInstallPlanRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // CheckKubernetesClusterConnection provides a mock function with given fields: ctx, kubeConfig func (_m *mockDbaasClient) CheckKubernetesClusterConnection(ctx context.Context, kubeConfig string) (*controllerv1beta1.CheckKubernetesClusterConnectionResponse, error) { ret := _m.Called(ctx, kubeConfig) @@ -336,6 +366,96 @@ func (_m *mockDbaasClient) GetResources(ctx context.Context, in *controllerv1bet return r0, r1 } +// GetSubscription provides a mock function with given fields: ctx, in, opts +func (_m *mockDbaasClient) GetSubscription(ctx context.Context, in *controllerv1beta1.GetSubscriptionRequest, opts ...grpc.CallOption) (*controllerv1beta1.GetSubscriptionResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *controllerv1beta1.GetSubscriptionResponse + if rf, ok := ret.Get(0).(func(context.Context, *controllerv1beta1.GetSubscriptionRequest, ...grpc.CallOption) *controllerv1beta1.GetSubscriptionResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*controllerv1beta1.GetSubscriptionResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *controllerv1beta1.GetSubscriptionRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// InstallOLMOperator provides a mock function with given fields: ctx, in, opts +func (_m *mockDbaasClient) InstallOLMOperator(ctx context.Context, in *controllerv1beta1.InstallOLMOperatorRequest, opts ...grpc.CallOption) (*controllerv1beta1.InstallOLMOperatorResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *controllerv1beta1.InstallOLMOperatorResponse + if rf, ok := ret.Get(0).(func(context.Context, *controllerv1beta1.InstallOLMOperatorRequest, ...grpc.CallOption) *controllerv1beta1.InstallOLMOperatorResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*controllerv1beta1.InstallOLMOperatorResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *controllerv1beta1.InstallOLMOperatorRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// InstallOperator provides a mock function with given fields: ctx, in, opts +func (_m *mockDbaasClient) InstallOperator(ctx context.Context, in *controllerv1beta1.InstallOperatorRequest, opts ...grpc.CallOption) (*controllerv1beta1.InstallOperatorResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *controllerv1beta1.InstallOperatorResponse + if rf, ok := ret.Get(0).(func(context.Context, *controllerv1beta1.InstallOperatorRequest, ...grpc.CallOption) *controllerv1beta1.InstallOperatorResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*controllerv1beta1.InstallOperatorResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *controllerv1beta1.InstallOperatorRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // InstallPSMDBOperator provides a mock function with given fields: ctx, in, opts func (_m *mockDbaasClient) InstallPSMDBOperator(ctx context.Context, in *controllerv1beta1.InstallPSMDBOperatorRequest, opts ...grpc.CallOption) (*controllerv1beta1.InstallPSMDBOperatorResponse, error) { _va := make([]interface{}, len(opts)) @@ -396,6 +516,36 @@ func (_m *mockDbaasClient) InstallPXCOperator(ctx context.Context, in *controlle return r0, r1 } +// ListInstallPlans provides a mock function with given fields: ctx, in, opts +func (_m *mockDbaasClient) ListInstallPlans(ctx context.Context, in *controllerv1beta1.ListInstallPlansRequest, opts ...grpc.CallOption) (*controllerv1beta1.ListInstallPlansResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *controllerv1beta1.ListInstallPlansResponse + if rf, ok := ret.Get(0).(func(context.Context, *controllerv1beta1.ListInstallPlansRequest, ...grpc.CallOption) *controllerv1beta1.ListInstallPlansResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*controllerv1beta1.ListInstallPlansResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *controllerv1beta1.ListInstallPlansRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // ListPSMDBClusters provides a mock function with given fields: ctx, in, opts func (_m *mockDbaasClient) ListPSMDBClusters(ctx context.Context, in *controllerv1beta1.ListPSMDBClustersRequest, opts ...grpc.CallOption) (*controllerv1beta1.ListPSMDBClustersResponse, error) { _va := make([]interface{}, len(opts)) @@ -456,6 +606,36 @@ func (_m *mockDbaasClient) ListPXCClusters(ctx context.Context, in *controllerv1 return r0, r1 } +// ListSubscriptions provides a mock function with given fields: ctx, in, opts +func (_m *mockDbaasClient) ListSubscriptions(ctx context.Context, in *controllerv1beta1.ListSubscriptionsRequest, opts ...grpc.CallOption) (*controllerv1beta1.ListSubscriptionsResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *controllerv1beta1.ListSubscriptionsResponse + if rf, ok := ret.Get(0).(func(context.Context, *controllerv1beta1.ListSubscriptionsRequest, ...grpc.CallOption) *controllerv1beta1.ListSubscriptionsResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*controllerv1beta1.ListSubscriptionsResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *controllerv1beta1.ListSubscriptionsRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // RestartPSMDBCluster provides a mock function with given fields: ctx, in, opts func (_m *mockDbaasClient) RestartPSMDBCluster(ctx context.Context, in *controllerv1beta1.RestartPSMDBClusterRequest, opts ...grpc.CallOption) (*controllerv1beta1.RestartPSMDBClusterResponse, error) { _va := make([]interface{}, len(opts)) diff --git a/managed/services/management/dbaas/psmdb_cluster_service_test.go b/managed/services/management/dbaas/psmdb_cluster_service_test.go index ae70e5848c..c5912d5216 100644 --- a/managed/services/management/dbaas/psmdb_cluster_service_test.go +++ b/managed/services/management/dbaas/psmdb_cluster_service_test.go @@ -106,7 +106,15 @@ func TestPSMDBClusterService(t *testing.T) { }, Status: controllerv1beta1.KubernetesClusterStatus_KUBERNETES_CLUSTER_STATUS_OK, }, nil) - dbaasClient.On("InstallPSMDBOperator", mock.Anything, mock.Anything).Return(&controllerv1beta1.InstallPSMDBOperatorResponse{}, nil) + dbaasClient.On("InstallOLMOperator", mock.Anything, mock.Anything).Return(&controllerv1beta1.InstallOLMOperatorResponse{}, nil) + dbaasClient.On("InstallOperator", mock.Anything, mock.Anything).Return(&controllerv1beta1.InstallOperatorResponse{}, nil) + mockGetSubscriptionResponse := &controllerv1beta1.GetSubscriptionResponse{ + Subscription: &controllerv1beta1.Subscription{ + InstallPlanName: "mocked-install-plan", + }, + } + dbaasClient.On("GetSubscription", mock.Anything, mock.Anything).Return(mockGetSubscriptionResponse, nil) + dbaasClient.On("ApproveInstallPlan", mock.Anything, mock.Anything).Return(&controllerv1beta1.ApproveInstallPlanResponse{}, nil) registerKubernetesClusterResponse, err := ks.RegisterKubernetesCluster(ctx, &dbaasv1beta1.RegisterKubernetesClusterRequest{ KubernetesClusterName: psmdbKubernetesClusterNameTest, diff --git a/managed/services/management/dbaas/pxc_cluster_service_test.go b/managed/services/management/dbaas/pxc_cluster_service_test.go index cb1ad0d243..1ed8dd9b6a 100644 --- a/managed/services/management/dbaas/pxc_cluster_service_test.go +++ b/managed/services/management/dbaas/pxc_cluster_service_test.go @@ -105,8 +105,15 @@ func TestPXCClusterService(t *testing.T) { }, Status: controllerv1beta1.KubernetesClusterStatus_KUBERNETES_CLUSTER_STATUS_OK, }, nil) - - dbaasClient.On("InstallPXCOperator", mock.Anything, mock.Anything).Return(&controllerv1beta1.InstallPXCOperatorResponse{}, nil) + dbaasClient.On("InstallOLMOperator", mock.Anything, mock.Anything).Return(&controllerv1beta1.InstallOLMOperatorResponse{}, nil) + dbaasClient.On("InstallOperator", mock.Anything, mock.Anything).Return(&controllerv1beta1.InstallOperatorResponse{}, nil) + mockGetSubscriptionResponse := &controllerv1beta1.GetSubscriptionResponse{ + Subscription: &controllerv1beta1.Subscription{ + InstallPlanName: "mocked-install-plan", + }, + } + dbaasClient.On("GetSubscription", mock.Anything, mock.Anything).Return(mockGetSubscriptionResponse, nil) + dbaasClient.On("ApproveInstallPlan", mock.Anything, mock.Anything).Return(&controllerv1beta1.ApproveInstallPlanResponse{}, nil) registerKubernetesClusterResponse, err := ks.RegisterKubernetesCluster(ctx, &dbaasv1beta1.RegisterKubernetesClusterRequest{ KubernetesClusterName: pxcKubernetesClusterNameTest, diff --git a/managed/services/supervisord/logs_test.go b/managed/services/supervisord/logs_test.go index 6f0c96493b..e7a6b9389c 100644 --- a/managed/services/supervisord/logs_test.go +++ b/managed/services/supervisord/logs_test.go @@ -140,6 +140,10 @@ func TestFiles(t *testing.T) { continue } + if f.Name == "dbaas-controller.log" { + continue + } + assert.NoError(t, f.Err, "name = %q", f.Name) actual = append(actual, f.Name) @@ -170,7 +174,9 @@ func TestZip(t *testing.T) { "systemctl_status.log", "prometheus.base.yml", } - + if os.Getenv("ENABLE_DBAAS") == "1" { + additionalFiles = append(additionalFiles, "dbaas-controller.log") + } // zip file includes client files expected := append(commonExpectedFiles, additionalFiles...) diff --git a/managed/utils/tests/fuzz.go b/managed/utils/tests/fuzz.go index 91dfc26fbf..c1a93b5aad 100644 --- a/managed/utils/tests/fuzz.go +++ b/managed/utils/tests/fuzz.go @@ -16,7 +16,6 @@ package tests import ( - // go-fuzz uses SHA1 for non-cryptographic hashing "crypto/sha1" //nolint:gosec "fmt" "os"