Problem
(an existing problem, analysis by Opus 4.6R )
The cloudstack_ipaddress resource always lets CloudStack auto-select the
next free IP. There is no way to request a particular address.
This blocks a common enterprise pattern: an operator dedicates an intranet
VLAN/IP range to an account (via cloudstack_vlan_ip_range with account +
domain_id), then the tenant must acquire a specific IP from that range
into a VPC — for example because firewall rules, DNS records, or routing
tables on the corporate side are pre-provisioned for that exact address.
The CloudStack API (associateIpAddress) already accepts an optional
ipaddress parameter, and the Go SDK (cloudstack-go/v2) already exposes
AssociateIpAddressParams.SetIpaddress(string). The Terraform provider
simply never calls it.
Analysis
| Layer |
Status |
CloudStack API (associateIpAddress) |
ipaddress parameter supported |
Go SDK v2.18.1 (AssociateIpAddressParams) |
SetIpaddress(string) exists |
Terraform provider cloudstack_ipaddress |
ip_address is Computed-only — never sent to the API |
The fix is small and self-contained:
- Change the
ip_address schema field from Computed-only to
Optional + Computed + ForceNew.
- In the Create function, if the user supplied
ip_address, call
p.SetIpaddress(...) before the API call.
- No changes to Read/Delete —
ip_address is already read back from the
API response.
What happens if not implemented
- Users who need a deterministic IP in a VPC (intranet routing, pre-provisioned
firewall/DNS) must fall back to a local-exec provisioner or an external
script calling cmk / raw HTTP after terraform apply.
- The IP is created outside Terraform state, so it cannot be referenced by
other resources, is invisible to terraform plan, and will not be destroyed
on terraform destroy.
- Drift detection is impossible: Terraform shows a Computed
ip_address that
may differ from the one the post-script allocated.
Files to touch
cloudstack/resource_cloudstack_ipaddress.go (schema + create function)
cloudstack/resource_cloudstack_ipaddress_test.go (acceptance test for specific IP)
website/docs/r/ipaddress.html.markdown (document the new field)
Code diffs
cloudstack/resource_cloudstack_ipaddress.go
1. Schema — make ip_address optional + force-new
"ip_address": {
- Type: schema.TypeString,
- Computed: true,
+ Type: schema.TypeString,
+ Optional: true,
+ Computed: true,
+ ForceNew: true,
},
Full context (lines 70-73):
// BEFORE
"ip_address": {
Type: schema.TypeString,
Computed: true,
},
// AFTER
"ip_address": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
2. Create function — pass the requested IP to the API
Insert after the p.SetVpcid block (line 110) and before the zone block
(line 112):
if vpcid, ok := d.GetOk("vpc_id"); ok {
// Set the vpcid
p.SetVpcid(vpcid.(string))
}
+ if ipaddress, ok := d.GetOk("ip_address"); ok {
+ p.SetIpaddress(ipaddress.(string))
+ }
+
if zone, ok := d.GetOk("zone"); ok {
Full context (lines 107-121):
// BEFORE
if vpcid, ok := d.GetOk("vpc_id"); ok {
// Set the vpcid
p.SetVpcid(vpcid.(string))
}
if zone, ok := d.GetOk("zone"); ok {
// AFTER
if vpcid, ok := d.GetOk("vpc_id"); ok {
// Set the vpcid
p.SetVpcid(vpcid.(string))
}
if ipaddress, ok := d.GetOk("ip_address"); ok {
p.SetIpaddress(ipaddress.(string))
}
if zone, ok := d.GetOk("zone"); ok {
No changes needed in resourceCloudStackIPAddressRead — line 168 already
reads back the allocated address:
d.Set("ip_address", ip.Ipaddress)
No changes needed in resourceCloudStackIPAddressDelete.
Problem
(an existing problem, analysis by Opus 4.6R )
The
cloudstack_ipaddressresource always lets CloudStack auto-select thenext free IP. There is no way to request a particular address.
This blocks a common enterprise pattern: an operator dedicates an intranet
VLAN/IP range to an account (via
cloudstack_vlan_ip_rangewithaccount+domain_id), then the tenant must acquire a specific IP from that rangeinto a VPC — for example because firewall rules, DNS records, or routing
tables on the corporate side are pre-provisioned for that exact address.
The CloudStack API (
associateIpAddress) already accepts an optionalipaddressparameter, and the Go SDK (cloudstack-go/v2) already exposesAssociateIpAddressParams.SetIpaddress(string). The Terraform providersimply never calls it.
Analysis
associateIpAddress)ipaddressparameter supportedv2.18.1(AssociateIpAddressParams)SetIpaddress(string)existscloudstack_ipaddressip_addressis Computed-only — never sent to the APIThe fix is small and self-contained:
ip_addressschema field fromComputed-only toOptional + Computed + ForceNew.ip_address, callp.SetIpaddress(...)before the API call.ip_addressis already read back from theAPI response.
What happens if not implemented
firewall/DNS) must fall back to a
local-execprovisioner or an externalscript calling
cmk/ raw HTTP afterterraform apply.other resources, is invisible to
terraform plan, and will not be destroyedon
terraform destroy.ip_addressthatmay differ from the one the post-script allocated.
Files to touch
Code diffs
cloudstack/resource_cloudstack_ipaddress.go1. Schema — make
ip_addressoptional + force-new"ip_address": { - Type: schema.TypeString, - Computed: true, + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, },Full context (lines 70-73):
2. Create function — pass the requested IP to the API
Insert after the
p.SetVpcidblock (line 110) and before thezoneblock(line 112):
if vpcid, ok := d.GetOk("vpc_id"); ok { // Set the vpcid p.SetVpcid(vpcid.(string)) } + if ipaddress, ok := d.GetOk("ip_address"); ok { + p.SetIpaddress(ipaddress.(string)) + } + if zone, ok := d.GetOk("zone"); ok {Full context (lines 107-121):
No changes needed in
resourceCloudStackIPAddressRead— line 168 alreadyreads back the allocated address:
No changes needed in
resourceCloudStackIPAddressDelete.