Skip to content

Commit 2ecc47b

Browse files
committed
test: add alluxio engine and transform coverage
Signed-off-by: Harsh <harshmastic@gmail.com>
1 parent 6df6421 commit 2ecc47b

2 files changed

Lines changed: 242 additions & 91 deletions

File tree

pkg/ddc/alluxio/api_gateway_test.go

Lines changed: 62 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -18,106 +18,77 @@ package alluxio
1818

1919
import (
2020
"fmt"
21-
"testing"
21+
22+
. "github.com/onsi/ginkgo/v2"
23+
. "github.com/onsi/gomega"
2224

2325
datav1alpha1 "github.com/fluid-cloudnative/fluid/api/v1alpha1"
2426
"github.com/fluid-cloudnative/fluid/pkg/common"
2527
"github.com/fluid-cloudnative/fluid/pkg/utils/fake"
26-
"github.com/stretchr/testify/assert"
2728
corev1 "k8s.io/api/core/v1"
2829
"k8s.io/apimachinery/pkg/types"
2930
)
3031

31-
func TestGetAPIGatewayStatus(t *testing.T) {
32-
endpointFormat := "%s-master-0.%s:%d"
33-
testCases := map[string]struct {
34-
engineName string
35-
engineNamespace string
36-
port int32
37-
wantStatus *datav1alpha1.APIGatewayStatus
38-
}{
39-
"test GetAPIGatewayStatus case 1": {
40-
engineName: "fluid",
41-
engineNamespace: "default",
42-
port: 8080,
43-
wantStatus: &datav1alpha1.APIGatewayStatus{
44-
Endpoint: fmt.Sprintf(endpointFormat, "fluid", "default", 8080),
45-
},
46-
},
47-
"test GetAPIGatewayStatus case 2": {
48-
engineName: "demo",
49-
engineNamespace: common.NamespaceFluidSystem,
50-
port: 80,
51-
wantStatus: &datav1alpha1.APIGatewayStatus{
52-
Endpoint: fmt.Sprintf(endpointFormat, "demo", common.NamespaceFluidSystem, 80),
53-
},
54-
},
55-
}
56-
57-
for _, item := range testCases {
58-
namespacedName := types.NamespacedName{Name: item.engineName, Namespace: item.engineNamespace}
59-
dataset, runtime := mockFluidObjectsForTests(namespacedName)
60-
engine := mockAlluxioEngineForTests(dataset, runtime)
61-
mockedObjects := mockAlluxioObjectsForTests(dataset, runtime, engine)
62-
63-
svc := mockedObjects.Services[fmt.Sprintf("%s-master-0", item.engineName)]
64-
svc.Spec.Ports = append(svc.Spec.Ports, corev1.ServicePort{Name: "rest", Port: item.port})
65-
client := fake.NewFakeClientWithScheme(datav1alpha1.UnitTestScheme, svc)
66-
engine.Client = client
67-
68-
// e := mockAlluxioEngineWithClient(item.engineName, item.engineNamespace, item.port)
69-
got, err := engine.GetAPIGatewayStatus()
70-
71-
assert.NoError(t, err)
72-
assert.Equal(t, got, item.wantStatus)
73-
// if !reflect.DeepEqual(got, item.wantStatus) {
74-
// t.Errorf("%s check failure,want:%v,got:%v", k, item.wantStatus, got)
75-
// }
76-
77-
}
78-
}
79-
80-
// TestQueryAPIGatewayEndpoint tests whether the Alluxio engine's queryAPIGatewayEndpoint method
81-
// correctly returns the API gateway access endpoint.
82-
// It uses two different test cases with varying engineName, engineNamespace, and port values,
83-
// and verifies that the generated endpoint string matches the expected format "%s-master-0.%s:%d".
84-
// The test cases cover both the default namespace and the system namespace scenarios.
85-
func TestQueryAPIGatewayEndpoint(t *testing.T) {
86-
endpointFormat := "%s-master-0.%s:%d"
87-
testCases := map[string]struct {
88-
engineName string
89-
engineNamespace string
90-
port int32
91-
wantEndpoint string
92-
}{
93-
"test GetAPIGatewayStatus case 1": {
94-
engineName: "fluid",
95-
engineNamespace: "default",
96-
port: 8080,
97-
wantEndpoint: fmt.Sprintf(endpointFormat, "fluid", "default", 8080),
98-
},
99-
"test GetAPIGatewayStatus case 2": {
100-
engineName: "demo",
101-
engineNamespace: common.NamespaceFluidSystem,
102-
port: 80,
103-
wantEndpoint: fmt.Sprintf(endpointFormat, "demo", common.NamespaceFluidSystem, 80),
104-
},
105-
}
32+
var _ = Describe("Alluxio API gateway", Label("pkg.ddc.alluxio.api_gateway_test.go"), func() {
33+
const endpointFormat = "%s-master-0.%s:%d"
10634

107-
for _, item := range testCases {
108-
namespacedName := types.NamespacedName{Name: item.engineName, Namespace: item.engineNamespace}
109-
dataset, runtime := mockFluidObjectsForTests(namespacedName)
110-
engine := mockAlluxioEngineForTests(dataset, runtime)
111-
mockedObjects := mockAlluxioObjectsForTests(dataset, runtime, engine)
35+
DescribeTable("GetAPIGatewayStatus",
36+
func(engineName string, engineNamespace string, port int32, wantStatus *datav1alpha1.APIGatewayStatus) {
37+
namespacedName := types.NamespacedName{Name: engineName, Namespace: engineNamespace}
38+
dataset, runtime := mockFluidObjectsForTests(namespacedName)
39+
engine := mockAlluxioEngineForTests(dataset, runtime)
40+
mockedObjects := mockAlluxioObjectsForTests(dataset, runtime, engine)
11241

113-
svc := mockedObjects.Services[fmt.Sprintf("%s-master-0", item.engineName)]
114-
svc.Spec.Ports = append(svc.Spec.Ports, corev1.ServicePort{Name: "rest", Port: item.port})
115-
client := fake.NewFakeClientWithScheme(datav1alpha1.UnitTestScheme, svc)
116-
engine.Client = client
42+
svc := mockedObjects.Services[fmt.Sprintf("%s-master-0", engineName)]
43+
svc.Spec.Ports = append(svc.Spec.Ports, corev1.ServicePort{Name: "rest", Port: port})
44+
engine.Client = fake.NewFakeClientWithScheme(datav1alpha1.UnitTestScheme, svc)
11745

118-
got, err := engine.queryAPIGatewayEndpoint()
46+
status, err := engine.GetAPIGatewayStatus()
11947

120-
assert.NoError(t, err)
121-
assert.Equal(t, got, item.wantEndpoint)
122-
}
123-
}
48+
Expect(err).NotTo(HaveOccurred())
49+
Expect(status).To(Equal(wantStatus))
50+
},
51+
Entry("returns the endpoint from the master service in the default namespace",
52+
"fluid",
53+
"default",
54+
int32(8080),
55+
&datav1alpha1.APIGatewayStatus{Endpoint: fmt.Sprintf(endpointFormat, "fluid", "default", 8080)},
56+
),
57+
Entry("returns the endpoint from the master service in the fluid system namespace",
58+
"demo",
59+
common.NamespaceFluidSystem,
60+
int32(80),
61+
&datav1alpha1.APIGatewayStatus{Endpoint: fmt.Sprintf(endpointFormat, "demo", common.NamespaceFluidSystem, 80)},
62+
),
63+
)
64+
65+
DescribeTable("queryAPIGatewayEndpoint",
66+
func(engineName string, engineNamespace string, port int32, wantEndpoint string) {
67+
namespacedName := types.NamespacedName{Name: engineName, Namespace: engineNamespace}
68+
dataset, runtime := mockFluidObjectsForTests(namespacedName)
69+
engine := mockAlluxioEngineForTests(dataset, runtime)
70+
mockedObjects := mockAlluxioObjectsForTests(dataset, runtime, engine)
71+
72+
svc := mockedObjects.Services[fmt.Sprintf("%s-master-0", engineName)]
73+
svc.Spec.Ports = append(svc.Spec.Ports, corev1.ServicePort{Name: "rest", Port: port})
74+
engine.Client = fake.NewFakeClientWithScheme(datav1alpha1.UnitTestScheme, svc)
75+
76+
endpoint, err := engine.queryAPIGatewayEndpoint()
77+
78+
Expect(err).NotTo(HaveOccurred())
79+
Expect(endpoint).To(Equal(wantEndpoint))
80+
},
81+
Entry("returns the endpoint from the default namespace master service",
82+
"fluid",
83+
"default",
84+
int32(8080),
85+
fmt.Sprintf(endpointFormat, "fluid", "default", 8080),
86+
),
87+
Entry("returns the endpoint from the fluid system namespace master service",
88+
"demo",
89+
common.NamespaceFluidSystem,
90+
int32(80),
91+
fmt.Sprintf(endpointFormat, "demo", common.NamespaceFluidSystem, 80),
92+
),
93+
)
94+
})
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
/*
2+
Copyright 2026 The Fluid Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package alluxio
18+
19+
import (
20+
"context"
21+
22+
"github.com/fluid-cloudnative/fluid/pkg/ddc/base"
23+
cruntime "github.com/fluid-cloudnative/fluid/pkg/runtime"
24+
"github.com/fluid-cloudnative/fluid/pkg/utils"
25+
"github.com/fluid-cloudnative/fluid/pkg/utils/fake"
26+
. "github.com/onsi/ginkgo/v2"
27+
. "github.com/onsi/gomega"
28+
corev1 "k8s.io/api/core/v1"
29+
apierrors "k8s.io/apimachinery/pkg/api/errors"
30+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
31+
"k8s.io/apimachinery/pkg/runtime/schema"
32+
"k8s.io/apimachinery/pkg/types"
33+
"sigs.k8s.io/controller-runtime/pkg/client"
34+
35+
datav1alpha1 "github.com/fluid-cloudnative/fluid/api/v1alpha1"
36+
)
37+
38+
type erroringGetClient struct {
39+
client.Client
40+
err error
41+
}
42+
43+
func (c erroringGetClient) Get(_ context.Context, _ client.ObjectKey, _ client.Object, _ ...client.GetOption) error {
44+
return c.err
45+
}
46+
47+
var _ = Describe("Alluxio engine and transform file scope", Label("pkg.ddc.alluxio.engine_transform_file_scope_test.go"), func() {
48+
Describe("Build", func() {
49+
It("returns an error when runtime is missing", func() {
50+
engine, err := Build("test-id", cruntime.ReconcileRequestContext{
51+
NamespacedName: types.NamespacedName{Name: "demo", Namespace: "fluid"},
52+
Log: fake.NullLogger(),
53+
RuntimeType: "alluxio",
54+
})
55+
56+
Expect(err).To(MatchError("engine demo is failed to parse"))
57+
Expect(engine).To(BeNil())
58+
})
59+
60+
It("returns an error when runtime has the wrong type", func() {
61+
engine, err := Build("test-id", cruntime.ReconcileRequestContext{
62+
NamespacedName: types.NamespacedName{Name: "demo", Namespace: "fluid"},
63+
Log: fake.NullLogger(),
64+
RuntimeType: "alluxio",
65+
Runtime: &datav1alpha1.ThinRuntime{},
66+
})
67+
68+
Expect(err).To(MatchError("engine demo is failed to parse"))
69+
Expect(engine).To(BeNil())
70+
})
71+
})
72+
73+
Describe("Precheck", func() {
74+
It("reports whether the alluxio runtime exists", func() {
75+
key := types.NamespacedName{Name: "demo", Namespace: "fluid"}
76+
runtime := &datav1alpha1.AlluxioRuntime{ObjectMeta: metav1.ObjectMeta{Name: key.Name, Namespace: key.Namespace}}
77+
client := fake.NewFakeClientWithScheme(datav1alpha1.UnitTestScheme, runtime)
78+
79+
found, err := Precheck(client, key)
80+
81+
Expect(err).NotTo(HaveOccurred())
82+
Expect(found).To(BeTrue())
83+
})
84+
85+
It("returns false without error when the runtime is absent", func() {
86+
found, err := Precheck(fake.NewFakeClientWithScheme(datav1alpha1.UnitTestScheme), types.NamespacedName{Name: "missing", Namespace: "fluid"})
87+
88+
Expect(err).NotTo(HaveOccurred())
89+
Expect(found).To(BeFalse())
90+
})
91+
92+
It("returns the client error for non-not-found failures", func() {
93+
failingClient := erroringGetClient{
94+
Client: fake.NewFakeClientWithScheme(datav1alpha1.UnitTestScheme),
95+
err: apierrors.NewForbidden(schema.GroupResource{Group: datav1alpha1.GroupVersion.Group, Resource: "alluxioruntimes"}, "demo", nil),
96+
}
97+
98+
found, err := Precheck(failingClient, types.NamespacedName{Name: "demo", Namespace: "fluid"})
99+
100+
Expect(err).To(HaveOccurred())
101+
Expect(apierrors.IsForbidden(err)).To(BeTrue())
102+
Expect(found).To(BeFalse())
103+
})
104+
})
105+
106+
Describe("transformPlacementMode", func() {
107+
It("defaults to exclusive placement when the dataset placement mode is empty", func() {
108+
value := &Alluxio{}
109+
110+
(&AlluxioEngine{}).transformPlacementMode(&datav1alpha1.Dataset{}, value)
111+
112+
Expect(value.PlacementMode).To(Equal(string(datav1alpha1.ExclusiveMode)))
113+
})
114+
})
115+
116+
Describe("transform", func() {
117+
It("builds an alluxio value for a dataset-backed runtime", func() {
118+
namespacedName := types.NamespacedName{Name: "demo", Namespace: "fluid"}
119+
dataset, runtime := mockFluidObjectsForTests(namespacedName)
120+
dataset.Spec.PlacementMode = ""
121+
runtime.Spec.AlluxioVersion.ImageTag = "2.8.0"
122+
runtime.Spec.Master.NetworkMode = datav1alpha1.ContainerNetworkMode
123+
runtime.Spec.Worker.NetworkMode = datav1alpha1.ContainerNetworkMode
124+
runtime.Spec.APIGateway.Enabled = true
125+
runtime.Spec.HadoopConfig = "demo-hadoop-conf"
126+
runtime.Spec.PodMetadata = datav1alpha1.PodMetadata{
127+
Labels: map[string]string{"common-label": "common-value"},
128+
Annotations: map[string]string{"common-annotation": "common-value"},
129+
}
130+
dataset.Spec.Mounts = []datav1alpha1.Mount{{
131+
MountPoint: "https://downloads.example.com/demo",
132+
Path: "/",
133+
Name: "http",
134+
}}
135+
136+
runtimeInfo, err := base.BuildRuntimeInfo(dataset.Name, dataset.Namespace, "alluxio", base.WithTieredStore(runtime.Spec.TieredStore))
137+
Expect(err).NotTo(HaveOccurred())
138+
runtimeInfo.SetOwnerDatasetUID(dataset.UID)
139+
runtimeInfo.SetupWithDataset(dataset)
140+
141+
engine := mockAlluxioEngineForTests(dataset, runtime)
142+
engine.runtimeInfo = runtimeInfo
143+
engine.Client = fake.NewFakeClientWithScheme(datav1alpha1.UnitTestScheme,
144+
dataset,
145+
runtime,
146+
&corev1.ConfigMap{
147+
ObjectMeta: metav1.ObjectMeta{Name: runtime.Spec.HadoopConfig, Namespace: runtime.Namespace},
148+
Data: map[string]string{
149+
hadoopConfCoreSiteFilename: "core-site",
150+
hadoopConfHdfsSiteFilename: "hdfs-site",
151+
},
152+
},
153+
)
154+
155+
value, err := engine.transform(runtime)
156+
157+
Expect(err).NotTo(HaveOccurred())
158+
Expect(value).NotTo(BeNil())
159+
Expect(value.FullnameOverride).To(Equal(namespacedName.Name))
160+
Expect(value.OwnerDatasetId).To(Equal(utils.GetDatasetId(namespacedName.Namespace, namespacedName.Name, string(dataset.UID))))
161+
Expect(value.Properties["alluxio.master.mount.table.root.ufs"]).To(Equal("https://downloads.example.com/demo"))
162+
Expect(value.Properties["alluxio.user.file.replication.max"]).To(Equal("1"))
163+
Expect(value.Properties["alluxio.proxy.web.port"]).To(Equal("39999"))
164+
Expect(value.Properties["alluxio.underfs.hdfs.configuration"]).To(ContainSubstring(hadoopConfMountPath + "/" + hadoopConfCoreSiteFilename))
165+
Expect(value.Properties["alluxio.underfs.hdfs.configuration"]).To(ContainSubstring(hadoopConfMountPath + "/" + hadoopConfHdfsSiteFilename))
166+
Expect(value.Properties["alluxio.user.block.size.bytes.default"]).To(Equal("256MB"))
167+
Expect(value.Monitoring).To(Equal(alluxioRuntimeMetricsLabel))
168+
Expect(value.Master.Labels).To(HaveKeyWithValue("common-label", "common-value"))
169+
Expect(value.Worker.Annotations).To(HaveKeyWithValue("common-annotation", "common-value"))
170+
Expect(value.APIGateway.Enabled).To(BeTrue())
171+
Expect(value.Fuse.Args).To(HaveLen(2))
172+
Expect(value.Fuse.Args[1]).To(ContainSubstring("max_readahead=0"))
173+
Expect(value.Fuse.Args[1]).To(ContainSubstring("allow_other"))
174+
Expect(value.Fuse.NodeSelector).To(HaveKeyWithValue(utils.GetFuseLabelName(runtime.Namespace, runtime.Name, string(dataset.UID)), "true"))
175+
Expect(value.TieredStore.Levels).To(HaveLen(1))
176+
Expect(value.TieredStore.Levels[0].Path).To(Equal("/dev/shm/fluid/demo"))
177+
Expect(value.PlacementMode).To(Equal(string(datav1alpha1.ExclusiveMode)))
178+
})
179+
})
180+
})

0 commit comments

Comments
 (0)