-
Couldn't load subscription status.
- Fork 53
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 { | ||
|
||
| 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)") | ||
|
||
| } | ||
| } | ||
| 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.StatusOKlooks 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. 🙂