mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-30 10:47:14 -06:00
d783e831f8
* vendor: update github.com/Ensighten/udnssdk to v1.2.1 * ultradns_tcpool: add * ultradns.baseurl: set default * ultradns.record: cleanup test * ultradns_record: extract common, cleanup * ultradns: extract common * ultradns_dirpool: add * ultradns_dirpool: fix rdata.ip_info.ips to be idempotent * ultradns_tcpool: add doc * ultradns_dirpool: fix rdata.geo_codes.codes to be idempotent * ultradns_dirpool: add doc * ultradns: cleanup testing * ultradns_record: rename resource * ultradns: log username from config, not client udnssdk.Client is being refactored to use x/oauth2, so don't assume we can access Username from it * ultradns_probe_ping: add * ultradns_probe_http: add * doc: add ultradns_probe_ping * doc: add ultradns_probe_http * ultradns_record: remove duplication from error messages * doc: cleanup typos in ultradns * ultradns_probe_ping: add test for pool-level probe * Clean documentation * ultradns: pull makeSetFromStrings() up to common.go * ultradns_dirpool: log hashIPInfoIPs Log the key and generated hashcode used to index ip_info.ips into a set. * ultradns: simplify hashLimits() Limits blocks only have the "name" attribute as their primary key, so hashLimits() needn't use a buffer to concatenate. Also changes log level to a more approriate DEBUG. * ultradns_tcpool: convert rdata to schema.Set RData blocks have the "host" attribute as their primary key, so it is used by hashRdatas() to create the hashcode. Tests are updated to use the new hashcode indexes instead of natural numbers. * ultradns_probe_http: convert agents to schema.Set Also pull the makeSetFromStrings() helper up to common.go * ultradns: pull hashRdatas() up to common * ultradns_dirpool: convert rdata to schema.Set Fixes TF-66 * ultradns_dirpool.conflict_resolve: fix default from response UltraDNS REST API User Guide claims that "Directional Pool Profile Fields" have a "conflictResolve" field which "If not specified, defaults to GEO." https://portal.ultradns.com/static/docs/REST-API_User_Guide.pdf But UltraDNS does not actually return a conflictResolve attribute when it has been updated to "GEO". We could fix it in udnssdk, but that would require either: * hide the response by coercing "" to "GEO" for everyone * use a pointer to allow checking for nil (requires all users to change if they fix this) An ideal solution would be to have the UltraDNS API respond with this attribute for every dirpool's rdata. So at the risk of foolish consistency in the sdk, we're going to solve it where it's visible to the user: by checking and overriding the parsing. I'm sorry. * ultradns_record: convert rdata to set UltraDNS does not store the ordering of rdata elements, so we need a way to identify if changes have been made even it the order changes. A perfect job for schema.Set. * ultradns_record: parse double-encoded answers for TXT records * ultradns: simplify hashLimits() Limits blocks only have the "name" attribute as their primary key, so hashLimits() needn't use a buffer to concatenate. * ultradns_dirpool.description: validate * ultradns_dirpool.rdata: doc need for set * ultradns_dirpool.conflict_resolve: validate
308 lines
10 KiB
Go
308 lines
10 KiB
Go
package udnssdk
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
"time"
|
|
)
|
|
|
|
// DirectionalPoolsService manages 'account level' 'geo' and 'ip' groups for directional-pools
|
|
type DirectionalPoolsService struct {
|
|
client *Client
|
|
}
|
|
|
|
// DirectionalPool wraps an account-level directional-groups response from a index request
|
|
type DirectionalPool struct {
|
|
DirectionalPoolID string `json:"taskId"`
|
|
DirectionalPoolStatusCode string `json:"taskStatusCode"`
|
|
Message string `json:"message"`
|
|
ResultURI string `json:"resultUri"`
|
|
}
|
|
|
|
// AccountLevelGeoDirectionalGroupDTO wraps an account-level, geo directonal-group response
|
|
type AccountLevelGeoDirectionalGroupDTO struct {
|
|
Name string `json:"name"`
|
|
Description string `json:"description"`
|
|
Codes []string `json:"codes"`
|
|
}
|
|
|
|
// IPAddrDTO wraps an IP address range or CIDR block
|
|
type IPAddrDTO struct {
|
|
Start string `json:"start,omitempty" terraform:"start"`
|
|
End string `json:"end,omitempty" terraform:"end"`
|
|
CIDR string `json:"cidr,omitempty" terraform:"cidr"`
|
|
Address string `json:"address,omitempty" terraform:"address"`
|
|
}
|
|
|
|
// AccountLevelIPDirectionalGroupDTO wraps an account-level, IP directional-group response
|
|
type AccountLevelIPDirectionalGroupDTO struct {
|
|
Name string `json:"name"`
|
|
Description string `json:"description"`
|
|
IPs []IPAddrDTO `json:"ips"`
|
|
}
|
|
|
|
// DirectionalPoolListDTO wraps a list of account-level directional-groups response from a index request
|
|
type DirectionalPoolListDTO struct {
|
|
DirectionalPools []DirectionalPool `json:"tasks"`
|
|
Queryinfo QueryInfo `json:"queryInfo"`
|
|
Resultinfo ResultInfo `json:"resultInfo"`
|
|
}
|
|
|
|
// AccountLevelGeoDirectionalGroupListDTO wraps a list of account-level, geo directional-groups response from a index request
|
|
type AccountLevelGeoDirectionalGroupListDTO struct {
|
|
AccountName string `json:"zoneName"`
|
|
GeoGroups []AccountLevelGeoDirectionalGroupDTO `json:"geoGroups"`
|
|
Queryinfo QueryInfo `json:"queryInfo"`
|
|
Resultinfo ResultInfo `json:"resultInfo"`
|
|
}
|
|
|
|
// AccountLevelIPDirectionalGroupListDTO wraps an account-level, IP directional-group response
|
|
type AccountLevelIPDirectionalGroupListDTO struct {
|
|
AccountName string `json:"zoneName"`
|
|
IPGroups []AccountLevelIPDirectionalGroupDTO `json:"ipGroups"`
|
|
Queryinfo QueryInfo `json:"queryInfo"`
|
|
Resultinfo ResultInfo `json:"resultInfo"`
|
|
}
|
|
|
|
// Geos allows access to the Geo DirectionalPools API
|
|
func (s *DirectionalPoolsService) Geos() *GeoDirectionalPoolsService {
|
|
return &GeoDirectionalPoolsService{client: s.client}
|
|
}
|
|
|
|
// IPs allows access to the IP DirectionalPools API
|
|
func (s *DirectionalPoolsService) IPs() *IPDirectionalPoolsService {
|
|
return &IPDirectionalPoolsService{client: s.client}
|
|
}
|
|
|
|
// DirectionalPoolKey collects the identifiers of a DirectionalPool
|
|
type DirectionalPoolKey struct {
|
|
Account AccountKey
|
|
Type string
|
|
Name string
|
|
}
|
|
|
|
// URI generates the URI for directional pools by account, type & slug ID
|
|
func (k DirectionalPoolKey) URI() string {
|
|
if k.Name == "" {
|
|
return fmt.Sprintf("%s/dirgroups/%s", k.Account.URI(), k.Type)
|
|
}
|
|
return fmt.Sprintf("%s/dirgroups/%s/%s", k.Account.URI(), k.Type, k.Name)
|
|
}
|
|
|
|
// QueryURI generates the URI for directional pools by account, type, query & offset
|
|
func (k DirectionalPoolKey) QueryURI(query string, offset int) string {
|
|
uri := k.URI()
|
|
|
|
if query != "" {
|
|
uri = fmt.Sprintf("%s?sort=NAME&query=%s&offset=%d", uri, query, offset)
|
|
} else {
|
|
uri = fmt.Sprintf("%s?offset=%d", uri, offset)
|
|
}
|
|
|
|
return uri
|
|
}
|
|
|
|
// GeoDirectionalPoolKey collects the identifiers of an DirectionalPool with type Geo
|
|
type GeoDirectionalPoolKey struct {
|
|
Account AccountKey
|
|
Name string
|
|
}
|
|
|
|
// DirectionalPoolKey generates the DirectionalPoolKey for the GeoDirectionalPoolKey
|
|
func (k GeoDirectionalPoolKey) DirectionalPoolKey() DirectionalPoolKey {
|
|
return DirectionalPoolKey{
|
|
Account: k.Account,
|
|
Type: "geo",
|
|
Name: k.Name,
|
|
}
|
|
}
|
|
|
|
// URI generates the URI for a GeoDirectionalPool
|
|
func (k GeoDirectionalPoolKey) URI() string {
|
|
return k.DirectionalPoolKey().URI()
|
|
}
|
|
|
|
// QueryURI generates the GeoDirectionalPool URI with query
|
|
func (k GeoDirectionalPoolKey) QueryURI(query string, offset int) string {
|
|
return k.DirectionalPoolKey().QueryURI(query, offset)
|
|
}
|
|
|
|
// GeoDirectionalPoolsService manages 'geo' groups for directional-pools
|
|
type GeoDirectionalPoolsService struct {
|
|
client *Client
|
|
}
|
|
|
|
// Select requests all geo directional-pools, by query and account, providing pagination and error handling
|
|
func (s *GeoDirectionalPoolsService) Select(k GeoDirectionalPoolKey, query string) ([]AccountLevelGeoDirectionalGroupDTO, error) {
|
|
// TODO: Sane Configuration for timeouts / retries
|
|
maxerrs := 5
|
|
waittime := 5 * time.Second
|
|
|
|
// init accumulators
|
|
dtos := []AccountLevelGeoDirectionalGroupDTO{}
|
|
errcnt := 0
|
|
offset := 0
|
|
|
|
for {
|
|
reqDtos, ri, res, err := s.SelectWithOffset(k, query, offset)
|
|
if err != nil {
|
|
if res != nil && res.StatusCode >= 500 {
|
|
errcnt = errcnt + 1
|
|
if errcnt < maxerrs {
|
|
time.Sleep(waittime)
|
|
continue
|
|
}
|
|
}
|
|
return dtos, err
|
|
}
|
|
|
|
log.Printf("[DEBUG] ResultInfo: %+v\n", ri)
|
|
for _, d := range reqDtos {
|
|
dtos = append(dtos, d)
|
|
}
|
|
if ri.ReturnedCount+ri.Offset >= ri.TotalCount {
|
|
return dtos, nil
|
|
}
|
|
offset = ri.ReturnedCount + ri.Offset
|
|
continue
|
|
}
|
|
}
|
|
|
|
// SelectWithOffset requests list of geo directional-pools, by query & account, and an offset, returning the directional-group, the list-metadata, the actual response, or an error
|
|
func (s *GeoDirectionalPoolsService) SelectWithOffset(k GeoDirectionalPoolKey, query string, offset int) ([]AccountLevelGeoDirectionalGroupDTO, ResultInfo, *http.Response, error) {
|
|
var tld AccountLevelGeoDirectionalGroupListDTO
|
|
|
|
res, err := s.client.get(k.QueryURI(query, offset), &tld)
|
|
|
|
pis := []AccountLevelGeoDirectionalGroupDTO{}
|
|
for _, pi := range tld.GeoGroups {
|
|
pis = append(pis, pi)
|
|
}
|
|
return pis, tld.Resultinfo, res, err
|
|
}
|
|
|
|
// Find requests a geo directional-pool by name & account
|
|
func (s *GeoDirectionalPoolsService) Find(k GeoDirectionalPoolKey) (AccountLevelGeoDirectionalGroupDTO, *http.Response, error) {
|
|
var t AccountLevelGeoDirectionalGroupDTO
|
|
res, err := s.client.get(k.URI(), &t)
|
|
return t, res, err
|
|
}
|
|
|
|
// Create requests creation of a DirectionalPool by DirectionalPoolKey given a directional-pool
|
|
func (s *GeoDirectionalPoolsService) Create(k GeoDirectionalPoolKey, val interface{}) (*http.Response, error) {
|
|
return s.client.post(k.URI(), val, nil)
|
|
}
|
|
|
|
// Update requests update of a DirectionalPool by DirectionalPoolKey given a directional-pool
|
|
func (s *GeoDirectionalPoolsService) Update(k GeoDirectionalPoolKey, val interface{}) (*http.Response, error) {
|
|
return s.client.put(k.URI(), val, nil)
|
|
}
|
|
|
|
// Delete requests deletion of a DirectionalPool
|
|
func (s *GeoDirectionalPoolsService) Delete(k GeoDirectionalPoolKey) (*http.Response, error) {
|
|
return s.client.delete(k.URI(), nil)
|
|
}
|
|
|
|
// IPDirectionalPoolKey collects the identifiers of an DirectionalPool with type IP
|
|
type IPDirectionalPoolKey struct {
|
|
Account AccountKey
|
|
Name string
|
|
}
|
|
|
|
// DirectionalPoolKey generates the DirectionalPoolKey for the IPDirectionalPoolKey
|
|
func (k IPDirectionalPoolKey) DirectionalPoolKey() DirectionalPoolKey {
|
|
return DirectionalPoolKey{
|
|
Account: k.Account,
|
|
Type: "ip",
|
|
Name: k.Name,
|
|
}
|
|
}
|
|
|
|
// URI generates the IPDirectionalPool query URI
|
|
func (k IPDirectionalPoolKey) URI() string {
|
|
return k.DirectionalPoolKey().URI()
|
|
}
|
|
|
|
// QueryURI generates the IPDirectionalPool URI with query
|
|
func (k IPDirectionalPoolKey) QueryURI(query string, offset int) string {
|
|
return k.DirectionalPoolKey().QueryURI(query, offset)
|
|
}
|
|
|
|
// IPDirectionalPoolsService manages 'geo' groups for directional-pools
|
|
type IPDirectionalPoolsService struct {
|
|
client *Client
|
|
}
|
|
|
|
// Select requests all IP directional-pools, using pagination and error handling
|
|
func (s *IPDirectionalPoolsService) Select(k IPDirectionalPoolKey, query string) ([]AccountLevelIPDirectionalGroupDTO, error) {
|
|
// TODO: Sane Configuration for timeouts / retries
|
|
maxerrs := 5
|
|
waittime := 5 * time.Second
|
|
|
|
// init accumulators
|
|
gs := []AccountLevelIPDirectionalGroupDTO{}
|
|
errcnt := 0
|
|
offset := 0
|
|
|
|
for {
|
|
reqIPGroups, ri, res, err := s.SelectWithOffset(k, query, offset)
|
|
if err != nil {
|
|
if res != nil && res.StatusCode >= 500 {
|
|
errcnt = errcnt + 1
|
|
if errcnt < maxerrs {
|
|
time.Sleep(waittime)
|
|
continue
|
|
}
|
|
}
|
|
return gs, err
|
|
}
|
|
|
|
log.Printf("ResultInfo: %+v\n", ri)
|
|
for _, g := range reqIPGroups {
|
|
gs = append(gs, g)
|
|
}
|
|
if ri.ReturnedCount+ri.Offset >= ri.TotalCount {
|
|
return gs, nil
|
|
}
|
|
offset = ri.ReturnedCount + ri.Offset
|
|
continue
|
|
}
|
|
}
|
|
|
|
// SelectWithOffset requests all IP directional-pools, by query & account, and an offset, returning the list of IP groups, list metadata & the actual response, or an error
|
|
func (s *IPDirectionalPoolsService) SelectWithOffset(k IPDirectionalPoolKey, query string, offset int) ([]AccountLevelIPDirectionalGroupDTO, ResultInfo, *http.Response, error) {
|
|
var tld AccountLevelIPDirectionalGroupListDTO
|
|
|
|
res, err := s.client.get(k.QueryURI(query, offset), &tld)
|
|
|
|
pis := []AccountLevelIPDirectionalGroupDTO{}
|
|
for _, pi := range tld.IPGroups {
|
|
pis = append(pis, pi)
|
|
}
|
|
|
|
return pis, tld.Resultinfo, res, err
|
|
}
|
|
|
|
// Find requests a directional-pool by name & account
|
|
func (s *IPDirectionalPoolsService) Find(k IPDirectionalPoolKey) (AccountLevelIPDirectionalGroupDTO, *http.Response, error) {
|
|
var t AccountLevelIPDirectionalGroupDTO
|
|
res, err := s.client.get(k.URI(), &t)
|
|
return t, res, err
|
|
}
|
|
|
|
// Create requests creation of a DirectionalPool by DirectionalPoolKey given a directional-pool
|
|
func (s *IPDirectionalPoolsService) Create(k IPDirectionalPoolKey, val interface{}) (*http.Response, error) {
|
|
return s.client.post(k.URI(), val, nil)
|
|
}
|
|
|
|
// Update requests update of a DirectionalPool by DirectionalPoolKey given a directional-pool
|
|
func (s *IPDirectionalPoolsService) Update(k IPDirectionalPoolKey, val interface{}) (*http.Response, error) {
|
|
return s.client.put(k.URI(), val, nil)
|
|
}
|
|
|
|
// Delete deletes an directional-pool
|
|
func (s *IPDirectionalPoolsService) Delete(k IPDirectionalPoolKey) (*http.Response, error) {
|
|
return s.client.delete(k.URI(), nil)
|
|
}
|