diff --git a/docs/data-sources/prefix.md b/docs/data-sources/prefix.md index b0a2041a..b5657d77 100644 --- a/docs/data-sources/prefix.md +++ b/docs/data-sources/prefix.md @@ -10,14 +10,27 @@ description: |- +## Example Usage +```terraform +//Retrieve resource by cidr +resource "netbox_prefix" "cidr" { + cidr = "10.0.0.0/16" +} + +//Retrieve resource by description +resource "netbox_prefix" "description" { + description = "prod-eu-west-1a" +} +``` ## Schema -### Required +### Optional - `cidr` (String) +- `description` (String) ### Read-Only diff --git a/examples/data-sources/netbox_prefix/data-source.tf b/examples/data-sources/netbox_prefix/data-source.tf new file mode 100644 index 00000000..585d9526 --- /dev/null +++ b/examples/data-sources/netbox_prefix/data-source.tf @@ -0,0 +1,9 @@ +//Retrieve resource by cidr +resource "netbox_prefix" "cidr" { + cidr = "10.0.0.0/16" +} + +//Retrieve resource by description +resource "netbox_prefix" "description" { + description = "prod-eu-west-1a" +} \ No newline at end of file diff --git a/netbox/data_source_netbox_prefix.go b/netbox/data_source_netbox_prefix.go index 389a71de..43fbcbad 100644 --- a/netbox/data_source_netbox_prefix.go +++ b/netbox/data_source_netbox_prefix.go @@ -2,10 +2,12 @@ package netbox import ( "errors" + "fmt" "strconv" "github.com/fbreckle/go-netbox/netbox/client" "github.com/fbreckle/go-netbox/netbox/client/ipam" + "github.com/fbreckle/go-netbox/netbox/models" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" ) @@ -20,9 +22,15 @@ func dataSourceNetboxPrefix() *schema.Resource { }, "cidr": { Type: schema.TypeString, - Required: true, + Computed: true, + Optional: true, ValidateFunc: validation.IsCIDR, }, + "description": { + Type: schema.TypeString, + Computed: true, + Optional: true, + }, }, } } @@ -31,7 +39,26 @@ func dataSourceNetboxPrefixRead(d *schema.ResourceData, m interface{}) error { api := m.(*client.NetBoxAPI) cidr := d.Get("cidr").(string) + description := d.Get("description").(string) + + if cidr == "" && description == "" { + return errors.New("Either a prefix or a description should be given.") + } else if cidr == "" && description != "" { + err := dataSourceNetBoxPrefixReadByDesc(api, d, description) + if err != nil { + return err + } + } else if cidr != "" { + err := dataSourceNetBoxPrefixReadByCidr(api, d, cidr) + if err != nil { + return err + } + } + + return nil +} +func dataSourceNetBoxPrefixReadByCidr(api *client.NetBoxAPI, d *schema.ResourceData, cidr string) error { params := ipam.NewIpamPrefixesListParams() params.Prefix = &cidr @@ -49,8 +76,45 @@ func dataSourceNetboxPrefixRead(d *schema.ResourceData, m interface{}) error { if *res.GetPayload().Count == int64(0) { return errors.New("No result") } + result := res.GetPayload().Results[0] d.Set("id", result.ID) + d.Set("description", result.Description) d.SetId(strconv.FormatInt(result.ID, 10)) return nil } + +func dataSourceNetBoxPrefixReadByDesc(api *client.NetBoxAPI, d *schema.ResourceData, description string) error { + params := ipam.NewIpamPrefixesListParams().WithDefaults() + params.Q = &description + + res, err := api.Ipam.IpamPrefixesList(params, nil) + if err != nil { + return err + } + + if *res.GetPayload().Count == int64(0) { + return errors.New(fmt.Sprintf("No result for %s", description)) + } + + var hit *models.Prefix + + for _, result := range res.GetPayload().Results { + if result.Description == description { + if hit != nil { + return errors.New(fmt.Sprintf("Multiple matches found for %s, can't continue.", description)) + } + + hit = result + } + } + + if hit == nil { + return errors.New(fmt.Sprintf("No exact match found for %s", description)) + } + + d.Set("id", hit.ID) + d.Set("cidr", hit.Prefix) + d.SetId(strconv.FormatInt(hit.ID, 10)) + return nil +} diff --git a/netbox/data_source_netbox_prefix_test.go b/netbox/data_source_netbox_prefix_test.go index 7edfd956..75cce3a8 100644 --- a/netbox/data_source_netbox_prefix_test.go +++ b/netbox/data_source_netbox_prefix_test.go @@ -2,6 +2,7 @@ package netbox import ( "fmt" + "regexp" "testing" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" @@ -9,7 +10,7 @@ import ( func TestAccNetboxPrefixDataSource_basic(t *testing.T) { - testPrefix := "10.0.0.0/24" + testPrefix := "3.2.1.0/24" resource.ParallelTest(t, resource.TestCase{ Providers: testAccProviders, Steps: []resource.TestStep{ @@ -32,3 +33,97 @@ data "netbox_prefix" "test" { }, }) } + +func TestAccNetboxPrefixDataSource_description_single(t *testing.T) { + + testPrefix := "1.2.4.0/24" + testSlug := "prefix_description_single" + testDesc := testAccGetTestName(testSlug) + resource.ParallelTest(t, resource.TestCase{ + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: fmt.Sprintf(` +resource "netbox_prefix" "test" { + prefix = "%[1]s" + status = "active" + is_pool = true + description = "%[2]s" +} +data "netbox_prefix" "test" { + depends_on = [netbox_prefix.test] + description = "%[2]s" +}`, testPrefix, testDesc), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrPair("data.netbox_prefix.test", "id", "netbox_prefix.test", "id"), + ), + ExpectNonEmptyPlan: false, + }, + }, + }) +} + +func TestAccNetboxPrefixDataSource_description_multiple_failure(t *testing.T) { + + testPrefix := "1.2.3.0/24" + testPrefix2 := "1.2.64.0/24" + + testSlug := "prefix_description_multiple_failure" + testDesc := testAccGetTestName(testSlug) + resource.ParallelTest(t, resource.TestCase{ + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: fmt.Sprintf(` +resource "netbox_prefix" "test" { + prefix = "%[1]s" + status = "active" + is_pool = true + description = "%[3]s" +} +resource "netbox_prefix" "test2" { + prefix = "%[2]s" + status = "active" + is_pool = true + description = "%[3]s" + } +data "netbox_prefix" "test" { + depends_on = [netbox_prefix.test] + description = "%[3]s" +}`, testPrefix, testPrefix2, testDesc), + ExpectError: regexp.MustCompile(fmt.Sprintf("Multiple matches found for %[1]s, can't continue.", testDesc)), + }, + }, + }) +} + +func TestAccNetboxPrefixDataSource_description_cidr(t *testing.T) { + + testPrefix := "16.32.64.0/24" + testSlug := "prefix_description_cidr" + testDesc := testAccGetTestName(testSlug) + resource.ParallelTest(t, resource.TestCase{ + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: fmt.Sprintf(` +resource "netbox_prefix" "test" { + prefix = "%[1]s" + status = "active" + is_pool = true + description = "%[2]s" +} +data "netbox_prefix" "test" { + depends_on = [netbox_prefix.test] + description = "%[2]s" +}`, testPrefix, testDesc), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrPair("data.netbox_prefix.test", "id", "netbox_prefix.test", "id"), + resource.TestCheckResourceAttrPair("data.netbox_prefix.test", "cidr", "netbox_prefix.test", "prefix"), + resource.TestCheckResourceAttrPair("data.netbox_prefix.test", "description", "netbox_prefix.test", "description"), + ), + ExpectNonEmptyPlan: false, + }, + }, + }) +}