Skip to content

Commit c6f0dc7

Browse files
authored
Merge pull request #125 from rollandf/ready
feat: Go implement Ready
2 parents 6e838a8 + 1b2e85e commit c6f0dc7

File tree

3 files changed

+264
-2
lines changed

3 files changed

+264
-2
lines changed

entrypoint/internal/utils/ready/ready.go

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package ready
1818

1919
import (
2020
"context"
21+
"path/filepath"
2122

2223
"github.com/go-logr/logr"
2324

@@ -49,14 +50,38 @@ type ready struct {
4950
func (r *ready) Set(ctx context.Context) error {
5051
log := logr.FromContextOrDiscard(ctx)
5152
log.Info("set driver ready indicator")
52-
// TODO add implementation
53+
54+
// Ensure the directory exists
55+
dir := filepath.Dir(r.path)
56+
if err := r.os.MkdirAll(dir, 0o755); err != nil {
57+
log.Error(err, "failed to create directory for readiness indicator", "dir", dir)
58+
return err
59+
}
60+
61+
// Create the readiness indicator file (equivalent to 'touch' command)
62+
file, err := r.os.Create(r.path)
63+
if err != nil {
64+
log.Error(err, "failed to create readiness indicator file", "path", r.path)
65+
return err
66+
}
67+
defer file.Close()
68+
69+
log.Info("driver ready indicator set", "path", r.path)
5370
return nil
5471
}
5572

5673
// Clear is the default implementation of the ready.Interface.
5774
func (r *ready) Clear(ctx context.Context) error {
5875
log := logr.FromContextOrDiscard(ctx)
5976
log.Info("remove driver ready indicator")
60-
// TODO add implementation
77+
78+
// Remove the readiness indicator file (equivalent to 'rm -f' command)
79+
// RemoveAll will not return an error if the file doesn't exist
80+
if err := r.os.RemoveAll(r.path); err != nil {
81+
log.Error(err, "failed to remove readiness indicator file", "path", r.path)
82+
return err
83+
}
84+
85+
log.Info("driver ready indicator cleared", "path", r.path)
6186
return nil
6287
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
Copyright 2025, NVIDIA CORPORATION & AFFILIATES
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 ready
18+
19+
import (
20+
"testing"
21+
22+
. "github.com/onsi/ginkgo/v2"
23+
. "github.com/onsi/gomega"
24+
)
25+
26+
func TestReady(t *testing.T) {
27+
RegisterFailHandler(Fail)
28+
RunSpecs(t, "Ready Suite")
29+
}
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
/*
2+
Copyright 2025, NVIDIA CORPORATION & AFFILIATES
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 ready
18+
19+
import (
20+
"context"
21+
"os"
22+
"path/filepath"
23+
24+
. "github.com/onsi/ginkgo/v2"
25+
. "github.com/onsi/gomega"
26+
"github.com/stretchr/testify/assert"
27+
28+
osMockPkg "github.com/Mellanox/doca-driver-build/entrypoint/internal/wrappers/mocks"
29+
)
30+
31+
var _ = Describe("Ready", func() {
32+
Context("Set", func() {
33+
var (
34+
r Interface
35+
osMock *osMockPkg.OSWrapper
36+
testDir string
37+
testFile string
38+
)
39+
40+
BeforeEach(func() {
41+
osMock = osMockPkg.NewOSWrapper(GinkgoT())
42+
testDir = "/tmp/test-ready"
43+
testFile = filepath.Join(testDir, ".driver-ready")
44+
r = New(testFile, osMock)
45+
})
46+
47+
It("should create readiness indicator file successfully", func() {
48+
// Mock file creation
49+
mockFile := &os.File{}
50+
osMock.EXPECT().MkdirAll(testDir, os.FileMode(0755)).Return(nil)
51+
osMock.EXPECT().Create(testFile).Return(mockFile, nil)
52+
53+
err := r.Set(context.Background())
54+
Expect(err).ToNot(HaveOccurred())
55+
})
56+
57+
It("should handle directory creation failure", func() {
58+
osMock.EXPECT().MkdirAll(testDir, os.FileMode(0755)).Return(assert.AnError)
59+
60+
err := r.Set(context.Background())
61+
Expect(err).To(HaveOccurred())
62+
Expect(err).To(Equal(assert.AnError))
63+
})
64+
65+
It("should handle file creation failure", func() {
66+
osMock.EXPECT().MkdirAll(testDir, os.FileMode(0755)).Return(nil)
67+
osMock.EXPECT().Create(testFile).Return(nil, assert.AnError)
68+
69+
err := r.Set(context.Background())
70+
Expect(err).To(HaveOccurred())
71+
Expect(err).To(Equal(assert.AnError))
72+
})
73+
74+
It("should handle nested directory creation", func() {
75+
nestedFile := "/tmp/nested/deep/path/.driver-ready"
76+
nestedDir := "/tmp/nested/deep/path"
77+
r = New(nestedFile, osMock)
78+
79+
mockFile := &os.File{}
80+
osMock.EXPECT().MkdirAll(nestedDir, os.FileMode(0755)).Return(nil)
81+
osMock.EXPECT().Create(nestedFile).Return(mockFile, nil)
82+
83+
err := r.Set(context.Background())
84+
Expect(err).ToNot(HaveOccurred())
85+
})
86+
87+
It("should handle file in current directory", func() {
88+
currentDirFile := ".driver-ready"
89+
r = New(currentDirFile, osMock)
90+
91+
mockFile := &os.File{}
92+
osMock.EXPECT().MkdirAll(".", os.FileMode(0755)).Return(nil)
93+
osMock.EXPECT().Create(currentDirFile).Return(mockFile, nil)
94+
95+
err := r.Set(context.Background())
96+
Expect(err).ToNot(HaveOccurred())
97+
})
98+
})
99+
100+
Context("Clear", func() {
101+
var (
102+
r Interface
103+
osMock *osMockPkg.OSWrapper
104+
testFile string
105+
)
106+
107+
BeforeEach(func() {
108+
osMock = osMockPkg.NewOSWrapper(GinkgoT())
109+
testFile = "/tmp/test-ready/.driver-ready"
110+
r = New(testFile, osMock)
111+
})
112+
113+
It("should remove readiness indicator file successfully", func() {
114+
osMock.EXPECT().RemoveAll(testFile).Return(nil)
115+
116+
err := r.Clear(context.Background())
117+
Expect(err).ToNot(HaveOccurred())
118+
})
119+
120+
It("should handle file removal failure", func() {
121+
osMock.EXPECT().RemoveAll(testFile).Return(assert.AnError)
122+
123+
err := r.Clear(context.Background())
124+
Expect(err).To(HaveOccurred())
125+
Expect(err).To(Equal(assert.AnError))
126+
})
127+
128+
It("should handle non-existent file gracefully", func() {
129+
// RemoveAll should not return an error if file doesn't exist
130+
osMock.EXPECT().RemoveAll(testFile).Return(nil)
131+
132+
err := r.Clear(context.Background())
133+
Expect(err).ToNot(HaveOccurred())
134+
})
135+
136+
It("should handle nested file path", func() {
137+
nestedFile := "/tmp/nested/deep/path/.driver-ready"
138+
r = New(nestedFile, osMock)
139+
140+
osMock.EXPECT().RemoveAll(nestedFile).Return(nil)
141+
142+
err := r.Clear(context.Background())
143+
Expect(err).ToNot(HaveOccurred())
144+
})
145+
146+
It("should handle file in current directory", func() {
147+
currentDirFile := ".driver-ready"
148+
r = New(currentDirFile, osMock)
149+
150+
osMock.EXPECT().RemoveAll(currentDirFile).Return(nil)
151+
152+
err := r.Clear(context.Background())
153+
Expect(err).ToNot(HaveOccurred())
154+
})
155+
})
156+
157+
Context("Integration", func() {
158+
var (
159+
r Interface
160+
osMock *osMockPkg.OSWrapper
161+
testFile string
162+
)
163+
164+
BeforeEach(func() {
165+
osMock = osMockPkg.NewOSWrapper(GinkgoT())
166+
testFile = "/tmp/test-ready/.driver-ready"
167+
r = New(testFile, osMock)
168+
})
169+
170+
It("should handle set and clear operations in sequence", func() {
171+
// Set operation
172+
mockFile := &os.File{}
173+
osMock.EXPECT().MkdirAll("/tmp/test-ready", os.FileMode(0755)).Return(nil)
174+
osMock.EXPECT().Create(testFile).Return(mockFile, nil)
175+
176+
err := r.Set(context.Background())
177+
Expect(err).ToNot(HaveOccurred())
178+
179+
// Clear operation
180+
osMock.EXPECT().RemoveAll(testFile).Return(nil)
181+
182+
err = r.Clear(context.Background())
183+
Expect(err).ToNot(HaveOccurred())
184+
})
185+
186+
It("should handle multiple set operations", func() {
187+
mockFile := &os.File{}
188+
osMock.EXPECT().MkdirAll("/tmp/test-ready", os.FileMode(0755)).Return(nil).Times(2)
189+
osMock.EXPECT().Create(testFile).Return(mockFile, nil).Times(2)
190+
191+
err := r.Set(context.Background())
192+
Expect(err).ToNot(HaveOccurred())
193+
194+
err = r.Set(context.Background())
195+
Expect(err).ToNot(HaveOccurred())
196+
})
197+
198+
It("should handle multiple clear operations", func() {
199+
osMock.EXPECT().RemoveAll(testFile).Return(nil).Times(2)
200+
201+
err := r.Clear(context.Background())
202+
Expect(err).ToNot(HaveOccurred())
203+
204+
err = r.Clear(context.Background())
205+
Expect(err).ToNot(HaveOccurred())
206+
})
207+
})
208+
})

0 commit comments

Comments
 (0)