opentofu/vendor/github.com/Ensighten/udnssdk/directional_pool.go
Joseph Anthony Pasquale Holsten d783e831f8 ultradns providers and improvements (#9788)
* 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
2016-12-15 16:28:34 +00:00

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