K8s/Folders: Use v1beta1 and app-sdk based spec (#103975)

pull/103966/head
Ryan McKinley 2 months ago committed by GitHub
parent acfd998fa6
commit 0283c98e30
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 1
      .github/CODEOWNERS
  2. 1
      Dockerfile
  3. 2
      Makefile
  4. 29
      apps/folder/Makefile
  5. 29
      apps/folder/go.mod
  6. 64
      apps/folder/go.sum
  7. 4
      apps/folder/kinds/cue.mod/module.cue
  8. 27
      apps/folder/kinds/folder.cue
  9. 9
      apps/folder/kinds/manifest.cue
  10. 18
      apps/folder/pkg/apis/folder/v1beta1/constants.go
  11. 5
      apps/folder/pkg/apis/folder/v1beta1/doc.go
  12. 28
      apps/folder/pkg/apis/folder/v1beta1/folder_codec_gen.go
  13. 28
      apps/folder/pkg/apis/folder/v1beta1/folder_metadata_gen.go
  14. 319
      apps/folder/pkg/apis/folder/v1beta1/folder_object_gen.go
  15. 34
      apps/folder/pkg/apis/folder/v1beta1/folder_schema_gen.go
  16. 14
      apps/folder/pkg/apis/folder/v1beta1/folder_spec_gen.go
  17. 3
      apps/folder/pkg/apis/folder/v1beta1/folder_status_gen.go
  18. 6
      apps/folder/pkg/apis/folder/v1beta1/register.go
  19. 32
      apps/folder/pkg/apis/folder/v1beta1/types.go
  20. 98
      apps/folder/pkg/apis/folder/v1beta1/zz_generated.deepcopy.go
  21. 2
      apps/folder/pkg/apis/folder/v1beta1/zz_generated.defaults.go
  22. 202
      apps/folder/pkg/apis/folder/v1beta1/zz_generated.openapi.go
  23. 3
      apps/folder/pkg/apis/folder/v1beta1/zz_generated.openapi_violation_exceptions.list
  24. 43
      apps/folder/pkg/apis/folder_manifest.go
  25. 2
      go.mod
  26. 4
      go.sum
  27. 2
      go.work
  28. 8
      go.work.sum
  29. 1
      hack/update-codegen.sh
  30. 2
      pkg/api/folder_test.go
  31. 6
      pkg/apis/folder/v1/doc.go
  32. 206
      pkg/apis/folder/v1/zz_generated.deepcopy.go
  33. 2
      pkg/apis/folder/v1/zz_generated.openapi_violation_exceptions.list
  34. 5
      pkg/cmd/grafana-cli/commands/datamigrations/to_unified_storage.go
  35. 4
      pkg/registry/apis/dashboard/legacy/migrate.go
  36. 2
      pkg/registry/apis/dashboard/legacysearcher/search_client.go
  37. 2
      pkg/registry/apis/dashboard/register.go
  38. 2
      pkg/registry/apis/dashboard/search.go
  39. 7
      pkg/registry/apis/folders/authorizer_test.go
  40. 17
      pkg/registry/apis/folders/conversions.go
  41. 2
      pkg/registry/apis/folders/folder_storage.go
  42. 13
      pkg/registry/apis/folders/folder_storage_test.go
  43. 10
      pkg/registry/apis/folders/legacy_storage.go
  44. 2
      pkg/registry/apis/folders/legacy_storage_test.go
  45. 2
      pkg/registry/apis/folders/register.go
  46. 46
      pkg/registry/apis/folders/register_test.go
  47. 2
      pkg/registry/apis/folders/sub_access.go
  48. 2
      pkg/registry/apis/folders/sub_count.go
  49. 11
      pkg/registry/apis/folders/sub_parent_test.go
  50. 8
      pkg/registry/apis/folders/sub_parents.go
  51. 2
      pkg/registry/apis/provisioning/controller/finalizers.go
  52. 2
      pkg/registry/apis/provisioning/register.go
  53. 2
      pkg/registry/apis/provisioning/resources/client.go
  54. 2
      pkg/registry/apis/provisioning/resources/folders.go
  55. 2
      pkg/registry/apis/provisioning/resources/object.go
  56. 2
      pkg/registry/apis/provisioning/resources/tree.go
  57. 8
      pkg/services/authn/authnimpl/service_test.go
  58. 4
      pkg/services/authz/rbac/store/folder_store.go
  59. 4
      pkg/services/authz/zanzana/common/info.go
  60. 2
      pkg/services/authz/zanzana/translations.go
  61. 2
      pkg/services/dashboards/service/dashboard_service.go
  62. 16
      pkg/services/folder/folderimpl/conversions_test.go
  63. 2
      pkg/services/folder/folderimpl/folder.go
  64. 2
      pkg/services/folder/folderimpl/folder_unifiedstorage.go
  65. 18
      pkg/services/folder/folderimpl/folder_unifiedstorage_test.go
  66. 2
      pkg/services/folder/folderimpl/unifiedstore.go
  67. 2
      pkg/storage/legacysql/dualwrite/utils.go
  68. 2
      pkg/storage/legacysql/dualwrite/utils_test.go
  69. 2
      pkg/storage/unified/README.md
  70. 4
      pkg/storage/unified/apistore/go.mod
  71. 4
      pkg/storage/unified/apistore/go.sum
  72. 10
      pkg/storage/unified/resource/go.mod
  73. 2
      pkg/storage/unified/resource/go.sum
  74. 5
      pkg/storage/unified/resource/search.go
  75. 2
      pkg/storage/unified/resource/testdata/folder-resource.json
  76. 2
      pkg/storage/unified/resource/testdata/folder-resource2.json
  77. 2
      pkg/storage/unified/search/testdata/doc/folder-aaa.json
  78. 2
      pkg/storage/unified/search/testdata/doc/folder-bbb.json
  79. 2
      pkg/tests/apis/dashboard/integration/api_validation_test.go
  80. 102
      pkg/tests/apis/folder/folders_test.go
  81. 2
      pkg/tests/apis/folder/testdata/folder-generate.yaml
  82. 2
      pkg/tests/apis/folder/testdata/folder-test-create.yaml
  83. 2
      pkg/tests/apis/folder/testdata/folder-test-replace.yaml
  84. 1822
      pkg/tests/apis/openapi_snapshots/folder.grafana.app-v1.json
  85. 196
      pkg/tests/apis/openapi_snapshots/folder.grafana.app-v1beta1.json
  86. 2
      pkg/tests/apis/openapi_test.go
  87. 2
      pkg/tests/apis/provisioning/helper_test.go
  88. 11
      public/app/api/clients/folder/endpoints.gen.ts
  89. 3
      public/app/api/clients/folder/index.ts
  90. 2
      scripts/generate-rtk-apis.ts

@ -73,6 +73,7 @@
/apps/alerting/ @grafana/alerting-backend
/apps/dashboard/ @grafana/grafana-app-platform-squad @grafana/dashboards-squad
/apps/folder/ @grafana/grafana-app-platform-squad
/apps/playlist/ @grafana/grafana-app-platform-squad
/apps/investigations/ @fcjack @matryer @svennergr
/apps/advisor/ @grafana/plugins-platform-backend

@ -85,6 +85,7 @@ COPY apps/playlist apps/playlist
COPY apps/investigations apps/investigations
COPY apps/advisor apps/advisor
COPY apps/dashboard apps/dashboard
COPY apps/folder apps/folder
COPY apps apps
COPY kindsv2 kindsv2
COPY apps/alerting/notifications apps/alerting/notifications

@ -165,7 +165,7 @@ gen-cuev2: ## Do all CUE code generation
# For now, we want to use an explicit list of apps to generate code for.
#
# APPS_DIRS=$(shell find ./apps -mindepth 1 -maxdepth 1 -type d | sort)
APPS_DIRS := ./apps/dashboard
APPS_DIRS := ./apps/dashboard ./apps/folder
.PHONY: gen-apps
gen-apps: ## Generate code for Grafana App SDK apps

@ -0,0 +1,29 @@
APP_SDK_VERSION := v0.35.1
APP_SDK_DIR := $(shell go env GOPATH)/bin/app-sdk-$(APP_SDK_VERSION)
APP_SDK_BIN := $(APP_SDK_DIR)/grafana-app-sdk
.PHONY: install-app-sdk
install-app-sdk: $(APP_SDK_BIN) ## Install the Grafana App SDK
$(APP_SDK_BIN):
@echo "Installing Grafana App SDK version $(APP_SDK_VERSION)"
@mkdir -p $(APP_SDK_DIR)
# The only way to install specific versions of binaries using `go install`
# is by setting GOBIN to the directory you want to install the binary to.
GOBIN=$(APP_SDK_DIR) go install github.com/grafana/grafana-app-sdk/cmd/grafana-app-sdk@$(APP_SDK_VERSION)
@touch $@
.PHONY: update-app-sdk
update-app-sdk: ## Update the Grafana App SDK dependency in go.mod
go get github.com/grafana/grafana-app-sdk@$(APP_SDK_VERSION)
go mod tidy
.PHONY: generate
generate: install-app-sdk update-app-sdk ## Run Grafana App SDK code generation
@$(APP_SDK_BIN) generate \
--source=./kinds/ \
--gogenpath=./pkg/apis \
--grouping=group \
--defencoding=none \
--genoperatorstate=false \
--noschemasinmanifest

@ -1,36 +1,57 @@
module github.com/grafana/grafana/pkg/apis/folder
module github.com/grafana/grafana/apps/folder
go 1.24.2
require (
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250401081501-6af5fbf3fff0
github.com/grafana/grafana-app-sdk v0.35.1
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250414114055-2b279efe15bf
k8s.io/apimachinery v0.32.3
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff
)
require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
github.com/getkin/kin-openapi v0.131.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/jsonreference v0.21.0 // indirect
github.com/go-openapi/swag v0.23.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/google/gnostic-models v0.6.9 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/grafana/grafana-app-sdk/logging v0.35.1 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.18.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/rogpeppe/go-internal v1.14.1 // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 // indirect
github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 // indirect
github.com/perimeterx/marshmallow v1.1.5 // indirect
github.com/prometheus/client_golang v1.21.1 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.63.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/x448/float16 v0.8.4 // indirect
go.opentelemetry.io/otel v1.35.0 // indirect
go.opentelemetry.io/otel/trace v1.35.0 // indirect
golang.org/x/net v0.39.0 // indirect
golang.org/x/oauth2 v0.29.0 // indirect
golang.org/x/sys v0.32.0 // indirect
golang.org/x/term v0.31.0 // indirect
golang.org/x/text v0.24.0 // indirect
golang.org/x/time v0.11.0 // indirect
google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/client-go v0.32.3 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect

@ -1,3 +1,7 @@
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
@ -6,6 +10,8 @@ github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxER
github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
github.com/getkin/kin-openapi v0.131.0 h1:NO2UeHnFKRYhZ8wg6Nyh5Cq7dHk4suQQr72a4pMrDxE=
github.com/getkin/kin-openapi v0.131.0/go.mod h1:3OlG51PCYNsPByuiMB0t4fjnNlIDnaEDsjiKUV8nL58=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
@ -14,8 +20,12 @@ github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF
github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw=
github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
@ -24,18 +34,28 @@ github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250401081501-6af5fbf3fff0 h1:/MtKK3BUWqLJVkoFQViNvD5BmblGlVwpOScEtLLpexU=
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250401081501-6af5fbf3fff0/go.mod h1:uju5OyW1BopywSF1jjIHei0L0/QIi4vn/EQ1ys+E6aI=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grafana/grafana-app-sdk v0.35.1 h1:zEXubzsQrxGBOzXJJMBwhEClC/tvPi0sfK7NGmlX3RI=
github.com/grafana/grafana-app-sdk v0.35.1/go.mod h1:Zx5MkVppYK+ElSDUAR6+fjzOVo6I/cIgk+ty+LmNOxI=
github.com/grafana/grafana-app-sdk/logging v0.35.1 h1:taVpl+RoixTYl0JBJGhH+fPVmwA9wvdwdzJTZsv9buM=
github.com/grafana/grafana-app-sdk/logging v0.35.1/go.mod h1:Y/bvbDhBiV/tkIle9RW49pgfSPIPSON8Q4qjx3pyqDk=
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250414114055-2b279efe15bf h1:BQ5z396ADz8Er+oeXPI3qjNGsA14tp6FJb3hnHsOT4k=
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250414114055-2b279efe15bf/go.mod h1:kzjpaBODMbCSS2kvAnV43Pwxoq4lOxrgw/TGKqq8oTA=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@ -43,9 +63,29 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 h1:G7ERwszslrBzRxj//JalHPu/3yz+De2J+4aLtSRlHiY=
github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037/go.mod h1:2bpvgLBZEtENV5scfDFEtB/5+1M4hkQhDQrccEJ/qGw=
github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 h1:bQx3WeLcUWy+RletIKwUIt4x3t8n2SxavmoclizMb8c=
github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o=
github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s=
github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.21.1 h1:DOvXXTqVzvkIewV/CDPFdejpMCGeMcbGCQ8YOmu+Ibk=
github.com/prometheus/client_golang v1.21.1/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k=
github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
@ -54,10 +94,16 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
@ -69,16 +115,24 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
golang.org/x/oauth2 v0.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98=
golang.org/x/oauth2 v0.29.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o=
golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
@ -92,12 +146,18 @@ google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls=
k8s.io/api v0.32.3/go.mod h1:2wEDTXADtm/HA7CCMD8D8bK4yuBUptzaRhYcYEEYA3k=
k8s.io/apimachinery v0.32.3 h1:JmDuDarhDmA/Li7j3aPrwhpNBA94Nvk5zLeOge9HH1U=
k8s.io/apimachinery v0.32.3/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
k8s.io/client-go v0.32.3 h1:RKPVltzopkSgHS7aS98QdscAgtgah/+zmpAogooIqVU=
k8s.io/client-go v0.32.3/go.mod h1:3v0+3k4IcT9bXTc4V2rt+d2ZPPG700Xy6Oi0Gdl2PaY=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4=

@ -0,0 +1,4 @@
module: "github.com/grafana/grafana/apps/folder/kinds"
language: {
version: "v0.9.0"
}

@ -0,0 +1,27 @@
package folder
folder: {
kind: "Folder"
pluralName: "Folders"
current: "v1beta1"
codegen: {
ts: {
enabled: false // Not sure if it should be enabled or not, currently it is.
}
go: {
enabled: true
}
}
versions: {
"v1beta1": {
schema: {
spec: {
title: string
description?: string
}
status: {} // nothing
}
}
}
}

@ -0,0 +1,9 @@
package folder
manifest: {
appName: "folder"
groupOverride: "folder.grafana.app"
kinds: [
folder,
]
}

@ -0,0 +1,18 @@
package v1beta1
import "k8s.io/apimachinery/pkg/runtime/schema"
const (
// Group is the API group used by all kinds in this package
Group = "folder.grafana.app"
// Version is the API version used by all kinds in this package
Version = "v1beta1"
)
var (
// GroupVersion is a schema.GroupVersion consisting of the Group and Version constants for this package
GroupVersion = schema.GroupVersion{
Group: Group,
Version: Version,
}
)

@ -0,0 +1,5 @@
// +k8s:openapi-gen=true
// +k8s:defaulter-gen=TypeMeta
// +groupName=folder.grafana.app
package v1beta1

@ -0,0 +1,28 @@
//
// Code generated by grafana-app-sdk. DO NOT EDIT.
//
package v1beta1
import (
"encoding/json"
"io"
"github.com/grafana/grafana-app-sdk/resource"
)
// FolderJSONCodec is an implementation of resource.Codec for kubernetes JSON encoding
type FolderJSONCodec struct{}
// Read reads JSON-encoded bytes from `reader` and unmarshals them into `into`
func (*FolderJSONCodec) Read(reader io.Reader, into resource.Object) error {
return json.NewDecoder(reader).Decode(into)
}
// Write writes JSON-encoded bytes into `writer` marshaled from `from`
func (*FolderJSONCodec) Write(writer io.Writer, from resource.Object) error {
return json.NewEncoder(writer).Encode(from)
}
// Interface compliance checks
var _ resource.Codec = &FolderJSONCodec{}

@ -0,0 +1,28 @@
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
package v1beta1
import (
time "time"
)
// metadata contains embedded CommonMetadata and can be extended with custom string fields
// TODO: use CommonMetadata instead of redefining here; currently needs to be defined here
// without external reference as using the CommonMetadata reference breaks thema codegen.
type FolderMetadata struct {
UpdateTimestamp time.Time `json:"updateTimestamp"`
CreatedBy string `json:"createdBy"`
Uid string `json:"uid"`
CreationTimestamp time.Time `json:"creationTimestamp"`
DeletionTimestamp *time.Time `json:"deletionTimestamp,omitempty"`
Finalizers []string `json:"finalizers"`
ResourceVersion string `json:"resourceVersion"`
Generation int64 `json:"generation"`
UpdatedBy string `json:"updatedBy"`
Labels map[string]string `json:"labels"`
}
// NewFolderMetadata creates a new FolderMetadata object.
func NewFolderMetadata() *FolderMetadata {
return &FolderMetadata{}
}

@ -0,0 +1,319 @@
//
// Code generated by grafana-app-sdk. DO NOT EDIT.
//
package v1beta1
import (
"fmt"
"github.com/grafana/grafana-app-sdk/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"time"
)
// +k8s:openapi-gen=true
type Folder struct {
metav1.TypeMeta `json:",inline" yaml:",inline"`
metav1.ObjectMeta `json:"metadata" yaml:"metadata"`
// Spec is the spec of the Folder
Spec FolderSpec `json:"spec" yaml:"spec"`
Status FolderStatus `json:"status" yaml:"status"`
}
func (o *Folder) GetSpec() any {
return o.Spec
}
func (o *Folder) SetSpec(spec any) error {
cast, ok := spec.(FolderSpec)
if !ok {
return fmt.Errorf("cannot set spec type %#v, not of type Spec", spec)
}
o.Spec = cast
return nil
}
func (o *Folder) GetSubresources() map[string]any {
return map[string]any{
"status": o.Status,
}
}
func (o *Folder) GetSubresource(name string) (any, bool) {
switch name {
case "status":
return o.Status, true
default:
return nil, false
}
}
func (o *Folder) SetSubresource(name string, value any) error {
switch name {
case "status":
cast, ok := value.(FolderStatus)
if !ok {
return fmt.Errorf("cannot set status type %#v, not of type FolderStatus", value)
}
o.Status = cast
return nil
default:
return fmt.Errorf("subresource '%s' does not exist", name)
}
}
func (o *Folder) GetStaticMetadata() resource.StaticMetadata {
gvk := o.GroupVersionKind()
return resource.StaticMetadata{
Name: o.ObjectMeta.Name,
Namespace: o.ObjectMeta.Namespace,
Group: gvk.Group,
Version: gvk.Version,
Kind: gvk.Kind,
}
}
func (o *Folder) SetStaticMetadata(metadata resource.StaticMetadata) {
o.Name = metadata.Name
o.Namespace = metadata.Namespace
o.SetGroupVersionKind(schema.GroupVersionKind{
Group: metadata.Group,
Version: metadata.Version,
Kind: metadata.Kind,
})
}
func (o *Folder) GetCommonMetadata() resource.CommonMetadata {
dt := o.DeletionTimestamp
var deletionTimestamp *time.Time
if dt != nil {
deletionTimestamp = &dt.Time
}
// Legacy ExtraFields support
extraFields := make(map[string]any)
if o.Annotations != nil {
extraFields["annotations"] = o.Annotations
}
if o.ManagedFields != nil {
extraFields["managedFields"] = o.ManagedFields
}
if o.OwnerReferences != nil {
extraFields["ownerReferences"] = o.OwnerReferences
}
return resource.CommonMetadata{
UID: string(o.UID),
ResourceVersion: o.ResourceVersion,
Generation: o.Generation,
Labels: o.Labels,
CreationTimestamp: o.CreationTimestamp.Time,
DeletionTimestamp: deletionTimestamp,
Finalizers: o.Finalizers,
UpdateTimestamp: o.GetUpdateTimestamp(),
CreatedBy: o.GetCreatedBy(),
UpdatedBy: o.GetUpdatedBy(),
ExtraFields: extraFields,
}
}
func (o *Folder) SetCommonMetadata(metadata resource.CommonMetadata) {
o.UID = types.UID(metadata.UID)
o.ResourceVersion = metadata.ResourceVersion
o.Generation = metadata.Generation
o.Labels = metadata.Labels
o.CreationTimestamp = metav1.NewTime(metadata.CreationTimestamp)
if metadata.DeletionTimestamp != nil {
dt := metav1.NewTime(*metadata.DeletionTimestamp)
o.DeletionTimestamp = &dt
} else {
o.DeletionTimestamp = nil
}
o.Finalizers = metadata.Finalizers
if o.Annotations == nil {
o.Annotations = make(map[string]string)
}
if !metadata.UpdateTimestamp.IsZero() {
o.SetUpdateTimestamp(metadata.UpdateTimestamp)
}
if metadata.CreatedBy != "" {
o.SetCreatedBy(metadata.CreatedBy)
}
if metadata.UpdatedBy != "" {
o.SetUpdatedBy(metadata.UpdatedBy)
}
// Legacy support for setting Annotations, ManagedFields, and OwnerReferences via ExtraFields
if metadata.ExtraFields != nil {
if annotations, ok := metadata.ExtraFields["annotations"]; ok {
if cast, ok := annotations.(map[string]string); ok {
o.Annotations = cast
}
}
if managedFields, ok := metadata.ExtraFields["managedFields"]; ok {
if cast, ok := managedFields.([]metav1.ManagedFieldsEntry); ok {
o.ManagedFields = cast
}
}
if ownerReferences, ok := metadata.ExtraFields["ownerReferences"]; ok {
if cast, ok := ownerReferences.([]metav1.OwnerReference); ok {
o.OwnerReferences = cast
}
}
}
}
func (o *Folder) GetCreatedBy() string {
if o.ObjectMeta.Annotations == nil {
o.ObjectMeta.Annotations = make(map[string]string)
}
return o.ObjectMeta.Annotations["grafana.com/createdBy"]
}
func (o *Folder) SetCreatedBy(createdBy string) {
if o.ObjectMeta.Annotations == nil {
o.ObjectMeta.Annotations = make(map[string]string)
}
o.ObjectMeta.Annotations["grafana.com/createdBy"] = createdBy
}
func (o *Folder) GetUpdateTimestamp() time.Time {
if o.ObjectMeta.Annotations == nil {
o.ObjectMeta.Annotations = make(map[string]string)
}
parsed, _ := time.Parse(time.RFC3339, o.ObjectMeta.Annotations["grafana.com/updateTimestamp"])
return parsed
}
func (o *Folder) SetUpdateTimestamp(updateTimestamp time.Time) {
if o.ObjectMeta.Annotations == nil {
o.ObjectMeta.Annotations = make(map[string]string)
}
o.ObjectMeta.Annotations["grafana.com/updateTimestamp"] = updateTimestamp.Format(time.RFC3339)
}
func (o *Folder) GetUpdatedBy() string {
if o.ObjectMeta.Annotations == nil {
o.ObjectMeta.Annotations = make(map[string]string)
}
return o.ObjectMeta.Annotations["grafana.com/updatedBy"]
}
func (o *Folder) SetUpdatedBy(updatedBy string) {
if o.ObjectMeta.Annotations == nil {
o.ObjectMeta.Annotations = make(map[string]string)
}
o.ObjectMeta.Annotations["grafana.com/updatedBy"] = updatedBy
}
func (o *Folder) Copy() resource.Object {
return resource.CopyObject(o)
}
func (o *Folder) DeepCopyObject() runtime.Object {
return o.Copy()
}
func (o *Folder) DeepCopy() *Folder {
cpy := &Folder{}
o.DeepCopyInto(cpy)
return cpy
}
func (o *Folder) DeepCopyInto(dst *Folder) {
dst.TypeMeta.APIVersion = o.TypeMeta.APIVersion
dst.TypeMeta.Kind = o.TypeMeta.Kind
o.ObjectMeta.DeepCopyInto(&dst.ObjectMeta)
o.Spec.DeepCopyInto(&dst.Spec)
o.Status.DeepCopyInto(&dst.Status)
}
// Interface compliance compile-time check
var _ resource.Object = &Folder{}
// +k8s:openapi-gen=true
type FolderList struct {
metav1.TypeMeta `json:",inline" yaml:",inline"`
metav1.ListMeta `json:"metadata" yaml:"metadata"`
Items []Folder `json:"items" yaml:"items"`
}
func (o *FolderList) DeepCopyObject() runtime.Object {
return o.Copy()
}
func (o *FolderList) Copy() resource.ListObject {
cpy := &FolderList{
TypeMeta: o.TypeMeta,
Items: make([]Folder, len(o.Items)),
}
o.ListMeta.DeepCopyInto(&cpy.ListMeta)
for i := 0; i < len(o.Items); i++ {
if item, ok := o.Items[i].Copy().(*Folder); ok {
cpy.Items[i] = *item
}
}
return cpy
}
func (o *FolderList) GetItems() []resource.Object {
items := make([]resource.Object, len(o.Items))
for i := 0; i < len(o.Items); i++ {
items[i] = &o.Items[i]
}
return items
}
func (o *FolderList) SetItems(items []resource.Object) {
o.Items = make([]Folder, len(items))
for i := 0; i < len(items); i++ {
o.Items[i] = *items[i].(*Folder)
}
}
func (o *FolderList) DeepCopy() *FolderList {
cpy := &FolderList{}
o.DeepCopyInto(cpy)
return cpy
}
func (o *FolderList) DeepCopyInto(dst *FolderList) {
resource.CopyObjectInto(dst, o)
}
// Interface compliance compile-time check
var _ resource.ListObject = &FolderList{}
// Copy methods for all subresource types
// DeepCopy creates a full deep copy of Spec
func (s *FolderSpec) DeepCopy() *FolderSpec {
cpy := &FolderSpec{}
s.DeepCopyInto(cpy)
return cpy
}
// DeepCopyInto deep copies Spec into another Spec object
func (s *FolderSpec) DeepCopyInto(dst *FolderSpec) {
resource.CopyObjectInto(dst, s)
}
// DeepCopy creates a full deep copy of FolderStatus
func (s *FolderStatus) DeepCopy() *FolderStatus {
cpy := &FolderStatus{}
s.DeepCopyInto(cpy)
return cpy
}
// DeepCopyInto deep copies FolderStatus into another FolderStatus object
func (s *FolderStatus) DeepCopyInto(dst *FolderStatus) {
resource.CopyObjectInto(dst, s)
}

@ -0,0 +1,34 @@
//
// Code generated by grafana-app-sdk. DO NOT EDIT.
//
package v1beta1
import (
"github.com/grafana/grafana-app-sdk/resource"
)
// schema is unexported to prevent accidental overwrites
var (
schemaFolder = resource.NewSimpleSchema("folder.grafana.app", "v1beta1", &Folder{}, &FolderList{}, resource.WithKind("Folder"),
resource.WithPlural("folders"), resource.WithScope(resource.NamespacedScope))
kindFolder = resource.Kind{
Schema: schemaFolder,
Codecs: map[resource.KindEncoding]resource.Codec{
resource.KindEncodingJSON: &FolderJSONCodec{},
},
}
)
// Kind returns a resource.Kind for this Schema with a JSON codec
func FolderKind() resource.Kind {
return kindFolder
}
// Schema returns a resource.SimpleSchema representation of Folder
func FolderSchema() *resource.SimpleSchema {
return schemaFolder
}
// Interface compliance checks
var _ resource.Schema = kindFolder

@ -0,0 +1,14 @@
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
package v1beta1
// +k8s:openapi-gen=true
type FolderSpec struct {
Title string `json:"title"`
Description *string `json:"description,omitempty"`
}
// NewFolderSpec creates a new FolderSpec object.
func NewFolderSpec() *FolderSpec {
return &FolderSpec{}
}

@ -0,0 +1,3 @@
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
package v1beta1

@ -1,4 +1,4 @@
package v1
package v1beta1
import (
"fmt"
@ -11,8 +11,8 @@ import (
)
const (
GROUP = "folder.grafana.app"
VERSION = "v1"
GROUP = Group
VERSION = Version
RESOURCE = "folders"
APIVERSION = GROUP + "/" + VERSION
RESOURCEGROUP = RESOURCE + "." + GROUP

@ -1,4 +1,4 @@
package v1
package v1beta1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -6,32 +6,9 @@ import (
"k8s.io/apimachinery/pkg/runtime"
)
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type Folder struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec Spec `json:"spec,omitempty"`
}
type Spec struct {
// Describe the feature toggle
Title string `json:"title"`
// Describe the feature toggle
Description string `json:"description,omitempty"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type FolderList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []Folder `json:"items,omitempty"`
}
// FolderInfoList returns a list of folder references (parents or children)
// Unlike FolderList, each item is not a full k8s object
// +k8s:deepcopy-gen=true
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type FolderInfoList struct {
metav1.TypeMeta `json:",inline"`
@ -62,6 +39,7 @@ type FolderInfo struct {
}
// Access control information for the current user
// +k8s:deepcopy-gen=true
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type FolderAccessInfo struct {
metav1.TypeMeta `json:",inline"`
@ -72,6 +50,7 @@ type FolderAccessInfo struct {
CanDelete bool `json:"canDelete"`
}
// +k8s:deepcopy-gen=true
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type DescendantCounts struct {
metav1.TypeMeta `json:",inline"`
@ -90,3 +69,6 @@ func UnstructuredToDescendantCounts(obj *unstructured.Unstructured) (*Descendant
err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.Object, &res)
return &res, err
}
// Empty stub
type FolderStatus struct{}

@ -0,0 +1,98 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
// SPDX-License-Identifier: AGPL-3.0-only
// Code generated by deepcopy-gen. DO NOT EDIT.
package v1beta1
import (
runtime "k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DescendantCounts) DeepCopyInto(out *DescendantCounts) {
*out = *in
out.TypeMeta = in.TypeMeta
if in.Counts != nil {
in, out := &in.Counts, &out.Counts
*out = make([]ResourceStats, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DescendantCounts.
func (in *DescendantCounts) DeepCopy() *DescendantCounts {
if in == nil {
return nil
}
out := new(DescendantCounts)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *DescendantCounts) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *FolderAccessInfo) DeepCopyInto(out *FolderAccessInfo) {
*out = *in
out.TypeMeta = in.TypeMeta
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FolderAccessInfo.
func (in *FolderAccessInfo) DeepCopy() *FolderAccessInfo {
if in == nil {
return nil
}
out := new(FolderAccessInfo)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *FolderAccessInfo) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *FolderInfoList) DeepCopyInto(out *FolderInfoList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]FolderInfo, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FolderInfoList.
func (in *FolderInfoList) DeepCopy() *FolderInfoList {
if in == nil {
return nil
}
out := new(FolderInfoList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *FolderInfoList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}

@ -5,7 +5,7 @@
// Code generated by defaulter-gen. DO NOT EDIT.
package v1
package v1beta1
import (
runtime "k8s.io/apimachinery/pkg/runtime"

@ -5,7 +5,7 @@
// Code generated by openapi-gen. DO NOT EDIT.
package v1
package v1beta1
import (
common "k8s.io/kube-openapi/pkg/common"
@ -14,18 +14,21 @@ import (
func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition {
return map[string]common.OpenAPIDefinition{
"github.com/grafana/grafana/pkg/apis/folder/v1.DescendantCounts": schema_pkg_apis_folder_v1_DescendantCounts(ref),
"github.com/grafana/grafana/pkg/apis/folder/v1.Folder": schema_pkg_apis_folder_v1_Folder(ref),
"github.com/grafana/grafana/pkg/apis/folder/v1.FolderAccessInfo": schema_pkg_apis_folder_v1_FolderAccessInfo(ref),
"github.com/grafana/grafana/pkg/apis/folder/v1.FolderInfo": schema_pkg_apis_folder_v1_FolderInfo(ref),
"github.com/grafana/grafana/pkg/apis/folder/v1.FolderInfoList": schema_pkg_apis_folder_v1_FolderInfoList(ref),
"github.com/grafana/grafana/pkg/apis/folder/v1.FolderList": schema_pkg_apis_folder_v1_FolderList(ref),
"github.com/grafana/grafana/pkg/apis/folder/v1.ResourceStats": schema_pkg_apis_folder_v1_ResourceStats(ref),
"github.com/grafana/grafana/pkg/apis/folder/v1.Spec": schema_pkg_apis_folder_v1_Spec(ref),
"github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1.DescendantCounts": schema_pkg_apis_folder_v1beta1_DescendantCounts(ref),
"github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1.Folder": schema_pkg_apis_folder_v1beta1_Folder(ref),
"github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1.FolderAccessInfo": schema_pkg_apis_folder_v1beta1_FolderAccessInfo(ref),
"github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1.FolderInfo": schema_pkg_apis_folder_v1beta1_FolderInfo(ref),
"github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1.FolderInfoList": schema_pkg_apis_folder_v1beta1_FolderInfoList(ref),
"github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1.FolderJSONCodec": schema_pkg_apis_folder_v1beta1_FolderJSONCodec(ref),
"github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1.FolderList": schema_pkg_apis_folder_v1beta1_FolderList(ref),
"github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1.FolderMetadata": schema_pkg_apis_folder_v1beta1_FolderMetadata(ref),
"github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1.FolderSpec": schema_pkg_apis_folder_v1beta1_FolderSpec(ref),
"github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1.FolderStatus": schema_pkg_apis_folder_v1beta1_FolderStatus(ref),
"github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1.ResourceStats": schema_pkg_apis_folder_v1beta1_ResourceStats(ref),
}
}
func schema_pkg_apis_folder_v1_DescendantCounts(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_folder_v1beta1_DescendantCounts(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@ -52,7 +55,7 @@ func schema_pkg_apis_folder_v1_DescendantCounts(ref common.ReferenceCallback) co
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/pkg/apis/folder/v1.ResourceStats"),
Ref: ref("github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1.ResourceStats"),
},
},
},
@ -63,11 +66,11 @@ func schema_pkg_apis_folder_v1_DescendantCounts(ref common.ReferenceCallback) co
},
},
Dependencies: []string{
"github.com/grafana/grafana/pkg/apis/folder/v1.ResourceStats"},
"github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1.ResourceStats"},
}
}
func schema_pkg_apis_folder_v1_Folder(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_folder_v1beta1_Folder(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@ -94,20 +97,28 @@ func schema_pkg_apis_folder_v1_Folder(ref common.ReferenceCallback) common.OpenA
},
},
"spec": {
SchemaProps: spec.SchemaProps{
Description: "Spec is the spec of the Folder",
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1.FolderSpec"),
},
},
"status": {
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/pkg/apis/folder/v1.Spec"),
Ref: ref("github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1.FolderStatus"),
},
},
},
Required: []string{"metadata", "spec", "status"},
},
},
Dependencies: []string{
"github.com/grafana/grafana/pkg/apis/folder/v1.Spec", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"},
"github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1.FolderSpec", "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1.FolderStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"},
}
}
func schema_pkg_apis_folder_v1_FolderAccessInfo(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_folder_v1beta1_FolderAccessInfo(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@ -163,7 +174,7 @@ func schema_pkg_apis_folder_v1_FolderAccessInfo(ref common.ReferenceCallback) co
}
}
func schema_pkg_apis_folder_v1_FolderInfo(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_folder_v1beta1_FolderInfo(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@ -214,7 +225,7 @@ func schema_pkg_apis_folder_v1_FolderInfo(ref common.ReferenceCallback) common.O
}
}
func schema_pkg_apis_folder_v1_FolderInfoList(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_folder_v1beta1_FolderInfoList(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@ -256,7 +267,7 @@ func schema_pkg_apis_folder_v1_FolderInfoList(ref common.ReferenceCallback) comm
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/pkg/apis/folder/v1.FolderInfo"),
Ref: ref("github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1.FolderInfo"),
},
},
},
@ -266,11 +277,22 @@ func schema_pkg_apis_folder_v1_FolderInfoList(ref common.ReferenceCallback) comm
},
},
Dependencies: []string{
"github.com/grafana/grafana/pkg/apis/folder/v1.FolderInfo", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"},
"github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1.FolderInfo", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"},
}
}
func schema_pkg_apis_folder_v1beta1_FolderJSONCodec(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "FolderJSONCodec is an implementation of resource.Codec for kubernetes JSON encoding",
Type: []string{"object"},
},
},
}
}
func schema_pkg_apis_folder_v1_FolderList(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_folder_v1beta1_FolderList(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@ -303,55 +325,118 @@ func schema_pkg_apis_folder_v1_FolderList(ref common.ReferenceCallback) common.O
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/pkg/apis/folder/v1.Folder"),
Ref: ref("github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1.Folder"),
},
},
},
},
},
},
Required: []string{"metadata", "items"},
},
},
Dependencies: []string{
"github.com/grafana/grafana/pkg/apis/folder/v1.Folder", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"},
"github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1.Folder", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"},
}
}
func schema_pkg_apis_folder_v1_ResourceStats(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_folder_v1beta1_FolderMetadata(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Description: "metadata contains embedded CommonMetadata and can be extended with custom string fields without external reference as using the CommonMetadata reference breaks thema codegen.",
Type: []string{"object"},
Properties: map[string]spec.Schema{
"group": {
"updateTimestamp": {
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
Format: "date-time",
},
},
"createdBy": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"resource": {
"uid": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"count": {
"creationTimestamp": {
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
Format: "date-time",
},
},
"deletionTimestamp": {
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
Format: "date-time",
},
},
"finalizers": {
SchemaProps: spec.SchemaProps{
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
},
},
},
"resourceVersion": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"generation": {
SchemaProps: spec.SchemaProps{
Default: 0,
Type: []string{"integer"},
Format: "int64",
},
},
"updatedBy": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"labels": {
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
AdditionalProperties: &spec.SchemaOrBool{
Allows: true,
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
},
},
},
},
Required: []string{"group", "resource", "count"},
Required: []string{"updateTimestamp", "createdBy", "uid", "creationTimestamp", "finalizers", "resourceVersion", "generation", "updatedBy", "labels"},
},
},
}
}
func schema_pkg_apis_folder_v1_Spec(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_folder_v1beta1_FolderSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@ -359,17 +444,15 @@ func schema_pkg_apis_folder_v1_Spec(ref common.ReferenceCallback) common.OpenAPI
Properties: map[string]spec.Schema{
"title": {
SchemaProps: spec.SchemaProps{
Description: "Describe the feature toggle",
Default: "",
Type: []string{"string"},
Format: "",
Default: "",
Type: []string{"string"},
Format: "",
},
},
"description": {
SchemaProps: spec.SchemaProps{
Description: "Describe the feature toggle",
Type: []string{"string"},
Format: "",
Type: []string{"string"},
Format: "",
},
},
},
@ -378,3 +461,48 @@ func schema_pkg_apis_folder_v1_Spec(ref common.ReferenceCallback) common.OpenAPI
},
}
}
func schema_pkg_apis_folder_v1beta1_FolderStatus(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "Empty stub",
Type: []string{"object"},
},
},
}
}
func schema_pkg_apis_folder_v1beta1_ResourceStats(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"group": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"resource": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"count": {
SchemaProps: spec.SchemaProps{
Default: 0,
Type: []string{"integer"},
Format: "int64",
},
},
},
Required: []string{"group", "resource", "count"},
},
},
}
}

@ -0,0 +1,3 @@
API rule violation: list_type_missing,github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1,DescendantCounts,Counts
API rule violation: list_type_missing,github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1,FolderInfoList,Items
API rule violation: list_type_missing,github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1,FolderMetadata,Finalizers

@ -0,0 +1,43 @@
//
// This file is generated by grafana-app-sdk
// DO NOT EDIT
//
package apis
import (
"encoding/json"
"github.com/grafana/grafana-app-sdk/app"
)
var appManifestData = app.ManifestData{
AppName: "folder",
Group: "folder.grafana.app",
Kinds: []app.ManifestKind{
{
Kind: "Folder",
Scope: "Namespaced",
Conversion: false,
Versions: []app.ManifestKindVersion{
{
Name: "v1beta1",
},
},
},
},
}
func jsonToMap(j string) map[string]any {
m := make(map[string]any)
json.Unmarshal([]byte(j), &j)
return m
}
func LocalManifest() app.Manifest {
return app.NewEmbeddedManifest(appManifestData)
}
func RemoteManifest() app.Manifest {
return app.NewAPIServerManifest("folder")
}

@ -211,11 +211,11 @@ require (
github.com/grafana/grafana/apps/advisor v0.0.0-20250220163425-b4c4b9abbdc8 // @grafana/plugins-platform-backend
github.com/grafana/grafana/apps/alerting/notifications v0.0.0-20250220163425-b4c4b9abbdc8 // @grafana/alerting-backend
github.com/grafana/grafana/apps/dashboard v0.0.0-20250317130411-3f270d1de043 // @grafana/grafana-app-platform-squad @grafana/dashboards-squad
github.com/grafana/grafana/apps/folder v0.0.0-20250414115220-48647355c37b // @grafana/grafana-search-and-storage
github.com/grafana/grafana/apps/investigations v0.0.0-20250220163425-b4c4b9abbdc8 // @fcjack @matryer
github.com/grafana/grafana/apps/playlist v0.0.0-20250220164708-c8d4ff28a450 // @grafana/grafana-app-platform-squad
github.com/grafana/grafana/pkg/aggregator v0.0.0-20250220163425-b4c4b9abbdc8 // @grafana/grafana-app-platform-squad
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250401081501-6af5fbf3fff0 // @grafana/grafana-app-platform-squad
github.com/grafana/grafana/pkg/apis/folder v0.0.0-20250402082028-6781612335d9 // indirect; @grafana/grafana-search-and-storage
github.com/grafana/grafana/pkg/apis/secret v0.0.0-20250319110241-5a004939da2a // @grafana/grafana-operator-experience-squad
github.com/grafana/grafana/pkg/apiserver v0.0.0-20250325075903-77fa2271be7a // @grafana/grafana-app-platform-squad

@ -1607,6 +1607,8 @@ github.com/grafana/grafana/apps/alerting/notifications v0.0.0-20250220163425-b4c
github.com/grafana/grafana/apps/alerting/notifications v0.0.0-20250220163425-b4c4b9abbdc8/go.mod h1:dHhFF484qs1cmdIShKCB3kl+tMJyc4yuwgTQ3Afz37o=
github.com/grafana/grafana/apps/dashboard v0.0.0-20250317130411-3f270d1de043 h1:wdJy5x6M7auWDjUIubqhfZuZvphUMyjD7hxB3RqV4aE=
github.com/grafana/grafana/apps/dashboard v0.0.0-20250317130411-3f270d1de043/go.mod h1:jwYig4wlnLLq4HQKDpS95nDeZi4+DmcD17KYYS1gMJg=
github.com/grafana/grafana/apps/folder v0.0.0-20250414115220-48647355c37b h1:n571OboxBgEnhAFnnc/soawXRsTsQYOaFC6Mn+iWPyI=
github.com/grafana/grafana/apps/folder v0.0.0-20250414115220-48647355c37b/go.mod h1:l7SqBgPw4c9iLCq/tVDAbrbsBdAHPIDF8xk0CdGHD/s=
github.com/grafana/grafana/apps/investigations v0.0.0-20250220163425-b4c4b9abbdc8 h1:jRcI2fE/u0tHfCmPLIt21M3DYOt3L6BmZcu/LeV2sRw=
github.com/grafana/grafana/apps/investigations v0.0.0-20250220163425-b4c4b9abbdc8/go.mod h1:ygFcJP2McdSeMJVj/3YrKafZMc/lZBsp54HO51MtJYw=
github.com/grafana/grafana/apps/playlist v0.0.0-20250220164708-c8d4ff28a450 h1:h3HsylGnuZiBgT5Q/N6bH+LazY3+nA98R76Xwcd0zXg=
@ -1615,8 +1617,6 @@ github.com/grafana/grafana/pkg/aggregator v0.0.0-20250220163425-b4c4b9abbdc8 h1:
github.com/grafana/grafana/pkg/aggregator v0.0.0-20250220163425-b4c4b9abbdc8/go.mod h1:deLQ/ywLvpVGbncRGUA4UDGt8a5Ei9sivOP+x6AQ2ko=
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250401081501-6af5fbf3fff0 h1:/MtKK3BUWqLJVkoFQViNvD5BmblGlVwpOScEtLLpexU=
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250401081501-6af5fbf3fff0/go.mod h1:uju5OyW1BopywSF1jjIHei0L0/QIi4vn/EQ1ys+E6aI=
github.com/grafana/grafana/pkg/apis/folder v0.0.0-20250402082028-6781612335d9 h1:kJWonBYechx35NbOUVf1ulufKyjH1UlDJDXlk8bdGn0=
github.com/grafana/grafana/pkg/apis/folder v0.0.0-20250402082028-6781612335d9/go.mod h1:QdqsZpdCtg+3TEzXX3mUakjq79LFblZ8xliHmqZj3oA=
github.com/grafana/grafana/pkg/apis/secret v0.0.0-20250319110241-5a004939da2a h1:dMllTcE0R1qvV4rWDehQzxNiHaale1yCzXsVkub07D0=
github.com/grafana/grafana/pkg/apis/secret v0.0.0-20250319110241-5a004939da2a/go.mod h1:K/fP4kODJmABug5b90PhACUZD6Xh/veEz2b1VRKNyuA=
github.com/grafana/grafana/pkg/apiserver v0.0.0-20250325075903-77fa2271be7a h1:NN0j9zdqYpfliR0P+au/PAJ5lqP7IZPNe8tAX5eaQNE=

@ -15,11 +15,11 @@ use (
./apps/advisor
./apps/alerting/notifications
./apps/dashboard
./apps/folder
./apps/investigations
./apps/playlist
./pkg/aggregator
./pkg/apimachinery
./pkg/apis/folder
./pkg/apis/secret // @grafana/grafana-operator-experience-squad
./pkg/apiserver
./pkg/build

@ -1115,6 +1115,7 @@ github.com/grafana/grafana-plugin-sdk-go v0.267.0/go.mod h1:OuwS4c/JYgn0rr/w5zhJ
github.com/grafana/grafana/apps/advisor v0.0.0-20250123151950-b066a6313173/go.mod h1:goSDiy3jtC2cp8wjpPZdUHRENcoSUHae1/Px/MDfddA=
github.com/grafana/grafana/apps/advisor v0.0.0-20250220154326-6e5de80ef295/go.mod h1:9I1dKV3Dqr0NPR9Af0WJGxOytp5/6W3JLiNChOz8r+c=
github.com/grafana/grafana/apps/alerting/notifications v0.0.0-20250121113133-e747350fee2d/go.mod h1:AvleS6icyPmcBjihtx5jYEvdzLmHGBp66NuE0AMR57A=
github.com/grafana/grafana/apps/folder v0.0.0-20250414115220-48647355c37b/go.mod h1:l7SqBgPw4c9iLCq/tVDAbrbsBdAHPIDF8xk0CdGHD/s=
github.com/grafana/grafana/apps/investigation v0.0.0-20250121113133-e747350fee2d/go.mod h1:HQprw3MmiYj5OUV9CZnkwA1FKDZBmYACuAB3oDvUOmI=
github.com/grafana/grafana/apps/playlist v0.0.0-20250121113133-e747350fee2d/go.mod h1:DjJe5osrW/BKrzN9hAAOSElNWutj1bcriExa7iDP7kA=
github.com/grafana/grafana/pkg/aggregator v0.0.0-20250121113133-e747350fee2d/go.mod h1:1sq0guad+G4SUTlBgx7SXfhnzy7D86K/LcVOtiQCiMA=
@ -1868,7 +1869,6 @@ golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ss
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
@ -1913,7 +1913,6 @@ golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM=
golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8=
golang.org/x/oauth2 v0.19.0/go.mod h1:vYi7skDa1x015PmRRYZ7+s1cWyPgrPiSYRe4rnsexc8=
@ -1948,26 +1947,22 @@ golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457 h1:zf5N6UOrA487eEFacMePxjXAJctxKmyjKUsjA11Uzuk=
golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457/go.mod h1:pRgIJT+bRLFKnoM1ldnzKoxTIn14Yxz928LQRYYgIN0=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/time v0.10.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
@ -1984,7 +1979,6 @@ golang.org/x/tools v0.25.0/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw=
golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY=
golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s=
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0 h1:OE9mWmgKkjJyEmDAAtGMPjXu+YNeGvK9VTSHY6+Qihc=
gonum.org/v1/plot v0.14.0 h1:+LBDVFYwFe4LHhdP8coW6296MBEY4nQ+Y4vuUpJopcE=

@ -87,6 +87,7 @@ grafana::codegen:run pkg
grafana::codegen:run pkg/apimachinery
grafana::codegen:run pkg/aggregator
grafana::codegen:run apps/dashboard/pkg
grafana::codegen:run apps/folder/pkg
if [ -d "pkg/extensions/apis" ]; then
grafana::codegen:run pkg/extensions

@ -14,8 +14,8 @@ import (
"github.com/stretchr/testify/require"
clientrest "k8s.io/client-go/rest"
folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
"github.com/grafana/grafana/pkg/api/dtos"
folders "github.com/grafana/grafana/pkg/apis/folder/v1"
grafanarest "github.com/grafana/grafana/pkg/apiserver/rest"
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/accesscontrol/actest"

@ -1,6 +0,0 @@
// +k8s:deepcopy-gen=package
// +k8s:openapi-gen=true
// +k8s:defaulter-gen=TypeMeta
// +groupName=folder.grafana.app
package v1 // import "github.com/grafana/grafana/pkg/apis/folder/v1"

@ -1,206 +0,0 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
// SPDX-License-Identifier: AGPL-3.0-only
// Code generated by deepcopy-gen. DO NOT EDIT.
package v1
import (
runtime "k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DescendantCounts) DeepCopyInto(out *DescendantCounts) {
*out = *in
out.TypeMeta = in.TypeMeta
if in.Counts != nil {
in, out := &in.Counts, &out.Counts
*out = make([]ResourceStats, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DescendantCounts.
func (in *DescendantCounts) DeepCopy() *DescendantCounts {
if in == nil {
return nil
}
out := new(DescendantCounts)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *DescendantCounts) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Folder) DeepCopyInto(out *Folder) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
out.Spec = in.Spec
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Folder.
func (in *Folder) DeepCopy() *Folder {
if in == nil {
return nil
}
out := new(Folder)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *Folder) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *FolderAccessInfo) DeepCopyInto(out *FolderAccessInfo) {
*out = *in
out.TypeMeta = in.TypeMeta
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FolderAccessInfo.
func (in *FolderAccessInfo) DeepCopy() *FolderAccessInfo {
if in == nil {
return nil
}
out := new(FolderAccessInfo)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *FolderAccessInfo) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *FolderInfo) DeepCopyInto(out *FolderInfo) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FolderInfo.
func (in *FolderInfo) DeepCopy() *FolderInfo {
if in == nil {
return nil
}
out := new(FolderInfo)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *FolderInfoList) DeepCopyInto(out *FolderInfoList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]FolderInfo, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FolderInfoList.
func (in *FolderInfoList) DeepCopy() *FolderInfoList {
if in == nil {
return nil
}
out := new(FolderInfoList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *FolderInfoList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *FolderList) DeepCopyInto(out *FolderList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]Folder, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FolderList.
func (in *FolderList) DeepCopy() *FolderList {
if in == nil {
return nil
}
out := new(FolderList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *FolderList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ResourceStats) DeepCopyInto(out *ResourceStats) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceStats.
func (in *ResourceStats) DeepCopy() *ResourceStats {
if in == nil {
return nil
}
out := new(ResourceStats)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Spec) DeepCopyInto(out *Spec) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Spec.
func (in *Spec) DeepCopy() *Spec {
if in == nil {
return nil
}
out := new(Spec)
in.DeepCopyInto(out)
return out
}

@ -1,2 +0,0 @@
API rule violation: list_type_missing,github.com/grafana/grafana/pkg/apis/folder/v1,DescendantCounts,Counts
API rule violation: list_type_missing,github.com/grafana/grafana/pkg/apis/folder/v1,FolderInfoList,Items

@ -11,10 +11,9 @@ import (
"github.com/prometheus/client_golang/prometheus"
"k8s.io/apimachinery/pkg/runtime/schema"
dashboard "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v1alpha1"
folders "github.com/grafana/grafana/pkg/apis/folder/v1"
authlib "github.com/grafana/authlib/types"
dashboard "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v1alpha1"
folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/cmd/grafana-cli/utils"
"github.com/grafana/grafana/pkg/infra/db"

@ -12,8 +12,8 @@ import (
authlib "github.com/grafana/authlib/types"
dashboard "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v1alpha1"
folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
"github.com/grafana/grafana/pkg/apimachinery/utils"
folders "github.com/grafana/grafana/pkg/apis/folder/v1"
"github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/services/provisioning"
"github.com/grafana/grafana/pkg/services/search/sort"
@ -328,7 +328,7 @@ func (a *dashboardSqlAccess) migrateFolders(ctx context.Context, orgId int64, op
// Now send each dashboard
for i := 1; rows.Next(); i++ {
dash := rows.row.Dash
dash.APIVersion = "folder.grafana.app/v1"
dash.APIVersion = "folder.grafana.app/v1beta1"
dash.Kind = "Folder"
dash.SetNamespace(opts.Namespace)
dash.SetResourceVersion("") // it will be filled in by the backend

@ -12,9 +12,9 @@ import (
claims "github.com/grafana/authlib/types"
dashboard "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v1alpha1"
folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/apimachinery/utils"
folders "github.com/grafana/grafana/pkg/apis/folder/v1"
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
"github.com/grafana/grafana/pkg/services/search/sort"

@ -48,7 +48,7 @@ import (
"github.com/grafana/grafana/pkg/storage/unified/apistore"
"github.com/grafana/grafana/pkg/storage/unified/resource"
folders "github.com/grafana/grafana/pkg/apis/folder/v1"
folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
"github.com/grafana/grafana/pkg/services/apiserver"
"github.com/grafana/grafana/pkg/services/apiserver/client"
)

@ -22,8 +22,8 @@ import (
"github.com/grafana/grafana/pkg/storage/unified/search"
dashboardv0alpha1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v0alpha1"
folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
"github.com/grafana/grafana/pkg/apimachinery/identity"
folders "github.com/grafana/grafana/pkg/apis/folder/v1"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/services/apiserver/builder"
"github.com/grafana/grafana/pkg/services/dashboards"

@ -5,15 +5,16 @@ import (
"testing"
"github.com/go-jose/go-jose/v3/jwt"
"github.com/stretchr/testify/require"
"k8s.io/apiserver/pkg/authorization/authorizer"
"github.com/grafana/authlib/authn"
"github.com/grafana/authlib/authz"
"github.com/grafana/authlib/types"
"github.com/stretchr/testify/require"
"k8s.io/apiserver/pkg/authorization/authorizer"
folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/apimachinery/utils"
folders "github.com/grafana/grafana/pkg/apis/folder/v1"
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/featuremgmt"

@ -8,8 +8,8 @@ import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
claims "github.com/grafana/authlib/types"
folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
"github.com/grafana/grafana/pkg/apimachinery/utils"
folders "github.com/grafana/grafana/pkg/apis/folder/v1"
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
gapiutil "github.com/grafana/grafana/pkg/services/apiserver/utils"
"github.com/grafana/grafana/pkg/services/folder"
@ -18,8 +18,8 @@ import (
func LegacyCreateCommandToUnstructured(cmd *folder.CreateFolderCommand) (*unstructured.Unstructured, error) {
obj := &unstructured.Unstructured{
Object: map[string]interface{}{
"spec": map[string]interface{}{
Object: map[string]any{
"spec": map[string]any{
"title": cmd.Title,
"description": cmd.Description,
},
@ -53,9 +53,9 @@ func convertToK8sResource(v *folder.Folder, namespacer request.NamespaceMapper)
CreationTimestamp: metav1.NewTime(v.Created),
Namespace: namespacer(v.OrgID),
},
Spec: folders.Spec{
Spec: folders.FolderSpec{
Title: v.Title,
Description: v.Description,
Description: descr(v.Description),
},
}
@ -92,3 +92,10 @@ func convertToK8sResource(v *folder.Folder, namespacer request.NamespaceMapper)
f.UID = gapiutil.CalculateClusterWideUID(f)
return f, nil
}
func descr(str string) *string {
if str == "" {
return nil
}
return &str
}

@ -10,9 +10,9 @@ import (
"k8s.io/apiserver/pkg/registry/rest"
claims "github.com/grafana/authlib/types"
folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/apimachinery/utils"
folders "github.com/grafana/grafana/pkg/apis/folder/v1"
grafanarest "github.com/grafana/grafana/pkg/apiserver/rest"
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"

@ -4,12 +4,6 @@ import (
"context"
"testing"
"github.com/grafana/grafana/pkg/apimachinery/identity"
folders "github.com/grafana/grafana/pkg/apis/folder/v1"
"github.com/grafana/grafana/pkg/services/accesscontrol"
acmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"gopkg.in/ini.v1"
@ -18,6 +12,13 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/apiserver/pkg/registry/rest"
folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/services/accesscontrol"
acmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
)
func TestSetDefaultPermissionsWhenCreatingFolder(t *testing.T) {

@ -11,10 +11,10 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/registry/rest"
folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
"github.com/grafana/grafana/pkg/api/apierrors"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/apimachinery/utils"
folders "github.com/grafana/grafana/pkg/apis/folder/v1"
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/featuremgmt"
@ -195,12 +195,16 @@ func (s *legacyStorage) Create(ctx context.Context,
}
parent := accessor.GetFolder()
descr := ""
if p.Spec.Description != nil {
descr = *p.Spec.Description
}
out, err := s.service.CreateLegacy(ctx, &folder.CreateFolderCommand{
SignedInUser: user,
UID: p.Name,
Title: p.Spec.Title,
Description: p.Spec.Description,
Description: descr,
OrgID: info.OrgID,
ParentUID: parent,
})
@ -285,7 +289,7 @@ func (s *legacyStorage) Update(ctx context.Context,
changed = true
}
if f.Spec.Description != old.Spec.Description {
cmd.NewDescription = &f.Spec.Description
cmd.NewDescription = f.Spec.Description
changed = true
}
if changed {

@ -12,9 +12,9 @@ import (
"encoding/base64"
folderv1 "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/apimachinery/utils"
folderv1 "github.com/grafana/grafana/pkg/apis/folder/v1"
"github.com/grafana/grafana/pkg/services/folder"
"github.com/grafana/grafana/pkg/services/folder/foldertest"
"github.com/grafana/grafana/pkg/services/org"

@ -18,9 +18,9 @@ import (
"k8s.io/kube-openapi/pkg/spec3"
authtypes "github.com/grafana/authlib/types"
folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/apimachinery/utils"
folders "github.com/grafana/grafana/pkg/apis/folder/v1"
grafanaregistry "github.com/grafana/grafana/pkg/apiserver/registry/generic"
grafanarest "github.com/grafana/grafana/pkg/apiserver/rest"
"github.com/grafana/grafana/pkg/services/accesscontrol"

@ -9,8 +9,8 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apiserver/pkg/admission"
folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
"github.com/grafana/grafana/pkg/apimachinery/utils"
folders "github.com/grafana/grafana/pkg/apis/folder/v1"
grafanarest "github.com/grafana/grafana/pkg/apiserver/rest"
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/dashboards"
@ -31,14 +31,14 @@ func TestFolderAPIBuilder_Validate_Create(t *testing.T) {
folderValidationRules.maxDepth = 2
defer func() { folderValidationRules.maxDepth = initialMaxDepth }()
deepFolder := &folders.Folder{
Spec: folders.Spec{
Spec: folders.FolderSpec{
Title: "foo",
},
}
deepFolder.Name = "valid-parent"
deepFolder.Annotations = map[string]string{"grafana.app/folder": "valid-grandparent"}
parentFolder := &folders.Folder{
Spec: folders.Spec{
Spec: folders.FolderSpec{
Title: "foo-grandparent",
},
}
@ -54,7 +54,7 @@ func TestFolderAPIBuilder_Validate_Create(t *testing.T) {
name: "should return error when name is invalid",
input: input{
obj: &folders.Folder{
Spec: folders.Spec{
Spec: folders.FolderSpec{
Title: "foo",
},
},
@ -66,7 +66,7 @@ func TestFolderAPIBuilder_Validate_Create(t *testing.T) {
name: "should return no error if every validation passes",
input: input{
obj: &folders.Folder{
Spec: folders.Spec{
Spec: folders.FolderSpec{
Title: "foo",
},
},
@ -77,7 +77,7 @@ func TestFolderAPIBuilder_Validate_Create(t *testing.T) {
name: "should not allow creating a folder in a tree that is too deep",
input: input{
obj: &folders.Folder{
Spec: folders.Spec{
Spec: folders.FolderSpec{
Title: "foo",
},
},
@ -98,7 +98,7 @@ func TestFolderAPIBuilder_Validate_Create(t *testing.T) {
name: "should return error when title is empty",
input: input{
obj: &folders.Folder{
Spec: folders.Spec{
Spec: folders.FolderSpec{
Title: "",
},
},
@ -111,7 +111,7 @@ func TestFolderAPIBuilder_Validate_Create(t *testing.T) {
input: input{
annotations: map[string]string{utils.AnnoKeyFolder: "myself"},
obj: &folders.Folder{
Spec: folders.Spec{
Spec: folders.FolderSpec{
Title: "title",
},
},
@ -189,7 +189,7 @@ func TestFolderAPIBuilder_Validate_Delete(t *testing.T) {
sm := searcherMock{Mock: m}
obj := &folders.Folder{
Spec: folders.Spec{
Spec: folders.FolderSpec{
Title: "foo",
},
ObjectMeta: metav1.ObjectMeta{
@ -261,7 +261,7 @@ func TestFolderAPIBuilder_Validate_Update(t *testing.T) {
{
name: "should allow updating a folder spec",
updatedObj: &folders.Folder{
Spec: folders.Spec{
Spec: folders.FolderSpec{
Title: "different title",
},
ObjectMeta: metav1.ObjectMeta{
@ -271,7 +271,7 @@ func TestFolderAPIBuilder_Validate_Update(t *testing.T) {
},
},
expected: &folders.Folder{
Spec: folders.Spec{
Spec: folders.FolderSpec{
Title: "different title",
},
ObjectMeta: metav1.ObjectMeta{
@ -284,7 +284,7 @@ func TestFolderAPIBuilder_Validate_Update(t *testing.T) {
{
name: "updated title should not be empty",
updatedObj: &folders.Folder{
Spec: folders.Spec{
Spec: folders.FolderSpec{
Title: "",
},
ObjectMeta: metav1.ObjectMeta{
@ -298,7 +298,7 @@ func TestFolderAPIBuilder_Validate_Update(t *testing.T) {
{
name: "should allow moving to a valid parent",
updatedObj: &folders.Folder{
Spec: folders.Spec{
Spec: folders.FolderSpec{
Title: "foo",
},
ObjectMeta: metav1.ObjectMeta{
@ -316,7 +316,7 @@ func TestFolderAPIBuilder_Validate_Update(t *testing.T) {
{
name: "should not allow moving to a k6 folder",
updatedObj: &folders.Folder{
Spec: folders.Spec{
Spec: folders.FolderSpec{
Title: "foo",
},
ObjectMeta: metav1.ObjectMeta{
@ -335,7 +335,7 @@ func TestFolderAPIBuilder_Validate_Update(t *testing.T) {
{
name: "should not allow moving to a folder that is too deep",
updatedObj: &folders.Folder{
Spec: folders.Spec{
Spec: folders.FolderSpec{
Title: "foo",
},
ObjectMeta: metav1.ObjectMeta{
@ -359,7 +359,7 @@ func TestFolderAPIBuilder_Validate_Update(t *testing.T) {
sm := searcherMock{Mock: m}
obj := &folders.Folder{
Spec: folders.Spec{
Spec: folders.FolderSpec{
Title: "foo",
},
ObjectMeta: metav1.ObjectMeta{
@ -417,7 +417,7 @@ func TestFolderAPIBuilder_Mutate_Create(t *testing.T) {
{
name: "should trim a title",
input: &folders.Folder{
Spec: folders.Spec{
Spec: folders.FolderSpec{
Title: " foo ",
},
TypeMeta: metav1.TypeMeta{
@ -428,7 +428,7 @@ func TestFolderAPIBuilder_Mutate_Create(t *testing.T) {
},
},
expected: &folders.Folder{
Spec: folders.Spec{
Spec: folders.FolderSpec{
Title: "foo",
},
TypeMeta: metav1.TypeMeta{
@ -442,7 +442,7 @@ func TestFolderAPIBuilder_Mutate_Create(t *testing.T) {
{
name: "should return error if title doesnt exist",
input: &folders.Folder{
Spec: folders.Spec{},
Spec: folders.FolderSpec{},
TypeMeta: metav1.TypeMeta{
Kind: "Folder",
},
@ -504,7 +504,7 @@ func TestFolderAPIBuilder_Mutate_Create(t *testing.T) {
func TestFolderAPIBuilder_Mutate_Update(t *testing.T) {
existingObj := &folders.Folder{
Spec: folders.Spec{
Spec: folders.FolderSpec{
Title: "some title",
},
TypeMeta: metav1.TypeMeta{
@ -523,7 +523,7 @@ func TestFolderAPIBuilder_Mutate_Update(t *testing.T) {
{
name: "should trim a title",
input: &folders.Folder{
Spec: folders.Spec{
Spec: folders.FolderSpec{
Title: " foo ",
},
TypeMeta: metav1.TypeMeta{
@ -534,7 +534,7 @@ func TestFolderAPIBuilder_Mutate_Update(t *testing.T) {
},
},
expected: &folders.Folder{
Spec: folders.Spec{
Spec: folders.FolderSpec{
Title: "foo",
},
TypeMeta: metav1.TypeMeta{
@ -548,7 +548,7 @@ func TestFolderAPIBuilder_Mutate_Update(t *testing.T) {
{
name: "should return error if title doesnt exist",
input: &folders.Folder{
Spec: folders.Spec{},
Spec: folders.FolderSpec{},
TypeMeta: metav1.TypeMeta{
Kind: "Folder",
},

@ -7,8 +7,8 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/registry/rest"
folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
"github.com/grafana/grafana/pkg/apimachinery/identity"
folders "github.com/grafana/grafana/pkg/apis/folder/v1"
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
"github.com/grafana/grafana/pkg/services/folder"
"github.com/grafana/grafana/pkg/services/guardian"

@ -7,7 +7,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/registry/rest"
folders "github.com/grafana/grafana/pkg/apis/folder/v1"
folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
"github.com/grafana/grafana/pkg/storage/unified/resource"
)

@ -4,11 +4,12 @@ import (
"context"
"testing"
folders "github.com/grafana/grafana/pkg/apis/folder/v1"
grafanarest "github.com/grafana/grafana/pkg/apiserver/rest"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
grafanarest "github.com/grafana/grafana/pkg/apiserver/rest"
)
func TestSubParent(t *testing.T) {
@ -25,7 +26,7 @@ func TestSubParent(t *testing.T) {
Name: "test",
Annotations: map[string]string{},
},
Spec: folders.Spec{
Spec: folders.FolderSpec{
Title: "some tittle",
},
},
@ -38,7 +39,7 @@ func TestSubParent(t *testing.T) {
Name: "test",
Annotations: map[string]string{"grafana.app/folder": "parent-test"},
},
Spec: folders.Spec{
Spec: folders.FolderSpec{
Title: "some tittle",
},
},
@ -48,7 +49,7 @@ func TestSubParent(t *testing.T) {
Name: "parent-test",
Annotations: map[string]string{},
},
Spec: folders.Spec{
Spec: folders.FolderSpec{
Title: "some other tittle",
},
}, nil).Once()

@ -10,7 +10,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/registry/rest"
folders "github.com/grafana/grafana/pkg/apis/folder/v1"
folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
)
type subParentsREST struct {
@ -67,10 +67,14 @@ func (r *subParentsREST) parents(ctx context.Context, folder *folders.Folder) *f
}
for folder != nil {
parent := getParent(folder)
descr := ""
if folder.Spec.Description != nil {
descr = *folder.Spec.Description
}
info.Items = append(info.Items, folders.FolderInfo{
Name: folder.Name,
Title: folder.Spec.Title,
Description: folder.Spec.Description,
Description: descr,
Parent: parent,
})
if parent == "" {

@ -11,8 +11,8 @@ import (
"k8s.io/client-go/dynamic"
"github.com/grafana/grafana-app-sdk/logging"
folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
"github.com/grafana/grafana/pkg/apimachinery/utils"
folders "github.com/grafana/grafana/pkg/apis/folder/v1"
provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1"
"github.com/grafana/grafana/pkg/registry/apis/provisioning/repository"
"github.com/grafana/grafana/pkg/registry/apis/provisioning/resources"

@ -27,9 +27,9 @@ import (
authlib "github.com/grafana/authlib/types"
"github.com/grafana/grafana-app-sdk/logging"
dashboard "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v0alpha1"
folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
"github.com/grafana/grafana/pkg/apimachinery/identity"
apiutils "github.com/grafana/grafana/pkg/apimachinery/utils"
folders "github.com/grafana/grafana/pkg/apis/folder/v1"
provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1"
"github.com/grafana/grafana/pkg/apiserver/readonly"
grafanaregistry "github.com/grafana/grafana/pkg/apiserver/registry/generic"

@ -11,7 +11,7 @@ import (
"k8s.io/client-go/dynamic"
dashboard "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v1alpha1"
folders "github.com/grafana/grafana/pkg/apis/folder/v1"
folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
iam "github.com/grafana/grafana/pkg/apis/iam/v0alpha1"
"github.com/grafana/grafana/pkg/services/apiserver"
"github.com/grafana/grafana/pkg/services/apiserver/client"

@ -10,9 +10,9 @@ import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/client-go/dynamic"
folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/apimachinery/utils"
folders "github.com/grafana/grafana/pkg/apis/folder/v1"
"github.com/grafana/grafana/pkg/registry/apis/provisioning/repository"
"github.com/grafana/grafana/pkg/registry/apis/provisioning/safepath"
)

@ -7,8 +7,8 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema"
dashboard "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v0alpha1"
folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
"github.com/grafana/grafana/pkg/apimachinery/utils"
folders "github.com/grafana/grafana/pkg/apis/folder/v1"
provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1"
"github.com/grafana/grafana/pkg/registry/apis/dashboard/legacy"
"github.com/grafana/grafana/pkg/storage/legacysql/dualwrite"

@ -7,8 +7,8 @@ import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
"github.com/grafana/grafana/pkg/apimachinery/utils"
folders "github.com/grafana/grafana/pkg/apis/folder/v1"
provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1"
"github.com/grafana/grafana/pkg/registry/apis/provisioning/safepath"
)

@ -307,7 +307,7 @@ func TestService_OrgID(t *testing.T) {
desc: "should set org id from default namespace",
req: &authn.Request{HTTPRequest: &http.Request{
Header: map[string][]string{},
URL: mustParseURL("http://localhost/apis/folder.grafana.app/v1/namespaces/default/folders"),
URL: mustParseURL("http://localhost/apis/folder.grafana.app/v1beta1/namespaces/default/folders"),
}},
expectedOrgID: 1,
},
@ -315,7 +315,7 @@ func TestService_OrgID(t *testing.T) {
desc: "should set org id from namespace",
req: &authn.Request{HTTPRequest: &http.Request{
Header: map[string][]string{},
URL: mustParseURL("http://localhost/apis/folder.grafana.app/v1/namespaces/org-2/folders"),
URL: mustParseURL("http://localhost/apis/folder.grafana.app/v1beta1/namespaces/org-2/folders"),
}},
expectedOrgID: 2,
},
@ -323,7 +323,7 @@ func TestService_OrgID(t *testing.T) {
desc: "should set set org 1 for stack namespace",
req: &authn.Request{HTTPRequest: &http.Request{
Header: map[string][]string{},
URL: mustParseURL("http://localhost/apis/folder.grafana.app/v1/namespaces/stacks-100/folders"),
URL: mustParseURL("http://localhost/apis/folder.grafana.app/v1beta1/namespaces/stacks-100/folders"),
}},
stackID: 100,
expectedOrgID: 1,
@ -332,7 +332,7 @@ func TestService_OrgID(t *testing.T) {
desc: "should error for wrong stack namespace",
req: &authn.Request{HTTPRequest: &http.Request{
Header: map[string][]string{},
URL: mustParseURL("http://localhost/apis/folder.grafana.app/v1/namespaces/stacks-100/folders"),
URL: mustParseURL("http://localhost/apis/folder.grafana.app/v1beta1/namespaces/stacks-100/folders"),
}},
stackID: 101,
expectedOrgID: 0,

@ -4,15 +4,15 @@ import (
"context"
"fmt"
"github.com/grafana/authlib/types"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/pager"
"github.com/grafana/authlib/types"
folderv1 "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
"github.com/grafana/grafana/pkg/apimachinery/utils"
folderv1 "github.com/grafana/grafana/pkg/apis/folder/v1"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/storage/legacysql"
"github.com/grafana/grafana/pkg/storage/unified/sql/sqltemplate"

@ -1,10 +1,10 @@
package common
import (
authzv1 "github.com/grafana/authlib/authz/proto/v1"
"google.golang.org/protobuf/types/known/structpb"
folders "github.com/grafana/grafana/pkg/apis/folder/v1"
authzv1 "github.com/grafana/authlib/authz/proto/v1"
folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
iamalpha1 "github.com/grafana/grafana/pkg/apis/iam/v0alpha1"
authzextv1 "github.com/grafana/grafana/pkg/services/authz/proto/v1"
)

@ -2,7 +2,7 @@ package zanzana
import (
dashboards "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v1alpha1"
folders "github.com/grafana/grafana/pkg/apis/folder/v1"
folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
)
const (

@ -28,9 +28,9 @@ import (
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard"
dashboardv0 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v0alpha1"
dashboardv1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v1alpha1"
folderv1 "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/apimachinery/utils"
folderv1 "github.com/grafana/grafana/pkg/apis/folder/v1"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/infra/kvstore"
"github.com/grafana/grafana/pkg/infra/log"

@ -18,7 +18,7 @@ func TestFolderConversions(t *testing.T) {
input := &unstructured.Unstructured{}
err := input.UnmarshalJSON([]byte(`{
"kind": "Folder",
"apiVersion": "folder.grafana.app/v1",
"apiVersion": "folder.grafana.app/v1beta1",
"metadata": {
"name": "be79sztagf20wd",
"namespace": "default",
@ -86,10 +86,10 @@ func TestFolderConversions(t *testing.T) {
func TestFolderListConversions(t *testing.T) {
input := &unstructured.UnstructuredList{}
err := input.UnmarshalJSON([]byte(`{
"apiVersion": "folder.grafana.app/v1",
"apiVersion": "folder.grafana.app/v1beta1",
"items": [
{
"apiVersion": "folder.grafana.app/v1",
"apiVersion": "folder.grafana.app/v1beta1",
"kind": "Folder",
"metadata": {
"annotations": {
@ -113,7 +113,7 @@ func TestFolderListConversions(t *testing.T) {
}
},
{
"apiVersion": "folder.grafana.app/v1",
"apiVersion": "folder.grafana.app/v1beta1",
"kind": "Folder",
"metadata": {
"annotations": {
@ -135,7 +135,7 @@ func TestFolderListConversions(t *testing.T) {
}
},
{
"apiVersion": "folder.grafana.app/v1",
"apiVersion": "folder.grafana.app/v1beta1",
"kind": "Folder",
"metadata": {
"annotations": {
@ -158,7 +158,7 @@ func TestFolderListConversions(t *testing.T) {
}
},
{
"apiVersion": "folder.grafana.app/v1",
"apiVersion": "folder.grafana.app/v1beta1",
"kind": "Folder",
"metadata": {
"annotations": {
@ -180,7 +180,7 @@ func TestFolderListConversions(t *testing.T) {
}
},
{
"apiVersion": "folder.grafana.app/v1",
"apiVersion": "folder.grafana.app/v1beta1",
"kind": "Folder",
"metadata": {
"annotations": {
@ -203,7 +203,7 @@ func TestFolderListConversions(t *testing.T) {
}
},
{
"apiVersion": "folder.grafana.app/v1",
"apiVersion": "folder.grafana.app/v1beta1",
"kind": "Folder",
"metadata": {
"annotations": {},

@ -19,8 +19,8 @@ import (
"github.com/grafana/dskit/concurrency"
dashboardv1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v1alpha1"
folderv1 "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
"github.com/grafana/grafana/pkg/apimachinery/identity"
folderv1 "github.com/grafana/grafana/pkg/apis/folder/v1"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/events"
"github.com/grafana/grafana/pkg/infra/db"

@ -14,9 +14,9 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
folderv1 "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/apimachinery/utils"
folderv1 "github.com/grafana/grafana/pkg/apis/folder/v1"
"github.com/grafana/grafana/pkg/events"
"github.com/grafana/grafana/pkg/infra/metrics"
"github.com/grafana/grafana/pkg/infra/slugify"

@ -15,9 +15,9 @@ import (
"k8s.io/apimachinery/pkg/selection"
clientrest "k8s.io/client-go/rest"
foldersv1 "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/apimachinery/utils"
foldersv1 "github.com/grafana/grafana/pkg/apis/folder/v1"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/infra/log/logtest"
@ -82,11 +82,11 @@ func TestIntegrationFolderServiceViaUnifiedStorage(t *testing.T) {
mux := http.NewServeMux()
mux.HandleFunc("DELETE /apis/folder.grafana.app/v1/namespaces/default/folders/deletefolder", func(w http.ResponseWriter, req *http.Request) {
mux.HandleFunc("DELETE /apis/folder.grafana.app/v1beta1/namespaces/default/folders/deletefolder", func(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Content-Type", "application/json")
})
mux.HandleFunc("GET /apis/folder.grafana.app/v1/namespaces/default/folders", func(w http.ResponseWriter, req *http.Request) {
mux.HandleFunc("GET /apis/folder.grafana.app/v1beta1/namespaces/default/folders", func(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Content-Type", "application/json")
l := &foldersv1.FolderList{}
l.Kind = "Folder"
@ -94,7 +94,7 @@ func TestIntegrationFolderServiceViaUnifiedStorage(t *testing.T) {
require.NoError(t, err)
})
mux.HandleFunc("GET /apis/folder.grafana.app/v1/namespaces/default/folders/foo", func(w http.ResponseWriter, req *http.Request) {
mux.HandleFunc("GET /apis/folder.grafana.app/v1beta1/namespaces/default/folders/foo", func(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Content-Type", "application/json")
namespacer := func(_ int64) string { return "1" }
result, err := internalfolders.LegacyFolderToUnstructured(fooFolder, namespacer)
@ -104,7 +104,7 @@ func TestIntegrationFolderServiceViaUnifiedStorage(t *testing.T) {
require.NoError(t, err)
})
mux.HandleFunc("GET /apis/folder.grafana.app/v1/namespaces/default/folders/updatefolder", func(w http.ResponseWriter, req *http.Request) {
mux.HandleFunc("GET /apis/folder.grafana.app/v1beta1/namespaces/default/folders/updatefolder", func(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Content-Type", "application/json")
namespacer := func(_ int64) string { return "1" }
result, err := internalfolders.LegacyFolderToUnstructured(updateFolder, namespacer)
@ -114,7 +114,7 @@ func TestIntegrationFolderServiceViaUnifiedStorage(t *testing.T) {
require.NoError(t, err)
})
mux.HandleFunc("PUT /apis/folder.grafana.app/v1/namespaces/default/folders/updatefolder", func(w http.ResponseWriter, req *http.Request) {
mux.HandleFunc("PUT /apis/folder.grafana.app/v1beta1/namespaces/default/folders/updatefolder", func(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Content-Type", "application/json")
buf, err := io.ReadAll(req.Body)
require.NoError(t, err)
@ -133,17 +133,17 @@ func TestIntegrationFolderServiceViaUnifiedStorage(t *testing.T) {
require.NoError(t, err)
})
mux.HandleFunc("GET /apis/folder.grafana.app/v1/namespaces/default/folders/ady4yobv315a8e", func(w http.ResponseWriter, req *http.Request) {
mux.HandleFunc("GET /apis/folder.grafana.app/v1beta1/namespaces/default/folders/ady4yobv315a8e", func(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Content-Type", "application/json")
err := json.NewEncoder(w).Encode(unifiedStorageFolder)
require.NoError(t, err)
})
mux.HandleFunc("PUT /apis/folder.grafana.app/v1/namespaces/default/folders/ady4yobv315a8e", func(w http.ResponseWriter, req *http.Request) {
mux.HandleFunc("PUT /apis/folder.grafana.app/v1beta1/namespaces/default/folders/ady4yobv315a8e", func(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Content-Type", "application/json")
err := json.NewEncoder(w).Encode(unifiedStorageFolder)
require.NoError(t, err)
})
mux.HandleFunc("POST /apis/folder.grafana.app/v1/namespaces/default/folders", func(w http.ResponseWriter, req *http.Request) {
mux.HandleFunc("POST /apis/folder.grafana.app/v1beta1/namespaces/default/folders", func(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Content-Type", "application/json")
buf, err := io.ReadAll(req.Body)
require.NoError(t, err)

@ -16,7 +16,7 @@ import (
"github.com/grafana/grafana/pkg/apimachinery/utils"
"github.com/grafana/grafana/pkg/storage/unified/resource"
folderv1 "github.com/grafana/grafana/pkg/apis/folder/v1"
folderv1 "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
"github.com/grafana/grafana/pkg/infra/log"
internalfolders "github.com/grafana/grafana/pkg/registry/apis/folders"
"github.com/grafana/grafana/pkg/services/accesscontrol"

@ -5,7 +5,7 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema"
dashboard "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v1alpha1"
folders "github.com/grafana/grafana/pkg/apis/folder/v1"
folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
)
func IsReadingLegacyDashboardsAndFolders(ctx context.Context, svc Service) bool {

@ -9,7 +9,7 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema"
dashboard "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v1alpha1"
folders "github.com/grafana/grafana/pkg/apis/folder/v1"
folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
)
func TestIsReadingLegacyDashboardsAndFolders(t *testing.T) {

@ -191,7 +191,7 @@ No resources found in default namespace.
To create a folder, create a file `folder-generate.yaml`:
```yaml
apiVersion: folder.grafana.app/v1
apiVersion: folder.grafana.app/v1beta1
kind: Folder
metadata:
generateName: x # anything is ok here... except yes or true -- they become boolean!

@ -17,7 +17,7 @@ require (
github.com/grafana/authlib/types v0.0.0-20250325095148-d6da9c164a7d
github.com/grafana/grafana v11.4.0-00010101000000-000000000000+incompatible
github.com/grafana/grafana/apps/dashboard v0.0.0-20250317130411-3f270d1de043
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250401081501-6af5fbf3fff0
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250414114055-2b279efe15bf
github.com/grafana/grafana/pkg/apiserver v0.0.0-20250325075903-77fa2271be7a
github.com/grafana/grafana/pkg/storage/unified/resource v0.0.0-20250317130411-3f270d1de043
github.com/stretchr/testify v1.10.0
@ -211,8 +211,8 @@ require (
github.com/grafana/grafana-aws-sdk v0.31.5 // indirect
github.com/grafana/grafana-azure-sdk-go/v2 v2.1.6 // indirect
github.com/grafana/grafana-plugin-sdk-go v0.275.0 // indirect
github.com/grafana/grafana/apps/folder v0.0.0-20250414115220-48647355c37b // indirect
github.com/grafana/grafana/pkg/aggregator v0.0.0-20250220163425-b4c4b9abbdc8 // indirect
github.com/grafana/grafana/pkg/apis/folder v0.0.0-20250411131846-e7b32d622991 // indirect
github.com/grafana/grafana/pkg/promlib v0.0.8 // indirect
github.com/grafana/grafana/pkg/semconv v0.0.0-20250220164708-c8d4ff28a450 // indirect
github.com/grafana/otel-profiling-go v0.5.1 // indirect

@ -1273,10 +1273,10 @@ github.com/grafana/grafana-plugin-sdk-go v0.275.0 h1:icGmZG91lVqIo79w/pSki6N44d3
github.com/grafana/grafana-plugin-sdk-go v0.275.0/go.mod h1:mO9LJqdXDh5JpO/xIdPAeg5LdThgQ06Y/SLpXDWKw2c=
github.com/grafana/grafana/apps/dashboard v0.0.0-20250317130411-3f270d1de043 h1:wdJy5x6M7auWDjUIubqhfZuZvphUMyjD7hxB3RqV4aE=
github.com/grafana/grafana/apps/dashboard v0.0.0-20250317130411-3f270d1de043/go.mod h1:jwYig4wlnLLq4HQKDpS95nDeZi4+DmcD17KYYS1gMJg=
github.com/grafana/grafana/apps/folder v0.0.0-20250414115220-48647355c37b h1:n571OboxBgEnhAFnnc/soawXRsTsQYOaFC6Mn+iWPyI=
github.com/grafana/grafana/apps/folder v0.0.0-20250414115220-48647355c37b/go.mod h1:l7SqBgPw4c9iLCq/tVDAbrbsBdAHPIDF8xk0CdGHD/s=
github.com/grafana/grafana/pkg/aggregator v0.0.0-20250220163425-b4c4b9abbdc8 h1:9qOLpC21AmXZqZ6rUhrBWl2mVqS3CzV53pzw0BCuHt0=
github.com/grafana/grafana/pkg/aggregator v0.0.0-20250220163425-b4c4b9abbdc8/go.mod h1:deLQ/ywLvpVGbncRGUA4UDGt8a5Ei9sivOP+x6AQ2ko=
github.com/grafana/grafana/pkg/apis/folder v0.0.0-20250411131846-e7b32d622991 h1:3gcAHB3K1tSJ3jPY7EYm4G/TBimwcETyZVFQDsx18iA=
github.com/grafana/grafana/pkg/apis/folder v0.0.0-20250411131846-e7b32d622991/go.mod h1:Lmze5IWgV2qTGY0l1JQGRXpWoNGfeGX/HXdc8ByMfE4=
github.com/grafana/grafana/pkg/promlib v0.0.8 h1:VUWsqttdf0wMI4j9OX9oNrykguQpZcruudDAFpJJVw0=
github.com/grafana/grafana/pkg/promlib v0.0.8/go.mod h1:U1ezG/MGaEPoThqsr3lymMPN5yIPdVTJnDZ+wcXT+ao=
github.com/grafana/grafana/pkg/semconv v0.0.0-20250220164708-c8d4ff28a450 h1:wSqgLKFwI7fyeqf3djRXGClBLb/UPjZ4XPm/UsKFDB0=

@ -3,12 +3,14 @@ module github.com/grafana/grafana/pkg/storage/unified/resource
go 1.24.2
replace (
github.com/grafana/grafana/apps/folder => ../../../../apps/folder
github.com/grafana/grafana/pkg/apimachinery => ../../../apimachinery
github.com/grafana/grafana/pkg/apiserver => ../../../apiserver
)
require (
github.com/fullstorydev/grpchan v1.1.1
github.com/go-jose/go-jose/v3 v3.0.4
github.com/google/uuid v1.6.0
github.com/grafana/authlib v0.0.0-20250325095148-d6da9c164a7d
github.com/grafana/authlib/types v0.0.0-20250325095148-d6da9c164a7d
@ -16,7 +18,8 @@ require (
github.com/grafana/grafana-app-sdk/logging v0.35.1
github.com/grafana/grafana-plugin-sdk-go v0.275.0
github.com/grafana/grafana/apps/dashboard v0.0.0-20250317130411-3f270d1de043
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250401081501-6af5fbf3fff0
github.com/grafana/grafana/apps/folder v0.0.0-20250402082028-6781612335d9
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250414114055-2b279efe15bf
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.1
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3
github.com/hashicorp/golang-lru/v2 v2.0.7
@ -31,11 +34,6 @@ require (
k8s.io/apimachinery v0.32.3
)
require (
github.com/go-jose/go-jose/v3 v3.0.4
github.com/grafana/grafana/pkg/apis/folder v0.0.0-20250411131846-e7b32d622991
)
require (
cel.dev/expr v0.19.1 // indirect
cloud.google.com/go v0.118.2 // indirect

@ -273,8 +273,6 @@ github.com/grafana/grafana-plugin-sdk-go v0.275.0 h1:icGmZG91lVqIo79w/pSki6N44d3
github.com/grafana/grafana-plugin-sdk-go v0.275.0/go.mod h1:mO9LJqdXDh5JpO/xIdPAeg5LdThgQ06Y/SLpXDWKw2c=
github.com/grafana/grafana/apps/dashboard v0.0.0-20250317130411-3f270d1de043 h1:wdJy5x6M7auWDjUIubqhfZuZvphUMyjD7hxB3RqV4aE=
github.com/grafana/grafana/apps/dashboard v0.0.0-20250317130411-3f270d1de043/go.mod h1:jwYig4wlnLLq4HQKDpS95nDeZi4+DmcD17KYYS1gMJg=
github.com/grafana/grafana/pkg/apis/folder v0.0.0-20250411131846-e7b32d622991 h1:3gcAHB3K1tSJ3jPY7EYm4G/TBimwcETyZVFQDsx18iA=
github.com/grafana/grafana/pkg/apis/folder v0.0.0-20250411131846-e7b32d622991/go.mod h1:Lmze5IWgV2qTGY0l1JQGRXpWoNGfeGX/HXdc8ByMfE4=
github.com/grafana/otel-profiling-go v0.5.1 h1:stVPKAFZSa7eGiqbYuG25VcqYksR6iWvF3YH66t4qL8=
github.com/grafana/otel-profiling-go v0.5.1/go.mod h1:ftN/t5A/4gQI19/8MoWurBEtC6gFw8Dns1sJZ9W4Tls=
github.com/grafana/pyroscope-go/godeltaprof v0.1.8 h1:iwOtYXeeVSAeYefJNaxDytgjKtUuKQbJqgAIjlnicKg=

@ -16,10 +16,9 @@ import (
"golang.org/x/sync/errgroup"
"k8s.io/apimachinery/pkg/runtime/schema"
dashboardv1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v1alpha1"
folders "github.com/grafana/grafana/pkg/apis/folder/v1"
"github.com/grafana/authlib/types"
dashboardv1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v1alpha1"
folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
)
type NamespacedResource struct {

@ -1,6 +1,6 @@
{
"kind": "Folder",
"apiVersion": "folder.grafana.app/v1",
"apiVersion": "folder.grafana.app/v1beta1",
"metadata": {
"name": "ae2ntrqxefvnke",
"namespace": "default",

@ -1,6 +1,6 @@
{
"kind": "Folder",
"apiVersion": "folder.grafana.app/v1",
"apiVersion": "folder.grafana.app/v1beta1",
"metadata": {
"name": "ae2ntrqxefvnke",
"namespace": "default",

@ -1,6 +1,6 @@
{
"kind": "Folder",
"apiVersion": "folder.grafana.app/v1",
"apiVersion": "folder.grafana.app/v1beta1",
"metadata": {
"name": "aaa",
"namespace": "default",

@ -1,6 +1,6 @@
{
"kind": "Folder",
"apiVersion": "folder.grafana.app/v1",
"apiVersion": "folder.grafana.app/v1beta1",
"metadata": {
"name": "bbb",
"namespace": "default",

@ -10,7 +10,7 @@ import (
dashboardv0alpha1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v0alpha1"
dashboardv1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v1alpha1"
dashboardv2alpha1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1"
folders "github.com/grafana/grafana/pkg/apis/folder/v1"
folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
"github.com/grafana/grafana/pkg/apiserver/rest"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/folder"

@ -7,7 +7,6 @@ import (
"fmt"
"net/http"
"slices"
"testing"
"github.com/stretchr/testify/require"
@ -16,9 +15,9 @@ import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
"github.com/grafana/grafana/pkg/api"
"github.com/grafana/grafana/pkg/api/dtos"
folders "github.com/grafana/grafana/pkg/apis/folder/v1"
grafanarest "github.com/grafana/grafana/pkg/apiserver/rest"
"github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions"
"github.com/grafana/grafana/pkg/services/dashboards"
@ -37,8 +36,8 @@ func TestMain(m *testing.M) {
}
var gvr = schema.GroupVersionResource{
Group: "folder.grafana.app",
Version: "v1",
Group: folders.GROUP,
Version: folders.VERSION,
Resource: "folders",
}
@ -55,7 +54,7 @@ func TestIntegrationFoldersApp(t *testing.T) {
t.Run("Check discovery client", func(t *testing.T) {
disco := helper.NewDiscoveryClient()
resources, err := disco.ServerResourcesForGroupVersion("folder.grafana.app/v1")
resources, err := disco.ServerResourcesForGroupVersion("folder.grafana.app/v1beta1")
require.NoError(t, err)
v1Disco, err := json.MarshalIndent(resources, "", " ")
@ -64,52 +63,52 @@ func TestIntegrationFoldersApp(t *testing.T) {
require.JSONEq(t, `{
"kind": "APIResourceList",
"apiVersion": "v1",
"groupVersion": "folder.grafana.app/v1",
"groupVersion": "folder.grafana.app/v1beta1",
"resources": [
{
"name": "folders",
"singularName": "folder",
"namespaced": true,
"kind": "Folder",
"verbs": [
"create",
"delete",
"deletecollection",
"get",
"list",
"patch",
"update"
]
},
{
"name": "folders/access",
"singularName": "",
"namespaced": true,
"kind": "FolderAccessInfo",
"verbs": [
"get"
]
},
{
"name": "folders/counts",
"singularName": "",
"namespaced": true,
"kind": "DescendantCounts",
"verbs": [
"get"
]
},
{
"name": "folders/parents",
"singularName": "",
"namespaced": true,
"kind": "FolderInfoList",
"verbs": [
"get"
]
}
{
"name": "folders",
"singularName": "folder",
"namespaced": true,
"kind": "Folder",
"verbs": [
"create",
"delete",
"deletecollection",
"get",
"list",
"patch",
"update"
]
},
{
"name": "folders/access",
"singularName": "",
"namespaced": true,
"kind": "FolderAccessInfo",
"verbs": [
"get"
]
},
{
"name": "folders/counts",
"singularName": "",
"namespaced": true,
"kind": "DescendantCounts",
"verbs": [
"get"
]
},
{
"name": "folders/parents",
"singularName": "",
"namespaced": true,
"kind": "FolderInfoList",
"verbs": [
"get"
]
}
]
}`, string(v1Disco))
}`, string(v1Disco))
})
t.Run("with dual write (unified storage, mode 0)", func(t *testing.T) {
@ -238,7 +237,7 @@ func doFolderTests(t *testing.T, helper *apis.K8sTestHelper) *apis.K8sTestHelper
require.NotEmpty(t, uid)
expectedResult := `{
"apiVersion": "folder.grafana.app/v1",
"apiVersion": "folder.grafana.app/v1beta1",
"kind": "Folder",
"metadata": {
"creationTimestamp": "${creationTimestamp}",
@ -250,7 +249,8 @@ func doFolderTests(t *testing.T, helper *apis.K8sTestHelper) *apis.K8sTestHelper
},
"spec": {
"title": "Test"
}
},
"status": {}
}`
// Get should return the same result

@ -1,4 +1,4 @@
apiVersion: folder.grafana.app/v1
apiVersion: folder.grafana.app/v1beta1
kind: Folder
metadata:
generateName: x # anything is ok here... except yes or true -- they become boolean!

@ -1,4 +1,4 @@
apiVersion: folder.grafana.app/v1
apiVersion: folder.grafana.app/v1beta1
kind: Folder
metadata:
name: test

@ -1,4 +1,4 @@
apiVersion: folder.grafana.app/v1
apiVersion: folder.grafana.app/v1beta1
kind: Folder
metadata:
name: test

File diff suppressed because it is too large Load Diff

@ -2,10 +2,10 @@
"openapi": "3.0.0",
"info": {
"description": "Grafana folders",
"title": "folder.grafana.app/v0alpha1"
"title": "folder.grafana.app/v1beta1"
},
"paths": {
"/apis/folder.grafana.app/v0alpha1/": {
"/apis/folder.grafana.app/v1beta1/": {
"get": {
"tags": [
"API Discovery"
@ -36,7 +36,7 @@
}
}
},
"/apis/folder.grafana.app/v0alpha1/namespaces/{namespace}/folders": {
"/apis/folder.grafana.app/v1beta1/namespaces/{namespace}/folders": {
"get": {
"tags": [
"Folder"
@ -141,27 +141,27 @@
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.FolderList"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.FolderList"
}
},
"application/json;stream=watch": {
"schema": {
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.FolderList"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.FolderList"
}
},
"application/vnd.kubernetes.protobuf": {
"schema": {
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.FolderList"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.FolderList"
}
},
"application/vnd.kubernetes.protobuf;stream=watch": {
"schema": {
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.FolderList"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.FolderList"
}
},
"application/yaml": {
"schema": {
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.FolderList"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.FolderList"
}
}
}
@ -170,7 +170,7 @@
"x-kubernetes-action": "list",
"x-kubernetes-group-version-kind": {
"group": "folder.grafana.app",
"version": "v0alpha1",
"version": "v1beta1",
"kind": "Folder"
}
},
@ -213,17 +213,17 @@
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.Folder"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.Folder"
}
},
"application/vnd.kubernetes.protobuf": {
"schema": {
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.Folder"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.Folder"
}
},
"application/yaml": {
"schema": {
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.Folder"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.Folder"
}
}
},
@ -235,17 +235,17 @@
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.Folder"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.Folder"
}
},
"application/vnd.kubernetes.protobuf": {
"schema": {
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.Folder"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.Folder"
}
},
"application/yaml": {
"schema": {
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.Folder"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.Folder"
}
}
}
@ -255,17 +255,17 @@
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.Folder"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.Folder"
}
},
"application/vnd.kubernetes.protobuf": {
"schema": {
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.Folder"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.Folder"
}
},
"application/yaml": {
"schema": {
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.Folder"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.Folder"
}
}
}
@ -275,17 +275,17 @@
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.Folder"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.Folder"
}
},
"application/vnd.kubernetes.protobuf": {
"schema": {
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.Folder"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.Folder"
}
},
"application/yaml": {
"schema": {
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.Folder"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.Folder"
}
}
}
@ -294,7 +294,7 @@
"x-kubernetes-action": "post",
"x-kubernetes-group-version-kind": {
"group": "folder.grafana.app",
"version": "v0alpha1",
"version": "v1beta1",
"kind": "Folder"
}
},
@ -448,7 +448,7 @@
"x-kubernetes-action": "deletecollection",
"x-kubernetes-group-version-kind": {
"group": "folder.grafana.app",
"version": "v0alpha1",
"version": "v1beta1",
"kind": "Folder"
}
},
@ -474,7 +474,7 @@
}
]
},
"/apis/folder.grafana.app/v0alpha1/namespaces/{namespace}/folders/{name}": {
"/apis/folder.grafana.app/v1beta1/namespaces/{namespace}/folders/{name}": {
"get": {
"tags": [
"Folder"
@ -487,17 +487,17 @@
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.Folder"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.Folder"
}
},
"application/vnd.kubernetes.protobuf": {
"schema": {
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.Folder"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.Folder"
}
},
"application/yaml": {
"schema": {
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.Folder"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.Folder"
}
}
}
@ -506,7 +506,7 @@
"x-kubernetes-action": "get",
"x-kubernetes-group-version-kind": {
"group": "folder.grafana.app",
"version": "v0alpha1",
"version": "v1beta1",
"kind": "Folder"
}
},
@ -549,17 +549,17 @@
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.Folder"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.Folder"
}
},
"application/vnd.kubernetes.protobuf": {
"schema": {
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.Folder"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.Folder"
}
},
"application/yaml": {
"schema": {
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.Folder"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.Folder"
}
}
},
@ -571,17 +571,17 @@
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.Folder"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.Folder"
}
},
"application/vnd.kubernetes.protobuf": {
"schema": {
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.Folder"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.Folder"
}
},
"application/yaml": {
"schema": {
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.Folder"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.Folder"
}
}
}
@ -591,17 +591,17 @@
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.Folder"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.Folder"
}
},
"application/vnd.kubernetes.protobuf": {
"schema": {
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.Folder"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.Folder"
}
},
"application/yaml": {
"schema": {
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.Folder"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.Folder"
}
}
}
@ -610,7 +610,7 @@
"x-kubernetes-action": "put",
"x-kubernetes-group-version-kind": {
"group": "folder.grafana.app",
"version": "v0alpha1",
"version": "v1beta1",
"kind": "Folder"
}
},
@ -712,7 +712,7 @@
"x-kubernetes-action": "delete",
"x-kubernetes-group-version-kind": {
"group": "folder.grafana.app",
"version": "v0alpha1",
"version": "v1beta1",
"kind": "Folder"
}
},
@ -791,17 +791,17 @@
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.Folder"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.Folder"
}
},
"application/vnd.kubernetes.protobuf": {
"schema": {
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.Folder"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.Folder"
}
},
"application/yaml": {
"schema": {
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.Folder"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.Folder"
}
}
}
@ -811,17 +811,17 @@
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.Folder"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.Folder"
}
},
"application/vnd.kubernetes.protobuf": {
"schema": {
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.Folder"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.Folder"
}
},
"application/yaml": {
"schema": {
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.Folder"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.Folder"
}
}
}
@ -830,7 +830,7 @@
"x-kubernetes-action": "patch",
"x-kubernetes-group-version-kind": {
"group": "folder.grafana.app",
"version": "v0alpha1",
"version": "v1beta1",
"kind": "Folder"
}
},
@ -866,7 +866,7 @@
}
]
},
"/apis/folder.grafana.app/v0alpha1/namespaces/{namespace}/folders/{name}/access": {
"/apis/folder.grafana.app/v1beta1/namespaces/{namespace}/folders/{name}/access": {
"get": {
"tags": [
"Folder"
@ -879,7 +879,7 @@
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.FolderAccessInfo"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.FolderAccessInfo"
}
}
}
@ -888,7 +888,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "folder.grafana.app",
"version": "v0alpha1",
"version": "v1beta1",
"kind": "FolderAccessInfo"
}
},
@ -915,7 +915,7 @@
}
]
},
"/apis/folder.grafana.app/v0alpha1/namespaces/{namespace}/folders/{name}/counts": {
"/apis/folder.grafana.app/v1beta1/namespaces/{namespace}/folders/{name}/counts": {
"get": {
"tags": [
"Folder"
@ -928,7 +928,7 @@
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.DescendantCounts"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.DescendantCounts"
}
}
}
@ -937,7 +937,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "folder.grafana.app",
"version": "v0alpha1",
"version": "v1beta1",
"kind": "DescendantCounts"
}
},
@ -964,7 +964,7 @@
}
]
},
"/apis/folder.grafana.app/v0alpha1/namespaces/{namespace}/folders/{name}/parents": {
"/apis/folder.grafana.app/v1beta1/namespaces/{namespace}/folders/{name}/parents": {
"get": {
"tags": [
"Folder"
@ -977,7 +977,7 @@
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.FolderInfoList"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.FolderInfoList"
}
}
}
@ -986,7 +986,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "folder.grafana.app",
"version": "v0alpha1",
"version": "v1beta1",
"kind": "FolderInfoList"
}
},
@ -1016,7 +1016,7 @@
},
"components": {
"schemas": {
"com.github.grafana.grafana.pkg.apis.folder.v0alpha1.DescendantCounts": {
"com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.DescendantCounts": {
"type": "object",
"required": [
"counts"
@ -1032,7 +1032,7 @@
"default": {},
"allOf": [
{
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.ResourceStats"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.ResourceStats"
}
]
}
@ -1051,12 +1051,17 @@
{
"group": "folder.grafana.app",
"kind": "DescendantCounts",
"version": "v0alpha1"
"version": "v1beta1"
}
]
},
"com.github.grafana.grafana.pkg.apis.folder.v0alpha1.Folder": {
"com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.Folder": {
"type": "object",
"required": [
"metadata",
"spec",
"status"
],
"properties": {
"apiVersion": {
"description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
@ -1075,10 +1080,19 @@
]
},
"spec": {
"description": "Spec is the spec of the Folder",
"default": {},
"allOf": [
{
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.Spec"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.FolderSpec"
}
]
},
"status": {
"default": {},
"allOf": [
{
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.FolderStatus"
}
]
}
@ -1092,11 +1106,11 @@
{
"group": "folder.grafana.app",
"kind": "Folder",
"version": "v0alpha1"
"version": "v1beta1"
}
]
},
"com.github.grafana.grafana.pkg.apis.folder.v0alpha1.FolderAccessInfo": {
"com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.FolderAccessInfo": {
"description": "Access control information for the current user",
"type": "object",
"required": [
@ -1140,11 +1154,11 @@
{
"group": "folder.grafana.app",
"kind": "FolderAccessInfo",
"version": "v0alpha1"
"version": "v1beta1"
}
]
},
"com.github.grafana.grafana.pkg.apis.folder.v0alpha1.FolderInfo": {
"com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.FolderInfo": {
"description": "FolderInfo briefly describes a folder -- unlike a folder resource, this is a partial record of the folder metadata used for navigating parents and children",
"type": "object",
"required": [
@ -1176,7 +1190,7 @@
}
}
},
"com.github.grafana.grafana.pkg.apis.folder.v0alpha1.FolderInfoList": {
"com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.FolderInfoList": {
"description": "FolderInfoList returns a list of folder references (parents or children) Unlike FolderList, each item is not a full k8s object",
"type": "object",
"properties": {
@ -1190,7 +1204,7 @@
"default": {},
"allOf": [
{
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.FolderInfo"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.FolderInfo"
}
]
},
@ -1221,12 +1235,16 @@
{
"group": "folder.grafana.app",
"kind": "FolderInfoList",
"version": "v0alpha1"
"version": "v1beta1"
}
]
},
"com.github.grafana.grafana.pkg.apis.folder.v0alpha1.FolderList": {
"com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.FolderList": {
"type": "object",
"required": [
"metadata",
"items"
],
"properties": {
"apiVersion": {
"description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
@ -1238,7 +1256,7 @@
"default": {},
"allOf": [
{
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.folder.v0alpha1.Folder"
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.Folder"
}
]
}
@ -1265,11 +1283,30 @@
{
"group": "folder.grafana.app",
"kind": "FolderList",
"version": "v0alpha1"
"version": "v1beta1"
}
]
},
"com.github.grafana.grafana.pkg.apis.folder.v0alpha1.ResourceStats": {
"com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.FolderSpec": {
"type": "object",
"required": [
"title"
],
"properties": {
"description": {
"type": "string"
},
"title": {
"type": "string",
"default": ""
}
}
},
"com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.FolderStatus": {
"description": "Empty stub",
"type": "object"
},
"com.github.grafana.grafana.apps.folder.pkg.apis.folder.v1beta1.ResourceStats": {
"type": "object",
"required": [
"group",
@ -1292,23 +1329,6 @@
}
}
},
"com.github.grafana.grafana.pkg.apis.folder.v0alpha1.Spec": {
"type": "object",
"required": [
"title"
],
"properties": {
"description": {
"description": "Describe the feature toggle",
"type": "string"
},
"title": {
"description": "Describe the feature toggle",
"type": "string",
"default": ""
}
}
},
"io.k8s.apimachinery.pkg.apis.meta.v1.APIResource": {
"description": "APIResource specifies the name of a resource and whether it is namespaced.",
"type": "object",

@ -71,7 +71,7 @@ func TestIntegrationOpenAPIs(t *testing.T) {
Version: "v2alpha1",
}, {
Group: "folder.grafana.app",
Version: "v1",
Version: "v1beta1",
}, {
Group: "provisioning.grafana.app",
Version: "v0alpha1",

@ -24,7 +24,7 @@ import (
"k8s.io/client-go/rest"
dashboard "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v1alpha1"
folder "github.com/grafana/grafana/pkg/apis/folder/v1"
folder "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1"
grafanarest "github.com/grafana/grafana/pkg/apiserver/rest"
"github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs"

@ -108,17 +108,18 @@ export type ObjectMeta = {
Populated by the system. Read-only. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#uids */
uid?: string;
};
export type Spec = {
/** Describe the feature toggle */
export type FolderSpec = {
description?: string;
/** Describe the feature toggle */
title: string;
};
export type FolderStatus = object;
export type Folder = {
/** APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources */
apiVersion?: string;
/** 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;
metadata?: ObjectMeta;
spec?: Spec;
metadata: ObjectMeta;
/** Spec is the spec of the Folder */
spec: FolderSpec;
status: FolderStatus;
};

@ -3,5 +3,6 @@ import { generatedAPI } from './endpoints.gen';
export const folderAPI = generatedAPI.enhanceEndpoints({});
export const { useGetFolderQuery } = folderAPI;
// eslint-disable-next-line no-barrel-files/no-barrel-files
export { type Spec, type Folder } from './endpoints.gen';
export { type Folder } from './endpoints.gen';

@ -56,7 +56,7 @@ const config: ConfigFile = {
},
'../public/app/api/clients/folder/endpoints.gen.ts': {
apiFile: '../public/app/api/clients/folder/baseAPI.ts',
schemaFile: '../data/openapi/folder.grafana.app-v0alpha1.json',
schemaFile: '../data/openapi/folder.grafana.app-v1beta1.json',
filterEndpoints: ['getFolder'],
tag: true,
},

Loading…
Cancel
Save