diff --git a/pkg/registry/apis/provisioning/controller/finalizers.go b/pkg/registry/apis/provisioning/controller/finalizers.go index a3eb35376fb..f4037326480 100644 --- a/pkg/registry/apis/provisioning/controller/finalizers.go +++ b/pkg/registry/apis/provisioning/controller/finalizers.go @@ -107,7 +107,7 @@ func (f *finalizer) processExistingItems( errors := 0 for _, item := range items.Items { - res, _, err := clients.ForResource(schema.GroupVersionResource{ + res, _, err := clients.ForResource(ctx, schema.GroupVersionResource{ Group: item.Group, Resource: item.Resource, }) diff --git a/pkg/registry/apis/provisioning/files.go b/pkg/registry/apis/provisioning/files.go index c22dca8512e..0360113f76b 100644 --- a/pkg/registry/apis/provisioning/files.go +++ b/pkg/registry/apis/provisioning/files.go @@ -99,7 +99,7 @@ func (c *filesConnector) Connect(ctx context.Context, name string, opts runtime. return } - folderClient, err := clients.Folder() + folderClient, err := clients.Folder(ctx) if err != nil { responder.Error(fmt.Errorf("failed to get folder client: %w", err)) return diff --git a/pkg/registry/apis/provisioning/jobs/export/all.go b/pkg/registry/apis/provisioning/jobs/export/all.go index c2cb0f85eb5..e3afdd1b036 100644 --- a/pkg/registry/apis/provisioning/jobs/export/all.go +++ b/pkg/registry/apis/provisioning/jobs/export/all.go @@ -11,7 +11,7 @@ import ( func ExportAll(ctx context.Context, repoName string, options provisioning.ExportJobOptions, clients resources.ResourceClients, repositoryResources resources.RepositoryResources, progress jobs.JobProgressRecorder) error { // FIXME: should we sign with grafana user? - folderClient, err := clients.Folder() + folderClient, err := clients.Folder(ctx) if err != nil { return err } diff --git a/pkg/registry/apis/provisioning/jobs/export/resources.go b/pkg/registry/apis/provisioning/jobs/export/resources.go index 8c3993a462c..c07a871815a 100644 --- a/pkg/registry/apis/provisioning/jobs/export/resources.go +++ b/pkg/registry/apis/provisioning/jobs/export/resources.go @@ -31,7 +31,7 @@ func ExportResources(ctx context.Context, options provisioning.ExportJobOptions, } progress.SetMessage(ctx, fmt.Sprintf("export %s", kind.Resource)) - client, _, err := clients.ForResource(kind) + client, _, err := clients.ForResource(ctx, kind) if err != nil { return fmt.Errorf("get client for %s: %w", kind.Resource, err) } @@ -47,7 +47,7 @@ func ExportResources(ctx context.Context, options provisioning.ExportJobOptions, // For v2 we need to request the original version if strings.HasPrefix(storedVersion, "v2alpha1") { if v2clientAlphaV1 == nil { - v2clientAlphaV1, _, err = clients.ForResource(resources.DashboardResourceV2alpha1) + v2clientAlphaV1, _, err = clients.ForResource(ctx, resources.DashboardResourceV2alpha1) if err != nil { return nil, err } @@ -57,7 +57,7 @@ func ExportResources(ctx context.Context, options provisioning.ExportJobOptions, if strings.HasPrefix(storedVersion, "v2beta1") { if v2clientAlphaV2 == nil { - v2clientAlphaV2, _, err = clients.ForResource(resources.DashboardResourceV2beta1) + v2clientAlphaV2, _, err = clients.ForResource(ctx, resources.DashboardResourceV2beta1) if err != nil { return nil, err } diff --git a/pkg/registry/apis/provisioning/jobs/export/resources_test.go b/pkg/registry/apis/provisioning/jobs/export/resources_test.go index 95d8d3540d1..709bdc3affc 100644 --- a/pkg/registry/apis/provisioning/jobs/export/resources_test.go +++ b/pkg/registry/apis/provisioning/jobs/export/resources_test.go @@ -98,7 +98,7 @@ func TestExportResources_Dashboards_Success(t *testing.T) { } setupResources := func(repoResources *resources.MockRepositoryResources, resourceClients *resources.MockResourceClients, mockClient *mockDynamicInterface, gvk schema.GroupVersionKind) { - resourceClients.On("ForResource", resources.DashboardResource).Return(mockClient, gvk, nil) + resourceClients.On("ForResource", mock.Anything, resources.DashboardResource).Return(mockClient, gvk, nil) options := resources.WriteOptions{ Path: "grafana", Ref: "feature/branch", @@ -124,7 +124,7 @@ func TestExportResources_Dashboards_ClientError(t *testing.T) { } setupResources := func(repoResources *resources.MockRepositoryResources, resourceClients *resources.MockResourceClients, mockClient *mockDynamicInterface, gvk schema.GroupVersionKind) { - resourceClients.On("ForResource", resources.DashboardResource).Return(mockClient, gvk, fmt.Errorf("didn't work")) + resourceClients.On("ForResource", mock.Anything, resources.DashboardResource).Return(mockClient, gvk, fmt.Errorf("didn't work")) } err := runExportTest(t, nil, setupProgress, setupResources) @@ -151,7 +151,7 @@ func TestExportResources_Dashboards_WithErrors(t *testing.T) { } setupResources := func(repoResources *resources.MockRepositoryResources, resourceClients *resources.MockResourceClients, mockClient *mockDynamicInterface, gvk schema.GroupVersionKind) { - resourceClients.On("ForResource", resources.DashboardResource).Return(mockClient, gvk, nil) + resourceClients.On("ForResource", mock.Anything, resources.DashboardResource).Return(mockClient, gvk, nil) options := resources.WriteOptions{ Path: "grafana", Ref: "feature/branch", @@ -185,7 +185,7 @@ func TestExportResources_Dashboards_TooManyErrors(t *testing.T) { } setupResources := func(repoResources *resources.MockRepositoryResources, resourceClients *resources.MockResourceClients, mockClient *mockDynamicInterface, gvk schema.GroupVersionKind) { - resourceClients.On("ForResource", resources.DashboardResource).Return(mockClient, gvk, nil) + resourceClients.On("ForResource", mock.Anything, resources.DashboardResource).Return(mockClient, gvk, nil) options := resources.WriteOptions{ Path: "grafana", Ref: "feature/branch", @@ -215,7 +215,7 @@ func TestExportResources_Dashboards_IgnoresExisting(t *testing.T) { } setupResources := func(repoResources *resources.MockRepositoryResources, resourceClients *resources.MockResourceClients, mockClient *mockDynamicInterface, gvk schema.GroupVersionKind) { - resourceClients.On("ForResource", resources.DashboardResource).Return(mockClient, gvk, nil) + resourceClients.On("ForResource", mock.Anything, resources.DashboardResource).Return(mockClient, gvk, nil) options := resources.WriteOptions{ Path: "grafana", Ref: "feature/branch", @@ -262,7 +262,7 @@ func TestExportResources_Dashboards_SavedVersion(t *testing.T) { } setupResources := func(repoResources *resources.MockRepositoryResources, resourceClients *resources.MockResourceClients, mockClient *mockDynamicInterface, gvk schema.GroupVersionKind) { - resourceClients.On("ForResource", resources.DashboardResource).Return(mockClient, gvk, nil) + resourceClients.On("ForResource", mock.Anything, resources.DashboardResource).Return(mockClient, gvk, nil) options := resources.WriteOptions{ Path: "grafana", Ref: "feature/branch", @@ -328,7 +328,7 @@ func TestExportResources_Dashboards_FailedConversionNoStoredVersion(t *testing.T } setupResources := func(repoResources *resources.MockRepositoryResources, resourceClients *resources.MockResourceClients, mockClient *mockDynamicInterface, gvk schema.GroupVersionKind) { - resourceClients.On("ForResource", resources.DashboardResource).Return(mockClient, gvk, nil) + resourceClients.On("ForResource", mock.Anything, resources.DashboardResource).Return(mockClient, gvk, nil) // The value is not saved } @@ -366,12 +366,12 @@ func TestExportResources_Dashboards_V2Alpha1(t *testing.T) { setupResources := func(repoResources *resources.MockRepositoryResources, resourceClients *resources.MockResourceClients, mockClient *mockDynamicInterface, gvk schema.GroupVersionKind) { // Setup v1 client - resourceClients.On("ForResource", resources.DashboardResource).Return(mockClient, gvk, nil) + resourceClients.On("ForResource", mock.Anything, resources.DashboardResource).Return(mockClient, gvk, nil) // Setup v2 client v2Dashboard := createV2DashboardObject("v2-dashboard", "v2alpha1") v2Client := &mockDynamicInterface{items: []unstructured.Unstructured{v2Dashboard}} - resourceClients.On("ForResource", resources.DashboardResourceV2alpha1).Return(v2Client, gvk, nil) + resourceClients.On("ForResource", mock.Anything, resources.DashboardResourceV2alpha1).Return(v2Client, gvk, nil) options := resources.WriteOptions{ Path: "grafana", @@ -427,8 +427,8 @@ func TestExportResources_Dashboards_V2Alpha1_ClientError(t *testing.T) { } setupResources := func(repoResources *resources.MockRepositoryResources, resourceClients *resources.MockResourceClients, mockClient *mockDynamicInterface, gvk schema.GroupVersionKind) { - resourceClients.On("ForResource", resources.DashboardResourceV2alpha1).Return(nil, gvk, fmt.Errorf("v2 client error")) - resourceClients.On("ForResource", resources.DashboardResource).Return(mockClient, gvk, nil) + resourceClients.On("ForResource", mock.Anything, resources.DashboardResourceV2alpha1).Return(nil, gvk, fmt.Errorf("v2 client error")) + resourceClients.On("ForResource", mock.Anything, resources.DashboardResource).Return(mockClient, gvk, nil) } err := runExportTest(t, mockItems, setupProgress, setupResources) @@ -465,12 +465,12 @@ func TestExportResources_Dashboards_V2beta1(t *testing.T) { setupResources := func(repoResources *resources.MockRepositoryResources, resourceClients *resources.MockResourceClients, mockClient *mockDynamicInterface, gvk schema.GroupVersionKind) { // Setup v1 client - resourceClients.On("ForResource", resources.DashboardResource).Return(mockClient, gvk, nil) + resourceClients.On("ForResource", mock.Anything, resources.DashboardResource).Return(mockClient, gvk, nil) // Setup v2 client v2Dashboard := createV2DashboardObject("v2-dashboard", "v2beta1") v2Client := &mockDynamicInterface{items: []unstructured.Unstructured{v2Dashboard}} - resourceClients.On("ForResource", resources.DashboardResourceV2beta1).Return(v2Client, gvk, nil) + resourceClients.On("ForResource", mock.Anything, resources.DashboardResourceV2beta1).Return(v2Client, gvk, nil) options := resources.WriteOptions{ Path: "grafana", @@ -526,8 +526,8 @@ func TestExportResources_Dashboards_V2beta1_ClientError(t *testing.T) { } setupResources := func(repoResources *resources.MockRepositoryResources, resourceClients *resources.MockResourceClients, mockClient *mockDynamicInterface, gvk schema.GroupVersionKind) { - resourceClients.On("ForResource", resources.DashboardResourceV2beta1).Return(nil, gvk, fmt.Errorf("v2 client error")) - resourceClients.On("ForResource", resources.DashboardResource).Return(mockClient, gvk, nil) + resourceClients.On("ForResource", mock.Anything, resources.DashboardResourceV2beta1).Return(nil, gvk, fmt.Errorf("v2 client error")) + resourceClients.On("ForResource", mock.Anything, resources.DashboardResource).Return(mockClient, gvk, nil) } err := runExportTest(t, mockItems, setupProgress, setupResources) @@ -560,7 +560,7 @@ func TestExportResources_Dashboards_SkipsManagedResources(t *testing.T) { } setupResources := func(repoResources *resources.MockRepositoryResources, resourceClients *resources.MockResourceClients, mockClient *mockDynamicInterface, gvk schema.GroupVersionKind) { - resourceClients.On("ForResource", resources.DashboardResource).Return(mockClient, gvk, nil) + resourceClients.On("ForResource", mock.Anything, resources.DashboardResource).Return(mockClient, gvk, nil) // No WriteResourceFileFromObject call expected since resource should be skipped } diff --git a/pkg/registry/apis/provisioning/jobs/migrate/clean.go b/pkg/registry/apis/provisioning/jobs/migrate/clean.go index dd65b937939..c1c606db71d 100644 --- a/pkg/registry/apis/provisioning/jobs/migrate/clean.go +++ b/pkg/registry/apis/provisioning/jobs/migrate/clean.go @@ -33,7 +33,7 @@ func (c *namespaceCleaner) Clean(ctx context.Context, namespace string, progress for _, kind := range resources.SupportedProvisioningResources { progress.SetMessage(ctx, fmt.Sprintf("remove unprovisioned %s", kind.Resource)) - client, _, err := clients.ForResource(kind) + client, _, err := clients.ForResource(ctx, kind) if err != nil { return fmt.Errorf("get resource client: %w", err) } diff --git a/pkg/registry/apis/provisioning/jobs/migrate/clean_test.go b/pkg/registry/apis/provisioning/jobs/migrate/clean_test.go index d466178422f..1a454151a87 100644 --- a/pkg/registry/apis/provisioning/jobs/migrate/clean_test.go +++ b/pkg/registry/apis/provisioning/jobs/migrate/clean_test.go @@ -21,8 +21,8 @@ type mockClients struct { mock.Mock } -func (m *mockClients) ForResource(gvr schema.GroupVersionResource) (dynamic.ResourceInterface, schema.GroupVersionKind, error) { - args := m.Called(gvr) +func (m *mockClients) ForResource(ctx context.Context, gvr schema.GroupVersionResource) (dynamic.ResourceInterface, schema.GroupVersionKind, error) { + args := m.Called(ctx, gvr) var ri dynamic.ResourceInterface if args.Get(0) != nil { ri = args.Get(0).(dynamic.ResourceInterface) @@ -30,8 +30,8 @@ func (m *mockClients) ForResource(gvr schema.GroupVersionResource) (dynamic.Reso return ri, args.Get(1).(schema.GroupVersionKind), args.Error(2) } -func (m *mockClients) ForKind(gvk schema.GroupVersionKind) (dynamic.ResourceInterface, schema.GroupVersionResource, error) { - args := m.Called(gvk) +func (m *mockClients) ForKind(ctx context.Context, gvk schema.GroupVersionKind) (dynamic.ResourceInterface, schema.GroupVersionResource, error) { + args := m.Called(ctx, gvk) var ri dynamic.ResourceInterface if args.Get(0) != nil { ri = args.Get(0).(dynamic.ResourceInterface) @@ -39,8 +39,8 @@ func (m *mockClients) ForKind(gvk schema.GroupVersionKind) (dynamic.ResourceInte return ri, args.Get(1).(schema.GroupVersionResource), args.Error(2) } -func (m *mockClients) Folder() (dynamic.ResourceInterface, error) { - args := m.Called() +func (m *mockClients) Folder(ctx context.Context) (dynamic.ResourceInterface, error) { + args := m.Called(ctx) var ri dynamic.ResourceInterface if args.Get(0) != nil { ri = args.Get(0).(dynamic.ResourceInterface) @@ -48,8 +48,8 @@ func (m *mockClients) Folder() (dynamic.ResourceInterface, error) { return ri, args.Error(1) } -func (m *mockClients) User() (dynamic.ResourceInterface, error) { - args := m.Called() +func (m *mockClients) User(ctx context.Context) (dynamic.ResourceInterface, error) { + args := m.Called(ctx) var ri dynamic.ResourceInterface if args.Get(0) != nil { ri = args.Get(0).(dynamic.ResourceInterface) @@ -75,7 +75,7 @@ func TestNamespaceCleaner_Clean(t *testing.T) { t.Run("should fail when getting resource client fails", func(t *testing.T) { clients := &mockClients{} - clients.On("ForResource", resources.SupportedProvisioningResources[0]). + clients.On("ForResource", mock.Anything, resources.SupportedProvisioningResources[0]). Return(nil, schema.GroupVersionKind{}, errors.New("failed to get resource client")) mockClientFactory := resources.NewMockClientFactory(t) @@ -113,7 +113,7 @@ func TestNamespaceCleaner_Clean(t *testing.T) { } clients := &mockClients{} - clients.On("ForResource", mock.Anything). + clients.On("ForResource", mock.Anything, mock.Anything). Return(mockDynamicClient, schema.GroupVersionKind{}, nil) mockClientFactory := resources.NewMockClientFactory(t) @@ -180,7 +180,7 @@ func TestNamespaceCleaner_Clean(t *testing.T) { } clients := &mockClients{} - clients.On("ForResource", mock.Anything). + clients.On("ForResource", mock.Anything, mock.Anything). Return(mockDynamicClient, schema.GroupVersionKind{}, nil) mockClientFactory := resources.NewMockClientFactory(t) @@ -253,7 +253,7 @@ func TestNamespaceCleaner_Clean(t *testing.T) { } clients := &mockClients{} - clients.On("ForResource", mock.Anything). + clients.On("ForResource", mock.Anything, mock.Anything). Return(mockDynamicClient, schema.GroupVersionKind{}, nil) mockClientFactory := resources.NewMockClientFactory(t) diff --git a/pkg/registry/apis/provisioning/jobs/sync/full.go b/pkg/registry/apis/provisioning/jobs/sync/full.go index ce68a0bea7a..8114d8a67ce 100644 --- a/pkg/registry/apis/provisioning/jobs/sync/full.go +++ b/pkg/registry/apis/provisioning/jobs/sync/full.go @@ -82,7 +82,7 @@ func applyChanges(ctx context.Context, changes []ResourceFileChange, clients res } // TODO: should we use the clients or the resource manager instead? - client, _, err := clients.ForResource(versionlessGVR) + client, _, err := clients.ForResource(ctx, versionlessGVR) if err != nil { result.Error = fmt.Errorf("get client for deleted object: %w", err) progress.Record(ctx, result) diff --git a/pkg/registry/apis/provisioning/jobs/sync/full_test.go b/pkg/registry/apis/provisioning/jobs/sync/full_test.go index 5543cfa74bf..0f051e20b72 100644 --- a/pkg/registry/apis/provisioning/jobs/sync/full_test.go +++ b/pkg/registry/apis/provisioning/jobs/sync/full_test.go @@ -408,7 +408,7 @@ func TestFullSync_ApplyChanges(t *testing.T) { //nolint:gocyclo return true, nil, nil }) - clients.On("ForResource", schema.GroupVersionResource{ + clients.On("ForResource", mock.Anything, schema.GroupVersionResource{ Group: "dashboards", Resource: "Dashboard", }).Return(fakeDynamicClient.Resource(resources.DashboardResource), schema.GroupVersionKind{ @@ -467,7 +467,7 @@ func TestFullSync_ApplyChanges(t *testing.T) { //nolint:gocyclo return true, nil, fmt.Errorf("delete failed") }) - clients.On("ForResource", schema.GroupVersionResource{ + clients.On("ForResource", mock.Anything, schema.GroupVersionResource{ Group: "dashboards", Resource: "Dashboard", }).Return(fakeDynamicClient.Resource(resources.DashboardResource), schema.GroupVersionKind{ @@ -544,7 +544,7 @@ func TestFullSync_ApplyChanges(t *testing.T) { //nolint:gocyclo setupMocks: func(repo *repository.MockRepository, repoResources *resources.MockRepositoryResources, clients *resources.MockResourceClients, progress *jobs.MockJobProgressRecorder, compareFn *MockCompareFn) { progress.On("TooManyErrors").Return(nil) - clients.On("ForResource", schema.GroupVersionResource{ + clients.On("ForResource", mock.Anything, schema.GroupVersionResource{ Group: "dashboards", Resource: "Dashboard", }).Return(nil, schema.GroupVersionKind{}, errors.New("didn't work")) @@ -599,7 +599,7 @@ func TestFullSync_ApplyChanges(t *testing.T) { //nolint:gocyclo return true, nil, nil }) - clients.On("ForResource", schema.GroupVersionResource{ + clients.On("ForResource", mock.Anything, schema.GroupVersionResource{ Group: "folders", Resource: "Folder", }).Return(fakeDynamicClient.Resource(resources.FolderResource), schema.GroupVersionKind{ @@ -658,7 +658,7 @@ func TestFullSync_ApplyChanges(t *testing.T) { //nolint:gocyclo return true, nil, fmt.Errorf("delete failed") }) - clients.On("ForResource", schema.GroupVersionResource{ + clients.On("ForResource", mock.Anything, schema.GroupVersionResource{ Group: "folders", Resource: "Folder", }).Return(fakeDynamicClient.Resource(resources.FolderResource), schema.GroupVersionKind{ diff --git a/pkg/registry/apis/provisioning/resources/client.go b/pkg/registry/apis/provisioning/resources/client.go index 59234937262..3ff93ce15fe 100644 --- a/pkg/registry/apis/provisioning/resources/client.go +++ b/pkg/registry/apis/provisioning/resources/client.go @@ -41,7 +41,7 @@ type ClientFactory interface { } type clientFactory struct { - configProvider apiserver.RestConfigProvider + clientsProvider clientsProvider } // TODO: Rename to NamespacedClients @@ -49,51 +49,92 @@ type clientFactory struct { // //go:generate mockery --name ResourceClients --structname MockResourceClients --inpackage --filename clients_mock.go --with-expecter type ResourceClients interface { - ForKind(gvk schema.GroupVersionKind) (dynamic.ResourceInterface, schema.GroupVersionResource, error) - ForResource(gvr schema.GroupVersionResource) (dynamic.ResourceInterface, schema.GroupVersionKind, error) + ForKind(ctx context.Context, gvk schema.GroupVersionKind) (dynamic.ResourceInterface, schema.GroupVersionResource, error) + ForResource(ctx context.Context, gvr schema.GroupVersionResource) (dynamic.ResourceInterface, schema.GroupVersionKind, error) + Folder(ctx context.Context) (dynamic.ResourceInterface, error) + User(ctx context.Context) (dynamic.ResourceInterface, error) +} - Folder() (dynamic.ResourceInterface, error) - User() (dynamic.ResourceInterface, error) +type clientsProvider interface { + GetClientsForKind(ctx context.Context, gvk schema.GroupVersionKind) (dynamic.Interface, client.DiscoveryClient, error) + GetClientsForResource(ctx context.Context, gvr schema.GroupVersionResource) (dynamic.Interface, client.DiscoveryClient, error) +} + +// singleAPIClients provides clients for all registered APIs +// It implements ClientsProvider by creating a dynamic client and discovery client +// for the given rest config provider +type singleAPIClients struct { + configProvider apiserver.RestConfigProvider + once sync.Once + dynamic dynamic.Interface + discovery client.DiscoveryClient + initErr error +} + +func newSingleAPIClients(configProvider apiserver.RestConfigProvider) clientsProvider { + return &singleAPIClients{configProvider: configProvider} +} + +func (p *singleAPIClients) onlyOnce(ctx context.Context) error { + p.once.Do(func() { + restConfig, e := p.configProvider.GetRestConfig(ctx) + if e != nil { + p.initErr = fmt.Errorf("get rest config: %w", e) + return + } + + p.dynamic, e = dynamic.NewForConfig(restConfig) + if e != nil { + p.initErr = fmt.Errorf("create dynamic client: %w", e) + return + } + + p.discovery, e = client.NewDiscoveryClient(restConfig) + if e != nil { + p.initErr = fmt.Errorf("create discovery client: %w", e) + return + } + }) + + return p.initErr +} + +func (p *singleAPIClients) GetClientsForKind(ctx context.Context, _ schema.GroupVersionKind) (dynamic.Interface, client.DiscoveryClient, error) { + if err := p.onlyOnce(ctx); err != nil { + return nil, nil, fmt.Errorf("get clients: %w", err) + } + + return p.dynamic, p.discovery, nil +} + +func (p *singleAPIClients) GetClientsForResource(ctx context.Context, _ schema.GroupVersionResource) (dynamic.Interface, client.DiscoveryClient, error) { + if err := p.onlyOnce(ctx); err != nil { + return nil, nil, fmt.Errorf("get clients: %w", err) + } + + return p.dynamic, p.discovery, nil } func NewClientFactory(configProvider apiserver.RestConfigProvider) ClientFactory { - return &clientFactory{configProvider} + return &clientFactory{newSingleAPIClients(configProvider)} } func (f *clientFactory) Clients(ctx context.Context, namespace string) (ResourceClients, error) { - restConfig, err := f.configProvider.GetRestConfig(ctx) - if err != nil { - return nil, err - } - if namespace == "" { return nil, fmt.Errorf("missing namespace") } - discovery, err := client.NewDiscoveryClient(restConfig) - if err != nil { - return nil, err - } - - client, err := dynamic.NewForConfig(restConfig) - if err != nil { - return nil, err - } - return &resourceClients{ - namespace: namespace, - discovery: discovery, - dynamic: client, - byKind: make(map[schema.GroupVersionKind]*clientInfo), - byResource: make(map[schema.GroupVersionResource]*clientInfo), + namespace: namespace, + clientsProvider: f.clientsProvider, + byKind: make(map[schema.GroupVersionKind]*clientInfo), + byResource: make(map[schema.GroupVersionResource]*clientInfo), }, nil } type resourceClients struct { - namespace string - - dynamic dynamic.Interface - discovery client.DiscoveryClient + namespace string + clientsProvider clientsProvider // ResourceInterface cache for this context + namespace mutex sync.Mutex @@ -110,7 +151,7 @@ type clientInfo struct { // ForKind returns a client for a kind. // If the kind has a version, it will be used. // If the kind does not have a version, the preferred version will be used. -func (c *resourceClients) ForKind(gvk schema.GroupVersionKind) (dynamic.ResourceInterface, schema.GroupVersionResource, error) { +func (c *resourceClients) ForKind(ctx context.Context, gvk schema.GroupVersionKind) (dynamic.ResourceInterface, schema.GroupVersionResource, error) { c.mutex.Lock() defer c.mutex.Unlock() @@ -119,12 +160,16 @@ func (c *resourceClients) ForKind(gvk schema.GroupVersionKind) (dynamic.Resource return info.client, info.gvr, nil } - var err error + dynamic, discovery, err := c.clientsProvider.GetClientsForKind(ctx, gvk) + if err != nil { + return nil, schema.GroupVersionResource{}, fmt.Errorf("get clients for resource %s: %w", gvk.String(), err) + } + var gvr schema.GroupVersionResource var versionless schema.GroupVersionKind if gvk.Version == "" { versionless = gvk - gvr, gvk, err = c.discovery.GetPreferredVersionForKind(schema.GroupKind{ + gvr, gvk, err = discovery.GetPreferredVersionForKind(schema.GroupKind{ Group: gvk.Group, Kind: gvk.Kind, }) @@ -138,7 +183,7 @@ func (c *resourceClients) ForKind(gvk schema.GroupVersionKind) (dynamic.Resource return info.client, info.gvr, nil } } else { - gvr, err = c.discovery.GetResourceForKind(gvk) + gvr, err = discovery.GetResourceForKind(gvk) if err != nil { return nil, schema.GroupVersionResource{}, err } @@ -146,7 +191,7 @@ func (c *resourceClients) ForKind(gvk schema.GroupVersionKind) (dynamic.Resource info = &clientInfo{ gvk: gvk, gvr: gvr, - client: c.dynamic.Resource(gvr).Namespace(c.namespace), + client: dynamic.Resource(gvr).Namespace(c.namespace), } c.byKind[gvk] = info c.byResource[gvr] = info @@ -159,7 +204,7 @@ func (c *resourceClients) ForKind(gvk schema.GroupVersionKind) (dynamic.Resource // ForResource returns a client for a resource. // If the resource has a version, it will be used. // If the resource does not have a version, the preferred version will be used. -func (c *resourceClients) ForResource(gvr schema.GroupVersionResource) (dynamic.ResourceInterface, schema.GroupVersionKind, error) { +func (c *resourceClients) ForResource(ctx context.Context, gvr schema.GroupVersionResource) (dynamic.ResourceInterface, schema.GroupVersionKind, error) { c.mutex.Lock() defer c.mutex.Unlock() @@ -168,12 +213,16 @@ func (c *resourceClients) ForResource(gvr schema.GroupVersionResource) (dynamic. return info.client, info.gvk, nil } - var err error + dynamic, discovery, err := c.clientsProvider.GetClientsForResource(ctx, gvr) + if err != nil { + return nil, schema.GroupVersionKind{}, fmt.Errorf("get clients for kind %s: %w", gvr.String(), err) + } + var gvk schema.GroupVersionKind var versionless schema.GroupVersionResource if gvr.Version == "" { versionless = gvr - gvr, gvk, err = c.discovery.GetPreferredVesion(schema.GroupResource{ + gvr, gvk, err = discovery.GetPreferredVesion(schema.GroupResource{ Group: gvr.Group, Resource: gvr.Resource, }) @@ -187,7 +236,7 @@ func (c *resourceClients) ForResource(gvr schema.GroupVersionResource) (dynamic. return info.client, info.gvk, nil } } else { - gvk, err = c.discovery.GetKindForResource(gvr) + gvk, err = discovery.GetKindForResource(gvr) if err != nil { return nil, schema.GroupVersionKind{}, err } @@ -195,7 +244,7 @@ func (c *resourceClients) ForResource(gvr schema.GroupVersionResource) (dynamic. info = &clientInfo{ gvk: gvk, gvr: gvr, - client: c.dynamic.Resource(gvr).Namespace(c.namespace), + client: dynamic.Resource(gvr).Namespace(c.namespace), } c.byKind[gvk] = info c.byResource[gvr] = info @@ -205,13 +254,13 @@ func (c *resourceClients) ForResource(gvr schema.GroupVersionResource) (dynamic. return info.client, info.gvk, nil } -func (c *resourceClients) Folder() (dynamic.ResourceInterface, error) { - client, _, err := c.ForResource(FolderResource) +func (c *resourceClients) Folder(ctx context.Context) (dynamic.ResourceInterface, error) { + client, _, err := c.ForResource(ctx, FolderResource) return client, err } -func (c *resourceClients) User() (dynamic.ResourceInterface, error) { - v, _, err := c.ForResource(UserResource) +func (c *resourceClients) User(ctx context.Context) (dynamic.ResourceInterface, error) { + v, _, err := c.ForResource(ctx, UserResource) return v, err } diff --git a/pkg/registry/apis/provisioning/resources/clients_mock.go b/pkg/registry/apis/provisioning/resources/clients_mock.go index 4af4559943a..165f88716d6 100644 --- a/pkg/registry/apis/provisioning/resources/clients_mock.go +++ b/pkg/registry/apis/provisioning/resources/clients_mock.go @@ -3,6 +3,8 @@ package resources import ( + context "context" + mock "github.com/stretchr/testify/mock" dynamic "k8s.io/client-go/dynamic" @@ -22,9 +24,9 @@ func (_m *MockResourceClients) EXPECT() *MockResourceClients_Expecter { return &MockResourceClients_Expecter{mock: &_m.Mock} } -// Folder provides a mock function with no fields -func (_m *MockResourceClients) Folder() (dynamic.ResourceInterface, error) { - ret := _m.Called() +// Folder provides a mock function with given fields: ctx +func (_m *MockResourceClients) Folder(ctx context.Context) (dynamic.ResourceInterface, error) { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for Folder") @@ -32,19 +34,19 @@ func (_m *MockResourceClients) Folder() (dynamic.ResourceInterface, error) { var r0 dynamic.ResourceInterface var r1 error - if rf, ok := ret.Get(0).(func() (dynamic.ResourceInterface, error)); ok { - return rf() + if rf, ok := ret.Get(0).(func(context.Context) (dynamic.ResourceInterface, error)); ok { + return rf(ctx) } - if rf, ok := ret.Get(0).(func() dynamic.ResourceInterface); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) dynamic.ResourceInterface); ok { + r0 = rf(ctx) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(dynamic.ResourceInterface) } } - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) } else { r1 = ret.Error(1) } @@ -58,13 +60,14 @@ type MockResourceClients_Folder_Call struct { } // Folder is a helper method to define mock.On call -func (_e *MockResourceClients_Expecter) Folder() *MockResourceClients_Folder_Call { - return &MockResourceClients_Folder_Call{Call: _e.mock.On("Folder")} +// - ctx context.Context +func (_e *MockResourceClients_Expecter) Folder(ctx interface{}) *MockResourceClients_Folder_Call { + return &MockResourceClients_Folder_Call{Call: _e.mock.On("Folder", ctx)} } -func (_c *MockResourceClients_Folder_Call) Run(run func()) *MockResourceClients_Folder_Call { +func (_c *MockResourceClients_Folder_Call) Run(run func(ctx context.Context)) *MockResourceClients_Folder_Call { _c.Call.Run(func(args mock.Arguments) { - run() + run(args[0].(context.Context)) }) return _c } @@ -74,14 +77,14 @@ func (_c *MockResourceClients_Folder_Call) Return(_a0 dynamic.ResourceInterface, return _c } -func (_c *MockResourceClients_Folder_Call) RunAndReturn(run func() (dynamic.ResourceInterface, error)) *MockResourceClients_Folder_Call { +func (_c *MockResourceClients_Folder_Call) RunAndReturn(run func(context.Context) (dynamic.ResourceInterface, error)) *MockResourceClients_Folder_Call { _c.Call.Return(run) return _c } -// ForKind provides a mock function with given fields: gvk -func (_m *MockResourceClients) ForKind(gvk schema.GroupVersionKind) (dynamic.ResourceInterface, schema.GroupVersionResource, error) { - ret := _m.Called(gvk) +// ForKind provides a mock function with given fields: ctx, gvk +func (_m *MockResourceClients) ForKind(ctx context.Context, gvk schema.GroupVersionKind) (dynamic.ResourceInterface, schema.GroupVersionResource, error) { + ret := _m.Called(ctx, gvk) if len(ret) == 0 { panic("no return value specified for ForKind") @@ -90,25 +93,25 @@ func (_m *MockResourceClients) ForKind(gvk schema.GroupVersionKind) (dynamic.Res var r0 dynamic.ResourceInterface var r1 schema.GroupVersionResource var r2 error - if rf, ok := ret.Get(0).(func(schema.GroupVersionKind) (dynamic.ResourceInterface, schema.GroupVersionResource, error)); ok { - return rf(gvk) + if rf, ok := ret.Get(0).(func(context.Context, schema.GroupVersionKind) (dynamic.ResourceInterface, schema.GroupVersionResource, error)); ok { + return rf(ctx, gvk) } - if rf, ok := ret.Get(0).(func(schema.GroupVersionKind) dynamic.ResourceInterface); ok { - r0 = rf(gvk) + if rf, ok := ret.Get(0).(func(context.Context, schema.GroupVersionKind) dynamic.ResourceInterface); ok { + r0 = rf(ctx, gvk) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(dynamic.ResourceInterface) } } - if rf, ok := ret.Get(1).(func(schema.GroupVersionKind) schema.GroupVersionResource); ok { - r1 = rf(gvk) + if rf, ok := ret.Get(1).(func(context.Context, schema.GroupVersionKind) schema.GroupVersionResource); ok { + r1 = rf(ctx, gvk) } else { r1 = ret.Get(1).(schema.GroupVersionResource) } - if rf, ok := ret.Get(2).(func(schema.GroupVersionKind) error); ok { - r2 = rf(gvk) + if rf, ok := ret.Get(2).(func(context.Context, schema.GroupVersionKind) error); ok { + r2 = rf(ctx, gvk) } else { r2 = ret.Error(2) } @@ -122,14 +125,15 @@ type MockResourceClients_ForKind_Call struct { } // ForKind is a helper method to define mock.On call +// - ctx context.Context // - gvk schema.GroupVersionKind -func (_e *MockResourceClients_Expecter) ForKind(gvk interface{}) *MockResourceClients_ForKind_Call { - return &MockResourceClients_ForKind_Call{Call: _e.mock.On("ForKind", gvk)} +func (_e *MockResourceClients_Expecter) ForKind(ctx interface{}, gvk interface{}) *MockResourceClients_ForKind_Call { + return &MockResourceClients_ForKind_Call{Call: _e.mock.On("ForKind", ctx, gvk)} } -func (_c *MockResourceClients_ForKind_Call) Run(run func(gvk schema.GroupVersionKind)) *MockResourceClients_ForKind_Call { +func (_c *MockResourceClients_ForKind_Call) Run(run func(ctx context.Context, gvk schema.GroupVersionKind)) *MockResourceClients_ForKind_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(schema.GroupVersionKind)) + run(args[0].(context.Context), args[1].(schema.GroupVersionKind)) }) return _c } @@ -139,14 +143,14 @@ func (_c *MockResourceClients_ForKind_Call) Return(_a0 dynamic.ResourceInterface return _c } -func (_c *MockResourceClients_ForKind_Call) RunAndReturn(run func(schema.GroupVersionKind) (dynamic.ResourceInterface, schema.GroupVersionResource, error)) *MockResourceClients_ForKind_Call { +func (_c *MockResourceClients_ForKind_Call) RunAndReturn(run func(context.Context, schema.GroupVersionKind) (dynamic.ResourceInterface, schema.GroupVersionResource, error)) *MockResourceClients_ForKind_Call { _c.Call.Return(run) return _c } -// ForResource provides a mock function with given fields: gvr -func (_m *MockResourceClients) ForResource(gvr schema.GroupVersionResource) (dynamic.ResourceInterface, schema.GroupVersionKind, error) { - ret := _m.Called(gvr) +// ForResource provides a mock function with given fields: ctx, gvr +func (_m *MockResourceClients) ForResource(ctx context.Context, gvr schema.GroupVersionResource) (dynamic.ResourceInterface, schema.GroupVersionKind, error) { + ret := _m.Called(ctx, gvr) if len(ret) == 0 { panic("no return value specified for ForResource") @@ -155,25 +159,25 @@ func (_m *MockResourceClients) ForResource(gvr schema.GroupVersionResource) (dyn var r0 dynamic.ResourceInterface var r1 schema.GroupVersionKind var r2 error - if rf, ok := ret.Get(0).(func(schema.GroupVersionResource) (dynamic.ResourceInterface, schema.GroupVersionKind, error)); ok { - return rf(gvr) + if rf, ok := ret.Get(0).(func(context.Context, schema.GroupVersionResource) (dynamic.ResourceInterface, schema.GroupVersionKind, error)); ok { + return rf(ctx, gvr) } - if rf, ok := ret.Get(0).(func(schema.GroupVersionResource) dynamic.ResourceInterface); ok { - r0 = rf(gvr) + if rf, ok := ret.Get(0).(func(context.Context, schema.GroupVersionResource) dynamic.ResourceInterface); ok { + r0 = rf(ctx, gvr) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(dynamic.ResourceInterface) } } - if rf, ok := ret.Get(1).(func(schema.GroupVersionResource) schema.GroupVersionKind); ok { - r1 = rf(gvr) + if rf, ok := ret.Get(1).(func(context.Context, schema.GroupVersionResource) schema.GroupVersionKind); ok { + r1 = rf(ctx, gvr) } else { r1 = ret.Get(1).(schema.GroupVersionKind) } - if rf, ok := ret.Get(2).(func(schema.GroupVersionResource) error); ok { - r2 = rf(gvr) + if rf, ok := ret.Get(2).(func(context.Context, schema.GroupVersionResource) error); ok { + r2 = rf(ctx, gvr) } else { r2 = ret.Error(2) } @@ -187,14 +191,15 @@ type MockResourceClients_ForResource_Call struct { } // ForResource is a helper method to define mock.On call +// - ctx context.Context // - gvr schema.GroupVersionResource -func (_e *MockResourceClients_Expecter) ForResource(gvr interface{}) *MockResourceClients_ForResource_Call { - return &MockResourceClients_ForResource_Call{Call: _e.mock.On("ForResource", gvr)} +func (_e *MockResourceClients_Expecter) ForResource(ctx interface{}, gvr interface{}) *MockResourceClients_ForResource_Call { + return &MockResourceClients_ForResource_Call{Call: _e.mock.On("ForResource", ctx, gvr)} } -func (_c *MockResourceClients_ForResource_Call) Run(run func(gvr schema.GroupVersionResource)) *MockResourceClients_ForResource_Call { +func (_c *MockResourceClients_ForResource_Call) Run(run func(ctx context.Context, gvr schema.GroupVersionResource)) *MockResourceClients_ForResource_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(schema.GroupVersionResource)) + run(args[0].(context.Context), args[1].(schema.GroupVersionResource)) }) return _c } @@ -204,14 +209,14 @@ func (_c *MockResourceClients_ForResource_Call) Return(_a0 dynamic.ResourceInter return _c } -func (_c *MockResourceClients_ForResource_Call) RunAndReturn(run func(schema.GroupVersionResource) (dynamic.ResourceInterface, schema.GroupVersionKind, error)) *MockResourceClients_ForResource_Call { +func (_c *MockResourceClients_ForResource_Call) RunAndReturn(run func(context.Context, schema.GroupVersionResource) (dynamic.ResourceInterface, schema.GroupVersionKind, error)) *MockResourceClients_ForResource_Call { _c.Call.Return(run) return _c } -// User provides a mock function with no fields -func (_m *MockResourceClients) User() (dynamic.ResourceInterface, error) { - ret := _m.Called() +// User provides a mock function with given fields: ctx +func (_m *MockResourceClients) User(ctx context.Context) (dynamic.ResourceInterface, error) { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for User") @@ -219,19 +224,19 @@ func (_m *MockResourceClients) User() (dynamic.ResourceInterface, error) { var r0 dynamic.ResourceInterface var r1 error - if rf, ok := ret.Get(0).(func() (dynamic.ResourceInterface, error)); ok { - return rf() + if rf, ok := ret.Get(0).(func(context.Context) (dynamic.ResourceInterface, error)); ok { + return rf(ctx) } - if rf, ok := ret.Get(0).(func() dynamic.ResourceInterface); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) dynamic.ResourceInterface); ok { + r0 = rf(ctx) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(dynamic.ResourceInterface) } } - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) } else { r1 = ret.Error(1) } @@ -245,13 +250,14 @@ type MockResourceClients_User_Call struct { } // User is a helper method to define mock.On call -func (_e *MockResourceClients_Expecter) User() *MockResourceClients_User_Call { - return &MockResourceClients_User_Call{Call: _e.mock.On("User")} +// - ctx context.Context +func (_e *MockResourceClients_Expecter) User(ctx interface{}) *MockResourceClients_User_Call { + return &MockResourceClients_User_Call{Call: _e.mock.On("User", ctx)} } -func (_c *MockResourceClients_User_Call) Run(run func()) *MockResourceClients_User_Call { +func (_c *MockResourceClients_User_Call) Run(run func(ctx context.Context)) *MockResourceClients_User_Call { _c.Call.Run(func(args mock.Arguments) { - run() + run(args[0].(context.Context)) }) return _c } @@ -261,7 +267,7 @@ func (_c *MockResourceClients_User_Call) Return(_a0 dynamic.ResourceInterface, _ return _c } -func (_c *MockResourceClients_User_Call) RunAndReturn(run func() (dynamic.ResourceInterface, error)) *MockResourceClients_User_Call { +func (_c *MockResourceClients_User_Call) RunAndReturn(run func(context.Context) (dynamic.ResourceInterface, error)) *MockResourceClients_User_Call { _c.Call.Return(run) return _c } diff --git a/pkg/registry/apis/provisioning/resources/parser.go b/pkg/registry/apis/provisioning/resources/parser.go index 7dacd33ff0b..44e48041bd5 100644 --- a/pkg/registry/apis/provisioning/resources/parser.go +++ b/pkg/registry/apis/provisioning/resources/parser.go @@ -208,7 +208,7 @@ func (r *parser) Parse(ctx context.Context, info *repository.FileInfo) (parsed * } // TODO: catch the not found gvk error to return bad request - parsed.Client, parsed.GVR, err = r.clients.ForKind(parsed.GVK) + parsed.Client, parsed.GVR, err = r.clients.ForKind(ctx, parsed.GVK) if err != nil { return nil, fmt.Errorf("get client for kind: %w", err) } diff --git a/pkg/registry/apis/provisioning/resources/parser_test.go b/pkg/registry/apis/provisioning/resources/parser_test.go index 8f19b5f748a..e171027608a 100644 --- a/pkg/registry/apis/provisioning/resources/parser_test.go +++ b/pkg/registry/apis/provisioning/resources/parser_test.go @@ -5,6 +5,7 @@ import ( "strings" "testing" + "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" dashboardV0 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v0alpha1" @@ -16,9 +17,9 @@ import ( func TestParser(t *testing.T) { clients := NewMockResourceClients(t) - clients.On("ForKind", dashboardV0.DashboardResourceInfo.GroupVersionKind()). + clients.On("ForKind", mock.Anything, dashboardV0.DashboardResourceInfo.GroupVersionKind()). Return(nil, dashboardV0.DashboardResourceInfo.GroupVersionResource(), nil).Maybe() - clients.On("ForKind", dashboardV1.DashboardResourceInfo.GroupVersionKind()). + clients.On("ForKind", mock.Anything, dashboardV1.DashboardResourceInfo.GroupVersionKind()). Return(nil, dashboardV1.DashboardResourceInfo.GroupVersionResource(), nil).Maybe() parser := &parser{ diff --git a/pkg/registry/apis/provisioning/resources/repository.go b/pkg/registry/apis/provisioning/resources/repository.go index 0ebf7197b50..67236d93cd5 100644 --- a/pkg/registry/apis/provisioning/resources/repository.go +++ b/pkg/registry/apis/provisioning/resources/repository.go @@ -64,7 +64,7 @@ func (r *repositoryResources) List(ctx context.Context) (*provisioning.ResourceL // FindResourcePath finds the repository file path for a resource by its name and GroupVersionKind func (r *repositoryResources) FindResourcePath(ctx context.Context, name string, gvk schema.GroupVersionKind) (string, error) { // Use ForKind to get the dynamic client for this resource type - client, gvr, err := r.clients.ForKind(gvk) + client, gvr, err := r.clients.ForKind(ctx, gvk) if err != nil { return "", fmt.Errorf("get client for kind %s: %w", gvk.Kind, err) } @@ -107,7 +107,7 @@ func (r *repositoryResourcesFactory) Client(ctx context.Context, repo repository return nil, fmt.Errorf("create clients: %w", err) } - folderClient, err := clients.Folder() + folderClient, err := clients.Folder(ctx) if err != nil { return nil, fmt.Errorf("create folder client: %w", err) } diff --git a/pkg/registry/apis/provisioning/resources/repository_test.go b/pkg/registry/apis/provisioning/resources/repository_test.go index 0c1c97f564f..5240d9d2758 100644 --- a/pkg/registry/apis/provisioning/resources/repository_test.go +++ b/pkg/registry/apis/provisioning/resources/repository_test.go @@ -313,9 +313,9 @@ func TestRepositoryResources_FindResourcePath(t *testing.T) { // Mock ForKind call if tt.forKindError != nil { - mockClients.On("ForKind", tt.gvk).Return(nil, schema.GroupVersionResource{}, tt.forKindError) + mockClients.On("ForKind", mock.Anything, tt.gvk).Return(nil, schema.GroupVersionResource{}, tt.forKindError) } else { - mockClients.On("ForKind", tt.gvk).Return(mockClient, tt.expectedGVR, nil) + mockClients.On("ForKind", mock.Anything, tt.gvk).Return(mockClient, tt.expectedGVR, nil) // Mock Get call if ForKind succeeds if tt.getError != nil { diff --git a/pkg/registry/apis/provisioning/resources/resources.go b/pkg/registry/apis/provisioning/resources/resources.go index 3f099d0c268..027f04671ff 100644 --- a/pkg/registry/apis/provisioning/resources/resources.go +++ b/pkg/registry/apis/provisioning/resources/resources.go @@ -263,7 +263,7 @@ func (r *ResourcesManager) RemoveResourceFromFile(ctx context.Context, path stri return "", schema.GroupVersionKind{}, ErrMissingName } - client, _, err := r.clients.ForKind(*gvk) + client, _, err := r.clients.ForKind(ctx, *gvk) if err != nil { return "", schema.GroupVersionKind{}, fmt.Errorf("unable to get client for deleted object: %w", err) } diff --git a/pkg/registry/apis/provisioning/resources/signature/signature.go b/pkg/registry/apis/provisioning/resources/signature/signature.go index 9ad606bb33e..c0b39f7b325 100644 --- a/pkg/registry/apis/provisioning/resources/signature/signature.go +++ b/pkg/registry/apis/provisioning/resources/signature/signature.go @@ -43,7 +43,7 @@ func (f *signerFactory) New(ctx context.Context, opts SignOptions) (Signer, erro return nil, fmt.Errorf("get clients: %w", err) } - userClient, err := clients.User() + userClient, err := clients.User(ctx) if err != nil { return nil, fmt.Errorf("get user client: %w", err) } diff --git a/pkg/registry/apis/provisioning/resources/signature/signature_test.go b/pkg/registry/apis/provisioning/resources/signature/signature_test.go index 2d8abdd2cd2..b339865ca5f 100644 --- a/pkg/registry/apis/provisioning/resources/signature/signature_test.go +++ b/pkg/registry/apis/provisioning/resources/signature/signature_test.go @@ -5,6 +5,7 @@ import ( "fmt" "testing" + "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "github.com/grafana/grafana/pkg/registry/apis/provisioning/resources" @@ -37,7 +38,7 @@ func TestSignerFactory_New(t *testing.T) { setupMocks: func(t *testing.T, clients *resources.MockClientFactory) { mockResourceClients := resources.NewMockResourceClients(t) clients.On("Clients", context.Background(), "test-ns").Return(mockResourceClients, nil) - mockResourceClients.On("User").Return(nil, nil) + mockResourceClients.On("User", mock.Anything).Return(nil, nil) }, expectedType: &loadUsersOnceSigner{}, }, @@ -61,7 +62,7 @@ func TestSignerFactory_New(t *testing.T) { setupMocks: func(t *testing.T, clients *resources.MockClientFactory) { mockResourceClients := resources.NewMockResourceClients(t) clients.On("Clients", context.Background(), "test-ns").Return(mockResourceClients, nil) - mockResourceClients.On("User").Return(nil, fmt.Errorf("user client error")) + mockResourceClients.On("User", mock.Anything).Return(nil, fmt.Errorf("user client error")) }, expectedError: "get user client: user client error", }, diff --git a/pkg/tests/apis/provisioning/client_test.go b/pkg/tests/apis/provisioning/client_test.go index 7f11699e3ab..215d97f84e0 100644 --- a/pkg/tests/apis/provisioning/client_test.go +++ b/pkg/tests/apis/provisioning/client_test.go @@ -24,7 +24,7 @@ func TestIntegrationProvisioning_Client(t *testing.T) { require.NoError(t, err) t.Run("dashboard client support", func(t *testing.T) { - _, _, err := clients.ForResource(schema.GroupVersionResource{ + _, _, err := clients.ForResource(ctx, schema.GroupVersionResource{ Group: dashboardV1.GROUP, Version: dashboardV1.VERSION, Resource: "dashboards", @@ -32,7 +32,7 @@ func TestIntegrationProvisioning_Client(t *testing.T) { require.NoError(t, err) // With empty version, we should get the preferred version (v1beta1) - _, gvk, err := clients.ForResource(schema.GroupVersionResource{ + _, gvk, err := clients.ForResource(ctx, schema.GroupVersionResource{ Group: dashboardV1.GROUP, Resource: "dashboards", }) @@ -40,7 +40,7 @@ func TestIntegrationProvisioning_Client(t *testing.T) { require.Equal(t, dashboardV1.VERSION, gvk.Version) require.Equal(t, "Dashboard", gvk.Kind) - _, _, err = clients.ForKind(schema.GroupVersionKind{ + _, _, err = clients.ForKind(ctx, schema.GroupVersionKind{ Group: dashboardV1.GROUP, Version: dashboardV1.VERSION, Kind: "Dashboard",