github.com/mweagle/Sparta@v1.15.0/archetype/cloudwatch.go (about)

     1  package archetype
     2  
     3  import (
     4  	"context"
     5  	"reflect"
     6  	"runtime"
     7  
     8  	awsLambdaEvents "github.com/aws/aws-lambda-go/events"
     9  	sparta "github.com/mweagle/Sparta"
    10  	"github.com/pkg/errors"
    11  )
    12  
    13  // CloudWatchReactor represents a lambda function that responds to CW messages
    14  type CloudWatchReactor interface {
    15  	// OnLogMessage when an SNS event occurs. Check the snsEvent field
    16  	// for the specific event
    17  	OnCloudWatchMessage(ctx context.Context,
    18  		cwLogs awsLambdaEvents.CloudwatchLogsEvent) (interface{}, error)
    19  }
    20  
    21  // CloudWatchReactorFunc is a free function that adapts a CloudWatchReactor
    22  // compliant signature into a function that exposes an OnEvent
    23  // function
    24  type CloudWatchReactorFunc func(ctx context.Context,
    25  	cwLogs awsLambdaEvents.CloudwatchLogsEvent) (interface{}, error)
    26  
    27  // OnCloudWatchMessage satisfies the CloudWatchReactor interface
    28  func (reactorFunc CloudWatchReactorFunc) OnCloudWatchMessage(ctx context.Context,
    29  	cwLogs awsLambdaEvents.CloudwatchLogsEvent) (interface{}, error) {
    30  	return reactorFunc(ctx, cwLogs)
    31  }
    32  
    33  // ReactorName provides the name of the reactor func
    34  func (reactorFunc CloudWatchReactorFunc) ReactorName() string {
    35  	return runtime.FuncForPC(reflect.ValueOf(reactorFunc).Pointer()).Name()
    36  }
    37  
    38  // NewCloudWatchEventedReactor returns a CloudWatch logs reactor lambda function
    39  // that executes in response to the given events. The eventPatterns map is a map of names
    40  // to map[string]interface{} values that represents the events to listen to. See
    41  // https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/CloudWatchEventsandEventPatterns.html
    42  // for the proper syntax. Example:
    43  // 	map[string]interface{}{
    44  //		"source":      []string{"aws.ec2"},
    45  //		"detail-type": []string{"EC2 Instance state change"},
    46  //	}
    47  func NewCloudWatchEventedReactor(reactor CloudWatchReactor,
    48  	eventPatterns map[string]map[string]interface{},
    49  	additionalLambdaPermissions []sparta.IAMRolePrivilege) (*sparta.LambdaAWSInfo, error) {
    50  
    51  	subscriptions := make(map[string]sparta.CloudWatchEventsRule)
    52  	for eachName, eachPattern := range eventPatterns {
    53  		subscriptions[eachName] = sparta.CloudWatchEventsRule{
    54  			EventPattern: eachPattern,
    55  		}
    56  	}
    57  	return NewCloudWatchReactor(reactor, subscriptions, additionalLambdaPermissions)
    58  }
    59  
    60  // NewCloudWatchScheduledReactor returns a CloudWatch logs reactor lambda function
    61  // that executes with the given schedule. The cronSchedules map is a map of names
    62  // to ScheduleExpressions. See
    63  // https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/ScheduledEvents.html#RateExpressions
    64  // for the proper syntax. Example:
    65  // 	"rate(5 minutes)"
    66  //
    67  func NewCloudWatchScheduledReactor(reactor CloudWatchReactor,
    68  	cronSchedules map[string]string,
    69  	additionalLambdaPermissions []sparta.IAMRolePrivilege) (*sparta.LambdaAWSInfo, error) {
    70  
    71  	subscriptions := make(map[string]sparta.CloudWatchEventsRule)
    72  	for eachName, eachSchedule := range cronSchedules {
    73  		subscriptions[eachName] = sparta.CloudWatchEventsRule{
    74  			ScheduleExpression: eachSchedule,
    75  		}
    76  	}
    77  	return NewCloudWatchReactor(reactor, subscriptions, additionalLambdaPermissions)
    78  }
    79  
    80  // NewCloudWatchReactor returns a CloudWatch logs reactor lambda function
    81  func NewCloudWatchReactor(reactor CloudWatchReactor,
    82  	subscriptions map[string]sparta.CloudWatchEventsRule,
    83  	additionalLambdaPermissions []sparta.IAMRolePrivilege) (*sparta.LambdaAWSInfo, error) {
    84  	if len(subscriptions) <= 0 {
    85  		return nil, errors.Errorf("CloudWatchLogs subscription map must not be empty")
    86  	}
    87  
    88  	reactorLambda := func(ctx context.Context, cwLogs awsLambdaEvents.CloudwatchLogsEvent) (interface{}, error) {
    89  		return reactor.OnCloudWatchMessage(ctx, cwLogs)
    90  	}
    91  	lambdaFn, lambdaFnErr := sparta.NewAWSLambda(reactorName(reactor),
    92  		reactorLambda,
    93  		sparta.IAMRoleDefinition{})
    94  	if lambdaFnErr != nil {
    95  		return nil, errors.Wrapf(lambdaFnErr, "attempting to create reactor")
    96  	}
    97  	cloudWatchEventsPermission := sparta.CloudWatchEventsPermission{}
    98  	cloudWatchEventsPermission.Rules = make(map[string]sparta.CloudWatchEventsRule)
    99  	for eachRuleName, eachRule := range subscriptions {
   100  		cloudWatchEventsPermission.Rules[eachRuleName] = eachRule
   101  	}
   102  	lambdaFn.Permissions = append(lambdaFn.Permissions, cloudWatchEventsPermission)
   103  
   104  	if len(additionalLambdaPermissions) != 0 {
   105  		lambdaFn.RoleDefinition.Privileges = additionalLambdaPermissions
   106  	}
   107  	return lambdaFn, nil
   108  }