Skip to content

Commit

Permalink
Add device datasource
Browse files Browse the repository at this point in the history
  • Loading branch information
skatsaounis committed Nov 24, 2023
1 parent 9dcc53a commit 701a57e
Show file tree
Hide file tree
Showing 12 changed files with 751 additions and 3 deletions.
62 changes: 62 additions & 0 deletions docs/data-sources/device.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "maas_device Data Source - terraform-provider-maas"
subcategory: ""
description: |-
Provides details about an existing MAAS device.
---

# maas_device (Data Source)

Provides details about an existing MAAS device.

## Example Usage

```terraform
resource "maas_dns_domain" "test_domain" {
name = "domain"
ttl = 3600
authoritative = true
}
resource "maas_device" "test_device" {
description = "Test description"
domain = "maas"
hostname = "test-device"
zone = "default"
network_interfaces {
mac_address = "12:23:45:67:89:de"
}
}
data "maas_device" "test_device" {
hostname = maas_device.test_device.hostname
}
```

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

### Required

- `hostname` (String) The device hostname.

### Read-Only

- `description` (String) The description of the device.
- `domain` (String) The domain of the device.
- `fqdn` (String) The device FQDN.
- `id` (String) The ID of this resource.
- `ip_addresses` (Set of String) A set of IP addressed assigned to the device.
- `network_interfaces` (Set of Object) A set of network interfaces attached to the device. (see [below for nested schema](#nestedatt--network_interfaces))
- `owner` (String) The owner of the device.
- `zone` (String) The zone of the device.

<a id="nestedatt--network_interfaces"></a>
### Nested Schema for `network_interfaces`

Read-Only:

- `id` (Number)
- `mac_address` (String)
- `name` (String)
73 changes: 73 additions & 0 deletions docs/resources/device.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "maas_device Resource - terraform-provider-maas"
subcategory: ""
description: |-
Provides a resource to manage MAAS devices.
---

# maas_device (Resource)

Provides a resource to manage MAAS devices.

## Example Usage

```terraform
resource "maas_dns_domain" "test_domain" {
name = "domain"
ttl = 3600
authoritative = true
}
resource "maas_device" "test_device" {
description = "Test description"
domain = maas_dns_domain.test_domain.name
hostname = "test-device"
zone = "default"
network_interfaces {
mac_address = "12:23:45:67:89:de"
}
}
```

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

### Required

- `network_interfaces` (Block Set, Min: 1) A set of network interfaces attached to the device. (see [below for nested schema](#nestedblock--network_interfaces))

### Optional

- `description` (String) The description of the device.
- `domain` (String) The domain of the device.
- `hostname` (String) The device hostname.
- `zone` (String) The zone of the device.

### Read-Only

- `fqdn` (String) The device FQDN.
- `id` (String) The ID of this resource.
- `ip_addresses` (Set of String) A set of IP addressed assigned to the device.
- `owner` (String) The owner of the device.

<a id="nestedblock--network_interfaces"></a>
### Nested Schema for `network_interfaces`

Required:

- `mac_address` (String) MAC address of the network interface.

Read-Only:

- `id` (Number) The id of the network interface.
- `name` (String) The name of the network interface.

## Import

Import is supported using the following syntax:

```shell
# Devices can be imported using their ID or hostname. e.g.
$ terraform import maas_device.test_device test-device
```
19 changes: 19 additions & 0 deletions examples/data-sources/maas_device/data-source.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
resource "maas_dns_domain" "test_domain" {
name = "domain"
ttl = 3600
authoritative = true
}

resource "maas_device" "test_device" {
description = "Test description"
domain = "maas"
hostname = "test-device"
zone = "default"
network_interfaces {
mac_address = "12:23:45:67:89:de"
}
}

data "maas_device" "test_device" {
hostname = maas_device.test_device.hostname
}
2 changes: 2 additions & 0 deletions examples/resources/maas_device/import.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Devices can be imported using their ID or hostname. e.g.
$ terraform import maas_device.test_device test-device
15 changes: 15 additions & 0 deletions examples/resources/maas_device/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
resource "maas_dns_domain" "test_domain" {
name = "domain"
ttl = 3600
authoritative = true
}

resource "maas_device" "test_device" {
description = "Test description"
domain = maas_dns_domain.test_domain.name
hostname = "test-device"
zone = "default"
network_interfaces {
mac_address = "12:23:45:67:89:de"
}
}
147 changes: 147 additions & 0 deletions maas/data_source_maas_device.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
package maas

import (
"context"
"fmt"

"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/maas/gomaasclient/client"
"github.com/maas/gomaasclient/entity"
)

func dataSourceMaasDevice() *schema.Resource {
return &schema.Resource{
Description: "Provides details about an existing MAAS device.",
ReadContext: dataSourceDeviceRead,

Schema: map[string]*schema.Schema{
"description": {
Type: schema.TypeString,
Computed: true,
Description: "The description of the device.",
},
"domain": {
Type: schema.TypeString,
Computed: true,
Description: "The domain of the device.",
},
"fqdn": {
Type: schema.TypeString,
Computed: true,
Description: "The device FQDN.",
},
"hostname": {
Type: schema.TypeString,
Required: true,
Description: "The device hostname.",
},
"ip_addresses": {
Type: schema.TypeSet,
Computed: true,
Description: "A set of IP addressed assigned to the device.",
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"network_interfaces": {
Type: schema.TypeSet,
Computed: true,
Description: "A set of network interfaces attached to the device.",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"id": {
Type: schema.TypeInt,
Computed: true,
Description: "The id of the network interface.",
},
"mac_address": {
Type: schema.TypeString,
Computed: true,
Description: "MAC address of the network interface.",
},
"name": {
Type: schema.TypeString,
Computed: true,
Description: "The name of the network interface.",
},
},
},
},
"owner": {
Type: schema.TypeString,
Computed: true,
Description: "The owner of the device.",
},
"zone": {
Type: schema.TypeString,
Computed: true,
Description: "The zone of the device.",
},
},
}
}

func dataSourceDeviceRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*client.Client)

device, err := getDevice(client, d.Get("hostname").(string))
if err != nil {
return diag.FromErr(err)
}

d.SetId(device.SystemID)

d.Set("description", device.Description)
d.Set("domain", device.Domain.Name)
d.Set("fqdn", device.FQDN)
d.Set("hostname", device.Hostname)
d.Set("owner", device.Owner)
d.Set("zone", device.Zone.Name)

ipAddresses := make([]string, len(device.IPAddresses))
for i, ip := range device.IPAddresses {
ipAddresses[i] = ip.String()
}
if err := d.Set("ip_addresses", ipAddresses); err != nil {
return diag.FromErr(err)
}

networkInterfaces := make([]map[string]interface{}, len(device.InterfaceSet))
for i, networkInterface := range device.InterfaceSet {
networkInterfaces[i] = map[string]interface{}{
"id": networkInterface.ID,
"mac_address": networkInterface.MACAddress,
"name": networkInterface.Name,
}
}
if err := d.Set("network_interfaces", networkInterfaces); err != nil {
return diag.FromErr(err)
}

return nil
}

func getDevice(client *client.Client, identifier string) (*entity.Device, error) {
device, err := findDevice(client, identifier)
if err != nil {
return nil, err
}
if device == nil {
return nil, fmt.Errorf("device (%s) was not found", identifier)
}
return device, nil
}

func findDevice(client *client.Client, identifier string) (*entity.Device, error) {
devices, err := client.Devices.Get()
if err != nil {
return nil, err
}
for _, d := range devices {
if d.SystemID == identifier || d.Hostname == identifier {
return &d, nil
}
}
return nil, nil
}
58 changes: 58 additions & 0 deletions maas/data_source_maas_device_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package maas_test

import (
"fmt"
"terraform-provider-maas/maas/testutils"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/maas/gomaasclient/entity"
)

func TestAccDataSourceMaasDevice_basic(t *testing.T) {

var device entity.Device
description := "Test description"
domain := "test-data-domain"
hostname := "test-data-device"
zone := "default"
mac_address := "12:23:45:67:89:fa"

checks := []resource.TestCheckFunc{
testAccMaasDeviceCheckExists("maas_device.test", &device),
resource.TestCheckResourceAttr("maas_device.test", "description", description),
resource.TestCheckResourceAttr("maas_device.test", "domain", domain),
resource.TestCheckResourceAttr("maas_device.test", "fqdn", fmt.Sprintf("%s.%s", hostname, domain)),
resource.TestCheckResourceAttr("maas_device.test", "hostname", hostname),
resource.TestCheckResourceAttr("maas_device.test", "zone", zone),
resource.TestCheckResourceAttr("maas_device.test", "ip_addresses.#", "0"),
resource.TestCheckResourceAttr("maas_device.test", "network_interfaces.#", "1"),
resource.TestCheckResourceAttrSet("maas_device.test", "network_interfaces.0.id"),
resource.TestCheckResourceAttr("maas_device.test", "network_interfaces.0.mac_address", mac_address),
resource.TestCheckResourceAttr("maas_device.test", "network_interfaces.0.name", "eth0"),
resource.TestCheckResourceAttrSet("maas_device.test", "owner"),
}

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testutils.PreCheck(t) },
Providers: testutils.TestAccProviders,
CheckDestroy: testAccCheckMaasDeviceDestroy,
ErrorCheck: func(err error) error { return err },
Steps: []resource.TestStep{
{
Config: testAccDataSourceMaasDevice(description, domain, hostname, zone, mac_address),
Check: resource.ComposeTestCheckFunc(checks...),
},
},
})
}

func testAccDataSourceMaasDevice(description string, domain string, hostname string, zone string, mac_address string) string {
return fmt.Sprintf(`
%s
data "maas_device" "test" {
hostname = maas_device.test.hostname
}
`, testAccMaasDevice(description, domain, hostname, zone, mac_address))
}
2 changes: 2 additions & 0 deletions maas/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ func Provider() *schema.Provider {
},
},
ResourcesMap: map[string]*schema.Resource{
"maas_device": resourceMaasDevice(),
"maas_instance": resourceMaasInstance(),
"maas_vm_host": resourceMaasVMHost(),
"maas_vm_host_machine": resourceMaasVMHostMachine(),
Expand All @@ -67,6 +68,7 @@ func Provider() *schema.Provider {
"maas_subnet": dataSourceMaasSubnet(),
"maas_machine": dataSourceMaasMachine(),
"maas_network_interface_physical": dataSourceMaasNetworkInterfacePhysical(),
"maas_device": dataSourceMaasDevice(),
},
ConfigureContextFunc: providerConfigure,
}
Expand Down
Loading

0 comments on commit 701a57e

Please sign in to comment.