Skip to content

Commit

Permalink
PMM-10705 Use OLM to install / upgrade operators (#1391)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
  • Loading branch information
percona-csalguero and solovevayaroslavna authored Dec 14, 2022
1 parent 226c625 commit 41e65bc
Show file tree
Hide file tree
Showing 14 changed files with 556 additions and 119 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -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=
Expand Down
39 changes: 39 additions & 0 deletions managed/services/dbaas/dbaas_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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...)
}
104 changes: 49 additions & 55 deletions managed/services/management/dbaas/components_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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
Expand Down Expand Up @@ -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
}

Expand Down Expand Up @@ -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:
Expand Down
46 changes: 41 additions & 5 deletions managed/services/management/dbaas/components_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -654,7 +659,6 @@ func TestInstallOperator(t *testing.T) {
}

func TestCheckForOperatorUpdate(t *testing.T) {
t.Parallel()
response := &VersionServiceResponse{
Versions: []Version{
{
Expand Down Expand Up @@ -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]
Expand All @@ -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]
Expand All @@ -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]
Expand Down
13 changes: 9 additions & 4 deletions managed/services/management/dbaas/db_cluster_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down
13 changes: 13 additions & 0 deletions managed/services/management/dbaas/deps.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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 {
Expand Down
Loading

0 comments on commit 41e65bc

Please sign in to comment.