diff --git a/api/v1beta1/grafanadatasource_types.go b/api/v1beta1/grafanadatasource_types.go index f45da5887..dbdcd5a4e 100644 --- a/api/v1beta1/grafanadatasource_types.go +++ b/api/v1beta1/grafanadatasource_types.go @@ -17,16 +17,15 @@ limitations under the License. package v1beta1 import ( - "bytes" "encoding/json" - "errors" - "fmt" "time" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) type GrafanaDatasourceInternal struct { + // Deprecated field, use spec.uid instead + // +optional UID string `json:"uid,omitempty"` Name string `json:"name,omitempty"` Type string `json:"type,omitempty"` @@ -40,7 +39,9 @@ type GrafanaDatasourceInternal struct { // Deprecated field, it has no effect OrgID *int64 `json:"orgId,omitempty"` - // Deprecated field, it has no effect + + // Whether to enable/disable editing of the datasource in Grafana UI + // +optional Editable *bool `json:"editable,omitempty"` // +kubebuilder:validation:Schemaless @@ -57,7 +58,13 @@ type GrafanaDatasourceInternal struct { } // GrafanaDatasourceSpec defines the desired state of GrafanaDatasource +// +kubebuilder:validation:XValidation:rule="((!has(oldSelf.uid) && !has(self.uid)) || (has(oldSelf.uid) && has(self.uid)))", message="spec.uid is immutable" type GrafanaDatasourceSpec struct { + // The UID, for the datasource, fallback to the deprecated spec.datasource.uid and metadata.uid + // +optional + // +kubebuilder:validation:XValidation:rule="self == oldSelf",message="spec.uid is immutable" + CustomUID string `json:"uid,omitempty"` + Datasource *GrafanaDatasourceInternal `json:"datasource"` // selects Grafana instances for import @@ -146,37 +153,26 @@ func (in *GrafanaDatasource) Unchanged(hash string) bool { return in.Status.Hash == hash } -func (in *GrafanaDatasource) IsUpdatedUID(uid string) bool { +func (in *GrafanaDatasource) IsUpdatedUID() bool { // Datasource has just been created, status is not yet updated if in.Status.UID == "" { return false } - if uid == "" { - uid = string(in.UID) - } - - return in.Status.UID != uid + return in.Status.UID != in.CustomUIDOrUID() } -func (in *GrafanaDatasource) ExpandVariables(variables map[string][]byte) ([]byte, error) { - if in.Spec.Datasource == nil { - return nil, errors.New("data source is empty, can't expand variables") - } - - raw, err := json.Marshal(in.Spec.Datasource) - if err != nil { - return nil, err +// Wrapper around CustomUID, datasourcelUID or default metadata.uid +func (in *GrafanaDatasource) CustomUIDOrUID() string { + if in.Spec.CustomUID != "" { + return in.Spec.CustomUID } - for key, value := range variables { - patterns := []string{fmt.Sprintf("$%v", key), fmt.Sprintf("${%v}", key)} - for _, pattern := range patterns { - raw = bytes.ReplaceAll(raw, []byte(pattern), value) - } + if in.Spec.Datasource.UID != "" { + return in.Spec.Datasource.UID } - return raw, nil + return string(in.ObjectMeta.UID) } func (in *GrafanaDatasource) IsAllowCrossNamespaceImport() bool { diff --git a/api/v1beta1/grafanadatasource_types_test.go b/api/v1beta1/grafanadatasource_types_test.go index e1727afee..97daedc04 100644 --- a/api/v1beta1/grafanadatasource_types_test.go +++ b/api/v1beta1/grafanadatasource_types_test.go @@ -1,62 +1,70 @@ package v1beta1 import ( - "bytes" - "fmt" - "testing" -) + "context" -func TestGrafanaDatasources_expandVariables(t *testing.T) { - type testcase struct { - name string - variables map[string][]byte - in GrafanaDatasource - out []byte - } + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) - testcases := []testcase{ - { - name: "basic replacement", - variables: map[string][]byte{ - "PROMETHEUS_USERNAME": []byte("root"), - }, - in: GrafanaDatasource{ - Spec: GrafanaDatasourceSpec{ - Datasource: &GrafanaDatasourceInternal{ - Name: "prometheus", - User: "${PROMETHEUS_USERNAME}", - }, - }, - }, - out: []byte("{\"name\":\"prometheus\",\"user\":\"root\"}"), +func newDatasource(name string, uid string) *GrafanaDatasource { + return &GrafanaDatasource{ + TypeMeta: v1.TypeMeta{ + APIVersion: APIVersion, + Kind: "GrafanaDatasource", }, - { - name: "replacement without curly braces", - variables: map[string][]byte{ - "PROMETHEUS_USERNAME": []byte("root"), - }, - in: GrafanaDatasource{ - Spec: GrafanaDatasourceSpec{ - Datasource: &GrafanaDatasourceInternal{ - Name: "prometheus", - User: "$PROMETHEUS_USERNAME", - }, + ObjectMeta: v1.ObjectMeta{ + Name: name, + Namespace: "default", + }, + Spec: GrafanaDatasourceSpec{ + CustomUID: uid, + InstanceSelector: &v1.LabelSelector{ + MatchLabels: map[string]string{ + "test": "datasource", }, }, - out: []byte("{\"name\":\"prometheus\",\"user\":\"root\"}"), + Datasource: &GrafanaDatasourceInternal{ + Name: "testdata", + Type: "grafana-testdata-datasource", + Access: "proxy", + }, }, } +} - for _, tc := range testcases { - t.Run(tc.name, func(t *testing.T) { - b, err := tc.in.ExpandVariables(tc.variables) - if err != nil { - t.Fatal(err) - } +var _ = Describe("Datasource type", func() { + Context("Ensure Datasource spec.uid is immutable", func() { + ctx := context.Background() + It("Should block adding uid field when missing", func() { + ds := newDatasource("missing-uid", "") + By("Create new Datasource without uid") + Expect(k8sClient.Create(ctx, ds)).To(Succeed()) - if !bytes.Equal(b, tc.out) { - t.Error(fmt.Errorf("expected %v, but got %v", string(tc.out), string(b))) - } + By("Adding a uid") + ds.Spec.CustomUID = "new-uid" + Expect(k8sClient.Update(ctx, ds)).To(HaveOccurred()) }) - } -} + + It("Should block removing uid field when set", func() { + ds := newDatasource("existing-uid", "existing-uid") + By("Creating Datasource with existing UID") + Expect(k8sClient.Create(ctx, ds)).To(Succeed()) + + By("And setting UID to ''") + ds.Spec.CustomUID = "" + Expect(k8sClient.Update(ctx, ds)).To(HaveOccurred()) + }) + + It("Should block changing value of uid", func() { + ds := newDatasource("removing-uid", "existing-uid") + By("Create new Datasource with existing UID") + Expect(k8sClient.Create(ctx, ds)).To(Succeed()) + + By("Changing the existing UID") + ds.Spec.CustomUID = "new-uid" + Expect(k8sClient.Update(ctx, ds)).To(HaveOccurred()) + }) + }) +}) diff --git a/api/v1beta1/suite_test.go b/api/v1beta1/suite_test.go new file mode 100644 index 000000000..9a4a36826 --- /dev/null +++ b/api/v1beta1/suite_test.go @@ -0,0 +1,80 @@ +/* +Copyright 2022. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1beta1 + +import ( + "path/filepath" + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/envtest" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/log/zap" + //+kubebuilder:scaffold:imports +) + +// These tests use Ginkgo (BDD-style Go testing framework). Refer to +// http://onsi.github.io/ginkgo/ to learn more about Ginkgo. + +const ( + APIVersion = "grafana.integreatly.org/v1beta1" +) + +var ( + cfg *rest.Config + k8sClient client.Client + testEnv *envtest.Environment +) + +func TestAPIs(t *testing.T) { + RegisterFailHandler(Fail) + + RunSpecs(t, "CRDs Suite") +} + +var _ = BeforeSuite(func() { + logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) + + By("bootstrapping test environment") + testEnv = &envtest.Environment{ + CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")}, + ErrorIfCRDPathMissing: true, + } + + cfg, err := testEnv.Start() + Expect(err).NotTo(HaveOccurred()) + Expect(cfg).NotTo(BeNil()) + + err = AddToScheme(scheme.Scheme) + Expect(err).NotTo(HaveOccurred()) + + //+kubebuilder:scaffold:scheme + + k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) + Expect(err).NotTo(HaveOccurred()) + Expect(k8sClient).NotTo(BeNil()) +}) + +var _ = AfterSuite(func() { + By("tearing down the test environment") + err := testEnv.Stop() + Expect(err).NotTo(HaveOccurred()) +}) diff --git a/config/crd/bases/grafana.integreatly.org_grafanadatasources.yaml b/config/crd/bases/grafana.integreatly.org_grafanadatasources.yaml index 8ee3e9faa..28596b2a5 100644 --- a/config/crd/bases/grafana.integreatly.org_grafanadatasources.yaml +++ b/config/crd/bases/grafana.integreatly.org_grafanadatasources.yaml @@ -67,7 +67,8 @@ spec: database: type: string editable: - description: Deprecated field, it has no effect + description: Whether to enable/disable editing of the datasource + in Grafana UI type: boolean isDefault: type: boolean @@ -86,6 +87,7 @@ spec: type: type: string uid: + description: Deprecated field, use spec.uid instead type: string url: type: string @@ -161,6 +163,13 @@ spec: format: duration pattern: ^([0-9]+(\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$ type: string + uid: + description: The UID, for the datasource, fallback to the deprecated + spec.datasource.uid and metadata.uid + type: string + x-kubernetes-validations: + - message: spec.uid is immutable + rule: self == oldSelf valuesFrom: description: environments variables from secrets or config maps items: @@ -231,6 +240,10 @@ spec: - datasource - instanceSelector type: object + x-kubernetes-validations: + - message: spec.uid is immutable + rule: ((!has(oldSelf.uid) && !has(self.uid)) || (has(oldSelf.uid) && + has(self.uid))) status: description: GrafanaDatasourceStatus defines the observed state of GrafanaDatasource properties: diff --git a/controllers/datasource_controller.go b/controllers/datasource_controller.go index a34cf783f..c99a3cc66 100644 --- a/controllers/datasource_controller.go +++ b/controllers/datasource_controller.go @@ -182,6 +182,9 @@ func (r *GrafanaDatasourceReconciler) Reconcile(ctx context.Context, req ctrl.Re return ctrl.Result{}, nil } + // Overwrite OrgID to ensure the field is useless + cr.Spec.Datasource.OrgID = nil + instances, err := r.GetMatchingDatasourceInstances(ctx, cr, r.Client) if err != nil { controllerLog.Error(err, "could not find matching instances", "name", cr.Name, "namespace", cr.Namespace) @@ -196,7 +199,7 @@ func (r *GrafanaDatasourceReconciler) Reconcile(ctx context.Context, req ctrl.Re return ctrl.Result{RequeueAfter: RequeueDelay}, err } - if cr.IsUpdatedUID(datasource.UID) { + if cr.IsUpdatedUID() { controllerLog.Info("datasource uid got updated, deleting datasources with the old uid") err = r.onDatasourceDeleted(ctx, req.Namespace, req.Name) if err != nil { @@ -258,7 +261,7 @@ func (r *GrafanaDatasourceReconciler) Reconcile(ctx context.Context, req ctrl.Re if cr.ResyncPeriodHasElapsed() { cr.Status.LastResync = metav1.Time{Time: time.Now()} } - cr.Status.UID = datasource.UID + cr.Status.UID = cr.CustomUIDOrUID() return ctrl.Result{RequeueAfter: cr.GetResyncPeriod()}, r.Client.Status().Update(ctx, cr) } else { // if there was an issue with the datasource, update the status @@ -445,9 +448,7 @@ func (r *GrafanaDatasourceReconciler) getDatasourceContent(ctx context.Context, return nil, "", err } - if cr.Spec.Datasource.UID == "" { - simpleContent.Set("uid", string(cr.UID)) - } + simpleContent.Set("uid", cr.CustomUIDOrUID()) for _, ref := range cr.Spec.ValuesFrom { ref := ref diff --git a/controllers/fetchers/suite_test.go b/controllers/fetchers/suite_test.go index 7f6d977a0..6a53a5494 100644 --- a/controllers/fetchers/suite_test.go +++ b/controllers/fetchers/suite_test.go @@ -5,7 +5,7 @@ import ( grafanav1beta1 "github.com/grafana/grafana-operator/v5/api/v1beta1" - "github.com/onsi/ginkgo" + "github.com/onsi/ginkgo/v2" "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/rest" "sigs.k8s.io/controller-runtime/pkg/client" @@ -13,7 +13,7 @@ import ( logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" - . "github.com/onsi/ginkgo" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) @@ -42,18 +42,12 @@ var _ = ginkgo.BeforeSuite(func() { err = grafanav1beta1.AddToScheme(scheme.Scheme) Expect(err).NotTo(HaveOccurred()) - err = grafanav1beta1.AddToScheme(scheme.Scheme) - Expect(err).NotTo(HaveOccurred()) - - err = grafanav1beta1.AddToScheme(scheme.Scheme) - Expect(err).NotTo(HaveOccurred()) - //+kubebuilder:scaffold:scheme k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) Expect(err).NotTo(HaveOccurred()) Expect(k8sClient).NotTo(BeNil()) -}, 60) +}) var _ = AfterSuite(func() { By("tearing down the test environment") diff --git a/controllers/fetchers/url_fetcher_test.go b/controllers/fetchers/url_fetcher_test.go index 42d6e5f20..4f6c04349 100644 --- a/controllers/fetchers/url_fetcher_test.go +++ b/controllers/fetchers/url_fetcher_test.go @@ -10,7 +10,7 @@ import ( "github.com/grafana/grafana-operator/v5/api/v1beta1" - . "github.com/onsi/ginkgo" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) diff --git a/controllers/suite_test.go b/controllers/suite_test.go index 231d9b9bd..db67f41e2 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -20,7 +20,7 @@ import ( "path/filepath" "testing" - . "github.com/onsi/ginkgo" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/rest" @@ -64,18 +64,12 @@ var _ = BeforeSuite(func() { err = grafanav1beta1.AddToScheme(scheme.Scheme) Expect(err).NotTo(HaveOccurred()) - err = grafanav1beta1.AddToScheme(scheme.Scheme) - Expect(err).NotTo(HaveOccurred()) - - err = grafanav1beta1.AddToScheme(scheme.Scheme) - Expect(err).NotTo(HaveOccurred()) - //+kubebuilder:scaffold:scheme k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) Expect(err).NotTo(HaveOccurred()) Expect(k8sClient).NotTo(BeNil()) -}, 60) +}) var _ = AfterSuite(func() { By("tearing down the test environment") diff --git a/deploy/helm/grafana-operator/crds/grafana.integreatly.org_grafanadatasources.yaml b/deploy/helm/grafana-operator/crds/grafana.integreatly.org_grafanadatasources.yaml index 8ee3e9faa..28596b2a5 100644 --- a/deploy/helm/grafana-operator/crds/grafana.integreatly.org_grafanadatasources.yaml +++ b/deploy/helm/grafana-operator/crds/grafana.integreatly.org_grafanadatasources.yaml @@ -67,7 +67,8 @@ spec: database: type: string editable: - description: Deprecated field, it has no effect + description: Whether to enable/disable editing of the datasource + in Grafana UI type: boolean isDefault: type: boolean @@ -86,6 +87,7 @@ spec: type: type: string uid: + description: Deprecated field, use spec.uid instead type: string url: type: string @@ -161,6 +163,13 @@ spec: format: duration pattern: ^([0-9]+(\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$ type: string + uid: + description: The UID, for the datasource, fallback to the deprecated + spec.datasource.uid and metadata.uid + type: string + x-kubernetes-validations: + - message: spec.uid is immutable + rule: self == oldSelf valuesFrom: description: environments variables from secrets or config maps items: @@ -231,6 +240,10 @@ spec: - datasource - instanceSelector type: object + x-kubernetes-validations: + - message: spec.uid is immutable + rule: ((!has(oldSelf.uid) && !has(self.uid)) || (has(oldSelf.uid) && + has(self.uid))) status: description: GrafanaDatasourceStatus defines the observed state of GrafanaDatasource properties: diff --git a/deploy/kustomize/base/crds.yaml b/deploy/kustomize/base/crds.yaml index e7680805a..8afd9d2d4 100644 --- a/deploy/kustomize/base/crds.yaml +++ b/deploy/kustomize/base/crds.yaml @@ -1141,7 +1141,8 @@ spec: database: type: string editable: - description: Deprecated field, it has no effect + description: Whether to enable/disable editing of the datasource + in Grafana UI type: boolean isDefault: type: boolean @@ -1160,6 +1161,7 @@ spec: type: type: string uid: + description: Deprecated field, use spec.uid instead type: string url: type: string @@ -1235,6 +1237,13 @@ spec: format: duration pattern: ^([0-9]+(\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$ type: string + uid: + description: The UID, for the datasource, fallback to the deprecated + spec.datasource.uid and metadata.uid + type: string + x-kubernetes-validations: + - message: spec.uid is immutable + rule: self == oldSelf valuesFrom: description: environments variables from secrets or config maps items: @@ -1305,6 +1314,10 @@ spec: - datasource - instanceSelector type: object + x-kubernetes-validations: + - message: spec.uid is immutable + rule: ((!has(oldSelf.uid) && !has(self.uid)) || (has(oldSelf.uid) && + has(self.uid))) status: description: GrafanaDatasourceStatus defines the observed state of GrafanaDatasource properties: diff --git a/docs/docs/api.md b/docs/docs/api.md index 8e249f1e7..18db5cd58 100644 --- a/docs/docs/api.md +++ b/docs/docs/api.md @@ -2258,6 +2258,8 @@ GrafanaDatasource is the Schema for the grafanadatasources API object GrafanaDatasourceSpec defines the desired state of GrafanaDatasource
+
+ Validations:
  • ((!has(oldSelf.uid) && !has(self.uid)) || (has(oldSelf.uid) && has(self.uid))): spec.uid is immutable
  • false @@ -2327,6 +2329,15 @@ GrafanaDatasourceSpec defines the desired state of GrafanaDatasource Default: 5m
    false + + uid + string + + The UID, for the datasource, fallback to the deprecated spec.datasource.uid and metadata.uid
    +
    + Validations:
  • self == oldSelf: spec.uid is immutable
  • + + false valuesFrom []object @@ -2386,7 +2397,7 @@ GrafanaDatasourceSpec defines the desired state of GrafanaDatasource editable boolean - Deprecated field, it has no effect
    + Whether to enable/disable editing of the datasource in Grafana UI
    false @@ -2437,7 +2448,7 @@ GrafanaDatasourceSpec defines the desired state of GrafanaDatasource uid string -
    + Deprecated field, use spec.uid instead
    false diff --git a/go.mod b/go.mod index 064bd5fe6..551e24699 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/go-openapi/strfmt v0.23.0 github.com/google/go-jsonnet v0.20.0 github.com/grafana/grafana-openapi-client-go v0.0.0-20240430202104-3ad0f7e4ee52 - github.com/onsi/ginkgo v1.16.5 + github.com/onsi/ginkgo/v2 v2.21.0 github.com/onsi/gomega v1.35.1 github.com/openshift/api v3.9.0+incompatible github.com/pkg/errors v0.9.1 @@ -33,7 +33,9 @@ require ( github.com/go-openapi/runtime v0.28.0 // indirect github.com/go-openapi/spec v0.21.0 // indirect github.com/go-openapi/validate v0.24.0 // indirect + github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/google/gnostic-models v0.6.8 // indirect + github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db // indirect github.com/klauspost/compress v1.17.9 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/oklog/ulid v1.3.1 // indirect @@ -45,6 +47,7 @@ require ( go.opentelemetry.io/otel/trace v1.28.0 // indirect golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect golang.org/x/sync v0.8.0 // indirect + golang.org/x/tools v0.26.0 // indirect ) require ( diff --git a/go.sum b/go.sum index 50af0f54b..5a2b46588 100644 --- a/go.sum +++ b/go.sum @@ -83,6 +83,8 @@ 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/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 h1:5iH8iuqE5apketRbSFBy+X1V0o+l+8NF1avt4HWl7cA= github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= +github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo= +github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= 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-openapi-client-go v0.0.0-20240430202104-3ad0f7e4ee52 h1:EBrKHk2URMJoT/xs+By+S+s92xsKNyyH7j8nrZFSCBY= @@ -126,6 +128,8 @@ github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.20.1 h1:YlVIbqct+ZmnEph770q9Q7NVAz4wwIiVNahee6JyUzo= github.com/onsi/ginkgo/v2 v2.20.1/go.mod h1:lG9ey2Z29hR41WMVthyJBGUBcBhGOtoPF2VFMvBXFCI= +github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM= +github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4= @@ -227,6 +231,8 @@ golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= +golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= +golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/tests/example-resources.yaml b/tests/example-resources.yaml index 2f80d2a37..5027d0325 100644 --- a/tests/example-resources.yaml +++ b/tests/example-resources.yaml @@ -24,7 +24,7 @@ spec: matchLabels: test: "testdata" uid: testdata - title: "Test Data testdata" + title: "Folder!" --- apiVersion: grafana.integreatly.org/v1beta1 kind: GrafanaDatasource @@ -35,10 +35,10 @@ spec: instanceSelector: matchLabels: test: "testdata" + uid: testdata-datasource datasource: orgId: 1 isDefault: true - uid: grafana-testdata name: grafana-testdata-datasource type: grafana-testdata-datasource access: proxy @@ -159,6 +159,7 @@ spec: instanceSelector: matchLabels: test: "testdata" + uid: testdata-dash json: > { "annotations": { @@ -185,7 +186,7 @@ spec: { "datasource": { "type": "grafana-testdata-datasource", - "uid": "grafana-testdata" + "uid": "testdata-datasource" }, "fieldConfig": { "defaults": { @@ -254,7 +255,7 @@ spec: { "datasource": { "type": "grafana-testdata-datasource", - "uid": "grafana-testdata" + "uid": "testdata-datasource" }, "refId": "A", "scenarioId": "grafana_api", @@ -267,7 +268,7 @@ spec: { "datasource": { "type": "grafana-testdata-datasource", - "uid": "grafana-testdata" + "uid": "testdata-datasource" }, "fieldConfig": { "defaults": { @@ -322,7 +323,7 @@ spec: { "datasource": { "type": "grafana-testdata-datasource", - "uid": "grafana-testdata" + "uid": "testdata-datasource" }, "hide": false, "refId": "A", @@ -334,6 +335,7 @@ spec: "type": "table" } ], + "refresh": "5s", "schemaVersion": 39, "tags": [], "templating": {