server.garden privileged automation agent (mirror of https://git.sequentialread.com/forest/rootsystem)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

149 lines
4.5 KiB

package automation
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
errors "git.sequentialread.com/forest/pkg-errors"
"git.sequentialread.com/forest/rootsystem/configuration"
)
// https://api.gandi.net/docs/livedns/
type gandiLiveDNSRecord struct {
Name string `json:"rrset_name"`
Type string `json:"rrset_type"`
Values []string `json:"rrset_values"`
}
func handleGandiLiveDNSRecordAlreadyExists(
config *configuration.Configuration,
workingDirectory string,
terraformDirectory string,
tfShow *TerraformShow,
) (bool, error) {
var gandiCredential *configuration.Credential = nil
for _, cred := range config.Credentials {
if cred.Type == configuration.GANDI {
gandiCredential = &cred
break
}
}
createLiveDNSRecords := filterResourceChanges(
tfShow,
ResourceChangeFilter{ResourceType: "gandi_livedns_record", Action: "create", NotAction: "delete"},
)
domainName, hasDomainName := config.Terraform.Variables["domain_name"]
if gandiCredential == nil || len(createLiveDNSRecords) == 0 || !hasDomainName {
return false, nil
}
// Get the list of DNS records from the Gandi API
httpClient := http.Client{}
gandiURL := fmt.Sprintf(
"%s/%s/%s/%s",
configuration.GANDI_API_URL, "v5/livedns/domains", domainName, "records",
)
request, err := http.NewRequest("GET", gandiURL, nil)
request.Header.Add("Authorization", fmt.Sprintf("Apikey %s", gandiCredential.Password))
response, err := httpClient.Do(request)
if err != nil {
return false, err
}
if response.StatusCode != 200 {
return false, fmt.Errorf("HTTP %d when calling %s ", gandiURL, response.StatusCode)
}
bytes, err := ioutil.ReadAll(response.Body)
if err != nil {
return false, errors.Wrapf(err, "HTTP read error when calling %s ", gandiURL)
}
var recordsFromAPI []gandiLiveDNSRecord
err = json.Unmarshal(bytes, &recordsFromAPI)
if err != nil {
return false, errors.Wrapf(err, "JSON parse error when calling %s ", gandiURL)
}
recordsFromAPIById := map[string]gandiLiveDNSRecord{}
for _, record := range recordsFromAPI {
recordsFromAPIById[fmt.Sprintf("%s/%s/%s", domainName, record.Name, record.Type)] = record
}
importedAnyRecords := false
// for each record terraform plans to create, check if it already exists in Gandi
for _, resource := range createLiveDNSRecords {
recordName, hasName := getStringValue(resource, "name")
recordType, hasType := getStringValue(resource, "type")
//recordName, hasName := getStringValue(resource, "type")
if !hasName {
return false, fmt.Errorf("gandi_livedns_record %s (from terraform planned_values) is missing string value \"name\" ", resource.Address)
}
if !hasType {
return false, fmt.Errorf("gandi_livedns_record %s (from terraform planned_values) is missing string value \"type\" ", resource.Address)
}
recordId := fmt.Sprintf("%s/%s/%s", domainName, recordName, recordType)
_, gandiAlreadyHasRecord := recordsFromAPIById[recordId]
if gandiAlreadyHasRecord {
fmt.Println("---------------------------------------")
fmt.Printf(
"Terraform plans to add the DNS record %s %s to gandi, but gandi already has a record like that \n",
recordType, domainName,
)
exitCode := removeAndImportResource(terraformDirectory, resource.Address, recordId)
if exitCode != 0 {
return false, errors.New("terraform import returned a non-zero exit code")
}
importedAnyRecords = true
fmt.Println("---------------------------------------")
} else {
altType := ""
if recordType == "CNAME" {
altType = "A"
}
if recordType == "A" {
altType = "CNAME"
}
altRecordId := fmt.Sprintf("%s/%s/%s", domainName, recordName, altType)
_, gandiHasAltRecord := recordsFromAPIById[altRecordId]
if gandiHasAltRecord {
fmt.Printf(
"Terraform plans to add the DNS record [%s %s] to gandi, but gandi has a conflicting record [%s %s]. Deleting the conflicting record...\n",
recordType, domainName, altType, domainName,
)
gandiURL := fmt.Sprintf(
"%s/%s/%s/%s/%s/%s",
configuration.GANDI_API_URL, "v5/livedns/domains", domainName, "records", recordName, altType,
)
request, err := http.NewRequest("DELETE", gandiURL, nil)
request.Header.Add("Authorization", fmt.Sprintf("Apikey %s", gandiCredential.Password))
response, err := httpClient.Do(request)
if err != nil {
return false, err
}
if response.StatusCode != 200 {
return false, fmt.Errorf("HTTP %d when calling DELETE %s ", gandiURL, response.StatusCode)
}
}
}
}
return importedAnyRecords, nil
}