mirror of
https://github.com/usual2970/certimate.git
synced 2025-06-08 13:39:53 +00:00
547 lines
14 KiB
Go
547 lines
14 KiB
Go
package edgio_api
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/go-resty/resty/v2"
|
|
|
|
"github.com/usual2970/certimate/internal/pkg/vendors/edgio-sdk/applications/v7/dtos"
|
|
)
|
|
|
|
// AccessTokenResponse represents the response from the token endpoint.
|
|
type AccessTokenResponse struct {
|
|
AccessToken string `json:"access_token"`
|
|
ExpiresIn int `json:"expires_in"`
|
|
TokenType string `json:"token_type"`
|
|
Scope string `json:"scope"`
|
|
}
|
|
|
|
// TokenCache represents a cached token. The token is stored along
|
|
// with its expiry time. Because different endpoints require different
|
|
// scopes, we store the token with the scope as the key, so that we
|
|
// can fetch the token from the cache based on the scope.
|
|
type TokenCache struct {
|
|
AccessToken string
|
|
Expiry time.Time
|
|
}
|
|
|
|
type EdgioClient struct {
|
|
client *resty.Client
|
|
clientID string
|
|
clientSecret string
|
|
tokenURL string
|
|
apiURL string
|
|
tokenCache map[string]TokenCache
|
|
}
|
|
|
|
func NewEdgioClient(clientID, clientSecret, tokenURL, apiURL string) *EdgioClient {
|
|
client := resty.New().
|
|
SetTimeout(30 * time.Second).
|
|
SetRetryCount(3).
|
|
SetRetryWaitTime(5 * time.Second).
|
|
SetRetryMaxWaitTime(20 * time.Second)
|
|
|
|
if tokenURL == "" {
|
|
tokenURL = "https://id.edgio.app/connect/token"
|
|
}
|
|
|
|
if apiURL == "" {
|
|
apiURL = "https://edgioapis.com"
|
|
}
|
|
|
|
return &EdgioClient{
|
|
client: client,
|
|
clientID: clientID,
|
|
clientSecret: clientSecret,
|
|
tokenURL: tokenURL,
|
|
apiURL: apiURL,
|
|
tokenCache: make(map[string]TokenCache),
|
|
}
|
|
}
|
|
|
|
func (c *EdgioClient) getToken(scope string) (string, error) {
|
|
if cachedToken, exists := c.tokenCache[scope]; exists && time.Now().Before(cachedToken.Expiry) {
|
|
return cachedToken.AccessToken, nil
|
|
}
|
|
|
|
var tokenResp AccessTokenResponse
|
|
resp, err := c.client.R().
|
|
SetFormData(map[string]string{
|
|
"client_id": c.clientID,
|
|
"client_secret": c.clientSecret,
|
|
"grant_type": "client_credentials",
|
|
"scope": scope,
|
|
}).
|
|
SetResult(&tokenResp).
|
|
Post(c.tokenURL)
|
|
if err != nil {
|
|
return "", fmt.Errorf("failed to request token: %w", err)
|
|
}
|
|
|
|
if resp.IsError() {
|
|
return "", fmt.Errorf("unexpected status code for getToken: %d", resp.StatusCode())
|
|
}
|
|
|
|
c.tokenCache[scope] = TokenCache{
|
|
AccessToken: tokenResp.AccessToken,
|
|
Expiry: time.Now().Add(time.Duration(tokenResp.ExpiresIn) * time.Second),
|
|
}
|
|
|
|
return tokenResp.AccessToken, nil
|
|
}
|
|
|
|
func (c *EdgioClient) GetProperty(ctx context.Context, propertyID string) (*dtos.Property, error) {
|
|
token, err := c.getToken("app.accounts")
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get token: %w", err)
|
|
}
|
|
|
|
url := fmt.Sprintf("%s/accounts/v0.1/properties/%s", c.apiURL, propertyID)
|
|
|
|
var property dtos.Property
|
|
resp, err := c.client.R().
|
|
SetContext(ctx).
|
|
SetAuthToken(token).
|
|
SetResult(&property).
|
|
Get(url)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to send request: %w", err)
|
|
}
|
|
|
|
if resp.IsError() {
|
|
return nil, fmt.Errorf("unexpected status code for getSpecificProperty: %d, %s", resp.StatusCode(), resp.Request.URL)
|
|
}
|
|
|
|
return &property, nil
|
|
}
|
|
|
|
func (c *EdgioClient) GetProperties(page int, pageSize int, organizationID string) (*dtos.Properties, error) {
|
|
token, err := c.getToken("app.accounts")
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get token: %w", err)
|
|
}
|
|
|
|
url := fmt.Sprintf("%s/accounts/v0.1/properties", c.apiURL)
|
|
|
|
var propertiesResp dtos.Properties
|
|
resp, err := c.client.R().
|
|
SetAuthToken(token).
|
|
SetQueryParams(map[string]string{
|
|
"page": fmt.Sprintf("%d", page),
|
|
"page_size": fmt.Sprintf("%d", pageSize),
|
|
"organization_id": organizationID,
|
|
}).
|
|
SetResult(&propertiesResp).
|
|
Get(url)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to send request: %w", err)
|
|
}
|
|
|
|
if resp.IsError() {
|
|
return nil, fmt.Errorf("unexpected status code for getProperties: %d, %s", resp.StatusCode(), resp.Body())
|
|
}
|
|
|
|
return &propertiesResp, nil
|
|
}
|
|
|
|
func (c *EdgioClient) CreateProperty(ctx context.Context, organizationID, slug string) (*dtos.Property, error) {
|
|
token, err := c.getToken("app.accounts")
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get token: %w", err)
|
|
}
|
|
|
|
url := fmt.Sprintf("%s/accounts/v0.1/properties", c.apiURL)
|
|
|
|
var createdProperty dtos.Property
|
|
resp, err := c.client.R().
|
|
SetContext(ctx).
|
|
SetAuthToken(token).
|
|
SetHeader("Content-Type", "application/json").
|
|
SetBody(map[string]string{
|
|
"organization_id": organizationID,
|
|
"slug": slug,
|
|
}).
|
|
SetResult(&createdProperty).
|
|
Post(url)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to send request: %w", err)
|
|
}
|
|
|
|
if resp.IsError() {
|
|
return nil, fmt.Errorf("unexpected status code for createProperty: %d, response: %s", resp.StatusCode(), resp.String())
|
|
}
|
|
|
|
return &createdProperty, nil
|
|
}
|
|
|
|
func (c *EdgioClient) DeleteProperty(propertyID string) error {
|
|
token, err := c.getToken("app.accounts")
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get token: %w", err)
|
|
}
|
|
|
|
url := fmt.Sprintf("%s/accounts/v0.1/properties/%s", c.apiURL, propertyID)
|
|
|
|
resp, err := c.client.R().
|
|
SetAuthToken(token).
|
|
Delete(url)
|
|
if err != nil {
|
|
return fmt.Errorf("error sending DELETE request: %w", err)
|
|
}
|
|
|
|
if resp.IsError() {
|
|
return fmt.Errorf("error deleting property: status code %d", resp.StatusCode())
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (c *EdgioClient) UpdateProperty(ctx context.Context, propertyID string, slug string) (*dtos.Property, error) {
|
|
token, err := c.getToken("app.accounts")
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get token: %w", err)
|
|
}
|
|
|
|
url := fmt.Sprintf("%s/accounts/v0.1/properties/%s", c.apiURL, propertyID)
|
|
|
|
requestBody := map[string]interface{}{
|
|
"slug": slug,
|
|
}
|
|
|
|
var updatedProperty dtos.Property
|
|
resp, err := c.client.R().
|
|
SetContext(ctx).
|
|
SetAuthToken(token).
|
|
SetBody(requestBody).
|
|
SetResult(&updatedProperty).
|
|
Patch(url)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to send request: %w", err)
|
|
}
|
|
|
|
if resp.IsError() {
|
|
return nil, fmt.Errorf("unexpected status code for updateProperty: %d", resp.StatusCode())
|
|
}
|
|
|
|
return &updatedProperty, nil
|
|
}
|
|
|
|
func (c *EdgioClient) GetEnvironments(page, pageSize int, propertyID string) (*dtos.EnvironmentsResponse, error) {
|
|
token, err := c.getToken("app.accounts")
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get token: %w", err)
|
|
}
|
|
|
|
url := fmt.Sprintf("%s/accounts/v0.1/environments", c.apiURL)
|
|
|
|
resp, err := c.client.R().
|
|
SetAuthToken(token).
|
|
SetQueryParams(map[string]string{
|
|
"page": fmt.Sprintf("%d", page),
|
|
"page_size": fmt.Sprintf("%d", pageSize),
|
|
"property_id": propertyID,
|
|
}).
|
|
SetResult(&dtos.EnvironmentsResponse{}).
|
|
Get(url)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if resp.IsError() {
|
|
return nil, fmt.Errorf("error response: %s", resp.String())
|
|
}
|
|
|
|
return resp.Result().(*dtos.EnvironmentsResponse), nil
|
|
}
|
|
|
|
func (c *EdgioClient) GetEnvironment(environmentID string) (*dtos.Environment, error) {
|
|
token, err := c.getToken("app.accounts")
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get token: %w", err)
|
|
}
|
|
|
|
url := fmt.Sprintf("%s/accounts/v0.1/environments/%s", c.apiURL, environmentID)
|
|
|
|
resp, err := c.client.R().
|
|
SetPathParams(map[string]string{
|
|
"environment_id": environmentID,
|
|
}).
|
|
SetAuthToken(token).
|
|
SetResult(&dtos.Environment{}).
|
|
Get(url)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if resp.IsError() {
|
|
return nil, fmt.Errorf("error response: %s", resp.String())
|
|
}
|
|
|
|
return resp.Result().(*dtos.Environment), nil
|
|
}
|
|
|
|
func (c *EdgioClient) CreateEnvironment(propertyID, name string, onlyMaintainersCanDeploy, httpRequestLogging bool) (*dtos.Environment, error) {
|
|
token, err := c.getToken("app.accounts")
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get token: %w", err)
|
|
}
|
|
|
|
url := fmt.Sprintf("%s/accounts/v0.1/environments", c.apiURL)
|
|
|
|
body := map[string]interface{}{
|
|
"property_id": propertyID,
|
|
"name": name,
|
|
"only_maintainers_can_deploy": onlyMaintainersCanDeploy,
|
|
"http_request_logging": httpRequestLogging,
|
|
}
|
|
|
|
resp, err := c.client.R().
|
|
SetBody(body).
|
|
SetAuthToken(token).
|
|
SetResult(&dtos.Environment{}).
|
|
Post(url)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if resp.IsError() {
|
|
return nil, fmt.Errorf("error response: %s", resp.String())
|
|
}
|
|
|
|
return resp.Result().(*dtos.Environment), nil
|
|
}
|
|
|
|
func (c *EdgioClient) UpdateEnvironment(environmentID, name string, onlyMaintainersCanDeploy, httpRequestLogging, preserveCache bool) (*dtos.Environment, error) {
|
|
token, err := c.getToken("app.accounts")
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get token: %w", err)
|
|
}
|
|
|
|
url := fmt.Sprintf("%s/accounts/v0.1/environments/%s", c.apiURL, environmentID)
|
|
|
|
body := map[string]interface{}{
|
|
"name": name,
|
|
// as can_members_deploy is depricated, but update api is not
|
|
// we need to use it to map onlyMaintainersCanDeploy
|
|
"only_maintainers_can_deploy": onlyMaintainersCanDeploy,
|
|
"http_request_logging": httpRequestLogging,
|
|
"preserve_cache": preserveCache,
|
|
}
|
|
|
|
resp, err := c.client.R().
|
|
SetPathParams(map[string]string{
|
|
"environment_id": environmentID,
|
|
}).
|
|
SetBody(body).
|
|
SetAuthToken(token).
|
|
SetResult(&dtos.Environment{}).
|
|
Patch(url)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if resp.IsError() {
|
|
return nil, fmt.Errorf("error response: %s", resp.String())
|
|
}
|
|
|
|
return resp.Result().(*dtos.Environment), nil
|
|
}
|
|
|
|
func (c *EdgioClient) DeleteEnvironment(environmentID string) error {
|
|
token, err := c.getToken("app.accounts")
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get token: %w", err)
|
|
}
|
|
|
|
url := fmt.Sprintf("%s/accounts/v0.1/environments/%s", c.apiURL, environmentID)
|
|
|
|
resp, err := c.client.R().
|
|
SetPathParams(map[string]string{
|
|
"environment_id": environmentID,
|
|
}).
|
|
SetAuthToken(token).
|
|
SetResult(&dtos.Environment{}).
|
|
Delete(url)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if resp.IsError() {
|
|
return fmt.Errorf("error response: %s", resp.String())
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (c *EdgioClient) GetTlsCert(tlsCertId string) (*dtos.TLSCertResponse, error) {
|
|
token, err := c.getToken("app.config")
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get token: %w", err)
|
|
}
|
|
|
|
url := fmt.Sprintf("%s/config/v0.1/tls-certs/%s", c.apiURL, tlsCertId)
|
|
|
|
var tlsCertResponse dtos.TLSCertResponse
|
|
resp, err := c.client.R().
|
|
SetAuthToken(token).
|
|
SetResult(&tlsCertResponse).
|
|
Get(url)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error response: %s", err)
|
|
}
|
|
|
|
if resp.IsError() {
|
|
return nil, fmt.Errorf("error response: %s", resp.String())
|
|
}
|
|
|
|
return &tlsCertResponse, nil
|
|
}
|
|
|
|
func (c *EdgioClient) UploadTlsCert(req dtos.UploadTlsCertRequest) (*dtos.TLSCertResponse, error) {
|
|
token, err := c.getToken("app.config")
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get token: %w", err)
|
|
}
|
|
|
|
url := fmt.Sprintf("%s/config/v0.1/tls-certs", c.apiURL)
|
|
response := &dtos.TLSCertResponse{}
|
|
|
|
resp, err := c.client.R().
|
|
SetAuthToken(token).
|
|
SetHeader("Content-Type", "application/json").
|
|
SetBody(req).
|
|
SetResult(response).
|
|
Post(url)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to upload TLS certificate: %w", err)
|
|
}
|
|
|
|
if resp.IsError() {
|
|
return nil, fmt.Errorf("API responded with error: %s", resp.String())
|
|
}
|
|
|
|
return response, nil
|
|
}
|
|
|
|
func (c *EdgioClient) GenerateTlsCert(environmentId string) (*dtos.TLSCertResponse, error) {
|
|
token, err := c.getToken("app.config")
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get token: %w", err)
|
|
}
|
|
|
|
url := fmt.Sprintf("%s/config/v0.1/tls-certs/generate", c.apiURL)
|
|
request := map[string]interface{}{
|
|
"environment_id": environmentId,
|
|
}
|
|
response := &dtos.TLSCertResponse{}
|
|
|
|
resp, err := c.client.R().
|
|
SetAuthToken(token).
|
|
SetHeader("Content-Type", "application/json").
|
|
SetBody(request).
|
|
SetResult(response).
|
|
Post(url)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to upload TLS certificate: %w", err)
|
|
}
|
|
|
|
if resp.IsError() {
|
|
return nil, fmt.Errorf("API responded with error: %s", resp.String())
|
|
}
|
|
|
|
return response, nil
|
|
}
|
|
|
|
func (c *EdgioClient) GetTlsCerts(page int, pageSize int, environmentID string) (*dtos.TLSCertSResponse, error) {
|
|
token, err := c.getToken("app.config")
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get token: %w", err)
|
|
}
|
|
|
|
url := fmt.Sprintf("%s/config/v0.1/tls-certs", c.apiURL)
|
|
|
|
var tlsCertsResponse dtos.TLSCertSResponse
|
|
resp, err := c.client.R().
|
|
SetAuthToken(token).
|
|
SetQueryParams(map[string]string{
|
|
"page": fmt.Sprintf("%d", page),
|
|
"page_size": fmt.Sprintf("%d", pageSize),
|
|
"environment_id": environmentID,
|
|
}).
|
|
SetResult(&tlsCertsResponse).
|
|
Get(url)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to send request: %w", err)
|
|
}
|
|
|
|
if resp.IsError() {
|
|
return nil, fmt.Errorf("unexpected status code for getTlsCerts: %d", resp.StatusCode())
|
|
}
|
|
|
|
return &tlsCertsResponse, nil
|
|
}
|
|
|
|
func (c *EdgioClient) UploadCdnConfiguration(config *dtos.CDNConfiguration) (*dtos.CDNConfiguration, error) {
|
|
fmt.Println("------------------------------------------------------------------------- uploading")
|
|
|
|
token, err := c.getToken("app.config")
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get token: %w", err)
|
|
}
|
|
|
|
url := fmt.Sprintf("%s/config/v0.1/configs", c.apiURL)
|
|
var response dtos.CDNConfiguration
|
|
|
|
// Convert config to json
|
|
jsonBody, _ := json.MarshalIndent(config, "", " ")
|
|
jsonString := string(jsonBody)
|
|
fmt.Println("------------------------- config report code: ", config.Hostnames[0].ReportCode == nil)
|
|
fmt.Println("------------------------- config report code value: ", config.Hostnames[0].ReportCode)
|
|
fmt.Println("----------------------------------- jsonBody: ", jsonString)
|
|
|
|
resp, err := c.client.R().
|
|
SetAuthToken(token).
|
|
SetHeader("Content-Type", "application/json").
|
|
SetBody(config).
|
|
SetResult(&response).
|
|
Post(url)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to upload CDN configuration: %w", err)
|
|
}
|
|
|
|
if resp.IsError() {
|
|
return nil, fmt.Errorf("unexpected status code for uploadCdnConfiguration: %d, %s", resp.StatusCode(), resp.Body())
|
|
}
|
|
|
|
return &response, nil
|
|
}
|
|
|
|
func (c *EdgioClient) GetCDNConfiguration(configID string) (*dtos.CDNConfiguration, error) {
|
|
fmt.Println("------------------------------------------------------------------------- reading config")
|
|
|
|
token, err := c.getToken("app.config")
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get token: %w", err)
|
|
}
|
|
|
|
url := fmt.Sprintf("https://edgioapis.com/config/v0.1/configs/%s", configID)
|
|
var response dtos.CDNConfiguration
|
|
|
|
resp, err := c.client.R().
|
|
SetAuthToken(token).
|
|
SetResult(&response).
|
|
Get(url)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get CDN configuration: %w", err)
|
|
}
|
|
|
|
if resp.IsError() {
|
|
return nil, fmt.Errorf("unexpected status code for GetCDNConfiguration: %d", resp.StatusCode())
|
|
}
|
|
|
|
return &response, nil
|
|
}
|