-
Notifications
You must be signed in to change notification settings - Fork 52
Add zone metadata resource #83
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
base: master
Are you sure you want to change the base?
Changes from 6 commits
0f991b0
c427979
0363bd3
68b8d61
cd81ddd
1d9a2cf
895dc0d
22c8b04
74f0d78
8f1266a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
terraform-provider-dns | ||
terraform-provider-powerdns | ||
|
||
*.dll | ||
*.exe | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
version: "3" | ||
version: "3.7" | ||
services: | ||
nginx: | ||
image: nginx:1.17.2 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -185,6 +185,12 @@ type ResourceRecordSet struct { | |
Records []Record `json:"records,omitempty"` | ||
} | ||
|
||
// ResourceZoneMetadata represents a PowerDNS Zone Metadata object | ||
type ResourceZoneMetadata struct { | ||
Kind string `json:"kind"` | ||
Metadata []string `json:"metadata"` | ||
} | ||
|
||
type zonePatchRequest struct { | ||
RecordSets []ResourceRecordSet `json:"rrsets"` | ||
} | ||
|
@@ -215,6 +221,11 @@ func (rrSet *ResourceRecordSet) ID() string { | |
return rrSet.Name + idSeparator + rrSet.Type | ||
} | ||
|
||
// ID returns a zoneMetadata with the ID format | ||
func (metadata *ResourceZoneMetadata) ID(zone string) string { | ||
return zone + idSeparator + metadata.Kind | ||
} | ||
|
||
// Returns name and type of record or record set based on its ID | ||
func parseID(recID string) (string, string, error) { | ||
s := strings.Split(recID, idSeparator) | ||
|
@@ -292,7 +303,7 @@ func (client *Client) GetZone(name string) (ZoneInfo, error) { | |
} | ||
defer resp.Body.Close() | ||
|
||
if resp.StatusCode != http.StatusOK { | ||
if resp.StatusCode != 200 { | ||
errorResp := new(errorResponse) | ||
if err = json.NewDecoder(resp.Body).Decode(errorResp); err != nil { | ||
return ZoneInfo{}, fmt.Errorf("Error getting zone: %s", name) | ||
|
@@ -576,6 +587,136 @@ func (client *Client) DeleteRecordSetByID(zone string, recID string) error { | |
return client.DeleteRecordSet(zone, name, tpe) | ||
} | ||
|
||
// GetZoneMetadata get metadata from zone by its ID | ||
func (client *Client) GetZoneMetadata(id string) (ResourceZoneMetadata, error) { | ||
zone, kind, err := parseID(id) | ||
if err != nil { | ||
return ResourceZoneMetadata{}, err | ||
} | ||
|
||
req, err := client.newRequest("GET", fmt.Sprintf("/servers/localhost/zones/%s/metadata/%s", zone, kind), nil) | ||
if err != nil { | ||
return ResourceZoneMetadata{}, err | ||
} | ||
|
||
resp, err := client.HTTP.Do(req) | ||
if err != nil { | ||
return ResourceZoneMetadata{}, err | ||
} | ||
defer resp.Body.Close() | ||
|
||
var zoneMetadata ResourceZoneMetadata | ||
err = json.NewDecoder(resp.Body).Decode(&zoneMetadata) | ||
if err != nil { | ||
return ResourceZoneMetadata{}, err | ||
} | ||
|
||
return zoneMetadata, nil | ||
} | ||
|
||
// UpdateZoneMetadata creates new record set in Zone | ||
func (client *Client) UpdateZoneMetadata(zone string, zoneMetadata ResourceZoneMetadata) (string, error) { | ||
body, err := json.Marshal(zoneMetadata) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
req, err := client.newRequest("PUT", fmt.Sprintf("/servers/localhost/zones/%s/metadata/%s", zone, zoneMetadata.Kind), body) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
resp, err := client.HTTP.Do(req) | ||
if err != nil { | ||
return "", err | ||
} | ||
defer resp.Body.Close() | ||
|
||
if resp.StatusCode != http.StatusOK { | ||
errorResp := new(errorResponse) | ||
if err = json.NewDecoder(resp.Body).Decode(errorResp); err != nil { | ||
return "", fmt.Errorf("Error updating zone metadata: %s", zoneMetadata.Kind) | ||
} | ||
return "", fmt.Errorf("Error updating zone metadata: %s, reason: %q", zoneMetadata.Kind, errorResp.ErrorMsg) | ||
} | ||
|
||
var createdZoneMetadata ResourceZoneMetadata | ||
err = json.NewDecoder(resp.Body).Decode(&createdZoneMetadata) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
return createdZoneMetadata.ID(zone), nil | ||
} | ||
|
||
// DeleteZoneMetadata deletes zone metadata by its ID | ||
func (client *Client) DeleteZoneMetadata(id string) error { | ||
zone, kind, err := parseID(id) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
req, err := client.newRequest("DELETE", fmt.Sprintf("/servers/localhost/zones/%s/metadata/%s", zone, kind), nil) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
resp, err := client.HTTP.Do(req) | ||
if err != nil { | ||
return err | ||
} | ||
defer resp.Body.Close() | ||
|
||
if resp.StatusCode != 200 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. http.StatusOK There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||
errorResp := new(errorResponse) | ||
if err = json.NewDecoder(resp.Body).Decode(errorResp); err != nil { | ||
return fmt.Errorf("Error deleting Zone Metadata: %s", kind) | ||
} | ||
return fmt.Errorf("Error deleting Zone Metadata: %s, reason: %q", kind, errorResp.ErrorMsg) | ||
} | ||
return nil | ||
} | ||
|
||
// ZoneMetadataExists checks if requested zone exists | ||
func (client *Client) ZoneMetadataExists(id string) (bool, error) { | ||
zone, kind, err := parseID(id) | ||
if err != nil { | ||
return false, err | ||
} | ||
|
||
req, err := client.newRequest("GET", fmt.Sprintf("/servers/localhost/zones/%s/metadata/%s", zone, kind), nil) | ||
if err != nil { | ||
return false, err | ||
} | ||
|
||
resp, err := client.HTTP.Do(req) | ||
if err != nil { | ||
return false, err | ||
} | ||
defer resp.Body.Close() | ||
|
||
if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusNotFound { | ||
errorResp := new(errorResponse) | ||
if err = json.NewDecoder(resp.Body).Decode(errorResp); err != nil { | ||
return false, fmt.Errorf("Error getting Zone Metadata: %s", kind) | ||
} | ||
return false, fmt.Errorf("Error getting Zone Metadata: %s, reason: %q", kind, errorResp.ErrorMsg) | ||
} | ||
|
||
var ZoneMetadata ResourceZoneMetadata | ||
err = json.NewDecoder(resp.Body).Decode(&ZoneMetadata) | ||
|
||
if err != nil { | ||
return false, err | ||
} | ||
|
||
if len(ZoneMetadata.Metadata) == 0 { | ||
return false, err | ||
} | ||
|
||
return resp.StatusCode == http.StatusOK, nil | ||
} | ||
|
||
func (client *Client) setServerVersion() error { | ||
req, err := client.newRequest("GET", "/servers/localhost", nil) | ||
if err != nil { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
package powerdns | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
"strings" | ||
|
||
"github.com/hashicorp/terraform-plugin-sdk/helper/schema" | ||
) | ||
|
||
func resourcePDNSZoneMetadata() *schema.Resource { | ||
return &schema.Resource{ | ||
Create: resourcePDNSZoneMetadataCreate, | ||
Read: resourcePDNSZoneMetadataRead, | ||
Delete: resourcePDNSZoneMetadataDelete, | ||
Exists: resourcePDNSZoneMetadataExists, | ||
Importer: &schema.ResourceImporter{ | ||
State: schema.ImportStatePassthrough, | ||
}, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"zone": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
|
||
"kind": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
|
||
"metadata": { | ||
Type: schema.TypeSet, | ||
Elem: &schema.Schema{Type: schema.TypeString}, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func resourcePDNSZoneMetadataCreate(d *schema.ResourceData, meta interface{}) error { | ||
client := meta.(*Client) | ||
|
||
zone := d.Get("zone").(string) | ||
mtdata := d.Get("metadata").(*schema.Set).List() | ||
|
||
for _, mt := range mtdata { | ||
if len(strings.Trim(mt.(string), " ")) == 0 { | ||
log.Printf("[WARN] One or more values in 'metadata' contain empty '' value(s)") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I assume here was something in single quotes but you deleted it but quotes are left. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And also there is a function TrimSpace in strings package. We can use it instead of regular trim :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed it, thanks! |
||
} | ||
} | ||
if !(len(mtdata) > 0) { | ||
return fmt.Errorf("'metadata' must not be empty") | ||
} | ||
|
||
metadata := make([]string, 0, len(mtdata)) | ||
for _, mt := range mtdata { | ||
metadata = append(metadata, mt.(string)) | ||
} | ||
|
||
zoneMetadata := ResourceZoneMetadata{ | ||
Kind: d.Get("kind").(string), | ||
Metadata: metadata, | ||
} | ||
|
||
log.Printf("[DEBUG] Creating PowerDNS Zone Metadata: %#v", zoneMetadata) | ||
|
||
metaid, err := client.UpdateZoneMetadata(zone, zoneMetadata) | ||
if err != nil { | ||
return fmt.Errorf("Failed to create PowerDNS Zone Metadata: %s", err) | ||
} | ||
|
||
d.SetId(metaid) | ||
log.Printf("[INFO] Created PowerDNS Zone Metadata with ID: %s", d.Id()) | ||
|
||
return nil | ||
} | ||
|
||
func resourcePDNSZoneMetadataRead(d *schema.ResourceData, meta interface{}) error { | ||
client := meta.(*Client) | ||
|
||
log.Printf("[DEBUG] Reading PowerDNS Zone Metadata: %s", d.Id()) | ||
record, err := client.GetZoneMetadata(d.Id()) | ||
if err != nil { | ||
return fmt.Errorf("Couldn't fetch PowerDNS Zone Metadata: %s", err) | ||
} | ||
|
||
zone, _, err := parseID(d.Id()) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
d.SetId(d.Id()) | ||
d.Set("kind", record.Kind) | ||
d.Set("metadata", record.Metadata) | ||
d.Set("zone", zone) | ||
|
||
return nil | ||
} | ||
|
||
func resourcePDNSZoneMetadataDelete(d *schema.ResourceData, meta interface{}) error { | ||
client := meta.(*Client) | ||
|
||
log.Printf("[INFO] Deleting PowerDNS Zone Metadata: %s", d.Id()) | ||
err := client.DeleteZoneMetadata(d.Id()) | ||
|
||
if err != nil { | ||
return fmt.Errorf("Error deleting PowerDNS Zone Metadata: %s", err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func resourcePDNSZoneMetadataExists(d *schema.ResourceData, meta interface{}) (bool, error) { | ||
log.Printf("[INFO] Checking existence of PowerDNS Zone Metadata: %s", d.Id()) | ||
|
||
client := meta.(*Client) | ||
exists, err := client.ZoneMetadataExists(d.Id()) | ||
|
||
if err != nil { | ||
return false, fmt.Errorf("Error checking PowerDNS Zone Metadata: %s", err) | ||
} | ||
return exists, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would suggest to change it back here. Also at some other places(I will point). Let keep the same style.
http.StatusOK
looks more clear at least for me.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh, I got it, It was unclear for me because both styles are exists in the code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, I am about to refactor the project a bit in near feature. 🙂