diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ed9036..56d5913 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# v0.1.x +* Add support for go1.x lambda runtime +* Fix support for deploying lambda via S3 bucket + # v0.1.2 * Fix property namespaces, function/handler, and include role (#2) diff --git a/README.md b/README.md index fb1017c..81252bc 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ source files contained within configured directories. * Acceptable functions will be defined inline * S3 storage will be used when inline is unacceptable * S3 versioning will be used when bucket configured for versioning - * Automatic asset builds (for `java8` runtime targets) + * Automatic asset builds (for `java8` and `go1.x` runtime targets) ## Usage @@ -44,14 +44,18 @@ Configuration.new do end ``` -_NOTE: If using the `java8` runtime for lambda functions, `maven` must -be installed with `mvn` being available within the user's PATH._ +_NOTE:_ + * If using the `java8` runtime for lambda functions, `maven` must + be installed with `mvn` being available within the user's PATH. + * If using the `go1.x` runtime for lambda functions, `golang` and + `zip` utility must be installed with `go` and `zip` being available + within the user's PATH. ### Configuration #### Lambda function files directory -By default the `sfn-lambda` callback will search the `./lambda` directory +By default, the `sfn-lambda` callback will search the `./lambda` directory for lambda function files. A custom directory path can be used by modifying the configuration: @@ -65,7 +69,7 @@ end #### S3 lambda function file storage -By default the `sfn-lambda` callback will use the bucket name provided by +By default, the `sfn-lambda` callback will use the bucket name provided by the `nesting_bucket` configuration item. This can be customized to use a different bucket by modifying the configuration: @@ -89,13 +93,9 @@ identifier to reference the function. The path structure is as follows: ./lambda/RUNTIME/FUNCTION_NAME.extension ``` -The `RUNTIME` defines the runtime used for handling the lambda function. At -the time of writing this, that value can be one of: - -* `nodejs` -* `nodejs4.3` -* `java8` -* `python2.7` +The `RUNTIME` defines the runtime used for handling the lambda function. +Please check https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html +for the full list. _NOTE: Runtime values are not validated which allows new runtimes to be used as they are made available._ @@ -222,4 +222,4 @@ _NOTE: Maven is required to be installed when using the `java8` runtime_ ## Info * Repository: https://github.com/sparkleformation/sfn-lambda -* IRC: Freenode @ #sparkleformation \ No newline at end of file +* IRC: Freenode @ #sparkleformation diff --git a/lib/sfn-lambda/control.rb b/lib/sfn-lambda/control.rb index 7802f65..5439414 100644 --- a/lib/sfn-lambda/control.rb +++ b/lib/sfn-lambda/control.rb @@ -13,12 +13,17 @@ class Control DEFAULTS = { :INLINE_MAX_SIZE => 4096, - :INLINE_RESTRICTED => ['java8'].freeze, + :INLINE_RESTRICTED => ['java8', 'go1.x'].freeze, :BUILD_REQUIRED => { 'java8' => { :build_command => 'mvn package', :output_directory => './target', - :asset_extension => '.jar' + :asset_extension => 'jar' + }.freeze, + 'go1.x' => { + :build_command => 'GOOS=linux CGO_ENABLED=0 GOARCH=amd64 go build -ldflags="-s -w" -o target/ && zip -j -r target/main.zip target/*', + :output_directory => './target', + :asset_extension => 'zip' }.freeze }.freeze }.freeze @@ -86,22 +91,25 @@ def format_content(info) Smash.new(:raw => File.read(info[:path])) else apply_build!(info) - key_name = generate_key_name(info) io = File.open(info[:path], 'rb') file = bucket.files.build - file.name = key_name + file.name = generate_key_name(info) file.body = io file.save io.close + + version = nil if(versioning_enabled?) + s3 = callback.api.connection.api_for(:storage) result = s3.request( - :path => s3.file_path(file), + :path => s3.file_path(file.name), :endpoint => s3.bucket_endpoint(file.bucket), :method => :head ) version = result[:headers][:x_amz_version_id] end - Smash(:bucket => storage_bucket, :key => key_name, :version => version) + + Smash.new(:bucket => bucket.name, :key => file.name, :version => version) end end @@ -121,12 +129,12 @@ def apply_build!(info) raise "Failed to build lambda asset for storage! (path: `#{info[:path]}`)" end end - file = Dir.glob(File.join(info[:path], build_info[:output_directory], "*.#{build_config[:asset_extension]}")).first + file = Dir.glob(File.join(info[:path], build_info[:output_directory], "*.#{build_info[:asset_extension]}")).first if(file) info[:path] = file true else - debug "Glob pattern used for build asset detection: `#{File.join(info[:path], build_info[:output_directory], "*.#{build_config[:asset_extension]}")}`" + callback.ui.debug "Glob pattern used for build asset detection: `#{File.join(info[:path], build_info[:output_directory], "*.#{build_info[:asset_extension]}")}`" raise "Failed to locate generated build asset for storage! (path: `#{info[:path]}`)" end else @@ -138,7 +146,7 @@ def apply_build!(info) def bucket storage_bucket = callback.config.fetch(:lambda, :upload, :bucket, callback.config[:nesting_bucket]) if(storage_bucket) - s3 = api.connection.api_for(:storage) + s3 = callback.api.connection.api_for(:storage) l_bucket = s3.buckets.get(storage_bucket) end unless(l_bucket) @@ -150,8 +158,8 @@ def bucket # @return [TrueClass, FalseClass] bucket has versioning enabled def versioning_enabled? - unless(@versioned.nil?) - s3 = api.connection.api_for(:storage) + if(@versioned.nil?) + s3 = callback.api.connection.api_for(:storage) result = s3.request( :path => '/', :params => { @@ -178,7 +186,8 @@ def generate_key_name(info) checksum << content end end - "sfn.lambda/#{info[:runtime]}/#{File.basename(info[:path])}-#{checksum.base64digest}" + checksum = Base64.urlsafe_encode64(checksum.digest) + "sfn.lambda/#{info[:runtime]}/#{info[:name]}/#{checksum}/#{File.basename(info[:path])}" end end diff --git a/lib/sfn-lambda/inject.rb b/lib/sfn-lambda/inject.rb index 1a20782..739eb05 100644 --- a/lib/sfn-lambda/inject.rb +++ b/lib/sfn-lambda/inject.rb @@ -28,11 +28,11 @@ def _lambda(*fn_args) new_fn.properties.handler fn_handler new_fn.properties.runtime lookup[:runtime] new_fn.properties.function_name fn_function_name || fn_name + new_fn.properties.role fn_role content = ::SfnLambda.control.format_content(lookup) if(content[:raw]) new_fn.properties.code.zip_file content[:raw] new_fn.properties.handler "index.#{fn_handler}" - new_fn.properties.role fn_role else new_fn.properties.code.s3_bucket content[:bucket] new_fn.properties.code.s3_key content[:key]