Skip to content

Commit

Permalink
Add device role and defaults for virtual machine which were lost on t…
Browse files Browse the repository at this point in the history
…ransfering the code
  • Loading branch information
Felix committed Aug 19, 2020
1 parent 90214b2 commit 9555af2
Show file tree
Hide file tree
Showing 10 changed files with 478 additions and 22 deletions.
2 changes: 1 addition & 1 deletion docker/start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"

docker-compose -f $SCRIPTPATH/docker-compose.yml up -d

echo "### Waiting for Netbox to come available on ${SERVER_URL}"
echo "### Waiting for Netbox to become available on ${SERVER_URL}"

attempt_counter=0
max_attempts=24
Expand Down
62 changes: 60 additions & 2 deletions example/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,64 @@ provider "netbox" {
api_token = " 72830d67beff4ae178b94d8f781842408df8069d"
}

resource "netbox_device_role" "testdevicerole" {
name = "my-device-role"
vm_role = true
color_hex = "ff0000" # beautiful red
}

resource "netbox_platform" "testplatform" {
name = "my-test-platform"
}
name = "my-test-platform"
}

resource "netbox_cluster_type" "testclustertype" {
name = "my-test-cluster-type"
}

resource "netbox_cluster" "testcluster" {
name = "my-test-cluster"
cluster_type_id = netbox_cluster_type.testclustertype.id
}

resource "netbox_tenant" "testtenant" {
name = "my-test-tenant"
}

resource "netbox_virtual_machine" "testvm" {
name = "my-test-vm"
comments = "my-test-comment"
memory_mb = 1024
vcpus = 4
disk_size_gb = 512
cluster_id = netbox_cluster.testcluster.id
tenant_id = netbox_tenant.testtenant.id
platform_id = netbox_platform.testplatform.id
role_id = netbox_device_role.testdevicerole.id
}

resource "netbox_interface" "testinterface" {
virtual_machine_id = netbox_virtual_machine.testvm.id
name = "my-test-interface"
description = "description"
type = "virtual"

tags = ["my:tag", "bar"]
}

resource "netbox_ip_address" "testip" {
ip_address = "1.2.3.4/32"
interface_id = netbox_interface.testinterface.id
status = "active"
}

resource "netbox_primary_ip" "testprimaryip" {
virtual_machine_id = netbox_virtual_machine.testvm.id
ip_address_id = netbox_ip_address.testip.id
}

resource "netbox_service" "testservice" {
name = "my-test-service"
virtual_machine_id = netbox_virtual_machine.testvm.id
protocol = "tcp"
port = 80
}
57 changes: 57 additions & 0 deletions netbox/data_source_netbox_device_role.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package netbox

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

func dataSourceNetboxDeviceRole() *schema.Resource {
return &schema.Resource{
Read: dataSourceNetboxDeviceRoleRead,
Schema: map[string]*schema.Schema{
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"slug": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
"color_hex": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
},
}
}

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

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

res, err := api.Dcim.DcimDeviceRolesList(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.SetId(strconv.FormatInt(result.ID, 10))
d.Set("name", result.Name)
d.Set("slug", result.Slug)
d.Set("color_hex", result.Color)
return nil
}
33 changes: 33 additions & 0 deletions netbox/data_source_netbox_device_role_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package netbox

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

func TestAccNetboxDeviceRoleDataSource_basic(t *testing.T) {

testSlug := "dvrl_ds_basic"
testName := testAccGetTestName(testSlug)
resource.ParallelTest(t, resource.TestCase{
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: fmt.Sprintf(`
resource "netbox_device_role" "test" {
name = "%[1]s"
color_hex = "123456"
}
data "netbox_device_role" "test" {
depends_on = [netbox_device_role.test]
name = "%[1]s"
}`, testName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrPair("data.netbox_device_role.test", "id", "netbox_device_role.test", "id"),
),
ExpectNonEmptyPlan: true,
},
},
})
}
8 changes: 5 additions & 3 deletions netbox/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ func Provider() *schema.Provider {
"netbox_service": resourceNetboxService(),
"netbox_platform": resourceNetboxPlatform(),
"netbox_primary_ip": resourceNetboxPrimaryIP(),
"netbox_device_role": resourceNetboxDeviceRole(),
},
DataSourcesMap: map[string]*schema.Resource{
"netbox_cluster": dataSourceNetboxCluster(),
"netbox_tenant": dataSourceNetboxTenant(),
"netbox_platform": dataSourceNetboxPlatform(),
"netbox_cluster": dataSourceNetboxCluster(),
"netbox_tenant": dataSourceNetboxTenant(),
"netbox_platform": dataSourceNetboxPlatform(),
"netbox_device_role": dataSourceNetboxDeviceRole(),
},
Schema: map[string]*schema.Schema{
"server_url": {
Expand Down
153 changes: 153 additions & 0 deletions netbox/resource_netbox_device_role.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
package netbox

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

func resourceNetboxDeviceRole() *schema.Resource {
return &schema.Resource{
Create: resourceNetboxDeviceRoleCreate,
Read: resourceNetboxDeviceRoleRead,
Update: resourceNetboxDeviceRoleUpdate,
Delete: resourceNetboxDeviceRoleDelete,

Schema: map[string]*schema.Schema{
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"slug": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"vm_role": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Default: true,
},
"color_hex": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
},
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
}
}

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

name := d.Get("name").(string)
slugValue, slugOk := d.GetOk("slug")
var slug string

// Default slug to name if not given
if !slugOk {
slug = name
} else {
slug = slugValue.(string)
}

color := d.Get("color_hex").(string)
vmRole := d.Get("vm_role").(bool)

params := dcim.NewDcimDeviceRolesCreateParams().WithData(
&models.DeviceRole{
Name: &name,
Slug: &slug,
Color: color,
VMRole: vmRole,
},
)

res, err := api.Dcim.DcimDeviceRolesCreate(params, nil)
if err != nil {
//return errors.New(getTextFromError(err))
return err
}

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

return resourceNetboxDeviceRoleRead(d, m)
}

func resourceNetboxDeviceRoleRead(d *schema.ResourceData, m interface{}) error {
api := m.(*client.NetBox)
id, _ := strconv.ParseInt(d.Id(), 10, 64)
params := dcim.NewDcimDeviceRolesReadParams().WithID(id)

res, err := api.Dcim.DcimDeviceRolesRead(params, nil)
if err != nil {
if apiError, ok := err.(*runtime.APIError); ok {
errorcode := 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("vm_role", res.GetPayload().VMRole)
d.Set("color_hex", res.GetPayload().Color)
return nil
}

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

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

name := d.Get("name").(string)
color := d.Get("color_hex").(string)
vmRole := d.Get("vm_role").(bool)

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
data.Name = &name
data.VMRole = vmRole
data.Color = color

params := dcim.NewDcimDeviceRolesPartialUpdateParams().WithID(id).WithData(&data)

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

return resourceNetboxDeviceRoleRead(d, m)
}

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

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

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

0 comments on commit 9555af2

Please sign in to comment.