lambda-microvms 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: de35523913c4cd5c11fc48549081c7901db9fdacfef2a72618264885596bb838
4
+ data.tar.gz: 960ec7995dc496da3f358c6ad484eb0a420140afa727275b92e5eadf7201ce2b
5
+ SHA512:
6
+ metadata.gz: 055d951f5d0a5dc948195eff437d7b67070faf74e5dba4eee65b583aa70fda29a0452d93ecbe4e311bf3e7f5f18054d999776c6c5294bc2c88b061c8a777c77c
7
+ data.tar.gz: 6948f65e7391fa14734dcd1f89757bfb6a1b2a04ee200566409de0851da3a80f41a7173607cbd6efa40a5bc31d09d1033237512eb145bf23358459871dd77da5
data/CHANGELOG.md ADDED
@@ -0,0 +1,14 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0 Unreleased
4
+
5
+ - Initial Ruby development kit for AWS Lambda MicroVMs.
6
+ - Client wrapper over `aws-sdk-lambda`.
7
+ - Image, MicroVM, Endpoint, Waiter, and session helper APIs.
8
+ - Project scaffolding via `lambda-microvms new NAME`.
9
+ - Generated Ruby MicroVM projects include `aws_lambda_ric` for guest-side Lambda Runtime API integration.
10
+ - Project configuration via `microvm.yml`.
11
+ - Packaging helper via `lambda-microvms package`.
12
+ - Deployment helper via `lambda-microvms deploy` using S3 artifact upload and MicroVM image creation.
13
+ - Runtime helper via `lambda-microvms run`.
14
+ - Project readiness checks via `lambda-microvms doctor`.
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Kenneth C. Demanawa
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,179 @@
1
+ # lambda-microvms
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/lambda-microvms.svg)](https://badge.fury.io/rb/lambda-microvms)
4
+ [![CI](https://github.com/kanutocd/lambda-microvms/workflows/CI/badge.svg)](https://github.com/kanutocd/lambda-microvms/actions)
5
+ [![Ruby Version](https://img.shields.io/badge/ruby-%3E%3D%203.2-ruby.svg)](https://www.ruby-lang.org/en/)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ A Ruby development kit for AWS Lambda MicroVMs.
9
+
10
+ `lambda-microvms` builds on the official `aws-sdk-lambda` gem. It provides Ruby resource objects, lifecycle helpers, endpoint calls, project scaffolding, packaging, and deployment commands for Lambda MicroVM applications.
11
+
12
+ It gives Ruby developers a higher-level workflow:
13
+
14
+ ```text
15
+ scaffold
16
+
17
+ develop
18
+
19
+ package
20
+
21
+ deploy image
22
+
23
+ run / suspend / resume / terminate
24
+ ```
25
+
26
+ ## Why `aws_lambda_ric` appears in generated projects
27
+
28
+ Ruby MicroVM applications need a runtime inside the image. For non-AWS or OS-only Ruby container images, AWS documents the Ruby Runtime Interface Client (`aws_lambda_ric`) as the component that lets Ruby code interact with the Lambda Runtime API.
29
+
30
+ `lambda-microvms` uses `aws_lambda_ric` as a **generated project dependency**, not as a host-side SDK dependency.
31
+
32
+ ```text
33
+ Host side:
34
+ lambda-microvms
35
+ aws-sdk-lambda
36
+ aws-sdk-s3
37
+
38
+ Guest side / inside generated image:
39
+ aws_lambda_ric
40
+ your Ruby handler
41
+ ```
42
+
43
+ ## Installation
44
+
45
+ ```ruby
46
+ gem "lambda-microvms"
47
+ ```
48
+
49
+ ## Scaffold a Ruby MicroVM project
50
+
51
+ ```bash
52
+ lambda-microvms new hello-worker
53
+ cd hello-worker
54
+ ```
55
+
56
+ Generated project:
57
+
58
+ ```text
59
+ hello-worker/
60
+ Dockerfile
61
+ Gemfile
62
+ app.rb
63
+ microvm.yml
64
+ README.md
65
+ .env.example
66
+ ```
67
+
68
+ The generated `Gemfile` includes:
69
+
70
+ ```ruby
71
+ gem "aws_lambda_ric"
72
+ ```
73
+
74
+ ## Check readiness
75
+
76
+ ```bash
77
+ lambda-microvms doctor
78
+ ```
79
+
80
+ Checks Ruby, Docker, AWS CLI, project config, Dockerfile, deployment bucket, runtime role, and `aws_lambda_ric` presence.
81
+
82
+ ## Package
83
+
84
+ ```bash
85
+ lambda-microvms package
86
+ ```
87
+
88
+ Creates the source artifact configured by `microvm.yml`.
89
+
90
+ ## Deploy
91
+
92
+ ```bash
93
+ lambda-microvms deploy
94
+ ```
95
+
96
+ Deployment flow:
97
+
98
+ ```text
99
+ zip project
100
+
101
+ upload to S3
102
+
103
+ create MicroVM image through aws-sdk-lambda
104
+ ```
105
+
106
+ The exact AWS Lambda MicroVM API parameter names are still kept close to AWS naming. Put API-specific values under `image.create` in `microvm.yml`.
107
+
108
+ ## Run
109
+
110
+ ```bash
111
+ lambda-microvms run
112
+ ```
113
+
114
+ Runs the configured image ARN with the configured role ARN and runtime payload.
115
+
116
+ ## Ruby SDK usage
117
+
118
+ ```ruby
119
+ require "lambda/microvms"
120
+
121
+ client = Lambda::MicroVMs::Client.new(region: "us-east-1")
122
+
123
+ image = client.image("arn:aws:lambda:us-east-1:123456789012:microvm-image:ruby-sandbox")
124
+
125
+ vm = image.run(
126
+ role_arn: "arn:aws:iam::123456789012:role/lambda-microvm-runtime",
127
+ payload: { tenant_id: "tenant_123" }
128
+ )
129
+
130
+ vm.wait_until_running
131
+
132
+ response = vm.post("/process", json: { hello: "world" })
133
+
134
+ vm.suspend
135
+ vm.resume
136
+ vm.terminate
137
+ ```
138
+
139
+ ## Session helper
140
+
141
+ ```ruby
142
+ Lambda::MicroVMs.session(
143
+ image_arn: "arn:aws:lambda:us-east-1:123456789012:microvm-image:ruby-sandbox",
144
+ role_arn: "arn:aws:iam::123456789012:role/lambda-microvm-runtime",
145
+ after: :suspend,
146
+ payload: { tenant_id: "tenant_123" }
147
+ ) do |vm|
148
+ vm.post("/process", json: { event_id: "evt_1" })
149
+ end
150
+ ```
151
+
152
+ Supported cleanup policies:
153
+
154
+ ```ruby
155
+ after: :keep
156
+ after: :suspend
157
+ after: :terminate
158
+ ```
159
+
160
+ ## Architecture
161
+
162
+ ```text
163
+ aws-sdk-lambda
164
+
165
+
166
+ Lambda::MicroVMs::Client
167
+
168
+ ├── Image
169
+ ├── MicroVM
170
+ ├── Endpoint
171
+ ├── Session
172
+ ├── Scaffold
173
+ ├── Packager
174
+ └── Deployer
175
+ ```
176
+
177
+ ## Status
178
+
179
+ This is an early implementation. Lambda MicroVMs is new, so generated AWS SDK operation shapes may evolve. Unsupported low-level operations raise `Lambda::MicroVMs::UnsupportedOperationError` with an upgrade hint.
@@ -0,0 +1,102 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'lambda/microvms'
5
+
6
+ module Lambda
7
+ module MicroVMs
8
+ # Minimal CLI for the Ruby Lambda MicroVM development kit.
9
+ class CLI
10
+ def initialize(argv, out: $stdout, err: $stderr)
11
+ @argv = argv
12
+ @out = out
13
+ @err = err
14
+ end
15
+
16
+ # rubocop:disable Metrics/MethodLength
17
+ def run
18
+ command = @argv.shift
19
+ case command
20
+ when 'version', '--version', '-v' then version
21
+ when 'new' then new_project
22
+ when 'package' then package
23
+ when 'deploy' then deploy
24
+ when 'run' then run_microvm
25
+ when 'doctor' then doctor
26
+ when 'help', nil then help
27
+ else
28
+ @err.puts "unknown command: #{command}"
29
+ help
30
+ 1
31
+ end
32
+ rescue Error, ArgumentError, LoadError => e
33
+ @err.puts "error: #{e.message}"
34
+ 1
35
+ end
36
+ # rubocop:enable Metrics/MethodLength
37
+
38
+ private
39
+
40
+ def version
41
+ @out.puts VERSION
42
+ 0
43
+ end
44
+
45
+ def new_project
46
+ name = @argv.shift || raise(ArgumentError, 'usage: lambda-microvms new NAME')
47
+ force = @argv.include?('--force')
48
+ Scaffold.new(name, force: force).create
49
+ @out.puts "created #{name}"
50
+ 0
51
+ end
52
+
53
+ def project
54
+ @project ||= Project.load
55
+ end
56
+
57
+ def package
58
+ path = Packager.new(project).package
59
+ @out.puts path
60
+ 0
61
+ end
62
+
63
+ def deploy
64
+ image = Deployer.new(project: project).deploy
65
+ @out.puts image.arn || image.data.inspect
66
+ 0
67
+ end
68
+
69
+ def run_microvm
70
+ vm = Deployer.new(project: project).run
71
+ @out.puts vm.id || vm.data.inspect
72
+ 0
73
+ end
74
+
75
+ def doctor
76
+ checks = Doctor.new(project: project).checks
77
+ checks.each do |check|
78
+ marker = check.ok ? 'PASS' : 'FAIL'
79
+ @out.puts "#{marker} #{check.name}: #{check.detail}"
80
+ end
81
+ checks.all?(&:ok) ? 0 : 1
82
+ end
83
+
84
+ def help
85
+ @out.puts <<~HELP
86
+ lambda-microvms #{VERSION}
87
+
88
+ Commands:
89
+ new NAME Generate a Ruby Lambda MicroVM project using aws_lambda_ric
90
+ doctor Check local project readiness
91
+ package Create deployable source artifact
92
+ deploy Package, upload to S3, and create a MicroVM image
93
+ run Run the configured MicroVM image
94
+ version Print version
95
+ HELP
96
+ 0
97
+ end
98
+ end
99
+ end
100
+ end
101
+
102
+ exit Lambda::MicroVMs::CLI.new(ARGV).run
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require 'aws-sdk-lambda'
5
+ rescue LoadError
6
+ nil
7
+ end
8
+
9
+ module Lambda
10
+ module MicroVMs
11
+ # Ruby wrapper over Aws::Lambda::Client for Lambda MicroVM lifecycle operations.
12
+ class Client
13
+ attr_reader :sdk
14
+
15
+ def initialize(region: nil, profile: nil, sdk: nil, **)
16
+ @sdk = sdk || build_sdk(region:, profile:, **)
17
+ end
18
+
19
+ def image(arn)
20
+ Image.new(client: self, arn: arn)
21
+ end
22
+
23
+ def microvm(id_or_arn)
24
+ MicroVM.new(client: self, id: id_or_arn)
25
+ end
26
+
27
+ def create_image(**params)
28
+ response = call_sdk(:create_microvm_image, **params)
29
+ Image.from_response(client: self, response: response)
30
+ end
31
+
32
+ def get_image(**params)
33
+ response = call_sdk(:get_microvm_image, **params)
34
+ Image.from_response(client: self, response: response)
35
+ end
36
+
37
+ def delete_image(**params)
38
+ call_sdk(:delete_microvm_image, **params)
39
+ end
40
+
41
+ def run(**params)
42
+ response = call_sdk(:run_microvm, **params)
43
+ MicroVM.from_response(client: self, response: response)
44
+ end
45
+ alias run_microvm run
46
+
47
+ def get_microvm(**params)
48
+ response = call_sdk(:get_microvm, **params)
49
+ MicroVM.from_response(client: self, response: response)
50
+ end
51
+
52
+ def list_microvms(**params)
53
+ call_sdk(:list_microvms, **params)
54
+ end
55
+
56
+ def suspend_microvm(**params)
57
+ call_sdk(:suspend_microvm, **params)
58
+ end
59
+
60
+ def resume_microvm(**params)
61
+ call_sdk(:resume_microvm, **params)
62
+ end
63
+
64
+ def terminate_microvm(**params)
65
+ call_sdk(:terminate_microvm, **params)
66
+ end
67
+
68
+ def create_auth_token(**params)
69
+ call_sdk(:create_microvm_auth_token, **params)
70
+ end
71
+ alias create_microvm_auth_token create_auth_token
72
+
73
+ def call_sdk(operation, **params)
74
+ unless @sdk.respond_to?(operation)
75
+ raise UnsupportedOperationError, "Aws::Lambda::Client does not expose ##{operation}; upgrade aws-sdk-lambda"
76
+ end
77
+
78
+ @sdk.public_send(operation, **params)
79
+ end
80
+
81
+ private
82
+
83
+ def build_sdk(region:, profile:, **options)
84
+ raise LoadError, 'install aws-sdk-lambda to use Lambda::MicroVMs::Client' unless defined?(Aws::Lambda::Client)
85
+
86
+ args = options.dup
87
+ args[:region] = region if region
88
+ args[:profile] = profile if profile
89
+ Aws::Lambda::Client.new(**args)
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ begin
6
+ require 'aws-sdk-s3'
7
+ rescue LoadError
8
+ nil
9
+ end
10
+
11
+ module Lambda
12
+ module MicroVMs
13
+ # Project-aware deployment helper: package, upload to S3, create MicroVM image.
14
+ class Deployer
15
+ attr_reader :project, :client, :s3
16
+
17
+ def initialize(project:, client: nil, s3: nil) # rubocop:disable Naming/MethodParameterName
18
+ @project = project
19
+ @client = client || Client.new(region: project.region, profile: project.profile)
20
+ @s3 = s3 || build_s3
21
+ end
22
+
23
+ def package
24
+ Packager.new(project).package
25
+ end
26
+
27
+ def upload(path)
28
+ bucket = project.require!('deployment.bucket', project.s3_bucket)
29
+ key = [project.s3_prefix.sub(%r{/\z}, ''), File.basename(path)].join('/')
30
+ s3.put_object(bucket: bucket, key: key, body: File.open(path, 'rb'))
31
+ "s3://#{bucket}/#{key}"
32
+ end
33
+
34
+ def deploy
35
+ artifact = package
36
+ artifact_uri = upload(artifact)
37
+ client.create_image(**project.create_image_params(artifact_uri: artifact_uri))
38
+ end
39
+
40
+ def run
41
+ image_arn = project.require!('image.arn', project.image_arn)
42
+ role_arn = project.require!('role_arn', project.role_arn)
43
+ client.image(image_arn).run(**project.run_params, role_arn: role_arn)
44
+ end
45
+
46
+ private
47
+
48
+ def build_s3
49
+ raise LoadError, 'install aws-sdk-s3 to use deployment helpers' unless defined?(Aws::S3::Client)
50
+
51
+ args = {}
52
+ args[:region] = project.region if project.region
53
+ args[:profile] = project.profile if project.profile
54
+ Aws::S3::Client.new(**args)
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'English'
4
+ module Lambda
5
+ module MicroVMs
6
+ # Performs lightweight local project readiness checks.
7
+ class Doctor
8
+ Check = Struct.new(:name, :ok, :detail, keyword_init: true)
9
+
10
+ attr_reader :project, :runner
11
+
12
+ def initialize(project:, runner: Kernel)
13
+ @project = project
14
+ @runner = runner
15
+ end
16
+
17
+ def checks
18
+ [
19
+ check('Ruby', RUBY_VERSION >= '3.2', RUBY_VERSION),
20
+ command_check('Docker', 'docker --version'),
21
+ command_check('AWS CLI', 'aws --version'),
22
+ file_check('microvm.yml', project.config_path),
23
+ file_check('Dockerfile', project.dockerfile),
24
+ config_check('role_arn', project.role_arn),
25
+ config_check('deployment.bucket', project.s3_bucket),
26
+ ric_check
27
+ ]
28
+ end
29
+
30
+ def ok?
31
+ checks.all?(&:ok)
32
+ end
33
+
34
+ private
35
+
36
+ def check(name, ok, detail) # rubocop:disable Naming/MethodParameterName
37
+ Check.new(name:, ok:, detail: detail.to_s)
38
+ end
39
+
40
+ def command_check(name, command)
41
+ output = `#{command} 2>&1`.strip
42
+ Check.new(name:, ok: $CHILD_STATUS.success?, detail: output)
43
+ rescue StandardError => e
44
+ Check.new(name:, ok: false, detail: e.message)
45
+ end
46
+
47
+ def file_check(name, path)
48
+ Check.new(name:, ok: File.exist?(path), detail: path)
49
+ end
50
+
51
+ def config_check(name, value)
52
+ Check.new(name:, ok: value && value != '', detail: value || 'missing')
53
+ end
54
+
55
+ def ric_check
56
+ gemfile = File.join(project.root, 'Gemfile')
57
+ ok = File.exist?(gemfile) && File.read(gemfile).include?('aws_lambda_ric')
58
+ Check.new(name: 'aws_lambda_ric', ok: ok, detail: ok ? 'present in Gemfile' : 'missing from Gemfile')
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'net/http'
5
+ require 'uri'
6
+
7
+ module Lambda
8
+ module MicroVMs
9
+ # HTTP client for a single Lambda MicroVM endpoint.
10
+ class Endpoint
11
+ attr_reader :url
12
+
13
+ def initialize(url:, token:, http: Net::HTTP)
14
+ @url = url
15
+ @token = token
16
+ @http = http
17
+ end
18
+
19
+ def get(path, headers: {})
20
+ request(Net::HTTP::Get, path, headers:)
21
+ end
22
+
23
+ def post(path, json: nil, body: nil, headers: {})
24
+ request(Net::HTTP::Post, path, json:, body:, headers:)
25
+ end
26
+
27
+ def request(klass, path, json: nil, body: nil, headers: {})
28
+ response = @http.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
29
+ http.request(build_request(klass, path, headers:, body:, json:))
30
+ end
31
+
32
+ success = response.code.to_i.between?(200, 299)
33
+ unless success
34
+ raise EndpointError.new("MicroVM endpoint returned HTTP #{response.code}", status: response.code.to_i,
35
+ body: response.body)
36
+ end
37
+
38
+ parse_response(response)
39
+ end
40
+
41
+ private
42
+
43
+ def build_uri(path)
44
+ base = URI(@url)
45
+ return base if path.nil? || path.empty? || path == '/'
46
+
47
+ joined = [base.path.sub(%r{/\z}, ''), path.sub(%r{\A/}, '')].reject(&:empty?).join('/')
48
+ base.path = "/#{joined}"
49
+ base
50
+ end
51
+
52
+ def parse_response(response)
53
+ content_type = response['Content-Type'].to_s
54
+ return JSON.parse(response.body) if content_type.include?('application/json') && !response.body.to_s.empty?
55
+
56
+ response.body
57
+ end
58
+
59
+ def build_request(klass, path, headers: {}, json: nil, body: nil)
60
+ uri = build_uri(path)
61
+ request = klass.new(uri)
62
+ headers = headers.merge('Authorization' => @token ? "Bearer #{@token}" : nil)
63
+ if json
64
+ headers['Content-Type'] ||= 'application/json'
65
+ request.body = JSON.generate(json)
66
+ elsif body
67
+ request.body = body
68
+ end
69
+ headers.each_pair.with_object(request) { |(key, value), req| req[key] = value }
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lambda
4
+ module MicroVMs
5
+ # Base error for lambda-microvms.
6
+ class Error < StandardError; end
7
+
8
+ # Raised when an expected MicroVM lifecycle state is not reached in time.
9
+ class WaitTimeoutError < Error; end
10
+
11
+ # Raised when the configured AWS Lambda SDK client does not expose a needed operation.
12
+ class UnsupportedOperationError < Error; end
13
+
14
+ # Raised when project configuration is invalid or incomplete.
15
+ class ConfigurationError < Error; end
16
+
17
+ # Raised when an external command such as Docker fails.
18
+ class CommandError < Error; end
19
+
20
+ # Raised when a MicroVM endpoint call fails with a non-success response.
21
+ class EndpointError < Error
22
+ attr_reader :status, :body
23
+
24
+ def initialize(message, status:, body:)
25
+ @status = status
26
+ @body = body
27
+ super(message)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lambda
4
+ module MicroVMs
5
+ # Represents a Lambda MicroVM image/snapshot artifact.
6
+ class Image
7
+ attr_reader :client, :arn, :data
8
+
9
+ def self.from_response(client:, response:)
10
+ arn = Util.extract(response, :image_arn, :microvm_image_arn, :arn)
11
+ new(client: client, arn: arn, data: response)
12
+ end
13
+
14
+ def initialize(client:, arn:, data: nil)
15
+ @client = client
16
+ @arn = arn
17
+ @data = data
18
+ end
19
+
20
+ def refresh
21
+ fresh = client.get_image(image_arn: arn)
22
+ @data = fresh.data
23
+ self
24
+ end
25
+
26
+ def state
27
+ Util.normalize_state(Util.extract(@data, :state, :status, :image_state))
28
+ end
29
+
30
+ def ready?
31
+ %i[ready available active].include?(state)
32
+ end
33
+
34
+ def wait_until_ready(delay: Waiter::DEFAULT_DELAY, timeout: Waiter::DEFAULT_TIMEOUT)
35
+ Waiter.new(delay: delay, timeout: timeout).wait(message: "image #{arn} to be ready") do
36
+ refresh.ready?
37
+ end
38
+ self
39
+ end
40
+
41
+ def run(role_arn:, payload: nil, **params)
42
+ request = params.merge(image_arn: arn, role_arn: role_arn)
43
+ request[:payload] = payload if payload
44
+ client.run(**request)
45
+ end
46
+ end
47
+ end
48
+ end