Commit Details
Author: Roberto Jiménez Sánchez
Date: 2026-06-08 11:57 UTC
Message:
Provisioning: Capability-based config-driven supported resources (#125856)
* Provisioning: Introduce flag-gated seam for supported resources
Add SupportedResources and SupportsFolderAnnotationResources constructors that
accept a featuremgmt.FeatureToggles checker and today return exactly the static
SupportedProvisioningResources / SupportsFolderAnnotation sets. This establishes
a single seam where future flag-gated resources can be appended, without changing
current behaviour and without adding any new resource or feature flag.
Migrate the pipeline consumers (export loop, export quota stats, migrate cleanup,
authorizer, folder-annotation write path) to call the constructors instead of
ranging over the package vars directly. The constructors tolerate a nil checker;
no flag is consulted yet, so the effective set is identical to today.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Provisioning: Make supported-resource set a ResourceClients concern
Move the supported-resource set behind the ResourceClients interface and
register extra types through the client factory instead of a flag-gated
package function.
- SupportedResources() and SupportsFolderAnnotationResources() are now
methods on ResourceClients, returning the static base set plus any extra
resources registered with the factory.
- NewClientFactory / NewClientFactoryForMultipleAPIServers accept variadic
SupportedResource registrations ({GVR, SupportsFolderAnnotation}); the
factory threads them into the namespaced clients.
- Consumers (authorizer, folder-annotation write path, export loop, quota
stats, migrate cleanup) resolve the set through the clients they already
hold; NewAuthorizer now takes a ResourceClients.
No behaviour change today: with no registered extras the effective set
equals the current static set.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Provisioning: Collapse supported-resource accessors into one method
Address review: precompute the supported set and expose it through a single
interface method.
- SupportedResources() now returns []SupportedResource (each carrying its
folder-annotation flag), replacing the separate SupportsFolderAnnotationResources.
- The merged base + registered set is computed once per factory and reused by
every ResourceClients it produces, instead of merging on each call.
- Consumers read .GVR / .SupportsFolderAnnotation off the entries; the
folder-annotation write path uses a supportsFolderAnnotation helper.
Adds a unit test for resources.go covering that the folder annotation is not
written for resources that do not support folders (and the contrasting case
that it is).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Provisioning: Drive the supported-resource set from config
Per the agreed design (git-ui-sync #1167), make the provisionable resource set
config-driven with a sensible default, instead of a package-level var. This
supersedes the per-resource feature-flag approach.
- New [provisioning] keys: resources and folder_resources (both default to
"dashboards | folders"), parsed into cfg.ProvisioningResources /
cfg.ProvisioningFolderResources, mirroring allowed_targets / repository_types.
- resources.BuildSupportedResources(resourceNames, folderResourceNames) maps the
configured short names to the effective []SupportedResource (folder_resources
is the subset that carries the folder annotation). Unknown names fail fast.
- register.go builds the set from cfg and threads it through NewAPIBuilder into
NewClientFactory; ResourceClients.SupportedResources() exposes it. With no
config the factory falls back to the static SupportedProvisioningResources.
- The effective set is surfaced on the settings endpoint (RepositoryViewList
.availableResources) the way allowed_targets is, so the frontend can read it.
Adding a resource is now a config change (folder-contained kinds go in both
lists; org-scoped kinds only in resources) — no feature flag, no codegen.
Kind/version are still resolved at runtime via discovery; folder-scope is
supplied by folder_resources until it can be declared as kind metadata.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Provisioning: Config carries the group+kind+folder triplet per resource
Address review: drive the supported set entirely from config with no hardcoded
name→GVR map, and identify resources by GroupKind (the API version and plural
resource are resolved at runtime via discovery).
- Each resource is declared in its own [provisioning.resources.<kind>.<group>]
section (mirroring the per-resource [unified_storage.<resource>.<group>]
convention), with a folder=<bool> key (extensible for future per-kind settings).
cfg.ProvisioningResources holds the parsed {Group, Kind, SupportsFolderAnnotation}
triplets; defaults to folders + dashboards.
- resources.SupportedResource is now {schema.GroupKind, SupportsFolderAnnotation}.
Consumers that need the plural resource (authorizer bulk checks + resolveFileGVR,
export loop, migrate cleanup, export quota counter) resolve it via clients.ForKind.
resolveFileGVR now matches on Group+Kind (a kind that shares a group is no longer
mis-authorized as the first kind in that group).
- The folder-annotation write path matches on the parsed GVK; no discovery needed.
- The effective set is surfaced on the settings endpoint as "<kind>.<group>"
identifiers (RepositoryViewList.availableResources), with an integration test.
Folder support is configured per kind because, although unified storage tracks it
(apistore.StorageOptions.EnableFolderSupport), it is server-side and not exposed via
the API/discovery, so a remote provisioning operator cannot read it. Declaring
folder-scope as discoverable kind metadata is a follow-up that would drop the config.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Provisioning: Regenerate frontend API client for availableResources
Run `yarn workspace @grafana/api-clients generate-apis` after adding
RepositoryViewList.availableResources to the OpenAPI: regenerates the processed
specs in @grafana/openapi and the RTK Query types in @grafana/api-clients, so
the frontend client exposes the new field.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Provisioning: Add extra-resources settings integration test + lint fix
- Simplify routes.go to r.String() (staticcheck QF1008: drop redundant embedded
GroupKind selector).
- Add a ProvisioningResources option to testinfra.GrafanaOpts that writes
[provisioning.resources.<kind>.<group>] sections.
- Add an integration test asserting a resource added purely through configuration
is surfaced on the settings endpoint (availableResources).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Provisioning: Surface supported resources as enabled-aware triplets
Address review on the settings endpoint shape:
- availableResources is now a list of structured descriptors (SupportedResource)
carrying group, kind, supportsFolderAnnotation and enabled — not opaque strings,
and the folder field is clearly named.
- Each [provisioning.resources.<kind>.<group>] section gains an enabled key
(default true). Disabled resources are still declared and surfaced, but the
pipeline (authorizer/export/migrate/quota) acts only on enabled ones —
ResourceClients.SupportedResources() returns the enabled subset, while the
settings endpoint surfaces the full declared set.
- defaults.ini declares library panels and playlists as disabled by default
(folders + dashboards remain enabled).
Regenerated deepcopy, OpenAPI (Go + snapshots + @grafana/openapi specs) and the
@grafana/api-clients RTK Query types. Adds/extends settings + client unit tests
and the settings-endpoint integration tests (default set incl. disabled, and an
extra resource added via config).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Provisioning: Thread supported resources into the operator; rename to EnableFolderSupport
- The operator (multi-API-server path) now builds the supported set from
cfg.ProvisioningResources and passes it to NewClientFactoryForMultipleAPIServers,
matching the in-process register.go wiring.
- Rename the folder field/setting/JSON to EnableFolderSupport / enableFolderSupport,
matching unified storage's apistore.StorageOptions.EnableFolderSupport and its
camelCase config-key convention. Config key folder -> enableFolderSupport.
Regenerated OpenAPI (Go + snapshots + @grafana/openapi) and the @grafana/api-clients
RTK Query types. Updated unit tests.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Provisioning: Config-driven strict-validation exemption + parser support gate; operator aggregated URL
- Strict-validation exemption is now config-driven (P0.5): per-resource
skipStrictValidation key (default false), replacing the hardcoded
`gvr == DashboardResource` check in the parser. Dashboards keep the exemption
via defaults.ini / the static fallback set.
- The parser now rejects resources that are not enabled/supported with a
ResourceValidationError, driven by the enabled supported set.
- Operator: add an aggregated_server_url [operator] key; enabled resources whose
API group has no dedicated server URL are served by the aggregated API server
(fails loudly if a resource needs it and it is unset). The operator also passes
SkipStrictValidation through.
Unit tests: parser skip-strict-validation wiring and unsupported-resource
rejection. (folder field/key already renamed to EnableFolderSupport/enableFolderSupport.)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Provisioning: Integration test for rejecting a disabled resource via files API
Writing a playlist (declared but disabled by default) through the files endpoint
is rejected as a client error referencing resource enablement/support.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Provisioning: Operator explicitly skips built-in groups for the aggregated server
Dashboards, folders and provisioning have dedicated server URLs, so skip those
groups explicitly when assigning the aggregated API server URL to extra resources.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Provisioning: Capability-based supported resources (shared grammar + parser)
Reshape the config-driven supported set to a single shared grammar, parser and
type, per the capability-based design:
- One INI key `[provisioning] resources` = comma-separated tokens
`<group>/<Kind>[:cap...]`. Capabilities (all default off): folder (folder-scoped),
skipvalidation (skip validation), disabled (declared but inert). No more
per-resource sections or enabled/folder bools.
- resources.SupportedResource is now {schema.GroupKind; Capabilities sets.Set[string]}
with IsActive()/IsValidated()/IsFolderScoped(); the shared
resources.ParseSupportedResources([]string) parses+validates the whole list
(strict, fails fast at startup) and is the single entry point for both OSS and
the (future) enterprise MT side.
- pkg/setting holds the raw []string token list (parsed in register.go and the
operator, avoiding a setting->resources import cycle).
- Settings endpoint surfaces availableResources as {group, kind, capabilities[]}.
- defaults.ini: folders + dashboards (folder), library panels (folder, disabled),
playlists (disabled).
Regenerated deepcopy, OpenAPI (Go + snapshots + @grafana/openapi) and the
@grafana/api-clients RTK Query types. Updated unit + integration tests.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Provisioning: Revert parser support-gate and strict-validation changes
The parser support-gate and per-resource skip-validation belong to separate
draft PRs. Restore parser.go to its pre-PR state (dashboard exemption hack),
drop the now-unused isSupportedResource/skipsStrictValidation helpers, and
remove the tests that exercised the reverted gate.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Provisioning: Re-attach availableResources $ref in OpenAPI post-processing
The settings connector adds RepositoryViewList to the served spec via an empty
ReferenceCallback, which strips array-item $refs. RepositoryViewList.items is
manually re-attached; do the same for the new availableResources field so its
SupportedResource element type resolves instead of degrading to {default:{}}.
Regenerate the v0alpha1/v1beta1 OpenAPI snapshots to match.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Provisioning: Surface availableResources as enabled/disabled, not capabilities
The settings endpoint only needs to tell the frontend which declared resources
are active and which are disabled, not the full internal capability set. Replace
SupportedResource.capabilities[] with a single disabled bool on the API DTO
(derived from the internal capability model via IsActive). Drop the now-unused
CapabilityList helper, regenerate deepcopy/openapi/snapshots and the frontend
RTK Query client, and update the settings integration test.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Provisioning: Regenerate deepcopy/openapi via codegen
Run hack/update-codegen.sh so the generated deepcopy and openapi for the
SupportedResource disabled-bool change match canonical generator output
(function ordering, shallow-copy for AvailableResources, violation list),
fixing the CODEGEN_VERIFY check.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Code Diff
diff --git a/apps/provisioning/pkg/apis/provisioning/v0alpha1/settings.go b/apps/provisioning/pkg/apis/provisioning/v0alpha1/settings.go
index 4decb049da1d2..8be7e1efaf2b1 100644
--- a/apps/provisioning/pkg/apis/provisioning/v0alpha1/settings.go
+++ b/apps/provisioning/pkg/apis/provisioning/v0alpha1/settings.go
@@ -21,10 +21,33 @@ type RepositoryViewList struct {
// AvailableRepositoryTypes is the list of repository types supported in this instance (e.g. git, bitbucket, github, etc)
AvailableRepositoryTypes []RepositoryType `json:"availableRepositoryTypes,omitempty"`
+ // AvailableResources is the list of resource types declared for provisioning in this
+ // instance, including disabled ones (see SupportedResource.Disabled).
+ AvailableResources []SupportedResource `json:"availableResources,omitempty"`
+
// +mapType=atomic
Items []RepositoryView `json:"items"`
}
+// SupportedResource describes a resource type declared for provisioning. A resource is
+// identified by its group and kind; the API version and plural resource are resolved at
+// runtime via discovery, so they are not part of this descriptor.
+type SupportedResource struct {
+ // Group is the API group of the resource (e.g. "dashboard.grafana.app").
+ Group string `json:"group"`
+
+ // Kind is the kind of the resource (e.g. "Dashboard").
+ Kind string `json:"kind"`
+
+ // Disabled reports whether the resource is declared but not acted on by provisioning.
+ // Active resources omit this field.
+ Disabled bool `json:"disabled,omitempty"`
+}
+
+func (SupportedResource) OpenAPIModelName() string {
+ return OpenAPIPrefix + "SupportedResource"
+}
+
func (RepositoryViewList) OpenAPIModelName() string {
return OpenAPIPrefix + "RepositoryViewList"
}
diff --git a/conf/defaults.ini b/conf/defaults.ini
index cefd01bc79346..8e8fa0dedfa8f 100644
--- a/conf/defaults.ini
+++ b/conf/defaults.ini
@@ -2451,6 +2451,16 @@ max_file_size = 5242880
# host. Analogous to [rendering] callback_url for the image renderer plugin.
public_root_url =
+# Resources that can be managed from the UI through provisioning, comma-separated, each as
+# "<group>/<Kind>[:cap...]". The API version and plural resource are resolved at runtime via
+# discovery, so only the group and kind are configured. Capabilities (all default to off):
+# folder - folder-scoped; carries the folder annotation on write (else org-scoped)
+# skipvalidation - skip validation on write (else validated)
+# disabled - declared but not acted on; still surfaced on the settings endpoint
+# Adding or enabling a resource is a config change. Library panels and playlists are declared
+# but disabled by default.
+resources = folder.grafana.app/Folder:folder, dashboard.grafana.app/Dashboard:folder, dashboard.grafana.app/LibraryPanel:folder:disabled, playlist.grafana.app/Playlist:disabled
+
#################################### Unified Storage ####################################
[unified_storage]
# index_path is the path where unified storage can store its index files for search.
diff --git a/packages/grafana-api-clients/src/clients/rtkq/provisioning/v0alpha1/endpoints.gen.ts b/packages/grafana-api-clients/src/clients/rtkq/provisioning/v0alpha1/endpoints.gen.ts
index 708f3aa5682f7..97454f720da64 100644
--- a/packages/grafana-api-clients/src/clients/rtkq/provisioning/v0alpha1/endpoints.gen.ts
+++ b/packages/grafana-api-clients/src/clients/rtkq/provisioning/v0alpha1/endpoints.gen.ts
@@ -2285,6 +2285,14 @@ export type WebhookResponse = {
/** Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds */
kind?: string;
};
+export type SupportedResource = {
+ /** Disabled reports whether the resource is declared but not acted on by provisioning. Active resources omit this field. */
+ disabled?: boolean;
+ /** Group is the API group of the resource (e.g. "dashboard.grafana.app"). */
+ group: string;
+ /** Kind is the kind of the resource (e.g. "Dashboard"). */
+ kind: string;
+};
export type RepositoryView = {
/** For git, this is the target branch */
branch?: string;
@@ -2327,6 +2335,8 @@ export type RepositoryViewList = {
apiVersion?: string;
/** AvailableRepositoryTypes is the list of repository types supported in this instance (e.g. git, bitbucket, github, etc) */
availableRepositoryTypes?: ('bitbucket' | 'git' | 'github' | 'githubEnterprise' | 'gitlab' | 'local')[];
+ /** AvailableResources is the list of resource types declared for provisioning in this instance, including disabled ones (see SupportedResource.Disabled). */
+ availableResources?: SupportedResource[];
items: RepositoryView[];
/** Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds */
kind?: string;
diff --git a/packages/grafana-openapi/src/apis/provisioning.grafana.app-v0alpha1.json b/packages/grafana-openapi/src/apis/provisioning.grafana.app-v0alpha1.json
index 1cfa8a0b510ee..3df59e07237e7 100644
--- a/packages/grafana-openapi/src/apis/provisioning.grafana.app-v0alpha1.json
+++ b/packages/grafana-openapi/src/apis/provisioning.grafana.app-v0alpha1.json
@@ -5553,6 +5553,17 @@
"enum": ["bitbucket", "git", "github", "githubEnterprise", "gitlab", "local"]
}
},
+ "availableResources": {
+ "description": "AvailableResources is the list of resource types declared for provisioning in this instance, including disabled ones (see SupportedResource.Disabled).",
+ "type": "array",
+ "items": {
+ "allOf": [
+ {
+ "$ref": "#/components/schemas/SupportedResource"
+ }
+ ]
+ }
+ },
"items": {
"type": "array",
"items": {
@@ -5945,6 +5956,27 @@
}
}
},
+ "SupportedResource": {
+ "description": "SupportedResource describes a resource type declared for provisioning. A resource is identified by its group and kind; the API version and plural resource are resolved at runtime via discovery, so they are not part of this descriptor.",
+ "type": "object",
+ "required": ["group", "kind"],
+ "properties": {
+ "disabled": {
+ "description": "Disabled reports whether the resource is declared but not acted on by provisioning. Active resources omit this field.",
+ "type": "boolean"
+ },
+ "group": {
+ "description": "Group is the API group of the resource (e.g. \"dashboard.grafana.app\").",
+ "type": "string",
+ "default": ""
+ },
+ "kind": {
+ "description": "Kind is the kind of the resource (e.g. \"Dashboard\").",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
"SyncJobOptions": {
"type": "object",
"required": ["incremental"],
diff --git a/packages/grafana-openapi/src/apis/provisioning.grafana.app-v1beta1.json b/packages/grafana-openapi/src/apis/provisioning.grafana.app-v1beta1.json
index 1f2e7914f05a8..b10c78f50ec9d 100644
--- a/packages/grafana-openapi/src/apis/provisioning.grafana.app-v1beta1.json
+++ b/packages/grafana-openapi/src/apis/provisioning.grafana.app-v1beta1.json
@@ -5169,6 +5169,17 @@
"enum": ["bitbucket", "git", "github", "githubEnterprise", "gitlab", "local"]
}
},
+ "availableResources": {
+ "description": "AvailableResources is the list of resource types declared for provisioning in this instance, including disabled ones (see SupportedResource.Disabled).",
+ "type": "array",
+ "items": {
+ "allOf": [
+ {
+ "$ref": "#/components/schemas/SupportedResource"
+ }
+ ]
+ }
+ },
"items": {
"type": "array",
"items": {
@@ -5496,6 +5507,27 @@
}
}
},
+ "SupportedResource": {
+ "description": "SupportedResource describes a resource type declared for provisioning. A resource is identified by its group and kind; the API version and plural resource are resolved at runtime via discovery, so they are not part of this descriptor.",
+ "type": "object",
+ "required": ["group", "kind"],
+ "properties": {
+ "disabled": {
+ "description": "Disabled reports whether the resource is declared but not acted on by provisioning. Active resources omit this field.",
+ "type": "boolean"
+ },
+ "group": {
+ "description": "Group is the API group of the resource (e.g. \"dashboard.grafana.app\").",
+ "type": "string",
+ "default": ""
+ },
+ "kind": {
+ "description": "Kind is the kind of the resource (e.g. \"Dashboard\").",
+ "type": "string",
+ "default": ""
+ }
+ }
+ },
"SyncJobOptions": {
"type": "object",
"required": ["incremental"],
diff --git a/pkg/operators/provisioning/config.go b/pkg/operators/provisioning/config.go
index afecfac39e21a..c84dd93f0e55b 100644
--- a/pkg/operators/provisioning/config.go
+++ b/pkg/operators/provisioning/config.go
@@ -92,6 +92,7 @@ type ControllerConfig struct {
// provisioning_server_public_url =
// dashboards_server_url =
// folders_server_url =
+// aggregated_server_url =
// folders_api_version =
// tls_insecure =
// tls_cert_file =
@@ -209,11 +210,42 @@ func (c *ControllerConfig) Clients() (resources.ClientFactory, error) {
return nil, fmt.Errorf("folders_server_url is required in [operator] section")
}
provisioningServerURL := operatorSec.Key("provisioning_server_url").String()
+ // aggregated_server_url serves resource groups that do not have a dedicated server URL
+ // (e.g. newly provisionable kinds in their own API group). Dashboards and folders keep
+ // their dedicated URLs for backwards compatibility.
+ aggregatedServerURL := operatorSec.Key("aggregated_server_url").String()
apiServerURLs := map[string]string{
resources.DashboardResource.Group: dashboardsServerURL,
resources.FolderResource.Group: foldersServerURL,
provisioning.GROUP: provisioningServerURL,
}
+
+ supportedResources, err := resources.ParseSupportedResources(c.Settings.ProvisioningResources)
+ if err != nil {
+ return nil, fmt.Errorf("invalid [provisioning] resources configuration: %w", err)
+ }
+
+ // Dashboards and folders have dedicated server URLs; everything else is served by the
+ // aggregated API server. Skip the built-in groups, then ensure every other active
+ // resource's group resolves to the aggregated server — failing loudly if a resource needs
+ // it and it is unset, rather than hitting "no clients provider for group" at request time.
+ for _, r := range supportedResources {
+ if !r.IsActive() {
+ continue
+ }
+ switch r.Group {
+ case resources.DashboardResource.Group, resources.FolderResource.Group, provisioning.GROUP:
+ continue // built-in groups with dedicated server URLs
+ }
+ if _, ok := apiServerURLs[r.Group]; ok {
+ continue
+ }
+ if aggregatedServerURL == "" {
+ return nil, fmt.Errorf("aggregated_server_url is required in [operator] section to serve resource %s/%s", r.Group, r.Kind)
+ }
+ apiServerURLs[r.Group] = aggregatedServerURL
+ }
+
configProviders := make(map[string]apiserver.RestConfigProvider)
tlsConfigForTransport, err := rest.TLSConfigFor(&rest.Config{TLSClientConfig: tlsConfig})
@@ -247,7 +279,7 @@ func (c *ControllerConfig) Clients() (resources.ClientFactory, error) {
configProviders[group] = NewDirectConfigProvider(config)
}
- clients := resources.NewClientFactoryForMultipleAPIServers(configProviders)
+ clients := resources.NewClientFactoryForMultipleAPIServers(configProviders, supportedResources...)
c.clients = clients
return clients, nil
}
diff --git a/pkg/registry/apis/provisioning/files.go b/pkg/registry/apis/provisioning/files.go
index 02d73188e0184..4ccb9a3e0f3a5 100644
--- a/pkg/registry/apis/provisioning/files.go
+++ b/pkg/registry/apis/provisioning/files.go
@@ -183,7 +183,7 @@ func (c *filesConnector) createDualReadWriter(ctx context.Context, repo reposito
}
folders := resources.NewFolderManager(readWriter, folderClient, resources.NewEmptyFolderTree(), folderGVK, resources.WithFolderMetadataEnabled(c.folderMetadataEnabled))
- authorizer := resources.NewAuthorizer(repo.Config(), readWriter, c.access, c.folderMetadataEnabled)
+ authorizer := resources.NewAuthorizer(repo.Config(), readWriter, c.access, clients, c.folderMetadataEnabled)
return resources.NewDualReadWriter(readWriter, parser, folders, authorizer, c.folderMetadataEnabled), authorizer, nil
}
diff --git a/pkg/registry/apis/provisioning/files_test.go b/pkg/registry/apis/provisioning/files_test.go
index 92e9823e75cf6..5d402afeece55 100644
--- a/pkg/registry/apis/provisioning/files_test.go
+++ b/pkg/registry/apis/provisioning/files_test.go
@@ -515,7 +515,7 @@ func TestHandleGetRawFile(t *testing.T) {
},
}
mockReadWriter.EXPECT().Config().Return(repo).Maybe()
- authorizer := resources.NewAuthorizer(repo, mockReadWriter, mockAccess, false)
+ authorizer := resources.NewAuthorizer(repo, mockReadWriter, mockAccess, resources.NewMockResourceClients(t), false)
if tt.readError != nil {
mockReadWriter.EXPECT().Read(mock.Anything, tt.path, "").Return(nil, tt.readError)
@@ -568,7 +568,7 @@ func TestHandleGetRawFile_FolderScopedAuth(t *testing.T) {
Check(mock.Anything, mock.Anything, mock.Anything).
Return(apierrors.NewForbidden(provisioningapi.RepositoryResourceInfo.GroupResource(), "team-a", errors.New("denied")))
- authorizer := resources.NewAuthorizer(repo, mockReadWriter, mockAccess, false)
+ authorizer := resources.NewAuthorizer(repo, mockReadWriter, mockAccess, resources.NewMockResourceClients(t), false)
connector := &filesConnector{access: mockAccess}
_, err := connector.handleGetRawFile(
@@ -612,7 +612,7 @@ func TestHandleGetRawFile_MaxFileSize(t *testing.T) {
mockAccess.EXPECT().Check(mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe()
mockReadWriter.EXPECT().Config().Return(repo).Maybe()
- authorizer := resources.NewAuthorizer(repo, mockReadWriter, mockAccess, false)
+ authorizer := resources.NewAuthorizer(repo, mockReadWriter, mockAccess, resources.NewMockResourceClients(t), false)
mockReadWriter.EX
... [truncated]