Skip to content

Commit d641c5a

Browse files
committed
chore(testcontainers): Prepare external Grafana instance
1 parent 90d958e commit d641c5a

File tree

2 files changed

+129
-37
lines changed

2 files changed

+129
-37
lines changed

controllers/controller_shared_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,7 @@ var _ = Describe("GetMatchingInstances functions", Ordered, func() {
435435
It("Finds all ready instances when instanceSelector is empty", func() {
436436
instances, err := GetScopedMatchingInstances(ctx, k8sClient, matchAllFolder)
437437
Expect(err).ToNot(HaveOccurred())
438-
Expect(instances).To(HaveLen(3 + 1)) // +1 To account for instance created in suite_test.go to provoke ApplyFailed conditions
438+
Expect(instances).To(HaveLen(3 + 2)) // +2 To account for instances created in controllers/suite_test.go to provoke conditions
439439
})
440440
It("Finds all ready and Matching instances", func() {
441441
instances, err := GetScopedMatchingInstances(ctx, k8sClient, &allowFolder)

controllers/suite_test.go

Lines changed: 128 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -23,27 +23,47 @@ import (
2323
"testing"
2424
"time"
2525

26-
. "github.com/onsi/ginkgo/v2"
27-
. "github.com/onsi/gomega"
26+
corev1 "k8s.io/api/core/v1"
2827
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
28+
"k8s.io/apimachinery/pkg/types"
2929
"k8s.io/client-go/kubernetes/scheme"
3030
"sigs.k8s.io/controller-runtime/pkg/client"
3131
"sigs.k8s.io/controller-runtime/pkg/envtest"
3232
logf "sigs.k8s.io/controller-runtime/pkg/log"
3333
"sigs.k8s.io/controller-runtime/pkg/log/zap"
3434

35+
"github.com/docker/go-connections/nat"
3536
"github.com/grafana/grafana-operator/v5/api/v1beta1"
3637
"github.com/grafana/grafana-operator/v5/controllers/config"
38+
39+
. "github.com/onsi/ginkgo/v2"
40+
. "github.com/onsi/gomega"
41+
"github.com/testcontainers/testcontainers-go"
42+
"github.com/testcontainers/testcontainers-go/wait"
3743
//+kubebuilder:scaffold:imports
3844
)
3945

4046
// These tests use Ginkgo (BDD-style Go testing framework). Refer to
4147
// http://onsi.github.io/ginkgo/ to learn more about Ginkgo.
4248

49+
const (
50+
grafanaName = "external-grafana"
51+
grafanaUser = "root"
52+
grafanaPass = "secret"
53+
)
54+
4355
var (
44-
k8sClient client.Client
45-
testEnv *envtest.Environment
46-
testCtx context.Context
56+
k8sClient client.Client
57+
testEnv *envtest.Environment
58+
testCtx context.Context
59+
grafanaContainer testcontainers.Container
60+
externalGrafanaCr *v1beta1.Grafana
61+
62+
grafanaPort = nat.Port(fmt.Sprint(config.GrafanaHTTPPort)) //nolint
63+
grafanaCredentials = map[string]string{
64+
"GF_SECURITY_ADMIN_USER": grafanaUser,
65+
"GF_SECURITY_ADMIN_PASSWORD": grafanaPass,
66+
}
4767
)
4868

4969
func TestAPIs(t *testing.T) {
@@ -78,20 +98,71 @@ var _ = BeforeSuite(func() {
7898

7999
//+kubebuilder:scaffold:scheme
80100

101+
By("Instantiating k8sClient")
81102
k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme})
82103
Expect(err).NotTo(HaveOccurred())
83104
Expect(k8sClient).NotTo(BeNil())
84105

85-
// NOTE(Baarsgaard) Ensure k8sClient is 100% ready
86-
// ENVTEST sometimes fail all tests with a 401 Unauthorized
87-
time.Sleep(100 * time.Millisecond)
106+
By("Starting Grafana TestContainer")
107+
grafanaContainer, err = testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
108+
Started: true,
109+
ContainerRequest: testcontainers.ContainerRequest{
110+
Name: fmt.Sprintf("%s-%d", grafanaName, GinkgoRandomSeed()),
111+
Image: fmt.Sprintf("%s:%s", config.GrafanaImage, config.GrafanaVersion),
112+
ExposedPorts: []string{grafanaPort.Port()},
113+
WaitingFor: wait.ForAll(
114+
wait.ForListeningPort(grafanaPort),
115+
wait.ForHTTP("/api/frontend/settings").
116+
WithPort(grafanaPort).
117+
WithBasicAuth(grafanaUser, grafanaPass).
118+
WithStartupTimeout(8*time.Second),
119+
),
120+
Env: grafanaCredentials,
121+
},
122+
})
123+
Expect(err).NotTo(HaveOccurred())
124+
125+
port, err := grafanaContainer.MappedPort(testCtx, grafanaPort)
126+
Expect(err).NotTo(HaveOccurred())
88127

89-
By("Create a dummy 'invalid' instance to provoke conditions")
128+
createSharedTestCRs(port.Port())
129+
})
130+
131+
var _ = AfterSuite(func() {
132+
By("tearing down the test environment")
133+
testcontainers.CleanupContainer(GinkgoTB(), grafanaContainer)
134+
Expect(testEnv.Stop()).To(Succeed())
135+
})
136+
137+
func createSharedTestCRs(port string) {
138+
GinkgoHelper()
139+
140+
By("Creating Configmaps and GrafanaFolder for testing")
141+
secretCR := &corev1.Secret{
142+
ObjectMeta: metav1.ObjectMeta{
143+
Namespace: "default",
144+
Name: "external-credentials",
145+
},
146+
StringData: grafanaCredentials,
147+
}
148+
Expect(k8sClient.Create(testCtx, secretCR)).ToNot(HaveOccurred())
149+
folderCR := &v1beta1.GrafanaFolder{
150+
ObjectMeta: metav1.ObjectMeta{
151+
Namespace: "default",
152+
Name: "apply-failed-helper",
153+
},
154+
Spec: v1beta1.GrafanaFolderSpec{
155+
GrafanaCommonSpec: commonSpecApplyFailed,
156+
},
157+
}
158+
Expect(k8sClient.Create(testCtx, folderCR)).ToNot(HaveOccurred())
159+
160+
By("Creating Grafana CRs. One Fake and one External")
90161
intP := 1
91-
grafanaCr := &v1beta1.Grafana{
162+
dummy := &v1beta1.Grafana{
92163
ObjectMeta: metav1.ObjectMeta{
93-
Name: "dummy",
94164
Namespace: "default",
165+
Name: "dummy",
95166
Labels: map[string]string{
96167
"apply-failed": "test",
97168
"invalid-spec": "test",
@@ -100,40 +171,61 @@ var _ = BeforeSuite(func() {
100171
},
101172
Spec: v1beta1.GrafanaSpec{
102173
Client: &v1beta1.GrafanaClient{TimeoutSeconds: &intP},
103-
Config: map[string]map[string]string{
104-
"security": {
105-
"admin_user": "root",
106-
"admin_password": "secret",
174+
},
175+
}
176+
external := &v1beta1.Grafana{
177+
ObjectMeta: metav1.ObjectMeta{
178+
Namespace: "default",
179+
Name: grafanaName,
180+
Labels: map[string]string{
181+
"synchronized": "test",
182+
"dashboards": "grafana",
183+
},
184+
},
185+
Spec: v1beta1.GrafanaSpec{
186+
External: &v1beta1.External{
187+
URL: fmt.Sprintf("http://localhost:%s", port),
188+
AdminUser: &corev1.SecretKeySelector{
189+
Key: "GF_SECURITY_ADMIN_USER",
190+
LocalObjectReference: corev1.LocalObjectReference{
191+
Name: secretCR.Name,
192+
},
193+
},
194+
AdminPassword: &corev1.SecretKeySelector{
195+
Key: "GF_SECURITY_ADMIN_PASSWORD",
196+
LocalObjectReference: corev1.LocalObjectReference{
197+
Name: secretCR.Name,
198+
},
107199
},
108200
},
201+
Client: &v1beta1.GrafanaClient{TimeoutSeconds: &intP},
109202
},
110203
}
111-
Expect(k8sClient.Create(testCtx, grafanaCr)).NotTo(HaveOccurred())
204+
Expect(k8sClient.Create(testCtx, dummy)).Should(Succeed())
205+
Expect(k8sClient.Create(testCtx, external)).Should(Succeed())
112206

113-
grafanaCr.Status = v1beta1.GrafanaStatus{
207+
dummy.Status = v1beta1.GrafanaStatus{
114208
Stage: v1beta1.OperatorStageComplete,
115209
StageStatus: v1beta1.OperatorStageResultSuccess,
116210
AdminURL: fmt.Sprintf("http://%s-service", "invalid"),
117211
Version: config.GrafanaVersion,
118212
}
119-
Expect(k8sClient.Status().Update(testCtx, grafanaCr)).ToNot(HaveOccurred())
213+
Expect(k8sClient.Status().Update(testCtx, dummy)).ToNot(HaveOccurred())
120214

121-
// Should not be reconciled
122-
By("Creating folder to use when provoking ApplyFailed conditions")
123-
folderCr := &v1beta1.GrafanaFolder{
124-
ObjectMeta: metav1.ObjectMeta{
125-
Namespace: objectMetaApplyFailed.Namespace,
126-
Name: "apply-failed-helper",
127-
},
128-
Spec: v1beta1.GrafanaFolderSpec{
129-
GrafanaCommonSpec: commonSpecApplyFailed,
130-
},
215+
By("Reconciling External Grafana")
216+
r := GrafanaReconciler{
217+
Client: k8sClient,
218+
Scheme: k8sClient.Scheme(),
219+
IsOpenShift: false,
131220
}
132-
Expect(k8sClient.Create(testCtx, folderCr)).ToNot(HaveOccurred())
133-
})
134-
135-
var _ = AfterSuite(func() {
136-
By("tearing down the test environment")
137-
err := testEnv.Stop()
138-
Expect(err).NotTo(HaveOccurred())
139-
})
221+
reg := requestFromMeta(external.ObjectMeta)
222+
_, err := r.Reconcile(testCtx, reg)
223+
Expect(err).ToNot(HaveOccurred())
224+
225+
By("Get External Grafana")
226+
externalGrafanaCr = &v1beta1.Grafana{}
227+
Expect(k8sClient.Get(testCtx, types.NamespacedName{
228+
Namespace: external.Namespace,
229+
Name: external.Name,
230+
}, externalGrafanaCr)).Should(Succeed())
231+
}

0 commit comments

Comments
 (0)