Skip to content

Commit d1923e6

Browse files
committed
apis: support zone and project better
1 parent aee6e68 commit d1923e6

14 files changed

Lines changed: 97 additions & 36 deletions

File tree

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ Quick reference for the key fields users will commonly set for higher-level reso
8383
| Field | Type | Description |
8484
|---|---|---|
8585
| `metadata.name` | string | Application name |
86-
| `spec.projectId` | string | CloudStack project UUID |
86+
| `spec.project` | string | CloudStack project UUID or name |
8787
| `spec.components` | list | Ordered list of component references (name, vmspec, replicas) |
8888

8989
**Component**
@@ -138,7 +138,7 @@ kind: Application
138138
metadata:
139139
name: app-with-reused-vmspec
140140
spec:
141-
projectId: 987e6543-e21b-12d3-a456-426655440000
141+
project: 987e6543-e21b-12d3-a456-426655440000
142142
components:
143143
- name: frontend
144144
virtualMachineSpec: basic-vm-spec
@@ -157,7 +157,7 @@ kind: Application
157157
metadata:
158158
name: simple-app
159159
spec:
160-
projectId: 987e6543-e21b-12d3-a456-426655440000
160+
project: 987e6543-e21b-12d3-a456-426655440000
161161
components:
162162
- name: frontend
163163
virtualMachineSpec: basic-vm-spec
@@ -175,7 +175,7 @@ kind: VirtualMachine
175175
metadata:
176176
name: standalone-vm
177177
spec:
178-
projectId: 987e6543-e21b-12d3-a456-426655440000
178+
project: 987e6543-e21b-12d3-a456-426655440000
179179
template: ubuntu-22.04
180180
serviceOffering: medium
181181
networkIds:

apis/v1/types.go

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ type Application struct {
3737

3838
// ApplicationSpec defines the desired state of an Application
3939
type ApplicationSpec struct {
40-
ProjectID string `yaml:"projectId"` // CloudStack project ID
40+
Project string `yaml:"project"` // CloudStack project ID or name
4141
Components []ComponentRef `yaml:"components" gorm:"serializer:json"` // Dependent components (ordered)
4242
}
4343

@@ -102,7 +102,8 @@ type VirtualMachine struct {
102102

103103
// VirtualMachineSpec defines reusable VM configuration (template/offering/network)
104104
type VirtualMachineSpec struct {
105-
ProjectID string `yaml:"projectId"` // CloudStack project ID
105+
Zone string `yaml:"zone"` // CloudStack zone ID or name
106+
Project string `yaml:"project"` // CloudStack project ID or name
106107
Template string `yaml:"template"` // VM template name/ID
107108
ServiceOffering string `yaml:"serviceOffering"` // VM service offering (size)
108109
NetworkIDs []string `yaml:"networkIds" gorm:"serializer:json"` // Attached networks
@@ -138,13 +139,13 @@ type Network struct {
138139

139140
// NetworkSpec defines the desired state of a Network
140141
type NetworkSpec struct {
141-
ZoneID string `yaml:"zoneId"` // CloudStack zone ID
142-
NetworkOfferingID string `yaml:"networkOfferingId,omitempty"` // Network offering ID for creation
143-
Description string `yaml:"description,omitempty"` // Human-friendly description / displayText
144-
Gateway string `yaml:"gateway,omitempty"` // Gateway IP for shared networks
145-
Netmask string `yaml:"netmask,omitempty"` // Netmask for shared networks
146-
StartIP string `yaml:"startIp,omitempty"` // Start IP for static IP range (shared network)
147-
EndIP string `yaml:"endIp,omitempty"` // End IP for static IP range (shared network)
142+
Zone string `yaml:"zone"` // CloudStack zone ID or name
143+
NetworkOffering string `yaml:"networkOffering,omitempty"` // Network offering ID or name for creation
144+
Description string `yaml:"description,omitempty"` // Human-friendly description / displayText
145+
Gateway string `yaml:"gateway,omitempty"` // Gateway IP for shared networks
146+
Netmask string `yaml:"netmask,omitempty"` // Netmask for shared networks
147+
StartIP string `yaml:"startIp,omitempty"` // Start IP for static IP range (shared network)
148+
EndIP string `yaml:"endIp,omitempty"` // End IP for static IP range (shared network)
148149
}
149150

150151
// Volume represents a disk attached to a VM in CloudStack
@@ -159,6 +160,7 @@ type Volume struct {
159160

160161
// VolumeSpec defines the desired state of a Volume
161162
type VolumeSpec struct {
163+
Zone string `yaml:"zone"` // CloudStack zone ID or name
162164
DiskOffering string `yaml:"diskOffering"` // Disk offering type (HDD/SSD)
163165
SizeGB int `yaml:"size" gorm:"size_gb"` // Disk size in GB
164166
ID string `yaml:"id,omitempty" gorm:"column:volume_id"`

apis/v1/types_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ kind: Network
1212
metadata:
1313
name: test-net
1414
spec:
15-
zoneId: zone-1
16-
networkOfferingId: offer-123
15+
zone: zone-1
16+
networkOffering: offer-123
1717
gateway: 10.0.0.1
1818
netmask: 255.255.255.0
1919
startIp: 10.0.0.10
@@ -28,11 +28,11 @@ spec:
2828
if n.Metadata.Name != "test-net" {
2929
t.Fatalf("unexpected metadata.name: %q", n.Metadata.Name)
3030
}
31-
if n.Spec.ZoneID != "zone-1" {
32-
t.Fatalf("unexpected zoneId: %q", n.Spec.ZoneID)
31+
if n.Spec.Zone != "zone-1" {
32+
t.Fatalf("unexpected zone: %q", n.Spec.Zone)
3333
}
34-
if n.Spec.NetworkOfferingID != "offer-123" {
35-
t.Fatalf("unexpected networkOfferingId: %q", n.Spec.NetworkOfferingID)
34+
if n.Spec.NetworkOffering != "offer-123" {
35+
t.Fatalf("unexpected networkOffering: %q", n.Spec.NetworkOffering)
3636
}
3737
if n.Spec.Gateway != "10.0.0.1" {
3838
t.Fatalf("unexpected gateway: %q", n.Spec.Gateway)

controller/cmd_get.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,12 @@ func ListApplications(name string) {
3636
}
3737

3838
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
39-
fmt.Fprintln(w, "NAME\tPROJECT ID\tSTATUS\tREADY\tDRIFT")
39+
fmt.Fprintln(w, "NAME\tPROJECT\tSTATUS\tREADY\tDRIFT")
4040

4141
for _, app := range apps {
4242
fmt.Fprintf(w, "%s\t%s\t%s\t%t\t%t\n",
4343
app.Metadata.Name,
44-
app.Spec.ProjectID,
44+
app.Spec.Project,
4545
app.Status.ObservedState,
4646
app.Status.Ready,
4747
app.Status.Drift,

controller/controller.go

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"log"
1111
"net/http"
1212
"reflect"
13+
"strings"
1314
"time"
1415

1516
"github.com/apache/cloudstack-go/v2/cloudstack"
@@ -567,8 +568,12 @@ func (c *Controller) applyVM(vm *v1.VirtualMachine) error {
567568
// search CloudStack by name and project
568569
params := c.csClient.VirtualMachine.NewListVirtualMachinesParams()
569570
params.SetName(vm.Metadata.Name)
570-
if vm.Spec.ProjectID != "" {
571-
params.SetProjectid(vm.Spec.ProjectID)
571+
if vm.Spec.Project != "" {
572+
if pid, perr := handlers.ResolveProject(vm.Spec.Project); perr == nil {
573+
params.SetProjectid(pid)
574+
} else {
575+
params.SetProjectid(vm.Spec.Project)
576+
}
572577
}
573578
tags := map[string]string{"managed_by": "cloudstackctl"}
574579
params.SetTags(tags)
@@ -618,7 +623,7 @@ func compareVMSpec(a, b v1.VirtualMachineSpec) bool {
618623
if a.ServiceOffering != b.ServiceOffering {
619624
return false
620625
}
621-
if a.ProjectID != b.ProjectID {
626+
if a.Project != b.Project {
622627
return false
623628
}
624629
if len(a.NetworkIDs) != len(b.NetworkIDs) {
@@ -673,7 +678,14 @@ func (c *Controller) createVM(vm *v1.VirtualMachine) error {
673678
"",
674679
)
675680
params.SetName(vm.Metadata.Name)
676-
params.SetProjectid(vm.Spec.ProjectID)
681+
// Accept project name or ID
682+
if vm.Spec.Project != "" {
683+
if pid, perr := handlers.ResolveProject(vm.Spec.Project); perr == nil {
684+
params.SetProjectid(pid)
685+
} else {
686+
params.SetProjectid(vm.Spec.Project)
687+
}
688+
}
677689
if len(vm.Spec.NetworkIDs) > 0 {
678690
params.SetNetworkids(vm.Spec.NetworkIDs)
679691
}
@@ -683,6 +695,32 @@ func (c *Controller) createVM(vm *v1.VirtualMachine) error {
683695
params.SetKeypair(vm.Spec.SSHKeys[0])
684696
}
685697

698+
// Apply optional deploy parameters from the VM spec where possible.
699+
// This attempts to call SDK setter methods (e.g., SetBootMode) if they exist.
700+
if vm.Spec.Parameters != nil {
701+
pv := reflect.ValueOf(params)
702+
for k, v := range vm.Spec.Parameters {
703+
parts := strings.FieldsFunc(k, func(r rune) bool { return r == '_' || r == '-' || r == ' ' })
704+
for i := range parts {
705+
parts[i] = strings.Title(parts[i])
706+
}
707+
camel := strings.Join(parts, "")
708+
candidates := []string{"Set" + camel, "Set" + strings.Title(k)}
709+
applied := false
710+
for _, m := range candidates {
711+
meth := pv.MethodByName(m)
712+
if meth.IsValid() && meth.Type().NumIn() == 1 && meth.Type().In(0).Kind() == reflect.String {
713+
meth.Call([]reflect.Value{reflect.ValueOf(v)})
714+
applied = true
715+
break
716+
}
717+
}
718+
if !applied {
719+
log.Printf("info: VM parameter '%s' not applied (no SDK setter found)", k)
720+
}
721+
}
722+
}
723+
686724
// Tagging is handled after deployment via the Resourcetags service below.
687725

688726
// Execute API call

controller/reconcile.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ func (c *Controller) populateObservedSpec(vm *v1.VirtualMachine) error {
172172

173173
// Project and zone
174174
if v.Projectid != "" {
175-
obs.ProjectID = v.Projectid
175+
obs.Project = v.Projectid
176176
}
177177

178178
// Volumes: list volumes attached to the VM if we have CloudStack ID

examples/application.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ kind: Application
33
metadata:
44
name: example-app
55
spec:
6-
projectId: 987e6543-e21b-12d3-a456-426655440000
76
components:
87
- name: frontend
98
virtualMachineSpec: basic-vm-spec

examples/cluster/virtualmachine.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,3 @@ metadata:
44
name: example-vm-cluster
55
spec:
66
virtualMachineSpec: frontend-vmspec
7-
projectId: ""

examples/standalone/network.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ kind: Network
33
metadata:
44
name: example-network
55
spec:
6-
projectId: 987e6543-e21b-12d3-a456-426655440000
6+
zone: zone-1
77
name: my-private-network
88
cidr: 10.0.0.0/24
99
description: "Existing network reference used by VMs"

examples/standalone/virtualmachine.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ kind: VirtualMachine
33
metadata:
44
name: standalone-vm
55
spec:
6-
projectId: 987e6543-e21b-12d3-a456-426655440000
6+
zone: zone-1
77
template: ubuntu-22.04
88
serviceOffering: medium
99
networkIds:

0 commit comments

Comments
 (0)