@@ -4,6 +4,7 @@ package fake
44
55import (
66 "context"
7+ "errors"
78
89 "github.com/hashicorp/go-uuid"
910
@@ -12,13 +13,13 @@ import (
1213)
1314
1415const zoneID = "a1887604-237c-4212-a9cd-94620b7880fa"
15- const snapshotID = "9d076136-657b-4c84-b279-455da3ea484c"
1616
1717type fakeConnector struct {
18- node * cloud.VM
19- snapshot * cloud.Snapshot
20- volumesByID map [string ]cloud.Volume
21- volumesByName map [string ]cloud.Volume
18+ node * cloud.VM
19+ volumesByID map [string ]cloud.Volume
20+ volumesByName map [string ]cloud.Volume
21+ snapshotsByID map [string ]* cloud.Snapshot
22+ snapshotsByName map [string ][]* cloud.Snapshot
2223}
2324
2425// New returns a new fake implementation of the
@@ -38,20 +39,15 @@ func New() cloud.Interface {
3839 ZoneID : zoneID ,
3940 }
4041
41- snapshot := & cloud.Snapshot {
42- ID : "9d076136-657b-4c84-b279-455da3ea484c" ,
43- Name : "pvc-vol-snap-1" ,
44- DomainID : "51f0fcb5-db16-4637-94f5-30131010214f" ,
45- ZoneID : zoneID ,
46- VolumeID : "4f1f610d-6f17-4ff9-9228-e4062af93e54" ,
47- CreatedAt : "2025-07-07 16:13:06" ,
48- }
42+ snapshotsByID := make (map [string ]* cloud.Snapshot )
43+ snapshotsByName := make (map [string ][]* cloud.Snapshot )
4944
5045 return & fakeConnector {
51- node : node ,
52- snapshot : snapshot ,
53- volumesByID : map [string ]cloud.Volume {volume .ID : volume },
54- volumesByName : map [string ]cloud.Volume {volume .Name : volume },
46+ node : node ,
47+ volumesByID : map [string ]cloud.Volume {volume .ID : volume },
48+ volumesByName : map [string ]cloud.Volume {volume .Name : volume },
49+ snapshotsByID : snapshotsByID ,
50+ snapshotsByName : snapshotsByName ,
5551 }
5652}
5753
@@ -72,6 +68,9 @@ func (f *fakeConnector) ListZonesID(_ context.Context) ([]string, error) {
7268}
7369
7470func (f * fakeConnector ) GetVolumeByID (_ context.Context , volumeID string ) (* cloud.Volume , error ) {
71+ if volumeID == "" {
72+ return nil , errors .New ("invalid volume ID: empty string" )
73+ }
7574 vol , ok := f .volumesByID [volumeID ]
7675 if ok {
7776 return & vol , nil
@@ -81,6 +80,9 @@ func (f *fakeConnector) GetVolumeByID(_ context.Context, volumeID string) (*clou
8180}
8281
8382func (f * fakeConnector ) GetVolumeByName (_ context.Context , name string ) (* cloud.Volume , error ) {
83+ if name == "" {
84+ return nil , errors .New ("invalid volume name: empty string" )
85+ }
8486 vol , ok := f .volumesByName [name ]
8587 if ok {
8688 return & vol , nil
@@ -137,18 +139,120 @@ func (f *fakeConnector) ExpandVolume(_ context.Context, volumeID string, newSize
137139 return cloud .ErrNotFound
138140}
139141
140- func (f * fakeConnector ) CreateVolumeFromSnapshot (ctx context.Context , zoneID , name , domainID , projectID , snapshotID string , sizeInGB int64 ) (* cloud.Volume , error ) {
141- return nil , nil
142+ func (f * fakeConnector ) CreateVolumeFromSnapshot (_ context.Context , zoneID , name , _ , _ string , sizeInGB int64 ) (* cloud.Volume , error ) {
143+ vol := & cloud.Volume {
144+ ID : "fake-vol-from-snap-" + name ,
145+ Name : name ,
146+ Size : util .GigaBytesToBytes (sizeInGB ),
147+ DiskOfferingID : "fake-disk-offering" ,
148+ ZoneID : zoneID ,
149+ }
150+ f .volumesByID [vol .ID ] = * vol
151+ f .volumesByName [vol .Name ] = * vol
152+
153+ return vol , nil
142154}
143155
144- func (f * fakeConnector ) GetSnapshotByID (ctx context.Context , snapshotID string ) (* cloud.Snapshot , error ) {
145- return f .snapshot , nil
156+ func (f * fakeConnector ) CreateSnapshot (_ context.Context , volumeID , name string ) (* cloud.Snapshot , error ) {
157+ if name == "" {
158+ return nil , errors .New ("invalid snapshot name: empty string" )
159+ }
160+ for _ , snap := range f .snapshotsByName [name ] {
161+ if snap .VolumeID == volumeID {
162+ // Allow multiple snapshots with the same name for the same volume
163+ continue
164+ }
165+
166+ // Name conflict: same name, different volume
167+ return nil , cloud .ErrAlreadyExists
168+ }
169+ id , _ := uuid .GenerateUUID ()
170+ newSnap := & cloud.Snapshot {
171+ ID : id ,
172+ Name : name ,
173+ DomainID : "fake-domain" ,
174+ ZoneID : zoneID ,
175+ VolumeID : volumeID ,
176+ CreatedAt : "2025-07-07T16:13:06-0700" ,
177+ }
178+ f .snapshotsByID [newSnap .ID ] = newSnap
179+ f .snapshotsByName [name ] = append (f .snapshotsByName [name ], newSnap )
180+
181+ return newSnap , nil
146182}
147183
148- func (f * fakeConnector ) CreateSnapshot (ctx context.Context , volumeID string ) (* cloud.Snapshot , error ) {
149- return f .snapshot , nil
184+ func (f * fakeConnector ) GetSnapshotByID (_ context.Context , snapshotID string ) (* cloud.Snapshot , error ) {
185+ snap , ok := f .snapshotsByID [snapshotID ]
186+ if ok {
187+ return snap , nil
188+ }
189+
190+ return nil , cloud .ErrNotFound
150191}
151192
152- func (f * fakeConnector ) DeleteSnapshot (ctx context.Context , snapshotID string ) error {
193+ func (f * fakeConnector ) GetSnapshotByName (_ context.Context , name string ) (* cloud.Snapshot , error ) {
194+ if name == "" {
195+ return nil , errors .New ("invalid snapshot name: empty string" )
196+ }
197+ snaps , ok := f .snapshotsByName [name ]
198+ if ok && len (snaps ) > 0 {
199+ return snaps [0 ], nil // Return the first for compatibility
200+ }
201+
202+ return nil , cloud .ErrNotFound
203+ }
204+
205+ // ListSnapshots returns all matching snapshots; pagination must be handled by the controller.
206+ func (f * fakeConnector ) ListSnapshots (_ context.Context , volumeID , snapshotID string ) ([]* cloud.Snapshot , error ) {
207+ if snapshotID != "" {
208+ result := make ([]* cloud.Snapshot , 0 , 1 )
209+ if snap , ok := f .snapshotsByID [snapshotID ]; ok {
210+ result = append (result , snap )
211+ }
212+
213+ return result , nil
214+ }
215+ if volumeID != "" {
216+ count := 0
217+ for _ , snap := range f .snapshotsByID {
218+ if snap .VolumeID == volumeID {
219+ count ++
220+ }
221+ }
222+ result := make ([]* cloud.Snapshot , 0 , count )
223+ for _ , snap := range f .snapshotsByID {
224+ if snap .VolumeID == volumeID {
225+ result = append (result , snap )
226+ }
227+ }
228+
229+ return result , nil
230+ }
231+ result := make ([]* cloud.Snapshot , 0 , len (f .snapshotsByID ))
232+ for _ , snap := range f .snapshotsByID {
233+ result = append (result , snap )
234+ }
235+
236+ return result , nil
237+ }
238+
239+ func (f * fakeConnector ) DeleteSnapshot (_ context.Context , snapshotID string ) error {
240+ snap , ok := f .snapshotsByID [snapshotID ]
241+ if ! ok {
242+ return cloud .ErrNotFound
243+ }
244+
245+ delete (f .snapshotsByID , snapshotID )
246+
247+ name := snap .Name
248+ snaps := f .snapshotsByName [name ]
249+ for i , s := range snaps {
250+ if s .ID == snapshotID {
251+ f .snapshotsByName [name ] = append (snaps [:i ], snaps [i + 1 :]... )
252+
253+ break
254+ }
255+ }
256+
153257 return nil
154258}
0 commit comments