Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions bin/aws-lambda/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
FROM public.ecr.aws/lambda/ruby:3.4 as ruby_dependencies_34

# Install system dependencies for native extensions
RUN dnf update -y && \
dnf install -y gcc gcc-c++ make

# Configure bundler and install gems
RUN echo "source 'https://rubygems.org'; gem 'instana'; gem 'get_process_mem'" > Gemfile && \
bundle config set --local path vendor/bundle && \
bundle install

# Create the layer structure
RUN mkdir -p ruby/gems/3.4.0 && \
cp -r vendor/bundle/ruby/3.4.0*/* ruby/gems/3.4.0/

FROM public.ecr.aws/lambda/ruby:3.3 as ruby_dependencies_33

# Install system dependencies for native extensions
RUN dnf update -y && \
dnf install -y gcc gcc-c++ make

# Configure bundler and install gems
RUN echo "source 'https://rubygems.org'; gem 'instana'; gem 'get_process_mem'" > Gemfile && \
bundle config set --local path vendor/bundle && \
bundle install

# Create the layer structure
RUN mkdir -p ruby/gems/3.3.0 && \
cp -r vendor/bundle/ruby/3.3.0*/* ruby/gems/3.3.0/

FROM public.ecr.aws/lambda/ruby:3.2 as ruby_dependencies_32

# Install system dependencies for native extensions
RUN yum update -y && \
yum install -y gcc gcc-c++ make && \
yum install -y zip

# Configure bundler and install gems
RUN echo "source 'https://rubygems.org'; gem 'instana'; gem 'get_process_mem'" > Gemfile && \
bundle config set --local path vendor/bundle && \
bundle install

# Create the layer structure
RUN mkdir -p ruby/gems/3.2.0 && \
cp -r vendor/bundle/ruby/3.2.0*/* ruby/gems/3.2.0/

FROM public.ecr.aws/docker/library/alpine:3.22 as final

RUN apk add --no-cache zip unzip

COPY --from=ruby_dependencies_34 /var/task/ruby/ ruby/
COPY --from=ruby_dependencies_33 /var/task/ruby/ ruby/
COPY --from=ruby_dependencies_32 /var/task/ruby/ ruby/

RUN zip -r /layer.zip ruby/
2 changes: 2 additions & 0 deletions bin/aws-lambda/aws-regions/cn-regions.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
cn-north-1
cn-northwest-1
32 changes: 32 additions & 0 deletions bin/aws-lambda/aws-regions/other_regions.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
af-south-1
ap-east-1
ap-east-2
ap-northeast-1
ap-northeast-2
ap-northeast-3
ap-south-1
ap-south-2
ap-southeast-1
ap-southeast-2
ap-southeast-3
ap-southeast-4
ap-southeast-5
ap-southeast-7
ca-central-1
ca-west-1
eu-central-1
eu-central-2
eu-north-1
eu-south-1
eu-south-2
eu-west-1
eu-west-2
eu-west-3
il-central-1
me-central-1
me-south-1
sa-east-1
us-east-1
us-east-2
us-west-1
us-west-2
61 changes: 61 additions & 0 deletions bin/aws-lambda/create_lambda_release_gh.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/usr/bin/env ruby

# (c) Copyright IBM Corp. 2025

# Script to make a new AWS Lambda Layer release on Github
# Requires the Github CLI to be installed and configured: https://github.com/cli/cli

require 'json'
require 'open3'

CHINA_REGIONS = File.readlines(File.join(File.dirname(__FILE__), 'aws-regions/cn-regions.txt')).map(&:chomp)
OTHER_REGIONS = File.readlines(File.join(File.dirname(__FILE__), 'aws-regions/other_regions.txt')).map(&:chomp)

if ARGV.length != 1
raise ArgumentError, 'Please specify the layer version to release. e.g. "1"'
end

if ['-h', '--help'].include?(ARGV[0])
filename = File.basename(__FILE__)
puts "Usage: #{filename} <version number>"
puts "Example: #{filename} 14"
puts ""
puts "This will create a AWS Lambda release on Github such as:"
puts "https://github.com/instana/ruby-sensor/releases/tag/v1"
exit 0
end

# Check requirements first
["gh"].each do |cmd|
if `which #{cmd}`.empty?
puts "Can't find required tool: #{cmd}"
exit 1
end
end

regions = CHINA_REGIONS + OTHER_REGIONS
version = ARGV[0]
semantic_version = "v#{version}"
title = "AWS Lambda Layer #{semantic_version}"

body = "| AWS Region | ARN |\n"
body += "| :-- | :-- |\n"
regions.each do |region|
body += "| #{region} | arn:aws:lambda:#{region}:410797082306:layer:instana-ruby:#{version} |\n"
end

stdout, stderr, status = Open3.capture3(
"gh", "api", "repos/:owner/:repo/releases", "--method=POST",
"-F", "tag_name=#{semantic_version}",
"-F", "name=#{title}",
"-F", "body=#{body}"
)

if status.success?
json_data = JSON.parse(stdout)
puts "The release is available at:"
puts json_data["html_url"]
else
puts "Error creating release: #{stderr}"
exit 1
end
99 changes: 99 additions & 0 deletions bin/aws-lambda/publish_lambda_layer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#!/usr/bin/env ruby

# (c) Copyright IBM Corp. 2025

require 'json'
require 'fileutils'
require 'time'
require 'aws-sdk-lambda'

CHINA_REGIONS = File.readlines(File.join(File.dirname(__FILE__), 'aws-regions/cn-regions.txt')).map(&:chomp)
OTHER_REGIONS = File.readlines(File.join(File.dirname(__FILE__), 'aws-regions/other_regions.txt')).map(&:chomp)
# Check AWS profiles
["china", "non-china"].each do |profile|
# Test if we can initialize a client with this profile
Aws::Lambda::Client.new(profile: profile)
rescue => e
abort "Please ensure that your aws configuration includes a profile called '#{profile}' " \
"and has the 'access_key' and 'secret_key' configured for the respective regions: #{e.message}"
end

# Either -dev or -prod must be specified (and nothing else)
if ARGV.length != 1 || !["-dev", "-prod"].include?(ARGV[0])
abort "Please specify -dev or -prod to indicate which type of layer to build."
end

dev_mode = ARGV[0] == "-dev"

# Determine where this script is running from
this_file_path = File.dirname(File.expand_path(__FILE__))

# Change directory to the base of the Ruby sensor repository
Dir.chdir(this_file_path.to_s)

zip_filename = "layer"

if dev_mode
target_regions = ["us-east-1"]
layer_name_prefix = "instana-ruby-dev"
else
target_regions = CHINA_REGIONS + OTHER_REGIONS
layer_name_prefix = "instana-ruby"
end

# AWS Lambda supported ruby versions
ruby_supported_runtimes = ["ruby3.2", "ruby3.3", "ruby3.4"]
# Publish each Ruby version as a separate layer
layer_name = layer_name_prefix.to_s
regional_publish = {}
target_regions.each do |region| # rubocop:disable Metrics/BlockLength
puts "===> Uploading layer for Ruby to AWS #{region}"
profile = CHINA_REGIONS.include?(region) ? "china" : "non-china"

# Initialize AWS Lambda client for this region and profile
lambda_client = Aws::Lambda::Client.new(
region: region,
profile: profile
)

# Read the zip file content
zip_file_path = "#{Dir.pwd}/#{zip_filename}.zip"
zip_content = File.read(zip_file_path, mode: 'rb')

begin
# Publish the layer version
response = lambda_client.publish_layer_version({
layer_name: layer_name,
description: "Provides Instana tracing and monitoring of AWS Lambda functions built with Ruby",
content: {
zip_file: zip_content
},
compatible_runtimes: ruby_supported_runtimes,
license_info: "MIT"
})

version_number = response.version
puts "===> Uploaded version is #{version_number}"

unless dev_mode
puts "===> Making layer public..."
lambda_client.add_layer_version_permission({
layer_name: layer_name,
version_number: version_number,
statement_id: "public-permission-all-accounts",
principal: "*",
action: "lambda:GetLayerVersion"
})
end

regional_publish[region] = response.layer_version_arn
rescue Aws::Lambda::Errors::ServiceError => e
puts "Failed to publish layer to #{region}: #{e.message}"
next
end
end

puts "===> Published list:"
regional_publish.each do |region, arn|
puts "#{region}\t#{arn}"
end
Loading