Ejemplo n.º 1
0
        public static void ExecuteWithNoUi(LocalLambdaOptions localLambdaOptions, CommandLineOptions commandOptions, string lambdaAssemblyDirectory, RunConfiguration runConfiguration)
        {
            runConfiguration.OutputWriter.WriteLine("Executing Lambda function without web interface");
            var lambdaProjectDirectory = Utils.FindLambdaProjectDirectory(lambdaAssemblyDirectory);

            string           configFile     = DetermineConfigFile(commandOptions, lambdaAssemblyDirectory: lambdaAssemblyDirectory, lambdaProjectDirectory: lambdaProjectDirectory);
            LambdaConfigInfo configInfo     = LoadLambdaConfigInfo(configFile, commandOptions, lambdaAssemblyDirectory: lambdaAssemblyDirectory, lambdaProjectDirectory: lambdaProjectDirectory, runConfiguration);
            LambdaFunction   lambdaFunction = LoadLambdaFunction(configInfo, localLambdaOptions, commandOptions, lambdaAssemblyDirectory: lambdaAssemblyDirectory, lambdaProjectDirectory: lambdaProjectDirectory, runConfiguration);

            string payload = DeterminePayload(localLambdaOptions, commandOptions, lambdaAssemblyDirectory: lambdaAssemblyDirectory, lambdaProjectDirectory: lambdaProjectDirectory, runConfiguration);

            var awsProfile = commandOptions.AWSProfile ?? configInfo.AWSProfile;

            if (!string.IsNullOrEmpty(awsProfile))
            {
                if (new Amazon.Runtime.CredentialManagement.CredentialProfileStoreChain().TryGetProfile(awsProfile, out _))
                {
                    runConfiguration.OutputWriter.WriteLine($"... Setting AWS_PROFILE environment variable to {awsProfile}.");
                }
                else
                {
                    runConfiguration.OutputWriter.WriteLine($"... Warning: Profile {awsProfile} not found in the aws credential store.");
                    awsProfile = null;
                }
            }
            else
            {
                runConfiguration.OutputWriter.WriteLine("... No profile choosen for AWS credentials. The --profile switch can be used to configure an AWS profile.");
            }

            var awsRegion = commandOptions.AWSRegion ?? configInfo.AWSRegion;

            if (!string.IsNullOrEmpty(awsRegion))
            {
                runConfiguration.OutputWriter.WriteLine($"... Setting AWS_REGION environment variable to {awsRegion}.");
            }
            else
            {
                runConfiguration.OutputWriter.WriteLine("... No default AWS region configured. The --region switch can be used to configure an AWS Region.");
            }

            // Create the execution request that will be sent into the LocalLambdaRuntime.
            var request = new ExecutionRequest()
            {
                AWSProfile = awsProfile,
                AWSRegion  = awsRegion,
                Payload    = payload,
                Function   = lambdaFunction
            };

            ExecuteRequest(request, localLambdaOptions, runConfiguration);


            if (runConfiguration.Mode == RunConfiguration.RunMode.Normal && commandOptions.PauseExit)
            {
                Console.WriteLine("Press any key to exist");
                Console.ReadKey();
            }
        }
        private async Task <APIGatewayProxyResponse> InvokeAPIGatewayRequest(TestLambdaContext context, string fileName)
        {
            var lambdaFunction = new LambdaFunction();
            var filePath       = Path.Combine(Path.GetDirectoryName(this.GetType().GetTypeInfo().Assembly.Location), fileName);
            var requestStr     = File.ReadAllText(filePath);
            var request        = JsonConvert.DeserializeObject <APIGatewayProxyRequest>(requestStr);

            return(await lambdaFunction.FunctionHandlerAsync(request, context));
        }
Ejemplo n.º 3
0
        private async Task <APIGatewayProxyResponse> InvokeAPIGatewayRequest(string fileName)
        {
            var context        = new TestLambdaContext();
            var lambdaFunction = new LambdaFunction();
            var requestStr     = File.ReadAllText(fileName);
            var request        = JsonConvert.DeserializeObject <APIGatewayProxyRequest>(requestStr);

            return(await lambdaFunction.FunctionHandlerAsync(request, context));
        }
        public void TestToUpperFunction()
        {
            // Invoke the lambda function and confirm the string was upper cased.
            var function  = new LambdaFunction();
            var context   = new TestLambdaContext();
            var upperCase = function.FunctionHandler("hello world", context);

            Assert.Equal("HELLO WORLD", upperCase);
        }
Ejemplo n.º 5
0
        public async Task TestGetQueryStringValue()
        {
            var lambdaFunction = new LambdaFunction();

            var requestStr = File.ReadAllText("values-get-querystring-apigatway-request.json");
            var request    = JsonConvert.DeserializeObject <APIGatewayProxyRequest>(requestStr);
            var response   = await lambdaFunction.FunctionHandlerAsync(request, null);

            Assert.Equal("Lewis, Meriwether", response.Body);
            Assert.True(response.Headers.ContainsKey("Content-Type"));
            Assert.Equal("text/plain; charset=utf-8", response.Headers["Content-Type"]);
        }
Ejemplo n.º 6
0
        public async Task TestGetAllValues()
        {
            var lambdaFunction = new LambdaFunction();

            var requestStr = File.ReadAllText("values-get-all-apigatway-request.json");
            var request    = JsonConvert.DeserializeObject <APIGatewayProxyRequest>(requestStr);
            var response   = await lambdaFunction.FunctionHandlerAsync(request, null);

            Assert.Equal("[\"value1\",\"value2\"]", response.Body);
            Assert.True(response.Headers.ContainsKey("Content-Type"));
            Assert.Equal("application/json; charset=utf-8", response.Headers["Content-Type"]);
        }
Ejemplo n.º 7
0
        internal LambdaStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            var config = new LambdaConfiguration()
            {
                FunctionName = id,
                Resource     = "./resources/function"
            };

            var lambda = new LambdaFunction(this);

            lambda.Construct(config);
        }
Ejemplo n.º 8
0
        public void ProcessStartAndRun()
        {
            AutoResetEvent handle   = new AutoResetEvent(false);
            int            count    = 0;
            IFunction      function = new LambdaFunction(() => { count = 1; return(handle.Set()); });
            Process        process  = new Process();

            process.Start(function);

            handle.WaitOne();

            Assert.AreEqual(1, count);
        }
Ejemplo n.º 9
0
        public void ProcessStartAndRun()
        {
            AutoResetEvent handle = new AutoResetEvent(false);
            int count = 0;
            IFunction function = new LambdaFunction(() => { count = 1; return handle.Set(); });
            Process process = new Process();

            process.Start(function);

            handle.WaitOne();

            Assert.AreEqual(1, count);
        }
Ejemplo n.º 10
0
        public async Task TestPutWithBody()
        {
            var lambdaFunction = new LambdaFunction();

            var requestStr = File.ReadAllText("values-put-withbody-apigatway-request.json");
            var request    = JsonConvert.DeserializeObject <APIGatewayProxyRequest>(requestStr);
            var response   = await lambdaFunction.FunctionHandlerAsync(request, null);

            Assert.Equal(200, response.StatusCode);
            Assert.Equal("Agent, Smith", response.Body);
            Assert.True(response.Headers.ContainsKey("Content-Type"));
            Assert.Equal("text/plain; charset=utf-8", response.Headers["Content-Type"]);
        }
Ejemplo n.º 11
0
        public void SpawnSimpleProcess()
        {
            AutoResetEvent handle = new AutoResetEvent(false);
            int            count  = 0;
            IFunction      func   = new SpawnFunction();
            IFunction      lambda = new LambdaFunction(() => { count = 1; return(handle.Set()); });

            var result = func.Apply(null, new object[] { lambda });

            Assert.IsNotNull(result);
            Assert.IsInstanceOfType(result, typeof(Process));

            handle.WaitOne();

            Assert.AreEqual(1, count);
        }
Ejemplo n.º 12
0
        public void SpawnSimpleProcess()
        {
            AutoResetEvent handle = new AutoResetEvent(false);
            int count = 0;
            IFunction func = new SpawnFunction();
            IFunction lambda = new LambdaFunction(() => { count = 1; return handle.Set(); });

            var result = func.Apply(null, new object[] { lambda });

            Assert.IsNotNull(result);
            Assert.IsInstanceOfType(result, typeof(Process));

            handle.WaitOne();

            Assert.AreEqual(1, count);
        }
Ejemplo n.º 13
0
        /// <summary>
        /// Starting point: define stack in this method
        /// </summary>
        /// <param name="scope"></param>
        /// <param name="id"></param>
        /// <param name="props"></param>
        /// <returns></returns>
        internal AirQualityCdkStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            // Metadata to be used by internal construct methods - might need a bit of refactoring and better design
            // this holds keyvaluePairs which can be used to configure environmentVariables
            var metadata = new Dictionary <string, KeyValuePair <string, string> >();

            // The code that defines your stack goes here
            // SNS Topics
            new Topic(this, "EmailNotificationPublisher");

            // SQS queues
            var cityFeedSqs = AirQualitySQS("CityFeedQueue");
            // SNS Topics
            var twitterPubSNS = new Topic(this, $"twitterPub-{Guid.NewGuid().ToString().Substring(0,10)}");
            var generalPubSNS = new Topic(this, $"generalPub-{Guid.NewGuid().ToString().Substring(0,10)}");

            // Dynamo DB table
            var tableProps = new Dynamo.TableProps();

            tableProps.TableName = Constants.DbAirQualityTableName;
            var primaryKey = new Dynamo.Attribute {
                Name = Constants.DbPartitionKeyName, Type = Dynamo.AttributeType.STRING
            };

            tableProps.BillingMode  = Dynamo.BillingMode.PAY_PER_REQUEST; // on-demand pricing
            tableProps.PartitionKey = primaryKey;
            tableProps.Stream       = Dynamo.StreamViewType.NEW_IMAGE;
            var airqualityTable = new Dynamo.Table(this, Constants.DbAirQualityTableName, tableProps);

            //Environment value metadata for lambda creation
            metadata[Constants.EnvCityFeedSqsUrl]     = KeyValuePair.Create(Constants.EnvCityFeedSqsUrl, cityFeedSqs.QueueUrl);
            metadata[Constants.EnvTwitterSNS]         = KeyValuePair.Create(Constants.EnvTwitterSNS, twitterPubSNS.TopicArn);
            metadata[Constants.EnvTwitterAPIKey]      = KeyValuePair.Create(Constants.EnvTwitterAPIKey, System.Environment.GetEnvironmentVariable(Constants.EnvTwitterAPIKey));
            metadata[Constants.EnvTwitterAPISecret]   = KeyValuePair.Create(Constants.EnvTwitterAPISecret, System.Environment.GetEnvironmentVariable(Constants.EnvTwitterAPISecret));
            metadata[Constants.EnvTwitterAccessToken] = KeyValuePair.Create(Constants.EnvTwitterAccessToken, System.Environment.GetEnvironmentVariable(Constants.EnvTwitterAccessToken));
            metadata[Constants.EnvTwitterTokenSecret] = KeyValuePair.Create(Constants.EnvTwitterTokenSecret, System.Environment.GetEnvironmentVariable(Constants.EnvTwitterTokenSecret));
            metadata[Constants.EnvAirQualityTable]    = KeyValuePair.Create(Constants.EnvAirQualityTable, airqualityTable.TableName);
            metadata[Constants.EnvGeneralSNSTopic]    = KeyValuePair.Create(Constants.EnvGeneralSNSTopic, generalPubSNS.TopicArn);
            // AWS lambdas
            // TODO: Lambda generation logic to be done using environment values. Config might also be pulled from S3
            // GetCityFeed lambda
            var functionsByName = ConstructLambdas(metadata);

            // subscribe and configure
            // find twitter publisher lambda

            twitterPubSNS.AddSubscription(new LambdaSubscription(functionsByName
                                                                 .Where(pair => pair.Key.Contains(Constants.DefaultAirQualityTwitterPublisherLambdaName))
                                                                 .Single().Value));

            // trigger feed processor lambda only on dynamo db stream change by coutry-city feed
            functionsByName
            .Where(pair => pair.Key.Contains(Constants.DefaultAirQualityFeedProcessorLambdaName))
            .Single().Value.AddEventSource(new DynamoEventSource(airqualityTable, new DynamoEventSourceProps()));

            // Event schedule every 15 mins - // architecture targets 5, change when tested and working
            var waqiLambda = functionsByName
                             .Where(pair => pair.Key.Contains(Constants.DefaultWaqiGetCityFeedLambdaName))
                             .Single().Value;
            var targetWaqiLambda = new LambdaFunction(waqiLambda);

            new Rule(this, "Waqi5min", new RuleProps {
                Schedule = Schedule.Rate(Duration.Minutes(5))
            }).AddTarget(targetWaqiLambda);
        }
        public bool TryLoadLambdaFuntion(LambdaConfigInfo configInfo, string functionHandler, out LambdaFunction lambdaFunction)
        {
            lambdaFunction = null;
            try
            {
                lambdaFunction = LoadLambdaFuntion(configInfo, functionHandler);
                return(true);
            }
            catch { }

            return(false);
        }
        public SrcStack(Construct scope, string id, IStackProps props) : base(scope, id, props)
        {
            #region VPC, Subnets and Security Groups
            IVpc batchVpc = new Vpc(this, Constants.VPC_ID, new VpcProps {
                Cidr   = Constants.CIDR_RANGE,
                MaxAzs = 4
            });

            var privateSubnetIds = new List <string>();
            foreach (Subnet subnet in batchVpc.PrivateSubnets)
            {
                privateSubnetIds.Add(subnet.SubnetId);
            }

            var batchSecurityGroup = new SecurityGroup(this, Constants.BATCH_SECURITY_GROUP_ID,
                                                       new SecurityGroupProps {
                Vpc = batchVpc,
                SecurityGroupName = Constants.BATCH_SECURITY_GROUP_NAME,
                Description       = Constants.BATCH_SECURITY_GROUP_DESCRIPTION,
            }
                                                       );

            var batchSecurityGroupIds = new List <string>()
            {
                batchSecurityGroup.SecurityGroupId
            };

            #endregion

            #region S3, DynamoDB, Lambda (to trigger the batch on file drop)
            s3.Bucket bucket = new s3.Bucket(this, Constants.S3_BUCKET_ID, new s3.BucketProps {
                BucketName = Constants.S3_BUCKET_NAME + this.Account
            });
            var bucketName = bucket.BucketName;

            var gsi = new dynamo.GlobalSecondaryIndexProps()
            {
                IndexName    = "GSI",
                PartitionKey = new dynamo.Attribute {
                    Name = "CreatedTime", Type = dynamo.AttributeType.STRING
                },
                ProjectionType = dynamo.ProjectionType.KEYS_ONLY
            };

            dynamo.Table table = new dynamo.Table(this, Constants.DynamoDB_TABLE_ID, new dynamo.TableProps {
                TableName    = Constants.DynamoDB_TABLE_ID,
                PartitionKey = new dynamo.Attribute {
                    Name = "ProductId", Type = dynamo.AttributeType.STRING
                },
                BillingMode = dynamo.BillingMode.PAY_PER_REQUEST
            });
            table.AddGlobalSecondaryIndex(gsi);


            var lambdaBatchExecutionRoleProvider = new LambdaBatchExecutionRole(this, Constants.LAMBDA_BATCH_EXECUTION_ROLE_ID);
            #endregion

            DockerImageAsset imageAsset = new DockerImageAsset(this, "BatchProcessorImage", new DockerImageAssetProps {
                Directory      = Constants.BATCH_PROCESSOR_PYTHON_CODE_PATH,
                RepositoryName = Constants.ECR_REPOSITORY_NAME
            });

            #region Batch - ComputeEnvironment - Job Queue - Job Definition
            var batchServiceRole     = new BatchServiceRole(this, Constants.BATCH_SERVICE_ROLE_ID);
            var ecsInstanceRole      = new EcsInstanceRole(this, Constants.ECS_INSTANCE_ROLE_ID);
            var batchInstanceProfile = new InstanceProfile(this, Constants.BATCH_INSTANCE_PROFILE_ID, ecsInstanceRole);

            var computeEnvironment = new batch.CfnComputeEnvironment(this, Constants.BATCH_COMPUTE_ENVIRONMENT_ID,
                                                                     new batch.CfnComputeEnvironmentProps {
                ComputeEnvironmentName = Constants.BATCH_COMPUTE_ENVIRONMENT_NAME,
                Type             = Constants.BATCH_COMPUTE_TYPE,
                ServiceRole      = batchServiceRole.Role.RoleName,
                ComputeResources = new batch.CfnComputeEnvironment.ComputeResourcesProperty {
                    Type          = Constants.BATCH_COMPUTE_RESOURCE_TYPE,
                    MinvCpus      = 0,
                    MaxvCpus      = 32,
                    DesiredvCpus  = 0,
                    InstanceRole  = ecsInstanceRole.Role.RoleName,
                    InstanceTypes = new string[] {
                        Constants.BATCH_INSTANCE_TYPE
                    },
                    SecurityGroupIds = batchSecurityGroupIds.ToArray(),
                    Subnets          = privateSubnetIds.ToArray()
                }
            });

            var computeEnvironmentOrders = new List <batch.CfnJobQueue.ComputeEnvironmentOrderProperty>();
            var computeEnvironmentOrder  = new batch.CfnJobQueue.ComputeEnvironmentOrderProperty()
            {
                Order = 1,
                ComputeEnvironment = computeEnvironment.Ref
            };
            computeEnvironmentOrders.Add(computeEnvironmentOrder);

            var batchProcessingJobQueue = new batch.CfnJobQueue(this, Constants.BATCH_JOB_QUEUE_ID, new batch.CfnJobQueueProps {
                JobQueueName            = Constants.BATCH_PROCESSING_JOB_QUEUE,
                Priority                = 1,
                ComputeEnvironmentOrder = computeEnvironmentOrders.ToArray()
            });

            var batchProcessingJobDefinition = new batch.CfnJobDefinition(this, Constants.BATCH_JOB_DEFINITION_ID, new batch.CfnJobDefinitionProps {
                Type = Constants.CONTAINER,
                JobDefinitionName   = Constants.BATCH_JOB_DEFINITION_NAME,
                ContainerProperties = new batch.CfnJobDefinition.ContainerPropertiesProperty()
                {
                    Image   = imageAsset.ImageUri,
                    Vcpus   = Constants.BATCH_JOB_DEFINITION_VCPU,
                    Memory  = Constants.BATCH_JOB_DEFINITION_MemoryLimitMiB,
                    Command = new string[] {
                        "python",
                        "batch_processor.py"
                    }
                }
            });
            #endregion


            #region lambda s3 event trigger

            BatchTriggerLambdaInput batchTriggerLambdaInput = new BatchTriggerLambdaInput {
                BucketName         = bucketName,
                FileName           = "sample.csv",
                Region             = "us-east-1",
                BatchJobDefinition = batchProcessingJobDefinition.JobDefinitionName,
                BatchJobName       = Constants.BATCH_JOB_NAME,
                BatchJobQueue      = batchProcessingJobQueue.JobQueueName,
                DBTable            = table.TableName
            };

            lambda.Function lambda = BatchTriggerLambda.BatchTriggerLambdaFunction(this, Constants.LAMBDA_NAME,
                                                                                   batchTriggerLambdaInput, lambdaBatchExecutionRoleProvider);

            var batchLambdaFunction = new LambdaFunction(
                lambda
                );

            var eventPutSource = new eventsources.S3EventSource(bucket, new eventsources.S3EventSourceProps {
                Events = new s3.EventType[] {
                    s3.EventType.OBJECT_CREATED_PUT
                }
            });

            lambda.AddEventSource(eventPutSource);

            #endregion

            #region OUTPUTS
            var cfnComputeOutput = new CfnOutput(this, Constants.BATCH_COMPUTE_ENVIRONMENT_NAME_OUTPUT_ID,
                                                 new CfnOutputProps {
                Value = computeEnvironment.Ref
            }
                                                 );

            var cfnS3Output = new CfnOutput(this, Constants.S3_BUCKET_OUTPUT_ID,
                                            new CfnOutputProps {
                Value = bucket.BucketName
            }
                                            );

            var cfnEcrRepositoryOutput = new CfnOutput(this, Constants.ECR_REPOSITORY_OUTPUT_ID,
                                                       new CfnOutputProps {
                Value = imageAsset.Repository.RepositoryArn
            }
                                                       );

            var cfnDynamoTableOutput = new CfnOutput(this, Constants.DYNAMO_TABLE_OUTPUT_ID,
                                                     new CfnOutputProps {
                Value = table.TableName
            }
                                                     );

            var cfnLambdaRepositoryOutput = new CfnOutput(this, Constants.LAMBDA_OUTPUT_ID,
                                                          new CfnOutputProps {
                Value = lambda.FunctionArn
            }
                                                          );

            #endregion

            Tag.Add(this, "Name", Constants.APP_NAME);
        }