lego/providers/dns/vkcloud/internal/client.go
2023-02-09 16:19:58 +00:00

140 lines
3 KiB
Go

package internal
import (
"errors"
"fmt"
"net/http"
"net/url"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack"
)
// Client VK client.
type Client struct {
baseURL *url.URL
openstack *gophercloud.ProviderClient
authOpts gophercloud.AuthOptions
authenticated bool
}
// NewClient creates a Client.
func NewClient(endpoint string, authOpts gophercloud.AuthOptions) (*Client, error) {
err := validateAuthOptions(authOpts)
if err != nil {
return nil, err
}
openstackClient, err := openstack.NewClient(authOpts.IdentityEndpoint)
if err != nil {
return nil, fmt.Errorf("new client: %w", err)
}
baseURL, err := url.Parse(endpoint)
if err != nil {
return nil, fmt.Errorf("parse URL: %w", err)
}
return &Client{
baseURL: baseURL,
openstack: openstackClient,
authOpts: authOpts,
}, nil
}
func (c *Client) ListZones() ([]DNSZone, error) {
var zones []DNSZone
opts := &gophercloud.RequestOpts{JSONResponse: &zones}
endpoint := c.baseURL.JoinPath("/")
err := c.request(http.MethodGet, endpoint, opts)
if err != nil {
return nil, err
}
return zones, nil
}
func (c *Client) ListTXTRecords(zoneUUID string) ([]DNSTXTRecord, error) {
var records []DNSTXTRecord
opts := &gophercloud.RequestOpts{JSONResponse: &records}
endpoint := c.baseURL.JoinPath(zoneUUID, "txt", "/")
err := c.request(http.MethodGet, endpoint, opts)
if err != nil {
return nil, err
}
return records, nil
}
func (c *Client) CreateTXTRecord(zoneUUID string, record *DNSTXTRecord) error {
opts := &gophercloud.RequestOpts{
JSONBody: record,
JSONResponse: record,
}
endpoint := c.baseURL.JoinPath(zoneUUID, "txt", "/")
return c.request(http.MethodPost, endpoint, opts)
}
func (c *Client) DeleteTXTRecord(zoneUUID, recordUUID string) error {
endpoint := c.baseURL.JoinPath(zoneUUID, "txt", recordUUID)
return c.request(http.MethodDelete, endpoint, &gophercloud.RequestOpts{})
}
func (c *Client) request(method string, endpoint *url.URL, options *gophercloud.RequestOpts) error {
if err := c.lazyAuth(); err != nil {
return fmt.Errorf("auth: %w", err)
}
_, err := c.openstack.Request(method, endpoint.String(), options)
if err != nil {
return fmt.Errorf("request: %w", err)
}
return nil
}
func (c *Client) lazyAuth() error {
if c.authenticated {
return nil
}
err := openstack.Authenticate(c.openstack, c.authOpts)
if err != nil {
return err
}
c.authenticated = true
return nil
}
func validateAuthOptions(opts gophercloud.AuthOptions) error {
if opts.TenantID == "" {
return errors.New("project id is missing in credentials information")
}
if opts.Username == "" {
return errors.New("username is missing in credentials information")
}
if opts.Password == "" {
return errors.New("password is missing in credentials information")
}
if opts.IdentityEndpoint == "" {
return errors.New("identity endpoint is missing in config")
}
if opts.DomainName == "" {
return errors.New("domain name is missing in config")
}
return nil
}