lambda-microvms 0.0.0 → 0.2.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 +4 -4
- data/CHANGELOG.md +10 -1
- data/README.md +39 -4
- data/exe/lambda-microvms +41 -10
- data/lib/lambda/microvms/adapters/microvm_sdk.rb +59 -0
- data/lib/lambda/microvms/client.rb +81 -8
- data/lib/lambda/microvms/deployer.rb +27 -5
- data/lib/lambda/microvms/doctor.rb +15 -2
- data/lib/lambda/microvms/endpoint.rb +26 -4
- data/lib/lambda/microvms/function_client.rb +90 -0
- data/lib/lambda/microvms/image.rb +22 -0
- data/lib/lambda/microvms/microvm.rb +68 -1
- data/lib/lambda/microvms/packager.rb +9 -2
- data/lib/lambda/microvms/project.rb +93 -4
- data/lib/lambda/microvms/scaffold.rb +3 -0
- data/lib/lambda/microvms/session.rb +15 -0
- data/lib/lambda/microvms/util.rb +9 -0
- data/lib/lambda/microvms/version.rb +2 -1
- data/lib/lambda/microvms/waiter.rb +8 -0
- data/lib/lambda/microvms.rb +7 -0
- data/sig/lambda/microvms.rbs +150 -3
- metadata +5 -6
|
@@ -6,6 +6,11 @@ module Lambda
|
|
|
6
6
|
class Image
|
|
7
7
|
attr_reader :client, :arn, :data
|
|
8
8
|
|
|
9
|
+
# Build an image resource from an SDK response.
|
|
10
|
+
#
|
|
11
|
+
# @param client [Client] lifecycle client
|
|
12
|
+
# @param response [Object] SDK response
|
|
13
|
+
# @return [Image] image resource
|
|
9
14
|
def self.from_response(client:, response:)
|
|
10
15
|
arn = Util.extract(response, :image_arn, :microvm_image_arn, :arn)
|
|
11
16
|
new(client: client, arn: arn, data: response)
|
|
@@ -17,12 +22,18 @@ module Lambda
|
|
|
17
22
|
@data = data
|
|
18
23
|
end
|
|
19
24
|
|
|
25
|
+
# Refresh image data from the service.
|
|
26
|
+
#
|
|
27
|
+
# @return [self]
|
|
20
28
|
def refresh
|
|
21
29
|
fresh = client.get_image(image_arn: arn)
|
|
22
30
|
@data = fresh.data
|
|
23
31
|
self
|
|
24
32
|
end
|
|
25
33
|
|
|
34
|
+
# Current normalized image state.
|
|
35
|
+
#
|
|
36
|
+
# @return [Symbol]
|
|
26
37
|
def state
|
|
27
38
|
Util.normalize_state(Util.extract(@data, :state, :status, :image_state))
|
|
28
39
|
end
|
|
@@ -31,6 +42,11 @@ module Lambda
|
|
|
31
42
|
%i[ready available active].include?(state)
|
|
32
43
|
end
|
|
33
44
|
|
|
45
|
+
# Wait until the image reaches a ready-like state.
|
|
46
|
+
#
|
|
47
|
+
# @param delay [Numeric] polling delay in seconds
|
|
48
|
+
# @param timeout [Numeric] maximum wait in seconds
|
|
49
|
+
# @return [self]
|
|
34
50
|
def wait_until_ready(delay: Waiter::DEFAULT_DELAY, timeout: Waiter::DEFAULT_TIMEOUT)
|
|
35
51
|
Waiter.new(delay: delay, timeout: timeout).wait(message: "image #{arn} to be ready") do
|
|
36
52
|
refresh.ready?
|
|
@@ -38,6 +54,12 @@ module Lambda
|
|
|
38
54
|
self
|
|
39
55
|
end
|
|
40
56
|
|
|
57
|
+
# Run a MicroVM from this image.
|
|
58
|
+
#
|
|
59
|
+
# @param role_arn [String] IAM role ARN used by the MicroVM runtime
|
|
60
|
+
# @param payload [Object,nil] optional runtime payload
|
|
61
|
+
# @param params [Hash] additional run parameters
|
|
62
|
+
# @return [MicroVM]
|
|
41
63
|
def run(role_arn:, payload: nil, **params)
|
|
42
64
|
request = params.merge(image_arn: arn, role_arn: role_arn)
|
|
43
65
|
request[:payload] = payload if payload
|
|
@@ -6,6 +6,11 @@ module Lambda
|
|
|
6
6
|
class MicroVM
|
|
7
7
|
attr_reader :client, :id, :data
|
|
8
8
|
|
|
9
|
+
# Build a MicroVM resource from an SDK response.
|
|
10
|
+
#
|
|
11
|
+
# @param client [Client] lifecycle client
|
|
12
|
+
# @param response [Object] SDK response
|
|
13
|
+
# @return [MicroVM] MicroVM resource
|
|
9
14
|
def self.from_response(client:, response:)
|
|
10
15
|
id = Util.extract(response, :microvm_id, :microvm_arn, :id, :arn)
|
|
11
16
|
new(client: client, id: id, data: response)
|
|
@@ -17,12 +22,18 @@ module Lambda
|
|
|
17
22
|
@data = data
|
|
18
23
|
end
|
|
19
24
|
|
|
25
|
+
# Refresh MicroVM data from the service.
|
|
26
|
+
#
|
|
27
|
+
# @return [self]
|
|
20
28
|
def refresh
|
|
21
29
|
fresh = client.get_microvm(microvm_id: id)
|
|
22
30
|
@data = fresh.data
|
|
23
31
|
self
|
|
24
32
|
end
|
|
25
33
|
|
|
34
|
+
# Current normalized MicroVM state.
|
|
35
|
+
#
|
|
36
|
+
# @return [Symbol]
|
|
26
37
|
def state
|
|
27
38
|
Util.normalize_state(Util.extract(@data, :state, :status, :microvm_state))
|
|
28
39
|
end
|
|
@@ -43,6 +54,9 @@ module Lambda
|
|
|
43
54
|
state == :pending
|
|
44
55
|
end
|
|
45
56
|
|
|
57
|
+
# Extract the direct endpoint URL from the current MicroVM data.
|
|
58
|
+
#
|
|
59
|
+
# @return [String, nil]
|
|
46
60
|
def endpoint_url
|
|
47
61
|
endpoint = Util.extract(@data, :endpoint, :endpoint_url, :url)
|
|
48
62
|
return endpoint if endpoint.is_a?(String)
|
|
@@ -50,6 +64,12 @@ module Lambda
|
|
|
50
64
|
Util.extract(endpoint, :url, :endpoint_url) if endpoint
|
|
51
65
|
end
|
|
52
66
|
|
|
67
|
+
# Request an auth token for direct endpoint access.
|
|
68
|
+
#
|
|
69
|
+
# @param ports [Array<Integer>, nil] optional allowed ports
|
|
70
|
+
# @param ttl_seconds [Integer, nil] optional token lifetime
|
|
71
|
+
# @param params [Hash] additional token request parameters
|
|
72
|
+
# @return [String, nil] auth token value
|
|
53
73
|
def auth_token(ports: nil, ttl_seconds: nil, **params)
|
|
54
74
|
request = params.merge(microvm_id: id)
|
|
55
75
|
request[:ports] = ports if ports
|
|
@@ -58,34 +78,71 @@ module Lambda
|
|
|
58
78
|
Util.extract(response, :token, :auth_token, :microvm_auth_token)
|
|
59
79
|
end
|
|
60
80
|
|
|
81
|
+
# Build an endpoint client for this MicroVM.
|
|
82
|
+
#
|
|
83
|
+
# @param token [String, nil] existing auth token
|
|
84
|
+
# @param token_params [Hash] parameters used when requesting a token
|
|
85
|
+
# @return [Endpoint]
|
|
61
86
|
def endpoint(token: nil, **token_params)
|
|
62
|
-
|
|
87
|
+
url = endpoint_url
|
|
88
|
+
raise EndpointError.new('MicroVM endpoint URL is unavailable', status: 0, body: nil) unless url
|
|
89
|
+
|
|
90
|
+
Endpoint.new(url: url, token: token || auth_token(**token_params))
|
|
63
91
|
end
|
|
64
92
|
|
|
93
|
+
# Send a GET request to the MicroVM endpoint.
|
|
94
|
+
#
|
|
95
|
+
# @param path [String] endpoint path
|
|
96
|
+
# @param token [String, nil] existing auth token
|
|
97
|
+
# @return [Hash,String,nil] endpoint response
|
|
65
98
|
def get(path, token: nil, **)
|
|
66
99
|
endpoint(token: token).get(path, **)
|
|
67
100
|
end
|
|
68
101
|
|
|
102
|
+
# Send a POST request to the MicroVM endpoint.
|
|
103
|
+
#
|
|
104
|
+
# @param path [String] endpoint path
|
|
105
|
+
# @param json [Hash,Array,nil] JSON body to encode
|
|
106
|
+
# @param body [String,nil] raw request body
|
|
107
|
+
# @param token [String, nil] existing auth token
|
|
108
|
+
# @return [Hash,String,nil] endpoint response
|
|
69
109
|
def post(path, json: nil, body: nil, token: nil, **)
|
|
70
110
|
endpoint(token: token).post(path, json: json, body: body, **)
|
|
71
111
|
end
|
|
72
112
|
|
|
113
|
+
# Suspend this MicroVM.
|
|
114
|
+
#
|
|
115
|
+
# @param params [Hash] additional suspend parameters
|
|
116
|
+
# @return [self]
|
|
73
117
|
def suspend(**params)
|
|
74
118
|
client.suspend_microvm(**params, microvm_id: id)
|
|
75
119
|
self
|
|
76
120
|
end
|
|
77
121
|
|
|
122
|
+
# Resume this MicroVM and update local data when the service returns a response.
|
|
123
|
+
#
|
|
124
|
+
# @param params [Hash] additional resume parameters
|
|
125
|
+
# @return [self]
|
|
78
126
|
def resume(**params)
|
|
79
127
|
response = client.resume_microvm(**params, microvm_id: id)
|
|
80
128
|
@data = response if response
|
|
81
129
|
self
|
|
82
130
|
end
|
|
83
131
|
|
|
132
|
+
# Terminate this MicroVM.
|
|
133
|
+
#
|
|
134
|
+
# @param params [Hash] additional terminate parameters
|
|
135
|
+
# @return [self]
|
|
84
136
|
def terminate(**params)
|
|
85
137
|
client.terminate_microvm(**params, microvm_id: id)
|
|
86
138
|
self
|
|
87
139
|
end
|
|
88
140
|
|
|
141
|
+
# Wait until this MicroVM is running.
|
|
142
|
+
#
|
|
143
|
+
# @param delay [Numeric] polling delay in seconds
|
|
144
|
+
# @param timeout [Numeric] maximum wait in seconds
|
|
145
|
+
# @return [self]
|
|
89
146
|
def wait_until_running(delay: Waiter::DEFAULT_DELAY, timeout: Waiter::DEFAULT_TIMEOUT)
|
|
90
147
|
Waiter.new(delay: delay, timeout: timeout).wait(message: "MicroVM #{id} to be running") do
|
|
91
148
|
refresh.running?
|
|
@@ -93,6 +150,11 @@ module Lambda
|
|
|
93
150
|
self
|
|
94
151
|
end
|
|
95
152
|
|
|
153
|
+
# Wait until this MicroVM is suspended.
|
|
154
|
+
#
|
|
155
|
+
# @param delay [Numeric] polling delay in seconds
|
|
156
|
+
# @param timeout [Numeric] maximum wait in seconds
|
|
157
|
+
# @return [self]
|
|
96
158
|
def wait_until_suspended(delay: Waiter::DEFAULT_DELAY, timeout: Waiter::DEFAULT_TIMEOUT)
|
|
97
159
|
Waiter.new(delay: delay, timeout: timeout).wait(message: "MicroVM #{id} to be suspended") do
|
|
98
160
|
refresh.suspended?
|
|
@@ -100,6 +162,11 @@ module Lambda
|
|
|
100
162
|
self
|
|
101
163
|
end
|
|
102
164
|
|
|
165
|
+
# Wait until this MicroVM is terminated.
|
|
166
|
+
#
|
|
167
|
+
# @param delay [Numeric] polling delay in seconds
|
|
168
|
+
# @param timeout [Numeric] maximum wait in seconds
|
|
169
|
+
# @return [self]
|
|
103
170
|
def wait_until_terminated(delay: Waiter::DEFAULT_DELAY, timeout: Waiter::DEFAULT_TIMEOUT)
|
|
104
171
|
Waiter.new(delay: delay, timeout: timeout).wait(message: "MicroVM #{id} to be terminated") do
|
|
105
172
|
refresh.terminated?
|
|
@@ -8,14 +8,21 @@ module Lambda
|
|
|
8
8
|
module MicroVMs
|
|
9
9
|
# Creates a deployable source artifact for Lambda MicroVM image creation.
|
|
10
10
|
class Packager
|
|
11
|
+
# Default zip exclusion patterns.
|
|
11
12
|
DEFAULT_EXCLUDES = ['.git/*', 'tmp/*', 'vendor/bundle/*', '*.gem'].freeze
|
|
12
13
|
|
|
13
14
|
attr_reader :project
|
|
14
15
|
|
|
15
|
-
def initialize(project)
|
|
16
|
+
def initialize(project, runner: Open3)
|
|
16
17
|
@project = project
|
|
18
|
+
@runner = runner
|
|
17
19
|
end
|
|
18
20
|
|
|
21
|
+
# Create the zip artifact for the configured project.
|
|
22
|
+
#
|
|
23
|
+
# @param output [String] output zip path
|
|
24
|
+
# @return [String] output path
|
|
25
|
+
# @raise [CommandError] when zip exits unsuccessfully
|
|
19
26
|
def package(output: project.artifact_path)
|
|
20
27
|
FileUtils.mkdir_p(File.dirname(output))
|
|
21
28
|
relative_output = begin
|
|
@@ -25,7 +32,7 @@ module Lambda
|
|
|
25
32
|
end
|
|
26
33
|
excludes = DEFAULT_EXCLUDES + [relative_output]
|
|
27
34
|
command = ['zip', '-q', '-r', output, '.'] + excludes.flat_map { |pattern| ['-x', pattern] }
|
|
28
|
-
stdout, stderr, status =
|
|
35
|
+
stdout, stderr, status = @runner.capture3(*command, chdir: project.root)
|
|
29
36
|
raise CommandError, "zip failed: #{stderr.empty? ? stdout : stderr}" unless status.success?
|
|
30
37
|
|
|
31
38
|
output
|
|
@@ -8,10 +8,15 @@ module Lambda
|
|
|
8
8
|
module MicroVMs
|
|
9
9
|
# Reads lambda-microvms project configuration from microvm.yml.
|
|
10
10
|
class Project
|
|
11
|
+
# Default project configuration file name.
|
|
11
12
|
DEFAULT_CONFIG = 'microvm.yml'
|
|
12
13
|
|
|
13
14
|
attr_reader :root, :config_path, :config
|
|
14
15
|
|
|
16
|
+
# Load a project configuration from disk.
|
|
17
|
+
#
|
|
18
|
+
# @param path [String] path to a YAML configuration file
|
|
19
|
+
# @return [Project] loaded project
|
|
15
20
|
def self.load(path = DEFAULT_CONFIG)
|
|
16
21
|
config_path = File.expand_path(path)
|
|
17
22
|
root = File.dirname(config_path)
|
|
@@ -25,36 +30,79 @@ module Lambda
|
|
|
25
30
|
@config = stringify_keys(config)
|
|
26
31
|
end
|
|
27
32
|
|
|
33
|
+
# Project name.
|
|
34
|
+
#
|
|
35
|
+
# @return [String]
|
|
28
36
|
def name = fetch('name', default: File.basename(root))
|
|
29
37
|
|
|
38
|
+
# AWS region from configuration or environment.
|
|
39
|
+
#
|
|
40
|
+
# @return [String, nil]
|
|
30
41
|
def region = fetch('region', default: ENV.fetch('AWS_REGION', nil))
|
|
31
42
|
|
|
43
|
+
# AWS profile from configuration or environment.
|
|
44
|
+
#
|
|
45
|
+
# @return [String, nil]
|
|
32
46
|
def profile = fetch('profile', default: ENV.fetch('AWS_PROFILE', nil))
|
|
33
47
|
|
|
48
|
+
# IAM role ARN used when running MicroVMs.
|
|
49
|
+
#
|
|
50
|
+
# @return [String, nil]
|
|
34
51
|
def role_arn = fetch('role_arn', 'role', default: nil)
|
|
35
52
|
|
|
53
|
+
# Existing MicroVM image ARN.
|
|
54
|
+
#
|
|
55
|
+
# @return [String, nil]
|
|
36
56
|
def image_arn = fetch('image_arn', 'image.arn', default: nil)
|
|
37
57
|
|
|
58
|
+
# Name used when creating a MicroVM image.
|
|
59
|
+
#
|
|
60
|
+
# @return [String]
|
|
38
61
|
def image_name = fetch('image.name', default: name)
|
|
39
62
|
|
|
63
|
+
# Absolute path to the Dockerfile.
|
|
64
|
+
#
|
|
65
|
+
# @return [String]
|
|
40
66
|
def dockerfile = File.expand_path(fetch('build.dockerfile', default: 'Dockerfile'), root)
|
|
41
67
|
|
|
68
|
+
# Absolute path to the build context.
|
|
69
|
+
#
|
|
70
|
+
# @return [String]
|
|
42
71
|
def build_context = File.expand_path(fetch('build.context', default: '.'), root)
|
|
43
72
|
|
|
73
|
+
# Absolute path for the packaged artifact.
|
|
74
|
+
#
|
|
75
|
+
# @return [String]
|
|
44
76
|
def artifact_path = File.expand_path(fetch('build.artifact', default: "tmp/#{name}-microvm.zip"), root)
|
|
45
77
|
|
|
78
|
+
# S3 bucket used for deployment artifacts.
|
|
79
|
+
#
|
|
80
|
+
# @return [String, nil]
|
|
46
81
|
def s3_bucket = fetch('deployment.bucket', 's3.bucket', default: nil)
|
|
47
82
|
|
|
83
|
+
# S3 key prefix used for deployment artifacts.
|
|
84
|
+
#
|
|
85
|
+
# @return [String]
|
|
48
86
|
def s3_prefix = fetch('deployment.prefix', 's3.prefix', default: "lambda-microvms/#{name}")
|
|
49
87
|
|
|
88
|
+
# Cleanup policy used after a session block.
|
|
89
|
+
#
|
|
90
|
+
# @return [Symbol]
|
|
50
91
|
def lifecycle_after = fetch('runtime.after', default: 'suspend').to_sym
|
|
51
92
|
|
|
93
|
+
# Runtime payload configured for MicroVM runs.
|
|
94
|
+
#
|
|
95
|
+
# @return [Hash]
|
|
52
96
|
def payload
|
|
53
|
-
|
|
97
|
+
hash_config('runtime.payload')
|
|
54
98
|
end
|
|
55
99
|
|
|
100
|
+
# Build parameters for image creation with the artifact URI injected.
|
|
101
|
+
#
|
|
102
|
+
# @param artifact_uri [String] uploaded artifact URI
|
|
103
|
+
# @return [Hash] SDK-style create image parameters
|
|
56
104
|
def create_image_params(artifact_uri:)
|
|
57
|
-
params =
|
|
105
|
+
params = hash_config('image.create')
|
|
58
106
|
params = stringify_keys(params)
|
|
59
107
|
symbolized = params.to_h { |key, value| [key.to_sym, value] }
|
|
60
108
|
symbolized[:name] ||= image_name
|
|
@@ -62,22 +110,63 @@ module Lambda
|
|
|
62
110
|
symbolized
|
|
63
111
|
end
|
|
64
112
|
|
|
113
|
+
# Build parameters for running a MicroVM.
|
|
114
|
+
#
|
|
115
|
+
# @return [Hash] SDK-style run parameters
|
|
65
116
|
def run_params
|
|
66
|
-
params = stringify_keys(
|
|
117
|
+
params = stringify_keys(hash_config('runtime.run'))
|
|
67
118
|
symbolized = params.to_h { |key, value| [key.to_sym, value] }
|
|
68
119
|
symbolized[:role_arn] ||= role_arn if role_arn
|
|
69
120
|
symbolized[:payload] ||= payload unless payload.empty?
|
|
70
121
|
symbolized
|
|
71
122
|
end
|
|
72
123
|
|
|
124
|
+
# Validate project configuration sections used by deployment commands.
|
|
125
|
+
#
|
|
126
|
+
# @return [self]
|
|
127
|
+
# @raise [ConfigurationError] when a known section has an invalid shape
|
|
128
|
+
def validate!
|
|
129
|
+
validate_hash!
|
|
130
|
+
validate_lifecycle_after!
|
|
131
|
+
hash_config('image.create')
|
|
132
|
+
hash_config('runtime.payload')
|
|
133
|
+
hash_config('runtime.run')
|
|
134
|
+
self
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# Return a required value or raise a configuration error.
|
|
138
|
+
#
|
|
139
|
+
# @param field [String] configuration field name used in the error
|
|
140
|
+
# @param value [Object] value to validate
|
|
141
|
+
# @return [Object] the validated value
|
|
142
|
+
# @raise [ConfigurationError] when the value is nil or empty
|
|
73
143
|
def require!(field, value)
|
|
74
|
-
return value if value && value != ''
|
|
144
|
+
return value if value && value.to_s.strip != ''
|
|
75
145
|
|
|
76
146
|
raise ConfigurationError, "missing required project configuration: #{field}"
|
|
77
147
|
end
|
|
78
148
|
|
|
79
149
|
private
|
|
80
150
|
|
|
151
|
+
def validate_hash!
|
|
152
|
+
return if @config.is_a?(Hash)
|
|
153
|
+
|
|
154
|
+
raise ConfigurationError, 'project configuration must be a YAML mapping'
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def validate_lifecycle_after!
|
|
158
|
+
return if %i[keep suspend terminate].include?(lifecycle_after)
|
|
159
|
+
|
|
160
|
+
raise ConfigurationError, "unsupported runtime.after: #{lifecycle_after.inspect}"
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def hash_config(path)
|
|
164
|
+
value = fetch(path, default: {}) || {}
|
|
165
|
+
return value if value.is_a?(Hash)
|
|
166
|
+
|
|
167
|
+
raise ConfigurationError, "#{path} must be a mapping"
|
|
168
|
+
end
|
|
169
|
+
|
|
81
170
|
def fetch(*paths, default:)
|
|
82
171
|
paths.each do |path|
|
|
83
172
|
current = @config
|
|
@@ -6,6 +6,15 @@ module Lambda
|
|
|
6
6
|
module Session
|
|
7
7
|
module_function
|
|
8
8
|
|
|
9
|
+
# Run a MicroVM, wait for it, yield it, and then clean it up.
|
|
10
|
+
#
|
|
11
|
+
# @param image_arn [String] MicroVM image ARN
|
|
12
|
+
# @param role_arn [String] IAM role ARN for the MicroVM runtime
|
|
13
|
+
# @param after [Symbol, nil] cleanup policy: :suspend, :terminate, :keep, or nil
|
|
14
|
+
# @param client [Client] lifecycle client
|
|
15
|
+
# @param run_options [Hash] additional run parameters
|
|
16
|
+
# @yieldparam vm [MicroVM] running MicroVM
|
|
17
|
+
# @return [Object] block result
|
|
9
18
|
def session(image_arn:, role_arn:, after: :suspend, client: Client.new, **run_options)
|
|
10
19
|
vm = client.image(image_arn).run(role_arn: role_arn, **run_options)
|
|
11
20
|
vm.wait_until_running
|
|
@@ -14,6 +23,12 @@ module Lambda
|
|
|
14
23
|
cleanup(vm, after) if vm
|
|
15
24
|
end
|
|
16
25
|
|
|
26
|
+
# Apply a session cleanup policy to a MicroVM.
|
|
27
|
+
#
|
|
28
|
+
# @param vm [MicroVM] MicroVM to clean up
|
|
29
|
+
# @param after [Symbol, nil] cleanup policy
|
|
30
|
+
# @return [Object, nil] cleanup result
|
|
31
|
+
# @raise [ArgumentError] when the policy is unknown
|
|
17
32
|
def cleanup(vm, after) # rubocop:disable Naming/MethodParameterName
|
|
18
33
|
case after
|
|
19
34
|
when :keep, nil
|
data/lib/lambda/microvms/util.rb
CHANGED
|
@@ -6,6 +6,11 @@ module Lambda
|
|
|
6
6
|
module Util
|
|
7
7
|
module_function
|
|
8
8
|
|
|
9
|
+
# Extract the first non-nil value from an object method or hash-like key.
|
|
10
|
+
#
|
|
11
|
+
# @param value [Object] response object, hash, or SDK structure
|
|
12
|
+
# @param keys [Array<Symbol,String>] candidate method or key names
|
|
13
|
+
# @return [Object, nil] the first extracted non-nil value
|
|
9
14
|
def extract(value, *keys)
|
|
10
15
|
keys.each do |key|
|
|
11
16
|
if value.respond_to?(key)
|
|
@@ -26,6 +31,10 @@ module Lambda
|
|
|
26
31
|
nil
|
|
27
32
|
end
|
|
28
33
|
|
|
34
|
+
# Normalize a provider state value into a lowercase symbol.
|
|
35
|
+
#
|
|
36
|
+
# @param value [Object] state-like value
|
|
37
|
+
# @return [Symbol] normalized state
|
|
29
38
|
def normalize_state(value)
|
|
30
39
|
value.to_s.downcase.to_sym
|
|
31
40
|
end
|
|
@@ -4,7 +4,9 @@ module Lambda
|
|
|
4
4
|
module MicroVMs
|
|
5
5
|
# Polls a resource until a desired lifecycle state is reached.
|
|
6
6
|
class Waiter
|
|
7
|
+
# Default polling delay, in seconds.
|
|
7
8
|
DEFAULT_DELAY = 1.0
|
|
9
|
+
# Default maximum wait time, in seconds.
|
|
8
10
|
DEFAULT_TIMEOUT = 60.0
|
|
9
11
|
|
|
10
12
|
def initialize(delay: DEFAULT_DELAY, timeout: DEFAULT_TIMEOUT, sleeper: Kernel)
|
|
@@ -13,6 +15,12 @@ module Lambda
|
|
|
13
15
|
@sleeper = sleeper
|
|
14
16
|
end
|
|
15
17
|
|
|
18
|
+
# Poll until the block returns a truthy value or the timeout expires.
|
|
19
|
+
#
|
|
20
|
+
# @param message [String] human-readable condition for timeout errors
|
|
21
|
+
# @yieldreturn [Object, false, nil] truthy value when the condition is satisfied
|
|
22
|
+
# @return [Object] the truthy block result
|
|
23
|
+
# @raise [WaitTimeoutError] if the timeout expires
|
|
16
24
|
def wait(message: 'condition')
|
|
17
25
|
deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + @timeout
|
|
18
26
|
|
data/lib/lambda/microvms.rb
CHANGED
|
@@ -5,7 +5,9 @@ require_relative 'microvms/error'
|
|
|
5
5
|
require_relative 'microvms/util'
|
|
6
6
|
require_relative 'microvms/waiter'
|
|
7
7
|
require_relative 'microvms/endpoint'
|
|
8
|
+
require_relative 'microvms/adapters/microvm_sdk'
|
|
8
9
|
require_relative 'microvms/client'
|
|
10
|
+
require_relative 'microvms/function_client'
|
|
9
11
|
require_relative 'microvms/image'
|
|
10
12
|
require_relative 'microvms/microvm'
|
|
11
13
|
require_relative 'microvms/session'
|
|
@@ -15,11 +17,16 @@ require_relative 'microvms/packager'
|
|
|
15
17
|
require_relative 'microvms/deployer'
|
|
16
18
|
require_relative 'microvms/doctor'
|
|
17
19
|
|
|
20
|
+
# Namespace for Lambda-related libraries.
|
|
18
21
|
module Lambda
|
|
19
22
|
# Idiomatic Ruby lifecycle helpers for AWS Lambda MicroVMs.
|
|
20
23
|
module MicroVMs
|
|
21
24
|
module_function
|
|
22
25
|
|
|
26
|
+
# Run a MicroVM from an image, yield it, and apply the requested cleanup policy.
|
|
27
|
+
#
|
|
28
|
+
# @see Lambda::MicroVMs::Session.session
|
|
29
|
+
# @return [Object] the block result
|
|
23
30
|
def session(...)
|
|
24
31
|
Session.session(...)
|
|
25
32
|
end
|