harbr 0.0.27 → 0.0.29
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/exe/harbr +2 -2
- data/lib/harbr/container.rb +11 -0
- data/lib/harbr/job.rb +124 -0
- data/lib/harbr/pool.rb +39 -0
- data/lib/harbr/port.rb +25 -0
- data/lib/harbr/version.rb +1 -1
- data/lib/harbr.rb +8 -204
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 05f9f6f2cfa6a6e47b98bf065594b68346c8348b8ec770265cd0f4e4c0f143c4
|
4
|
+
data.tar.gz: 9c0196f50e7c60f93dc0666511dc80243949408a5f8247f09daf162f9941edd2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b0f056c312eee44919da4409680f25c28933892d09a44f83c563c7566480a54917d43f330246196112f9c50f884d823a7bcf80281c3e1b87c00b32e6a1604b5a
|
7
|
+
data.tar.gz: 7f50616e3a8134dbacef6ecbdbc8d5376961bf088a18fc00cd7497d7f6ffe6ed9bfcb294e7b26966e71cf03b237170fc293f606fe31e959c40204b891870c7f0
|
data/exe/harbr
CHANGED
@@ -5,7 +5,7 @@ require "harbr"
|
|
5
5
|
require "sucker_punch"
|
6
6
|
require "terminal-table"
|
7
7
|
require "yaml"
|
8
|
-
require
|
8
|
+
require "toml-rb"
|
9
9
|
require "fileutils"
|
10
10
|
require "ostruct"
|
11
11
|
|
@@ -35,7 +35,7 @@ class HarbrCLI < Thor
|
|
35
35
|
headers = ["Name", "Host Header", "IP", "Port"]
|
36
36
|
|
37
37
|
rows = containers.map do |container|
|
38
|
-
[container.name, container.host_header, container.ip.nil? ? "127.0.0.1" : container.ip
|
38
|
+
[container.name, container.host_header, container.ip.nil? ? "127.0.0.1" : container.ip, container.port]
|
39
39
|
end
|
40
40
|
|
41
41
|
table = ::Terminal::Table.new(headings: headers, rows: rows)
|
data/lib/harbr/job.rb
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
module Harbr
|
2
|
+
module Harbr
|
3
|
+
class Container
|
4
|
+
class Job
|
5
|
+
include SuckerPunch::Job
|
6
|
+
def create_traefik_config(containers)
|
7
|
+
config = {
|
8
|
+
"http" => {
|
9
|
+
"routers" => {
|
10
|
+
"traefik-dashboard" => {
|
11
|
+
"rule" => "Host(`traefik.harbr.zero2one.ee`)",
|
12
|
+
"service" => "api@internal"
|
13
|
+
}
|
14
|
+
},
|
15
|
+
"services" => {}
|
16
|
+
}
|
17
|
+
}
|
18
|
+
|
19
|
+
containers.each do |container|
|
20
|
+
container.ip = "127.0.0.1"
|
21
|
+
|
22
|
+
config["http"]["routers"]["#{container.name}-router"] = {
|
23
|
+
"rule" => "Host(`#{container.host_header}`)",
|
24
|
+
"service" => "#{container.name}-service"
|
25
|
+
}
|
26
|
+
config["http"]["services"]["#{container.name}-service"] = {
|
27
|
+
"loadBalancer" => {
|
28
|
+
"servers" => [{"url" => "http://#{container.ip}:#{container.port}"}]
|
29
|
+
}
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
File.write("/etc/traefik/harbr.toml", TomlRB.dump(config))
|
34
|
+
puts "Traefik configuration written to /etc/traefik/harbr.toml"
|
35
|
+
end
|
36
|
+
|
37
|
+
def create_run_script(container_name, port)
|
38
|
+
service_dir = "/etc/sv/harbr/#{container_name}"
|
39
|
+
if File.directory?(service_dir)
|
40
|
+
puts "Directory already exists: #{service_dir}"
|
41
|
+
return
|
42
|
+
end
|
43
|
+
|
44
|
+
script_template = <<~SCRIPT
|
45
|
+
#!/bin/sh
|
46
|
+
exec 2>&1
|
47
|
+
cd /var/harbr/#{container_name}/current
|
48
|
+
exec bundle install && bundle exec puma -p #{port}
|
49
|
+
SCRIPT
|
50
|
+
|
51
|
+
service_dir = "/etc/sv/harbr/#{container_name}"
|
52
|
+
FileUtils.mkdir_p(service_dir)
|
53
|
+
|
54
|
+
File.write("#{service_dir}/run", script_template)
|
55
|
+
FileUtils.chmod("+x", "#{service_dir}/run")
|
56
|
+
puts "Run script created and made executable for container: #{container_name}"
|
57
|
+
end
|
58
|
+
|
59
|
+
def create_log_script(container_name)
|
60
|
+
log_dir = "/var/log/harbr/#{container_name}"
|
61
|
+
|
62
|
+
if File.directory?(log_dir)
|
63
|
+
puts "Directory already exists: #{log_dir}"
|
64
|
+
return
|
65
|
+
end
|
66
|
+
|
67
|
+
FileUtils.mkdir_p(log_dir)
|
68
|
+
|
69
|
+
script_template = <<~SCRIPT
|
70
|
+
#!/bin/sh
|
71
|
+
exec svlogd -tt #{log_dir}/
|
72
|
+
SCRIPT
|
73
|
+
|
74
|
+
dir_path = "/etc/sv/harbr/#{container_name}/log"
|
75
|
+
FileUtils.mkdir_p(dir_path)
|
76
|
+
|
77
|
+
File.write("#{dir_path}/run", script_template)
|
78
|
+
FileUtils.chmod("+x", "#{dir_path}/run")
|
79
|
+
puts "Log script created and made executable for container: #{container_name}"
|
80
|
+
end
|
81
|
+
|
82
|
+
def create_a_service(container_name, port)
|
83
|
+
create_run_script(container_name, port)
|
84
|
+
create_log_script(container_name)
|
85
|
+
system("ln -s /etc/sv/harbr/#{container_name} /etc/service/#{container_name}") unless File.exist?("/etc/service/#{container_name}")
|
86
|
+
end
|
87
|
+
|
88
|
+
def run_container(manifest)
|
89
|
+
puts "Starting container: #{manifest.name}"
|
90
|
+
|
91
|
+
Dddr.configure do |config|
|
92
|
+
config.data_dir = Harbr::DEFAULT_DIRECTORY_DATA_DIR
|
93
|
+
end
|
94
|
+
|
95
|
+
pool = Harbr::Port::Pool.new
|
96
|
+
port = pool.get_port(manifest.host)
|
97
|
+
|
98
|
+
create_a_service(manifest.name, port.number)
|
99
|
+
|
100
|
+
sleep 5
|
101
|
+
system("sv restart #{manifest.name}")
|
102
|
+
sleep 5
|
103
|
+
system("sv status #{manifest.name}")
|
104
|
+
puts "Started container: #{manifest.name}"
|
105
|
+
|
106
|
+
container = Container.new
|
107
|
+
containers = Container::Repository.new
|
108
|
+
|
109
|
+
container.name = manifest.name
|
110
|
+
container.host_header = manifest.host
|
111
|
+
container.ip = manifest.ip.nil?
|
112
|
+
container.port = port.number
|
113
|
+
containers.add(container) unless containers.find_by_header(manifest.host)
|
114
|
+
|
115
|
+
create_traefik_config(containers.all)
|
116
|
+
end
|
117
|
+
|
118
|
+
def perform(manifest)
|
119
|
+
run_container(manifest)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
data/lib/harbr/pool.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
module Harbr
|
2
|
+
class Port
|
3
|
+
class Pool # rubocop:disable Style/Documentation
|
4
|
+
def initialize(port_range = 50000..51000)
|
5
|
+
@repository = Port::Repository.new
|
6
|
+
|
7
|
+
port_range.each do |number|
|
8
|
+
port = Port.new
|
9
|
+
port.number = number
|
10
|
+
|
11
|
+
unless @repository.has_port_number? number
|
12
|
+
@repository.add(port)
|
13
|
+
puts port.number.to_s + " added!"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def get_port(host_header)
|
19
|
+
port = @repository.assigned_a_port?(host_header)
|
20
|
+
return port unless port.nil?
|
21
|
+
|
22
|
+
port = ports.shuffle.sample
|
23
|
+
port.host_header = host_header
|
24
|
+
@repository.update(port)
|
25
|
+
port
|
26
|
+
end
|
27
|
+
|
28
|
+
def return_port(port)
|
29
|
+
port.host_header = nil
|
30
|
+
@repository.update(port)
|
31
|
+
port.host_header.nil?
|
32
|
+
end
|
33
|
+
|
34
|
+
def ports
|
35
|
+
@repository.all
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/harbr/port.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Harbr
|
4
|
+
class Port # rubocop:disable Style/Documentation
|
5
|
+
include Dddr::Entity
|
6
|
+
attr_accessor :host_header, :number
|
7
|
+
|
8
|
+
queries do
|
9
|
+
# Checks if a port with the specified number exists.
|
10
|
+
#
|
11
|
+
# Parameters:
|
12
|
+
# - number: The port number to check.
|
13
|
+
#
|
14
|
+
# Returns:
|
15
|
+
# - The port object if found, nil otherwise.
|
16
|
+
def has_port_number?(number)
|
17
|
+
all.find { |port| port.number == number.to_i }
|
18
|
+
end
|
19
|
+
|
20
|
+
def assigned_a_port?(host_header)
|
21
|
+
all.find { |port| port.host_header == host_header }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/harbr/version.rb
CHANGED
data/lib/harbr.rb
CHANGED
@@ -1,13 +1,14 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative "harbr/version"
|
4
|
-
require "dddr"
|
5
1
|
require "sucker_punch"
|
2
|
+
require "toml-rb"
|
6
3
|
|
7
|
-
|
4
|
+
require_relative "harbr/version"
|
5
|
+
require_relative "harbr/container"
|
6
|
+
require_relative "harbr/job"
|
7
|
+
require_relative "harbr/port"
|
8
|
+
require_relative "harbr/pool"
|
8
9
|
|
10
|
+
# Harbr module for managing containers, jobs, ports, and pools
|
9
11
|
module Harbr
|
10
|
-
|
11
12
|
DEFAULT_DIRECTORY = "/var/harbr"
|
12
13
|
DEFAULT_DIRECTORY_DATA_DIR = "#{DEFAULT_DIRECTORY}/.data"
|
13
14
|
|
@@ -15,202 +16,5 @@ module Harbr
|
|
15
16
|
config.data_dir = DEFAULT_DIRECTORY_DATA_DIR
|
16
17
|
end
|
17
18
|
|
18
|
-
|
19
|
-
|
20
19
|
class Error < StandardError; end
|
21
|
-
|
22
|
-
class Container
|
23
|
-
class Job
|
24
|
-
include SuckerPunch::Job
|
25
|
-
|
26
|
-
def perform(manifest)
|
27
|
-
run_container(manifest)
|
28
|
-
end
|
29
|
-
|
30
|
-
|
31
|
-
def create_traefik_config(containers)
|
32
|
-
config = {
|
33
|
-
"http" => {
|
34
|
-
"routers" => {
|
35
|
-
"traefik-dashboard" => {
|
36
|
-
"rule" => "Host(`traefik.harbr.zero2one.ee`)",
|
37
|
-
"service" => "api@internal"
|
38
|
-
}
|
39
|
-
},
|
40
|
-
"services" => {}
|
41
|
-
}
|
42
|
-
}
|
43
|
-
|
44
|
-
containers.each do |container|
|
45
|
-
|
46
|
-
container.ip = "127.0.0.1"
|
47
|
-
|
48
|
-
config["http"]["routers"]["#{container.name}-router"] = {
|
49
|
-
"rule" => "Host(`#{container.host_header}`)",
|
50
|
-
"service" => "#{container.name}-service"
|
51
|
-
}
|
52
|
-
config["http"]["services"]["#{container.name}-service"] = {
|
53
|
-
"loadBalancer" => {
|
54
|
-
"servers" => [{ "url" => "http://#{container.ip}:#{container.port}" }]
|
55
|
-
}
|
56
|
-
}
|
57
|
-
end
|
58
|
-
|
59
|
-
File.write('/etc/traefik/harbr.toml', TomlRB.dump(config))
|
60
|
-
puts "Traefik configuration written to /etc/traefik/harbr.toml"
|
61
|
-
end
|
62
|
-
|
63
|
-
def create_run_script(container_name, port)
|
64
|
-
service_dir = "/etc/sv/harbr/#{container_name}"
|
65
|
-
if File.directory?(service_dir)
|
66
|
-
puts "Directory already exists: #{service_dir}"
|
67
|
-
return
|
68
|
-
end
|
69
|
-
|
70
|
-
script_template = <<~SCRIPT
|
71
|
-
#!/bin/sh
|
72
|
-
exec 2>&1
|
73
|
-
cd /var/harbr/#{container_name}/current
|
74
|
-
exec bundle install && bundle exec puma -p #{port}
|
75
|
-
SCRIPT
|
76
|
-
|
77
|
-
service_dir = "/etc/sv/harbr/#{container_name}"
|
78
|
-
FileUtils.mkdir_p(service_dir)
|
79
|
-
|
80
|
-
File.write("#{service_dir}/run", script_template)
|
81
|
-
FileUtils.chmod("+x", "#{service_dir}/run")
|
82
|
-
puts "Run script created and made executable for container: #{container_name}"
|
83
|
-
end
|
84
|
-
|
85
|
-
def create_log_script(container_name)
|
86
|
-
|
87
|
-
log_dir = "/var/log/harbr/#{container_name}"
|
88
|
-
|
89
|
-
if File.directory?(log_dir)
|
90
|
-
puts "Directory already exists: #{log_dir}"
|
91
|
-
return
|
92
|
-
end
|
93
|
-
|
94
|
-
FileUtils.mkdir_p(log_dir)
|
95
|
-
|
96
|
-
script_template = <<~SCRIPT
|
97
|
-
#!/bin/sh
|
98
|
-
exec svlogd -tt #{log_dir}/
|
99
|
-
SCRIPT
|
100
|
-
|
101
|
-
dir_path = "/etc/sv/harbr/#{container_name}/log"
|
102
|
-
FileUtils.mkdir_p(dir_path)
|
103
|
-
|
104
|
-
File.write("#{dir_path}/run", script_template)
|
105
|
-
FileUtils.chmod("+x", "#{dir_path}/run")
|
106
|
-
puts "Log script created and made executable for container: #{container_name}"
|
107
|
-
end
|
108
|
-
|
109
|
-
def create_a_service(container_name, port)
|
110
|
-
create_run_script(container_name, port)
|
111
|
-
create_log_script(container_name)
|
112
|
-
system("ln -s /etc/sv/harbr/#{container_name} /etc/service/#{container_name}") unless File.exist?("/etc/service/#{container_name}")
|
113
|
-
end
|
114
|
-
|
115
|
-
def run_container(manifest)
|
116
|
-
|
117
|
-
puts "Starting container: #{manifest.name}"
|
118
|
-
|
119
|
-
Dddr.configure do |config|
|
120
|
-
config.data_dir = Harbr::DEFAULT_DIRECTORY_DATA_DIR
|
121
|
-
end
|
122
|
-
|
123
|
-
pool = Harbr::Port::Pool.new
|
124
|
-
port = pool.get_port(manifest.host)
|
125
|
-
|
126
|
-
create_a_service(manifest.name, port.number)
|
127
|
-
|
128
|
-
|
129
|
-
sleep 5
|
130
|
-
system("sv restart #{manifest.name}")
|
131
|
-
sleep 5
|
132
|
-
system("sv status #{manifest.name}")
|
133
|
-
puts "Started container: #{manifest.name}"
|
134
|
-
|
135
|
-
|
136
|
-
container = Container.new
|
137
|
-
containers = Container::Repository.new
|
138
|
-
|
139
|
-
container.name = manifest.name
|
140
|
-
container.host_header = manifest.host
|
141
|
-
container.ip = manifest.ip.nil?
|
142
|
-
container.port = port.number
|
143
|
-
containers.add(container) unless containers.find_by_header(manifest.host)
|
144
|
-
|
145
|
-
create_traefik_config(containers.all)
|
146
|
-
|
147
|
-
|
148
|
-
end
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
end
|
153
|
-
|
154
|
-
include Dddr::Entity
|
155
|
-
attr_accessor :name, :host_header, :ip, :port
|
156
|
-
|
157
|
-
queries do
|
158
|
-
def find_by_header(host_header)
|
159
|
-
all.find { |container| container.host_header.downcase == host_header.downcase }
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
|
-
end
|
164
|
-
|
165
|
-
class Port
|
166
|
-
include Dddr::Entity
|
167
|
-
attr_accessor :host_header, :number
|
168
|
-
|
169
|
-
queries do
|
170
|
-
def has_port_number?(number)
|
171
|
-
all.find { |port| port.number == number.to_i }
|
172
|
-
end
|
173
|
-
|
174
|
-
def assigned_a_port?(host_header)
|
175
|
-
all.find { |port| port.host_header == host_header }
|
176
|
-
end
|
177
|
-
end
|
178
|
-
class Pool
|
179
|
-
def initialize(port_range = 50000..51000)
|
180
|
-
@repository = Port::Repository.new
|
181
|
-
|
182
|
-
port_range.each do |number|
|
183
|
-
port = Port.new
|
184
|
-
port.number = number
|
185
|
-
|
186
|
-
unless @repository.has_port_number? number
|
187
|
-
@repository.add(port)
|
188
|
-
puts port.number.to_s + " added!"
|
189
|
-
end
|
190
|
-
end
|
191
|
-
end
|
192
|
-
|
193
|
-
def get_port(host_header)
|
194
|
-
port = @repository.assigned_a_port?(host_header)
|
195
|
-
return port unless port.nil?
|
196
|
-
|
197
|
-
port = ports.shuffle.sample
|
198
|
-
port.host_header = host_header
|
199
|
-
@repository.update(port)
|
200
|
-
port
|
201
|
-
end
|
202
|
-
|
203
|
-
def return_port(port)
|
204
|
-
port.host_header = nil
|
205
|
-
@repository.update(port)
|
206
|
-
port.host_header.nil?
|
207
|
-
end
|
208
|
-
|
209
|
-
def ports
|
210
|
-
@repository.all
|
211
|
-
end
|
212
|
-
end
|
213
|
-
end
|
214
|
-
|
215
|
-
# Your code goes here...
|
216
|
-
end
|
20
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: harbr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.29
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Delaney Kuldvee Burke
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-12-
|
11
|
+
date: 2023-12-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: listen
|
@@ -118,6 +118,10 @@ files:
|
|
118
118
|
- lib/examples/harbr.toml
|
119
119
|
- lib/examples/template.toml
|
120
120
|
- lib/harbr.rb
|
121
|
+
- lib/harbr/container.rb
|
122
|
+
- lib/harbr/job.rb
|
123
|
+
- lib/harbr/pool.rb
|
124
|
+
- lib/harbr/port.rb
|
121
125
|
- lib/harbr/version.rb
|
122
126
|
- sig/harbr.rbs
|
123
127
|
homepage: https://github.com/delaneyburke/harbr
|