Skip to content

Commit

Permalink
feat(netbox_virtual_disk): add new resource
Browse files Browse the repository at this point in the history
Add support to manage [virtual disks][0], which were added in netbox
3.7.0.

[0]:https://docs.netbox.dev/en/stable/models/virtualization/virtualdisk/
  • Loading branch information
Ikke committed Feb 29, 2024
1 parent 46a0c59 commit 7435e66
Show file tree
Hide file tree
Showing 5 changed files with 364 additions and 0 deletions.
56 changes: 56 additions & 0 deletions docs/resources/virtual_disk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
---
# generated by https://github.com/fbreckle/terraform-plugin-docs
page_title: "netbox_virtual_disk Resource - terraform-provider-netbox"
subcategory: "Virtualization"
description: |-
From the official documentation https://docs.netbox.dev/en/stable/models/virtualization/virtualdisk/:
> A virtual disk is used to model discrete virtual hard disks assigned to virtual machines.
---

# netbox_virtual_disk (Resource)

From the [official documentation](https://docs.netbox.dev/en/stable/models/virtualization/virtualdisk/):

> A virtual disk is used to model discrete virtual hard disks assigned to virtual machines.

## Example Usage

```terraform
// Assumes vmw-cluster-01 exists in Netbox
data "netbox_cluster" "vmw_cluster_01" {
name = "vmw-cluster-01"
}
resource "netbox_virtual_machine" "base_vm" {
cluster_id = data.netbox_cluster.vmw_cluster_01.id
name = "myvm-1"
}
resource "netbox_virtual_disk" "example" {
name = "disk-01"
description = "Main disk"
size = 50
virtual_machine_id = netbox_virtual_machine.base_vm.id
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `name` (String)
- `size` (Number)
- `virtual_machine_id` (Number)

### Optional

- `custom_fields` (Map of String)
- `description` (String)
- `tags` (Set of String)

### Read-Only

- `id` (String) The ID of this resource.


16 changes: 16 additions & 0 deletions examples/resources/netbox_virtual_disk/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Assumes vmw-cluster-01 exists in Netbox
data "netbox_cluster" "vmw_cluster_01" {
name = "vmw-cluster-01"
}

resource "netbox_virtual_machine" "base_vm" {
cluster_id = data.netbox_cluster.vmw_cluster_01.id
name = "myvm-1"
}

resource "netbox_virtual_disk" "example" {
name = "disk-01"
description = "Main disk"
size = 50
virtual_machine_id = netbox_virtual_machine.base_vm.id
}
1 change: 1 addition & 0 deletions netbox/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ func Provider() *schema.Provider {
"netbox_webhook": resourceNetboxWebhook(),
"netbox_custom_field_choice_set": resourceNetboxCustomFieldChoiceSet(),
"netbox_virtual_chassis": resourceNetboxVirtualChassis(),
"netbox_virtual_disk": resourceNetboxVirtualDisks(),
"netbox_event_rule": resourceNetboxEventRule(),
"netbox_vpn_tunnel_group": resourceNetboxVpnTunnelGroup(),
"netbox_vpn_tunnel": resourceNetboxVpnTunnel(),
Expand Down
186 changes: 186 additions & 0 deletions netbox/resource_netbox_virtual_disk.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
package netbox

import (
"context"
"strconv"

"github.com/fbreckle/go-netbox/netbox/client"
"github.com/fbreckle/go-netbox/netbox/client/virtualization"
"github.com/fbreckle/go-netbox/netbox/models"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func resourceNetboxVirtualDisks() *schema.Resource {
return &schema.Resource{
CreateContext: resourceNetboxVirtualDisksCreate,
ReadContext: resourceNetboxVirtualDisksRead,
UpdateContext: resourceNetboxVirtualDisksUpdate,
DeleteContext: resourceNetboxVirtualDisksDelete,
Description: `:meta:subcategory:Virtualization:From the [official documentation](https://docs.netbox.dev/en/stable/models/virtualization/virtualdisk/):
> A virtual disk is used to model discrete virtual hard disks assigned to virtual machines.`,

Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
},
"description": {
Type: schema.TypeString,
Optional: true,
},
"size": {
Type: schema.TypeInt,
Required: true,
},
"virtual_machine_id": {
Type: schema.TypeInt,
Required: true,
},
tagsKey: tagsSchema,
customFieldsKey: customFieldsSchema,
},
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},
}
}

func resourceNetboxVirtualDisksCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
api := m.(*client.NetBoxAPI)

name := d.Get("name").(string)
size := d.Get("size").(int)
virtualMachineID := d.Get("virtual_machine_id").(int)

data := models.WritableVirtualDisk{
Name: &name,
Size: int64ToPtr(int64(size)),
VirtualMachine: int64ToPtr(int64(virtualMachineID)),
}

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

ct, ok := d.GetOk(customFieldsKey)
if ok {
data.CustomFields = ct
}

data.Tags, _ = getNestedTagListFromResourceDataSet(api, d.Get(tagsKey))

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

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

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

return resourceNetboxVirtualDisksRead(ctx, d, m)
}

func resourceNetboxVirtualDisksRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
api := m.(*client.NetBoxAPI)

id, _ := strconv.ParseInt(d.Id(), 10, 64)

params := virtualization.NewVirtualizationVirtualDisksReadParams().WithID(id)

res, err := api.Virtualization.VirtualizationVirtualDisksRead(params, nil)
if err != nil {
if errresp, ok := err.(*virtualization.VirtualizationVirtualDisksReadDefault); ok {
errorcode := errresp.Code()
if errorcode == 404 {
d.SetId("")
return nil
}
}
return diag.FromErr(err)
}

VirtualDisks := res.GetPayload()

d.Set("name", VirtualDisks.Name)
d.Set("description", VirtualDisks.Description)

if VirtualDisks.Size != nil {
d.Set("size", *VirtualDisks.Size)
}
if VirtualDisks.VirtualMachine != nil {
d.Set("virtual_machine_id", VirtualDisks.VirtualMachine.ID)
}

cf := getCustomFields(res.GetPayload().CustomFields)
if cf != nil {
d.Set(customFieldsKey, cf)
}

d.Set(tagsKey, getTagListFromNestedTagList(VirtualDisks.Tags))
return nil
}

func resourceNetboxVirtualDisksUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
api := m.(*client.NetBoxAPI)

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

name := d.Get("name").(string)
size := int64(d.Get("size").(int))
virtualMachineID := int64(d.Get("virtual_machine_id").(int))

data.Name = &name
data.Size = &size
data.VirtualMachine = &virtualMachineID

ct, ok := d.GetOk(customFieldsKey)
if ok {
data.CustomFields = ct
}

data.Tags, _ = getNestedTagListFromResourceDataSet(api, d.Get(tagsKey))

if d.HasChanges("description") {
// check if description is set
if descriptionValue, ok := d.GetOk("description"); ok {
data.Description = descriptionValue.(string)
} else {
data.Description = " "
}
}

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

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

return resourceNetboxVirtualDisksRead(ctx, d, m)
}

func resourceNetboxVirtualDisksDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
api := m.(*client.NetBoxAPI)

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

_, err := api.Virtualization.VirtualizationVirtualDisksDelete(params, nil)
if err != nil {
if errresp, ok := err.(*virtualization.VirtualizationVirtualDisksDeleteDefault); ok {
if errresp.Code() == 404 {
d.SetId("")
return nil
}
}
return diag.FromErr(err)
}

return nil
}
105 changes: 105 additions & 0 deletions netbox/resource_netbox_virtual_disk_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package netbox

import (
"fmt"
"strconv"
"testing"

"github.com/fbreckle/go-netbox/netbox/client"
"github.com/fbreckle/go-netbox/netbox/client/virtualization"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
)

func TestAccNetboxVirtualDisk_basic(t *testing.T) {
testSlug := "virtual_disk"
testName := testAccGetTestName(testSlug)

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckVirtualDiskDestroy,
Steps: []resource.TestStep{
{
Config: fmt.Sprintf(`
resource "netbox_tag" "tag_a" {
name = "[%[1]s_a]"
color_hex = "123456"
}
resource "netbox_site" "test" {
name = "%[1]s"
status = "active"
}
resource "netbox_virtual_machine" "test" {
name = "%[1]s"
site_id = netbox_site.test.id
}
resource "netbox_virtual_disk" "test" {
name = "%[1]s"
description = "description"
size = 30
virtual_machine_id = netbox_virtual_machine.test.id
tags = [netbox_tag.tag_a.name]
}
`, testName),
},
{
Config: fmt.Sprintf(`
resource "netbox_tag" "tag_a" {
name = "[%[1]s_a]"
color_hex = "123456"
}
resource "netbox_site" "test" {
name = "%[1]s"
status = "active"
}
resource "netbox_virtual_machine" "test" {
name = "%[1]s"
site_id = netbox_site.test.id
}
resource "netbox_virtual_disk" "test" {
name = "%[1]s_updated"
description = "description updated"
size = 60
virtual_machine_id = netbox_virtual_machine.test.id
tags = [netbox_tag.tag_a.name]
}
`, testName),
},
{
ResourceName: "netbox_virtual_disk.test",
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func testAccCheckVirtualDiskDestroy(s *terraform.State) error {
conn := testAccProvider.Meta().(*client.NetBoxAPI)

// loop through the resources in state, verifying each virtual machine
// is destroyed
for _, rs := range s.RootModule().Resources {
if rs.Type != "netbox_virtual_disk" {
continue
}

stateID, _ := strconv.ParseInt(rs.Primary.ID, 10, 64)
params := virtualization.NewVirtualizationVirtualDisksReadParams().WithID(stateID)
_, err := conn.Virtualization.VirtualizationVirtualDisksRead(params, nil)

if err == nil {
return fmt.Errorf("virtual disk (%s) still exists", rs.Primary.ID)
}

if errresp, ok := err.(*virtualization.VirtualizationVirtualDisksReadDefault); ok {
errorcode := errresp.Code()
if errorcode == 404 {
return nil
}
}
return err
}
return nil
}

0 comments on commit 7435e66

Please sign in to comment.