github.com/argoproj/argo-events@v1.9.1/sensors/triggers/aws-lambda/aws-lambda.go (about)

     1  /*
     2  Copyright 2020 BlackRock, Inc.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  	http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  package aws_lambda
    17  
    18  import (
    19  	"context"
    20  	"encoding/json"
    21  	"fmt"
    22  
    23  	"github.com/aws/aws-sdk-go/aws"
    24  	"github.com/aws/aws-sdk-go/service/lambda"
    25  	"go.uber.org/zap"
    26  
    27  	"github.com/argoproj/argo-events/common"
    28  	"github.com/argoproj/argo-events/common/logging"
    29  	commonaws "github.com/argoproj/argo-events/eventsources/common/aws"
    30  	apicommon "github.com/argoproj/argo-events/pkg/apis/common"
    31  	"github.com/argoproj/argo-events/pkg/apis/sensor/v1alpha1"
    32  	"github.com/argoproj/argo-events/sensors/policy"
    33  	"github.com/argoproj/argo-events/sensors/triggers"
    34  )
    35  
    36  // AWSLambdaTrigger refers to trigger that invokes AWS Lambda functions
    37  type AWSLambdaTrigger struct {
    38  	// LambdaClient is AWS Lambda client
    39  	LambdaClient *lambda.Lambda
    40  	// Sensor object
    41  	Sensor *v1alpha1.Sensor
    42  	// Trigger definition
    43  	Trigger *v1alpha1.Trigger
    44  	// logger to log stuff
    45  	Logger *zap.SugaredLogger
    46  }
    47  
    48  // NewAWSLambdaTrigger returns a new AWS Lambda context
    49  func NewAWSLambdaTrigger(lambdaClients common.StringKeyedMap[*lambda.Lambda], sensor *v1alpha1.Sensor, trigger *v1alpha1.Trigger, logger *zap.SugaredLogger) (*AWSLambdaTrigger, error) {
    50  	lambdatrigger := trigger.Template.AWSLambda
    51  
    52  	lambdaClient, ok := lambdaClients.Load(trigger.Template.Name)
    53  	if !ok {
    54  		awsSession, err := commonaws.CreateAWSSessionWithCredsInVolume(lambdatrigger.Region, lambdatrigger.RoleARN, lambdatrigger.AccessKey, lambdatrigger.SecretKey, nil)
    55  		if err != nil {
    56  			return nil, fmt.Errorf("failed to create a AWS session, %w", err)
    57  		}
    58  		lambdaClient = lambda.New(awsSession, &aws.Config{Region: &lambdatrigger.Region})
    59  		lambdaClients.Store(trigger.Template.Name, lambdaClient)
    60  	}
    61  
    62  	return &AWSLambdaTrigger{
    63  		LambdaClient: lambdaClient,
    64  		Sensor:       sensor,
    65  		Trigger:      trigger,
    66  		Logger:       logger.With(logging.LabelTriggerType, apicommon.LambdaTrigger),
    67  	}, nil
    68  }
    69  
    70  // GetTriggerType returns the type of the trigger
    71  func (t *AWSLambdaTrigger) GetTriggerType() apicommon.TriggerType {
    72  	return apicommon.LambdaTrigger
    73  }
    74  
    75  // FetchResource fetches the trigger resource
    76  func (t *AWSLambdaTrigger) FetchResource(ctx context.Context) (interface{}, error) {
    77  	return t.Trigger.Template.AWSLambda, nil
    78  }
    79  
    80  // ApplyResourceParameters applies parameters to the trigger resource
    81  func (t *AWSLambdaTrigger) ApplyResourceParameters(events map[string]*v1alpha1.Event, resource interface{}) (interface{}, error) {
    82  	resourceBytes, err := json.Marshal(resource)
    83  	if err != nil {
    84  		return nil, fmt.Errorf("failed to marshal the aws lamda trigger resource, %w", err)
    85  	}
    86  	parameters := t.Trigger.Template.AWSLambda.Parameters
    87  	if parameters != nil {
    88  		updatedResourceBytes, err := triggers.ApplyParams(resourceBytes, t.Trigger.Template.AWSLambda.Parameters, events)
    89  		if err != nil {
    90  			return nil, err
    91  		}
    92  		var ht *v1alpha1.AWSLambdaTrigger
    93  		if err := json.Unmarshal(updatedResourceBytes, &ht); err != nil {
    94  			return nil, fmt.Errorf("failed to unmarshal the updated aws lambda trigger resource after applying resource parameters, %w", err)
    95  		}
    96  		return ht, nil
    97  	}
    98  	return resource, nil
    99  }
   100  
   101  // Execute executes the trigger
   102  func (t *AWSLambdaTrigger) Execute(ctx context.Context, events map[string]*v1alpha1.Event, resource interface{}) (interface{}, error) {
   103  	trigger, ok := resource.(*v1alpha1.AWSLambdaTrigger)
   104  	if !ok {
   105  		return nil, fmt.Errorf("failed to interpret the trigger resource")
   106  	}
   107  
   108  	if trigger.Payload == nil {
   109  		return nil, fmt.Errorf("payload parameters are not specified")
   110  	}
   111  
   112  	payload, err := triggers.ConstructPayload(events, trigger.Payload)
   113  	if err != nil {
   114  		return nil, err
   115  	}
   116  
   117  	response, err := t.LambdaClient.Invoke(&lambda.InvokeInput{
   118  		FunctionName:   &trigger.FunctionName,
   119  		Payload:        payload,
   120  		InvocationType: trigger.InvocationType,
   121  	})
   122  	if err != nil {
   123  		return nil, err
   124  	}
   125  
   126  	return response, nil
   127  }
   128  
   129  // ApplyPolicy applies the policy on the trigger execution response
   130  func (t *AWSLambdaTrigger) ApplyPolicy(ctx context.Context, resource interface{}) error {
   131  	if t.Trigger.Policy == nil || t.Trigger.Policy.Status == nil || t.Trigger.Policy.Status.Allow == nil {
   132  		return nil
   133  	}
   134  
   135  	obj, ok := resource.(*lambda.InvokeOutput)
   136  	if !ok {
   137  		return fmt.Errorf("failed to interpret the trigger resource")
   138  	}
   139  
   140  	p := policy.NewStatusPolicy(int(*obj.StatusCode), t.Trigger.Policy.Status.GetAllow())
   141  	return p.ApplyPolicy(ctx)
   142  }