mirror of
https://github.com/psviderski/uncloud.git
synced 2026-08-28 03:53:33 +00:00
feat(dns): client for creating ingress records
This commit is contained in:
@@ -0,0 +1,33 @@
|
|||||||
|
package client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"uncloud/internal/machine/api/pb"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
func (cli *Client) CreateIngressRecords(ctx context.Context, serviceID string) ([]*pb.DNSRecord, error) {
|
||||||
|
// TODO:
|
||||||
|
// - Inspect the service and get the list of machines it runs on.
|
||||||
|
// - For each machine get the machine's public IP address(s).
|
||||||
|
// - Update the wildcard DNS record for the service with the public IP addresses (call Cluster API).
|
||||||
|
|
||||||
|
req := &pb.CreateDomainRecordsRequest{
|
||||||
|
Records: []*pb.DNSRecord{
|
||||||
|
{
|
||||||
|
Name: "*",
|
||||||
|
Type: pb.DNSRecord_A,
|
||||||
|
// TODO: Get the public IP addresses of the machines running Caddy containers.
|
||||||
|
Values: []string{"1.2.3.4", "5.6.7.8"},
|
||||||
|
},
|
||||||
|
// TODO: Add AAAA record with routable IPv6 addresses of machines running Caddy containers.
|
||||||
|
},
|
||||||
|
}
|
||||||
|
resp, err := cli.CreateDomainRecords(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("create cluster domain records in Uncloud DNS: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp.Records, nil
|
||||||
|
}
|
||||||
@@ -1,10 +1,28 @@
|
|||||||
package dns
|
package dns
|
||||||
|
|
||||||
|
const (
|
||||||
|
RecordTypeA RecordType = "A"
|
||||||
|
RecordTypeAAAA RecordType = "AAAA"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RecordType string
|
||||||
|
|
||||||
type DomainResponse struct {
|
type DomainResponse struct {
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
Token string `json:"token,omitempty"`
|
Token string `json:"token,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RecordRequest struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Type RecordType `json:"type,omitempty"`
|
||||||
|
Values []string `json:"values,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RecordResponse struct {
|
||||||
|
RecordRequest
|
||||||
|
FQDN string `json:"fqdn,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
type AuthErrorResponse struct {
|
type AuthErrorResponse struct {
|
||||||
Status int `json:"status,omitempty"`
|
Status int `json:"status,omitempty"`
|
||||||
Message string `json:"msg,omitempty"`
|
Message string `json:"msg,omitempty"`
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package dns
|
package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -17,6 +18,10 @@ type Client interface {
|
|||||||
// ReserveDomain calls Uncloud DNS to reserve a new domain. It returns the domain, a token for authentication,
|
// ReserveDomain calls Uncloud DNS to reserve a new domain. It returns the domain, a token for authentication,
|
||||||
// and an error.
|
// and an error.
|
||||||
ReserveDomain(endpoint string) (string, string, error)
|
ReserveDomain(endpoint string) (string, string, error)
|
||||||
|
|
||||||
|
// CreateRecords calls Uncloud DNS to create or update DNS records based on the supplied RecordRequests
|
||||||
|
// for the specified domain.
|
||||||
|
CreateRecords(endpoint, domain, token string, records []RecordRequest) ([]RecordResponse, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrAuthNoDomain indicates that a request failed authentication because the domain was not found.
|
// ErrAuthNoDomain indicates that a request failed authentication because the domain was not found.
|
||||||
@@ -55,6 +60,35 @@ func (c *client) ReserveDomain(endpoint string) (string, string, error) {
|
|||||||
return domain, resp.Token, nil
|
return domain, resp.Token, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *client) CreateRecords(endpoint, domain, token string, records []RecordRequest) ([]RecordResponse, error) {
|
||||||
|
// TODO: update Uncloud DNS service to not use a leading dot for domain names.
|
||||||
|
if !strings.HasPrefix(domain, ".") {
|
||||||
|
domain = "." + domain
|
||||||
|
}
|
||||||
|
url := fmt.Sprintf("%s/domains/%s/records", endpoint, domain)
|
||||||
|
|
||||||
|
var resp []RecordResponse
|
||||||
|
for _, recordRequest := range records {
|
||||||
|
body, err := jsonBody(recordRequest)
|
||||||
|
if err != nil {
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := c.request(http.MethodPost, url, body, token)
|
||||||
|
if err != nil {
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var recordResp RecordResponse
|
||||||
|
if err = c.do(req, &recordResp); err != nil {
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
resp = append(resp, recordResp)
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *client) request(method string, url string, body io.Reader, token string) (*http.Request, error) {
|
func (c *client) request(method string, url string, body io.Reader, token string) (*http.Request, error) {
|
||||||
req, err := http.NewRequest(method, url, body)
|
req, err := http.NewRequest(method, url, body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -116,3 +150,12 @@ func (c *client) do(req *http.Request, responseBody any) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func jsonBody(payload any) (io.Reader, error) {
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
err := json.NewEncoder(buf).Encode(payload)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return buf, nil
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user