gretl 1.0.4 → 1.0.5
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/gretl.rb +180 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 96aab4c6f7f37f115ae1b8db4f531374f4aa37e4cd7da305b87f24c97a8e6bb0
|
|
4
|
+
data.tar.gz: 5607a48037a46aeb238cc01c982a6c9819fae444b03bd0d66ee33a8e77e12230
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5f338845601daefa91c8bd5a2a31facaed2afbc7b0b648896d1913dab2c90c175b55d3d09da0d0a1705e28f535c54d3ac24e7fdced128196e3f994ca216ee0f7
|
|
7
|
+
data.tar.gz: 632f13e0748e22208bb452479d6fe7a877eb16f374570589286bc7b3e1aabb96b684962319be967c3579ca1c2a579a0e16ac44f2db8839d95850071d7b573dd4
|
data/lib/gretl.rb
CHANGED
|
@@ -155,6 +155,185 @@ module Gretl
|
|
|
155
155
|
end
|
|
156
156
|
end
|
|
157
157
|
|
|
158
|
-
|
|
158
|
+
CLOUD_API = "https://api.gretl.dev"
|
|
159
|
+
|
|
160
|
+
class K8sClient
|
|
161
|
+
def initialize(token)
|
|
162
|
+
@token = token
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def clusters
|
|
166
|
+
_cloud_get("/k8s/clusters")
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def workloads(cluster_id: nil)
|
|
170
|
+
path = cluster_id ? "/k8s/clusters/#{cluster_id}/workloads" : "/k8s/workloads"
|
|
171
|
+
_cloud_get(path)
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def sync(cluster_id)
|
|
175
|
+
_cloud_post("/k8s/clusters/#{cluster_id}/sync")
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def sleep(workload_id)
|
|
179
|
+
_cloud_post("/k8s/workloads/#{workload_id}/sleep")
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def wake(workload_id)
|
|
183
|
+
_cloud_post("/k8s/workloads/#{workload_id}/wake")
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def tether(workload_id, container_port:, label: nil)
|
|
187
|
+
body = { container_port: container_port }
|
|
188
|
+
body[:label] = label if label
|
|
189
|
+
_cloud_post("/k8s/workloads/#{workload_id}/tether", body)
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def detach(tether_id)
|
|
193
|
+
_cloud_post("/k8s/tethers/#{tether_id}/deactivate")
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def tethers
|
|
197
|
+
_cloud_get("/k8s/tethers")
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def auto_sleep(workload_id)
|
|
201
|
+
_cloud_get("/k8s/workloads/#{workload_id}/auto-sleep")
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def set_auto_sleep(workload_id, enabled:, idle_timeout_minutes:)
|
|
205
|
+
_cloud_put("/k8s/workloads/#{workload_id}/auto-sleep",
|
|
206
|
+
{ auto_sleep_enabled: enabled, idle_timeout_minutes: idle_timeout_minutes })
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
private
|
|
210
|
+
|
|
211
|
+
def _cloud_get(path)
|
|
212
|
+
uri = URI("#{CLOUD_API}#{path}")
|
|
213
|
+
req = Net::HTTP::Get.new(uri, "Authorization" => "Bearer #{@token}")
|
|
214
|
+
_cloud_call(uri, req)
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def _cloud_post(path, body = nil)
|
|
218
|
+
uri = URI("#{CLOUD_API}#{path}")
|
|
219
|
+
req = Net::HTTP::Post.new(uri, "Authorization" => "Bearer #{@token}", "Content-Type" => "application/json")
|
|
220
|
+
req.body = body.to_json if body
|
|
221
|
+
_cloud_call(uri, req)
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
def _cloud_put(path, body)
|
|
225
|
+
uri = URI("#{CLOUD_API}#{path}")
|
|
226
|
+
req = Net::HTTP::Put.new(uri, "Authorization" => "Bearer #{@token}", "Content-Type" => "application/json")
|
|
227
|
+
req.body = body.to_json
|
|
228
|
+
_cloud_call(uri, req)
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def _cloud_call(uri, req)
|
|
232
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
233
|
+
http.use_ssl = uri.scheme == "https"
|
|
234
|
+
http.open_timeout = 10
|
|
235
|
+
http.read_timeout = 10
|
|
236
|
+
res = http.request(req)
|
|
237
|
+
raise "Gretl API error #{res.code}: #{res.body}" unless res.is_a?(Net::HTTPSuccess)
|
|
238
|
+
JSON.parse(res.body, symbolize_names: true)
|
|
239
|
+
rescue Errno::ECONNREFUSED => e
|
|
240
|
+
raise "Cannot reach Gretl API: #{e}"
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
class Client
|
|
245
|
+
def initialize(token: nil)
|
|
246
|
+
_token = token || ENV.fetch("GR_TOKEN", "")
|
|
247
|
+
@k8s = K8sClient.new(_token)
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
attr_reader :k8s
|
|
251
|
+
|
|
252
|
+
def ports = Gretl._fetch_ports
|
|
253
|
+
def port(query) = Gretl._resolve(query)
|
|
254
|
+
def active = Gretl._fetch_ports.select(&:active)
|
|
255
|
+
def inactive = Gretl._fetch_ports.reject(&:active)
|
|
256
|
+
|
|
257
|
+
def start(query)
|
|
258
|
+
matches = Gretl._resolve(query)
|
|
259
|
+
raise ArgumentError, "No port found matching #{query.inspect}" if matches.empty?
|
|
260
|
+
matches.each do |p|
|
|
261
|
+
Gretl._request(:post, "/ports/#{p.port}/start") if !p.active && p.has_command
|
|
262
|
+
end
|
|
263
|
+
matches
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
def stop(query)
|
|
267
|
+
matches = Gretl._resolve(query)
|
|
268
|
+
raise ArgumentError, "No port found matching #{query.inspect}" if matches.empty?
|
|
269
|
+
matches.each do |p|
|
|
270
|
+
Gretl._request(:post, "/ports/#{p.port}/stop") if p.active
|
|
271
|
+
end
|
|
272
|
+
matches
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
def start_group(group)
|
|
276
|
+
matches = Gretl._fetch_ports.select { |p| p.group&.downcase == group.downcase }
|
|
277
|
+
raise ArgumentError, "No ports found in group #{group.inspect}" if matches.empty?
|
|
278
|
+
matches.each { |p| Gretl._request(:post, "/ports/#{p.port}/start") if !p.active && p.has_command }
|
|
279
|
+
matches
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
def stop_group(group)
|
|
283
|
+
matches = Gretl._fetch_ports.select { |p| p.group&.downcase == group.downcase }
|
|
284
|
+
raise ArgumentError, "No ports found in group #{group.inspect}" if matches.empty?
|
|
285
|
+
matches.each { |p| Gretl._request(:post, "/ports/#{p.port}/stop") if p.active }
|
|
286
|
+
matches
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
def status_group(group)
|
|
290
|
+
matches = Gretl._fetch_ports.select { |p| p.group&.downcase == group.downcase }
|
|
291
|
+
raise ArgumentError, "No ports found in group #{group.inspect}" if matches.empty?
|
|
292
|
+
matches
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
def remove(query)
|
|
296
|
+
matches = Gretl._resolve(query)
|
|
297
|
+
raise ArgumentError, "No port found matching #{query.inspect}" if matches.empty?
|
|
298
|
+
matches.each { |p| Gretl._request(:delete, "/ports/#{p.port}") }
|
|
299
|
+
matches
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
def wait_for_active(query, timeout: 30, interval: 0.5)
|
|
303
|
+
deadline = Time.now + timeout
|
|
304
|
+
while Time.now < deadline
|
|
305
|
+
Gretl._resolve(query).each { |p| return p if p.active }
|
|
306
|
+
sleep interval
|
|
307
|
+
end
|
|
308
|
+
raise "Port matching #{query.inspect} did not become active within #{timeout}s"
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
def add(port, name: nil, cmd: nil, group: nil, cwd: nil)
|
|
312
|
+
Gretl._ensure_daemon
|
|
313
|
+
uri = URI("#{Gretl::BASE}/ports")
|
|
314
|
+
body = { port: port }
|
|
315
|
+
body[:name] = name if name
|
|
316
|
+
body[:cmd] = cmd if cmd
|
|
317
|
+
body[:group] = group if group
|
|
318
|
+
body[:cwd] = cwd if cwd
|
|
319
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
320
|
+
req = Net::HTTP::Post.new(uri, "Content-Type" => "application/json")
|
|
321
|
+
req.body = body.to_json
|
|
322
|
+
res = http.request(req)
|
|
323
|
+
data = JSON.parse(res.body, symbolize_names: true)
|
|
324
|
+
Gretl::PortInfo.new(**data.slice(*Gretl::PortInfo.members))
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
def wait_for_inactive(query, timeout: 30, interval: 0.5)
|
|
328
|
+
deadline = Time.now + timeout
|
|
329
|
+
while Time.now < deadline
|
|
330
|
+
Gretl._resolve(query).each { |p| return p if p.stopped? }
|
|
331
|
+
sleep interval
|
|
332
|
+
end
|
|
333
|
+
raise "Port matching #{query.inspect} did not become inactive within #{timeout}s"
|
|
334
|
+
end
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
# Default client — token read from GR_TOKEN env var
|
|
159
338
|
PA = Client.new
|
|
160
339
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: gretl
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Gretl
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-05-
|
|
11
|
+
date: 2026-05-18 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description:
|
|
14
14
|
email:
|