smplkit 1.0.13 → 1.0.15
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/README.md +14 -3
- data/lib/smplkit/_generated/app/lib/smplkit_app_client/configuration.rb +1 -1
- data/lib/smplkit/_generated/config/lib/smplkit_config_client/configuration.rb +1 -1
- data/lib/smplkit/_generated/flags/lib/smplkit_flags_client/configuration.rb +1 -1
- data/lib/smplkit/_generated/flags/lib/smplkit_flags_client/models/flag_environment.rb +1 -1
- data/lib/smplkit/_generated/logging/lib/smplkit_logging_client/configuration.rb +1 -1
- data/lib/smplkit/client.rb +26 -17
- data/lib/smplkit/config/helpers.rb +0 -26
- data/lib/smplkit/config_resolution.rb +6 -4
- data/lib/smplkit/errors.rb +2 -2
- data/lib/smplkit/flags/helpers.rb +0 -24
- data/lib/smplkit/flags/models.rb +1 -1
- data/lib/smplkit/logging/client.rb +4 -0
- data/lib/smplkit/logging/helpers.rb +0 -26
- data/lib/smplkit/management/client.rb +366 -215
- data/lib/smplkit/ws.rb +9 -5
- data/lib/smplkit.rb +23 -0
- data/sig/smplkit/config.rbs +78 -0
- data/sig/smplkit/flags.rbs +93 -0
- data/sig/smplkit/logging.rbs +92 -0
- data/sig/smplkit/management.rbs +123 -0
- metadata +50 -14
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "faraday"
|
|
4
3
|
require "json"
|
|
5
|
-
require "concurrent"
|
|
6
4
|
|
|
7
5
|
module Smplkit
|
|
8
6
|
# Top-level management client. Owns the HTTP transports + CRUD APIs for
|
|
@@ -21,6 +19,13 @@ module Smplkit
|
|
|
21
19
|
#
|
|
22
20
|
# Constructable both as +Smplkit::ManagementClient.new+ (standalone) and as
|
|
23
21
|
# +Smplkit::Client#manage+ (shared transports).
|
|
22
|
+
#
|
|
23
|
+
# Each namespace is wired to a generated +SmplkitGeneratedClient+ +ApiClient+
|
|
24
|
+
# under the hood — auth, request encoding, and response parsing flow through
|
|
25
|
+
# the openapi-generator-produced layer in +lib/smplkit/_generated+. The
|
|
26
|
+
# wrapper layer keeps the customer-facing domain models (+Flag+, +Config+,
|
|
27
|
+
# etc.) and converts at the boundary via the existing
|
|
28
|
+
# +<resource>_from_resource+ helpers.
|
|
24
29
|
class ManagementClient
|
|
25
30
|
attr_reader :contexts, :context_types, :environments, :account_settings,
|
|
26
31
|
:config, :flags, :loggers, :log_groups
|
|
@@ -39,95 +44,110 @@ module Smplkit
|
|
|
39
44
|
Smplkit.enable_debug if cfg.debug
|
|
40
45
|
|
|
41
46
|
@resolved = cfg
|
|
42
|
-
|
|
43
|
-
@
|
|
44
|
-
@
|
|
45
|
-
@
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
@
|
|
49
|
-
@
|
|
50
|
-
@
|
|
51
|
-
@
|
|
52
|
-
@
|
|
53
|
-
@
|
|
54
|
-
@
|
|
47
|
+
|
|
48
|
+
@app_api_client = build_api_client(SmplkitGeneratedClient::App, "app", cfg)
|
|
49
|
+
@config_api_client = build_api_client(SmplkitGeneratedClient::Config, "config", cfg)
|
|
50
|
+
@flags_api_client = build_api_client(SmplkitGeneratedClient::Flags, "flags", cfg)
|
|
51
|
+
@logging_api_client = build_api_client(SmplkitGeneratedClient::Logging, "logging", cfg)
|
|
52
|
+
|
|
53
|
+
@contexts = ContextsNamespace.new(@app_api_client)
|
|
54
|
+
@context_types = ContextTypesNamespace.new(@app_api_client)
|
|
55
|
+
@environments = EnvironmentsNamespace.new(@app_api_client)
|
|
56
|
+
@account_settings = AccountSettingsNamespace.new(@app_api_client)
|
|
57
|
+
@config = ConfigNamespace.new(@config_api_client)
|
|
58
|
+
@flags = FlagsNamespace.new(@flags_api_client)
|
|
59
|
+
@loggers = LoggersNamespace.new(@logging_api_client)
|
|
60
|
+
@log_groups = LogGroupsNamespace.new(@logging_api_client)
|
|
55
61
|
end
|
|
56
62
|
|
|
57
63
|
def close
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
end
|
|
64
|
+
# The generated ApiClient owns Faraday connections that release on GC.
|
|
65
|
+
# No explicit shutdown is exposed; this stub keeps the API stable.
|
|
61
66
|
end
|
|
62
67
|
|
|
63
68
|
def _resolved = @resolved
|
|
64
|
-
def _app_http = @
|
|
65
|
-
def _config_http = @
|
|
66
|
-
def _flags_http = @
|
|
67
|
-
def _logging_http = @
|
|
69
|
+
def _app_http = @app_api_client
|
|
70
|
+
def _config_http = @config_api_client
|
|
71
|
+
def _flags_http = @flags_api_client
|
|
72
|
+
def _logging_http = @logging_api_client
|
|
68
73
|
|
|
69
74
|
private
|
|
70
75
|
|
|
71
|
-
def
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
76
|
+
def build_api_client(generated_module, subdomain, cfg)
|
|
77
|
+
configuration = generated_module::Configuration.new
|
|
78
|
+
configuration.scheme = cfg.scheme
|
|
79
|
+
configuration.host = "#{subdomain}.#{cfg.base_domain}"
|
|
80
|
+
configuration.base_path = ""
|
|
81
|
+
configuration.access_token = cfg.api_key
|
|
82
|
+
configuration.debugging = cfg.debug
|
|
83
|
+
generated_module::ApiClient.new(configuration).tap do |client|
|
|
84
|
+
client.default_headers["User-Agent"] = "smplkit-ruby-sdk/#{Smplkit::VERSION}"
|
|
78
85
|
end
|
|
79
86
|
end
|
|
80
87
|
|
|
81
88
|
# ------------------------------------------------------------------
|
|
82
|
-
#
|
|
89
|
+
# Shared error-mapping wrapper
|
|
83
90
|
# ------------------------------------------------------------------
|
|
84
91
|
|
|
85
|
-
#
|
|
86
|
-
#
|
|
87
|
-
#
|
|
88
|
-
#
|
|
89
|
-
|
|
90
|
-
|
|
92
|
+
# Wraps a generated-API call and converts any +ApiError+ raised by the
|
|
93
|
+
# generated layer into the +Smplkit::Error+ hierarchy. Connection-level
|
|
94
|
+
# failures (no response from the server) become +Smplkit::ConnectionError+;
|
|
95
|
+
# status-coded failures route through +Errors.raise_for_status+ which
|
|
96
|
+
# emits +NotFoundError+ / +ConflictError+ / +ValidationError+ / +Error+
|
|
97
|
+
# depending on the JSON:API body.
|
|
98
|
+
module ErrorMapping
|
|
99
|
+
module_function
|
|
100
|
+
|
|
101
|
+
def call
|
|
102
|
+
yield
|
|
103
|
+
rescue StandardError => e
|
|
104
|
+
raise unless generated_api_error?(e)
|
|
91
105
|
|
|
92
|
-
|
|
93
|
-
response = @http.get(path)
|
|
94
|
-
Errors.raise_for_status(response.status, response.body)
|
|
95
|
-
response.body.to_s.empty? ? {} : JSON.parse(response.body)
|
|
96
|
-
end
|
|
106
|
+
raise Smplkit::ConnectionError, e.message.to_s if e.code.nil? || e.code.zero?
|
|
97
107
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
108
|
+
Smplkit::Errors.raise_for_status(e.code, e.response_body.to_s)
|
|
109
|
+
# raise_for_status only returns on 2xx; if we get here the generated
|
|
110
|
+
# layer raised on a 2xx (shouldn't happen) so re-raise the original.
|
|
111
|
+
raise
|
|
101
112
|
end
|
|
102
113
|
|
|
103
|
-
def
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
end
|
|
107
|
-
Errors.raise_for_status(response.status, response.body)
|
|
108
|
-
response.body.to_s.empty? ? {} : JSON.parse(response.body)
|
|
114
|
+
def generated_api_error?(err)
|
|
115
|
+
klass_name = err.class.name.to_s
|
|
116
|
+
klass_name.start_with?("SmplkitGeneratedClient::") && klass_name.end_with?("::ApiError")
|
|
109
117
|
end
|
|
118
|
+
end
|
|
110
119
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
120
|
+
# Deep-stringify Hash keys so resources returned by generated +to_hash+
|
|
121
|
+
# (symbol-keyed) match what the wrapper helpers expect (string-keyed).
|
|
122
|
+
module ResourceShim
|
|
123
|
+
module_function
|
|
124
|
+
|
|
125
|
+
def stringify(value)
|
|
126
|
+
case value
|
|
127
|
+
when Hash
|
|
128
|
+
value.each_with_object({}) { |(k, v), out| out[k.to_s] = stringify(v) }
|
|
129
|
+
when Array
|
|
130
|
+
value.map { |v| stringify(v) }
|
|
131
|
+
else
|
|
132
|
+
value
|
|
114
133
|
end
|
|
115
|
-
Errors.raise_for_status(response.status, response.body)
|
|
116
|
-
response.body.to_s.empty? ? {} : JSON.parse(response.body)
|
|
117
134
|
end
|
|
118
135
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
136
|
+
# Convenience: produce a string-keyed Hash from a generated model.
|
|
137
|
+
def from_model(model)
|
|
138
|
+
return {} if model.nil?
|
|
139
|
+
|
|
140
|
+
stringify(model.to_hash)
|
|
123
141
|
end
|
|
124
142
|
end
|
|
125
143
|
|
|
126
|
-
|
|
127
|
-
|
|
144
|
+
# ------------------------------------------------------------------
|
|
145
|
+
# Sub-namespaces
|
|
146
|
+
# ------------------------------------------------------------------
|
|
128
147
|
|
|
129
|
-
|
|
130
|
-
|
|
148
|
+
class ContextsNamespace
|
|
149
|
+
def initialize(api_client)
|
|
150
|
+
@api = SmplkitGeneratedClient::App::ContextsApi.new(api_client)
|
|
131
151
|
@buffer = Management::ContextRegistrationBuffer.new
|
|
132
152
|
end
|
|
133
153
|
|
|
@@ -142,38 +162,46 @@ module Smplkit
|
|
|
142
162
|
batch = @buffer.drain
|
|
143
163
|
return if batch.empty?
|
|
144
164
|
|
|
145
|
-
|
|
146
|
-
|
|
165
|
+
items = batch.map do |entry|
|
|
166
|
+
SmplkitGeneratedClient::App::ContextBulkItem.new(
|
|
167
|
+
type: entry["type"], key: entry["key"], attributes: entry["attributes"] || {}
|
|
168
|
+
)
|
|
169
|
+
end
|
|
170
|
+
body = SmplkitGeneratedClient::App::ContextBulkRegister.new(contexts: items)
|
|
171
|
+
ErrorMapping.call { @api.bulk_register_contexts(body) }
|
|
147
172
|
rescue StandardError => e
|
|
148
173
|
Smplkit.debug("registration", "context flush failed: #{e.class}: #{e.message}")
|
|
149
174
|
end
|
|
150
175
|
|
|
151
176
|
def list
|
|
152
|
-
|
|
153
|
-
|
|
177
|
+
response = ErrorMapping.call { @api.list_contexts }
|
|
178
|
+
(response.data || []).map { |r| context_from_resource(ResourceShim.from_model(r)) }
|
|
154
179
|
end
|
|
155
180
|
|
|
156
181
|
def get(id_or_type, key = nil)
|
|
157
182
|
type, ckey = split_id(id_or_type, key)
|
|
158
|
-
|
|
159
|
-
context_from_resource(
|
|
183
|
+
response = ErrorMapping.call { @api.get_context("#{type}:#{ckey}") }
|
|
184
|
+
context_from_resource(ResourceShim.from_model(response.data))
|
|
160
185
|
end
|
|
161
186
|
|
|
162
187
|
def delete(id_or_type, key = nil)
|
|
163
188
|
type, ckey = split_id(id_or_type, key)
|
|
164
|
-
|
|
189
|
+
ErrorMapping.call { @api.delete_context("#{type}:#{ckey}") }
|
|
190
|
+
true
|
|
165
191
|
end
|
|
166
192
|
|
|
167
193
|
def _save_context(ctx)
|
|
168
|
-
body =
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
194
|
+
body = SmplkitGeneratedClient::App::ContextResponse.new(
|
|
195
|
+
data: SmplkitGeneratedClient::App::ContextResource.new(
|
|
196
|
+
type: "context",
|
|
197
|
+
id: ctx.id,
|
|
198
|
+
attributes: SmplkitGeneratedClient::App::Context.new(
|
|
199
|
+
name: ctx.name, context_type: ctx.type, attributes: ctx.attributes
|
|
200
|
+
)
|
|
201
|
+
)
|
|
202
|
+
)
|
|
203
|
+
response = ErrorMapping.call { @api.update_context(ctx.id, body) }
|
|
204
|
+
context_from_resource(ResourceShim.from_model(response.data)).tap { |c| c._bind_client(self) }
|
|
177
205
|
end
|
|
178
206
|
|
|
179
207
|
private
|
|
@@ -192,7 +220,7 @@ module Smplkit
|
|
|
192
220
|
def context_from_resource(resource)
|
|
193
221
|
attrs = resource["attributes"] || {}
|
|
194
222
|
Smplkit::Context.new(
|
|
195
|
-
attrs["type"] || resource["id"].to_s.split(":").first,
|
|
223
|
+
attrs["context_type"] || attrs["type"] || resource["id"].to_s.split(":").first,
|
|
196
224
|
attrs["key"] || resource["id"].to_s.split(":", 2).last,
|
|
197
225
|
attrs["attributes"] || {},
|
|
198
226
|
name: attrs["name"],
|
|
@@ -203,24 +231,23 @@ module Smplkit
|
|
|
203
231
|
end
|
|
204
232
|
|
|
205
233
|
class ContextTypesNamespace
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
def initialize(http)
|
|
209
|
-
@http = http
|
|
234
|
+
def initialize(api_client)
|
|
235
|
+
@api = SmplkitGeneratedClient::App::ContextTypesApi.new(api_client)
|
|
210
236
|
end
|
|
211
237
|
|
|
212
238
|
def list
|
|
213
|
-
|
|
214
|
-
|
|
239
|
+
response = ErrorMapping.call { @api.list_context_types }
|
|
240
|
+
(response.data || []).map { |r| from_resource(ResourceShim.from_model(r)) }
|
|
215
241
|
end
|
|
216
242
|
|
|
217
243
|
def get(key)
|
|
218
|
-
|
|
219
|
-
from_resource(
|
|
244
|
+
response = ErrorMapping.call { @api.get_context_type(key) }
|
|
245
|
+
from_resource(ResourceShim.from_model(response.data))
|
|
220
246
|
end
|
|
221
247
|
|
|
222
248
|
def delete(key)
|
|
223
|
-
|
|
249
|
+
ErrorMapping.call { @api.delete_context_type(key) }
|
|
250
|
+
true
|
|
224
251
|
end
|
|
225
252
|
|
|
226
253
|
def new_context_type(key, name: nil, description: nil)
|
|
@@ -228,25 +255,27 @@ module Smplkit
|
|
|
228
255
|
end
|
|
229
256
|
|
|
230
257
|
def _create_context_type(ct)
|
|
231
|
-
|
|
232
|
-
from_resource(
|
|
258
|
+
response = ErrorMapping.call { @api.create_context_type(body_for(ct)) }
|
|
259
|
+
from_resource(ResourceShim.from_model(response.data))
|
|
233
260
|
end
|
|
234
261
|
|
|
235
262
|
def _update_context_type(ct)
|
|
236
|
-
|
|
237
|
-
from_resource(
|
|
263
|
+
response = ErrorMapping.call { @api.update_context_type(ct.key, body_for(ct)) }
|
|
264
|
+
from_resource(ResourceShim.from_model(response.data))
|
|
238
265
|
end
|
|
239
266
|
|
|
240
267
|
private
|
|
241
268
|
|
|
242
269
|
def body_for(ct)
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
270
|
+
# ContextType server schema: name, attributes, created_at, updated_at.
|
|
271
|
+
# Customer-side +description+ is wrapper-only; not sent on the wire.
|
|
272
|
+
SmplkitGeneratedClient::App::ContextTypeResponse.new(
|
|
273
|
+
data: SmplkitGeneratedClient::App::ContextTypeResource.new(
|
|
274
|
+
type: "context_type",
|
|
275
|
+
id: ct.key,
|
|
276
|
+
attributes: SmplkitGeneratedClient::App::ContextType.new(name: ct.name)
|
|
277
|
+
)
|
|
278
|
+
)
|
|
250
279
|
end
|
|
251
280
|
|
|
252
281
|
def from_resource(resource)
|
|
@@ -261,24 +290,23 @@ module Smplkit
|
|
|
261
290
|
end
|
|
262
291
|
|
|
263
292
|
class EnvironmentsNamespace
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
def initialize(http)
|
|
267
|
-
@http = http
|
|
293
|
+
def initialize(api_client)
|
|
294
|
+
@api = SmplkitGeneratedClient::App::EnvironmentsApi.new(api_client)
|
|
268
295
|
end
|
|
269
296
|
|
|
270
297
|
def list
|
|
271
|
-
|
|
272
|
-
|
|
298
|
+
response = ErrorMapping.call { @api.list_environments }
|
|
299
|
+
(response.data || []).map { |r| from_resource(ResourceShim.from_model(r)) }
|
|
273
300
|
end
|
|
274
301
|
|
|
275
302
|
def get(key)
|
|
276
|
-
|
|
277
|
-
from_resource(
|
|
303
|
+
response = ErrorMapping.call { @api.get_environment(key) }
|
|
304
|
+
from_resource(ResourceShim.from_model(response.data))
|
|
278
305
|
end
|
|
279
306
|
|
|
280
307
|
def delete(key)
|
|
281
|
-
|
|
308
|
+
ErrorMapping.call { @api.delete_environment(key) }
|
|
309
|
+
true
|
|
282
310
|
end
|
|
283
311
|
|
|
284
312
|
def new(key, name: nil, color: nil,
|
|
@@ -293,31 +321,31 @@ module Smplkit
|
|
|
293
321
|
end
|
|
294
322
|
|
|
295
323
|
def _create_environment(env)
|
|
296
|
-
|
|
297
|
-
from_resource(
|
|
324
|
+
response = ErrorMapping.call { @api.create_environment(body_for(env)) }
|
|
325
|
+
from_resource(ResourceShim.from_model(response.data))
|
|
298
326
|
end
|
|
299
327
|
|
|
300
328
|
def _update_environment(env)
|
|
301
|
-
|
|
302
|
-
from_resource(
|
|
329
|
+
response = ErrorMapping.call { @api.update_environment(env.key, body_for(env)) }
|
|
330
|
+
from_resource(ResourceShim.from_model(response.data))
|
|
303
331
|
end
|
|
304
332
|
|
|
305
333
|
private
|
|
306
334
|
|
|
307
335
|
def body_for(env)
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
"
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
336
|
+
# Environment server schema: name, color, classification.
|
|
337
|
+
# Customer-side +description+ stays wrapper-only.
|
|
338
|
+
SmplkitGeneratedClient::App::EnvironmentResponse.new(
|
|
339
|
+
data: SmplkitGeneratedClient::App::EnvironmentResource.new(
|
|
340
|
+
type: "environment",
|
|
341
|
+
id: env.key,
|
|
342
|
+
attributes: SmplkitGeneratedClient::App::Environment.new(
|
|
343
|
+
name: env.name,
|
|
344
|
+
color: env.color&.hex,
|
|
345
|
+
classification: env.classification
|
|
346
|
+
)
|
|
347
|
+
)
|
|
348
|
+
)
|
|
321
349
|
end
|
|
322
350
|
|
|
323
351
|
def from_resource(resource)
|
|
@@ -335,41 +363,42 @@ module Smplkit
|
|
|
335
363
|
end
|
|
336
364
|
|
|
337
365
|
class AccountSettingsNamespace
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
def initialize(http)
|
|
341
|
-
@http = http
|
|
366
|
+
def initialize(api_client)
|
|
367
|
+
@api = SmplkitGeneratedClient::App::AccountApi.new(api_client)
|
|
342
368
|
end
|
|
343
369
|
|
|
344
370
|
def get
|
|
345
|
-
|
|
346
|
-
|
|
371
|
+
raw = ErrorMapping.call { @api.get_account_settings }
|
|
372
|
+
from_raw(raw)
|
|
347
373
|
end
|
|
348
374
|
|
|
349
375
|
def _update_account_settings(settings)
|
|
350
|
-
|
|
351
|
-
|
|
376
|
+
# The generator pulled this op without wiring a body parameter
|
|
377
|
+
# (the server accepts a free-form JSON object). The +debug_body+
|
|
378
|
+
# opt is the documented escape hatch.
|
|
379
|
+
raw = ErrorMapping.call do
|
|
380
|
+
@api.put_account_settings(debug_body: settings_body(settings))
|
|
381
|
+
end
|
|
382
|
+
from_raw(raw)
|
|
352
383
|
end
|
|
353
384
|
|
|
354
385
|
private
|
|
355
386
|
|
|
356
|
-
def
|
|
387
|
+
def settings_body(settings)
|
|
357
388
|
{
|
|
358
|
-
"
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
"environment_order" => settings.environment_order,
|
|
362
|
-
"default_environment" => settings.default_environment
|
|
363
|
-
}.compact
|
|
364
|
-
}
|
|
365
|
-
}
|
|
389
|
+
"environment_order" => settings.environment_order,
|
|
390
|
+
"default_environment" => settings.default_environment
|
|
391
|
+
}.compact
|
|
366
392
|
end
|
|
367
393
|
|
|
368
|
-
def
|
|
369
|
-
attrs =
|
|
394
|
+
def from_raw(raw)
|
|
395
|
+
attrs = raw.respond_to?(:to_hash) ? ResourceShim.stringify(raw.to_hash) : (raw || {})
|
|
396
|
+
if attrs.is_a?(Hash) && attrs["data"].is_a?(Hash) && attrs["data"]["attributes"]
|
|
397
|
+
attrs = attrs["data"]["attributes"]
|
|
398
|
+
end
|
|
370
399
|
Management::AccountSettings.new(
|
|
371
400
|
self,
|
|
372
|
-
id:
|
|
401
|
+
id: attrs["id"],
|
|
373
402
|
environment_order: attrs["environment_order"] || [],
|
|
374
403
|
default_environment: attrs["default_environment"],
|
|
375
404
|
updated_at: attrs["updated_at"]
|
|
@@ -378,24 +407,23 @@ module Smplkit
|
|
|
378
407
|
end
|
|
379
408
|
|
|
380
409
|
class ConfigNamespace
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
def initialize(http)
|
|
384
|
-
@http = http
|
|
410
|
+
def initialize(api_client)
|
|
411
|
+
@api = SmplkitGeneratedClient::Config::ConfigsApi.new(api_client)
|
|
385
412
|
end
|
|
386
413
|
|
|
387
414
|
def list
|
|
388
|
-
|
|
389
|
-
|
|
415
|
+
response = ErrorMapping.call { @api.list_configs }
|
|
416
|
+
(response.data || []).map { |r| Smplkit::Config::Helpers.config_from_json(self, ResourceShim.from_model(r)) }
|
|
390
417
|
end
|
|
391
418
|
|
|
392
419
|
def get(key)
|
|
393
|
-
|
|
394
|
-
Smplkit::Config::Helpers.config_from_json(self,
|
|
420
|
+
response = ErrorMapping.call { @api.get_config(key) }
|
|
421
|
+
Smplkit::Config::Helpers.config_from_json(self, ResourceShim.from_model(response.data))
|
|
395
422
|
end
|
|
396
423
|
|
|
397
424
|
def delete(key)
|
|
398
|
-
|
|
425
|
+
ErrorMapping.call { @api.delete_config(key) }
|
|
426
|
+
true
|
|
399
427
|
end
|
|
400
428
|
|
|
401
429
|
def new_config(key, name: nil, description: nil, parent: nil)
|
|
@@ -409,27 +437,22 @@ module Smplkit
|
|
|
409
437
|
end
|
|
410
438
|
|
|
411
439
|
def _create_config(config)
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
Smplkit::Config::Helpers.config_from_json(self, resp["data"])
|
|
440
|
+
response = ErrorMapping.call { @api.create_config(config_body(config)) }
|
|
441
|
+
Smplkit::Config::Helpers.config_from_json(self, ResourceShim.from_model(response.data))
|
|
415
442
|
end
|
|
416
443
|
|
|
417
444
|
def _update_config(config)
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
Smplkit::Config::Helpers.config_from_json(self, resp["data"])
|
|
445
|
+
response = ErrorMapping.call { @api.update_config(config.key, config_body(config)) }
|
|
446
|
+
Smplkit::Config::Helpers.config_from_json(self, ResourceShim.from_model(response.data))
|
|
421
447
|
end
|
|
422
448
|
|
|
423
449
|
# Build the parent-chain for a given config, walking +parent_id+
|
|
424
450
|
# pointers across the full config list. Mirrors the Python SDK's
|
|
425
451
|
# client-side resolution — there is no server +/chain+ endpoint.
|
|
426
|
-
#
|
|
427
|
-
# Each chain entry is a Hash matching the wire shape that
|
|
428
|
-
# +Smplkit::Config::Helpers.resolve_chain+ consumes.
|
|
429
452
|
def fetch_chain(target_key)
|
|
430
453
|
all_configs = list
|
|
431
454
|
by_key = all_configs.to_h { |c| [c.key, c] }
|
|
432
|
-
by_id
|
|
455
|
+
by_id = all_configs.to_h { |c| [c.id, c] }
|
|
433
456
|
|
|
434
457
|
current = by_key[target_key]
|
|
435
458
|
return [] unless current
|
|
@@ -450,6 +473,46 @@ module Smplkit
|
|
|
450
473
|
|
|
451
474
|
private
|
|
452
475
|
|
|
476
|
+
def config_body(config)
|
|
477
|
+
SmplkitGeneratedClient::Config::ConfigResponse.new(
|
|
478
|
+
data: SmplkitGeneratedClient::Config::ConfigResource.new(
|
|
479
|
+
type: "config",
|
|
480
|
+
id: config.key,
|
|
481
|
+
attributes: SmplkitGeneratedClient::Config::Config.new(
|
|
482
|
+
name: config.name,
|
|
483
|
+
description: config.description,
|
|
484
|
+
parent: config.parent_id,
|
|
485
|
+
items: config_items_to_wire(config.items),
|
|
486
|
+
environments: config_envs_to_wire(config.environments)
|
|
487
|
+
)
|
|
488
|
+
)
|
|
489
|
+
)
|
|
490
|
+
end
|
|
491
|
+
|
|
492
|
+
def config_items_to_wire(items)
|
|
493
|
+
return nil if items.nil? || items.empty?
|
|
494
|
+
|
|
495
|
+
items.to_h do |item|
|
|
496
|
+
[item.name, SmplkitGeneratedClient::Config::ConfigItemDefinition.new(
|
|
497
|
+
value: item.value, type: item.type, description: item.description
|
|
498
|
+
)]
|
|
499
|
+
end
|
|
500
|
+
end
|
|
501
|
+
|
|
502
|
+
def config_envs_to_wire(environments)
|
|
503
|
+
return nil if environments.empty?
|
|
504
|
+
|
|
505
|
+
# ConfigItemOverride only carries +value+ on the wire — environment
|
|
506
|
+
# overrides override the value, not the type or description.
|
|
507
|
+
environments.each_with_object({}) do |(env_key, env_obj), out|
|
|
508
|
+
values = env_obj.values_raw.each_with_object({}) do |(k, v), inner|
|
|
509
|
+
v_hash = v.is_a?(Hash) ? v : { "value" => v }
|
|
510
|
+
inner[k] = SmplkitGeneratedClient::Config::ConfigItemOverride.new(value: v_hash["value"])
|
|
511
|
+
end
|
|
512
|
+
out[env_key] = SmplkitGeneratedClient::Config::EnvironmentOverride.new(values: values)
|
|
513
|
+
end
|
|
514
|
+
end
|
|
515
|
+
|
|
453
516
|
def config_to_chain_entry(config)
|
|
454
517
|
items_hash = {}
|
|
455
518
|
config.items.each do |item|
|
|
@@ -469,10 +532,8 @@ module Smplkit
|
|
|
469
532
|
end
|
|
470
533
|
|
|
471
534
|
class FlagsNamespace
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
def initialize(http)
|
|
475
|
-
@http = http
|
|
535
|
+
def initialize(api_client)
|
|
536
|
+
@api = SmplkitGeneratedClient::Flags::FlagsApi.new(api_client)
|
|
476
537
|
@buffer = Management::FlagRegistrationBuffer.new
|
|
477
538
|
end
|
|
478
539
|
|
|
@@ -485,24 +546,31 @@ module Smplkit
|
|
|
485
546
|
batch = @buffer.drain
|
|
486
547
|
return if batch.empty?
|
|
487
548
|
|
|
488
|
-
|
|
489
|
-
|
|
549
|
+
flag_items = batch.map do |entry|
|
|
550
|
+
SmplkitGeneratedClient::Flags::FlagBulkItem.new(
|
|
551
|
+
id: entry["id"], type: entry["type"], default: entry["default"],
|
|
552
|
+
service: entry["service"], environment: entry["environment"]
|
|
553
|
+
)
|
|
554
|
+
end
|
|
555
|
+
body = SmplkitGeneratedClient::Flags::FlagBulkRequest.new(flags: flag_items)
|
|
556
|
+
ErrorMapping.call { @api.bulk_register_flags(body) }
|
|
490
557
|
rescue StandardError => e
|
|
491
558
|
Smplkit.debug("registration", "flag flush failed: #{e.class}: #{e.message}")
|
|
492
559
|
end
|
|
493
560
|
|
|
494
561
|
def list
|
|
495
|
-
|
|
496
|
-
|
|
562
|
+
response = ErrorMapping.call { @api.list_flags }
|
|
563
|
+
(response.data || []).map { |r| flag_from_resource(ResourceShim.from_model(r)) }
|
|
497
564
|
end
|
|
498
565
|
|
|
499
566
|
def get(id)
|
|
500
|
-
|
|
501
|
-
flag_from_resource(
|
|
567
|
+
response = ErrorMapping.call { @api.get_flag(id) }
|
|
568
|
+
flag_from_resource(ResourceShim.from_model(response.data))
|
|
502
569
|
end
|
|
503
570
|
|
|
504
571
|
def delete(id)
|
|
505
|
-
|
|
572
|
+
ErrorMapping.call { @api.delete_flag(id) }
|
|
573
|
+
true
|
|
506
574
|
end
|
|
507
575
|
|
|
508
576
|
def new_boolean_flag(id, default:, name: nil, description: nil, values: nil)
|
|
@@ -534,29 +602,67 @@ module Smplkit
|
|
|
534
602
|
end
|
|
535
603
|
|
|
536
604
|
def _create_flag(flag)
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
flag_from_resource(resp["data"])
|
|
605
|
+
response = ErrorMapping.call { @api.create_flag(flag_body(flag)) }
|
|
606
|
+
flag_from_resource(ResourceShim.from_model(response.data))
|
|
540
607
|
end
|
|
541
608
|
|
|
542
609
|
def _update_flag(flag)
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
flag_from_resource(resp["data"])
|
|
610
|
+
response = ErrorMapping.call { @api.update_flag(flag.id, flag_body(flag)) }
|
|
611
|
+
flag_from_resource(ResourceShim.from_model(response.data))
|
|
546
612
|
end
|
|
547
613
|
|
|
548
614
|
def fetch_flag(id)
|
|
549
|
-
|
|
550
|
-
Smplkit::Flags::Helpers.flag_dict_from_json(
|
|
615
|
+
response = ErrorMapping.call { @api.get_flag(id) }
|
|
616
|
+
Smplkit::Flags::Helpers.flag_dict_from_json(ResourceShim.from_model(response.data))
|
|
551
617
|
end
|
|
552
618
|
|
|
553
619
|
def list_flags
|
|
554
|
-
|
|
555
|
-
|
|
620
|
+
response = ErrorMapping.call { @api.list_flags }
|
|
621
|
+
(response.data || []).map { |r| Smplkit::Flags::Helpers.flag_dict_from_json(ResourceShim.from_model(r)) }
|
|
556
622
|
end
|
|
557
623
|
|
|
558
624
|
private
|
|
559
625
|
|
|
626
|
+
def flag_body(flag)
|
|
627
|
+
SmplkitGeneratedClient::Flags::FlagResponse.new(
|
|
628
|
+
data: SmplkitGeneratedClient::Flags::FlagResource.new(
|
|
629
|
+
type: "flag",
|
|
630
|
+
id: flag.id,
|
|
631
|
+
attributes: SmplkitGeneratedClient::Flags::Flag.new(
|
|
632
|
+
name: flag.name,
|
|
633
|
+
type: flag.type,
|
|
634
|
+
default: flag.default,
|
|
635
|
+
description: flag.description,
|
|
636
|
+
values: flag_values_to_wire(flag.values),
|
|
637
|
+
environments: flag_envs_to_wire(flag.environments)
|
|
638
|
+
)
|
|
639
|
+
)
|
|
640
|
+
)
|
|
641
|
+
end
|
|
642
|
+
|
|
643
|
+
def flag_values_to_wire(values)
|
|
644
|
+
return nil if values.nil?
|
|
645
|
+
|
|
646
|
+
values.map do |v|
|
|
647
|
+
SmplkitGeneratedClient::Flags::FlagValue.new(name: v.name, value: v.value)
|
|
648
|
+
end
|
|
649
|
+
end
|
|
650
|
+
|
|
651
|
+
def flag_envs_to_wire(environments)
|
|
652
|
+
return nil if environments.empty?
|
|
653
|
+
|
|
654
|
+
environments.each_with_object({}) do |(env_key, env_obj), out|
|
|
655
|
+
rules = env_obj.rules.map do |r|
|
|
656
|
+
SmplkitGeneratedClient::Flags::FlagRule.new(
|
|
657
|
+
logic: r.logic, value: r.value, description: r.description
|
|
658
|
+
)
|
|
659
|
+
end
|
|
660
|
+
out[env_key] = SmplkitGeneratedClient::Flags::FlagEnvironment.new(
|
|
661
|
+
enabled: env_obj.enabled, default: env_obj.default, rules: rules
|
|
662
|
+
)
|
|
663
|
+
end
|
|
664
|
+
end
|
|
665
|
+
|
|
560
666
|
def flag_from_resource(resource)
|
|
561
667
|
d = Smplkit::Flags::Helpers.flag_dict_from_json(resource)
|
|
562
668
|
klass =
|
|
@@ -577,10 +683,8 @@ module Smplkit
|
|
|
577
683
|
end
|
|
578
684
|
|
|
579
685
|
class LoggersNamespace
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
def initialize(http)
|
|
583
|
-
@http = http
|
|
686
|
+
def initialize(api_client)
|
|
687
|
+
@api = SmplkitGeneratedClient::Logging::LoggersApi.new(api_client)
|
|
584
688
|
@buffer = Management::LoggerRegistrationBuffer.new
|
|
585
689
|
end
|
|
586
690
|
|
|
@@ -594,54 +698,86 @@ module Smplkit
|
|
|
594
698
|
batch = @buffer.drain
|
|
595
699
|
return if batch.empty?
|
|
596
700
|
|
|
597
|
-
|
|
598
|
-
|
|
701
|
+
items = batch.map do |entry|
|
|
702
|
+
SmplkitGeneratedClient::Logging::LoggerBulkItem.new(
|
|
703
|
+
id: entry["id"],
|
|
704
|
+
resolved_level: entry["resolved_level"],
|
|
705
|
+
level: entry["level"],
|
|
706
|
+
service: entry["service"],
|
|
707
|
+
environment: entry["environment"]
|
|
708
|
+
)
|
|
709
|
+
end
|
|
710
|
+
body = SmplkitGeneratedClient::Logging::LoggerBulkRequest.new(loggers: items)
|
|
711
|
+
ErrorMapping.call { @api.bulk_register_loggers(body) }
|
|
599
712
|
rescue StandardError => e
|
|
600
713
|
Smplkit.debug("registration", "logger flush failed: #{e.class}: #{e.message}")
|
|
601
714
|
end
|
|
602
715
|
|
|
603
716
|
def list
|
|
604
|
-
|
|
605
|
-
|
|
717
|
+
response = ErrorMapping.call { @api.list_loggers }
|
|
718
|
+
(response.data || []).map do |r|
|
|
719
|
+
Smplkit::Logging::Helpers.logger_resource_to_model(self, ResourceShim.from_model(r))
|
|
720
|
+
end
|
|
606
721
|
end
|
|
607
722
|
|
|
608
723
|
def get(id)
|
|
609
724
|
normalized = Smplkit::Logging::Normalize.normalize_logger_name(id)
|
|
610
|
-
|
|
611
|
-
Smplkit::Logging::Helpers.logger_resource_to_model(self,
|
|
725
|
+
response = ErrorMapping.call { @api.get_logger(normalized) }
|
|
726
|
+
Smplkit::Logging::Helpers.logger_resource_to_model(self, ResourceShim.from_model(response.data))
|
|
612
727
|
end
|
|
613
728
|
|
|
614
729
|
def delete(id)
|
|
615
730
|
normalized = Smplkit::Logging::Normalize.normalize_logger_name(id)
|
|
616
|
-
|
|
731
|
+
ErrorMapping.call { @api.delete_logger(normalized) }
|
|
732
|
+
true
|
|
617
733
|
end
|
|
618
734
|
|
|
619
735
|
def _update_logger(logger)
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
736
|
+
response = ErrorMapping.call { @api.update_logger(logger.id || logger.name, logger_body(logger)) }
|
|
737
|
+
Smplkit::Logging::Helpers.logger_resource_to_model(self, ResourceShim.from_model(response.data))
|
|
738
|
+
end
|
|
739
|
+
|
|
740
|
+
private
|
|
741
|
+
|
|
742
|
+
def logger_body(logger)
|
|
743
|
+
# Logger server schema: name, level, group, managed.
|
|
744
|
+
# +resolved_level+ is read-only, +service+/+environment+ are
|
|
745
|
+
# observed via bulk register, +description+ is wrapper-local.
|
|
746
|
+
SmplkitGeneratedClient::Logging::LoggerResponse.new(
|
|
747
|
+
data: SmplkitGeneratedClient::Logging::LoggerResource.new(
|
|
748
|
+
type: "logger",
|
|
749
|
+
id: logger.id,
|
|
750
|
+
attributes: SmplkitGeneratedClient::Logging::Logger.new(
|
|
751
|
+
name: logger.name,
|
|
752
|
+
level: logger.level&.to_s,
|
|
753
|
+
group: logger.log_group_id,
|
|
754
|
+
managed: logger.managed
|
|
755
|
+
)
|
|
756
|
+
)
|
|
757
|
+
)
|
|
623
758
|
end
|
|
624
759
|
end
|
|
625
760
|
|
|
626
761
|
class LogGroupsNamespace
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
def initialize(http)
|
|
630
|
-
@http = http
|
|
762
|
+
def initialize(api_client)
|
|
763
|
+
@api = SmplkitGeneratedClient::Logging::LogGroupsApi.new(api_client)
|
|
631
764
|
end
|
|
632
765
|
|
|
633
766
|
def list
|
|
634
|
-
|
|
635
|
-
|
|
767
|
+
response = ErrorMapping.call { @api.list_log_groups }
|
|
768
|
+
(response.data || []).map do |r|
|
|
769
|
+
Smplkit::Logging::Helpers.log_group_resource_to_model(self, ResourceShim.from_model(r))
|
|
770
|
+
end
|
|
636
771
|
end
|
|
637
772
|
|
|
638
773
|
def get(key)
|
|
639
|
-
|
|
640
|
-
Smplkit::Logging::Helpers.log_group_resource_to_model(self,
|
|
774
|
+
response = ErrorMapping.call { @api.get_log_group(key) }
|
|
775
|
+
Smplkit::Logging::Helpers.log_group_resource_to_model(self, ResourceShim.from_model(response.data))
|
|
641
776
|
end
|
|
642
777
|
|
|
643
778
|
def delete(key)
|
|
644
|
-
|
|
779
|
+
ErrorMapping.call { @api.delete_log_group(key) }
|
|
780
|
+
true
|
|
645
781
|
end
|
|
646
782
|
|
|
647
783
|
def new_log_group(key, name: nil, level: nil, description: nil, parent: nil)
|
|
@@ -653,15 +789,30 @@ module Smplkit
|
|
|
653
789
|
end
|
|
654
790
|
|
|
655
791
|
def _create_log_group(group)
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
Smplkit::Logging::Helpers.log_group_resource_to_model(self, resp["data"])
|
|
792
|
+
response = ErrorMapping.call { @api.create_log_group(log_group_body(group)) }
|
|
793
|
+
Smplkit::Logging::Helpers.log_group_resource_to_model(self, ResourceShim.from_model(response.data))
|
|
659
794
|
end
|
|
660
795
|
|
|
661
796
|
def _update_log_group(group)
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
797
|
+
response = ErrorMapping.call { @api.update_log_group(group.key, log_group_body(group)) }
|
|
798
|
+
Smplkit::Logging::Helpers.log_group_resource_to_model(self, ResourceShim.from_model(response.data))
|
|
799
|
+
end
|
|
800
|
+
|
|
801
|
+
private
|
|
802
|
+
|
|
803
|
+
def log_group_body(group)
|
|
804
|
+
# LogGroup server schema: name, level, parent_id (no description).
|
|
805
|
+
SmplkitGeneratedClient::Logging::LogGroupResponse.new(
|
|
806
|
+
data: SmplkitGeneratedClient::Logging::LogGroupResource.new(
|
|
807
|
+
type: "log_group",
|
|
808
|
+
id: group.key,
|
|
809
|
+
attributes: SmplkitGeneratedClient::Logging::LogGroup.new(
|
|
810
|
+
name: group.name,
|
|
811
|
+
level: group.level&.to_s,
|
|
812
|
+
parent_id: group.parent_id
|
|
813
|
+
)
|
|
814
|
+
)
|
|
815
|
+
)
|
|
665
816
|
end
|
|
666
817
|
end
|
|
667
818
|
end
|