Skip to content

Commit 70673ff

Browse files
authored
Merge pull request #12 from shapeblue/update-runner
Update ubuntu version
2 parents 5c0ef9e + 027f805 commit 70673ff

File tree

11 files changed

+332
-78
lines changed

11 files changed

+332
-78
lines changed

.github/workflows/pr-check.yaml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,28 +6,28 @@ on:
66
jobs:
77
lint:
88
name: Lint
9-
runs-on: ubuntu-20.04
9+
runs-on: ubuntu-24.04
1010
steps:
11-
- name: Setup up Go 1.x
11+
- name: Setup up Go 1.23
1212
uses: actions/setup-go@v5
1313
with:
14-
go-version: "^1.15"
14+
go-version: "1.23"
1515
- name: Check out code
1616
uses: actions/checkout@v4
1717
- name: golangci-lint
1818
uses: golangci/golangci-lint-action@v6
1919
with:
20-
version: v1.58.2
20+
version: v1.63.4
2121
args: --timeout=5m
2222

2323
build:
2424
name: Test & Build
25-
runs-on: ubuntu-20.04
25+
runs-on: ubuntu-24.04
2626
steps:
27-
- name: Setup up Go 1.x
27+
- name: Setup up Go 1.23
2828
uses: actions/setup-go@v5
2929
with:
30-
go-version: "^1.15"
30+
go-version: "1.23"
3131

3232
- name: Check out code
3333
uses: actions/checkout@v4

.github/workflows/release.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ env:
1414
jobs:
1515
push:
1616
name: Push images
17-
runs-on: ubuntu-20.04
17+
runs-on: ubuntu-24.04
1818

1919
steps:
2020
- name: Check out code
@@ -67,7 +67,7 @@ jobs:
6767

6868
release:
6969
name: Release
70-
runs-on: ubuntu-20.04
70+
runs-on: ubuntu-24.04
7171

7272
# Run only if previous job has succeeded
7373
needs: [push]

go.mod

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
module github.com/shapeblue/cloudstack-csi-driver
22

3-
go 1.21
3+
go 1.23
4+
5+
toolchain go1.23.5
46

57
require (
68
github.com/apache/cloudstack-go/v2 v2.16.1
@@ -12,6 +14,7 @@ require (
1214
golang.org/x/sys v0.20.0
1315
golang.org/x/text v0.16.0
1416
google.golang.org/grpc v1.65.0
17+
google.golang.org/protobuf v1.34.1
1518
gopkg.in/gcfg.v1 v1.2.3
1619
k8s.io/api v0.29.7
1720
k8s.io/apimachinery v0.29.7
@@ -67,7 +70,6 @@ require (
6770
golang.org/x/time v0.5.0 // indirect
6871
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
6972
google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // indirect
70-
google.golang.org/protobuf v1.34.1 // indirect
7173
gopkg.in/inf.v0 v0.9.1 // indirect
7274
gopkg.in/warnings.v0 v0.1.2 // indirect
7375
gopkg.in/yaml.v2 v2.4.0 // indirect

pkg/cloud/cloud.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import (
1010
)
1111

1212
// Interface is the CloudStack client interface.
13+
14+
//nolint:interfacebloat
1315
type Interface interface {
1416
GetNodeInfo(ctx context.Context, vmName string) (*VM, error)
1517
GetVMByID(ctx context.Context, vmID string) (*VM, error)
@@ -24,10 +26,12 @@ type Interface interface {
2426
DetachVolume(ctx context.Context, volumeID string) error
2527
ExpandVolume(ctx context.Context, volumeID string, newSizeInGB int64) error
2628

27-
CreateVolumeFromSnapshot(ctx context.Context, zoneID, name, domainID, projectID, snapshotID string, sizeInGB int64) (*Volume, error)
29+
CreateVolumeFromSnapshot(ctx context.Context, zoneID, name, projectID, snapshotID string, sizeInGB int64) (*Volume, error)
2830
GetSnapshotByID(ctx context.Context, snapshotID string) (*Snapshot, error)
29-
CreateSnapshot(ctx context.Context, volumeID string) (*Snapshot, error)
31+
GetSnapshotByName(ctx context.Context, name string) (*Snapshot, error)
32+
CreateSnapshot(ctx context.Context, volumeID, name string) (*Snapshot, error)
3033
DeleteSnapshot(ctx context.Context, snapshotID string) error
34+
ListSnapshots(ctx context.Context, volumeID, snapshotID string) ([]*Snapshot, error)
3135
}
3236

3337
// Volume represents a CloudStack volume.
@@ -70,6 +74,7 @@ type VM struct {
7074
var (
7175
ErrNotFound = errors.New("not found")
7276
ErrTooManyResults = errors.New("too many results")
77+
ErrAlreadyExists = errors.New("already exists")
7378
)
7479

7580
// client is the implementation of Interface.

pkg/cloud/config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package cloud
33
import (
44
"fmt"
55

6-
"gopkg.in/gcfg.v1"
6+
gcfg "gopkg.in/gcfg.v1"
77
)
88

99
// Config holds CloudStack connection configuration.

pkg/cloud/fake/fake.go

Lines changed: 128 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package fake
44

55
import (
66
"context"
7+
"errors"
78

89
"github.com/hashicorp/go-uuid"
910

@@ -12,13 +13,13 @@ import (
1213
)
1314

1415
const zoneID = "a1887604-237c-4212-a9cd-94620b7880fa"
15-
const snapshotID = "9d076136-657b-4c84-b279-455da3ea484c"
1616

1717
type 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

7470
func (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

8382
func (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

Comments
 (0)