package cfn import ( "github.com/aws-cloudformation/cloudformation-cli-go-plugin/cfn/encoding" "github.com/aws-cloudformation/cloudformation-cli-go-plugin/cfn/handler" "github.com/aws/aws-sdk-go/service/cloudformation" ) // response represents a response to the // cloudformation service from a resource handler. // The zero value is ready to use. type response struct { // Message which can be shown to callers to indicate the nature of a // progress transition or callback delay; for example a message // indicating "propagating to edge" Message string `json:"message,omitempty"` // The operationStatus indicates whether the handler has reached a terminal // state or is still computing and requires more time to complete OperationStatus handler.Status `json:"status,omitempty"` // ResourceModel it The output resource instance populated by a READ/LIST for // synchronous results and by CREATE/UPDATE/DELETE for final response // validation/confirmation ResourceModel interface{} `json:"resourceModel,omitempty"` // ErrorCode is used to report granular failures back to CloudFormation ErrorCode string `json:"errorCode,omitempty"` // BearerToken is used to report progress back to CloudFormation and is // passed back to CloudFormation BearerToken string `json:"bearerToken,omitempty"` // ResourceModels is the output resource instances populated by a LIST for // synchronous results. ResourceModels must be returned by LIST so it's // always included in the response. When ResourceModels is not set, null is // returned. ResourceModels []interface{} `json:"resourceModels"` // NextToken the token used to request additional pages of resources for a LIST operation NextToken string `json:"nextToken,omitempty"` // CallbackContext is an arbitrary datum which the handler can return in an // IN_PROGRESS event to allow the passing through of additional state or // metadata between subsequent retries; for example to pass through a Resource // identifier which can be used to continue polling for stabilization CallbackContext map[string]interface{} `json:"callbackContext,omitempty"` // CallbackDelaySeconds will be scheduled with an initial delay of no less than the number // of seconds specified in the progress event. Set this value to <= 0 to // indicate no callback should be made. CallbackDelaySeconds int64 `json:"callbackDelaySeconds,omitempty"` } // newFailedResponse returns a response pre-filled with the supplied error func newFailedResponse(err error, bearerToken string) response { return response{ OperationStatus: handler.Failed, ErrorCode: cloudformation.HandlerErrorCodeInternalFailure, Message: err.Error(), BearerToken: bearerToken, } } // newResponse converts a progress event into a useable reponse // for the CloudFormation Resource Provider service to understand. func newResponse(pevt *handler.ProgressEvent, bearerToken string) (response, error) { model, err := encoding.Stringify(pevt.ResourceModel) if err != nil { return response{}, err } var models []interface{} if pevt.ResourceModels != nil { models = make([]interface{}, len(pevt.ResourceModels)) for i := range pevt.ResourceModels { m, err := encoding.Stringify(pevt.ResourceModels[i]) if err != nil { return response{}, err } models[i] = m } } resp := response{ BearerToken: bearerToken, Message: pevt.Message, OperationStatus: pevt.OperationStatus, ResourceModel: model, ResourceModels: models, NextToken: pevt.NextToken, CallbackContext: pevt.CallbackContext, CallbackDelaySeconds: pevt.CallbackDelaySeconds, } if pevt.HandlerErrorCode != "" { resp.ErrorCode = pevt.HandlerErrorCode } return resp, nil }