diff --git a/examples/main.tf b/examples/main.tf index 82a7d04b5..c3f58aea3 100644 --- a/examples/main.tf +++ b/examples/main.tf @@ -402,13 +402,18 @@ resource "netbox_ipam_ip_range" "range_test" { } } +resource "netbox_virtualization_vm_primary_ip" "name" { + virtualmachine_id = netbox_virtualization_vm.vm_test.id + primary_ip4_id = netbox_ipam_ip_addresses.ip_test.id + primary_ip6_id = netbox_ipam_ip_addresses.ip6_test.id +} + resource "netbox_ipam_ip_addresses" "ip_test" { address = "192.168.56.1/24" status = "active" tenant_id = netbox_tenancy_tenant.tenant_test.id object_id = netbox_virtualization_interface.interface_test.id object_type = netbox_virtualization_interface.interface_test.type - primary_ip4 = true tag { name = "tag1" @@ -493,6 +498,13 @@ resource "netbox_ipam_ip_addresses" "ip_test" { } } +resource "netbox_ipam_ip_addresses" "ip6_test" { + address = "2001:db8::1234/64" + status = "active" + object_id = netbox_virtualization_interface.interface_test.id + object_type = netbox_virtualization_interface.interface_test.type +} + resource "netbox_ipam_ip_addresses" "dynamic_ip_from_prefix" { prefix = netbox_ipam_prefix.dynamic_prefix_test.id description = "Dynamic IP in dynamic prefix created by terraform" diff --git a/examples/resources/netbox_ipam_ip_addresses/resource.tf b/examples/resources/netbox_ipam_ip_addresses/resource.tf index 9ecc9b694..a3796a6db 100644 --- a/examples/resources/netbox_ipam_ip_addresses/resource.tf +++ b/examples/resources/netbox_ipam_ip_addresses/resource.tf @@ -81,6 +81,13 @@ resource "netbox_ipam_ip_addresses" "ip_test" { } } +resource "netbox_ipam_ip_addresses" "ip6_test" { + address = "2001:db8::1234/64" + status = "active" + object_id = netbox_virtualization_interface.interface_test.id + object_type = netbox_virtualization_interface.interface_test.type +} + resource "netbox_ipam_ip_addresses" "dynamic_ip_from_prefix" { prefix = netbox_ipam_prefix.dynamic_prefix_test.id description = "Dynamic IP in dynamic prefix created by terraform" diff --git a/examples/resources/netbox_virtualization_vm_primary_ip/resource.tf b/examples/resources/netbox_virtualization_vm_primary_ip/resource.tf new file mode 100644 index 000000000..b4122114b --- /dev/null +++ b/examples/resources/netbox_virtualization_vm_primary_ip/resource.tf @@ -0,0 +1,5 @@ +resource "netbox_virtualization_vm_primary_ip" "name" { + virtualmachine_id = netbox_virtualization_vm.vm_test.id + primary_ip4_id = netbox_ipam_ip_addresses.ip_test.id + primary_ip6_id = netbox_ipam_ip_addresses.ip6_test.id +} diff --git a/netbox/provider.go b/netbox/provider.go index c5b4879f3..249521028 100644 --- a/netbox/provider.go +++ b/netbox/provider.go @@ -156,21 +156,22 @@ func Provider() *schema.Provider { "netbox_virtualization_cluster": dataNetboxVirtualizationCluster(), }, ResourcesMap: map[string]*schema.Resource{ - "netbox_ipam_aggregate": resourceNetboxIpamAggregate(), - "netbox_ipam_ip_addresses": resourceNetboxIpamIPAddresses(), - "netbox_ipam_ip_range": resourceNetboxIpamIPRange(), - "netbox_ipam_prefix": resourceNetboxIpamPrefix(), - "netbox_ipam_service": resourceNetboxIpamService(), - "netbox_ipam_vlan": resourceNetboxIpamVlan(), - "netbox_ipam_vlan_group": resourceNetboxIpamVlanGroup(), - "netbox_tenancy_contact": resourceNetboxTenancyContact(), - "netbox_tenancy_contact_assignment": resourceNetboxTenancyContactAssignment(), - "netbox_tenancy_contact_group": resourceNetboxTenancyContactGroup(), - "netbox_tenancy_contact_role": resourceNetboxTenancyContactRole(), - "netbox_tenancy_tenant": resourceNetboxTenancyTenant(), - "netbox_tenancy_tenant_group": resourceNetboxTenancyTenantGroup(), - "netbox_virtualization_interface": resourceNetboxVirtualizationInterface(), - "netbox_virtualization_vm": resourceNetboxVirtualizationVM(), + "netbox_ipam_aggregate": resourceNetboxIpamAggregate(), + "netbox_ipam_ip_addresses": resourceNetboxIpamIPAddresses(), + "netbox_ipam_ip_range": resourceNetboxIpamIPRange(), + "netbox_ipam_prefix": resourceNetboxIpamPrefix(), + "netbox_ipam_service": resourceNetboxIpamService(), + "netbox_ipam_vlan": resourceNetboxIpamVlan(), + "netbox_ipam_vlan_group": resourceNetboxIpamVlanGroup(), + "netbox_tenancy_contact": resourceNetboxTenancyContact(), + "netbox_tenancy_contact_assignment": resourceNetboxTenancyContactAssignment(), + "netbox_tenancy_contact_group": resourceNetboxTenancyContactGroup(), + "netbox_tenancy_contact_role": resourceNetboxTenancyContactRole(), + "netbox_tenancy_tenant": resourceNetboxTenancyTenant(), + "netbox_tenancy_tenant_group": resourceNetboxTenancyTenantGroup(), + "netbox_virtualization_interface": resourceNetboxVirtualizationInterface(), + "netbox_virtualization_vm": resourceNetboxVirtualizationVM(), + "netbox_virtualization_vm_primary_ip": resourceNetboxVirtualizationVMPrimaryIP(), }, ConfigureContextFunc: configureProvider, } diff --git a/netbox/resource_netbox_ipam_ip_addresses.go b/netbox/resource_netbox_ipam_ip_addresses.go index 9bbcd0c21..6a1939f25 100644 --- a/netbox/resource_netbox_ipam_ip_addresses.go +++ b/netbox/resource_netbox_ipam_ip_addresses.go @@ -91,7 +91,11 @@ func resourceNetboxIpamIPAddresses() *schema.Resource { Type: schema.TypeBool, Optional: true, Default: false, + Deprecated: "Use new netbox_virtualization_primary_ip resource instead", Description: "Set this resource as primary IPv4 (false by default).", + DiffSuppressFunc: func(k, oldValue, newValue string, d *schema.ResourceData) bool { + return d.GetRawConfig().GetAttr("primary_ip4").IsNull() + }, }, "role": { Type: schema.TypeString, @@ -473,17 +477,19 @@ func resourceNetboxIpamIPAddressesUpdate(ctx context.Context, d *schema.Resource return diag.FromErr(err) } - if (d.HasChange("object_id") && d.Get("primary_ip4").(bool)) || - (!d.HasChange("object_id") && d.HasChange("primary_ip4")) || - (d.HasChange("primary_ip4") && d.Get("primary_ip4").(bool)) { - objectID := int64(d.Get("object_id").(int)) - vmID, err := getVMIDForInterface(client, objectID) - if err != nil { - return diag.FromErr(err) - } - err = updatePrimaryStatus(client, vmID, resourceID, d.Get("primary_ip4").(bool)) - if err != nil { - return diag.FromErr(err) + if !d.GetRawConfig().GetAttr("primary_ip4").IsNull() { + if (d.HasChange("object_id") && d.Get("primary_ip4").(bool)) || + (!d.HasChange("object_id") && d.HasChange("primary_ip4")) || + (d.HasChange("primary_ip4") && d.Get("primary_ip4").(bool)) { + objectID := int64(d.Get("object_id").(int)) + vmID, err := getVMIDForInterface(client, objectID) + if err != nil { + return diag.FromErr(err) + } + err = updatePrimaryStatus(client, vmID, resourceID, d.Get("primary_ip4").(bool)) + if err != nil { + return diag.FromErr(err) + } } } diff --git a/netbox/resource_netbox_virtualization_vm.go b/netbox/resource_netbox_virtualization_vm.go index 4f079022e..bd2d856f8 100644 --- a/netbox/resource_netbox_virtualization_vm.go +++ b/netbox/resource_netbox_virtualization_vm.go @@ -75,6 +75,24 @@ func resourceNetboxVirtualizationVM() *schema.Resource { Default: nil, Description: "ID of the platform for this VM (virtualization module).", }, + "primary_ip": { + Type: schema.TypeString, + Computed: true, + Default: nil, + Description: "Primary IP of this VM (virtualization module). Can be IPv4 or IPv6. See [Netbox docs|https://docs.netbox.dev/en/stable/models/virtualization/virtualmachine/] for more information.", + }, + "primary_ip4": { + Type: schema.TypeString, + Computed: true, + Default: nil, + Description: "Primary IPv4 of this VM (virtualization module).", + }, + "primary_ip6": { + Type: schema.TypeString, + Computed: true, + Default: nil, + Description: "Primary IPv6 of this VM (virtualization module).", + }, "role_id": { Type: schema.TypeInt, Optional: true, @@ -283,6 +301,34 @@ func resourceNetboxVirtualizationVMRead(ctx context.Context, d *schema.ResourceD } } + if resource.PrimaryIP == nil { + if err = d.Set("primary_ip", nil); err != nil { + return diag.FromErr(err) + } + } else { + if err = d.Set("primary_ip", resource.PrimaryIP.Address); err != nil { + return diag.FromErr(err) + } + } + if resource.PrimaryIp4 == nil { + if err = d.Set("primary_ip4", nil); err != nil { + return diag.FromErr(err) + } + } else { + if err = d.Set("primary_ip4", resource.PrimaryIp4.Address); err != nil { + return diag.FromErr(err) + } + } + if resource.PrimaryIp6 == nil { + if err = d.Set("primary_ip6", nil); err != nil { + return diag.FromErr(err) + } + } else { + if err = d.Set("primary_ip6", resource.PrimaryIp6.Address); err != nil { + return diag.FromErr(err) + } + } + if resource.Role == nil { if err = d.Set("role_id", 0); err != nil { return diag.FromErr(err) diff --git a/netbox/resource_netbox_virtualization_vm_primary_ip.go b/netbox/resource_netbox_virtualization_vm_primary_ip.go new file mode 100644 index 000000000..a2f9aa44b --- /dev/null +++ b/netbox/resource_netbox_virtualization_vm_primary_ip.go @@ -0,0 +1,266 @@ +package netbox + +import ( + "context" + "strconv" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + netboxclient "github.com/smutel/go-netbox/v3/netbox/client" + "github.com/smutel/go-netbox/v3/netbox/client/virtualization" + "github.com/smutel/go-netbox/v3/netbox/models" +) + +func resourceNetboxVirtualizationVMPrimaryIP() *schema.Resource { + return &schema.Resource{ + Description: "Manage a primary ip assignment for a VM (virtualization module) resource within Netbox.", + CreateContext: resourceNetboxVirtualizationVMPrimaryIPCreate, + ReadContext: resourceNetboxVirtualizationVMPrimaryIPRead, + UpdateContext: resourceNetboxVirtualizationVMPrimaryIPUpdate, + DeleteContext: resourceNetboxVirtualizationVMPrimaryIPDelete, + Exists: resourceNetboxVirtualizationVMPrimaryIPExists, + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + + Schema: map[string]*schema.Schema{ + "virtualmachine_id": { + Type: schema.TypeInt, + Required: true, + ForceNew: true, + Default: nil, + Description: "ID of the virtual machine.", + }, + "primary_ip4_id": { + Type: schema.TypeInt, + Optional: true, + Default: nil, + Description: "ID of the primary IPv4 address.", + }, + "primary_ip6_id": { + Type: schema.TypeInt, + Optional: true, + Default: nil, + Description: "ID of the primary IPv4 address.", + }, + }, + } +} + +func resourceNetboxVirtualizationVMPrimaryIPCreate(ctx context.Context, d *schema.ResourceData, + m interface{}) diag.Diagnostics { + client := m.(*netboxclient.NetBoxAPI) + + resourceExists, err := resourceNetboxVirtualizationVMPrimaryIPExists(d, m) + if err != nil { + return diag.FromErr(err) + } + + if !resourceExists { + return diag.Errorf("virtual machine with ID %d does not exist", d.Get("virtualmachine_id")) + } + + dropFields := []string{ + "created", + "last_updated", + "name", + "cluster", + "tags", + } + emptyFields := make(map[string]interface{}) + + vmID := int64(d.Get("virtualmachine_id").(int)) + + newResource := &models.WritableVirtualMachineWithConfigContext{} + if primaryIP4ID := int64(d.Get("primary_ip4_id").(int)); primaryIP4ID != 0 { + newResource.PrimaryIp4 = &primaryIP4ID + } + if primaryIP6ID := int64(d.Get("primary_ip6_id").(int)); primaryIP6ID != 0 { + newResource.PrimaryIp6 = &primaryIP6ID + } + + resource := virtualization.NewVirtualizationVirtualMachinesPartialUpdateParams().WithData(newResource).WithID(vmID) + + resourceCreated, err := client.Virtualization.VirtualizationVirtualMachinesPartialUpdate(resource, nil, newRequestModifierOperation(emptyFields, dropFields)) + if err != nil { + return diag.FromErr(err) + } + + d.SetId(strconv.FormatInt(resourceCreated.Payload.ID, 10)) + + return resourceNetboxVirtualizationVMPrimaryIPRead(ctx, d, m) +} + +func resourceNetboxVirtualizationVMPrimaryIPRead(ctx context.Context, d *schema.ResourceData, + m interface{}) diag.Diagnostics { + client := m.(*netboxclient.NetBoxAPI) + + resourceID := d.Id() + params := virtualization.NewVirtualizationVirtualMachinesListParams().WithID( + &resourceID) + resources, err := client.Virtualization.VirtualizationVirtualMachinesList( + params, nil) + + if err != nil { + return diag.FromErr(err) + } + + for _, resource := range resources.Payload.Results { + if strconv.FormatInt(resource.ID, 10) == d.Id() { + + // Setting this is only needed for imported resources + if err := d.Set("virtualmachine_id", resource.ID); err != nil { + return diag.FromErr(err) + } + + var primaryIP4ID *int64 + primaryIP4ID = nil + if resource.PrimaryIp4 != nil { + primaryIP4ID = &resource.PrimaryIp4.ID + } + if err := d.Set("primary_ip4_id", primaryIP4ID); err != nil { + return diag.FromErr(err) + } + + var primaryIP6ID *int64 + primaryIP6ID = nil + if resource.PrimaryIp6 != nil { + primaryIP6ID = &resource.PrimaryIp6.ID + } + if err := d.Set("primary_ip6_id", primaryIP6ID); err != nil { + return diag.FromErr(err) + } + + return nil + } + } + + d.SetId("") + return nil +} + +func resourceNetboxVirtualizationVMPrimaryIPUpdate(ctx context.Context, d *schema.ResourceData, + m interface{}) diag.Diagnostics { + client := m.(*netboxclient.NetBoxAPI) + + resourceExists, err := resourceNetboxVirtualizationVMPrimaryIPExists(d, m) + if err != nil { + return diag.FromErr(err) + } + + if !resourceExists { + return diag.Errorf("virtual machine with ID %d does not exist", d.Get("virtualmachine_id")) + } + + dropFields := []string{ + "created", + "last_updated", + "name", + "cluster", + "tags", + } + emptyFields := make(map[string]interface{}) + + params := &models.WritableVirtualMachineWithConfigContext{} + + if d.HasChange("primary_ip4_id") { + primaryIP4ID := int64(d.Get("primary_ip4_id").(int)) + params.PrimaryIp4 = &primaryIP4ID + if primaryIP4ID == 0 { + emptyFields["primary_ip4"] = nil + } + } + if d.HasChange("primary_ip6_id") { + primaryIP6ID := int64(d.Get("primary_ip6_id").(int)) + params.PrimaryIp6 = &primaryIP6ID + if primaryIP6ID == 0 { + emptyFields["primary_ip6"] = nil + } + } + + resource := virtualization.NewVirtualizationVirtualMachinesPartialUpdateParams().WithData(params) + + resourceID, err := strconv.ParseInt(d.Id(), 10, 64) + if err != nil { + return diag.Errorf("Unable to convert ID into int64") + } + + resource.SetID(resourceID) + + _, err = client.Virtualization.VirtualizationVirtualMachinesPartialUpdate( + resource, nil, newRequestModifierOperation(emptyFields, dropFields)) + if err != nil { + return diag.FromErr(err) + } + + return resourceNetboxVirtualizationVMPrimaryIPRead(ctx, d, m) +} + +func resourceNetboxVirtualizationVMPrimaryIPDelete(ctx context.Context, d *schema.ResourceData, + m interface{}) diag.Diagnostics { + client := m.(*netboxclient.NetBoxAPI) + + resourceExists, err := resourceNetboxVirtualizationVMPrimaryIPExists(d, m) + if err != nil { + return diag.FromErr(err) + } + + if !resourceExists { + return nil + } + + dropFields := []string{ + "created", + "last_updated", + "name", + "cluster", + "tags", + } + emptyFields := map[string]interface{}{ + "primary_ip4": nil, + "primary_ip6": nil, + } + + params := &models.WritableVirtualMachineWithConfigContext{} + + resource := virtualization.NewVirtualizationVirtualMachinesPartialUpdateParams().WithData(params) + + resourceID, err := strconv.ParseInt(d.Id(), 10, 64) + if err != nil { + return diag.Errorf("Unable to convert ID into int64") + } + + resource.SetID(resourceID) + + _, err = client.Virtualization.VirtualizationVirtualMachinesPartialUpdate( + resource, nil, newRequestModifierOperation(emptyFields, dropFields)) + if err != nil { + return diag.FromErr(err) + } + + return nil +} + +func resourceNetboxVirtualizationVMPrimaryIPExists(d *schema.ResourceData, + m interface{}) (b bool, e error) { + client := m.(*netboxclient.NetBoxAPI) + resourceExist := false + + resourceID := int64(d.Get("virtualmachine_id").(int)) + resourceIDString := strconv.FormatInt(resourceID, 10) + params := virtualization.NewVirtualizationVirtualMachinesListParams().WithID( + &resourceIDString) + resources, err := client.Virtualization.VirtualizationVirtualMachinesList( + params, nil) + if err != nil { + return resourceExist, err + } + + for _, resource := range resources.Payload.Results { + if resource.ID == resourceID { + resourceExist = true + } + } + + return resourceExist, nil +} diff --git a/netbox/resource_netbox_virtualization_vm_primary_ip_test.go b/netbox/resource_netbox_virtualization_vm_primary_ip_test.go new file mode 100644 index 000000000..f2ce79e24 --- /dev/null +++ b/netbox/resource_netbox_virtualization_vm_primary_ip_test.go @@ -0,0 +1,194 @@ +package netbox + +import ( + "strconv" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +const resourceNameNetboxVirtualizationVMPrimaryIP = "netbox_virtualization_vm_primary_ip.test" + +func TestAccNetboxVirtualizationVMPrimaryIPMinimal(t *testing.T) { + nameSuffix := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) + ipnum := int64(acctest.RandIntRange(1, 16384)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckNetboxVirtualizationVMPrimaryIPConfig(nameSuffix, false, false, ipnum, false), + Check: resource.ComposeTestCheckFunc( + testAccResourceExists(resourceNameNetboxVirtualizationVMPrimaryIP), + ), + }, + { + ResourceName: resourceNameNetboxVirtualizationVM, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccNetboxVirtualizationVMPrimaryIPFull(t *testing.T) { + nameSuffix := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) + ipnum := int64(acctest.RandIntRange(1, 16384)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckNetboxVirtualizationVMPrimaryIPConfig(nameSuffix, true, true, ipnum, false), + Check: resource.ComposeTestCheckFunc( + testAccResourceExists(resourceNameNetboxVirtualizationVMPrimaryIP), + ), + }, + { + ResourceName: resourceNameNetboxVirtualizationVM, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccNetboxVirtualizationVMPrimaryIPMinimalFullMinimal(t *testing.T) { + nameSuffix := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) + ipnum := int64(acctest.RandIntRange(1, 16384)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckNetboxVirtualizationVMPrimaryIPConfig(nameSuffix, false, false, ipnum, false), + Check: resource.ComposeTestCheckFunc( + testAccResourceExists(resourceNameNetboxVirtualizationVMPrimaryIP), + ), + }, + { + Config: testAccCheckNetboxVirtualizationVMPrimaryIPConfig(nameSuffix, true, true, ipnum, false), + Check: resource.ComposeTestCheckFunc( + testAccResourceExists(resourceNameNetboxVirtualizationVMPrimaryIP), + ), + }, + { + Config: testAccCheckNetboxVirtualizationVMPrimaryIPConfig(nameSuffix, false, true, ipnum, false), + Check: resource.ComposeTestCheckFunc( + testAccResourceExists(resourceNameNetboxVirtualizationVMPrimaryIP), + ), + }, + { + Config: testAccCheckNetboxVirtualizationVMPrimaryIPConfig(nameSuffix, false, false, ipnum, false), + Check: resource.ComposeTestCheckFunc( + testAccResourceExists(resourceNameNetboxVirtualizationVMPrimaryIP), + ), + }, + }, + }) +} +func TestAccNetboxVirtualizationVMPrimaryIPLegacy(t *testing.T) { + nameSuffix := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) + ipnum := int64(acctest.RandIntRange(1, 16384)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckNetboxVirtualizationVMPrimaryIPConfig(nameSuffix, true, true, ipnum, true), + }, + { + Config: testAccCheckNetboxVirtualizationVMPrimaryIPConfig(nameSuffix, true, true, ipnum, false), + Check: resource.ComposeTestCheckFunc( + testAccResourceExists(resourceNameNetboxVirtualizationVMPrimaryIP), + ), + }, + }, + }) +} + +func testAccCheckNetboxVirtualizationVMPrimaryIPConfig(nameSuffix string, resourceFull, extraResources bool, ipnum int64, legacy bool) string { + template := ` + #resource "netbox_virtualization_cluster_type" "test" { + # name = "test-{{ .namesuffix }}" + # slug = "test-{{ .namesuffix }}" + #} + + #resource "netbox_virtualization_cluster" "test" { + # name = "test-{{ .namesuffix }}" + # type_id = netbox_virtualization_cluster_type.test.id + #} + + data "netbox_virtualization_cluster" "cluster_test" { + name = "test" + } + + resource "netbox_virtualization_vm" "test" { + name = "test-{{ .namesuffix }}" + #cluster_id = netbox_virtualization_cluster.test.id + cluster_id = data.netbox_virtualization_cluster.cluster_test.id + } + + {{ if eq .extraresources "true" }} + resource "netbox_virtualization_interface" "test" { + name = "test-{{ .namesuffix }}" + virtualmachine_id = netbox_virtualization_vm.test.id + } + + resource "netbox_virtualization_interface" "test2" { + name = "test2-{{ .namesuffix }}" + virtualmachine_id = netbox_virtualization_vm.test.id + } + + resource "netbox_ipam_ip_addresses" "test4" { + address = "${cidrhost("10.0.0.0/8", {{ .ipnum }})}/24" + object_id = netbox_virtualization_interface.test.id + object_type = "virtualization.vminterface" + {{ if eq .legacy "true" }} + primary_ip4 = true + {{ end }} + } + + resource "netbox_ipam_ip_addresses" "test6" { + address = "${cidrhost("2001:db8::/32", {{ .ipnum }})}/24" + object_id = netbox_virtualization_interface.test.id + object_type = "virtualization.vminterface" + } + + resource "netbox_ipam_ip_addresses" "test4alt" { + address = "${cidrhost("10.0.0.0/8", {{ .ipnum }} + 1)}/24" + object_id = netbox_virtualization_interface.test2.id + object_type = "virtualization.vminterface" + } + + resource "netbox_ipam_ip_addresses" "test6alt" { + address = "${cidrhost("2001:db8::/32", {{ .ipnum }} + 1)}/24" + object_id = netbox_virtualization_interface.test2.id + object_type = "virtualization.vminterface" + } + {{ end }} + + {{ if eq .legacy "false" }} + resource "netbox_virtualization_vm_primary_ip" "test" { + virtualmachine_id = netbox_virtualization_vm.test.id + {{ if eq .resourcefull "true" }} + primary_ip4_id = netbox_ipam_ip_addresses.test4.id + primary_ip6_id = netbox_ipam_ip_addresses.test6.id + {{ end }} + } + {{ end }} + ` + data := map[string]string{ + "namesuffix": nameSuffix, + "extraresources": strconv.FormatBool(extraResources), + "resourcefull": strconv.FormatBool(resourceFull), + "ipnum": strconv.FormatInt(ipnum, 10), + "legacy": strconv.FormatBool(legacy), + } + return renderTemplate(template, data) +}