smplkit 3.0.95 → 3.0.96
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/lib/smplkit/account/client.rb +121 -0
- data/lib/smplkit/account/models.rb +53 -0
- data/lib/smplkit/api_support.rb +83 -0
- data/lib/smplkit/audit/client.rb +9 -10
- data/lib/smplkit/{management/audit.rb → audit/forwarders.rb} +73 -76
- data/lib/smplkit/audit/models.rb +40 -1
- data/lib/smplkit/buffers.rb +235 -0
- data/lib/smplkit/client.rb +126 -67
- data/lib/smplkit/config/client.rb +617 -182
- data/lib/smplkit/config_resolution.rb +11 -5
- data/lib/smplkit/errors.rb +8 -0
- data/lib/smplkit/flags/client.rb +472 -114
- data/lib/smplkit/flags/types.rb +6 -7
- data/lib/smplkit/{management/jobs.rb → jobs/client.rb} +148 -89
- data/lib/smplkit/logging/client.rb +647 -192
- data/lib/smplkit/logging/helpers.rb +1 -0
- data/lib/smplkit/logging/models.rb +92 -1
- data/lib/smplkit/logging/sources.rb +1 -1
- data/lib/smplkit/platform/client.rb +472 -0
- data/lib/smplkit/platform/models.rb +182 -0
- data/lib/smplkit/{management → platform}/types.rb +7 -4
- data/lib/smplkit/transport.rb +99 -0
- data/lib/smplkit.rb +18 -6
- metadata +11 -7
- data/lib/smplkit/management/buffer.rb +0 -198
- data/lib/smplkit/management/client.rb +0 -1074
- data/lib/smplkit/management/models.rb +0 -178
|
@@ -1,1074 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "json"
|
|
4
|
-
|
|
5
|
-
module Smplkit
|
|
6
|
-
# Top-level management client. Owns the HTTP transports + CRUD APIs for
|
|
7
|
-
# every resource on the smplkit platform.
|
|
8
|
-
#
|
|
9
|
-
# Sub-namespaces (mirroring the Python SDK):
|
|
10
|
-
#
|
|
11
|
-
# - +mgmt.contexts.*+
|
|
12
|
-
# - +mgmt.context_types.*+
|
|
13
|
-
# - +mgmt.environments.*+
|
|
14
|
-
# - +mgmt.services.*+
|
|
15
|
-
# - +mgmt.account_settings.*+
|
|
16
|
-
# - +mgmt.config.*+
|
|
17
|
-
# - +mgmt.flags.*+
|
|
18
|
-
# - +mgmt.loggers.*+
|
|
19
|
-
# - +mgmt.log_groups.*+
|
|
20
|
-
#
|
|
21
|
-
# Constructable both as +Smplkit::ManagementClient.new+ (standalone) and as
|
|
22
|
-
# +Smplkit::Client#manage+ (shared transports).
|
|
23
|
-
#
|
|
24
|
-
# Each namespace is wired to a generated +SmplkitGeneratedClient+ +ApiClient+
|
|
25
|
-
# under the hood — auth, request encoding, and response parsing flow through
|
|
26
|
-
# the openapi-generator-produced layer in +lib/smplkit/_generated+. The
|
|
27
|
-
# wrapper layer keeps the customer-facing domain models (+Flag+, +Config+,
|
|
28
|
-
# etc.) and converts at the boundary via the existing
|
|
29
|
-
# +<resource>_from_resource+ helpers.
|
|
30
|
-
class ManagementClient
|
|
31
|
-
# Default page[size] the runtime asks for when walking a list
|
|
32
|
-
# endpoint to completion. The platform caps page[size] at 1000;
|
|
33
|
-
# using the same value here makes the minimum number of round-trips
|
|
34
|
-
# per exhaustive fetch.
|
|
35
|
-
RUNTIME_PAGE_SIZE = 1000
|
|
36
|
-
|
|
37
|
-
attr_reader :contexts, :context_types, :environments, :services, :account_settings,
|
|
38
|
-
:config, :flags, :loggers, :log_groups, :audit, :jobs
|
|
39
|
-
|
|
40
|
-
def self.from_resolved(resolved, extra_headers: nil)
|
|
41
|
-
new(_resolved: resolved, extra_headers: extra_headers)
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def initialize(api_key: nil, base_domain: nil, scheme: nil, profile: nil,
|
|
45
|
-
debug: nil, _resolved: nil, extra_headers: nil)
|
|
46
|
-
cfg = _resolved ||
|
|
47
|
-
ConfigResolution.resolve_management_config(
|
|
48
|
-
api_key: api_key, base_domain: base_domain, scheme: scheme,
|
|
49
|
-
profile: profile, debug: debug
|
|
50
|
-
)
|
|
51
|
-
Smplkit.enable_debug if cfg.debug
|
|
52
|
-
|
|
53
|
-
@resolved = cfg
|
|
54
|
-
|
|
55
|
-
@extra_headers = extra_headers
|
|
56
|
-
@app_api_client = build_api_client(SmplkitGeneratedClient::App, "app", cfg)
|
|
57
|
-
@config_api_client = build_api_client(SmplkitGeneratedClient::Config, "config", cfg)
|
|
58
|
-
@flags_api_client = build_api_client(SmplkitGeneratedClient::Flags, "flags", cfg)
|
|
59
|
-
@logging_api_client = build_api_client(SmplkitGeneratedClient::Logging, "logging", cfg)
|
|
60
|
-
@audit_api_client = build_api_client(SmplkitGeneratedClient::Audit, "audit", cfg)
|
|
61
|
-
@jobs_api_client = build_api_client(SmplkitGeneratedClient::Jobs, "jobs", cfg)
|
|
62
|
-
|
|
63
|
-
@contexts = ContextsNamespace.new(@app_api_client)
|
|
64
|
-
@context_types = ContextTypesNamespace.new(@app_api_client)
|
|
65
|
-
@environments = EnvironmentsNamespace.new(@app_api_client)
|
|
66
|
-
@services = ServicesNamespace.new(@app_api_client)
|
|
67
|
-
@account_settings = AccountSettingsNamespace.new(@app_api_client)
|
|
68
|
-
@config = ConfigNamespace.new(@config_api_client)
|
|
69
|
-
@flags = FlagsNamespace.new(@flags_api_client)
|
|
70
|
-
@loggers = LoggersNamespace.new(@logging_api_client)
|
|
71
|
-
@log_groups = LogGroupsNamespace.new(@logging_api_client)
|
|
72
|
-
@audit = Management::AuditNamespace.new(@audit_api_client)
|
|
73
|
-
@jobs = Management::JobsNamespace.new(@jobs_api_client)
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def close
|
|
77
|
-
# The generated ApiClient owns Faraday connections that release on GC.
|
|
78
|
-
# No explicit shutdown is exposed; this stub keeps the API stable.
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
def _resolved = @resolved
|
|
82
|
-
def _app_http = @app_api_client
|
|
83
|
-
def _config_http = @config_api_client
|
|
84
|
-
def _flags_http = @flags_api_client
|
|
85
|
-
def _logging_http = @logging_api_client
|
|
86
|
-
def _audit_http = @audit_api_client
|
|
87
|
-
def _jobs_http = @jobs_api_client
|
|
88
|
-
|
|
89
|
-
SDK_OWNED_HEADERS = %w[authorization content-type user-agent].freeze
|
|
90
|
-
|
|
91
|
-
private
|
|
92
|
-
|
|
93
|
-
def build_api_client(generated_module, subdomain, cfg)
|
|
94
|
-
configuration = generated_module::Configuration.new
|
|
95
|
-
configuration.scheme = cfg.scheme
|
|
96
|
-
configuration.host = "#{subdomain}.#{cfg.base_domain}"
|
|
97
|
-
configuration.base_path = ""
|
|
98
|
-
configuration.access_token = cfg.api_key
|
|
99
|
-
configuration.debugging = cfg.debug
|
|
100
|
-
HttpPool.configure(configuration)
|
|
101
|
-
generated_module::ApiClient.new(configuration).tap do |client|
|
|
102
|
-
client.default_headers["User-Agent"] = "smplkit-ruby-sdk/#{Smplkit::VERSION}"
|
|
103
|
-
@extra_headers&.each do |k, v|
|
|
104
|
-
client.default_headers[k] = v unless SDK_OWNED_HEADERS.include?(k.downcase)
|
|
105
|
-
end
|
|
106
|
-
end
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
# ------------------------------------------------------------------
|
|
110
|
-
# Shared error-mapping wrapper
|
|
111
|
-
# ------------------------------------------------------------------
|
|
112
|
-
|
|
113
|
-
# Wraps a generated-API call and converts any +ApiError+ raised by the
|
|
114
|
-
# generated layer into the +Smplkit::Error+ hierarchy. Connection-level
|
|
115
|
-
# failures (no response from the server) become +Smplkit::ConnectionError+;
|
|
116
|
-
# status-coded failures route through +Errors.raise_for_status+ which
|
|
117
|
-
# emits +NotFoundError+ / +ConflictError+ / +ValidationError+ / +Error+
|
|
118
|
-
# depending on the JSON:API body.
|
|
119
|
-
module ErrorMapping
|
|
120
|
-
module_function
|
|
121
|
-
|
|
122
|
-
def call
|
|
123
|
-
yield
|
|
124
|
-
rescue StandardError => e
|
|
125
|
-
raise unless generated_api_error?(e)
|
|
126
|
-
|
|
127
|
-
raise Smplkit::ConnectionError, e.message.to_s if e.code.nil? || e.code.zero?
|
|
128
|
-
|
|
129
|
-
Smplkit::Errors.raise_for_status(e.code, e.response_body.to_s)
|
|
130
|
-
# raise_for_status only returns on 2xx; if we get here the generated
|
|
131
|
-
# layer raised on a 2xx (shouldn't happen) so re-raise the original.
|
|
132
|
-
raise
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
def generated_api_error?(err)
|
|
136
|
-
klass_name = err.class.name.to_s
|
|
137
|
-
klass_name.start_with?("SmplkitGeneratedClient::") && klass_name.end_with?("::ApiError")
|
|
138
|
-
end
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
# Walk a generated paginated list endpoint to completion.
|
|
142
|
-
#
|
|
143
|
-
# The block receives a per-page +opts+ hash with +page_number+ and
|
|
144
|
-
# +page_size+ filled in, calls the generated list method through
|
|
145
|
-
# {ErrorMapping.call}, and returns the response object. Pages stop
|
|
146
|
-
# when the server returns fewer rows than requested — the platform's
|
|
147
|
-
# standard last-page signal across every offset-paginated list
|
|
148
|
-
# endpoint. Returns the concatenated +response.data+ rows.
|
|
149
|
-
module PaginatedFetch
|
|
150
|
-
module_function
|
|
151
|
-
|
|
152
|
-
def collect(page_size: RUNTIME_PAGE_SIZE)
|
|
153
|
-
rows = []
|
|
154
|
-
page_number = 1
|
|
155
|
-
loop do
|
|
156
|
-
opts = { page_number: page_number, page_size: page_size }
|
|
157
|
-
response = ErrorMapping.call { yield(opts) }
|
|
158
|
-
page = response.data || []
|
|
159
|
-
rows.concat(page)
|
|
160
|
-
break if page.length < page_size
|
|
161
|
-
|
|
162
|
-
page_number += 1
|
|
163
|
-
end
|
|
164
|
-
rows
|
|
165
|
-
end
|
|
166
|
-
end
|
|
167
|
-
|
|
168
|
-
# Deep-stringify Hash keys so resources returned by generated +to_hash+
|
|
169
|
-
# (symbol-keyed) match what the wrapper helpers expect (string-keyed).
|
|
170
|
-
module ResourceShim
|
|
171
|
-
module_function
|
|
172
|
-
|
|
173
|
-
def stringify(value)
|
|
174
|
-
Smplkit::Helpers.deep_stringify_keys(value)
|
|
175
|
-
end
|
|
176
|
-
|
|
177
|
-
# Convenience: produce a string-keyed Hash from a generated model.
|
|
178
|
-
def from_model(model)
|
|
179
|
-
return {} if model.nil?
|
|
180
|
-
|
|
181
|
-
stringify(model.to_hash)
|
|
182
|
-
end
|
|
183
|
-
end
|
|
184
|
-
|
|
185
|
-
# ------------------------------------------------------------------
|
|
186
|
-
# Sub-namespaces
|
|
187
|
-
# ------------------------------------------------------------------
|
|
188
|
-
|
|
189
|
-
class ContextsNamespace
|
|
190
|
-
def initialize(api_client)
|
|
191
|
-
@api = SmplkitGeneratedClient::App::ContextsApi.new(api_client)
|
|
192
|
-
@buffer = Management::ContextRegistrationBuffer.new
|
|
193
|
-
end
|
|
194
|
-
|
|
195
|
-
def register(contexts)
|
|
196
|
-
return if contexts.nil? || contexts.empty?
|
|
197
|
-
|
|
198
|
-
@buffer.observe(contexts)
|
|
199
|
-
flush if @buffer.pending_count >= Management::CONTEXT_BATCH_FLUSH_SIZE
|
|
200
|
-
end
|
|
201
|
-
|
|
202
|
-
def flush
|
|
203
|
-
batch = @buffer.drain
|
|
204
|
-
return if batch.empty?
|
|
205
|
-
|
|
206
|
-
items = batch.map do |entry|
|
|
207
|
-
SmplkitGeneratedClient::App::ContextBulkItem.new(
|
|
208
|
-
type: entry["type"], key: entry["key"], attributes: entry["attributes"] || {}
|
|
209
|
-
)
|
|
210
|
-
end
|
|
211
|
-
body = SmplkitGeneratedClient::App::ContextBulkRegister.new(contexts: items)
|
|
212
|
-
ErrorMapping.call { @api.bulk_register_contexts(body) }
|
|
213
|
-
rescue StandardError => e
|
|
214
|
-
Smplkit.debug("registration", "context flush failed: #{e.class}: #{e.message}")
|
|
215
|
-
end
|
|
216
|
-
|
|
217
|
-
def list(page_number: nil, page_size: nil)
|
|
218
|
-
opts = {}
|
|
219
|
-
opts[:page_number] = page_number unless page_number.nil?
|
|
220
|
-
opts[:page_size] = page_size unless page_size.nil?
|
|
221
|
-
response = ErrorMapping.call { @api.list_contexts(opts) }
|
|
222
|
-
(response.data || []).map { |r| context_from_resource(ResourceShim.from_model(r)) }
|
|
223
|
-
end
|
|
224
|
-
|
|
225
|
-
def get(id_or_type, key = nil)
|
|
226
|
-
type, ckey = split_id(id_or_type, key)
|
|
227
|
-
response = ErrorMapping.call { @api.get_context("#{type}:#{ckey}") }
|
|
228
|
-
context_from_resource(ResourceShim.from_model(response.data))
|
|
229
|
-
end
|
|
230
|
-
|
|
231
|
-
def delete(id_or_type, key = nil)
|
|
232
|
-
type, ckey = split_id(id_or_type, key)
|
|
233
|
-
ErrorMapping.call { @api.delete_context("#{type}:#{ckey}") }
|
|
234
|
-
true
|
|
235
|
-
end
|
|
236
|
-
|
|
237
|
-
def _save_context(ctx)
|
|
238
|
-
body = SmplkitGeneratedClient::App::ContextResponse.new(
|
|
239
|
-
data: SmplkitGeneratedClient::App::ContextResource.new(
|
|
240
|
-
type: "context",
|
|
241
|
-
id: ctx.id,
|
|
242
|
-
attributes: SmplkitGeneratedClient::App::Context.new(
|
|
243
|
-
name: ctx.name, context_type: ctx.type, attributes: ctx.attributes
|
|
244
|
-
)
|
|
245
|
-
)
|
|
246
|
-
)
|
|
247
|
-
response = ErrorMapping.call { @api.update_context(ctx.id, body) }
|
|
248
|
-
context_from_resource(ResourceShim.from_model(response.data)).tap { |c| c._bind_client(self) }
|
|
249
|
-
end
|
|
250
|
-
|
|
251
|
-
private
|
|
252
|
-
|
|
253
|
-
def split_id(id_or_type, key)
|
|
254
|
-
return [id_or_type, key] if key
|
|
255
|
-
|
|
256
|
-
unless id_or_type.include?(":")
|
|
257
|
-
raise ArgumentError, "context id must be 'type:key' (got #{id_or_type.inspect}); " \
|
|
258
|
-
"alternatively pass type and key as separate args"
|
|
259
|
-
end
|
|
260
|
-
|
|
261
|
-
id_or_type.split(":", 2)
|
|
262
|
-
end
|
|
263
|
-
|
|
264
|
-
def context_from_resource(resource)
|
|
265
|
-
attrs = resource["attributes"] || {}
|
|
266
|
-
Smplkit::Context.new(
|
|
267
|
-
attrs["context_type"] || attrs["type"] || resource["id"].to_s.split(":").first,
|
|
268
|
-
attrs["key"] || resource["id"].to_s.split(":", 2).last,
|
|
269
|
-
attrs["attributes"] || {},
|
|
270
|
-
name: attrs["name"],
|
|
271
|
-
created_at: attrs["created_at"],
|
|
272
|
-
updated_at: attrs["updated_at"]
|
|
273
|
-
)._bind_client(self)
|
|
274
|
-
end
|
|
275
|
-
end
|
|
276
|
-
|
|
277
|
-
class ContextTypesNamespace
|
|
278
|
-
def initialize(api_client)
|
|
279
|
-
@api = SmplkitGeneratedClient::App::ContextTypesApi.new(api_client)
|
|
280
|
-
end
|
|
281
|
-
|
|
282
|
-
def list(page_number: nil, page_size: nil)
|
|
283
|
-
opts = {}
|
|
284
|
-
opts[:page_number] = page_number unless page_number.nil?
|
|
285
|
-
opts[:page_size] = page_size unless page_size.nil?
|
|
286
|
-
response = ErrorMapping.call { @api.list_context_types(opts) }
|
|
287
|
-
(response.data || []).map { |r| from_resource(ResourceShim.from_model(r)) }
|
|
288
|
-
end
|
|
289
|
-
|
|
290
|
-
def get(key)
|
|
291
|
-
response = ErrorMapping.call { @api.get_context_type(key) }
|
|
292
|
-
from_resource(ResourceShim.from_model(response.data))
|
|
293
|
-
end
|
|
294
|
-
|
|
295
|
-
def delete(key)
|
|
296
|
-
ErrorMapping.call { @api.delete_context_type(key) }
|
|
297
|
-
true
|
|
298
|
-
end
|
|
299
|
-
|
|
300
|
-
def new_context_type(key, name: nil, description: nil)
|
|
301
|
-
Management::ContextType.new(self, key: key, name: name, description: description)
|
|
302
|
-
end
|
|
303
|
-
|
|
304
|
-
def _create_context_type(ct)
|
|
305
|
-
response = ErrorMapping.call { @api.create_context_type(body_for(ct)) }
|
|
306
|
-
from_resource(ResourceShim.from_model(response.data))
|
|
307
|
-
end
|
|
308
|
-
|
|
309
|
-
def _update_context_type(ct)
|
|
310
|
-
response = ErrorMapping.call { @api.update_context_type(ct.key, body_for(ct)) }
|
|
311
|
-
from_resource(ResourceShim.from_model(response.data))
|
|
312
|
-
end
|
|
313
|
-
|
|
314
|
-
private
|
|
315
|
-
|
|
316
|
-
def body_for(ct)
|
|
317
|
-
# ContextType server schema: name, attributes, created_at, updated_at.
|
|
318
|
-
# Customer-side +description+ is wrapper-only; not sent on the wire.
|
|
319
|
-
SmplkitGeneratedClient::App::ContextTypeResponse.new(
|
|
320
|
-
data: SmplkitGeneratedClient::App::ContextTypeResource.new(
|
|
321
|
-
type: "context_type",
|
|
322
|
-
id: ct.key,
|
|
323
|
-
attributes: SmplkitGeneratedClient::App::ContextType.new(name: ct.name)
|
|
324
|
-
)
|
|
325
|
-
)
|
|
326
|
-
end
|
|
327
|
-
|
|
328
|
-
def from_resource(resource)
|
|
329
|
-
attrs = resource["attributes"] || {}
|
|
330
|
-
Management::ContextType.new(
|
|
331
|
-
self,
|
|
332
|
-
id: resource["id"], key: attrs["key"] || resource["id"],
|
|
333
|
-
name: attrs["name"], description: attrs["description"],
|
|
334
|
-
created_at: attrs["created_at"], updated_at: attrs["updated_at"]
|
|
335
|
-
)
|
|
336
|
-
end
|
|
337
|
-
end
|
|
338
|
-
|
|
339
|
-
class EnvironmentsNamespace
|
|
340
|
-
def initialize(api_client)
|
|
341
|
-
@api = SmplkitGeneratedClient::App::EnvironmentsApi.new(api_client)
|
|
342
|
-
end
|
|
343
|
-
|
|
344
|
-
def list(page_number: nil, page_size: nil)
|
|
345
|
-
opts = {}
|
|
346
|
-
opts[:page_number] = page_number unless page_number.nil?
|
|
347
|
-
opts[:page_size] = page_size unless page_size.nil?
|
|
348
|
-
response = ErrorMapping.call { @api.list_environments(opts) }
|
|
349
|
-
(response.data || []).map { |r| from_resource(ResourceShim.from_model(r)) }
|
|
350
|
-
end
|
|
351
|
-
|
|
352
|
-
def get(key)
|
|
353
|
-
response = ErrorMapping.call { @api.get_environment(key) }
|
|
354
|
-
from_resource(ResourceShim.from_model(response.data))
|
|
355
|
-
end
|
|
356
|
-
|
|
357
|
-
def delete(key)
|
|
358
|
-
ErrorMapping.call { @api.delete_environment(key) }
|
|
359
|
-
true
|
|
360
|
-
end
|
|
361
|
-
|
|
362
|
-
def new(key, name: nil, color: nil,
|
|
363
|
-
classification: Management::EnvironmentClassification::STANDARD,
|
|
364
|
-
description: nil)
|
|
365
|
-
color = Management::Color.new(color) if color.is_a?(String)
|
|
366
|
-
Management::Environment.new(
|
|
367
|
-
self,
|
|
368
|
-
key: key, name: name || Smplkit::Helpers.key_to_display_name(key),
|
|
369
|
-
color: color, classification: classification, description: description
|
|
370
|
-
)
|
|
371
|
-
end
|
|
372
|
-
|
|
373
|
-
def _create_environment(env)
|
|
374
|
-
response = ErrorMapping.call { @api.create_environment(body_for(env)) }
|
|
375
|
-
from_resource(ResourceShim.from_model(response.data))
|
|
376
|
-
end
|
|
377
|
-
|
|
378
|
-
def _update_environment(env)
|
|
379
|
-
response = ErrorMapping.call { @api.update_environment(env.key, body_for(env)) }
|
|
380
|
-
from_resource(ResourceShim.from_model(response.data))
|
|
381
|
-
end
|
|
382
|
-
|
|
383
|
-
private
|
|
384
|
-
|
|
385
|
-
def body_for(env)
|
|
386
|
-
# Environment server schema: name, color, classification.
|
|
387
|
-
# Customer-side +description+ stays wrapper-only.
|
|
388
|
-
SmplkitGeneratedClient::App::EnvironmentResponse.new(
|
|
389
|
-
data: SmplkitGeneratedClient::App::EnvironmentResource.new(
|
|
390
|
-
type: "environment",
|
|
391
|
-
id: env.key,
|
|
392
|
-
attributes: SmplkitGeneratedClient::App::Environment.new(
|
|
393
|
-
name: env.name,
|
|
394
|
-
color: env.color&.hex,
|
|
395
|
-
classification: env.classification
|
|
396
|
-
)
|
|
397
|
-
)
|
|
398
|
-
)
|
|
399
|
-
end
|
|
400
|
-
|
|
401
|
-
def from_resource(resource)
|
|
402
|
-
attrs = resource["attributes"] || {}
|
|
403
|
-
color = attrs["color"] && Management::Color.new(attrs["color"])
|
|
404
|
-
Management::Environment.new(
|
|
405
|
-
self,
|
|
406
|
-
id: resource["id"], key: attrs["key"] || resource["id"],
|
|
407
|
-
name: attrs["name"], color: color,
|
|
408
|
-
classification: attrs["classification"] || Management::EnvironmentClassification::STANDARD,
|
|
409
|
-
description: attrs["description"],
|
|
410
|
-
created_at: attrs["created_at"], updated_at: attrs["updated_at"]
|
|
411
|
-
)
|
|
412
|
-
end
|
|
413
|
-
end
|
|
414
|
-
|
|
415
|
-
class ServicesNamespace
|
|
416
|
-
def initialize(api_client)
|
|
417
|
-
@api = SmplkitGeneratedClient::App::ServicesApi.new(api_client)
|
|
418
|
-
end
|
|
419
|
-
|
|
420
|
-
def list(page_number: nil, page_size: nil)
|
|
421
|
-
opts = {}
|
|
422
|
-
opts[:page_number] = page_number unless page_number.nil?
|
|
423
|
-
opts[:page_size] = page_size unless page_size.nil?
|
|
424
|
-
response = ErrorMapping.call { @api.list_services(opts) }
|
|
425
|
-
(response.data || []).map { |r| from_resource(ResourceShim.from_model(r)) }
|
|
426
|
-
end
|
|
427
|
-
|
|
428
|
-
def get(key)
|
|
429
|
-
response = ErrorMapping.call { @api.get_service(key) }
|
|
430
|
-
from_resource(ResourceShim.from_model(response.data))
|
|
431
|
-
end
|
|
432
|
-
|
|
433
|
-
def delete(key)
|
|
434
|
-
ErrorMapping.call { @api.delete_service(key) }
|
|
435
|
-
true
|
|
436
|
-
end
|
|
437
|
-
|
|
438
|
-
def new(key, name: nil)
|
|
439
|
-
Management::Service.new(
|
|
440
|
-
self,
|
|
441
|
-
key: key,
|
|
442
|
-
name: name || Smplkit::Helpers.key_to_display_name(key)
|
|
443
|
-
)
|
|
444
|
-
end
|
|
445
|
-
|
|
446
|
-
def _create_service(svc)
|
|
447
|
-
response = ErrorMapping.call { @api.create_service(create_body_for(svc)) }
|
|
448
|
-
from_resource(ResourceShim.from_model(response.data))
|
|
449
|
-
end
|
|
450
|
-
|
|
451
|
-
def _update_service(svc)
|
|
452
|
-
response = ErrorMapping.call { @api.update_service(svc.key, body_for(svc)) }
|
|
453
|
-
from_resource(ResourceShim.from_model(response.data))
|
|
454
|
-
end
|
|
455
|
-
|
|
456
|
-
private
|
|
457
|
-
|
|
458
|
-
def body_for(svc)
|
|
459
|
-
SmplkitGeneratedClient::App::ServiceRequest.new(
|
|
460
|
-
data: SmplkitGeneratedClient::App::ServiceResource.new(
|
|
461
|
-
type: "service",
|
|
462
|
-
id: svc.key,
|
|
463
|
-
attributes: SmplkitGeneratedClient::App::Service.new(
|
|
464
|
-
name: svc.name
|
|
465
|
-
)
|
|
466
|
-
)
|
|
467
|
-
)
|
|
468
|
-
end
|
|
469
|
-
|
|
470
|
-
def create_body_for(svc)
|
|
471
|
-
SmplkitGeneratedClient::App::ServiceCreateRequest.new(
|
|
472
|
-
data: SmplkitGeneratedClient::App::ServiceCreateResource.new(
|
|
473
|
-
type: "service",
|
|
474
|
-
id: svc.key,
|
|
475
|
-
attributes: SmplkitGeneratedClient::App::Service.new(
|
|
476
|
-
name: svc.name
|
|
477
|
-
)
|
|
478
|
-
)
|
|
479
|
-
)
|
|
480
|
-
end
|
|
481
|
-
|
|
482
|
-
def from_resource(resource)
|
|
483
|
-
attrs = resource["attributes"] || {}
|
|
484
|
-
Management::Service.new(
|
|
485
|
-
self,
|
|
486
|
-
id: resource["id"], key: attrs["key"] || resource["id"],
|
|
487
|
-
name: attrs["name"],
|
|
488
|
-
created_at: attrs["created_at"], updated_at: attrs["updated_at"]
|
|
489
|
-
)
|
|
490
|
-
end
|
|
491
|
-
end
|
|
492
|
-
|
|
493
|
-
class AccountSettingsNamespace
|
|
494
|
-
def initialize(api_client)
|
|
495
|
-
@api = SmplkitGeneratedClient::App::AccountApi.new(api_client)
|
|
496
|
-
end
|
|
497
|
-
|
|
498
|
-
def get
|
|
499
|
-
raw = ErrorMapping.call { @api.get_account_settings }
|
|
500
|
-
from_raw(raw)
|
|
501
|
-
end
|
|
502
|
-
|
|
503
|
-
def _update_account_settings(settings)
|
|
504
|
-
# The generator pulled this op without wiring a body parameter
|
|
505
|
-
# (the server accepts a free-form JSON object). The +debug_body+
|
|
506
|
-
# opt is the documented escape hatch.
|
|
507
|
-
raw = ErrorMapping.call do
|
|
508
|
-
@api.put_account_settings(debug_body: settings_body(settings))
|
|
509
|
-
end
|
|
510
|
-
from_raw(raw)
|
|
511
|
-
end
|
|
512
|
-
|
|
513
|
-
private
|
|
514
|
-
|
|
515
|
-
def settings_body(settings)
|
|
516
|
-
{
|
|
517
|
-
"environment_order" => settings.environment_order,
|
|
518
|
-
"default_environment" => settings.default_environment
|
|
519
|
-
}.compact
|
|
520
|
-
end
|
|
521
|
-
|
|
522
|
-
def from_raw(raw)
|
|
523
|
-
attrs = raw.respond_to?(:to_hash) ? ResourceShim.stringify(raw.to_hash) : (raw || {})
|
|
524
|
-
if attrs.is_a?(Hash) && attrs["data"].is_a?(Hash) && attrs["data"]["attributes"]
|
|
525
|
-
attrs = attrs["data"]["attributes"]
|
|
526
|
-
end
|
|
527
|
-
Management::AccountSettings.new(
|
|
528
|
-
self,
|
|
529
|
-
id: attrs["id"],
|
|
530
|
-
environment_order: attrs["environment_order"] || [],
|
|
531
|
-
default_environment: attrs["default_environment"],
|
|
532
|
-
updated_at: attrs["updated_at"]
|
|
533
|
-
)
|
|
534
|
-
end
|
|
535
|
-
end
|
|
536
|
-
|
|
537
|
-
class ConfigNamespace
|
|
538
|
-
def initialize(api_client)
|
|
539
|
-
@api = SmplkitGeneratedClient::Config::ConfigsApi.new(api_client)
|
|
540
|
-
@buffer = Management::ConfigRegistrationBuffer.new
|
|
541
|
-
end
|
|
542
|
-
|
|
543
|
-
# ---------------------------------------------------------------
|
|
544
|
-
# Discovery API (ADR-037 §2.13/§2.14)
|
|
545
|
-
# ---------------------------------------------------------------
|
|
546
|
-
|
|
547
|
-
# Queue a configuration declaration for bulk-discovery upload.
|
|
548
|
-
# Called from +ConfigClient#bind+ and +ConfigClient#get(id, key,
|
|
549
|
-
# default)+. Threshold-flushes on a background thread once the
|
|
550
|
-
# pending buffer reaches the flush size.
|
|
551
|
-
def register_config(config_id, service:, environment:, parent: nil,
|
|
552
|
-
name: nil, description: nil)
|
|
553
|
-
@buffer.declare(config_id, service: service, environment: environment,
|
|
554
|
-
parent: parent, name: name, description: description)
|
|
555
|
-
trigger_background_flush_if_needed
|
|
556
|
-
end
|
|
557
|
-
|
|
558
|
-
# Queue a config item declaration. +register_config+ must have run
|
|
559
|
-
# first; items added without a prior declaration are dropped.
|
|
560
|
-
def register_config_item(config_id, item_key, item_type, default, description = nil)
|
|
561
|
-
@buffer.add_item(config_id, item_key, item_type, default, description)
|
|
562
|
-
trigger_background_flush_if_needed
|
|
563
|
-
end
|
|
564
|
-
|
|
565
|
-
def pending_count
|
|
566
|
-
@buffer.pending_count
|
|
567
|
-
end
|
|
568
|
-
|
|
569
|
-
# Send any pending config declarations to
|
|
570
|
-
# +POST /api/v1/configs/bulk+. Per ADR-024 §2.9 the bulk endpoint is
|
|
571
|
-
# plan-limit-exempt; failures here never propagate to customer code.
|
|
572
|
-
def flush
|
|
573
|
-
batch = @buffer.drain
|
|
574
|
-
return if batch.empty?
|
|
575
|
-
|
|
576
|
-
items = batch.map do |entry|
|
|
577
|
-
SmplkitGeneratedClient::Config::ConfigBulkItem.new(
|
|
578
|
-
id: entry["id"],
|
|
579
|
-
service: entry["service"],
|
|
580
|
-
environment: entry["environment"],
|
|
581
|
-
parent: entry["parent"],
|
|
582
|
-
name: entry["name"],
|
|
583
|
-
description: entry["description"],
|
|
584
|
-
items: bulk_items_to_wire(entry["items"])
|
|
585
|
-
)
|
|
586
|
-
end
|
|
587
|
-
body = SmplkitGeneratedClient::Config::ConfigBulkRequest.new(configs: items)
|
|
588
|
-
begin
|
|
589
|
-
ErrorMapping.call { @api.bulk_register_configs(body) }
|
|
590
|
-
rescue StandardError => e
|
|
591
|
-
# Fire-and-forget per ADR-024 §2.9.
|
|
592
|
-
Smplkit.debug("registration", "config bulk register failed: #{e.class}: #{e.message}")
|
|
593
|
-
end
|
|
594
|
-
end
|
|
595
|
-
|
|
596
|
-
def list(page_number: nil, page_size: nil)
|
|
597
|
-
opts = {}
|
|
598
|
-
opts[:page_number] = page_number unless page_number.nil?
|
|
599
|
-
opts[:page_size] = page_size unless page_size.nil?
|
|
600
|
-
response = ErrorMapping.call { @api.list_configs(opts) }
|
|
601
|
-
(response.data || []).map { |r| Smplkit::Config::Helpers.config_from_json(self, ResourceShim.from_model(r)) }
|
|
602
|
-
end
|
|
603
|
-
|
|
604
|
-
def get(key)
|
|
605
|
-
response = ErrorMapping.call { @api.get_config(key) }
|
|
606
|
-
Smplkit::Config::Helpers.config_from_json(self, ResourceShim.from_model(response.data))
|
|
607
|
-
end
|
|
608
|
-
|
|
609
|
-
def delete(key)
|
|
610
|
-
ErrorMapping.call { @api.delete_config(key) }
|
|
611
|
-
true
|
|
612
|
-
end
|
|
613
|
-
|
|
614
|
-
def new_config(key, name: nil, description: nil, parent: nil)
|
|
615
|
-
Smplkit::Config::Config.new(
|
|
616
|
-
self,
|
|
617
|
-
key: key,
|
|
618
|
-
name: name || Smplkit::Helpers.key_to_display_name(key),
|
|
619
|
-
description: description,
|
|
620
|
-
parent_id: parent.is_a?(Smplkit::Config::Config) ? parent.key : parent
|
|
621
|
-
)
|
|
622
|
-
end
|
|
623
|
-
|
|
624
|
-
def _create_config(config)
|
|
625
|
-
response = ErrorMapping.call { @api.create_config(config_body(config)) }
|
|
626
|
-
Smplkit::Config::Helpers.config_from_json(self, ResourceShim.from_model(response.data))
|
|
627
|
-
end
|
|
628
|
-
|
|
629
|
-
def _update_config(config)
|
|
630
|
-
response = ErrorMapping.call { @api.update_config(config.key, config_body(config)) }
|
|
631
|
-
Smplkit::Config::Helpers.config_from_json(self, ResourceShim.from_model(response.data))
|
|
632
|
-
end
|
|
633
|
-
|
|
634
|
-
# Walk every page of +list_configs+ so an account with more than
|
|
635
|
-
# +RUNTIME_PAGE_SIZE+ configs still resolves to the complete set. Used
|
|
636
|
-
# by the runtime client to refresh the resolved cache.
|
|
637
|
-
def list_all
|
|
638
|
-
rows = PaginatedFetch.collect { |opts| @api.list_configs(opts) }
|
|
639
|
-
rows.map { |r| Smplkit::Config::Helpers.config_from_json(self, ResourceShim.from_model(r)) }
|
|
640
|
-
end
|
|
641
|
-
|
|
642
|
-
private
|
|
643
|
-
|
|
644
|
-
def config_body(config)
|
|
645
|
-
SmplkitGeneratedClient::Config::ConfigResponse.new(
|
|
646
|
-
data: SmplkitGeneratedClient::Config::ConfigResource.new(
|
|
647
|
-
type: "config",
|
|
648
|
-
id: config.key,
|
|
649
|
-
attributes: SmplkitGeneratedClient::Config::Config.new(
|
|
650
|
-
name: config.name,
|
|
651
|
-
description: config.description,
|
|
652
|
-
parent: config.parent_id,
|
|
653
|
-
items: config_items_to_wire(config.items),
|
|
654
|
-
environments: config_envs_to_wire(config.environments)
|
|
655
|
-
)
|
|
656
|
-
)
|
|
657
|
-
)
|
|
658
|
-
end
|
|
659
|
-
|
|
660
|
-
def config_items_to_wire(items)
|
|
661
|
-
return nil if items.nil? || items.empty?
|
|
662
|
-
|
|
663
|
-
items.to_h do |item|
|
|
664
|
-
[item.name, SmplkitGeneratedClient::Config::ConfigItemDefinition.new(
|
|
665
|
-
value: item.value, type: item.type, description: item.description
|
|
666
|
-
)]
|
|
667
|
-
end
|
|
668
|
-
end
|
|
669
|
-
|
|
670
|
-
def config_envs_to_wire(environments)
|
|
671
|
-
return nil if environments.empty?
|
|
672
|
-
|
|
673
|
-
# Per ADR-024 §2.4 the wire shape for env overrides is a flat
|
|
674
|
-
# +{env: {key: rawValue}}+ map — no envelope, no per-key type
|
|
675
|
-
# wrapper. The generated +Config.environments+ attribute accepts
|
|
676
|
-
# +Hash<String, Hash<String, Object>>+ directly.
|
|
677
|
-
environments.each_with_object({}) do |(env_key, env_obj), out|
|
|
678
|
-
out[env_key] = env_obj.values
|
|
679
|
-
end
|
|
680
|
-
end
|
|
681
|
-
|
|
682
|
-
def bulk_items_to_wire(items_hash)
|
|
683
|
-
return nil if items_hash.nil? || items_hash.empty?
|
|
684
|
-
|
|
685
|
-
items_hash.transform_values do |def_hash|
|
|
686
|
-
SmplkitGeneratedClient::Config::ConfigItemDefinition.new(
|
|
687
|
-
value: def_hash["value"],
|
|
688
|
-
type: def_hash["type"],
|
|
689
|
-
description: def_hash["description"]
|
|
690
|
-
)
|
|
691
|
-
end
|
|
692
|
-
end
|
|
693
|
-
|
|
694
|
-
def trigger_background_flush_if_needed
|
|
695
|
-
return unless @buffer.pending_count >= Management::CONFIG_BATCH_FLUSH_SIZE
|
|
696
|
-
|
|
697
|
-
Thread.new do
|
|
698
|
-
flush
|
|
699
|
-
rescue StandardError => e
|
|
700
|
-
Smplkit.debug("registration", "threshold config flush failed: #{e.class}: #{e.message}")
|
|
701
|
-
end
|
|
702
|
-
end
|
|
703
|
-
end
|
|
704
|
-
|
|
705
|
-
class FlagsNamespace
|
|
706
|
-
def initialize(api_client)
|
|
707
|
-
@api = SmplkitGeneratedClient::Flags::FlagsApi.new(api_client)
|
|
708
|
-
@buffer = Management::FlagRegistrationBuffer.new
|
|
709
|
-
end
|
|
710
|
-
|
|
711
|
-
def register(declaration)
|
|
712
|
-
@buffer.add(declaration)
|
|
713
|
-
return unless @buffer.pending_count >= Management::FLAG_BATCH_FLUSH_SIZE
|
|
714
|
-
|
|
715
|
-
begin
|
|
716
|
-
flush
|
|
717
|
-
rescue StandardError => e
|
|
718
|
-
Smplkit.debug("registration", "threshold flag flush failed: #{e.class}: #{e.message}")
|
|
719
|
-
end
|
|
720
|
-
end
|
|
721
|
-
|
|
722
|
-
# POST pending declarations to the bulk endpoint.
|
|
723
|
-
#
|
|
724
|
-
# Items remain in the buffer until the request succeeds, so a flush
|
|
725
|
-
# against an unhealthy service is automatically retried by the next
|
|
726
|
-
# +flush+ call (lazy +start+ retry, periodic background flush, or
|
|
727
|
-
# final flush on close). Raises on failure — callers decide whether
|
|
728
|
-
# to retry.
|
|
729
|
-
def flush
|
|
730
|
-
batch = @buffer.peek
|
|
731
|
-
return if batch.empty?
|
|
732
|
-
|
|
733
|
-
flag_items = batch.map do |entry|
|
|
734
|
-
SmplkitGeneratedClient::Flags::FlagBulkItem.new(
|
|
735
|
-
id: entry["id"], type: entry["type"], default: entry["default"],
|
|
736
|
-
service: entry["service"], environment: entry["environment"]
|
|
737
|
-
)
|
|
738
|
-
end
|
|
739
|
-
body = SmplkitGeneratedClient::Flags::FlagBulkRequest.new(flags: flag_items)
|
|
740
|
-
ErrorMapping.call { @api.bulk_register_flags(body) }
|
|
741
|
-
@buffer.commit(batch.map { |b| b["id"] })
|
|
742
|
-
end
|
|
743
|
-
|
|
744
|
-
def pending_count
|
|
745
|
-
@buffer.pending_count
|
|
746
|
-
end
|
|
747
|
-
|
|
748
|
-
def list(page_number: nil, page_size: nil)
|
|
749
|
-
opts = {}
|
|
750
|
-
opts[:page_number] = page_number unless page_number.nil?
|
|
751
|
-
opts[:page_size] = page_size unless page_size.nil?
|
|
752
|
-
response = ErrorMapping.call { @api.list_flags(opts) }
|
|
753
|
-
(response.data || []).map { |r| flag_from_resource(ResourceShim.from_model(r)) }
|
|
754
|
-
end
|
|
755
|
-
|
|
756
|
-
def get(id)
|
|
757
|
-
response = ErrorMapping.call { @api.get_flag(id) }
|
|
758
|
-
flag_from_resource(ResourceShim.from_model(response.data))
|
|
759
|
-
end
|
|
760
|
-
|
|
761
|
-
def delete(id)
|
|
762
|
-
ErrorMapping.call { @api.delete_flag(id) }
|
|
763
|
-
true
|
|
764
|
-
end
|
|
765
|
-
|
|
766
|
-
def new_boolean_flag(id, default:, name: nil, description: nil, values: nil)
|
|
767
|
-
Smplkit::Flags::BooleanFlag.new(
|
|
768
|
-
self, id: id, name: name || id, type: "BOOLEAN", default: default,
|
|
769
|
-
description: description, values: values
|
|
770
|
-
)
|
|
771
|
-
end
|
|
772
|
-
|
|
773
|
-
def new_string_flag(id, default:, name: nil, description: nil, values: nil)
|
|
774
|
-
Smplkit::Flags::StringFlag.new(
|
|
775
|
-
self, id: id, name: name || id, type: "STRING", default: default,
|
|
776
|
-
description: description, values: values
|
|
777
|
-
)
|
|
778
|
-
end
|
|
779
|
-
|
|
780
|
-
def new_number_flag(id, default:, name: nil, description: nil, values: nil)
|
|
781
|
-
Smplkit::Flags::NumberFlag.new(
|
|
782
|
-
self, id: id, name: name || id, type: "NUMERIC", default: default,
|
|
783
|
-
description: description, values: values
|
|
784
|
-
)
|
|
785
|
-
end
|
|
786
|
-
|
|
787
|
-
def new_json_flag(id, default:, name: nil, description: nil, values: nil)
|
|
788
|
-
Smplkit::Flags::JsonFlag.new(
|
|
789
|
-
self, id: id, name: name || id, type: "JSON", default: default,
|
|
790
|
-
description: description, values: values
|
|
791
|
-
)
|
|
792
|
-
end
|
|
793
|
-
|
|
794
|
-
def _create_flag(flag)
|
|
795
|
-
response = ErrorMapping.call { @api.create_flag(flag_body(flag)) }
|
|
796
|
-
flag_from_resource(ResourceShim.from_model(response.data))
|
|
797
|
-
end
|
|
798
|
-
|
|
799
|
-
def _update_flag(flag)
|
|
800
|
-
response = ErrorMapping.call { @api.update_flag(flag.id, flag_body(flag)) }
|
|
801
|
-
flag_from_resource(ResourceShim.from_model(response.data))
|
|
802
|
-
end
|
|
803
|
-
|
|
804
|
-
def fetch_flag(id)
|
|
805
|
-
response = ErrorMapping.call { @api.get_flag(id) }
|
|
806
|
-
Smplkit::Flags::Helpers.flag_dict_from_json(ResourceShim.from_model(response.data))
|
|
807
|
-
end
|
|
808
|
-
|
|
809
|
-
# Runtime entry — walks every page so an account holding more than
|
|
810
|
-
# +RUNTIME_PAGE_SIZE+ flags still gets a complete in-memory store.
|
|
811
|
-
def list_flags
|
|
812
|
-
rows = PaginatedFetch.collect { |opts| @api.list_flags(opts) }
|
|
813
|
-
rows.map { |r| Smplkit::Flags::Helpers.flag_dict_from_json(ResourceShim.from_model(r)) }
|
|
814
|
-
end
|
|
815
|
-
|
|
816
|
-
private
|
|
817
|
-
|
|
818
|
-
def flag_body(flag)
|
|
819
|
-
SmplkitGeneratedClient::Flags::FlagResponse.new(
|
|
820
|
-
data: SmplkitGeneratedClient::Flags::FlagResource.new(
|
|
821
|
-
type: "flag",
|
|
822
|
-
id: flag.id,
|
|
823
|
-
attributes: SmplkitGeneratedClient::Flags::Flag.new(
|
|
824
|
-
name: flag.name,
|
|
825
|
-
type: flag.type,
|
|
826
|
-
default: flag.default,
|
|
827
|
-
description: flag.description,
|
|
828
|
-
values: flag_values_to_wire(flag.values),
|
|
829
|
-
environments: flag_envs_to_wire(flag.environments)
|
|
830
|
-
)
|
|
831
|
-
)
|
|
832
|
-
)
|
|
833
|
-
end
|
|
834
|
-
|
|
835
|
-
def flag_values_to_wire(values)
|
|
836
|
-
return nil if values.nil?
|
|
837
|
-
|
|
838
|
-
values.map do |v|
|
|
839
|
-
SmplkitGeneratedClient::Flags::FlagValue.new(name: v.name, value: v.value)
|
|
840
|
-
end
|
|
841
|
-
end
|
|
842
|
-
|
|
843
|
-
def flag_envs_to_wire(environments)
|
|
844
|
-
return nil if environments.empty?
|
|
845
|
-
|
|
846
|
-
environments.each_with_object({}) do |(env_key, env_obj), out|
|
|
847
|
-
rules = env_obj.rules.map do |r|
|
|
848
|
-
SmplkitGeneratedClient::Flags::FlagRule.new(
|
|
849
|
-
logic: r.logic, value: r.value, description: r.description
|
|
850
|
-
)
|
|
851
|
-
end
|
|
852
|
-
out[env_key] = SmplkitGeneratedClient::Flags::FlagEnvironment.new(
|
|
853
|
-
enabled: env_obj.enabled, default: env_obj.default, rules: rules
|
|
854
|
-
)
|
|
855
|
-
end
|
|
856
|
-
end
|
|
857
|
-
|
|
858
|
-
def flag_from_resource(resource)
|
|
859
|
-
d = Smplkit::Flags::Helpers.flag_dict_from_json(resource)
|
|
860
|
-
klass =
|
|
861
|
-
case d["type"]
|
|
862
|
-
when "BOOLEAN" then Smplkit::Flags::BooleanFlag
|
|
863
|
-
when "STRING" then Smplkit::Flags::StringFlag
|
|
864
|
-
when "NUMERIC" then Smplkit::Flags::NumberFlag
|
|
865
|
-
else Smplkit::Flags::JsonFlag
|
|
866
|
-
end
|
|
867
|
-
klass.new(
|
|
868
|
-
self,
|
|
869
|
-
id: d["id"], name: d["name"], type: d["type"], default: d["default"],
|
|
870
|
-
description: d["description"], values: d["values"], environments: d["environments"],
|
|
871
|
-
created_at: (resource["attributes"] || {})["created_at"],
|
|
872
|
-
updated_at: (resource["attributes"] || {})["updated_at"]
|
|
873
|
-
)
|
|
874
|
-
end
|
|
875
|
-
end
|
|
876
|
-
|
|
877
|
-
class LoggersNamespace
|
|
878
|
-
def initialize(api_client)
|
|
879
|
-
@api = SmplkitGeneratedClient::Logging::LoggersApi.new(api_client)
|
|
880
|
-
@buffer = Management::LoggerRegistrationBuffer.new
|
|
881
|
-
end
|
|
882
|
-
|
|
883
|
-
def register(source)
|
|
884
|
-
sources = source.is_a?(Array) ? source : [source]
|
|
885
|
-
sources.each { |s| @buffer.add(s) }
|
|
886
|
-
flush if @buffer.pending_count >= Management::LOGGER_BATCH_FLUSH_SIZE
|
|
887
|
-
end
|
|
888
|
-
|
|
889
|
-
def flush
|
|
890
|
-
batch = @buffer.drain
|
|
891
|
-
return if batch.empty?
|
|
892
|
-
|
|
893
|
-
items = batch.map do |entry|
|
|
894
|
-
SmplkitGeneratedClient::Logging::LoggerBulkItem.new(
|
|
895
|
-
id: entry["id"],
|
|
896
|
-
resolved_level: entry["resolved_level"],
|
|
897
|
-
level: entry["level"],
|
|
898
|
-
service: entry["service"],
|
|
899
|
-
environment: entry["environment"]
|
|
900
|
-
)
|
|
901
|
-
end
|
|
902
|
-
body = SmplkitGeneratedClient::Logging::LoggerBulkRequest.new(loggers: items)
|
|
903
|
-
ErrorMapping.call { @api.bulk_register_loggers(body) }
|
|
904
|
-
rescue StandardError => e
|
|
905
|
-
Smplkit.debug("registration", "logger flush failed: #{e.class}: #{e.message}")
|
|
906
|
-
end
|
|
907
|
-
|
|
908
|
-
def list(page_number: nil, page_size: nil)
|
|
909
|
-
opts = {}
|
|
910
|
-
opts[:page_number] = page_number unless page_number.nil?
|
|
911
|
-
opts[:page_size] = page_size unless page_size.nil?
|
|
912
|
-
response = ErrorMapping.call { @api.list_loggers(opts) }
|
|
913
|
-
(response.data || []).map do |r|
|
|
914
|
-
Smplkit::Logging::Helpers.logger_resource_to_model(self, ResourceShim.from_model(r))
|
|
915
|
-
end
|
|
916
|
-
end
|
|
917
|
-
|
|
918
|
-
def get(id)
|
|
919
|
-
normalized = Smplkit::Logging::Normalize.normalize_logger_name(id)
|
|
920
|
-
response = ErrorMapping.call { @api.get_logger(normalized) }
|
|
921
|
-
Smplkit::Logging::Helpers.logger_resource_to_model(self, ResourceShim.from_model(response.data))
|
|
922
|
-
end
|
|
923
|
-
|
|
924
|
-
def delete(id)
|
|
925
|
-
normalized = Smplkit::Logging::Normalize.normalize_logger_name(id)
|
|
926
|
-
ErrorMapping.call { @api.delete_logger(normalized) }
|
|
927
|
-
true
|
|
928
|
-
end
|
|
929
|
-
|
|
930
|
-
def _update_logger(logger)
|
|
931
|
-
response = ErrorMapping.call { @api.update_logger(logger.id || logger.name, logger_body(logger)) }
|
|
932
|
-
Smplkit::Logging::Helpers.logger_resource_to_model(self, ResourceShim.from_model(response.data))
|
|
933
|
-
end
|
|
934
|
-
|
|
935
|
-
# Runtime entry — walks every page and returns an id-keyed Hash of
|
|
936
|
-
# resolution-cache entries (+level+, +group+, +managed+,
|
|
937
|
-
# +environments+). Mirrors the Python SDK's
|
|
938
|
-
# +LoggingClient._fetch_and_apply+ loggers branch.
|
|
939
|
-
def list_logger_entries
|
|
940
|
-
rows = PaginatedFetch.collect { |opts| @api.list_loggers(opts) }
|
|
941
|
-
rows.to_h { |r| logger_entry_from_resource(ResourceShim.from_model(r)) }
|
|
942
|
-
end
|
|
943
|
-
|
|
944
|
-
# Fetch one logger as a resolution-cache entry. Used by the
|
|
945
|
-
# +logger_changed+ WS handler.
|
|
946
|
-
def get_logger_entry(id)
|
|
947
|
-
normalized = Smplkit::Logging::Normalize.normalize_logger_name(id)
|
|
948
|
-
response = ErrorMapping.call { @api.get_logger(normalized) }
|
|
949
|
-
logger_entry_from_resource(ResourceShim.from_model(response.data))
|
|
950
|
-
end
|
|
951
|
-
|
|
952
|
-
private
|
|
953
|
-
|
|
954
|
-
def logger_entry_from_resource(resource)
|
|
955
|
-
attrs = resource["attributes"] || {}
|
|
956
|
-
[
|
|
957
|
-
resource["id"],
|
|
958
|
-
{
|
|
959
|
-
"level" => attrs["level"],
|
|
960
|
-
"group" => attrs["group"],
|
|
961
|
-
"managed" => attrs.key?("managed") ? attrs["managed"] : true,
|
|
962
|
-
"environments" => attrs["environments"] || {}
|
|
963
|
-
}
|
|
964
|
-
]
|
|
965
|
-
end
|
|
966
|
-
|
|
967
|
-
def logger_body(logger)
|
|
968
|
-
# Logger server schema: name, level, group, managed.
|
|
969
|
-
# +resolved_level+ is read-only, +service+/+environment+ are
|
|
970
|
-
# observed via bulk register, +description+ is wrapper-local.
|
|
971
|
-
SmplkitGeneratedClient::Logging::LoggerResponse.new(
|
|
972
|
-
data: SmplkitGeneratedClient::Logging::LoggerResource.new(
|
|
973
|
-
type: "logger",
|
|
974
|
-
id: logger.id,
|
|
975
|
-
attributes: SmplkitGeneratedClient::Logging::Logger.new(
|
|
976
|
-
name: logger.name,
|
|
977
|
-
level: logger.level&.to_s,
|
|
978
|
-
group: logger.log_group_id,
|
|
979
|
-
managed: logger.managed
|
|
980
|
-
)
|
|
981
|
-
)
|
|
982
|
-
)
|
|
983
|
-
end
|
|
984
|
-
end
|
|
985
|
-
|
|
986
|
-
class LogGroupsNamespace
|
|
987
|
-
def initialize(api_client)
|
|
988
|
-
@api = SmplkitGeneratedClient::Logging::LogGroupsApi.new(api_client)
|
|
989
|
-
end
|
|
990
|
-
|
|
991
|
-
def list(page_number: nil, page_size: nil)
|
|
992
|
-
opts = {}
|
|
993
|
-
opts[:page_number] = page_number unless page_number.nil?
|
|
994
|
-
opts[:page_size] = page_size unless page_size.nil?
|
|
995
|
-
response = ErrorMapping.call { @api.list_log_groups(opts) }
|
|
996
|
-
(response.data || []).map do |r|
|
|
997
|
-
Smplkit::Logging::Helpers.log_group_resource_to_model(self, ResourceShim.from_model(r))
|
|
998
|
-
end
|
|
999
|
-
end
|
|
1000
|
-
|
|
1001
|
-
def get(key)
|
|
1002
|
-
response = ErrorMapping.call { @api.get_log_group(key) }
|
|
1003
|
-
Smplkit::Logging::Helpers.log_group_resource_to_model(self, ResourceShim.from_model(response.data))
|
|
1004
|
-
end
|
|
1005
|
-
|
|
1006
|
-
def delete(key)
|
|
1007
|
-
ErrorMapping.call { @api.delete_log_group(key) }
|
|
1008
|
-
true
|
|
1009
|
-
end
|
|
1010
|
-
|
|
1011
|
-
def new_log_group(key, name: nil, level: nil, description: nil, parent: nil)
|
|
1012
|
-
Smplkit::Logging::SmplLogGroup.new(
|
|
1013
|
-
self, key: key, name: name || Smplkit::Helpers.key_to_display_name(key),
|
|
1014
|
-
level: level && Smplkit::LogLevel.coerce(level), description: description,
|
|
1015
|
-
parent_id: parent.is_a?(Smplkit::Logging::SmplLogGroup) ? parent.key : parent
|
|
1016
|
-
)
|
|
1017
|
-
end
|
|
1018
|
-
|
|
1019
|
-
def _create_log_group(group)
|
|
1020
|
-
response = ErrorMapping.call { @api.create_log_group(log_group_body(group)) }
|
|
1021
|
-
Smplkit::Logging::Helpers.log_group_resource_to_model(self, ResourceShim.from_model(response.data))
|
|
1022
|
-
end
|
|
1023
|
-
|
|
1024
|
-
def _update_log_group(group)
|
|
1025
|
-
response = ErrorMapping.call { @api.update_log_group(group.key, log_group_body(group)) }
|
|
1026
|
-
Smplkit::Logging::Helpers.log_group_resource_to_model(self, ResourceShim.from_model(response.data))
|
|
1027
|
-
end
|
|
1028
|
-
|
|
1029
|
-
# Runtime entry — walks every page and returns an id-keyed Hash of
|
|
1030
|
-
# resolution-cache entries (+level+, +group+, +environments+). The
|
|
1031
|
-
# +group+ key carries the *parent group id* so the resolution
|
|
1032
|
-
# algorithm can walk the chain with the same key shape it uses for
|
|
1033
|
-
# loggers.
|
|
1034
|
-
def list_group_entries
|
|
1035
|
-
rows = PaginatedFetch.collect { |opts| @api.list_log_groups(opts) }
|
|
1036
|
-
rows.to_h { |r| group_entry_from_resource(ResourceShim.from_model(r)) }
|
|
1037
|
-
end
|
|
1038
|
-
|
|
1039
|
-
def get_group_entry(key)
|
|
1040
|
-
response = ErrorMapping.call { @api.get_log_group(key) }
|
|
1041
|
-
group_entry_from_resource(ResourceShim.from_model(response.data))
|
|
1042
|
-
end
|
|
1043
|
-
|
|
1044
|
-
private
|
|
1045
|
-
|
|
1046
|
-
def group_entry_from_resource(resource)
|
|
1047
|
-
attrs = resource["attributes"] || {}
|
|
1048
|
-
[
|
|
1049
|
-
resource["id"],
|
|
1050
|
-
{
|
|
1051
|
-
"level" => attrs["level"],
|
|
1052
|
-
"group" => attrs["parent_id"],
|
|
1053
|
-
"environments" => attrs["environments"] || {}
|
|
1054
|
-
}
|
|
1055
|
-
]
|
|
1056
|
-
end
|
|
1057
|
-
|
|
1058
|
-
def log_group_body(group)
|
|
1059
|
-
# LogGroup server schema: name, level, parent_id (no description).
|
|
1060
|
-
SmplkitGeneratedClient::Logging::LogGroupResponse.new(
|
|
1061
|
-
data: SmplkitGeneratedClient::Logging::LogGroupResource.new(
|
|
1062
|
-
type: "log_group",
|
|
1063
|
-
id: group.key,
|
|
1064
|
-
attributes: SmplkitGeneratedClient::Logging::LogGroup.new(
|
|
1065
|
-
name: group.name,
|
|
1066
|
-
level: group.level&.to_s,
|
|
1067
|
-
parent_id: group.parent_id
|
|
1068
|
-
)
|
|
1069
|
-
)
|
|
1070
|
-
)
|
|
1071
|
-
end
|
|
1072
|
-
end
|
|
1073
|
-
end
|
|
1074
|
-
end
|