Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support to create Alias Records and Changing the State of a Pre-existing #16

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions docs/data-sources/alias_record.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "bluecat_alias_record Data Source - terraform-provider-bluecat"
subcategory: ""
description: |-
Data source to access the attributes of a alias record. If the API returns more than one alias record that matches, an error will be returned.
---

# bluecat_alias_record (Data Source)

Data source to access the attributes of a alias record. If the API returns more than one alias record that matches, an error will be returned.

## Example Usage

```terraform
data "bluecat_host_record" "host" {
absolute_name = "alias.example.com"
}

output "bluecat_host_addresses" {
value = data.bluecat_host_record.host.linked_record_name
}
```

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

### Required

- **absolute_name** (String) The absolute name/fqdn of the alias record.

### Optional

- **id** (String) The ID of this resource.
- **result_count** (Number) The number of results the API should return. This must be between 1 and 10. You most likely want to leave this alone. Defaults to `10`.
- **start** (Number) The start index of the search results the API should return. You most likely want to leave this alone. Defaults to `0`.

### Read-Only

- **custom_properties** (Map of String) A map of all custom properties associated with the alias record.
- **linked_record_name** (String) The record to which this alias should point.
- **name** (String) The short name of the alias record.
- **parent_id** (String) The ID of the parent of the alias record.
- **parent_type** (String) The type of the parent of the alias record.
- **properties** (String) The properties of the alias record as returned by the API (pipe delimited).
- **ttl** (Number) The TTL of the alias record.
- **type** (String) The type of the resource.


50 changes: 50 additions & 0 deletions docs/resources/alias_record.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "bluecat_alias_record Resource - terraform-provider-bluecat"
subcategory: ""
description: |-
Resource create an alias record.
---

# bluecat_alias_record (Resource)

Resource create a alias record.

## Example Usage

```terraform
resource "bluecat_alias_record" "alias" {
view_id = data.bluecat_entity.view.id
name = "alias"
dns_zone = "example.com"
linked_record_name = "hostname.example.com"
}

output "bluecat_alias_fqdn" {
value = bluecat_alias_record.alias.absolute_name
}
```

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

### Required

- **dns_zone** (String) The DNS zone to create the alias record in. Combined with `name` to make the fqdn. If changed, forces a new resource.
- **linked_record_name** (String) The record to which this alias should point.
- **name** (String) The name of the alias record to be created. Combined with `dns_zone` to make the fqdn.
- **view_id** (String) The object ID of the View that alias record should be created in. If changed, forces a new resource.

### Optional

- **custom_properties** (Map of String) A map of all custom properties associated with the alias record.
- **id** (String) The ID of this resource.
- **ttl** (Number) The TTL for the alias record. When set to -1, ignores the TTL. Defaults to `-1`.

### Read-Only

- **absolute_name** (String) The absolute name (fqdn) of the alias record.
- **properties** (String) The properties of the alias record as returned by the API (pipe delimited).
- **type** (String) The type of the resource.


44 changes: 44 additions & 0 deletions docs/resources/ip4_change_state.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "bluecat_ip4_change_state Resource - terraform-provider-bluecat"
subcategory: ""
description: |-
Resource change the state of a IP4 resource that was created outside of the context of this provider (i.e. a DHCP Reservation).
---

# bluecat_ip4_change_state (Resource)

Resource change the state of a IP4 resource that was created outside of the context of this provider (i.e. a DHCP Reservation).

## Example Usage

```terraform
resource "bluecat_ip4_change_state" "ip4_action" {
address_id = data.bluecat_ip4_address.addr.id
action = "MAKE_DHCP_RESERVED"
mac_address = data.bluecat_ip4_address.addr.mac_address
}

output "ip4_final_state" {
value = bluecat_ip4_change_state.ip4_action.state
}
```

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

### Required

- **action** (String) The action to take on the provided IPv4 address. Must be one of: "MAKE_STATIC", "MAKE_RESERVED", or "MAKE_DHCP_RESERVED". If changed, forces a new resource.
- **address_id** (String) The object ID of the Address that will have its state changed. If changed, forces a new resource.

### Optional

- **id** (String) The ID of this resource.
- **mac_address** (String) The MAC address to associate with the IPv4 address. Defaults to ``.

### Read-Only

- **state** (String) The state of the IPv4 address.


7 changes: 7 additions & 0 deletions examples/data-sources/bluecat_alias_record/data-source.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
data "bluecat_host_record" "host" {
absolute_name = "alias.example.com"
}

output "bluecat_host_addresses" {
value = data.bluecat_host_record.host.linked_record_name
}
10 changes: 10 additions & 0 deletions examples/resources/bluecat_alias_record/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
resource "bluecat_alias_record" "alias" {
view_id = data.bluecat_entity.view.id
name = "alias"
dns_zone = "example.com"
linked_record_name = "hostname.example.com"
}

output "bluecat_alias_fqdn" {
value = bluecat_alias_record.alias.absolute_name
}
9 changes: 9 additions & 0 deletions examples/resources/bluecat_ip4_change_state/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
resource "bluecat_ip4_change_state" "ip4_action" {
address_id = data.bluecat_ip4_address.addr.id
action = "MAKE_DHCP_RESERVED"
mac_address = data.bluecat_ip4_address.addr.mac_address
}

output "ip4_final_state" {
value = bluecat_ip4_change_state.ip4_action.state
}
202 changes: 202 additions & 0 deletions internal/provider/data_source_alias_record.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
package provider

import (
"context"
"fmt"
"log"
"strconv"
"strings"

"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/umich-vci/gobam"
)

func dataSourceAliasRecord() *schema.Resource {
return &schema.Resource{
Description: "Data source to access the attributes of a alias record. If the API returns more than one alias record that matches, an error will be returned.",

ReadContext: dataSourceAliasRecordRead,

Schema: map[string]*schema.Schema{
"absolute_name": {
Description: "The absolute name/fqdn of the alias record.",
Type: schema.TypeString,
Required: true,
},
"result_count": {
Description: "The number of results the API should return. This must be between 1 and 10. You most likely want to leave this alone.",
Type: schema.TypeInt,
Optional: true,
Default: 10,
},
"start": {
Description: "The start index of the search results the API should return. You most likely want to leave this alone.",
Type: schema.TypeInt,
Optional: true,
Default: 0,
},
"custom_properties": {
Description: "A map of all custom properties associated with the alias record.",
Type: schema.TypeMap,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"name": {
Description: "The short name of the alias record.",
Type: schema.TypeString,
Computed: true,
},
"linked_record_name": {
Description: "The record to which this alias should point.",
Type: schema.TypeString,
Computed: true,
},
"parent_id": {
Description: "The ID of the parent of the alias record.",
Type: schema.TypeString,
Computed: true,
},
"parent_type": {
Description: "The type of the parent of the alias record.",
Type: schema.TypeString,
Computed: true,
},
"properties": {
Description: "The properties of the alias record as returned by the API (pipe delimited).",
Type: schema.TypeString,
Computed: true,
},
"ttl": {
Description: "The TTL of the alias record.",
Type: schema.TypeInt,
Computed: true,
},
"type": {
Description: "The type of the resource.",
Type: schema.TypeString,
Computed: true,
},
},
}
}

func dataSourceAliasRecordRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
mutex.Lock()
client := meta.(*apiClient).Client
client.Login(meta.(*apiClient).Username, meta.(*apiClient).Password)

start := d.Get("start").(int)
count := d.Get("result_count").(int)
absoluteName := d.Get("absolute_name").(string)
options := "hint=^" + absoluteName + "$|"

resp, err := client.GetAliasesByHint(start, count, options)
if err = gobam.LogoutClientIfError(client, err, "Failed to get Host Records by hint"); err != nil {
mutex.Unlock()
return diag.FromErr(err)
}

log.Printf("[INFO] GetAliasesByHint returned %s results", strconv.Itoa(len(resp.Item)))

matches := 0
matchLocation := -1
for x := range resp.Item {
properties := *resp.Item[x].Properties
props := strings.Split(properties, "|")
for y := range props {
if len(props[y]) > 0 {
prop := strings.Split(props[y], "=")[0]
val := strings.Split(props[y], "=")[1]
if prop == "absoluteName" && val == absoluteName {
matches++
matchLocation = x
}
}
}
}

if matches == 0 || matches > 1 {
err := fmt.Errorf("no exact alias record match found for: %s", absoluteName)
if err = gobam.LogoutClientIfError(client, err, "No exact alias record match found for hint"); err != nil {
mutex.Unlock()
return diag.FromErr(err)
}
}

d.SetId(strconv.FormatInt(*resp.Item[matchLocation].Id, 10))
d.Set("name", resp.Item[matchLocation].Name)
d.Set("properties", resp.Item[matchLocation].Properties)
d.Set("type", resp.Item[matchLocation].Type)

aliasRecordProperties, err := parseAliasRecordProperties(*resp.Item[matchLocation].Properties)
if err = gobam.LogoutClientIfError(client, err, "Error parsing alias record properties"); err != nil {
mutex.Unlock()
return diag.FromErr(err)
}

d.Set("absolute_name", aliasRecordProperties.absoluteName)
d.Set("parent_id", aliasRecordProperties.parentID)
d.Set("parent_type", aliasRecordProperties.parentType)
d.Set("linked_record_name", aliasRecordProperties.linkedRecordName)
d.Set("custom_properties", aliasRecordProperties.customProperties)
d.Set("ttl", aliasRecordProperties.ttl)

// logout client
if err := client.Logout(); err != nil {
mutex.Unlock()
return diag.FromErr(err)
}
log.Printf("[INFO] BlueCat Logout was successful")
mutex.Unlock()

return nil
}

type aliasRecordProperties struct {
absoluteName string
parentID string
parentType string
ttl int
linkedRecordName string
customProperties map[string]string
}

func parseAliasRecordProperties(properties string) (aliasRecordProperties, error) {
var hrProperties aliasRecordProperties
hrProperties.customProperties = make(map[string]string)

// if ttl isn't returned as a property it will remain set at -1
hrProperties.ttl = -1

props := strings.Split(properties, "|")
for x := range props {
if len(props[x]) > 0 {
prop := strings.Split(props[x], "=")[0]
val := strings.Split(props[x], "=")[1]

switch prop {
case "absoluteName":
hrProperties.absoluteName = val
case "linkedRecordName":
hrProperties.linkedRecordName = val
case "parentId":
hrProperties.parentID = val
case "parentType":
hrProperties.parentType = val
case "ttl":
ttlval, err := strconv.Atoi(val)
if err != nil {
return hrProperties, fmt.Errorf("error parsing ttl to int")
}
hrProperties.ttl = ttlval
default:
hrProperties.customProperties[prop] = val
}
}
}

return hrProperties, nil
}
3 changes: 3 additions & 0 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,19 @@ func New(version string) func() *schema.Provider {
},

DataSourcesMap: map[string]*schema.Resource{
"bluecat_alias_record": dataSourceAliasRecord(),
"bluecat_entity": dataSourceEntity(),
"bluecat_host_record": dataSourceHostRecord(),
"bluecat_ip4_address": dataSourceIP4Address(),
"bluecat_ip4_network": dataSourceIP4Network(),
"bluecat_ip4_network-block-range": dataSourceIP4NBR(),
},
ResourcesMap: map[string]*schema.Resource{
"bluecat_alias_record": resourceAliasRecord(),
"bluecat_host_record": resourceHostRecord(),
"bluecat_ip4_address": resourceIP4Address(),
"bluecat_ip4_available_network": resourceIP4AvailableNetwork(),
"bluecat_ip4_change_state": resourceIP4ChangeState(),
"bluecat_ip4_network": resourceIP4Network(),
},
}
Expand Down
Loading