-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add inventory endpoint and support for pulling details about resource…
…s by spaceid (#26)
- Loading branch information
Showing
11 changed files
with
633 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package api | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"net/http" | ||
"strconv" | ||
|
||
"github.com/YaleSpinup/apierror" | ||
"github.com/YaleSpinup/cost-api/resourcegroupstaggingapi" | ||
"github.com/gorilla/mux" | ||
log "github.com/sirupsen/logrus" | ||
) | ||
|
||
// SpaceInventoryGetHandler handles getting the inventory for resources with a spaceid | ||
func (s *server) SpaceInventoryGetHandler(w http.ResponseWriter, r *http.Request) { | ||
w = LogWriter{w} | ||
vars := mux.Vars(r) | ||
account := vars["account"] | ||
spaceID := vars["space"] | ||
|
||
role := fmt.Sprintf("arn:aws:iam::%s:role/%s", account, s.session.RoleName) | ||
session, err := s.assumeRole( | ||
r.Context(), | ||
s.session.ExternalID, | ||
role, | ||
"", | ||
"arn:aws:iam::aws:policy/AWSResourceGroupsReadOnlyAccess", | ||
) | ||
if err != nil { | ||
msg := fmt.Sprintf("failed to assume role in account: %s", account) | ||
handleError(w, apierror.New(apierror.ErrForbidden, msg, nil)) | ||
return | ||
} | ||
|
||
orch := newInventoryOrchestrator( | ||
resourcegroupstaggingapi.New(resourcegroupstaggingapi.WithSession(session.Session)), | ||
s.org, | ||
) | ||
|
||
out, err := orch.GetResourceInventory(r.Context(), account, spaceID) | ||
if err != nil { | ||
handleError(w, err) | ||
return | ||
} | ||
|
||
j, err := json.Marshal(out) | ||
if err != nil { | ||
log.Errorf("cannot marshal response (%v) into JSON: %s", out, err) | ||
w.WriteHeader(http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
w.Header().Set("X-Items", strconv.Itoa(len(out))) | ||
w.Header().Set("Content-Type", "application/json") | ||
w.WriteHeader(http.StatusOK) | ||
w.Write(j) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package api | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/YaleSpinup/apierror" | ||
"github.com/aws/aws-sdk-go/aws" | ||
"github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi" | ||
log "github.com/sirupsen/logrus" | ||
) | ||
|
||
func (o *inventoryOrchestrator) GetResourceInventory(ctx context.Context, account, spaceid string) ([]*InventoryResponse, error) { | ||
if spaceid == "" { | ||
return nil, apierror.New(apierror.ErrBadRequest, "spaceid is required", nil) | ||
} | ||
|
||
list := []*InventoryResponse{} | ||
input := resourcegroupstaggingapi.GetResourcesInput{ | ||
TagFilters: []*resourcegroupstaggingapi.TagFilter{ | ||
{ | ||
Key: aws.String("spinup:spaceid"), | ||
Values: []*string{aws.String(spaceid)}, | ||
}, | ||
}, | ||
ResourcesPerPage: aws.Int64(100), | ||
} | ||
|
||
for { | ||
out, err := o.client.ListResourcesWithTags(ctx, &input) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
for _, res := range out.ResourceTagMappingList { | ||
list = append(list, toInventoryResponse(res)) | ||
} | ||
|
||
log.Debugf("%+v:%s", out.PaginationToken, aws.StringValue(out.PaginationToken)) | ||
|
||
if aws.StringValue(out.PaginationToken) == "" { | ||
break | ||
} | ||
|
||
input.PaginationToken = out.PaginationToken | ||
|
||
log.Debugf("%d resources in list", len(list)) | ||
} | ||
|
||
return list, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
package resourcegroupstaggingapi | ||
|
||
import ( | ||
"github.com/YaleSpinup/apierror" | ||
"github.com/aws/aws-sdk-go/aws/awserr" | ||
"github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi" | ||
"github.com/pkg/errors" | ||
) | ||
|
||
func ErrCode(msg string, err error) error { | ||
if aerr, ok := errors.Cause(err).(awserr.Error); ok { | ||
switch aerr.Code() { | ||
case | ||
|
||
// ErrCodeInternalServiceException for service response error code | ||
// "InternalServiceException". | ||
// | ||
// The request processing failed because of an unknown error, exception, or | ||
// failure. You can retry the request. | ||
resourcegroupstaggingapi.ErrCodeInternalServiceException: | ||
|
||
return apierror.New(apierror.ErrInternalError, msg, err) | ||
case | ||
|
||
// ErrCodeConcurrentModificationException for service response error code | ||
// "ConcurrentModificationException". | ||
// | ||
// The target of the operation is currently being modified by a different request. | ||
// Try again later. | ||
resourcegroupstaggingapi.ErrCodeConcurrentModificationException, | ||
|
||
// ErrCodeThrottledException for service response error code | ||
// "ThrottledException". | ||
// | ||
// The request was denied to limit the frequency of submitted requests. | ||
resourcegroupstaggingapi.ErrCodeThrottledException: | ||
return apierror.New(apierror.ErrConflict, msg, aerr) | ||
case | ||
|
||
// ErrCodeConstraintViolationException for service response error code | ||
// "ConstraintViolationException". | ||
// | ||
// The request was denied because performing this operation violates a constraint. | ||
// | ||
// Some of the reasons in the following list might not apply to this specific | ||
// operation. | ||
// | ||
// * You must meet the prerequisites for using tag policies. For information, | ||
// see Prerequisites and Permissions for Using Tag Policies (http://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_tag-policies-prereqs.html) | ||
// in the AWS Organizations User Guide. | ||
// | ||
// * You must enable the tag policies service principal (tagpolicies.tag.amazonaws.com) | ||
// to integrate with AWS Organizations For information, see EnableAWSServiceAccess | ||
// (http://docs.aws.amazon.com/organizations/latest/APIReference/API_EnableAWSServiceAccess.html). | ||
// | ||
// * You must have a tag policy attached to the organization root, an OU, | ||
// or an account. | ||
resourcegroupstaggingapi.ErrCodeConstraintViolationException, | ||
|
||
// ErrCodeInvalidParameterException for service response error code | ||
// "InvalidParameterException". | ||
// | ||
// This error indicates one of the following: | ||
// | ||
// * A parameter is missing. | ||
// | ||
// * A malformed string was supplied for the request parameter. | ||
// | ||
// * An out-of-range value was supplied for the request parameter. | ||
// | ||
// * The target ID is invalid, unsupported, or doesn't exist. | ||
// | ||
// * You can't access the Amazon S3 bucket for report storage. For more information, | ||
// see Additional Requirements for Organization-wide Tag Compliance Reports | ||
// (http://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_tag-policies-prereqs.html#bucket-policies-org-report) | ||
// in the AWS Organizations User Guide. | ||
resourcegroupstaggingapi.ErrCodeInvalidParameterException, | ||
|
||
// ErrCodePaginationTokenExpiredException for service response error code | ||
// "PaginationTokenExpiredException". | ||
// | ||
// A PaginationToken is valid for a maximum of 15 minutes. Your request was | ||
// denied because the specified PaginationToken has expired. | ||
resourcegroupstaggingapi.ErrCodePaginationTokenExpiredException: | ||
|
||
return apierror.New(apierror.ErrBadRequest, msg, aerr) | ||
case | ||
"Not Found": | ||
return apierror.New(apierror.ErrNotFound, msg, aerr) | ||
default: | ||
m := msg + ": " + aerr.Message() | ||
return apierror.New(apierror.ErrBadRequest, m, aerr) | ||
} | ||
} | ||
|
||
return apierror.New(apierror.ErrInternalError, msg, err) | ||
} |
Oops, something went wrong.