diff --git a/pkg/api/api.go b/pkg/api/api.go index 61ced28f276..bb4aa87dc5d 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -116,6 +116,7 @@ func (hs *HTTPServer) registerRoutes() { r.Get("/admin/orgs", authorizeInOrg(ac.UseGlobalOrg, ac.OrgsAccessEvaluator), hs.Index) r.Get("/admin/orgs/edit/:id", authorizeInOrg(ac.UseGlobalOrg, ac.OrgsAccessEvaluator), hs.Index) r.Get("/admin/stats", authorize(ac.EvalPermission(ac.ActionServerStatsRead)), hs.Index) + r.Get("/admin/provisioning", reqOrgAdmin, hs.Index) if hs.Features.IsEnabledGlobally(featuremgmt.FlagOnPremToCloudMigrations) { r.Get("/admin/migrate-to-cloud", authorize(cloudmigration.MigrationAssistantAccess), hs.Index) @@ -156,6 +157,7 @@ func (hs *HTTPServer) registerRoutes() { r.Get("/dashboard/script/*", reqSignedIn, hs.Index) r.Get("/dashboard/new", reqSignedIn, hs.Index) r.Get("/dashboard-solo/snapshot/*", hs.Index) + r.Get("/dashboard/provisioning/*", reqSignedIn, hs.Index) r.Get("/d-solo/:uid/:slug", reqSignedIn, hs.Index) r.Get("/d-solo/:uid", reqSignedIn, hs.Index) r.Get("/dashboard-solo/script/*", reqSignedIn, hs.Index) diff --git a/pkg/apis/provisioning/v0alpha1/types.go b/pkg/apis/provisioning/v0alpha1/types.go index 170b655d999..1e32879b390 100644 --- a/pkg/apis/provisioning/v0alpha1/types.go +++ b/pkg/apis/provisioning/v0alpha1/types.go @@ -50,6 +50,13 @@ type GitHubRepositoryConfig struct { // Whether we should show dashboard previews for pull requests. // By default, this is false (i.e. we will not create previews). GenerateDashboardPreviews bool `json:"generateDashboardPreviews,omitempty"` + + // Path is the subdirectory for the Grafana data. If specified, Grafana will ignore anything that is outside this directory in the repository. + // This is usually something like `grafana/`. Trailing and leading slash are not required. They are always added when needed. + // The path is relative to the root of the repository, regardless of the leading slash. + // + // When specifying something like `grafana-`, we will not look for `grafana-*`; we will only look for files under the directory `/grafana-/`. That means `/grafana-example.json` would not be found. + Path string `json:"path,omitempty"` } // RepositoryType defines the types of Repository diff --git a/pkg/apis/provisioning/v0alpha1/zz_generated.openapi.go b/pkg/apis/provisioning/v0alpha1/zz_generated.openapi.go index ec6e3c0cdbc..571f26b2b27 100644 --- a/pkg/apis/provisioning/v0alpha1/zz_generated.openapi.go +++ b/pkg/apis/provisioning/v0alpha1/zz_generated.openapi.go @@ -274,6 +274,13 @@ func schema_pkg_apis_provisioning_v0alpha1_GitHubRepositoryConfig(ref common.Ref Format: "", }, }, + "path": { + SchemaProps: spec.SchemaProps{ + Description: "Path is the subdirectory for the Grafana data. If specified, Grafana will ignore anything that is outside this directory in the repository. This is usually something like `grafana/`. Trailing and leading slash are not required. They are always added when needed. The path is relative to the root of the repository, regardless of the leading slash.\n\nWhen specifying something like `grafana-`, we will not look for `grafana-*`; we will only look for files under the directory `/grafana-/`. That means `/grafana-example.json` would not be found.", + Type: []string{"string"}, + Format: "", + }, + }, }, Required: []string{"branch"}, }, diff --git a/pkg/generated/applyconfiguration/provisioning/v0alpha1/githubrepositoryconfig.go b/pkg/generated/applyconfiguration/provisioning/v0alpha1/githubrepositoryconfig.go index e3cc1f0829c..89b2b9893a8 100644 --- a/pkg/generated/applyconfiguration/provisioning/v0alpha1/githubrepositoryconfig.go +++ b/pkg/generated/applyconfiguration/provisioning/v0alpha1/githubrepositoryconfig.go @@ -12,6 +12,7 @@ type GitHubRepositoryConfigApplyConfiguration struct { Token *string `json:"token,omitempty"` EncryptedToken []byte `json:"encryptedToken,omitempty"` GenerateDashboardPreviews *bool `json:"generateDashboardPreviews,omitempty"` + Path *string `json:"path,omitempty"` } // GitHubRepositoryConfigApplyConfiguration constructs a declarative configuration of the GitHubRepositoryConfig type for use with @@ -61,3 +62,11 @@ func (b *GitHubRepositoryConfigApplyConfiguration) WithGenerateDashboardPreviews b.GenerateDashboardPreviews = &value return b } + +// WithPath sets the Path field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Path field is set to the value of the last call. +func (b *GitHubRepositoryConfigApplyConfiguration) WithPath(value string) *GitHubRepositoryConfigApplyConfiguration { + b.Path = &value + return b +} diff --git a/pkg/services/navtree/navtreeimpl/admin.go b/pkg/services/navtree/navtreeimpl/admin.go index 9bc0b500130..c2a4ebd9406 100644 --- a/pkg/services/navtree/navtreeimpl/admin.go +++ b/pkg/services/navtree/navtreeimpl/admin.go @@ -52,15 +52,6 @@ func (s *ServiceImpl) getAdminNode(c *contextmodel.ReqContext) (*navtree.NavLink Icon: "toggle-on", }) } - if hasAccess(ac.EvalPermission(ac.ActionSettingsRead, ac.ScopeSettingsAll)) && s.features.IsEnabled(ctx, featuremgmt.FlagStorage) { - generalNodeLinks = append(generalNodeLinks, &navtree.NavLink{ - Text: "Storage", - Id: "storage", - SubTitle: "Manage file storage", - Icon: "cube", - Url: s.cfg.AppSubURL + "/admin/storage", - }) - } if hasAccess(cloudmigration.MigrationAssistantAccess) && s.features.IsEnabled(ctx, featuremgmt.FlagOnPremToCloudMigrations) { generalNodeLinks = append(generalNodeLinks, &navtree.NavLink{ Text: "Migrate to Grafana Cloud", @@ -69,6 +60,14 @@ func (s *ServiceImpl) getAdminNode(c *contextmodel.ReqContext) (*navtree.NavLink Url: s.cfg.AppSubURL + "/admin/migrate-to-cloud", }) } + if hasAccess(ac.EvalPermission(ac.ActionSettingsRead, ac.ScopeSettingsAll)) && s.features.IsEnabled(ctx, featuremgmt.FlagProvisioning) { + generalNodeLinks = append(generalNodeLinks, &navtree.NavLink{ + Text: "Provisioning", + Id: "provisioning", + SubTitle: "Manage resources from remote repositories", + Url: s.cfg.AppSubURL + "/admin/provisioning", + }) + } generalNode := &navtree.NavLink{ Text: "General",