Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: create datadome_endpoint resource #31

Merged
merged 9 commits into from
Jan 15, 2025
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ test:
echo $(TEST) | xargs -t -n4 go test $(TESTARGS) -timeout=30s -parallel=4

testacc:
TF_ACC=1 go test $(TEST) -v $(TESTARGS) -timeout 120m
TF_ACC=1 go test $(TEST) -v $(TESTARGS) -timeout=1m

clean:
rm -rf ./dist/
8 changes: 4 additions & 4 deletions common/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ package common
import "context"

// API interface
type API[T any] interface {
Create(ctx context.Context, params T) (*int, error)
Read(ctx context.Context) ([]T, error)
type API[T any, I comparable] interface {
Create(ctx context.Context, params T) (*I, error)
Read(ctx context.Context, id I) (*T, error)
laurodd marked this conversation as resolved.
Show resolved Hide resolved
Update(ctx context.Context, params T) (*T, error)
Delete(ctx context.Context, id int) error
Delete(ctx context.Context, id I) error
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,21 @@ import (
"time"
)

// HOST_URL default datadome dashboard URL
const HOST_URL string = "https://customer-api.datadome.co/1.1/protection"
// HostURLCustomRule default datadome dashboard URL
const HostURLCustomRule string = "https://customer-api.datadome.co/1.1/protection/custom-rules"

// Client to perform request on DataDome's API
type Client struct {
// ClientCustomRule to perform request on DataDome's API
type ClientCustomRule struct {
HostURL string
HTTPClient *http.Client
Token string
}

// NewClient is instantiate with given host and password parameters
func NewClient(host, password *string) (*Client, error) {
c := Client{
// NewClientCustomRules is instantiate with given host and password parameters
lriberon marked this conversation as resolved.
Show resolved Hide resolved
func NewClientCustomRules(host, password *string) (*ClientCustomRule, error) {
lriberon marked this conversation as resolved.
Show resolved Hide resolved
c := ClientCustomRule{
HTTPClient: &http.Client{Timeout: 10 * time.Second},
HostURL: HOST_URL,
HostURL: HostURLCustomRule,
}

if host != nil {
Expand All @@ -40,7 +40,7 @@ func NewClient(host, password *string) (*Client, error) {
}

// doRequest on the DataDome API with given http.Request and HttpResponse
func (c *Client) doRequest(req *http.Request, httpResponse *HttpResponse) (*HttpResponse, error) {
func (c *ClientCustomRule) doRequest(req *http.Request, httpResponse *HttpResponse) (*HttpResponse, error) {
// Add apikey as a header on each request for authentication
// Add also withoutTraffic parameter to true to have better performances
q := req.URL.Query()
Expand Down Expand Up @@ -75,16 +75,16 @@ func (c *Client) doRequest(req *http.Request, httpResponse *HttpResponse) (*Http
return nil, err
}

if httpResponse.Status != 200 {
if httpResponse.Status < 200 || httpResponse.Status > 299 {
return nil, fmt.Errorf("status: %d, body: %s", res.StatusCode, httpResponse.Errors)
}

return httpResponse, err
}

// Read custom rule list from the API management
func (c *Client) Read(ctx context.Context) ([]CustomRule, error) {
req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("%s/custom-rules", c.HostURL), nil)
func (c *ClientCustomRule) Read(ctx context.Context, id int) (*CustomRule, error) {
req, err := http.NewRequestWithContext(ctx, "GET", c.HostURL, nil)
if err != nil {
return nil, err
}
Expand All @@ -100,11 +100,18 @@ func (c *Client) Read(ctx context.Context) ([]CustomRule, error) {
return nil, fmt.Errorf("response status is %d", resp.Status)
}

return customRules.CustomRules, nil
customRule := &CustomRule{}
for _, v := range customRules.CustomRules {
if *v.ID == id {
customRule = &v
}
}

return customRule, nil
}

// Create custom rule with given CustomRule parameters
func (c *Client) Create(ctx context.Context, params CustomRule) (*int, error) {
func (c *ClientCustomRule) Create(ctx context.Context, params CustomRule) (*int, error) {
reqBody := HttpRequest{
Data: params,
}
Expand All @@ -116,7 +123,7 @@ func (c *Client) Create(ctx context.Context, params CustomRule) (*int, error) {
req, err := http.NewRequestWithContext(
ctx,
"POST",
fmt.Sprintf("%s/custom-rules", c.HostURL),
c.HostURL,
laurodd marked this conversation as resolved.
Show resolved Hide resolved
strings.NewReader(string(rb)),
)
if err != nil {
Expand All @@ -138,7 +145,7 @@ func (c *Client) Create(ctx context.Context, params CustomRule) (*int, error) {
}

// Update custom rule by its ID
func (c *Client) Update(ctx context.Context, params CustomRule) (*CustomRule, error) {
func (c *ClientCustomRule) Update(ctx context.Context, params CustomRule) (*CustomRule, error) {
reqBody := HttpRequest{
Data: params,
}
Expand All @@ -152,7 +159,7 @@ func (c *Client) Update(ctx context.Context, params CustomRule) (*CustomRule, er
req, err := http.NewRequestWithContext(
ctx,
"PUT",
fmt.Sprintf("%s/custom-rules/%d", c.HostURL, params.ID),
fmt.Sprintf("%s/%d", c.HostURL, params.ID),
strings.NewReader(string(rb)),
)
if err != nil {
Expand All @@ -173,11 +180,11 @@ func (c *Client) Update(ctx context.Context, params CustomRule) (*CustomRule, er
}

// Delete custom rule by its ID
func (c *Client) Delete(ctx context.Context, id int) error {
func (c *ClientCustomRule) Delete(ctx context.Context, id int) error {
req, err := http.NewRequestWithContext(
ctx,
"DELETE",
fmt.Sprintf("%s/custom-rules/%d", c.HostURL, id),
fmt.Sprintf("%s/%d", c.HostURL, id),
nil,
)
if err != nil {
Expand Down
172 changes: 172 additions & 0 deletions datadome-client-go/client_endpoint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
package datadome

import (
"context"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"strings"
"time"
)

// HOST_URL default datadome dashboard URL
const HostURLEndpoint string = "https://customer-api.datadome.co/1.0/endpoints"

// ClientEndpoint to perform request on DataDome's API
type ClientEndpoint struct {
HostURL string
HTTPClient *http.Client
Token string
}

// NewClientEndpoint is instantiate with given host and password parameters
lriberon marked this conversation as resolved.
Show resolved Hide resolved
func NewClientEndpoint(host, password *string) (*ClientEndpoint, error) {
c := ClientEndpoint{
HTTPClient: &http.Client{Timeout: 10 * time.Second},
HostURL: HostURLEndpoint,
}

if host != nil {
c.HostURL = *host
}

if password != nil {
c.Token = *password
}

return &c, nil
}

// doRequest on the DataDome API with given http.Request and HttpResponse
func (c *ClientEndpoint) doRequest(req *http.Request, endpoint *Endpoint) error {
// Add apikey as a header on each request for authentication
req.Header.Set("x-api-key", c.Token)

res, err := c.HTTPClient.Do(req)
if err != nil {
return err
}
defer func() {
err = res.Body.Close()
if err != nil {
log.Printf("failed to close body: %v", err)
}
}()

body, err := io.ReadAll(res.Body)
if err != nil {
return err
}

if res.StatusCode < 200 || res.StatusCode > 299 {
return fmt.Errorf("status: %d, body: %s", res.StatusCode, body)
}

log.Printf("[DEBUG] %s\n", body)
laurodd marked this conversation as resolved.
Show resolved Hide resolved

if endpoint != nil {
err = json.Unmarshal(body, endpoint)
if err != nil {
return err
}
}

return err
}

// Read endpoint information by its ID from the API management
func (c *ClientEndpoint) Read(ctx context.Context, id string) (*Endpoint, error) {
req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("%s/%s", c.HostURL, id), nil)
if err != nil {
return nil, err
}

endpoint := &Endpoint{}

err = c.doRequest(req, endpoint)
if err != nil {
return nil, err
}

return endpoint, nil
}

// Create new endpoint with given Endpoint parameters
func (c *ClientEndpoint) Create(ctx context.Context, params Endpoint) (*string, error) {
rb, err := json.Marshal(params)
if err != nil {
return nil, err
}

req, err := http.NewRequestWithContext(
ctx,
"POST",
c.HostURL,
strings.NewReader(string(rb)),
)
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/json")

endpoint := &Endpoint{}

err = c.doRequest(req, endpoint)
if err != nil {
return nil, err
}

return endpoint.ID, nil
}

// Update endpoint by its ID
func (c *ClientEndpoint) Update(ctx context.Context, params Endpoint) (*Endpoint, error) {
rb, err := json.Marshal(params)
if err != nil {
return nil, err
}

log.Printf("[DEBUG] %+v\n", params)
laurodd marked this conversation as resolved.
Show resolved Hide resolved

req, err := http.NewRequestWithContext(
ctx,
"PATCH",
fmt.Sprintf("%s/%s", c.HostURL, *params.ID),
strings.NewReader(string(rb)),
)
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/merge-patch+json")

endpoint := &Endpoint{}

err = c.doRequest(req, endpoint)
if err != nil {
return nil, err
}

return endpoint, nil
}

// Delete endpoint by its ID
func (c *ClientEndpoint) Delete(ctx context.Context, id string) error {
req, err := http.NewRequestWithContext(
ctx,
"DELETE",
fmt.Sprintf("%s/%s", c.HostURL, id),
nil,
)
if err != nil {
return err
}

err = c.doRequest(req, nil)
if err != nil {
return err
}

return nil
}
Loading
Loading