Skip to content

Commit

Permalink
Merge branch 'main' into cdtool-966-followup
Browse files Browse the repository at this point in the history
  • Loading branch information
kpfleming authored Jan 20, 2025
2 parents 7d432c5 + b2b646e commit 6f4fcf6
Show file tree
Hide file tree
Showing 16 changed files with 605 additions and 2 deletions.
3 changes: 3 additions & 0 deletions fastly/domains/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Package domains contains subpackages which offer various operations to
// enable, disable, and configure Fastly domains
package domains
33 changes: 33 additions & 0 deletions fastly/domains/v1/api_create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package v1

import (
"encoding/json"
"fmt"

"github.com/fastly/go-fastly/v9/fastly"
)

// CreateInput specifies the information needed for the Create() function to
// perform the operation.
type CreateInput struct {
// FQDN is the fully-qualified domain name of the domain (required).
FQDN *string `json:"fqdn"`
// ServiceID is the service_id associated with the domain or nil if there
// is no association (optional)
ServiceID *string `json:"service_id"`
}

// Create creates a new domain.
func Create(c *fastly.Client, i *CreateInput) (*Data, error) {
resp, err := c.PostJSON("/domains/v1", i, nil)
if err != nil {
return nil, err
}
defer resp.Body.Close()

var d *Data
if err := json.NewDecoder(resp.Body).Decode(&d); err != nil {
return nil, fmt.Errorf("failed to decode json response: %w", err)
}
return d, nil
}
35 changes: 35 additions & 0 deletions fastly/domains/v1/api_delete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package v1

import (
"net/http"

"github.com/fastly/go-fastly/v9/fastly"
)

// DeleteInput specifies the information needed for the Delete() function to
// perform the operation.
type DeleteInput struct {
// DomainID of the domain to delete (required).
DomainID *string
}

// Delete deletes the specified domain.
func Delete(c *fastly.Client, i *DeleteInput) error {
if i.DomainID == nil {
return fastly.ErrMissingDomainID
}

path := fastly.ToSafeURL("domains", "v1", *i.DomainID)

resp, err := c.Delete(path, nil)
if err != nil {
return err
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusNoContent {
return fastly.NewHTTPError(resp)
}

return nil
}
37 changes: 37 additions & 0 deletions fastly/domains/v1/api_get.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package v1

import (
"encoding/json"
"fmt"

"github.com/fastly/go-fastly/v9/fastly"
)

// GetInput specifies the information needed for the Get() function to perform
// the operation.
type GetInput struct {
// DomainID is the domain identifier (required).
DomainID *string
}

// Get retrieves a specified domain.
func Get(c *fastly.Client, i *GetInput) (*Data, error) {
if i.DomainID == nil {
return nil, fastly.ErrMissingDomainID
}

path := fastly.ToSafeURL("domains", "v1", *i.DomainID)

resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
defer resp.Body.Close()

var d *Data
if err := json.NewDecoder(resp.Body).Decode(&d); err != nil {
return nil, fmt.Errorf("failed to decode json response: %w", err)
}

return d, nil
}
61 changes: 61 additions & 0 deletions fastly/domains/v1/api_list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package v1

import (
"encoding/json"
"fmt"
"strconv"

"github.com/fastly/go-fastly/v9/fastly"
)

// ListInput specifies the information needed for the List() function to perform
// the operation.
type ListInput struct {
// Cursor is the cursor value from the next_cursor field of a previous
// response, used to retrieve the next page. To request the first page, this
// should be an empty string or nil.
Cursor *string
// FQDN filters results by the FQDN using a fuzzy/partial match (optional).
FQDN *string
// Limit is the maximum number of results to return (optional).
Limit *int
// ServiceID filter results based on a service_id (optional).
ServiceID *string
// Sort is the order in which to list the results (optional).
Sort *string
}

// List retrieves a list of domains, with optional filtering and pagination.
func List(c *fastly.Client, i *ListInput) (*Collection, error) {
ro := &fastly.RequestOptions{
Params: map[string]string{},
}
if i.Cursor != nil {
ro.Params["cursor"] = *i.Cursor
}
if i.Limit != nil {
ro.Params["limit"] = strconv.Itoa(*i.Limit)
}
if i.FQDN != nil {
ro.Params["fqdn"] = *i.FQDN
}
if i.ServiceID != nil {
ro.Params["service_id"] = *i.ServiceID
}
if i.Sort != nil {
ro.Params["sort"] = *i.Sort
}

resp, err := c.Get("/domains/v1", ro)
if err != nil {
return nil, err
}
defer resp.Body.Close()

var cl *Collection
if err := json.NewDecoder(resp.Body).Decode(&cl); err != nil {
return nil, fmt.Errorf("failed to decode json response: %w", err)
}

return cl, nil
}
43 changes: 43 additions & 0 deletions fastly/domains/v1/api_response.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package v1

import (
"time"
)

// Collection is the API response structure for the list operation.
type Collection struct {
// Data contains the API data.
Data []Data `json:"data"`
// Meta contains metadata related to paginating the full dataset.
Meta Meta `json:"meta"`
}

// Data is a subset of the API response structure containing the specific API
// data itself.
type Data struct {
// CreatedAt is the date and time in ISO 8601 format.
CreatedAt time.Time `json:"created_at"`
// ID is the domain identifier (UUID).
DomainID string `json:"id"`
// FQDN is the fully-qualified domain name of the domain. Read-only
// after creation.
FQDN string `json:"fqdn"`
// ServiceID is the service_id associated with the domain or nil if there
// is no association.
ServiceID *string `json:"service_id"`
// UpdatedAt is the date and time in ISO 8601 format.
UpdatedAt time.Time `json:"updated_at"`
}

// Meta is a subset of the API response structure containing metadata related to
// paginating the full dataset.
type Meta struct {
// Limit is how many results are included in this response.
Limit int `json:"limit"`
// NextCursor is the cursor value used to retrieve the next page.
NextCursor string `json:"next_cursor"`
// Sort is the field used to order the response by.
Sort string `json:"sort"`
// Total is the total number of results.
Total int `json:"total"`
}
116 changes: 116 additions & 0 deletions fastly/domains/v1/api_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package v1

import (
"errors"
"testing"

"github.com/fastly/go-fastly/v9/fastly"
)

func TestClient_Domain(t *testing.T) {
t.Parallel()

var err error
fqdn := "fastly-sdk-gofastly-testing.com"

// Create
var d *Data
fastly.Record(t, "create", func(c *fastly.Client) {
d, err = Create(c, &CreateInput{
FQDN: fastly.ToPointer(fqdn),
})
})
if err != nil {
t.Fatal(err)
}
if d.FQDN != fqdn {
t.Errorf("bad fqdn: %v", d.FQDN)
}
if d.ServiceID != nil {
t.Errorf("bad service_id: %v", d.ServiceID)
}

// List Definitions
var cl *Collection
fastly.Record(t, "list", func(c *fastly.Client) {
cl, err = List(c, &ListInput{
Limit: fastly.ToPointer(10),
FQDN: fastly.ToPointer(d.FQDN),
Sort: fastly.ToPointer("fqdn"),
})
})
if err != nil {
t.Fatal(err)
}
if len(cl.Data) < 1 {
t.Errorf("bad domains list: %v", cl)
}

// Get
var gd *Data
fastly.Record(t, "get", func(c *fastly.Client) {
gd, err = Get(c, &GetInput{
DomainID: &d.DomainID,
})
})
if err != nil {
t.Fatal(err)
}
if d.FQDN != gd.FQDN {
t.Errorf("bad fqdn: %q (%q)", d.FQDN, gd.FQDN)
}

// Update
var ud *Data
fastly.Record(t, "update", func(c *fastly.Client) {
ud, err = Update(c, &UpdateInput{
DomainID: fastly.ToPointer(d.DomainID),
ServiceID: fastly.ToPointer(fastly.DefaultDeliveryTestServiceID),
})
})
if err != nil {
t.Fatal(err)
}
if ud.ServiceID == nil || *ud.ServiceID != fastly.DefaultDeliveryTestServiceID {
t.Errorf("bad service id: %v", ud.ServiceID)
}

// Delete
fastly.Record(t, "delete", func(c *fastly.Client) {
err = Delete(c, &DeleteInput{
DomainID: &d.DomainID,
})
})
if err != nil {
t.Fatal(err)
}
}

func TestClient_GetDomain_validation(t *testing.T) {
var err error
_, err = Get(fastly.TestClient, &GetInput{
DomainID: nil,
})
if !errors.Is(err, fastly.ErrMissingDomainID) {
t.Errorf("bad error: %s", err)
}
}

func TestClient_UpdateDomain_validation(t *testing.T) {
var err error
_, err = Update(fastly.TestClient, &UpdateInput{
DomainID: nil,
})
if !errors.Is(err, fastly.ErrMissingDomainID) {
t.Errorf("bad error: %s", err)
}
}

func TestClient_DeleteDomain_validation(t *testing.T) {
err := Delete(fastly.TestClient, &DeleteInput{
DomainID: nil,
})
if !errors.Is(err, fastly.ErrMissingDomainID) {
t.Errorf("bad error: %s", err)
}
}
39 changes: 39 additions & 0 deletions fastly/domains/v1/api_update.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package v1

import (
"encoding/json"
"fmt"

"github.com/fastly/go-fastly/v9/fastly"
)

// UpdateInput specifies the information needed for the Update() function to
// perform the operation.
type UpdateInput struct {
// DomainID is the domain identifier (required).
DomainID *string `json:"-"`
// ServiceID is the service_id associated with the domain or nil if there
// is no association (optional)
ServiceID *string `json:"service_id"`
}

// Update updates the specified domain.
func Update(c *fastly.Client, i *UpdateInput) (*Data, error) {
if i.DomainID == nil {
return nil, fastly.ErrMissingDomainID
}

path := fastly.ToSafeURL("domains", "v1", *i.DomainID)

resp, err := c.PatchJSON(path, i, nil)
if err != nil {
return nil, err
}
defer resp.Body.Close()

var d *Data
if err := json.NewDecoder(resp.Body).Decode(&d); err != nil {
return nil, fmt.Errorf("failed to decode json response: %w", err)
}
return d, nil
}
3 changes: 3 additions & 0 deletions fastly/domains/v1/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Package v1 contains functionality which offer various operations to enable,
// disable, and configure Fastly domains using its v1 implementation.
package v1
Loading

0 comments on commit 6f4fcf6

Please sign in to comment.