コード例 #1
0
        protected override Task <bool> PerformActionAsync()
        {
            EnsureInProjectDirectory();

            // Disable interactive since this command is intended to be run as part of a pipeline.
            this.DisableInteractive = true;

            return(Task.Run(() =>
            {
                // Release will be the default configuration if nothing set.
                var configuration = this.GetStringValueOrDefault(this.Configuration, CommonDefinedCommandOptions.ARGUMENT_CONFIGURATION, false);

                var targetFramework = this.GetStringValueOrDefault(this.TargetFramework, CommonDefinedCommandOptions.ARGUMENT_FRAMEWORK, true);
                var projectLocation = this.GetStringValueOrDefault(this.ProjectLocation, CommonDefinedCommandOptions.ARGUMENT_PROJECT_LOCATION, false);
                var msbuildParameters = this.GetStringValueOrDefault(this.MSBuildParameters, CommonDefinedCommandOptions.ARGUMENT_MSBUILD_PARAMETERS, false);
                var disableVersionCheck = this.GetBoolValueOrDefault(this.DisableVersionCheck, LambdaDefinedCommandOptions.ARGUMENT_DISABLE_VERSION_CHECK, false).GetValueOrDefault();

                var zipArchivePath = GetStringValueOrDefault(this.OutputPackageFileName, LambdaDefinedCommandOptions.ARGUMENT_OUTPUT_PACKAGE, false);

                string publishLocation;
                var success = LambdaPackager.CreateApplicationBundle(this.DefaultConfig, this.Logger, this.WorkingDirectory, projectLocation, configuration, targetFramework, msbuildParameters, disableVersionCheck, out publishLocation, ref zipArchivePath);
                if (!success)
                {
                    this.Logger.WriteLine("Failed to create application package");
                    return false;
                }


                this.Logger.WriteLine("Lambda project successfully packaged: " + zipArchivePath);

                return true;
            }));
        }
コード例 #2
0
        protected override async Task <bool> PerformActionAsync()
        {
            EnsureInProjectDirectory();

            // Disable interactive since this command is intended to be run as part of a pipeline.
            DisableInteractive = true;

            string projectLocation    = this.GetStringValueOrDefault(this.ProjectLocation, CommonDefinedCommandOptions.ARGUMENT_PROJECT_LOCATION, false);
            string s3Bucket           = this.GetStringValueOrDefault(this.S3Bucket, LambdaDefinedCommandOptions.ARGUMENT_S3_BUCKET, true);
            string s3Prefix           = this.GetStringValueOrDefault(this.S3Prefix, LambdaDefinedCommandOptions.ARGUMENT_S3_PREFIX, false);
            string templatePath       = this.GetStringValueOrDefault(this.CloudFormationTemplate, LambdaDefinedCommandOptions.ARGUMENT_CLOUDFORMATION_TEMPLATE, true);
            string outputTemplatePath = this.GetStringValueOrDefault(this.CloudFormationOutputTemplate, LambdaDefinedCommandOptions.ARGUMENT_OUTPUT_CLOUDFORMATION_TEMPLATE, true);

            if (!Path.IsPathRooted(templatePath))
            {
                templatePath = Path.Combine(Utilities.DetermineProjectLocation(this.WorkingDirectory, projectLocation), templatePath);
            }

            if (!File.Exists(templatePath))
            {
                throw new LambdaToolsException($"Template file {templatePath} cannot be found.", LambdaToolsException.LambdaErrorCode.ServerlessTemplateNotFound);
            }

            await Utilities.ValidateBucketRegionAsync(this.S3Client, s3Bucket);

            string zipArchivePath      = null;
            var    configuration       = this.GetStringValueOrDefault(this.Configuration, CommonDefinedCommandOptions.ARGUMENT_CONFIGURATION, true);
            var    targetFramework     = this.GetStringValueOrDefault(this.TargetFramework, CommonDefinedCommandOptions.ARGUMENT_FRAMEWORK, true);
            var    msbuildParameters   = this.GetStringValueOrDefault(this.MSBuildParameters, CommonDefinedCommandOptions.ARGUMENT_MSBUILD_PARAMETERS, false);
            var    disableVersionCheck = this.GetBoolValueOrDefault(this.DisableVersionCheck, LambdaDefinedCommandOptions.ARGUMENT_DISABLE_VERSION_CHECK, false).GetValueOrDefault();
            string publishLocation;

            LambdaPackager.CreateApplicationBundle(this.DefaultConfig, this.Logger, this.WorkingDirectory, projectLocation, configuration, targetFramework, msbuildParameters, disableVersionCheck, out publishLocation, ref zipArchivePath);
            if (string.IsNullOrEmpty(zipArchivePath))
            {
                return(false);
            }

            string s3KeyApplicationBundle;

            using (var stream = new MemoryStream(File.ReadAllBytes(zipArchivePath)))
            {
                s3KeyApplicationBundle = await Utilities.UploadToS3Async(this.Logger, this.S3Client, s3Bucket, s3Prefix, Path.GetFileName(zipArchivePath), stream);
            }

            this.Logger.WriteLine($"Updating CloudFormation template to point to application bundle: s3://{s3Bucket}/{s3KeyApplicationBundle}");
            var templateBody = File.ReadAllText(templatePath);

            // Process any template substitutions
            templateBody = LambdaUtilities.ProcessTemplateSubstitions(this.Logger, templateBody, this.GetKeyValuePairOrDefault(this.TemplateSubstitutions, LambdaDefinedCommandOptions.ARGUMENT_CLOUDFORMATION_TEMPLATE_SUBSTITUTIONS, false), Utilities.DetermineProjectLocation(this.WorkingDirectory, projectLocation));

            var transformedBody = LambdaUtilities.UpdateCodeLocationInTemplate(templateBody, s3Bucket, s3KeyApplicationBundle);

            this.Logger.WriteLine($"Writing updated template: {outputTemplatePath}");
            File.WriteAllText(outputTemplatePath, transformedBody);

            return(true);
        }
コード例 #3
0
        public override Task <bool> ExecuteAsync()
        {
            // Disable interactive since this command is intended to be run as part of a pipeline.
            this.DisableInteractive = true;

            return(Task.Run(() =>
            {
                try
                {
                    string configuration = this.GetStringValueOrDefault(this.Configuration, DefinedCommandOptions.ARGUMENT_CONFIGURATION, true);
                    string targetFramework = this.GetStringValueOrDefault(this.TargetFramework, DefinedCommandOptions.ARGUMENT_FRAMEWORK, true);
                    string projectLocation = this.GetStringValueOrDefault(this.ProjectLocation, DefinedCommandOptions.ARGUMENT_PROJECT_LOCATION, false);
                    string msbuildParameters = this.GetStringValueOrDefault(this.MSBuildParameters, DefinedCommandOptions.ARGUMENT_MSBUILD_PARAMETERS, false);
                    bool disableVersionCheck = this.GetBoolValueOrDefault(this.DisableVersionCheck, DefinedCommandOptions.ARGUMENT_DISABLE_VERSION_CHECK, false).GetValueOrDefault();

                    var zipArchivePath = GetStringValueOrDefault(this.OutputPackageFileName, DefinedCommandOptions.ARGUMENT_OUTPUT_PACKAGE, false);

                    string publishLocation;
                    bool success = LambdaPackager.CreateApplicationBundle(this.DefaultConfig, this.Logger, this.WorkingDirectory, projectLocation, configuration, targetFramework, msbuildParameters, disableVersionCheck, out publishLocation, ref zipArchivePath);
                    if (!success)
                    {
                        this.Logger.WriteLine("Failed to create application package");
                        return false;
                    }


                    this.Logger.WriteLine("Lambda project successfully packaged: " + zipArchivePath);
                    return true;
                }
                catch (LambdaToolsException e)
                {
                    this.Logger.WriteLine(e.Message);
                    this.LastToolsException = e;
                    return false;
                }
                catch (Exception e)
                {
                    this.Logger.WriteLine($"Unknown error executing Lambda packaging: {e.Message}");
                    this.Logger.WriteLine(e.StackTrace);
                    return false;
                }
            }));
        }
コード例 #4
0
        public override Task <bool> ExecuteAsync()
        {
            return(Task.Run(() =>
            {
                try
                {
                    string configuration = this.GetStringValueOrDefault(this.Configuration, DefinedCommandOptions.ARGUMENT_CONFIGURATION, true);
                    string targetFramework = this.GetStringValueOrDefault(this.TargetFramework, DefinedCommandOptions.ARGUMENT_FRAMEWORK, true);
                    string projectLocation = this.GetStringValueOrDefault(this.ProjectLocation, DefinedCommandOptions.ARGUMENT_PROJECT_LOCATION, false);

                    var zipArchivePath = GetStringValueOrDefault(this.OutputPackageFileName, DefinedCommandOptions.ARGUMENT_OUTPUT_PACKAGE, false);

                    string publishLocation;
                    bool success = LambdaPackager.CreateApplicationBundle(this.DefaultConfig, this.Logger, this.WorkingDirectory, projectLocation, configuration, targetFramework, out publishLocation, ref zipArchivePath);
                    if (!success)
                    {
                        this.Logger.WriteLine("Failed to create application package");
                        return false;
                    }


                    this.Logger.WriteLine("Lambda project successfully packaged: " + zipArchivePath);
                    return true;
                }
                catch (LambdaToolsException e)
                {
                    this.Logger.WriteLine(e.Message);
                    this.LastToolsException = e;
                    return false;
                }
                catch (Exception e)
                {
                    this.Logger.WriteLine($"Unknown error executing Lambda packaging: {e.Message}");
                    this.Logger.WriteLine(e.StackTrace);
                    return false;
                }
            }));
        }
コード例 #5
0
        public override async Task <bool> ExecuteAsync()
        {
            try
            {
                string projectLocation = this.GetStringValueOrDefault(this.ProjectLocation, DefinedCommandOptions.ARGUMENT_PROJECT_LOCATION, false);
                string zipArchivePath  = null;
                string publishLocation = null;
                string package         = this.GetStringValueOrDefault(this.Package, DefinedCommandOptions.ARGUMENT_PACKAGE, false);
                if (string.IsNullOrEmpty(package))
                {
                    string configuration   = this.GetStringValueOrDefault(this.Configuration, DefinedCommandOptions.ARGUMENT_CONFIGURATION, true);
                    string targetFramework = this.GetStringValueOrDefault(this.TargetFramework, DefinedCommandOptions.ARGUMENT_FRAMEWORK, true);

                    ValidateTargetFrameworkAndLambdaRuntime();

                    LambdaPackager.CreateApplicationBundle(this.DefaultConfig, this.Logger, this.WorkingDirectory, projectLocation, configuration, targetFramework, out publishLocation, ref zipArchivePath);
                    if (string.IsNullOrEmpty(zipArchivePath))
                    {
                        return(false);
                    }
                }
                else
                {
                    if (!File.Exists(package))
                    {
                        throw new LambdaToolsException($"Package {package} does not exist", LambdaToolsException.ErrorCode.InvalidPackage);
                    }
                    if (!string.Equals(Path.GetExtension(package), ".zip", StringComparison.OrdinalIgnoreCase))
                    {
                        throw new LambdaToolsException($"Package {package} must be a zip file", LambdaToolsException.ErrorCode.InvalidPackage);
                    }

                    this.Logger.WriteLine($"Skipping compilation and using precompiled package {package}");
                    zipArchivePath = package;
                }


                using (var stream = new MemoryStream(File.ReadAllBytes(zipArchivePath)))
                {
                    var    s3Bucket = this.GetStringValueOrDefault(this.S3Bucket, DefinedCommandOptions.ARGUMENT_S3_BUCKET, false);
                    string s3Key    = null;
                    if (!string.IsNullOrEmpty(s3Bucket))
                    {
                        await Utilities.ValidateBucketRegionAsync(this.S3Client, s3Bucket);

                        var functionName = this.GetStringValueOrDefault(this.FunctionName, DefinedCommandOptions.ARGUMENT_FUNCTION_NAME, true);
                        var s3Prefix     = this.GetStringValueOrDefault(this.S3Prefix, DefinedCommandOptions.ARGUMENT_S3_PREFIX, false);
                        s3Key = await Utilities.UploadToS3Async(this.Logger, this.S3Client, s3Bucket, s3Prefix, functionName, stream);
                    }


                    var currentConfiguration = await GetFunctionConfigurationAsync();

                    if (currentConfiguration == null)
                    {
                        this.Logger.WriteLine($"Creating new Lambda function {this.FunctionName}");
                        var createRequest = new CreateFunctionRequest
                        {
                            FunctionName = this.GetStringValueOrDefault(this.FunctionName, DefinedCommandOptions.ARGUMENT_FUNCTION_NAME, true),
                            Description  = this.GetStringValueOrDefault(this.Description, DefinedCommandOptions.ARGUMENT_FUNCTION_DESCRIPTION, false),
                            Role         = this.GetStringValueOrDefault(this.Role, DefinedCommandOptions.ARGUMENT_FUNCTION_ROLE, true),
                            Handler      = this.GetStringValueOrDefault(this.Handler, DefinedCommandOptions.ARGUMENT_FUNCTION_HANDLER, true),
                            Publish      = this.GetBoolValueOrDefault(this.Publish, DefinedCommandOptions.ARGUMENT_FUNCTION_PUBLISH, false).GetValueOrDefault(),
                            MemorySize   = this.GetIntValueOrDefault(this.MemorySize, DefinedCommandOptions.ARGUMENT_FUNCTION_MEMORY_SIZE, true).GetValueOrDefault(),
                            Runtime      = this.GetStringValueOrDefault(this.Runtime, DefinedCommandOptions.ARGUMENT_FUNCTION_RUNTIME, true),
                            Timeout      = this.GetIntValueOrDefault(this.Timeout, DefinedCommandOptions.ARGUMENT_FUNCTION_TIMEOUT, true).GetValueOrDefault(),
                            KMSKeyArn    = this.GetStringValueOrDefault(this.KMSKeyArn, DefinedCommandOptions.ARGUMENT_KMS_KEY_ARN, false),
                            VpcConfig    = new VpcConfig
                            {
                                SubnetIds        = this.GetStringValuesOrDefault(this.SubnetIds, DefinedCommandOptions.ARGUMENT_FUNCTION_SUBNETS, false)?.ToList(),
                                SecurityGroupIds = this.GetStringValuesOrDefault(this.SecurityGroupIds, DefinedCommandOptions.ARGUMENT_FUNCTION_SECURITY_GROUPS, false)?.ToList()
                            }
                        };

                        var environmentVariables = this.GetKeyValuePairOrDefault(this.EnvironmentVariables, DefinedCommandOptions.ARGUMENT_ENVIRONMENT_VARIABLES, false);
                        if (environmentVariables != null && environmentVariables.Count > 0)
                        {
                            createRequest.Environment = new Model.Environment
                            {
                                Variables = environmentVariables
                            };
                        }

                        var deadLetterQueue = this.GetStringValueOrDefault(this.DeadLetterTargetArn, DefinedCommandOptions.ARGUMENT_DEADLETTER_TARGET_ARN, false);
                        if (!string.IsNullOrEmpty(deadLetterQueue))
                        {
                            createRequest.DeadLetterConfig = new DeadLetterConfig {
                                TargetArn = deadLetterQueue
                            };
                        }

                        if (s3Bucket != null)
                        {
                            createRequest.Code = new FunctionCode
                            {
                                S3Bucket = s3Bucket,
                                S3Key    = s3Key
                            };
                        }
                        else
                        {
                            createRequest.Code = new FunctionCode
                            {
                                ZipFile = stream
                            };
                        }


                        if (!this.SkipHandlerValidation && !string.IsNullOrEmpty(publishLocation))
                        {
                            createRequest.Handler = EnsureFunctionHandlerIsValid(publishLocation, createRequest.Handler);
                        }

                        try
                        {
                            await this.LambdaClient.CreateFunctionAsync(createRequest);

                            this.Logger.WriteLine("New Lambda function created");
                        }
                        catch (Exception e)
                        {
                            throw new LambdaToolsException($"Error creating Lambda function: {e.Message}", LambdaToolsException.ErrorCode.LambdaCreateFunction, e);
                        }
                    }
                    else
                    {
                        if (!this.SkipHandlerValidation && !string.IsNullOrEmpty(publishLocation))
                        {
                            if (!string.IsNullOrEmpty(this.Handler))
                            {
                                this.Handler = EnsureFunctionHandlerIsValid(publishLocation, this.Handler);
                            }
                            else
                            {
                                this.Handler = EnsureFunctionHandlerIsValid(publishLocation, currentConfiguration.Handler);
                            }
                        }

                        this.Logger.WriteLine($"Updating code for existing function {this.FunctionName}");

                        var updateCodeRequest = new UpdateFunctionCodeRequest
                        {
                            FunctionName = this.GetStringValueOrDefault(this.FunctionName, DefinedCommandOptions.ARGUMENT_FUNCTION_NAME, true)
                        };

                        if (s3Bucket != null)
                        {
                            updateCodeRequest.S3Bucket = s3Bucket;
                            updateCodeRequest.S3Key    = s3Key;
                        }
                        else
                        {
                            updateCodeRequest.ZipFile = stream;
                        }

                        try
                        {
                            await this.LambdaClient.UpdateFunctionCodeAsync(updateCodeRequest);
                        }
                        catch (Exception e)
                        {
                            throw new LambdaToolsException($"Error updating code for Lambda function: {e.Message}", LambdaToolsException.ErrorCode.LambdaUpdateFunctionCode, e);
                        }

                        await base.UpdateConfigAsync(currentConfiguration);
                    }
                }


                if (this.GetBoolValueOrDefault(this.PersistConfigFile, DefinedCommandOptions.ARGUMENT_PERSIST_CONFIG_FILE, false).GetValueOrDefault())
                {
                    this.SaveConfigFile();
                }

                return(true);
            }
            catch (LambdaToolsException e)
            {
                this.Logger.WriteLine(e.Message);
                this.LastToolsException = e;
                return(false);
            }
            catch (Exception e)
            {
                this.Logger.WriteLine($"Unknown error executing Lambda deployment: {e.Message}");
                this.Logger.WriteLine(e.StackTrace);
                return(false);
            }
        }
コード例 #6
0
        protected override async Task <bool> PerformActionAsync()
        {
            string projectLocation = this.GetStringValueOrDefault(this.ProjectLocation, CommonDefinedCommandOptions.ARGUMENT_PROJECT_LOCATION, false);
            string zipArchivePath  = null;
            string package         = this.GetStringValueOrDefault(this.Package, LambdaDefinedCommandOptions.ARGUMENT_PACKAGE, false);

            var layerVersionArns = this.GetStringValuesOrDefault(this.LayerVersionArns, LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_LAYERS, false);
            var layerPackageInfo = await LambdaUtilities.LoadLayerPackageInfos(this.Logger, this.LambdaClient, this.S3Client, layerVersionArns);

            Lambda.PackageType packageType = DeterminePackageType();
            string             ecrImageUri = null;

            if (packageType == Lambda.PackageType.Image)
            {
                var pushResults = await PushLambdaImageAsync();

                if (!pushResults.Success)
                {
                    if (pushResults.LastToolsException != null)
                    {
                        throw pushResults.LastToolsException;
                    }

                    return(false);
                }

                ecrImageUri = pushResults.ImageUri;
            }
            else
            {
                if (string.IsNullOrEmpty(package))
                {
                    EnsureInProjectDirectory();

                    // Release will be the default configuration if nothing set.
                    string configuration = this.GetStringValueOrDefault(this.Configuration, CommonDefinedCommandOptions.ARGUMENT_CONFIGURATION, false);

                    var targetFramework = this.GetStringValueOrDefault(this.TargetFramework, CommonDefinedCommandOptions.ARGUMENT_FRAMEWORK, false);
                    if (string.IsNullOrEmpty(targetFramework))
                    {
                        targetFramework = Utilities.LookupTargetFrameworkFromProjectFile(Utilities.DetermineProjectLocation(this.WorkingDirectory, projectLocation));

                        // If we still don't know what the target framework is ask the user what targetframework to use.
                        // This is common when a project is using multi targeting.
                        if (string.IsNullOrEmpty(targetFramework))
                        {
                            targetFramework = this.GetStringValueOrDefault(this.TargetFramework, CommonDefinedCommandOptions.ARGUMENT_FRAMEWORK, true);
                        }
                    }
                    string msbuildParameters = this.GetStringValueOrDefault(this.MSBuildParameters, CommonDefinedCommandOptions.ARGUMENT_MSBUILD_PARAMETERS, false);

                    ValidateTargetFrameworkAndLambdaRuntime(targetFramework);

                    bool   disableVersionCheck = this.GetBoolValueOrDefault(this.DisableVersionCheck, LambdaDefinedCommandOptions.ARGUMENT_DISABLE_VERSION_CHECK, false).GetValueOrDefault();
                    string publishLocation;
                    LambdaPackager.CreateApplicationBundle(this.DefaultConfig, this.Logger, this.WorkingDirectory, projectLocation, configuration, targetFramework, msbuildParameters, disableVersionCheck, layerPackageInfo, out publishLocation, ref zipArchivePath);
                    if (string.IsNullOrEmpty(zipArchivePath))
                    {
                        return(false);
                    }
                }
                else
                {
                    if (!File.Exists(package))
                    {
                        throw new LambdaToolsException($"Package {package} does not exist", LambdaToolsException.LambdaErrorCode.InvalidPackage);
                    }
                    if (!string.Equals(Path.GetExtension(package), ".zip", StringComparison.OrdinalIgnoreCase))
                    {
                        throw new LambdaToolsException($"Package {package} must be a zip file", LambdaToolsException.LambdaErrorCode.InvalidPackage);
                    }

                    this.Logger.WriteLine($"Skipping compilation and using precompiled package {package}");
                    zipArchivePath = package;
                }
            }


            MemoryStream lambdaZipArchiveStream = null;

            if (zipArchivePath != null)
            {
                lambdaZipArchiveStream = new MemoryStream(File.ReadAllBytes(zipArchivePath));
            }
            try
            {
                var    s3Bucket = this.GetStringValueOrDefault(this.S3Bucket, LambdaDefinedCommandOptions.ARGUMENT_S3_BUCKET, false);
                string s3Key    = null;
                if (zipArchivePath != null && !string.IsNullOrEmpty(s3Bucket))
                {
                    await Utilities.ValidateBucketRegionAsync(this.S3Client, s3Bucket);

                    var functionName = this.GetStringValueOrDefault(this.FunctionName, LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_NAME, true);
                    var s3Prefix     = this.GetStringValueOrDefault(this.S3Prefix, LambdaDefinedCommandOptions.ARGUMENT_S3_PREFIX, false);
                    s3Key = await Utilities.UploadToS3Async(this.Logger, this.S3Client, s3Bucket, s3Prefix, functionName, lambdaZipArchiveStream);
                }


                var currentConfiguration = await GetFunctionConfigurationAsync();

                if (currentConfiguration == null)
                {
                    this.Logger.WriteLine($"Creating new Lambda function {this.FunctionName}");
                    var createRequest = new CreateFunctionRequest
                    {
                        PackageType  = packageType,
                        FunctionName = this.GetStringValueOrDefault(this.FunctionName, LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_NAME, true),
                        Description  = this.GetStringValueOrDefault(this.Description, LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_DESCRIPTION, false),
                        Role         = this.GetRoleValueOrDefault(this.Role, LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_ROLE,
                                                                  Constants.LAMBDA_PRINCIPAL, LambdaConstants.AWS_LAMBDA_MANAGED_POLICY_PREFIX,
                                                                  LambdaConstants.KNOWN_MANAGED_POLICY_DESCRIPTIONS, true),

                        Publish    = this.GetBoolValueOrDefault(this.Publish, LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_PUBLISH, false).GetValueOrDefault(),
                        MemorySize = this.GetIntValueOrDefault(this.MemorySize, LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_MEMORY_SIZE, true).GetValueOrDefault(),
                        Timeout    = this.GetIntValueOrDefault(this.Timeout, LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_TIMEOUT, true).GetValueOrDefault(),
                        KMSKeyArn  = this.GetStringValueOrDefault(this.KMSKeyArn, LambdaDefinedCommandOptions.ARGUMENT_KMS_KEY_ARN, false),
                        VpcConfig  = new VpcConfig
                        {
                            SubnetIds        = this.GetStringValuesOrDefault(this.SubnetIds, LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_SUBNETS, false)?.ToList(),
                            SecurityGroupIds = this.GetStringValuesOrDefault(this.SecurityGroupIds, LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_SECURITY_GROUPS, false)?.ToList()
                        }
                    };

                    if (packageType == Lambda.PackageType.Zip)
                    {
                        createRequest.Handler = this.GetStringValueOrDefault(this.Handler, LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_HANDLER, true);
                        createRequest.Runtime = this.GetStringValueOrDefault(this.Runtime, LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_RUNTIME, true);
                        createRequest.Layers  = layerVersionArns?.ToList();

                        if (s3Bucket != null)
                        {
                            createRequest.Code = new FunctionCode
                            {
                                S3Bucket = s3Bucket,
                                S3Key    = s3Key
                            };
                        }
                        else
                        {
                            createRequest.Code = new FunctionCode
                            {
                                ZipFile = lambdaZipArchiveStream
                            };
                        }
                    }
                    else if (packageType == Lambda.PackageType.Image)
                    {
                        createRequest.Code = new FunctionCode
                        {
                            ImageUri = ecrImageUri
                        };

                        createRequest.ImageConfig = new ImageConfig
                        {
                            Command          = this.GetStringValuesOrDefault(this.ImageCommand, LambdaDefinedCommandOptions.ARGUMENT_IMAGE_COMMAND, false)?.ToList(),
                            EntryPoint       = this.GetStringValuesOrDefault(this.ImageEntryPoint, LambdaDefinedCommandOptions.ARGUMENT_IMAGE_ENTRYPOINT, false)?.ToList(),
                            WorkingDirectory = this.GetStringValueOrDefault(this.ImageWorkingDirectory, LambdaDefinedCommandOptions.ARGUMENT_IMAGE_WORKING_DIRECTORY, false)
                        };
                    }

                    var environmentVariables = GetEnvironmentVariables(null);

                    var dotnetShareStoreVal = layerPackageInfo.GenerateDotnetSharedStoreValue();
                    if (!string.IsNullOrEmpty(dotnetShareStoreVal))
                    {
                        if (environmentVariables == null)
                        {
                            environmentVariables = new Dictionary <string, string>();
                        }
                        environmentVariables[LambdaConstants.ENV_DOTNET_SHARED_STORE] = dotnetShareStoreVal;
                    }

                    if (environmentVariables != null && environmentVariables.Count > 0)
                    {
                        createRequest.Environment = new Model.Environment
                        {
                            Variables = environmentVariables
                        };
                    }

                    var tags = this.GetKeyValuePairOrDefault(this.Tags, LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_TAGS, false);
                    if (tags != null && tags.Count > 0)
                    {
                        createRequest.Tags = tags;
                    }

                    var deadLetterQueue = this.GetStringValueOrDefault(this.DeadLetterTargetArn, LambdaDefinedCommandOptions.ARGUMENT_DEADLETTER_TARGET_ARN, false);
                    if (!string.IsNullOrEmpty(deadLetterQueue))
                    {
                        createRequest.DeadLetterConfig = new DeadLetterConfig {
                            TargetArn = deadLetterQueue
                        };
                    }

                    var tracingMode = this.GetStringValueOrDefault(this.TracingMode, LambdaDefinedCommandOptions.ARGUMENT_TRACING_MODE, false);
                    if (!string.IsNullOrEmpty(tracingMode))
                    {
                        createRequest.TracingConfig = new TracingConfig {
                            Mode = tracingMode
                        };
                    }


                    try
                    {
                        await this.LambdaClient.CreateFunctionAsync(createRequest);

                        this.Logger.WriteLine("New Lambda function created");
                    }
                    catch (Exception e)
                    {
                        throw new LambdaToolsException($"Error creating Lambda function: {e.Message}", LambdaToolsException.LambdaErrorCode.LambdaCreateFunction, e);
                    }
                }
                else
                {
                    this.Logger.WriteLine($"Updating code for existing function {this.FunctionName}");

                    var updateCodeRequest = new UpdateFunctionCodeRequest
                    {
                        FunctionName = this.GetStringValueOrDefault(this.FunctionName, LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_NAME, true)
                    };

                    // In case the function is currently being updated from previous deployment wait till it available
                    // to be updated.
                    if (currentConfiguration.LastUpdateStatus == LastUpdateStatus.InProgress)
                    {
                        await LambdaUtilities.WaitTillFunctionAvailableAsync(Logger, this.LambdaClient, updateCodeRequest.FunctionName);
                    }

                    if (packageType == Lambda.PackageType.Zip)
                    {
                        if (s3Bucket != null)
                        {
                            updateCodeRequest.S3Bucket = s3Bucket;
                            updateCodeRequest.S3Key    = s3Key;
                        }
                        else
                        {
                            updateCodeRequest.ZipFile = lambdaZipArchiveStream;
                        }
                    }
                    else if (packageType == Lambda.PackageType.Image)
                    {
                        updateCodeRequest.ImageUri = ecrImageUri;
                    }

                    try
                    {
                        await this.LambdaClient.UpdateFunctionCodeAsync(updateCodeRequest);
                    }
                    catch (Exception e)
                    {
                        throw new LambdaToolsException($"Error updating code for Lambda function: {e.Message}", LambdaToolsException.LambdaErrorCode.LambdaUpdateFunctionCode, e);
                    }

                    await base.UpdateConfigAsync(currentConfiguration, layerPackageInfo.GenerateDotnetSharedStoreValue());

                    await base.ApplyTags(currentConfiguration.FunctionArn);

                    var publish = this.GetBoolValueOrDefault(this.Publish, LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_PUBLISH, false).GetValueOrDefault();
                    if (publish)
                    {
                        await base.PublishFunctionAsync(updateCodeRequest.FunctionName);
                    }
                }
            }
            finally
            {
                lambdaZipArchiveStream?.Dispose();
            }

            return(true);
        }
コード例 #7
0
        public override async Task <bool> ExecuteAsync()
        {
            try
            {
                string projectLocation = this.GetStringValueOrDefault(this.ProjectLocation, DefinedCommandOptions.ARGUMENT_PROJECT_LOCATION, false);
                string stackName       = this.GetStringValueOrDefault(this.StackName, DefinedCommandOptions.ARGUMENT_STACK_NAME, true);
                string s3Bucket        = this.GetStringValueOrDefault(this.S3Bucket, DefinedCommandOptions.ARGUMENT_S3_BUCKET, true);
                string s3Prefix        = this.GetStringValueOrDefault(this.S3Prefix, DefinedCommandOptions.ARGUMENT_S3_PREFIX, false);
                string templatePath    = this.GetStringValueOrDefault(this.CloudFormationTemplate, DefinedCommandOptions.ARGUMENT_CLOUDFORMATION_TEMPLATE, true);

                await Utilities.ValidateBucketRegionAsync(this.S3Client, s3Bucket);

                if (!Path.IsPathRooted(templatePath))
                {
                    templatePath = Path.Combine(Utilities.DetermineProjectLocation(this.WorkingDirectory, projectLocation), templatePath);
                }

                if (!File.Exists(templatePath))
                {
                    throw new LambdaToolsException($"Template file {templatePath} cannot be found.", LambdaToolsException.ErrorCode.ServerlessTemplateNotFound);
                }


                // Build and bundle up the users project.
                string publishLocation;
                string zipArchivePath = null;
                string package        = this.GetStringValueOrDefault(this.Package, DefinedCommandOptions.ARGUMENT_PACKAGE, false);
                if (string.IsNullOrEmpty(package))
                {
                    string configuration   = this.GetStringValueOrDefault(this.Configuration, DefinedCommandOptions.ARGUMENT_CONFIGURATION, true);
                    string targetFramework = this.GetStringValueOrDefault(this.TargetFramework, DefinedCommandOptions.ARGUMENT_FRAMEWORK, true);
                    LambdaPackager.CreateApplicationBundle(this.DefaultConfig, this.Logger, this.WorkingDirectory, projectLocation, configuration, targetFramework, out publishLocation, ref zipArchivePath);
                    if (string.IsNullOrEmpty(zipArchivePath))
                    {
                        return(false);
                    }
                }
                else
                {
                    if (!File.Exists(package))
                    {
                        throw new LambdaToolsException($"Package {package} does not exist", LambdaToolsException.ErrorCode.InvalidPackage);
                    }
                    if (!string.Equals(Path.GetExtension(package), ".zip", StringComparison.OrdinalIgnoreCase))
                    {
                        throw new LambdaToolsException($"Package {package} must be a zip file", LambdaToolsException.ErrorCode.InvalidPackage);
                    }

                    this.Logger.WriteLine($"Skipping compilation and using precompiled package {package}");
                    zipArchivePath = package;
                }


                // Upload the app bundle to S3
                string s3KeyApplicationBundle;
                using (var stream = new MemoryStream(File.ReadAllBytes(zipArchivePath)))
                {
                    s3KeyApplicationBundle = await Utilities.UploadToS3Async(this.Logger, this.S3Client, s3Bucket, s3Prefix, stackName, stream);
                }

                // Read in the serverless template and update all the locations for Lambda functions to point to the app bundle that was just uploaded.
                string templateBody = File.ReadAllText(templatePath);

                // Process any template substitutions
                templateBody = Utilities.ProcessTemplateSubstitions(this.Logger, templateBody, this.GetKeyValuePairOrDefault(this.TemplateSubstitutions, DefinedCommandOptions.ARGUMENT_CLOUDFORMATION_TEMPLATE_SUBSTITUTIONS, false), Utilities.DetermineProjectLocation(this.WorkingDirectory, projectLocation));

                templateBody = UpdateCodeLocationInTemplate(templateBody, s3Bucket, s3KeyApplicationBundle);

                // Upload the template to S3 instead of sending it straight to CloudFormation to avoid the size limitation
                string s3KeyTemplate;
                using (var stream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(templateBody)))
                {
                    s3KeyTemplate = await Utilities.UploadToS3Async(this.Logger, this.S3Client, s3Bucket, s3Prefix, stackName + "-" + Path.GetFileName(templatePath), stream);
                }

                var existingStack = await GetExistingStackAsync(stackName);

                this.Logger.WriteLine("Found existing stack: " + (existingStack != null));
                var changeSetName = "Lambda-Tools-" + DateTime.Now.Ticks;

                // Determine if the stack is in a good state to be updated.
                ChangeSetType changeSetType;
                if (existingStack == null || existingStack.StackStatus == StackStatus.REVIEW_IN_PROGRESS || existingStack.StackStatus == StackStatus.DELETE_COMPLETE)
                {
                    changeSetType = ChangeSetType.CREATE;
                }
                // If the status was ROLLBACK_COMPLETE that means the stack failed on initial creation
                // and the resources were cleaned up. It is safe to delete the stack so we can recreate it.
                else if (existingStack.StackStatus == StackStatus.ROLLBACK_COMPLETE)
                {
                    await DeleteRollbackCompleteStackAsync(existingStack);

                    changeSetType = ChangeSetType.CREATE;
                }
                // If the status was ROLLBACK_IN_PROGRESS that means the initial creation is failing.
                // Wait to see if it goes into ROLLBACK_COMPLETE status meaning everything got cleaned up and then delete it.
                else if (existingStack.StackStatus == StackStatus.ROLLBACK_IN_PROGRESS)
                {
                    existingStack = await WaitForNoLongerInProgress(existingStack.StackName);

                    if (existingStack != null && existingStack.StackStatus == StackStatus.ROLLBACK_COMPLETE)
                    {
                        await DeleteRollbackCompleteStackAsync(existingStack);
                    }

                    changeSetType = ChangeSetType.CREATE;
                }
                // If the status was DELETE_IN_PROGRESS then just wait for delete to complete
                else if (existingStack.StackStatus == StackStatus.DELETE_IN_PROGRESS)
                {
                    await WaitForNoLongerInProgress(existingStack.StackName);

                    changeSetType = ChangeSetType.CREATE;
                }
                // The Stack state is in a normal state and ready to be updated.
                else if (existingStack.StackStatus == StackStatus.CREATE_COMPLETE ||
                         existingStack.StackStatus == StackStatus.UPDATE_COMPLETE ||
                         existingStack.StackStatus == StackStatus.UPDATE_ROLLBACK_COMPLETE)
                {
                    changeSetType = ChangeSetType.UPDATE;
                }
                // All other states means the Stack is in an inconsistent state.
                else
                {
                    this.Logger.WriteLine($"The stack's current state of {existingStack.StackStatus} is invalid for updating");
                    return(false);
                }

                CreateChangeSetResponse changeSetResponse;
                try
                {
                    var templateParameters = GetTemplateParameters(changeSetType == ChangeSetType.UPDATE ? existingStack : null);
                    if (templateParameters?.Count > 0)
                    {
                        var setParameters = templateParameters.Where(x => !x.UsePreviousValue);
                        if (setParameters?.Count() > 0)
                        {
                            this.Logger.WriteLine("Template Parameters Applied:");
                            foreach (var parameter in setParameters)
                            {
                                this.Logger.WriteLine($"\t{parameter.ParameterKey}: {parameter.ParameterValue}");
                            }
                        }
                    }

                    var capabilities        = new List <string>();
                    var disabledCapabilties = GetStringValuesOrDefault(this.DisabledCapabilities, DefinedCommandOptions.ARGUMENT_CLOUDFORMATION_DISABLE_CAPABILITIES, false);

                    if (disabledCapabilties?.FirstOrDefault(x => string.Equals(x, "CAPABILITY_IAM", StringComparison.OrdinalIgnoreCase)) == null)
                    {
                        capabilities.Add("CAPABILITY_IAM");
                    }
                    if (disabledCapabilties?.FirstOrDefault(x => string.Equals(x, "CAPABILITY_NAMED_IAM", StringComparison.OrdinalIgnoreCase)) == null)
                    {
                        capabilities.Add("CAPABILITY_NAMED_IAM");
                    }

                    var changeSetRequest = new CreateChangeSetRequest
                    {
                        StackName     = stackName,
                        Parameters    = templateParameters,
                        ChangeSetName = changeSetName,
                        ChangeSetType = changeSetType,
                        Capabilities  = capabilities,
                        RoleARN       = this.GetStringValueOrDefault(this.CloudFormationRole, DefinedCommandOptions.ARGUMENT_CLOUDFORMATION_ROLE, false),
                        Tags          = new List <Tag> {
                            new Tag {
                                Key = Constants.SERVERLESS_TAG_NAME, Value = "true"
                            }
                        }
                    };

                    if (new FileInfo(templatePath).Length < Constants.MAX_TEMPLATE_BODY_IN_REQUEST_SIZE)
                    {
                        changeSetRequest.TemplateBody = templateBody;
                    }
                    else
                    {
                        changeSetRequest.TemplateURL = this.S3Client.GetPreSignedURL(new S3.Model.GetPreSignedUrlRequest {
                            BucketName = s3Bucket, Key = s3KeyTemplate, Expires = DateTime.Now.AddHours(1)
                        });
                    }

                    // Create the change set which performs the transformation on the Serverless resources in the template.
                    changeSetResponse = await this.CloudFormationClient.CreateChangeSetAsync(changeSetRequest);


                    this.Logger.WriteLine("CloudFormation change set created");
                }
                catch (LambdaToolsException)
                {
                    throw;
                }
                catch (Exception e)
                {
                    throw new LambdaToolsException($"Error creating CloudFormation change set: {e.Message}", LambdaToolsException.ErrorCode.CloudFormationCreateStack, e);
                }

                // The change set can take a few seconds to be reviewed and be ready to be executed.
                if (!await WaitForChangeSetBeingAvailableAsync(changeSetResponse.Id, existingStack != null))
                {
                    return(false);
                }

                var executeChangeSetRequest = new ExecuteChangeSetRequest
                {
                    StackName     = stackName,
                    ChangeSetName = changeSetResponse.Id
                };

                // Execute the change set.
                DateTime timeChangeSetExecuted = DateTime.Now;
                ExecuteChangeSetResponse executeChangeSetResponse;
                try
                {
                    executeChangeSetResponse = await this.CloudFormationClient.ExecuteChangeSetAsync(executeChangeSetRequest);

                    if (changeSetType == ChangeSetType.CREATE)
                    {
                        this.Logger.WriteLine($"Created CloudFormation stack {stackName}");
                    }
                    else
                    {
                        this.Logger.WriteLine($"Initiated CloudFormation stack update on {stackName}");
                    }
                }
                catch (Exception e)
                {
                    throw new LambdaToolsException($"Error executing CloudFormation change set: {e.Message}", LambdaToolsException.ErrorCode.CloudFormationCreateChangeSet, e);
                }

                // Wait for the stack to finish unless the user opts out of waiting. The VS Toolkit opts out and
                // instead shows the stack view in the IDE, enabling the user to view progress.
                var shouldWait = GetBoolValueOrDefault(this.WaitForStackToComplete, DefinedCommandOptions.ARGUMENT_STACK_WAIT, false);
                if (!shouldWait.HasValue || shouldWait.Value)
                {
                    var updatedStack = await WaitStackToCompleteAsync(stackName, timeChangeSetExecuted);

                    if (updatedStack.StackStatus == StackStatus.CREATE_COMPLETE || updatedStack.StackStatus == StackStatus.UPDATE_COMPLETE)
                    {
                        this.Logger.WriteLine($"Stack finished updating with status: {updatedStack.StackStatus}");

                        // Display the output parameters.
                        DisplayOutputs(updatedStack);
                    }
                    else
                    {
                        this.Logger.WriteLine($"Stack update failed with status: {updatedStack.StackStatus} ({updatedStack.StackStatusReason})");
                        return(false);
                    }
                }

                if (this.GetBoolValueOrDefault(this.PersistConfigFile, DefinedCommandOptions.ARGUMENT_PERSIST_CONFIG_FILE, false).GetValueOrDefault())
                {
                    this.SaveConfigFile();
                }

                return(true);
            }
            catch (LambdaToolsException e)
            {
                this.Logger.WriteLine(e.Message);
                this.LastToolsException = e;
                return(false);
            }
            catch (Exception e)
            {
                this.Logger.WriteLine($"Unknown error executing AWS Serverless deployment: {e.Message}");
                this.Logger.WriteLine(e.StackTrace);
                return(false);
            }
        }
コード例 #8
0
        protected override async Task <bool> PerformActionAsync()
        {
            EnsureInProjectDirectory();

            // Disable interactive since this command is intended to be run as part of a pipeline.
            this.DisableInteractive = true;

            var layerVersionArns = this.GetStringValuesOrDefault(this.LayerVersionArns, LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_LAYERS, false);
            LayerPackageInfo layerPackageInfo = null;

            if (layerVersionArns != null)
            {
                if (!this.DisableRegionAndCredentialsCheck)
                {
                    // Region and credentials are only required if using layers. This is new behavior so do a preemptive check when there are layers to
                    // see if region and credentials are set. If they are not set give a specific error message about region and credentials required
                    // when using layers.
                    try
                    {
                        base.DetermineAWSRegion();
                    }
                    catch (Exception)
                    {
                        throw new ToolsException("Region is required for the package command when layers are specified. The layers must be inspected to see how they affect packaging.", ToolsException.CommonErrorCode.RegionNotConfigured);
                    }
                    try
                    {
                        base.DetermineAWSCredentials();
                    }
                    catch (Exception)
                    {
                        throw new ToolsException("AWS credentials are required for the package command when layers are specified. The layers must be inspected to see how they affect packaging.", ToolsException.CommonErrorCode.InvalidCredentialConfiguration);
                    }
                }

                layerPackageInfo = await LambdaUtilities.LoadLayerPackageInfos(this.Logger, this.LambdaClient, this.S3Client, layerVersionArns);
            }
            else
            {
                layerPackageInfo = new LayerPackageInfo();
            }

            var projectLocation = this.GetStringValueOrDefault(this.ProjectLocation, CommonDefinedCommandOptions.ARGUMENT_PROJECT_LOCATION, false);

            // Release will be the default configuration if nothing set.
            var configuration = this.GetStringValueOrDefault(this.Configuration, CommonDefinedCommandOptions.ARGUMENT_CONFIGURATION, false);

            var targetFramework = this.GetStringValueOrDefault(this.TargetFramework, CommonDefinedCommandOptions.ARGUMENT_FRAMEWORK, false);

            if (string.IsNullOrEmpty(targetFramework))
            {
                targetFramework = Utilities.LookupTargetFrameworkFromProjectFile(Utilities.DetermineProjectLocation(this.WorkingDirectory, projectLocation));
            }

            var msbuildParameters   = this.GetStringValueOrDefault(this.MSBuildParameters, CommonDefinedCommandOptions.ARGUMENT_MSBUILD_PARAMETERS, false);
            var disableVersionCheck = this.GetBoolValueOrDefault(this.DisableVersionCheck, LambdaDefinedCommandOptions.ARGUMENT_DISABLE_VERSION_CHECK, false).GetValueOrDefault();

            var zipArchivePath = GetStringValueOrDefault(this.OutputPackageFileName, LambdaDefinedCommandOptions.ARGUMENT_OUTPUT_PACKAGE, false);

            string publishLocation;
            var    success = LambdaPackager.CreateApplicationBundle(this.DefaultConfig, this.Logger, this.WorkingDirectory, projectLocation, configuration, targetFramework, msbuildParameters, disableVersionCheck, layerPackageInfo, out publishLocation, ref zipArchivePath);

            if (!success)
            {
                this.Logger.WriteLine("Failed to create application package");
                return(false);
            }


            this.Logger.WriteLine("Lambda project successfully packaged: " + zipArchivePath);
            var dotnetSharedStoreValue = layerPackageInfo.GenerateDotnetSharedStoreValue();

            if (!string.IsNullOrEmpty(dotnetSharedStoreValue))
            {
                this.NewDotnetSharedStoreValue = dotnetSharedStoreValue;

                this.Logger.WriteLine($"\nWarning: You must set the {LambdaConstants.ENV_DOTNET_SHARED_STORE} environment variable when deploying the package. " +
                                      "If not set the layers specified will not be located by the .NET Core runtime. The trailing '/' is required.");
                this.Logger.WriteLine($"{LambdaConstants.ENV_DOTNET_SHARED_STORE}: {dotnetSharedStoreValue}");
            }

            return(true);
        }
コード例 #9
0
        protected override async Task <bool> PerformActionAsync()
        {
            string projectLocation = this.GetStringValueOrDefault(this.ProjectLocation, CommonDefinedCommandOptions.ARGUMENT_PROJECT_LOCATION, false);
            string zipArchivePath  = null;
            string package         = this.GetStringValueOrDefault(this.Package, LambdaDefinedCommandOptions.ARGUMENT_PACKAGE, false);

            if (string.IsNullOrEmpty(package))
            {
                EnsureInProjectDirectory();

                string configuration     = this.GetStringValueOrDefault(this.Configuration, CommonDefinedCommandOptions.ARGUMENT_CONFIGURATION, true);
                string targetFramework   = this.GetStringValueOrDefault(this.TargetFramework, CommonDefinedCommandOptions.ARGUMENT_FRAMEWORK, true);
                string msbuildParameters = this.GetStringValueOrDefault(this.MSBuildParameters, CommonDefinedCommandOptions.ARGUMENT_MSBUILD_PARAMETERS, false);

                ValidateTargetFrameworkAndLambdaRuntime();

                bool   disableVersionCheck = this.GetBoolValueOrDefault(this.DisableVersionCheck, LambdaDefinedCommandOptions.ARGUMENT_DISABLE_VERSION_CHECK, false).GetValueOrDefault();
                string publishLocation;
                LambdaPackager.CreateApplicationBundle(this.DefaultConfig, this.Logger, this.WorkingDirectory, projectLocation, configuration, targetFramework, msbuildParameters, disableVersionCheck, out publishLocation, ref zipArchivePath);
                if (string.IsNullOrEmpty(zipArchivePath))
                {
                    return(false);
                }
            }
            else
            {
                if (!File.Exists(package))
                {
                    throw new LambdaToolsException($"Package {package} does not exist", LambdaToolsException.LambdaErrorCode.InvalidPackage);
                }
                if (!string.Equals(Path.GetExtension(package), ".zip", StringComparison.OrdinalIgnoreCase))
                {
                    throw new LambdaToolsException($"Package {package} must be a zip file", LambdaToolsException.LambdaErrorCode.InvalidPackage);
                }

                this.Logger.WriteLine($"Skipping compilation and using precompiled package {package}");
                zipArchivePath = package;
            }


            using (var stream = new MemoryStream(File.ReadAllBytes(zipArchivePath)))
            {
                var    s3Bucket = this.GetStringValueOrDefault(this.S3Bucket, LambdaDefinedCommandOptions.ARGUMENT_S3_BUCKET, false);
                string s3Key    = null;
                if (!string.IsNullOrEmpty(s3Bucket))
                {
                    await Utilities.ValidateBucketRegionAsync(this.S3Client, s3Bucket);

                    var functionName = this.GetStringValueOrDefault(this.FunctionName, LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_NAME, true);
                    var s3Prefix     = this.GetStringValueOrDefault(this.S3Prefix, LambdaDefinedCommandOptions.ARGUMENT_S3_PREFIX, false);
                    s3Key = await Utilities.UploadToS3Async(this.Logger, this.S3Client, s3Bucket, s3Prefix, functionName, stream);
                }


                var currentConfiguration = await GetFunctionConfigurationAsync();

                if (currentConfiguration == null)
                {
                    this.Logger.WriteLine($"Creating new Lambda function {this.FunctionName}");
                    var createRequest = new CreateFunctionRequest
                    {
                        FunctionName = this.GetStringValueOrDefault(this.FunctionName, LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_NAME, true),
                        Description  = this.GetStringValueOrDefault(this.Description, LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_DESCRIPTION, false),

                        Role = this.GetRoleValueOrDefault(this.Role, LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_ROLE,
                                                          Constants.LAMBDA_PRINCIPAL, LambdaConstants.AWS_LAMBDA_MANAGED_POLICY_PREFIX,
                                                          LambdaConstants.KNOWN_MANAGED_POLICY_DESCRIPTIONS, true),

                        Handler    = this.GetStringValueOrDefault(this.Handler, LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_HANDLER, true),
                        Publish    = this.GetBoolValueOrDefault(this.Publish, LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_PUBLISH, false).GetValueOrDefault(),
                        MemorySize = this.GetIntValueOrDefault(this.MemorySize, LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_MEMORY_SIZE, true).GetValueOrDefault(),
                        Runtime    = this.GetStringValueOrDefault(this.Runtime, LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_RUNTIME, true),
                        Timeout    = this.GetIntValueOrDefault(this.Timeout, LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_TIMEOUT, true).GetValueOrDefault(),
                        KMSKeyArn  = this.GetStringValueOrDefault(this.KMSKeyArn, LambdaDefinedCommandOptions.ARGUMENT_KMS_KEY_ARN, false),
                        VpcConfig  = new VpcConfig
                        {
                            SubnetIds        = this.GetStringValuesOrDefault(this.SubnetIds, LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_SUBNETS, false)?.ToList(),
                            SecurityGroupIds = this.GetStringValuesOrDefault(this.SecurityGroupIds, LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_SECURITY_GROUPS, false)?.ToList()
                        }
                    };

                    var environmentVariables = GetEnvironmentVariables(null);

                    if (environmentVariables != null && environmentVariables.Count > 0)
                    {
                        createRequest.Environment = new Model.Environment
                        {
                            Variables = environmentVariables
                        };
                    }

                    var tags = this.GetKeyValuePairOrDefault(this.Tags, LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_TAGS, false);
                    if (tags != null && tags.Count > 0)
                    {
                        createRequest.Tags = tags;
                    }

                    var deadLetterQueue = this.GetStringValueOrDefault(this.DeadLetterTargetArn, LambdaDefinedCommandOptions.ARGUMENT_DEADLETTER_TARGET_ARN, false);
                    if (!string.IsNullOrEmpty(deadLetterQueue))
                    {
                        createRequest.DeadLetterConfig = new DeadLetterConfig {
                            TargetArn = deadLetterQueue
                        };
                    }

                    var tracingMode = this.GetStringValueOrDefault(this.TracingMode, LambdaDefinedCommandOptions.ARGUMENT_TRACING_MODE, false);
                    if (!string.IsNullOrEmpty(tracingMode))
                    {
                        createRequest.TracingConfig = new TracingConfig {
                            Mode = tracingMode
                        };
                    }

                    if (s3Bucket != null)
                    {
                        createRequest.Code = new FunctionCode
                        {
                            S3Bucket = s3Bucket,
                            S3Key    = s3Key
                        };
                    }
                    else
                    {
                        createRequest.Code = new FunctionCode
                        {
                            ZipFile = stream
                        };
                    }


                    try
                    {
                        await this.LambdaClient.CreateFunctionAsync(createRequest);

                        this.Logger.WriteLine("New Lambda function created");
                    }
                    catch (Exception e)
                    {
                        throw new LambdaToolsException($"Error creating Lambda function: {e.Message}", LambdaToolsException.LambdaErrorCode.LambdaCreateFunction, e);
                    }
                }
                else
                {
                    this.Logger.WriteLine($"Updating code for existing function {this.FunctionName}");

                    var updateCodeRequest = new UpdateFunctionCodeRequest
                    {
                        FunctionName = this.GetStringValueOrDefault(this.FunctionName, LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_NAME, true)
                    };

                    if (s3Bucket != null)
                    {
                        updateCodeRequest.S3Bucket = s3Bucket;
                        updateCodeRequest.S3Key    = s3Key;
                    }
                    else
                    {
                        updateCodeRequest.ZipFile = stream;
                    }

                    try
                    {
                        await this.LambdaClient.UpdateFunctionCodeAsync(updateCodeRequest);
                    }
                    catch (Exception e)
                    {
                        throw new LambdaToolsException($"Error updating code for Lambda function: {e.Message}", LambdaToolsException.LambdaErrorCode.LambdaUpdateFunctionCode, e);
                    }

                    await base.UpdateConfigAsync(currentConfiguration);

                    await base.ApplyTags(currentConfiguration.FunctionArn);

                    var publish = this.GetBoolValueOrDefault(this.Publish, LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_PUBLISH, false).GetValueOrDefault();
                    if (publish)
                    {
                        await base.PublishFunctionAsync(updateCodeRequest.FunctionName);
                    }
                }
            }

            return(true);
        }