enviroblyd 0.3 → 0.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2b81310d8a36d3cb1cf6f6c52d106cc956efda2aa46a88e82f62faa4d350abf6
4
- data.tar.gz: c7bb64bff1ba36ba7bdbc3c9ebdc759a452242787d5b77876f8b5bc5aa5fb853
3
+ metadata.gz: 5bfe5d8525ca24df27fe3c85f2715a6dc74d9bd931aff02c1a1c96c79b4b8c98
4
+ data.tar.gz: cb67d4b4c55e328c63e85ad6a976b24fd29e7517ec5de154ae613fe2712a7ec8
5
5
  SHA512:
6
- metadata.gz: c529bc70a326723e8ca8ab18eda6207e06a9b272ba75e06cdb01746c451009d991fedc77647d17dfa787016a5a9bf8cde1d77f45080ac4a7b707bc477a7cf3e0
7
- data.tar.gz: aa5e7808630a375aa4dffeda5ca67c4c1866f8cf3577db35be27d22b50f3d7854b78499c9f35256c6079916ff49fc0c81a9a565d60b160d3bb8d9c586b6b9171
6
+ metadata.gz: 30ce5bcada6cd8abdfc0ab7f8cf58e15b3670f55f659d2b40bec9ef75e502ca8e65fbd6ab7e13fc42ec5d7cae362522f1e82645a746b24f7fb8ba2218677029e
7
+ data.tar.gz: 6125a642bc7ecad4db9ea7c50f2039584a7f7ddccd4a1f41663bff22318149c78333bd936cf5d023e5e409b69beebd71ea854919b89cc479ca93c12587943c15
data/bin/enviroblyctl ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "enviroblyd"
5
+
6
+ Enviroblyd::Cli::Main.start(ARGV)
data/bin/enviroblyd CHANGED
@@ -3,4 +3,4 @@
3
3
 
4
4
  require "enviroblyd"
5
5
 
6
- Enviroblyd::Cli::Main.start(ARGV)
6
+ Enviroblyd::Daemon.start
@@ -1,95 +1,8 @@
1
1
  # frozen_string_literal: true
2
- require "net/http"
3
- require "uri"
4
- require "open3"
5
2
 
6
3
  class Enviroblyd::Cli::Main < Enviroblyd::Base
7
4
  desc "version", "Show version"
8
5
  def version
9
6
  puts Enviroblyd::VERSION
10
7
  end
11
-
12
- TOKEN_TTL_SECONDS = 30
13
- IMDS_HOST = ENV.fetch("ENVIROBLYD_IMDS_HOST", "169.254.169.254")
14
- API_HOST = ENV.fetch("ENVIROBLYD_API_HOST", "envirobly.com")
15
- desc "boot", "Get IMDSv2 metadata"
16
- def boot
17
- @token = http("http://#{IMDS_HOST}/latest/api/token",
18
- type: Net::HTTP::Put, headers: { "X-aws-ec2-metadata-token-ttl-seconds" => TOKEN_TTL_SECONDS.to_s }).
19
- body.chomp("")
20
- puts "token: #{@token} ."
21
- instance_id = http("http://#{IMDS_HOST}/latest/meta-data/instance-id",
22
- headers: { "X-aws-ec2-metadata-token" => @token }).
23
- body.chomp("")
24
- puts "instance_id: #{instance_id} ."
25
-
26
- # process_user_data
27
- # unless @exit_code.nil?
28
- # puts @stdout
29
- # $stderr.puts @stderr
30
- # unless @exit_code == 0
31
- # $stderr.puts "User data script exited with code: #{@exit_code}. Aborting."
32
- # exit 1
33
- # end
34
- # end
35
-
36
- response = http("https://#{API_HOST}/api/v1/boots/#{instance_id}", retry_interval: 3, retries: 5, backoff: :exponential)
37
- puts "/api/v1/boots response code: #{response.code}"
38
- end
39
-
40
- private
41
- def http(url, type: Net::HTTP::Get, headers: {}, retry_interval: 2, retries: 30, backoff: false, success_codes: 200..299, tries: 1)
42
- uri = URI(url)
43
- http = Net::HTTP.new uri.host, uri.port
44
- http.use_ssl = true if uri.scheme == "https"
45
- http.open_timeout = 5
46
- http.read_timeout = 5
47
-
48
- request = type.new(uri, headers)
49
- # request.content_type = CONTENT_TYPE
50
-
51
- yield request if block_given?
52
-
53
- response =
54
- begin
55
- http.request(request)
56
- rescue
57
- nil
58
- end
59
-
60
- if response && success_codes.include?(response.code.to_i)
61
- response
62
- elsif retries <= tries
63
- $stderr.puts "Retried #{tries} times. Aborting."
64
- exit 1
65
- else
66
- sleep_time = (backoff == :exponential) ? (retry_interval * tries) : retry_interval
67
- $stderr.puts "Retry #{uri} in #{sleep_time}s"
68
- sleep sleep_time
69
- http(url, type:, retry_interval:, retries:, backoff:, success_codes:, tries: (tries + 1))
70
- end
71
- end
72
-
73
- def process_user_data
74
- response = http("http://#{IMDS_HOST}/latest/user-data",
75
- headers: { "X-aws-ec2-metadata-token" => @token })
76
-
77
- if response.body.start_with?("#!/bin/bash")
78
- run response.body
79
- else
80
- $stderr.puts "User data does not contain runable script."
81
- end
82
- end
83
-
84
- RUN_TIMEOUT = "5m"
85
- def run(script)
86
- @stdout = @stderr = @exit_code = nil
87
- Open3.popen3("timeout #{RUN_TIMEOUT} /bin/bash") do |stdin, stdout, stderr, thread|
88
- stdin.puts script
89
- stdin.close
90
- @stdout = stdout.read
91
- @stderr = stderr.read
92
- @exit_code = thread.value.exitstatus
93
- end
94
- end
95
8
  end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "open3"
4
+
5
+ class Enviroblyd::Command
6
+ DEFAULT_TIMEOUT_SECONDS = 5 * 60
7
+ DEFAULT_RUNTIME = "/bin/bash"
8
+
9
+ def initialize(params)
10
+ @web = Enviroblyd::Web.new
11
+ @url = params.fetch "url"
12
+ @script = params.fetch "script"
13
+ @runtime = params.fetch "runtime", DEFAULT_RUNTIME
14
+ @timeout = params.fetch "timeout", DEFAULT_TIMEOUT_SECONDS
15
+ @stdout = @stderr = @exit_code = nil
16
+ end
17
+
18
+ def run
19
+ puts "Command #{@url} starting"
20
+
21
+ Open3.popen3("timeout #{@timeout} #{@runtime}") do |stdin, stdout, stderr, thread|
22
+ stdin.puts @script
23
+ stdin.close
24
+ @stdout = stdout.read
25
+ @stderr = stderr.read
26
+ @exit_code = thread.value.exitstatus
27
+ end
28
+
29
+ puts "Command #{@url} exited with #{@exit_code}"
30
+
31
+ @web.http(@url, type: Net::HTTP::Put, params: to_complete_params)
32
+ end
33
+
34
+ private
35
+ def to_complete_params
36
+ {
37
+ command: {
38
+ stdout: @stdout,
39
+ stderr: @stderr,
40
+ exit_code: @exit_code
41
+ }
42
+ }
43
+ end
44
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "socket"
4
+ require "json"
5
+
6
+ class Enviroblyd::Daemon
7
+ MAX_MESSAGE_SIZE = 6000 # bytes
8
+ LISTEN_PORT = ENV.fetch("ENVIROBLYD_PORT", 63106).to_i
9
+
10
+ def self.start
11
+ web = Enviroblyd::Web.new
12
+ web.register
13
+
14
+ daemon = new
15
+ daemon.listen
16
+ end
17
+
18
+ def listen
19
+ server = TCPServer.new LISTEN_PORT
20
+ puts "Listening on port #{LISTEN_PORT}"
21
+
22
+ loop do
23
+ Thread.start(server.accept) do |client|
24
+ message = client.recv(MAX_MESSAGE_SIZE)
25
+
26
+ params =
27
+ begin
28
+ JSON.parse message
29
+ rescue
30
+ nil
31
+ end
32
+
33
+ if params.nil?
34
+ client.puts "Error parsing JSON"
35
+ else
36
+ puts "Received valid JSON:"
37
+ puts params
38
+ client.puts "OK"
39
+ end
40
+
41
+ # TODO: Handle Broken pipe (Errno::EPIPE) (client closing connection before we write back)
42
+ client.close
43
+
44
+ Thread.new do
45
+ Enviroblyd::Command.new(params).run
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Enviroblyd
4
- VERSION = "0.3"
4
+ VERSION = "0.4"
5
5
  end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "net/http"
4
+ require "uri"
5
+ require "open3"
6
+ require "fileutils"
7
+ require "pathname"
8
+ require "json"
9
+
10
+ class Enviroblyd::Web
11
+ USER_AGENT = "enviroblyd #{Enviroblyd::VERSION}"
12
+ CONTENT_TYPE = "application/json"
13
+ # TOKEN_TTL_SECONDS = 30
14
+ # IMDS_HOST = ENV.fetch("ENVIROBLYD_IMDS_HOST", "169.254.169.254")
15
+ API_HOST = ENV.fetch("ENVIROBLYD_API_HOST", "envirobly.com")
16
+ WORKING_DIR = Pathname.new ENV.fetch("ENVIROBLYD_WORKING_DIR", "/var/envirobly/daemon")
17
+ INITIALIZED_FILE = WORKING_DIR.join "initialized"
18
+
19
+ def register
20
+ if File.exist?(INITIALIZED_FILE)
21
+ puts "Skipping initialization because #{INITIALIZED_FILE} exists."
22
+ else
23
+ init_url = ENV.fetch "ENVIROBLYD_INIT_URL"
24
+ puts "Init URL: #{init_url}"
25
+ response = http(init_url, type: Net::HTTP::Put, retry_interval: 3, retries: 10, backoff: :exponential)
26
+ puts "Init response code: #{response.code}"
27
+
28
+ if response.code.to_i == 200
29
+ FileUtils.mkdir_p WORKING_DIR
30
+ File.write INITIALIZED_FILE, init_url
31
+ end
32
+ end
33
+ end
34
+
35
+ def http(url, type: Net::HTTP::Get, headers: {}, retry_interval: 2, retries: 30, backoff: false, tries: 1, params: nil)
36
+ if retries <= tries
37
+ $stderr.puts "Retried #{tries} times. Aborting."
38
+ exit 1
39
+ end
40
+
41
+ uri = URI(url)
42
+ http = Net::HTTP.new uri.host, uri.port
43
+ http.use_ssl = true if uri.scheme == "https"
44
+ http.open_timeout = 5
45
+ http.read_timeout = 5
46
+
47
+ request = type.new(uri, default_headers.merge(headers))
48
+ request.content_type = CONTENT_TYPE
49
+
50
+ unless params.nil?
51
+ request.body = JSON.dump params
52
+ end
53
+
54
+ response =
55
+ begin
56
+ http.request(request)
57
+ rescue
58
+ :retry
59
+ end
60
+
61
+ # https://developers.cloudflare.com/support/troubleshooting/cloudflare-errors/troubleshooting-cloudflare-1xxx-errors/
62
+ if response == :retry || (500..599).include?(response.code.to_i)
63
+ sleep_time = (backoff == :exponential) ? (retry_interval * tries) : retry_interval
64
+ $stderr.puts "Retry #{uri} in #{sleep_time}s"
65
+ sleep sleep_time
66
+ http(url, type:, retry_interval:, retries:, backoff:, tries: (tries + 1))
67
+ else
68
+ response
69
+ end
70
+ end
71
+
72
+ private
73
+ def default_headers
74
+ { "User-Agent" => USER_AGENT }
75
+ end
76
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: enviroblyd
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.3'
4
+ version: '0.4'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Starsi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-09-03 00:00:00.000000000 Z
11
+ date: 2024-09-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -55,16 +55,21 @@ dependencies:
55
55
  description:
56
56
  email: klevo@klevo.sk
57
57
  executables:
58
+ - enviroblyctl
58
59
  - enviroblyd
59
60
  extensions: []
60
61
  extra_rdoc_files: []
61
62
  files:
62
63
  - LICENSE
64
+ - bin/enviroblyctl
63
65
  - bin/enviroblyd
64
66
  - lib/enviroblyd.rb
65
67
  - lib/enviroblyd/base.rb
66
68
  - lib/enviroblyd/cli/main.rb
69
+ - lib/enviroblyd/command.rb
70
+ - lib/enviroblyd/daemon.rb
67
71
  - lib/enviroblyd/version.rb
72
+ - lib/enviroblyd/web.rb
68
73
  homepage: https://github.com/envirobly/enviroblyd
69
74
  licenses:
70
75
  - MIT
@@ -84,7 +89,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
84
89
  - !ruby/object:Gem::Version
85
90
  version: '0'
86
91
  requirements: []
87
- rubygems_version: 3.5.14
92
+ rubygems_version: 3.5.18
88
93
  signing_key:
89
94
  specification_version: 4
90
95
  summary: Envirobly instance daemon