Skip to content

Commit

Permalink
feat: Add custom_fields to IP address resource
Browse files Browse the repository at this point in the history
  • Loading branch information
smutel committed Dec 13, 2020
1 parent a0c8a45 commit bb962ee
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 23 deletions.
16 changes: 16 additions & 0 deletions docs/resources/ipam_ip_addresses.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,29 @@ resource "netbox_ipam_ip_addresses" "ip_test" {
name = "tag1"
slug = "tag1"
}
custom_fields = {
cf_boolean = "true"
cf_date = "2020-12-25"
cf_integer = "10"
cf_selection = "1"
cf_text = "Some text"
cf_url = "https://github.com"
}
}
```

## Argument Reference

The following arguments are supported:
* ``address`` - (Required) The IP address (with mask) used for this object.
* ``custom_fields`` - (Optional) Custom Field Keys and Values for this object
* For boolean, use the string value "true" or "false"
* For data, use the string format "YYYY-MM-DD"
* For integer, use the value between double quote "10"
* For selection, use the level id
* For text, use the string value
* For URL, use the URL as string
* ``description`` - (Optional) The description of this object.
* ``dns_name`` - (Optional) The DNS name of this object.
* ``nat_inside_id`` - (Optional) The ID of the NAT inside of this object.
Expand Down
12 changes: 6 additions & 6 deletions docs/resources/tenancy_tenant.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@ resource "netbox_tenancy_tenant" "tenant_test" {
The following arguments are supported:
* ``comments`` - (Optional) Comments for this object.
* ``custom_fields`` - (Optional) Custom Field Keys and Values for this object
** For boolean, use the string value "true" or "false"
** For data, use the string format "YYYY-MM-DD"
** For integer, use the value between double quote "10"
** For selection, use the level id
** For text, use the string value
** For URL, use the URL as string
* For boolean, use the string value "true" or "false"
* For data, use the string format "YYYY-MM-DD"
* For integer, use the value between double quote "10"
* For selection, use the level id
* For text, use the string value
* For URL, use the URL as string
* ``description`` - (Optional) The description for this object.
* ``tenant_group_id`` - (Optional) ID of the group where this object is located.
* ``name`` - (Required) The name for this object.
Expand Down
12 changes: 6 additions & 6 deletions docs/resources/virtualization_vm.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ The following arguments are supported:
* ``cluster_id`` - (Required) ID of the cluster which host this object.
* ``comments`` - (Optional) Comments for this object.
* ``custom_fields`` - (Optional) Custom Field Keys and Values for this object
** For boolean, use the string value "true" or "false"
** For data, use the string format "YYYY-MM-DD"
** For integer, use the value between double quote "10"
** For selection, use the level id
** For text, use the string value
** For URL, use the URL as string
* For boolean, use the string value "true" or "false"
* For data, use the string format "YYYY-MM-DD"
* For integer, use the value between double quote "10"
* For selection, use the level id
* For text, use the string value
* For URL, use the URL as string
* ``disk`` - (Optional) The size in GB of the disk for this object.
* ``local_context_data`` - (Optional) Local context data for this object.
* ``memory`` - (Optional) The size in MB of the memory of this object.
Expand Down
45 changes: 39 additions & 6 deletions netbox/resource_netbox_ipam_ip_addresses.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,24 @@ func resourceNetboxIpamIPAddresses() *schema.Resource {
regexp.MustCompile("^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}/"+
"[0-9]{1,2}$"), "Must be like 192.168.56.1/24"),
},
"custom_fields": {
Type: schema.TypeMap,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
// terraform default behavior sees a difference between null and an empty string
// therefore we override the default, because null in terraform results in empty string in netbox
DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
// function is called for each member of map
// including additional call on the amount of entries
// we ignore the count, because the actual state always returns the amount of existing custom_fields and all are optional in terraform
if k == CustomFieldsRegex {
return true
}
return old == new
},
},
"description": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -116,6 +134,8 @@ func resourceNetboxIpamIPAddressesCreate(d *schema.ResourceData,
client := m.(*netboxclient.NetBoxAPI)

address := d.Get("address").(string)
resourceCustomFields := d.Get("custom_fields").(map[string]interface{})
customFields := convertCustomFieldsFromTerraformToAPICreate(resourceCustomFields)
description := d.Get("description").(string)
dnsName := d.Get("dns_name").(string)
natInsideID := int64(d.Get("nat_inside_id").(int))
Expand All @@ -130,12 +150,13 @@ func resourceNetboxIpamIPAddressesCreate(d *schema.ResourceData,
vrfID := int64(d.Get("vrf_id").(int))

newResource := &models.WritableIPAddress{
Address: &address,
Description: description,
DNSName: dnsName,
Role: role,
Status: status,
Tags: convertTagsToNestedTags(tags),
Address: &address,
CustomFields: &customFields,
Description: description,
DNSName: dnsName,
Role: role,
Status: status,
Tags: convertTagsToNestedTags(tags),
}

if natInsideID != 0 {
Expand Down Expand Up @@ -204,6 +225,12 @@ func resourceNetboxIpamIPAddressesRead(d *schema.ResourceData,
return err
}

customFields := convertCustomFieldsFromAPIToTerraform(resource.CustomFields)

if err = d.Set("custom_fields", customFields); err != nil {
return err
}

var description string
if resource.Description == "" {
description = " "
Expand Down Expand Up @@ -352,6 +379,12 @@ func resourceNetboxIpamIPAddressesUpdate(d *schema.ResourceData,
address := d.Get("address").(string)
params.Address = &address

if d.HasChange("custom_fields") {
stateCustomFields, resourceCustomFields := d.GetChange("custom_fields")
customFields := convertCustomFieldsFromTerraformToAPIUpdate(stateCustomFields, resourceCustomFields)
params.CustomFields = &customFields
}

if d.HasChange("description") {
if description, exist := d.GetOk("description"); exist {
params.Description = description.(string)
Expand Down
2 changes: 1 addition & 1 deletion netbox/resource_netbox_tenancy_tenant.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func resourceNetboxTenancyTenant() *schema.Resource {
// function is called for each member of map
// including additional call on the amount of entries
// we ignore the count, because the actual state always returns the amount of existing custom_fields and all are optional in terraform
if k == "custom_fields.%" {
if k == CustomFieldsRegex {
return true
}
return old == new
Expand Down
6 changes: 3 additions & 3 deletions netbox/resource_netbox_virtualization_vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func resourceNetboxVirtualizationVM() *schema.Resource {
// function is called for each member of map
// including additional call on the amount of entries
// we ignore the count, because the actual state always returns the amount of existing custom_fields and all are optional in terraform
if k == "custom_fields.%" {
if k == CustomFieldsRegex {
return true
}
return old == new
Expand Down Expand Up @@ -118,6 +118,8 @@ func resourceNetboxVirtualizationVMCreate(d *schema.ResourceData,

clusterID := int64(d.Get("cluster_id").(int))
comments := d.Get("comments").(string)
resourceCustomFields := d.Get("custom_fields").(map[string]interface{})
customFields := convertCustomFieldsFromTerraformToAPICreate(resourceCustomFields)
disk := int64(d.Get("disk").(int))
localContextData := d.Get("local_context_data").(string)
memory := int64(d.Get("memory").(int))
Expand All @@ -128,8 +130,6 @@ func resourceNetboxVirtualizationVMCreate(d *schema.ResourceData,
tags := d.Get("tag").(*schema.Set).List()
tenantID := int64(d.Get("tenant_id").(int))
vcpus := int64(d.Get("vcpus").(int))
resourceCustomFields := d.Get("custom_fields").(map[string]interface{})
customFields := convertCustomFieldsFromTerraformToAPICreate(resourceCustomFields)

newResource := &models.WritableVirtualMachineWithConfigContext{
Cluster: &clusterID,
Expand Down
6 changes: 5 additions & 1 deletion netbox/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ type InfosForPrimary struct {
}

const VMInterfaceType string = "virtualization.vminterface"
const CustomFieldsRegex = "custom_fields.%"

func expandToStringSlice(v []interface{}) []string {
s := make([]string, len(v))
Expand Down Expand Up @@ -144,6 +145,7 @@ func updatePrimaryStatus(m interface{}, info InfosForPrimary, id int64) error {
func convertCustomFieldsFromAPIToTerraform(customFields interface{}) map[string]string {
toReturn := make(map[string]string)
switch t := customFields.(type) {

case map[string]interface{}:
for key, value := range t {
var strValue string
Expand All @@ -155,8 +157,8 @@ func convertCustomFieldsFromAPIToTerraform(customFields interface{}) map[string]
strValue = fmt.Sprintf("%v", v["value"])
}
}
toReturn[key] = strValue

toReturn[key] = strValue
}
}

Expand Down Expand Up @@ -188,6 +190,7 @@ func convertCustomFieldsFromTerraformToAPIUpdate(stateCustomFields, resourceCust
for key := range stateCustomFields.(map[string]interface{}) {
toReturn[key] = nil
}

// then we override the values that still exist in the terraform code with their respective value
for key, value := range resourceCustomFields.(map[string]interface{}) {
toReturn[key] = value
Expand All @@ -199,5 +202,6 @@ func convertCustomFieldsFromTerraformToAPIUpdate(stateCustomFields, resourceCust
toReturn[key] = 0
}
}

return toReturn
}

0 comments on commit bb962ee

Please sign in to comment.