Skip to content

Commit 70d9752

Browse files
authored
test: add thin transform Ginkgo coverage (#5821)
* test: add thin transform ginkgo coverage Signed-off-by: Harsh <harshmastic@gmail.com> * test: remove unused thin profile fixture Signed-off-by: Harsh <harshmastic@gmail.com> * remove thin transform overlap Signed-off-by: Harsh <harshmastic@gmail.com> * fix thin transform review issues Signed-off-by: Harsh <harshmastic@gmail.com> * seed thin shutdown runtimes Signed-off-by: Harsh <harshmastic@gmail.com> * Revert "seed thin shutdown runtimes" This reverts commit be1cdab. Signed-off-by: Harsh <harshmastic@gmail.com> --------- Signed-off-by: Harsh <harshmastic@gmail.com>
1 parent 18bf531 commit 70d9752

5 files changed

Lines changed: 743 additions & 172 deletions

File tree

pkg/ddc/thin/health_check_test.go

Lines changed: 188 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ package thin
1818

1919
import (
2020
"context"
21-
2221
. "github.com/onsi/ginkgo/v2"
2322
. "github.com/onsi/gomega"
2423

@@ -265,6 +264,117 @@ var _ = Describe("ThinEngine Health Check", Label("pkg.ddc.thin.health_check_tes
265264
Expect(err).To(HaveOccurred())
266265
})
267266
})
267+
268+
Context("when a fuse-only runtime is healthy", func() {
269+
var (
270+
client client.Client
271+
engine ThinEngine
272+
)
273+
274+
BeforeEach(func() {
275+
healthyFuse := &appsv1.DaemonSet{
276+
ObjectMeta: metav1.ObjectMeta{
277+
Name: healthCheckTestSpark + "-fuse",
278+
Namespace: healthCheckTestNamespace,
279+
},
280+
Status: appsv1.DaemonSetStatus{
281+
NumberUnavailable: 0,
282+
NumberReady: 1,
283+
NumberAvailable: 1,
284+
},
285+
}
286+
runtimeObj := &datav1alpha1.ThinRuntime{
287+
ObjectMeta: metav1.ObjectMeta{
288+
Name: healthCheckTestSpark,
289+
Namespace: healthCheckTestNamespace,
290+
},
291+
Spec: datav1alpha1.ThinRuntimeSpec{},
292+
Status: datav1alpha1.RuntimeStatus{
293+
CacheStates: map[common.CacheStateName]string{common.Cached: "true"},
294+
},
295+
}
296+
datasetObj := &datav1alpha1.Dataset{
297+
ObjectMeta: metav1.ObjectMeta{
298+
Name: healthCheckTestSpark,
299+
Namespace: healthCheckTestNamespace,
300+
},
301+
Status: datav1alpha1.DatasetStatus{},
302+
}
303+
304+
client = fake.NewFakeClientWithScheme(testScheme, healthyFuse, runtimeObj, datasetObj)
305+
engine = ThinEngine{
306+
Client: client,
307+
Log: fake.NullLogger(),
308+
namespace: healthCheckTestNamespace,
309+
name: healthCheckTestSpark,
310+
runtime: runtimeObj,
311+
}
312+
})
313+
314+
JustBeforeEach(func() {
315+
runtimeInfo, err := base.BuildRuntimeInfo(engine.name, engine.namespace, common.ThinRuntime)
316+
Expect(err).NotTo(HaveOccurred())
317+
engine.Helper = ctrl.BuildHelper(runtimeInfo, client, engine.Log)
318+
})
319+
320+
It("skips worker checks and updates the dataset to bound", func() {
321+
err := engine.CheckRuntimeHealthy()
322+
Expect(err).NotTo(HaveOccurred())
323+
324+
updatedRuntime, err := engine.getRuntime()
325+
Expect(err).NotTo(HaveOccurred())
326+
Expect(updatedRuntime.Status.FuseNumberReady).To(Equal(int32(1)))
327+
Expect(updatedRuntime.Status.FuseNumberAvailable).To(Equal(int32(1)))
328+
329+
updatedDataset, err := utils.GetDataset(client, healthCheckTestSpark, healthCheckTestNamespace)
330+
Expect(err).NotTo(HaveOccurred())
331+
Expect(updatedDataset.Status.Phase).To(Equal(datav1alpha1.BoundDatasetPhase))
332+
})
333+
})
334+
335+
Context("when checking a fuse-only runtime without a fuse daemonset", func() {
336+
var (
337+
client client.Client
338+
engine ThinEngine
339+
)
340+
341+
BeforeEach(func() {
342+
runtimeObj := &datav1alpha1.ThinRuntime{
343+
ObjectMeta: metav1.ObjectMeta{
344+
Name: healthCheckTestSpark,
345+
Namespace: healthCheckTestNamespace,
346+
},
347+
Spec: datav1alpha1.ThinRuntimeSpec{},
348+
}
349+
datasetObj := &datav1alpha1.Dataset{
350+
ObjectMeta: metav1.ObjectMeta{
351+
Name: healthCheckTestSpark,
352+
Namespace: healthCheckTestNamespace,
353+
},
354+
}
355+
356+
client = fake.NewFakeClientWithScheme(testScheme, runtimeObj, datasetObj)
357+
engine = ThinEngine{
358+
Client: client,
359+
Log: fake.NullLogger(),
360+
namespace: healthCheckTestNamespace,
361+
name: healthCheckTestSpark,
362+
runtime: runtimeObj,
363+
}
364+
})
365+
366+
JustBeforeEach(func() {
367+
runtimeInfo, err := base.BuildRuntimeInfo(engine.name, engine.namespace, common.ThinRuntime)
368+
Expect(err).NotTo(HaveOccurred())
369+
engine.Helper = ctrl.BuildHelper(runtimeInfo, client, engine.Log)
370+
})
371+
372+
It("returns the fuse check error", func() {
373+
err := engine.CheckRuntimeHealthy()
374+
Expect(err).To(HaveOccurred())
375+
})
376+
})
377+
268378
})
269379

270380
Describe("checkFuseHealthy", func() {
@@ -419,4 +529,81 @@ var _ = Describe("ThinEngine Health Check", Label("pkg.ddc.thin.health_check_tes
419529
})
420530
})
421531
})
532+
533+
Describe("CheckAndUpdateRuntimeStatus", func() {
534+
It("initializes fuse-only runtime status and strips mount options", func() {
535+
dataset := &datav1alpha1.Dataset{
536+
ObjectMeta: metav1.ObjectMeta{
537+
Name: healthCheckTestSpark,
538+
Namespace: healthCheckTestNamespace,
539+
},
540+
Status: datav1alpha1.DatasetStatus{
541+
Mounts: []datav1alpha1.Mount{{
542+
MountPoint: "s3://bucket/data",
543+
Options: map[string]string{"endpoint": "test"},
544+
EncryptOptions: []datav1alpha1.EncryptOption{{
545+
Name: "secret",
546+
}},
547+
}},
548+
},
549+
}
550+
551+
runtimeObj := &datav1alpha1.ThinRuntime{
552+
ObjectMeta: metav1.ObjectMeta{
553+
Name: healthCheckTestSpark,
554+
Namespace: healthCheckTestNamespace,
555+
CreationTimestamp: metav1.Now(),
556+
},
557+
Spec: datav1alpha1.ThinRuntimeSpec{
558+
Fuse: datav1alpha1.ThinFuseSpec{},
559+
},
560+
Status: datav1alpha1.RuntimeStatus{
561+
FusePhase: datav1alpha1.RuntimePhaseNone,
562+
},
563+
}
564+
565+
client := fake.NewFakeClientWithScheme(testScheme, dataset, runtimeObj)
566+
engine := ThinEngine{
567+
Client: client,
568+
Log: fake.NullLogger(),
569+
name: healthCheckTestSpark,
570+
namespace: healthCheckTestNamespace,
571+
runtime: runtimeObj,
572+
}
573+
574+
ready, err := engine.CheckAndUpdateRuntimeStatus()
575+
576+
Expect(err).NotTo(HaveOccurred())
577+
Expect(ready).To(BeTrue())
578+
579+
updatedRuntime, err := engine.getRuntime()
580+
Expect(err).NotTo(HaveOccurred())
581+
Expect(updatedRuntime.Status.FusePhase).To(Equal(datav1alpha1.RuntimePhaseReady))
582+
Expect(updatedRuntime.Status.ValueFileConfigmap).To(Equal(engine.getHelmValuesConfigMapName()))
583+
Expect(updatedRuntime.Status.SetupDuration).NotTo(BeEmpty())
584+
Expect(updatedRuntime.Status.CacheStates).To(HaveKeyWithValue(common.Cached, "N/A"))
585+
Expect(updatedRuntime.Status.Mounts).To(HaveLen(1))
586+
Expect(updatedRuntime.Status.Mounts[0].Options).To(BeNil())
587+
Expect(updatedRuntime.Status.Mounts[0].EncryptOptions).To(BeNil())
588+
589+
_, cond := utils.GetRuntimeCondition(updatedRuntime.Status.Conditions, datav1alpha1.RuntimeFusesInitialized)
590+
Expect(cond).NotTo(BeNil())
591+
})
592+
})
593+
594+
Describe("ThinEngine.getDataSetFileNum", func() {
595+
It("returns an empty count when no running fuse pod can be found", func() {
596+
engine := &ThinEngine{
597+
Client: fake.NewFakeClientWithScheme(testScheme),
598+
Log: fake.NullLogger(),
599+
name: healthCheckTestName,
600+
namespace: healthCheckTestNamespace,
601+
}
602+
603+
count, err := engine.getDataSetFileNum()
604+
605+
Expect(err).To(HaveOccurred())
606+
Expect(count).To(BeEmpty())
607+
})
608+
})
422609
})

pkg/ddc/thin/master_internal.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ func (t *ThinEngine) ifRuntimeHelmValueEnable() bool {
132132
if err != nil {
133133
return true
134134
}
135-
return enableRuntimeHelmValueConfig
135+
return !enableRuntimeHelmValueConfig
136136
}
137137

138138
func (t *ThinEngine) getHelmValuesConfigMapName() string {

pkg/ddc/thin/master_test.go

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,21 @@
1717
package thin
1818

1919
import (
20+
"context"
21+
"errors"
22+
. "github.com/agiledragon/gomonkey/v2"
2023
datav1alpha1 "github.com/fluid-cloudnative/fluid/api/v1alpha1"
24+
"github.com/fluid-cloudnative/fluid/pkg/common"
2125
"github.com/fluid-cloudnative/fluid/pkg/utils/fake"
26+
"github.com/fluid-cloudnative/fluid/pkg/utils/helm"
2227
. "github.com/onsi/ginkgo/v2"
2328
. "github.com/onsi/gomega"
2429
appsv1 "k8s.io/api/apps/v1"
30+
corev1 "k8s.io/api/core/v1"
31+
apierrors "k8s.io/apimachinery/pkg/api/errors"
2532
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2633
"k8s.io/apimachinery/pkg/runtime"
34+
"k8s.io/apimachinery/pkg/types"
2735
)
2836

2937
var _ = Describe("Master Tests", func() {
@@ -123,5 +131,133 @@ var _ = Describe("Master Tests", func() {
123131
Expect(err).To(BeNil())
124132
})
125133
})
134+
135+
})
136+
137+
Describe("ThinEngine.generateThinValueFile", func() {
138+
It("skips storing runtime helm values when runtime config map generation is disabled", func() {
139+
dataset, runtimeObj, profile := mockFluidObjectsForTests(types.NamespacedName{Name: "test-dataset", Namespace: "default"})
140+
runtimeObj.Spec.Fuse = datav1alpha1.ThinFuseSpec{Image: "runtime-fuse"}
141+
runtimeObj.Annotations = map[string]string{common.AnnotationDisableRuntimeHelmValueConfig: "true"}
142+
143+
engine := mockThinEngineForTests(dataset, runtimeObj, profile)
144+
engine.Client = fake.NewFakeClientWithScheme(testScheme, dataset, runtimeObj, profile)
145+
engine.runtime = runtimeObj
146+
147+
valueFile, err := engine.generateThinValueFile(runtimeObj, profile)
148+
Expect(err).NotTo(HaveOccurred())
149+
Expect(valueFile).To(BeAnExistingFile())
150+
151+
configMap := &corev1.ConfigMap{}
152+
err = engine.Client.Get(context.TODO(), types.NamespacedName{
153+
Name: engine.getHelmValuesConfigMapName(),
154+
Namespace: engine.namespace,
155+
}, configMap)
156+
Expect(apierrors.IsNotFound(err)).To(BeTrue())
157+
})
158+
159+
})
160+
161+
Describe("ThinEngine.setupMasterInternal", func() {
162+
It("installs the release when it is not already present", func() {
163+
dataset, runtimeObj, profile := mockFluidObjectsForTests(types.NamespacedName{Name: "test-dataset", Namespace: "default"})
164+
runtimeObj.Spec.Fuse = datav1alpha1.ThinFuseSpec{Image: "runtime-fuse"}
165+
166+
engine := mockThinEngineForTests(dataset, runtimeObj, profile)
167+
engine.Client = fake.NewFakeClientWithScheme(testScheme, dataset, runtimeObj, profile)
168+
engine.runtime = runtimeObj
169+
170+
checkReleasePatch := ApplyFunc(helm.CheckRelease, func(string, string) (bool, error) {
171+
return false, nil
172+
})
173+
installReleasePatch := ApplyFunc(helm.InstallRelease, func(name string, namespace string, valueFile string, chart string) error {
174+
Expect(name).To(Equal(engine.name))
175+
Expect(namespace).To(Equal(engine.namespace))
176+
Expect(valueFile).To(BeAnExistingFile())
177+
Expect(chart).To(ContainSubstring("thin"))
178+
return nil
179+
})
180+
defer checkReleasePatch.Reset()
181+
defer installReleasePatch.Reset()
182+
183+
Expect(engine.setupMasterInternal()).To(Succeed())
184+
})
185+
186+
It("returns the install release error", func() {
187+
dataset, runtimeObj, profile := mockFluidObjectsForTests(types.NamespacedName{Name: "test-dataset", Namespace: "default"})
188+
runtimeObj.Spec.Fuse = datav1alpha1.ThinFuseSpec{Image: "runtime-fuse"}
189+
190+
engine := mockThinEngineForTests(dataset, runtimeObj, profile)
191+
engine.Client = fake.NewFakeClientWithScheme(testScheme, dataset, runtimeObj, profile)
192+
engine.runtime = runtimeObj
193+
194+
checkReleasePatch := ApplyFunc(helm.CheckRelease, func(string, string) (bool, error) {
195+
return false, nil
196+
})
197+
installReleasePatch := ApplyFunc(helm.InstallRelease, func(string, string, string, string) error {
198+
return errors.New("install failed")
199+
})
200+
defer checkReleasePatch.Reset()
201+
defer installReleasePatch.Reset()
202+
203+
Expect(engine.setupMasterInternal()).To(MatchError("install failed"))
204+
})
205+
})
206+
207+
Describe("ThinEngine.getThinRuntimeProfile", func() {
208+
It("returns nil when the engine runtime is nil", func() {
209+
engine := &ThinEngine{}
210+
211+
profile, err := engine.getThinRuntimeProfile()
212+
213+
Expect(err).NotTo(HaveOccurred())
214+
Expect(profile).To(BeNil())
215+
})
216+
217+
It("loads the referenced runtime profile", func() {
218+
dataset, runtimeObj, profile := mockFluidObjectsForTests(types.NamespacedName{Name: "test-dataset", Namespace: "default"})
219+
engine := mockThinEngineForTests(dataset, runtimeObj, profile)
220+
engine.Client = fake.NewFakeClientWithScheme(testScheme, dataset, runtimeObj, profile)
221+
222+
loadedProfile, err := engine.getThinRuntimeProfile()
223+
224+
Expect(err).NotTo(HaveOccurred())
225+
Expect(loadedProfile).NotTo(BeNil())
226+
Expect(loadedProfile.Name).To(Equal(profile.Name))
227+
})
228+
})
229+
230+
Describe("ThinEngine.ifRuntimeHelmValueEnable", func() {
231+
It("defaults to enabled when runtime is nil or the annotation is invalid", func() {
232+
Expect((&ThinEngine{}).ifRuntimeHelmValueEnable()).To(BeTrue())
233+
234+
engine := &ThinEngine{runtime: &datav1alpha1.ThinRuntime{
235+
ObjectMeta: metav1.ObjectMeta{
236+
Annotations: map[string]string{common.AnnotationDisableRuntimeHelmValueConfig: "not-a-bool"},
237+
},
238+
}}
239+
240+
Expect(engine.ifRuntimeHelmValueEnable()).To(BeTrue())
241+
})
242+
243+
It("disables runtime helm values when the disable annotation is true", func() {
244+
engine := &ThinEngine{runtime: &datav1alpha1.ThinRuntime{
245+
ObjectMeta: metav1.ObjectMeta{
246+
Annotations: map[string]string{common.AnnotationDisableRuntimeHelmValueConfig: "true"},
247+
},
248+
}}
249+
250+
Expect(engine.ifRuntimeHelmValueEnable()).To(BeFalse())
251+
})
252+
253+
It("keeps runtime helm values enabled when the disable annotation is false", func() {
254+
engine := &ThinEngine{runtime: &datav1alpha1.ThinRuntime{
255+
ObjectMeta: metav1.ObjectMeta{
256+
Annotations: map[string]string{common.AnnotationDisableRuntimeHelmValueConfig: "false"},
257+
},
258+
}}
259+
260+
Expect(engine.ifRuntimeHelmValueEnable()).To(BeTrue())
261+
})
126262
})
127263
})

0 commit comments

Comments
 (0)