Skip to content

Commit

Permalink
DXE-3536 Properties associated with access key
Browse files Browse the repository at this point in the history
  • Loading branch information
wzagrajcz committed Jul 5, 2024
1 parent 294611f commit b81a4d6
Show file tree
Hide file tree
Showing 6 changed files with 651 additions and 5 deletions.
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@




* Properties using Access Key
* [LookupProperties](https://techdocs.akamai.com/cloud-access-mgr/reference/get-access-key-version-properties)
* [GetAsyncPropertiesLookupID](https://techdocs.akamai.com/cloud-access-mgr/reference/get-async-version-property-lookup)
* [PerformAsyncPropertiesLookup](https://techdocs.akamai.com/cloud-access-mgr/reference/get-property-lookup)

## X.X.X (X X, X)

Expand Down
16 changes: 16 additions & 0 deletions pkg/cloudaccess/cloudaccess.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,22 @@ type (
//
// See: https://techdocs.akamai.com/cloud-access-mgr/reference/delete-access-key-version
DeleteAccessKeyVersion(context.Context, DeleteAccessKeyVersionRequest) (*DeleteAccessKeyVersionResponse, error)

// LookupProperties returns information about all the Property Manager properties that use a specific version of an access key.
// This operation gets the data directly. To avoid any latency problems, use the GetAsyncPropertiesLookupID and PerformAsyncPropertiesLookup
//
// See: https://techdocs.akamai.com/cloud-access-mgr/reference/get-access-key-version-properties
LookupProperties(ctx context.Context, params LookupPropertiesRequest) (*LookupPropertiesResponse, error)

// GetAsyncPropertiesLookupID gets the unique identifier used to perform an PerformAsyncPropertiesLookup
//
// See: https://techdocs.akamai.com/cloud-access-mgr/reference/get-async-version-property-lookup
GetAsyncPropertiesLookupID(ctx context.Context, params GetAsyncPropertiesLookupIDRequest) (*GetAsyncPropertiesLookupIDResponse, error)

// PerformAsyncPropertiesLookup returns in asynchronous way information about all the Property Manager properties that use a specific version of an access key.
//
// See: https://techdocs.akamai.com/cloud-access-mgr/reference/get-property-lookup
PerformAsyncPropertiesLookup(ctx context.Context, params PerformAsyncPropertiesLookupRequest) (*PerformAsyncPropertiesLookupResponse, error)
}

cloudaccess struct {
Expand Down
9 changes: 5 additions & 4 deletions pkg/cloudaccess/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@ type (
Title string `json:"title"`
Detail string `json:"detail"`
Instance string `json:"instance"`
Status int `json:"status"`
AccessKeyUID int `json:"accessKeyUid,omitempty"`
Status int64 `json:"status"`
AccessKeyUID int64 `json:"accessKeyUid,omitempty"`
AccessKeyName string `json:"accessKeyName,omitempty"`
ProblemID string `json:"problemId,omitempty"`
Version int64 `json:"version"`
Errors []ErrorItem `json:"errors,omitempty"`
}

Expand All @@ -40,7 +41,7 @@ func (c *cloudaccess) Error(r *http.Response) error {
body, err := io.ReadAll(r.Body)
if err != nil {
c.Log(r.Request.Context()).Errorf("reading error response body: %s", err)
e.Status = r.StatusCode
e.Status = int64(r.StatusCode)
e.Title = fmt.Sprintf("Failed to read error body")
e.Detail = err.Error()
return &e
Expand All @@ -52,7 +53,7 @@ func (c *cloudaccess) Error(r *http.Response) error {
e.Detail = errs.UnescapeContent(string(body))
}

e.Status = r.StatusCode
e.Status = int64(r.StatusCode)

return &e
}
Expand Down
30 changes: 30 additions & 0 deletions pkg/cloudaccess/mocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,36 @@ func (m *Mock) GetAccessKeyVersionStatus(ctx context.Context, r GetAccessKeyVers
return args.Get(0).(*GetAccessKeyVersionStatusResponse), args.Error(1)
}

func (m *Mock) LookupProperties(ctx context.Context, r LookupPropertiesRequest) (*LookupPropertiesResponse, error) {
args := m.Called(ctx, r)

if args.Error(1) != nil {
return nil, args.Error(1)
}

return args.Get(0).(*LookupPropertiesResponse), args.Error(1)
}

func (m *Mock) GetAsyncPropertiesLookupID(ctx context.Context, r GetAsyncPropertiesLookupIDRequest) (*GetAsyncPropertiesLookupIDResponse, error) {
args := m.Called(ctx, r)

if args.Error(1) != nil {
return nil, args.Error(1)
}

return args.Get(0).(*GetAsyncPropertiesLookupIDResponse), args.Error(1)
}

func (m *Mock) PerformAsyncPropertiesLookup(ctx context.Context, r PerformAsyncPropertiesLookupRequest) (*PerformAsyncPropertiesLookupResponse, error) {
args := m.Called(ctx, r)

if args.Error(1) != nil {
return nil, args.Error(1)
}

return args.Get(0).(*PerformAsyncPropertiesLookupResponse), args.Error(1)
}

func (m *Mock) CreateAccessKey(ctx context.Context, r CreateAccessKeyRequest) (*CreateAccessKeyResponse, error) {
args := m.Called(ctx, r)

Expand Down
200 changes: 200 additions & 0 deletions pkg/cloudaccess/properties.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
package cloudaccess

import (
"context"
"errors"
"fmt"
"net/http"
"net/url"

"github.com/akamai/AkamaiOPEN-edgegrid-golang/v8/pkg/edgegriderr"
validation "github.com/go-ozzo/ozzo-validation/v4"
)

type (
// LookupPropertiesRequest holds parameters for LookupProperties
LookupPropertiesRequest struct {
AccessKeyUID int64
Version int64
}

// LookupPropertiesResponse contains response for LookupProperties
LookupPropertiesResponse struct {
Properties []Property `json:"properties"`
}

// Property holds information about property related to given access key
Property struct {
AccessKeyUID int64 `json:"accessKeyUid"`
Version int64 `json:"version"`
PropertyID string `json:"propertyId"`
PropertyName string `json:"propertyName"`
ProductionVersion *int64 `json:"productionVersion"`
StagingVersion *int64 `json:"stagingVersion"`
}

// GetAsyncPropertiesLookupIDRequest holds parameters for GetAsyncPropertiesLookupID
GetAsyncPropertiesLookupIDRequest struct {
AccessKeyUID int64
Version int64
}

// GetAsyncPropertiesLookupIDResponse contains response for GetAsyncPropertiesLookupID
GetAsyncPropertiesLookupIDResponse struct {
LookupID int64 `json:"lookupId"`
RetryAfter int64 `json:"retryAfter"`
}

// PerformAsyncPropertiesLookupRequest holds parameters for PerformAsyncPropertiesLookup
PerformAsyncPropertiesLookupRequest struct {
LookupID int64
}

// PerformAsyncPropertiesLookupResponse contains response for PerformAsyncPropertiesLookup
PerformAsyncPropertiesLookupResponse struct {
LookupID int64 `json:"lookupId"`
LookupStatus LookupStatus `json:"lookupStatus"`
Properties []Property `json:"properties"`
}

// LookupStatus represents a lookup status
LookupStatus string
)

const (
// LookupComplete represents complete asynchronous property lookup status
LookupComplete LookupStatus = "COMPLETE"
// LookupError represents error asynchronous property lookup status
LookupError LookupStatus = "ERROR"
// LookupInProgress represents in progress asynchronous property lookup status
LookupInProgress LookupStatus = "IN_PROGRESS"
// LookupPending represents pending asynchronous property lookup status
LookupPending LookupStatus = "PENDING"
// LookupSubmitted represents submitted asynchronous property lookup status
LookupSubmitted LookupStatus = "SUBMITTED"
)

// Validate validates LookupPropertiesRequest
func (r LookupPropertiesRequest) Validate() error {
return edgegriderr.ParseValidationErrors(validation.Errors{
"Version": validation.Validate(r.Version, validation.Required),
"AccessKeyUID": validation.Validate(r.AccessKeyUID, validation.Required),
})
}

// Validate validates GetAsyncPropertiesLookupIDRequest
func (r GetAsyncPropertiesLookupIDRequest) Validate() interface{} {
return edgegriderr.ParseValidationErrors(validation.Errors{
"Version": validation.Validate(r.Version, validation.Required),
"AccessKeyUID": validation.Validate(r.AccessKeyUID, validation.Required),
})
}

// Validate validates PerformAsyncPropertiesLookupRequest
func (r PerformAsyncPropertiesLookupRequest) Validate() interface{} {
return edgegriderr.ParseValidationErrors(validation.Errors{
"LookupID": validation.Validate(r.LookupID, validation.Required),
})
}

var (
// ErrLookupProperties is returned when LookupProperties fails
ErrLookupProperties = errors.New("lookup properties")
// ErrGetAsyncLookupIDProperties is returned when GetAsyncPropertiesLookupID fails
ErrGetAsyncLookupIDProperties = errors.New("get lookup properties id async")
// ErrPerformAsyncLookupProperties is returned when PerformAsyncPropertiesLookup fails
ErrPerformAsyncLookupProperties = errors.New("perform async lookup properties")
)

func (c *cloudaccess) LookupProperties(ctx context.Context, params LookupPropertiesRequest) (*LookupPropertiesResponse, error) {
logger := c.Log(ctx)
logger.Debug("LookupProperties")

if err := params.Validate(); err != nil {
return nil, fmt.Errorf("%s: %w: %s", ErrLookupProperties, ErrStructValidation, err)
}

uri, err := url.Parse(fmt.Sprintf("/cam/v1/access-keys/%d/versions/%d/properties", params.AccessKeyUID, params.Version))
if err != nil {
return nil, fmt.Errorf("%w: failed to parse url: %s", ErrLookupProperties, err)
}

req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri.String(), nil)
if err != nil {
return nil, fmt.Errorf("%w: failed to create request: %s", ErrLookupProperties, err)
}

var result LookupPropertiesResponse
resp, err := c.Exec(req, &result)
if err != nil {
return nil, fmt.Errorf("%w: request failed: %s", ErrLookupProperties, err)
}

if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("%s: %w", ErrLookupProperties, c.Error(resp))
}

return &result, nil
}

func (c *cloudaccess) GetAsyncPropertiesLookupID(ctx context.Context, params GetAsyncPropertiesLookupIDRequest) (*GetAsyncPropertiesLookupIDResponse, error) {
logger := c.Log(ctx)
logger.Debug("GetAsyncPropertiesLookupID")

if err := params.Validate(); err != nil {
return nil, fmt.Errorf("%s: %w: %s", ErrGetAsyncLookupIDProperties, ErrStructValidation, err)
}

uri, err := url.Parse(fmt.Sprintf("/cam/v1/access-keys/%d/versions/%d/property-lookup-id", params.AccessKeyUID, params.Version))
if err != nil {
return nil, fmt.Errorf("%w: failed to parse url: %s", ErrGetAsyncLookupIDProperties, err)
}

req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri.String(), nil)
if err != nil {
return nil, fmt.Errorf("%w: failed to create request: %s", ErrGetAsyncLookupIDProperties, err)
}

var result GetAsyncPropertiesLookupIDResponse
resp, err := c.Exec(req, &result)
if err != nil {
return nil, fmt.Errorf("%w: request failed: %s", ErrGetAsyncLookupIDProperties, err)
}

if resp.StatusCode != http.StatusAccepted {
return nil, fmt.Errorf("%s: %w", ErrGetAsyncLookupIDProperties, c.Error(resp))
}

return &result, nil
}

func (c *cloudaccess) PerformAsyncPropertiesLookup(ctx context.Context, params PerformAsyncPropertiesLookupRequest) (*PerformAsyncPropertiesLookupResponse, error) {
logger := c.Log(ctx)
logger.Debug("PerformAsyncPropertiesLookup")

if err := params.Validate(); err != nil {
return nil, fmt.Errorf("%s: %w: %s", ErrPerformAsyncLookupProperties, ErrStructValidation, err)
}

uri, err := url.Parse(fmt.Sprintf("/cam/v1/property-lookups/%d", params.LookupID))
if err != nil {
return nil, fmt.Errorf("%w: failed to parse url: %s", ErrPerformAsyncLookupProperties, err)
}

req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri.String(), nil)
if err != nil {
return nil, fmt.Errorf("%w: failed to create request: %s", ErrPerformAsyncLookupProperties, err)
}

var result PerformAsyncPropertiesLookupResponse
resp, err := c.Exec(req, &result)
if err != nil {
return nil, fmt.Errorf("%w: request failed: %s", ErrPerformAsyncLookupProperties, err)
}

if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("%s: %w", ErrPerformAsyncLookupProperties, c.Error(resp))
}

return &result, nil
}
Loading

0 comments on commit b81a4d6

Please sign in to comment.