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
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 |
|
}
|
|
|