dry-stack 0.0.88 → 0.1.1
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/dry-stack/command_compose.rb +4 -5
- data/lib/dry-stack/command_line.rb +11 -5
- data/lib/dry-stack/command_swarm_deploy.rb +14 -20
- data/lib/dry-stack/stack.rb +29 -29
- data/lib/version.rb +1 -1
- metadata +2 -5
- data/bin/stack.drs +0 -33
- data/bin/stack1.drs +0 -1
- data/bin/stack2.drs +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8e0189d36c23f0487d26004278fd73f0d8e94410d31a7a44237ca88521edd165
|
4
|
+
data.tar.gz: a7e80baf8f3cec031ec0dcd863738301e3758ebea4dfc11c4101b3f9c1ba51a2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0bacfd11de68b970264c5749cd38797b52ea83aa9a2b6b818232798d22e50bfc1c6a8ae243cff52af1a03a35b841165bbfd08053dfbb39e1d5cb193f20e985ac
|
7
|
+
data.tar.gz: d3e124944972e6efaccba32322bff5edc5bf9ff9855e23981488f2ebe440cd4763781a6a9930c14b7c121ed38e5895f29e55ca54f5e017b272871d4b3e9a0812
|
@@ -1,14 +1,13 @@
|
|
1
1
|
require_relative 'command_line'
|
2
2
|
|
3
3
|
Dry::CommandLine::COMMANDS[:to_compose] = Class.new do
|
4
|
-
def run(stack, params,
|
5
|
-
raise "none or one deploy name may be specified: #{args}" unless args.empty? || args.size == 1
|
4
|
+
def run(stack, params, _args, _extra)
|
6
5
|
_params = stack.options.merge params
|
7
|
-
|
8
|
-
|
6
|
+
yaml = stack.to_compose(_params ).lines[1..].join
|
7
|
+
$stdout.puts yaml
|
9
8
|
|
10
9
|
# substitute ENV variables
|
11
|
-
_params[:'no-env'] ? $stdout.puts(yaml) : system("echo \"#{yaml.gsub("`", '\\\`')}\"")
|
10
|
+
# _params[:'no-env'] ? $stdout.puts(yaml) : system("echo \"#{yaml.gsub("`", '\\\`')}\"")
|
12
11
|
end
|
13
12
|
|
14
13
|
def help = ['Print stack in docker compose format',
|
@@ -37,7 +37,9 @@ module Dry
|
|
37
37
|
raise 'Invalid .env file'
|
38
38
|
end
|
39
39
|
|
40
|
-
def safe_eval(
|
40
|
+
def safe_eval(drs, params)
|
41
|
+
Dry::Stack(params[:name], params[:configuration]) { eval drs, self.binding }
|
42
|
+
end
|
41
43
|
|
42
44
|
def run(args)
|
43
45
|
params = {}
|
@@ -68,9 +70,12 @@ module Dry
|
|
68
70
|
o.on('', '--name STACK_NAME', 'Define stack name')
|
69
71
|
o.on('', '--ingress', 'Generate ingress labels') { true }
|
70
72
|
o.on('', '--traefik', 'Generate traefik labels') { true }
|
71
|
-
o.on('', '--
|
72
|
-
o.on('', '--
|
73
|
-
o.on('-n', '--no-env', '
|
73
|
+
o.on('', '--traefik-tls', 'Generate traefik tls labels') { true }
|
74
|
+
o.on('', '--host-sed /from/to/', 'Sed ingress host /\\*/dev.*/')
|
75
|
+
o.on('-n', '--no-env', 'Deprecated') { $stderr.puts 'warning: deprecated option: -n' } # TODO: remove
|
76
|
+
o.on('-c', '--configuration name', 'Configuration name')
|
77
|
+
COMMANDS.values.select{_1.options(o) if _1.respond_to? :options }
|
78
|
+
|
74
79
|
o.on('-h', '--help') { puts o; exit }
|
75
80
|
o.parse! args, into: params
|
76
81
|
|
@@ -82,7 +87,8 @@ module Dry
|
|
82
87
|
stack_text = File.read(params[:stack]) if params[:stack]
|
83
88
|
stack_text ||= STDIN.read unless $stdin.tty?
|
84
89
|
|
85
|
-
|
90
|
+
|
91
|
+
safe_eval stack_text, params # isolate context
|
86
92
|
|
87
93
|
Stack.last_stack.name = params[:name] if params[:name]
|
88
94
|
COMMANDS[command.to_sym].run Stack.last_stack, params, args, extra
|
@@ -1,41 +1,35 @@
|
|
1
1
|
require_relative 'command_line'
|
2
2
|
|
3
3
|
Dry::CommandLine::COMMANDS[:swarm_deploy] = Class.new do
|
4
|
+
def options(parser)
|
5
|
+
parser.on('-x', '--context-endpoint host', 'Docker context host. Created if not exists')
|
6
|
+
end
|
7
|
+
|
4
8
|
def run(stack, params, args, extra)
|
5
|
-
unless args.empty?
|
6
|
-
c_name = args[0].to_sym
|
7
|
-
raise "deploy config not found: #{args[0]}" unless stack.swarm_deploy.key? args[0].to_sym
|
8
|
-
context = stack.swarm_deploy[args[0].to_sym]
|
9
|
-
end
|
10
9
|
_params = stack.options.merge params
|
11
10
|
stack.name = _params[:name] if _params[:name]
|
12
11
|
|
13
|
-
if context
|
14
|
-
name =
|
15
|
-
|
12
|
+
if params[:'context-endpoint']
|
13
|
+
name = params[:'context-endpoint'].gsub( /[\/.:@]/,'_').gsub( '__','_')
|
14
|
+
name = "dry-#{name}".to_sym
|
15
|
+
endpoint = params[:'context-endpoint']
|
16
16
|
contexts = {}
|
17
|
-
exec_o_lines
|
17
|
+
exec_o_lines 'docker context ls --format json' do |line|
|
18
18
|
ctx = JSON.parse line, symbolize_names: true
|
19
19
|
contexts[ctx[:Name].to_sym] = ctx # {"Current":false,"Description":"","DockerEndpoint":"ssh://root@x.x.x.x","Error":"","Name":"prod-swarm"}
|
20
20
|
end
|
21
21
|
|
22
|
-
if contexts[name] && contexts[name][:DockerEndpoint] !=
|
23
|
-
raise "context '#{name}' has different host value: #{contexts[name][:DockerEndpoint]} != #{
|
22
|
+
if contexts[name] && contexts[name][:DockerEndpoint] != endpoint
|
23
|
+
raise "context '#{name}' has different host value: #{contexts[name][:DockerEndpoint]} != #{endpoint}"
|
24
24
|
end
|
25
25
|
|
26
|
-
exec_i "docker context create #{name} --docker host=#{
|
26
|
+
exec_i "docker context create #{name} --docker host=#{endpoint}" unless contexts[name]
|
27
27
|
|
28
28
|
ENV['DOCKER_CONTEXT'] = name.to_s
|
29
|
-
stack.name = context[:stack_name] || stack.name
|
30
|
-
context[:environment].each do |k,v|
|
31
|
-
ENV[k.to_s] = v.to_s
|
32
|
-
end
|
33
29
|
end
|
34
30
|
|
35
31
|
# substitute ENV variables
|
36
|
-
yaml = stack.to_compose(_params
|
37
|
-
yaml = _params[:'no-env'] ? yaml : `echo \"#{yaml.gsub("`", '\\\`')}\"`
|
38
|
-
system " echo \"#{yaml.gsub("`", '\\\`')}\"" if _params[:v]
|
32
|
+
yaml = stack.to_compose(_params).lines[1..].join
|
39
33
|
# system " echo \"#{yaml.gsub("`", '\\\`')}\" | docker stack deploy -c - #{stack.name} --prune --resolve-image changed"
|
40
34
|
|
41
35
|
# --prune --resolve-image changed
|
@@ -48,7 +42,7 @@ Dry::CommandLine::COMMANDS[:swarm_deploy] = Class.new do
|
|
48
42
|
end
|
49
43
|
|
50
44
|
def help = ['Call docker stack deploy & add config readme w/ description',
|
51
|
-
'[... swarm_deploy
|
45
|
+
'[... swarm_deploy -- --prune --resolve-image changed]']
|
52
46
|
|
53
47
|
end.new
|
54
48
|
|
data/lib/dry-stack/stack.rb
CHANGED
@@ -39,9 +39,10 @@ module Dry
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
-
def Stack(name = nil, &)
|
42
|
+
def Stack(name = nil, configuration = nil, &)
|
43
43
|
Stack.last_stack = Stack.new name
|
44
44
|
Stack.last_stack.instance_exec(&) if block_given?
|
45
|
+
Stack.last_stack.apply_configuration configuration if configuration
|
45
46
|
end
|
46
47
|
|
47
48
|
class ServiceFunction
|
@@ -54,20 +55,15 @@ module Dry
|
|
54
55
|
def command(cmd)= @service[:command] = cmd
|
55
56
|
def entrypoint(cmd)= @service[:entrypoint] = cmd
|
56
57
|
def deploy_label(str)= @service[:deploy][:labels] << str
|
57
|
-
def config(name = nil, opts)= (@service[:configs] ||= []) << {source: name.to_s
|
58
|
+
def config(name = nil, opts)= (@service[:configs] ||= []) << {source: name.to_s}.merge(opts)
|
58
59
|
def logging(opts) = (@service[:logging] ||= {}).merge! opts
|
59
60
|
def user(user) = @service[:user] = user # "${UID}:${GID}", "www-data:www-data"
|
60
61
|
def network(names) = (@service[:networks] ||= []) << names
|
61
62
|
def ingress(ing) = ((@service[:ingress] ||=[]) << ing).flatten!
|
62
63
|
end
|
63
64
|
|
64
|
-
class
|
65
|
-
def initialize(
|
66
|
-
def env(variables)= @swarm[:environment].merge! variables
|
67
|
-
def options(variables)= @swarm[:options].merge! variables
|
68
|
-
def context_host(host)= @swarm[:context_host] = host
|
69
|
-
def context_name(name)= @swarm[:context_name] = name
|
70
|
-
def stack_name(name)= @swarm[:stack_name] = name
|
65
|
+
class ConfigurationFunction
|
66
|
+
def initialize(configuration, &); @configuration = configuration; instance_exec(&) end
|
71
67
|
end
|
72
68
|
|
73
69
|
class Stack
|
@@ -75,12 +71,13 @@ module Dry
|
|
75
71
|
class << self
|
76
72
|
attr_accessor :last_stack
|
77
73
|
end
|
78
|
-
attr_accessor :name, :options, :description, :
|
74
|
+
attr_accessor :name, :options, :description, :configuration
|
79
75
|
|
80
|
-
def Stack(
|
81
|
-
|
82
|
-
|
83
|
-
|
76
|
+
def Stack(...) = Dry::Stack(...)
|
77
|
+
|
78
|
+
# def self.new(*args, &block)
|
79
|
+
# super
|
80
|
+
# end
|
84
81
|
|
85
82
|
def initialize(name)
|
86
83
|
@name = name || 'stack'
|
@@ -97,7 +94,7 @@ module Dry
|
|
97
94
|
@labels = {}
|
98
95
|
@configs = {}
|
99
96
|
@logging = {}
|
100
|
-
@
|
97
|
+
@configurations = {}
|
101
98
|
end
|
102
99
|
|
103
100
|
def expand_hash(hash)
|
@@ -123,12 +120,13 @@ module Dry
|
|
123
120
|
end
|
124
121
|
end
|
125
122
|
|
126
|
-
def
|
127
|
-
|
128
|
-
|
123
|
+
def apply_configuration(configuration)
|
124
|
+
raise "Configuration not found: #{configuration}" unless @configurations[configuration.to_sym]
|
125
|
+
@configurations[configuration.to_sym][:block_function].call
|
126
|
+
end
|
129
127
|
|
130
|
-
|
131
|
-
|
128
|
+
def to_compose(opts = @options)
|
129
|
+
@name = @options[:name] || @name
|
132
130
|
|
133
131
|
compose = {
|
134
132
|
# name: @name.to_s, # https://docs.docker.com/compose/compose-file/#name-top-level-element
|
@@ -323,8 +321,8 @@ module Dry
|
|
323
321
|
end
|
324
322
|
|
325
323
|
def Options(opts)
|
326
|
-
warn 'WARN: Options command is used for testing purpose.\
|
327
|
-
|
324
|
+
# warn 'WARN: Options command is used for testing purpose.\
|
325
|
+
# Not recommended in real life configurations.' unless $0 =~ /rspec/
|
328
326
|
@options.merge! opts
|
329
327
|
end
|
330
328
|
|
@@ -333,7 +331,9 @@ module Dry
|
|
333
331
|
end
|
334
332
|
|
335
333
|
def Ingress(services)
|
336
|
-
|
334
|
+
services.each do |name, ing|
|
335
|
+
@ingress[name] = ((@ingress[name] || [] ) | [ing]).flatten
|
336
|
+
end
|
337
337
|
end
|
338
338
|
|
339
339
|
def Config(name, opts)
|
@@ -382,12 +382,12 @@ module Dry
|
|
382
382
|
yield if block_given?
|
383
383
|
end
|
384
384
|
|
385
|
-
def
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
385
|
+
def Configuration(name, opts = {}, &)
|
386
|
+
configuration = @configurations[name.to_sym] ||= {}
|
387
|
+
configuration.merge! opts
|
388
|
+
configuration.merge! block_function: -> {
|
389
|
+
instance_exec(&) if block_given? # https://rubyreferences.github.io/rubychanges/3.3.html#anonymous-parameters-forwarding-inside-blocks-are-disallowed
|
390
|
+
}
|
391
391
|
end
|
392
392
|
|
393
393
|
end
|
data/lib/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dry-stack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Artyom B
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-07-
|
11
|
+
date: 2024-07-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -102,9 +102,6 @@ extensions: []
|
|
102
102
|
extra_rdoc_files: []
|
103
103
|
files:
|
104
104
|
- bin/dry-stack
|
105
|
-
- bin/stack.drs
|
106
|
-
- bin/stack1.drs
|
107
|
-
- bin/stack2.drs
|
108
105
|
- lib/dry-stack.rb
|
109
106
|
- lib/dry-stack/apache_specific_md5.rb
|
110
107
|
- lib/dry-stack/command_compose.rb
|
data/bin/stack.drs
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
Description <<~DSC
|
2
|
-
|
3
|
-
DSC
|
4
|
-
|
5
|
-
Options name: 'stack_name', traefik: true
|
6
|
-
SwarmDeploy :sky_gates do
|
7
|
-
context_host 'ssh://root@10.0.0.1'
|
8
|
-
stack_name 'remote_stack'
|
9
|
-
env REGISTRY_HOST: '10.100.0.2:5000'
|
10
|
-
end
|
11
|
-
Ingress admin: [
|
12
|
-
{host: 'backend.*'},
|
13
|
-
{host: 'admin.*', path: '/api', port: 4000}
|
14
|
-
]
|
15
|
-
|
16
|
-
Deploy [:admin, :operator], labels: [
|
17
|
-
'traefik.http.middlewares.%{service-name}_auth.basicauth.users=admin:$$apr1$$i7hdbc9g$$Rkocxo9snhmuESvUg0TTv/',
|
18
|
-
"traefik.http.routers.%{service-name}.middlewares=%{service-name}_auth"
|
19
|
-
]
|
20
|
-
|
21
|
-
PublishPorts admin: 4000, operator: 4001, navigator: 4002, reports: 7000 # mode: ingress, protocol: tcp
|
22
|
-
|
23
|
-
Service :admin, image: 'frontend', env: {APP: 'admin'}, ports: 5000
|
24
|
-
Service :operator, image: 'frontend', env: {APP: 'operator'}, ports: 5000
|
25
|
-
Service :navigator, image: 'frontend', env: {APP: 'navigator'}, ports: 5000
|
26
|
-
|
27
|
-
Service :backend, image: 'backend', ports: 3000 do
|
28
|
-
env APP_PORT: 3000, NODE_ENV: 'development', SKIP_GZ: true, DB_URL: '$DB_URL'
|
29
|
-
end
|
30
|
-
|
31
|
-
Service :reports, image: 'reports:0.1', env: {DB_URL: '$DB_URL'}, ports: 7000
|
32
|
-
|
33
|
-
Network :default, attachable: true
|
data/bin/stack1.drs
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
Service :reports, image: 'reports', ports: 7000, env: {DB_URL: '$DB_URL'}
|
data/bin/stack2.drs
DELETED
@@ -1,8 +0,0 @@
|
|
1
|
-
PublishPorts reports: 7000
|
2
|
-
Ingress reports: {host: 'reports.*', protocol: :http, port: 7000}
|
3
|
-
Deploy admin: { replica: 2, 'resources.limits': { cpus: 4, memory: '500M' } }
|
4
|
-
|
5
|
-
Service :admin, image: '$REGISTRY_HOST/frontend', env: { APP: 'admin' }, ports: 5000
|
6
|
-
Service :reports, image: '$REGISTRY_HOST/reports', env: { DB_URL: '$DB_URL' }
|
7
|
-
|
8
|
-
Network :default, attachable: true
|