Skip to content

Commit

Permalink
Merge pull request #25 from e-breuninger/feature/cluster_groups
Browse files Browse the repository at this point in the history
Add cluster group resource

Closes #10
  • Loading branch information
fbreckle authored Dec 24, 2020
2 parents 1f4c594 + 57c9072 commit 84a226a
Show file tree
Hide file tree
Showing 9 changed files with 376 additions and 9 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@ FEATURES

* **New Resource:** `netbox_vrf` ([#26](https://github.com/e-breuninger/terraform-provider-netbox/pull/26) by [@rthomson](https://github.com/rthomson))
* **New Data Source:** `netbox_vrf` ([#26](https://github.com/e-breuninger/terraform-provider-netbox/pull/26) by [@rthomson](https://github.com/rthomson))
* **New Resource:** `netbox_cluster_group`
* **New Data Source:** `netbox_cluster_group`

ENHANCEMENTS

* resource/netbox_ip_address: Add `tenant_id` attribute
* resource/netbox_cluster: Add `cluster_group_id` attribute

## 0.0.9 (November 20, 2020)

Expand Down
6 changes: 6 additions & 0 deletions example/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,19 @@ resource "netbox_cluster_type" "testclustertype" {
name = "my-test-cluster-type"
}

resource "netbox_cluster_group" "testclustergroup" {
name = "my-test-cluster-group"
description = "test cluster group description"
}

resource "netbox_vrf" "testvrf" {
name = "my-test-vrf"
}

resource "netbox_cluster" "testcluster" {
name = "my-test-cluster"
cluster_type_id = netbox_cluster_type.testclustertype.id
cluster_group_id = netbox_cluster_group.testclustergroup.id
# tags can be referenced by name but have to be created first ..
tags = ["foo"]
# .. or explicitly depended upon, unless created separately
Expand Down
52 changes: 52 additions & 0 deletions netbox/data_source_netbox_cluster_group.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package netbox

import (
"errors"
"github.com/fbreckle/go-netbox/netbox/client"
"github.com/fbreckle/go-netbox/netbox/client/virtualization"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"strconv"
)

func dataSourceNetboxClusterGroup() *schema.Resource {
return &schema.Resource{
Read: dataSourceNetboxClusterGroupRead,
Schema: map[string]*schema.Schema{
"cluster_group_id": &schema.Schema{
Type: schema.TypeInt,
Computed: true,
},
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
},
}
}

func dataSourceNetboxClusterGroupRead(d *schema.ResourceData, m interface{}) error {
api := m.(*client.NetBoxAPI)

name := d.Get("name").(string)
params := virtualization.NewVirtualizationClusterGroupsListParams()
params.Name = &name
limit := int64(2) // Limit of 2 is enough
params.Limit = &limit

res, err := api.Virtualization.VirtualizationClusterGroupsList(params, nil)
if err != nil {
return err
}

if *res.GetPayload().Count > int64(1) {
return errors.New("More than one result. Specify a more narrow filter")
}
if *res.GetPayload().Count == int64(0) {
return errors.New("No result")
}
result := res.GetPayload().Results[0]
d.Set("cluster_group_id", result.ID)
d.SetId(strconv.FormatInt(result.ID, 10))
d.Set("name", result.Name)
return nil
}
34 changes: 34 additions & 0 deletions netbox/data_source_netbox_cluster_group_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package netbox

import (
"fmt"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"testing"
)

func TestAccNetboxClusterGroupDataSource_basic(t *testing.T) {

testSlug := "clstrgrp_ds_basic"
testName := testAccGetTestName(testSlug)
resource.ParallelTest(t, resource.TestCase{
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: fmt.Sprintf(`
resource "netbox_cluster_group" "test" {
name = "%[1]s"
}
data "netbox_cluster_group" "test" {
depends_on = [netbox_cluster_group.test]
name = "%[1]s"
}`, testName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrPair("data.netbox_cluster_group.test", "cluster_group_id", "netbox_cluster_group.test", "id"),
resource.TestCheckResourceAttrPair("data.netbox_cluster_group.test", "id", "netbox_cluster_group.test", "id"),
),
ExpectNonEmptyPlan: true,
},
},
})
}
2 changes: 2 additions & 0 deletions netbox/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ func Provider() *schema.Provider {
"netbox_primary_ip": resourceNetboxPrimaryIP(),
"netbox_device_role": resourceNetboxDeviceRole(),
"netbox_tag": resourceNetboxTag(),
"netbox_cluster_group": resourceNetboxClusterGroup(),
},
DataSourcesMap: map[string]*schema.Resource{
"netbox_cluster": dataSourceNetboxCluster(),
"netbox_cluster_group": dataSourceNetboxClusterGroup(),
"netbox_tenant": dataSourceNetboxTenant(),
"netbox_vrf": dataSourceNetboxVrf(),
"netbox_platform": dataSourceNetboxPlatform(),
Expand Down
38 changes: 29 additions & 9 deletions netbox/resource_netbox_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ func resourceNetboxCluster() *schema.Resource {
Type: schema.TypeInt,
Required: true,
},
"cluster_group_id": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
},
"tags": &schema.Schema{
Type: schema.TypeSet,
Elem: &schema.Schema{
Expand All @@ -44,17 +48,23 @@ func resourceNetboxCluster() *schema.Resource {
func resourceNetboxClusterCreate(d *schema.ResourceData, m interface{}) error {
api := m.(*client.NetBoxAPI)

data := models.WritableCluster{}

name := d.Get("name").(string)
data.Name = &name

clusterTypeID := int64(d.Get("cluster_type_id").(int))
data.Type = &clusterTypeID

if clusterGroupIDValue, ok := d.GetOk("cluster_group_id"); ok {
clusterGroupID := int64(clusterGroupIDValue.(int))
data.Group = &clusterGroupID
}

tags, _ := getNestedTagListFromResourceDataSet(api, d.Get("tags"))
data.Tags = tags

params := virtualization.NewVirtualizationClustersCreateParams().WithData(
&models.WritableCluster{
Name: &name,
Type: &clusterTypeID,
Tags: tags,
},
)
params := virtualization.NewVirtualizationClustersCreateParams().WithData(&data)

res, err := api.Virtualization.VirtualizationClustersCreate(params, nil)
if err != nil {
Expand Down Expand Up @@ -88,6 +98,11 @@ func resourceNetboxClusterRead(d *schema.ResourceData, m interface{}) error {

d.Set("name", res.GetPayload().Name)
d.Set("cluster_type_id", res.GetPayload().Type.ID)
if res.GetPayload().Group != nil {
d.Set("cluster_group_id", res.GetPayload().Group.ID)
} else {
d.Set("cluster_group_id", nil)
}
d.Set("tags", getTagListFromNestedTagList(res.GetPayload().Tags))
return nil
}
Expand All @@ -99,11 +114,16 @@ func resourceNetboxClusterUpdate(d *schema.ResourceData, m interface{}) error {
data := models.WritableCluster{}

name := d.Get("name").(string)
clusterTypeID := int64(d.Get("cluster_type_id").(int))

data.Name = &name

clusterTypeID := int64(d.Get("cluster_type_id").(int))
data.Type = &clusterTypeID

if clusterGroupIDValue, ok := d.GetOk("cluster_group_id"); ok {
clusterGroupID := int64(clusterGroupIDValue.(int))
data.Group = &clusterGroupID
}

params := virtualization.NewVirtualizationClustersPartialUpdateParams().WithID(id).WithData(&data)

_, err := api.Virtualization.VirtualizationClustersPartialUpdate(params, nil)
Expand Down
147 changes: 147 additions & 0 deletions netbox/resource_netbox_cluster_group.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
package netbox

import (
"github.com/fbreckle/go-netbox/netbox/client"
"github.com/fbreckle/go-netbox/netbox/client/virtualization"
"github.com/fbreckle/go-netbox/netbox/models"
"github.com/go-openapi/runtime"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"strconv"
)

func resourceNetboxClusterGroup() *schema.Resource {
return &schema.Resource{
Create: resourceNetboxClusterGroupCreate,
Read: resourceNetboxClusterGroupRead,
Update: resourceNetboxClusterGroupUpdate,
Delete: resourceNetboxClusterGroupDelete,

Schema: map[string]*schema.Schema{
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"slug": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
ValidateFunc: validation.StringLenBetween(0, 30),
},
"description": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
},
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
}
}

func resourceNetboxClusterGroupCreate(d *schema.ResourceData, m interface{}) error {
api := m.(*client.NetBoxAPI)

data := models.ClusterGroup{}

name := d.Get("name").(string)
data.Name = &name

slugValue, slugOk := d.GetOk("slug")
var slug string
// Default slug to name attribute if not given
if !slugOk {
slug = name
} else {
slug = slugValue.(string)
}
data.Slug = &slug

if description, ok := d.GetOk("description"); ok {
data.Description = description.(string)
}

params := virtualization.NewVirtualizationClusterGroupsCreateParams().WithData(&data)

res, err := api.Virtualization.VirtualizationClusterGroupsCreate(params, nil)
if err != nil {
return err
}

d.SetId(strconv.FormatInt(res.GetPayload().ID, 10))

return resourceNetboxClusterGroupRead(d, m)
}

func resourceNetboxClusterGroupRead(d *schema.ResourceData, m interface{}) error {
api := m.(*client.NetBoxAPI)
id, _ := strconv.ParseInt(d.Id(), 10, 64)
params := virtualization.NewVirtualizationClusterGroupsReadParams().WithID(id)

res, err := api.Virtualization.VirtualizationClusterGroupsRead(params, nil)
if err != nil {
errorcode := err.(*runtime.APIError).Response.(runtime.ClientResponse).Code()
if errorcode == 404 {
// If the ID is updated to blank, this tells Terraform the resource no longer exists (maybe it was destroyed out of band). Just like the destroy callback, the Read function should gracefully handle this case. https://www.terraform.io/docs/extend/writing-custom-providers.html
d.SetId("")
return nil
}
return err
}

d.Set("name", res.GetPayload().Name)
d.Set("slug", res.GetPayload().Slug)
d.Set("description", res.GetPayload().Description)
return nil
}

func resourceNetboxClusterGroupUpdate(d *schema.ResourceData, m interface{}) error {
api := m.(*client.NetBoxAPI)

id, _ := strconv.ParseInt(d.Id(), 10, 64)
data := models.ClusterGroup{}

name := d.Get("name").(string)
data.Name = &name

slugValue, slugOk := d.GetOk("slug")
var slug string
// Default slug to name if not given
if !slugOk {
slug = name
} else {
slug = slugValue.(string)
}
data.Slug = &slug

if d.HasChange("description") {
// description omits empty values so set to ' '
if description := d.Get("description"); description.(string) == "" {
data.Description = " "
} else {
data.Description = description.(string)
}
}

params := virtualization.NewVirtualizationClusterGroupsPartialUpdateParams().WithID(id).WithData(&data)

_, err := api.Virtualization.VirtualizationClusterGroupsPartialUpdate(params, nil)
if err != nil {
return err
}

return resourceNetboxClusterGroupRead(d, m)
}

func resourceNetboxClusterGroupDelete(d *schema.ResourceData, m interface{}) error {
api := m.(*client.NetBoxAPI)

id, _ := strconv.ParseInt(d.Id(), 10, 64)
params := virtualization.NewVirtualizationClusterGroupsDeleteParams().WithID(id)

_, err := api.Virtualization.VirtualizationClusterGroupsDelete(params, nil)
if err != nil {
return err
}
return nil
}
Loading

0 comments on commit 84a226a

Please sign in to comment.