Skip to content

Commit 96f370f

Browse files
committed
pkg: improve resolvers
1 parent d1923e6 commit 96f370f

10 files changed

Lines changed: 101 additions & 12 deletions

File tree

pkg/handlers/affinitygroup.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,11 @@ func DescribeAffinityGroup(name string) error {
8787

8888
// ResolveAffinityGroup returns the CloudStack affinity group ID for a given name.
8989
func ResolveAffinityGroup(name string) (string, error) {
90+
// Treat UUID inputs as IDs.
91+
if IsUUID(name) {
92+
return name, nil
93+
}
94+
9095
client, err := cloudstack.NewClient()
9196
if err != nil {
9297
return "", fmt.Errorf("failed to create CloudStack client: %w", err)

pkg/handlers/network.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ import (
1313

1414
// ResolveNetwork returns the CloudStack network ID for a given network name.
1515
func ResolveNetwork(name string) (string, error) {
16+
// If the value looks like a UUID, treat it as an ID and return it.
17+
if IsUUID(name) {
18+
return name, nil
19+
}
20+
1621
client, err := cloudstack.NewClient()
1722
if err != nil {
1823
return "", fmt.Errorf("failed to create CloudStack client: %w", err)
@@ -140,7 +145,12 @@ func ApplyNetwork(netRes *v1.Network) error {
140145
if netRes.Spec.NetworkOffering == "" || netRes.Spec.Zone == "" {
141146
return fmt.Errorf("network create requires spec.networkOffering and spec.zone in standalone mode")
142147
}
143-
createParams := client.Network.NewCreateNetworkParams(name, netRes.Spec.NetworkOffering, netRes.Spec.Zone)
148+
// Resolve zone name to ID; require resolution or return an error.
149+
zoneID, zerr := ResolveZone(netRes.Spec.Zone)
150+
if zerr != nil {
151+
return fmt.Errorf("failed to resolve zone %s: %w", netRes.Spec.Zone, zerr)
152+
}
153+
createParams := client.Network.NewCreateNetworkParams(name, netRes.Spec.NetworkOffering, zoneID)
144154
if netRes.Spec.Description != "" {
145155
createParams.SetDisplaytext(netRes.Spec.Description)
146156
}

pkg/handlers/resolve_helpers.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,18 @@ package handlers
22

33
import (
44
"fmt"
5+
"regexp"
56

67
"cloudstackctl/pkg/cloudstack"
78
)
89

910
// ResolveZone returns the CloudStack zone ID for a zone name.
1011
func ResolveZone(name string) (string, error) {
12+
// If the value already looks like a UUID, treat it as an ID and return it.
13+
if IsUUID(name) {
14+
return name, nil
15+
}
16+
1117
client, err := cloudstack.NewClient()
1218
if err != nil {
1319
return "", fmt.Errorf("failed to create CloudStack client: %w", err)
@@ -26,6 +32,11 @@ func ResolveZone(name string) (string, error) {
2632

2733
// ResolveServiceOffering returns the service offering ID for a name.
2834
func ResolveServiceOffering(name string) (string, error) {
35+
// If the value looks like a UUID, treat it as an ID and return it.
36+
if IsUUID(name) {
37+
return name, nil
38+
}
39+
2940
client, err := cloudstack.NewClient()
3041
if err != nil {
3142
return "", fmt.Errorf("failed to create CloudStack client: %w", err)
@@ -44,6 +55,11 @@ func ResolveServiceOffering(name string) (string, error) {
4455

4556
// ResolveDiskOffering returns the disk offering ID for a name.
4657
func ResolveDiskOffering(name string) (string, error) {
58+
// If the value looks like a UUID, treat it as an ID and return it.
59+
if IsUUID(name) {
60+
return name, nil
61+
}
62+
4763
client, err := cloudstack.NewClient()
4864
if err != nil {
4965
return "", fmt.Errorf("failed to create CloudStack client: %w", err)
@@ -62,6 +78,11 @@ func ResolveDiskOffering(name string) (string, error) {
6278

6379
// ResolveProject returns the CloudStack project ID for a given project name.
6480
func ResolveProject(name string) (string, error) {
81+
// If the value looks like a UUID, treat it as an ID and return it.
82+
if IsUUID(name) {
83+
return name, nil
84+
}
85+
6586
client, err := cloudstack.NewClient()
6687
if err != nil {
6788
return "", fmt.Errorf("failed to create CloudStack client: %w", err)
@@ -77,3 +98,9 @@ func ResolveProject(name string) (string, error) {
7798
}
7899
return resp.Projects[0].Id, nil
79100
}
101+
102+
// IsUUID returns true if the provided string matches a UUID pattern.
103+
func IsUUID(s string) bool {
104+
var uuidRegex = regexp.MustCompile(`(?i)^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`)
105+
return uuidRegex.MatchString(s)
106+
}

pkg/handlers/securitygroup.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,11 @@ func ApplySecurityGroup(sg *v1.SecurityGroup) error {
106106

107107
// ResolveSecurityGroup returns the CloudStack security group ID for a given name.
108108
func ResolveSecurityGroup(name string) (string, error) {
109+
// UUID inputs are treated as IDs.
110+
if IsUUID(name) {
111+
return name, nil
112+
}
113+
109114
client, err := cloudstack.NewClient()
110115
if err != nil {
111116
return "", fmt.Errorf("failed to create CloudStack client: %w", err)

pkg/handlers/snapshot.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,11 @@ func DeleteSnapshot(name string) error {
7979

8080
// ResolveSnapshot returns the CloudStack snapshot ID for a given snapshot name.
8181
func ResolveSnapshot(name string) (string, error) {
82+
// If the value looks like a UUID, treat it as an ID and return it.
83+
if IsUUID(name) {
84+
return name, nil
85+
}
86+
8287
client, err := cloudstack.NewClient()
8388
if err != nil {
8489
return "", fmt.Errorf("failed to create CloudStack client: %w", err)

pkg/handlers/sshkey.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,11 @@ func ApplySSHKey(key *v1.SSHKey) error {
106106

107107
// ResolveSSHKey returns the SSH keypair name if present in CloudStack.
108108
func ResolveSSHKey(name string) (string, error) {
109+
// If the value looks like a UUID, treat it as an ID and return it.
110+
if IsUUID(name) {
111+
return name, nil
112+
}
113+
109114
client, err := cloudstack.NewClient()
110115
if err != nil {
111116
return "", fmt.Errorf("failed to create CloudStack client: %w", err)

pkg/handlers/template.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,11 @@ func DeleteTemplate(name string) error {
7979

8080
// ResolveTemplate returns the CloudStack template ID for a given template name.
8181
func ResolveTemplate(name string) (string, error) {
82+
// If the value looks like a UUID, treat it as an ID and return it.
83+
if IsUUID(name) {
84+
return name, nil
85+
}
86+
8287
client, err := cloudstack.NewClient()
8388
if err != nil {
8489
return "", fmt.Errorf("failed to create CloudStack client: %w", err)

pkg/handlers/userdata.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,11 @@ func DescribeUserData(name string) error {
9696

9797
// ResolveUserData returns the CloudStack UserData ID for a given name.
9898
func ResolveUserData(name string) (string, error) {
99+
// If the value looks like a UUID, treat it as an ID and return it.
100+
if IsUUID(name) {
101+
return name, nil
102+
}
103+
99104
client, err := cloudstack.NewClient()
100105
if err != nil {
101106
return "", fmt.Errorf("failed to create CloudStack client: %w", err)

pkg/handlers/virtualmachine.go

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -122,28 +122,37 @@ func ApplyVirtualMachineManaged(vm *v1.VirtualMachine, managed bool) error {
122122
}
123123

124124
// Resolve potential name references to IDs for template, service offering, and networks
125-
templateID := vm.Spec.Template
126-
if tid, terr := ResolveTemplate(vm.Spec.Template); terr == nil {
127-
templateID = tid
125+
// Resolve template and service offering names to IDs; require resolution.
126+
templateID, terr := ResolveTemplate(vm.Spec.Template)
127+
if terr != nil {
128+
return fmt.Errorf("failed to resolve template %s: %w", vm.Spec.Template, terr)
128129
}
129-
serviceOfferingID := vm.Spec.ServiceOffering
130-
if soid, soerr := ResolveServiceOffering(vm.Spec.ServiceOffering); soerr == nil {
131-
serviceOfferingID = soid
130+
serviceOfferingID, soerr := ResolveServiceOffering(vm.Spec.ServiceOffering)
131+
if soerr != nil {
132+
return fmt.Errorf("failed to resolve service offering %s: %w", vm.Spec.ServiceOffering, soerr)
132133
}
133134

134135
// Resolve network names to IDs where provided
135136
resolvedNets := make([]string, 0, len(vm.Spec.NetworkIDs))
136137
for _, n := range vm.Spec.NetworkIDs {
137-
if nid, nerr := ResolveNetwork(n); nerr == nil {
138-
resolvedNets = append(resolvedNets, nid)
139-
} else {
140-
// assume already an ID
141-
resolvedNets = append(resolvedNets, n)
138+
nid, nerr := ResolveNetwork(n)
139+
if nerr != nil {
140+
return fmt.Errorf("failed to resolve network %s: %w", n, nerr)
142141
}
142+
resolvedNets = append(resolvedNets, nid)
143143
}
144144

145145
params := client.VirtualMachine.NewDeployVirtualMachineParams(serviceOfferingID, templateID, "")
146146
params.SetName(vm.Metadata.Name)
147+
// If a zone is provided in the spec, try to resolve the zone name to an ID.
148+
// If resolution fails, assume the provided value is already an ID and use it.
149+
if vm.Spec.Zone != "" {
150+
zid, zerr := ResolveZone(vm.Spec.Zone)
151+
if zerr != nil {
152+
return fmt.Errorf("failed to resolve zone %s: %w", vm.Spec.Zone, zerr)
153+
}
154+
params.SetZoneid(zid)
155+
}
147156
if vm.Spec.Project != "" {
148157
// Accept either a project UUID or a project name; try resolving name first.
149158
if pid, perr := ResolveProject(vm.Spec.Project); perr == nil {

pkg/handlers/volume.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,14 @@ func ApplyVolume(vol *v1.Volume) error {
107107
if vol.Spec.SizeGB > 0 {
108108
cp.SetSize(int64(vol.Spec.SizeGB))
109109
}
110+
// If a zone is provided, resolve its name to an ID; fail if not resolvable.
111+
if vol.Spec.Zone != "" {
112+
zid, zerr := ResolveZone(vol.Spec.Zone)
113+
if zerr != nil {
114+
return fmt.Errorf("failed to resolve zone %s: %w", vol.Spec.Zone, zerr)
115+
}
116+
cp.SetZoneid(zid)
117+
}
110118
if _, err := client.Volume.CreateVolume(cp); err != nil {
111119
return fmt.Errorf("failed to create volume: %w", err)
112120
}
@@ -119,6 +127,11 @@ func ApplyVolume(vol *v1.Volume) error {
119127

120128
// ResolveVolume returns the CloudStack volume ID for a given volume name.
121129
func ResolveVolume(name string) (string, error) {
130+
// If the value looks like a UUID, treat it as an ID and return it.
131+
if IsUUID(name) {
132+
return name, nil
133+
}
134+
122135
client, err := cloudstack.NewClient()
123136
if err != nil {
124137
return "", fmt.Errorf("failed to create CloudStack client: %w", err)

0 commit comments

Comments
 (0)