mirror of
https://github.com/kubernetes-sigs/external-dns.git
synced 2025-08-06 01:26:59 +02:00
* ci linting fixes Signed-off-by: Raffaele Di Fazio <difazio.raffaele@gmail.com> * remove staticcheck Signed-off-by: Raffaele Di Fazio <difazio.raffaele@gmail.com> * disable naming rule Signed-off-by: Raffaele Di Fazio <difazio.raffaele@gmail.com> * disable stylecheck too Signed-off-by: Raffaele Di Fazio <difazio.raffaele@gmail.com> * linter errors fixes Signed-off-by: Raffaele Di Fazio <difazio.raffaele@gmail.com> * re-add staticcheck Signed-off-by: Raffaele Di Fazio <difazio.raffaele@gmail.com> * fixes various linting issues Signed-off-by: Raffaele Di Fazio <difazio.raffaele@gmail.com> * fix imports Signed-off-by: Raffaele Di Fazio <difazio.raffaele@gmail.com> * fix tlsconfig Signed-off-by: Raffaele Di Fazio <difazio.raffaele@gmail.com> * fix alibabacloud Signed-off-by: Raffaele Di Fazio <difazio.raffaele@gmail.com> * ioutil fixes Signed-off-by: Raffaele Di Fazio <difazio.raffaele@gmail.com> * remove all references to ioutil Signed-off-by: Raffaele Di Fazio <difazio.raffaele@gmail.com> * ignore linting for azure deprecated sdk Signed-off-by: Raffaele Di Fazio <difazio.raffaele@gmail.com> Signed-off-by: Raffaele Di Fazio <difazio.raffaele@gmail.com>
584 lines
20 KiB
Go
584 lines
20 KiB
Go
/*
|
|
Copyright 2020 The Kubernetes Authors.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
// TODO: add logging
|
|
// TODO: add timeouts
|
|
package api
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/tls"
|
|
"encoding/json"
|
|
"io"
|
|
"net/http"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/pkg/errors"
|
|
log "github.com/sirupsen/logrus"
|
|
)
|
|
|
|
// TODO: Ensure DNS Deploy Type Defaults to no-deploy instead of ""
|
|
type BluecatConfig struct {
|
|
GatewayHost string `json:"gatewayHost"`
|
|
GatewayUsername string `json:"gatewayUsername,omitempty"`
|
|
GatewayPassword string `json:"gatewayPassword,omitempty"`
|
|
DNSConfiguration string `json:"dnsConfiguration"`
|
|
DNSServerName string `json:"dnsServerName"`
|
|
DNSDeployType string `json:"dnsDeployType"`
|
|
View string `json:"dnsView"`
|
|
RootZone string `json:"rootZone"`
|
|
SkipTLSVerify bool `json:"skipTLSVerify"`
|
|
}
|
|
|
|
type GatewayClient interface {
|
|
GetBluecatZones(zoneName string) ([]BluecatZone, error)
|
|
GetHostRecords(zone string, records *[]BluecatHostRecord) error
|
|
GetCNAMERecords(zone string, records *[]BluecatCNAMERecord) error
|
|
GetHostRecord(name string, record *BluecatHostRecord) error
|
|
GetCNAMERecord(name string, record *BluecatCNAMERecord) error
|
|
CreateHostRecord(zone string, req *BluecatCreateHostRecordRequest) error
|
|
CreateCNAMERecord(zone string, req *BluecatCreateCNAMERecordRequest) error
|
|
DeleteHostRecord(name string, zone string) (err error)
|
|
DeleteCNAMERecord(name string, zone string) (err error)
|
|
GetTXTRecords(zone string, records *[]BluecatTXTRecord) error
|
|
GetTXTRecord(name string, record *BluecatTXTRecord) error
|
|
CreateTXTRecord(zone string, req *BluecatCreateTXTRecordRequest) error
|
|
DeleteTXTRecord(name string, zone string) error
|
|
ServerFullDeploy() error
|
|
}
|
|
|
|
// GatewayClientConfig defines the configuration for a Bluecat Gateway Client
|
|
type GatewayClientConfig struct {
|
|
Cookie http.Cookie
|
|
Token string
|
|
Host string
|
|
DNSConfiguration string
|
|
View string
|
|
RootZone string
|
|
DNSServerName string
|
|
SkipTLSVerify bool
|
|
}
|
|
|
|
// BluecatZone defines a zone to hold records
|
|
type BluecatZone struct {
|
|
ID int `json:"id"`
|
|
Name string `json:"name"`
|
|
Properties string `json:"properties"`
|
|
Type string `json:"type"`
|
|
}
|
|
|
|
// BluecatHostRecord defines dns Host record
|
|
type BluecatHostRecord struct {
|
|
ID int `json:"id"`
|
|
Name string `json:"name"`
|
|
Properties string `json:"properties"`
|
|
Type string `json:"type"`
|
|
}
|
|
|
|
// BluecatCNAMERecord defines dns CNAME record
|
|
type BluecatCNAMERecord struct {
|
|
ID int `json:"id"`
|
|
Name string `json:"name"`
|
|
Properties string `json:"properties"`
|
|
Type string `json:"type"`
|
|
}
|
|
|
|
// BluecatTXTRecord defines dns TXT record
|
|
type BluecatTXTRecord struct {
|
|
ID int `json:"id"`
|
|
Name string `json:"name"`
|
|
Properties string `json:"properties"`
|
|
}
|
|
|
|
type BluecatCreateHostRecordRequest struct {
|
|
AbsoluteName string `json:"absolute_name"`
|
|
IP4Address string `json:"ip4_address"`
|
|
TTL int `json:"ttl"`
|
|
Properties string `json:"properties"`
|
|
}
|
|
|
|
type BluecatCreateCNAMERecordRequest struct {
|
|
AbsoluteName string `json:"absolute_name"`
|
|
LinkedRecord string `json:"linked_record"`
|
|
TTL int `json:"ttl"`
|
|
Properties string `json:"properties"`
|
|
}
|
|
|
|
type BluecatCreateTXTRecordRequest struct {
|
|
AbsoluteName string `json:"absolute_name"`
|
|
Text string `json:"txt"`
|
|
}
|
|
|
|
type BluecatServerFullDeployRequest struct {
|
|
ServerName string `json:"server_name"`
|
|
}
|
|
|
|
// NewGatewayClient creates and returns a new Bluecat gateway client
|
|
func NewGatewayClientConfig(cookie http.Cookie, token, gatewayHost, dnsConfiguration, view, rootZone, dnsServerName string, skipTLSVerify bool) GatewayClientConfig {
|
|
// TODO: do not handle defaulting here
|
|
//
|
|
// Right now the Bluecat gateway doesn't seem to have a way to get the root zone from the API. If the user
|
|
// doesn't provide one via the config file we'll assume it's 'com'
|
|
if rootZone == "" {
|
|
rootZone = "com"
|
|
}
|
|
return GatewayClientConfig{
|
|
Cookie: cookie,
|
|
Token: token,
|
|
Host: gatewayHost,
|
|
DNSConfiguration: dnsConfiguration,
|
|
DNSServerName: dnsServerName,
|
|
View: view,
|
|
RootZone: rootZone,
|
|
SkipTLSVerify: skipTLSVerify,
|
|
}
|
|
}
|
|
|
|
// GetBluecatGatewayToken retrieves a Bluecat Gateway API token.
|
|
func GetBluecatGatewayToken(cfg BluecatConfig) (string, http.Cookie, error) {
|
|
var username string
|
|
if cfg.GatewayUsername != "" {
|
|
username = cfg.GatewayUsername
|
|
}
|
|
if v, ok := os.LookupEnv("BLUECAT_USERNAME"); ok {
|
|
username = v
|
|
}
|
|
|
|
var password string
|
|
if cfg.GatewayPassword != "" {
|
|
password = cfg.GatewayPassword
|
|
}
|
|
if v, ok := os.LookupEnv("BLUECAT_PASSWORD"); ok {
|
|
password = v
|
|
}
|
|
|
|
body, err := json.Marshal(map[string]string{
|
|
"username": username,
|
|
"password": password,
|
|
})
|
|
if err != nil {
|
|
return "", http.Cookie{}, errors.Wrap(err, "could not unmarshal credentials for bluecat gateway config")
|
|
}
|
|
url := cfg.GatewayHost + "/rest_login"
|
|
|
|
response, err := executeHTTPRequest(cfg.SkipTLSVerify, http.MethodPost, url, "", bytes.NewBuffer(body), http.Cookie{})
|
|
if err != nil {
|
|
return "", http.Cookie{}, errors.Wrap(err, "error obtaining API token from bluecat gateway")
|
|
}
|
|
defer response.Body.Close()
|
|
|
|
responseBody, err := io.ReadAll(response.Body)
|
|
if err != nil {
|
|
return "", http.Cookie{}, errors.Wrap(err, "failed to read login response from bluecat gateway")
|
|
}
|
|
|
|
if response.StatusCode != http.StatusOK {
|
|
return "", http.Cookie{}, errors.Errorf("got HTTP response code %v, detailed message: %v", response.StatusCode, string(responseBody))
|
|
}
|
|
|
|
jsonResponse := map[string]string{}
|
|
err = json.Unmarshal(responseBody, &jsonResponse)
|
|
if err != nil {
|
|
return "", http.Cookie{}, errors.Wrap(err, "error unmarshaling json response (auth) from bluecat gateway")
|
|
}
|
|
|
|
// Example response: {"access_token": "BAMAuthToken: abc123"}
|
|
// We only care about the actual token string - i.e. abc123
|
|
// The gateway also creates a cookie as part of the response. This seems to be the actual auth mechanism, at least
|
|
// for now.
|
|
return strings.Split(jsonResponse["access_token"], " ")[1], *response.Cookies()[0], nil
|
|
}
|
|
|
|
func (c GatewayClientConfig) GetBluecatZones(zoneName string) ([]BluecatZone, error) {
|
|
zonePath := expandZone(zoneName)
|
|
url := c.Host + "/api/v1/configurations/" + c.DNSConfiguration + "/views/" + c.View + "/" + zonePath
|
|
|
|
response, err := executeHTTPRequest(c.SkipTLSVerify, http.MethodGet, url, c.Token, nil, c.Cookie)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "error requesting zones from gateway: %v, %v", url, zoneName)
|
|
}
|
|
defer response.Body.Close()
|
|
|
|
if response.StatusCode != http.StatusOK {
|
|
return nil, errors.Errorf("received http %v requesting zones from gateway in zone %v", response.StatusCode, zoneName)
|
|
}
|
|
|
|
zones := []BluecatZone{}
|
|
json.NewDecoder(response.Body).Decode(&zones)
|
|
|
|
// Bluecat Gateway only returns subzones one level deeper than the provided zone
|
|
// so this recursion is needed to traverse subzones until none are returned
|
|
for _, zone := range zones {
|
|
zoneProps := SplitProperties(zone.Properties)
|
|
subZones, err := c.GetBluecatZones(zoneProps["absoluteName"])
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "error retrieving subzones from gateway: %v", zoneName)
|
|
}
|
|
zones = append(zones, subZones...)
|
|
}
|
|
|
|
return zones, nil
|
|
}
|
|
|
|
func (c GatewayClientConfig) GetHostRecords(zone string, records *[]BluecatHostRecord) error {
|
|
zonePath := expandZone(zone)
|
|
// Remove the trailing 'zones/'
|
|
zonePath = strings.TrimSuffix(zonePath, "zones/")
|
|
|
|
url := c.Host + "/api/v1/configurations/" + c.DNSConfiguration + "/views/" + c.View + "/" + zonePath + "host_records/"
|
|
|
|
response, err := executeHTTPRequest(c.SkipTLSVerify, http.MethodGet, url, c.Token, nil, c.Cookie)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "error requesting host records from gateway in zone %v", zone)
|
|
}
|
|
defer response.Body.Close()
|
|
|
|
if response.StatusCode != http.StatusOK {
|
|
return errors.Errorf("received http %v requesting host records from gateway in zone %v", response.StatusCode, zone)
|
|
}
|
|
|
|
json.NewDecoder(response.Body).Decode(records)
|
|
log.Debugf("Get Host Records Response: %v", records)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (c GatewayClientConfig) GetCNAMERecords(zone string, records *[]BluecatCNAMERecord) error {
|
|
zonePath := expandZone(zone)
|
|
// Remove the trailing 'zones/'
|
|
zonePath = strings.TrimSuffix(zonePath, "zones/")
|
|
|
|
url := c.Host + "/api/v1/configurations/" + c.DNSConfiguration + "/views/" + c.View + "/" + zonePath + "cname_records/"
|
|
|
|
response, err := executeHTTPRequest(c.SkipTLSVerify, http.MethodGet, url, c.Token, nil, c.Cookie)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "error retrieving cname records from gateway in zone %v", zone)
|
|
}
|
|
defer response.Body.Close()
|
|
|
|
if response.StatusCode != http.StatusOK {
|
|
return errors.Errorf("received http %v requesting cname records from gateway in zone %v", response.StatusCode, zone)
|
|
}
|
|
|
|
json.NewDecoder(response.Body).Decode(records)
|
|
log.Debugf("Get CName Records Response: %v", records)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (c GatewayClientConfig) GetTXTRecords(zone string, records *[]BluecatTXTRecord) error {
|
|
zonePath := expandZone(zone)
|
|
// Remove the trailing 'zones/'
|
|
zonePath = strings.TrimSuffix(zonePath, "zones/")
|
|
|
|
url := c.Host + "/api/v1/configurations/" + c.DNSConfiguration + "/views/" + c.View + "/" + zonePath + "text_records/"
|
|
|
|
response, err := executeHTTPRequest(c.SkipTLSVerify, http.MethodGet, url, c.Token, nil, c.Cookie)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "error retrieving txt records from gateway in zone %v", zone)
|
|
}
|
|
defer response.Body.Close()
|
|
|
|
if response.StatusCode != http.StatusOK {
|
|
return errors.Errorf("received http %v requesting txt records from gateway in zone %v", response.StatusCode, zone)
|
|
}
|
|
|
|
log.Debugf("Get Txt Records response: %v", response)
|
|
json.NewDecoder(response.Body).Decode(records)
|
|
log.Debugf("Get TXT Records Body: %v", records)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (c GatewayClientConfig) GetHostRecord(name string, record *BluecatHostRecord) error {
|
|
url := c.Host + "/api/v1/configurations/" + c.DNSConfiguration +
|
|
"/views/" + c.View + "/" +
|
|
"host_records/" + name + "/"
|
|
|
|
response, err := executeHTTPRequest(c.SkipTLSVerify, http.MethodGet, url, c.Token, nil, c.Cookie)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "error retrieving host record %v from gateway", name)
|
|
}
|
|
defer response.Body.Close()
|
|
|
|
if response.StatusCode != http.StatusOK {
|
|
return errors.Errorf("received http %v while retrieving host record %v from gateway", response.StatusCode, name)
|
|
}
|
|
|
|
json.NewDecoder(response.Body).Decode(record)
|
|
log.Debugf("Get Host Record Response: %v", record)
|
|
return nil
|
|
}
|
|
|
|
func (c GatewayClientConfig) GetCNAMERecord(name string, record *BluecatCNAMERecord) error {
|
|
url := c.Host + "/api/v1/configurations/" + c.DNSConfiguration +
|
|
"/views/" + c.View + "/" +
|
|
"cname_records/" + name + "/"
|
|
|
|
response, err := executeHTTPRequest(c.SkipTLSVerify, http.MethodGet, url, c.Token, nil, c.Cookie)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "error retrieving cname record %v from gateway", name)
|
|
}
|
|
defer response.Body.Close()
|
|
|
|
if response.StatusCode != http.StatusOK {
|
|
return errors.Errorf("received http %v while retrieving cname record %v from gateway", response.StatusCode, name)
|
|
}
|
|
|
|
json.NewDecoder(response.Body).Decode(record)
|
|
log.Debugf("Get CName Record Response: %v", record)
|
|
return nil
|
|
}
|
|
|
|
func (c GatewayClientConfig) GetTXTRecord(name string, record *BluecatTXTRecord) error {
|
|
url := c.Host + "/api/v1/configurations/" + c.DNSConfiguration +
|
|
"/views/" + c.View + "/" +
|
|
"text_records/" + name + "/"
|
|
|
|
response, err := executeHTTPRequest(c.SkipTLSVerify, http.MethodGet, url, c.Token, nil, c.Cookie)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "error retrieving record %v from gateway", name)
|
|
}
|
|
defer response.Body.Close()
|
|
|
|
if response.StatusCode != http.StatusOK {
|
|
return errors.Errorf("received http %v while retrieving txt record %v from gateway", response.StatusCode, name)
|
|
}
|
|
|
|
json.NewDecoder(response.Body).Decode(record)
|
|
log.Debugf("Get TXT Record Response: %v", record)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (c GatewayClientConfig) CreateHostRecord(zone string, req *BluecatCreateHostRecordRequest) error {
|
|
zonePath := expandZone(zone)
|
|
// Remove the trailing 'zones/'
|
|
zonePath = strings.TrimSuffix(zonePath, "zones/")
|
|
|
|
url := c.Host + "/api/v1/configurations/" + c.DNSConfiguration + "/views/" + c.View + "/" + zonePath + "host_records/"
|
|
body, err := json.Marshal(req)
|
|
if err != nil {
|
|
return errors.Wrap(err, "could not marshal body for create host record")
|
|
}
|
|
|
|
response, err := executeHTTPRequest(c.SkipTLSVerify, http.MethodPost, url, c.Token, bytes.NewBuffer(body), c.Cookie)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "error creating host record %v in gateway", req.AbsoluteName)
|
|
}
|
|
defer response.Body.Close()
|
|
|
|
if response.StatusCode != http.StatusCreated {
|
|
return errors.Errorf("received http %v while creating host record %v in gateway", response.StatusCode, req.AbsoluteName)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (c GatewayClientConfig) CreateCNAMERecord(zone string, req *BluecatCreateCNAMERecordRequest) error {
|
|
zonePath := expandZone(zone)
|
|
// Remove the trailing 'zones/'
|
|
zonePath = strings.TrimSuffix(zonePath, "zones/")
|
|
|
|
url := c.Host + "/api/v1/configurations/" + c.DNSConfiguration + "/views/" + c.View + "/" + zonePath + "cname_records/"
|
|
body, err := json.Marshal(req)
|
|
if err != nil {
|
|
return errors.Wrap(err, "could not marshal body for create cname record")
|
|
}
|
|
|
|
response, err := executeHTTPRequest(c.SkipTLSVerify, http.MethodPost, url, c.Token, bytes.NewBuffer(body), c.Cookie)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "error creating cname record %v in gateway", req.AbsoluteName)
|
|
}
|
|
defer response.Body.Close()
|
|
|
|
if response.StatusCode != http.StatusCreated {
|
|
return errors.Errorf("received http %v while creating cname record %v to alias %v in gateway", response.StatusCode, req.AbsoluteName, req.LinkedRecord)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (c GatewayClientConfig) CreateTXTRecord(zone string, req *BluecatCreateTXTRecordRequest) error {
|
|
zonePath := expandZone(zone)
|
|
// Remove the trailing 'zones/'
|
|
zonePath = strings.TrimSuffix(zonePath, "zones/")
|
|
|
|
url := c.Host + "/api/v1/configurations/" + c.DNSConfiguration + "/views/" + c.View + "/" + zonePath + "text_records/"
|
|
body, err := json.Marshal(req)
|
|
if err != nil {
|
|
return errors.Wrap(err, "could not marshal body for create txt record")
|
|
}
|
|
|
|
response, err := executeHTTPRequest(c.SkipTLSVerify, http.MethodPost, url, c.Token, bytes.NewBuffer(body), c.Cookie)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "error creating txt record %v in gateway", req.AbsoluteName)
|
|
}
|
|
defer response.Body.Close()
|
|
|
|
if response.StatusCode != http.StatusCreated {
|
|
return errors.Errorf("received http %v while creating txt record %v in gateway", response.StatusCode, req.AbsoluteName)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (c GatewayClientConfig) DeleteHostRecord(name string, zone string) (err error) {
|
|
url := c.Host + "/api/v1/configurations/" + c.DNSConfiguration +
|
|
"/views/" + c.View + "/" +
|
|
"host_records/" + name + "." + zone + "/"
|
|
|
|
response, err := executeHTTPRequest(c.SkipTLSVerify, http.MethodDelete, url, c.Token, nil, c.Cookie)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "error deleting host record %v from gateway", name)
|
|
}
|
|
|
|
if response.StatusCode != http.StatusNoContent {
|
|
return errors.Errorf("received http %v while deleting host record %v from gateway", response.StatusCode, name)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (c GatewayClientConfig) DeleteCNAMERecord(name string, zone string) (err error) {
|
|
url := c.Host + "/api/v1/configurations/" + c.DNSConfiguration +
|
|
"/views/" + c.View + "/" +
|
|
"cname_records/" + name + "." + zone + "/"
|
|
|
|
response, err := executeHTTPRequest(c.SkipTLSVerify, http.MethodDelete, url, c.Token, nil, c.Cookie)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "error deleting cname record %v from gateway", name)
|
|
}
|
|
if response.StatusCode != http.StatusNoContent {
|
|
return errors.Errorf("received http %v while deleting cname record %v from gateway", response.StatusCode, name)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (c GatewayClientConfig) DeleteTXTRecord(name string, zone string) error {
|
|
url := c.Host + "/api/v1/configurations/" + c.DNSConfiguration +
|
|
"/views/" + c.View + "/" +
|
|
"text_records/" + name + "." + zone + "/"
|
|
|
|
response, err := executeHTTPRequest(c.SkipTLSVerify, http.MethodDelete, url, c.Token, nil, c.Cookie)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "error deleting txt record %v from gateway", name)
|
|
}
|
|
if response.StatusCode != http.StatusNoContent {
|
|
return errors.Errorf("received http %v while deleting txt record %v from gateway", response.StatusCode, name)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (c GatewayClientConfig) ServerFullDeploy() error {
|
|
log.Infof("Executing full deploy on server %s", c.DNSServerName)
|
|
url := c.Host + "/api/v1/configurations/" + c.DNSConfiguration + "/server/full_deploy/"
|
|
requestBody := BluecatServerFullDeployRequest{
|
|
ServerName: c.DNSServerName,
|
|
}
|
|
|
|
body, err := json.Marshal(requestBody)
|
|
if err != nil {
|
|
return errors.Wrap(err, "could not marshal body for server full deploy")
|
|
}
|
|
|
|
response, err := executeHTTPRequest(c.SkipTLSVerify, http.MethodPost, url, c.Token, bytes.NewBuffer(body), c.Cookie)
|
|
if err != nil {
|
|
return errors.Wrap(err, "error executing full deploy")
|
|
}
|
|
|
|
if response.StatusCode != http.StatusCreated {
|
|
responseBody, err := io.ReadAll(response.Body)
|
|
if err != nil {
|
|
return errors.Wrap(err, "failed to read full deploy response body")
|
|
}
|
|
return errors.Errorf("got HTTP response code %v, detailed message: %v", response.StatusCode, string(responseBody))
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// SplitProperties is a helper function to break a '|' separated string into key/value pairs
|
|
// i.e. "foo=bar|baz=mop"
|
|
func SplitProperties(props string) map[string]string {
|
|
propMap := make(map[string]string)
|
|
// remove trailing | character before we split
|
|
props = strings.TrimSuffix(props, "|")
|
|
|
|
splits := strings.Split(props, "|")
|
|
for _, pair := range splits {
|
|
items := strings.Split(pair, "=")
|
|
propMap[items[0]] = items[1]
|
|
}
|
|
|
|
return propMap
|
|
}
|
|
|
|
// IsValidDNSDeployType validates the deployment type provided by a users configuration is supported by the Bluecat Provider.
|
|
func IsValidDNSDeployType(deployType string) bool {
|
|
validDNSDeployTypes := []string{"no-deploy", "full-deploy"}
|
|
for _, t := range validDNSDeployTypes {
|
|
if t == deployType {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// expandZone takes an absolute domain name such as 'example.com' and returns a zone hierarchy used by Bluecat Gateway,
|
|
// such as '/zones/com/zones/example/zones/'
|
|
func expandZone(zone string) string {
|
|
ze := "zones/"
|
|
parts := strings.Split(zone, ".")
|
|
if len(parts) > 1 {
|
|
last := len(parts) - 1
|
|
for i := range parts {
|
|
ze = ze + parts[last-i] + "/zones/"
|
|
}
|
|
} else {
|
|
ze = ze + zone + "/zones/"
|
|
}
|
|
return ze
|
|
}
|
|
|
|
func executeHTTPRequest(skipTLSVerify bool, method, url, token string, body io.Reader, cookie http.Cookie) (*http.Response, error) {
|
|
httpClient := &http.Client{
|
|
Transport: &http.Transport{
|
|
Proxy: http.ProxyFromEnvironment,
|
|
TLSClientConfig: &tls.Config{
|
|
InsecureSkipVerify: skipTLSVerify,
|
|
},
|
|
},
|
|
}
|
|
request, err := http.NewRequest(method, url, body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if request.Method == http.MethodPost {
|
|
request.Header.Add("Content-Type", "application/json")
|
|
}
|
|
request.Header.Add("Accept", "application/json")
|
|
|
|
if token != "" {
|
|
request.Header.Add("Authorization", "Basic "+token)
|
|
}
|
|
request.AddCookie(&cookie)
|
|
|
|
return httpClient.Do(request)
|
|
}
|