docker_toolkit 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 8bed7bfd3321be850470d15839c3e4516c030ef2fd85a5cb893719e69651235c
4
+ data.tar.gz: bca92e12468219f060491956acc7d1867c198e43b9f933a08351ee0929fd5ffd
5
+ SHA512:
6
+ metadata.gz: 5146180b05f18e8ba0a42da96465c3aefaf3a671b3d9b396dabb184eda42023c86df8ba6320f279962711f743eb16ea7e4fdfa781ac4caa60065199d1dea8ebd
7
+ data.tar.gz: a6776d22bbc35be6b0283cb0ee730c8eb9addb16063e8acdb3d8258d95f75f78ebb13fa62178f46a25f3744e46d9ebe187074556882d1d74fe71aadafd1f97ee
data/.dockerignore ADDED
@@ -0,0 +1,20 @@
1
+ .git
2
+ log/*
3
+ tmp/*
4
+ doc/*
5
+ envs/*
6
+ Dockerfile
7
+ /node_modules
8
+ config/keys/*
9
+ config/database.yml
10
+ config/secrets.yml
11
+
12
+ .gitignore
13
+ .gitlab-ci.yml
14
+ base-service.yml
15
+ common-services.yml
16
+
17
+ vendor/cache
18
+
19
+ ca/db
20
+
data/.gitignore ADDED
@@ -0,0 +1,109 @@
1
+ # See https://help.github.com/articles/ignoring-files for more about ignoring files.
2
+ #
3
+ # If you find yourself ignoring temporary files generated by your text editor
4
+ # or operating system, you probably want to add a global ignore instead:
5
+ # git config --global core.excludesfile '~/.gitignore_global'
6
+
7
+ # bundler state
8
+ /.bundle
9
+ vendor/cache
10
+ vendor/bundle
11
+ /vendor/ruby/
12
+
13
+ # minimal Rails specific artifacts
14
+ db/*.sqlite3
15
+ /db/*.sqlite3-journal
16
+ /log/*
17
+ /tmp/*
18
+
19
+ # add /config/database.yml if it contains passwords
20
+ # /config/database.yml
21
+
22
+ # various artifacts
23
+ **.war
24
+ *.rbc
25
+ *.sassc
26
+ .redcar/
27
+ .sass-cache
28
+ /config/config.yml
29
+ /coverage.data
30
+ /coverage/
31
+ /db/*.javadb/
32
+ /db/*.sqlite3
33
+ /config/database.yml
34
+ /config/secrets.yml
35
+ oxymoron.js
36
+ /doc/api/
37
+ /doc/app/
38
+ /doc/features.html
39
+ /doc/specs.html
40
+ /public/cache
41
+ /public/uploads
42
+ /public/stylesheets/compiled
43
+ /public/system/*
44
+ /spec/tmp/*
45
+ /cache
46
+ /capybara*
47
+ /capybara-*.html
48
+ /gems
49
+ /specifications
50
+ app/assets/fonts/disp-preview.html
51
+ rerun.txt
52
+ pickle-email-*.html
53
+ *.sublime-project
54
+ *.sublime-workspace
55
+ .zeus.sock
56
+ .byebug_history
57
+
58
+ #test
59
+ /docs
60
+
61
+
62
+ # If you find yourself ignoring temporary files generated by your text editor
63
+ # or operating system, you probably want to add a global ignore instead:
64
+ # git config --global core.excludesfile ~/.gitignore_global
65
+ #
66
+ # Here are some files you may want to ignore globally:
67
+
68
+ # scm revert files
69
+ **.orig
70
+
71
+ # Mac finder artifacts
72
+ .DS_Store
73
+
74
+ # Netbeans project directory
75
+ /nbproject/
76
+
77
+ # RubyMine project files
78
+ .idea
79
+
80
+ # Textmate project files
81
+ /*.tmproj
82
+
83
+ # vim artifacts
84
+ **.swp
85
+
86
+ # Environment files that may contain sensitive data
87
+ .env
88
+ .powenv
89
+
90
+ # tilde files are usually backup files from a text editor
91
+ *~
92
+ public/assets/
93
+ config/keys
94
+ .ruby-gemset
95
+ .ruby-version
96
+ spec/reports/
97
+ app/assets/javascripts/oxymoron.js
98
+
99
+ !/log/.keep
100
+ !/tmp/.keep
101
+
102
+ /node_modules
103
+ /yarn-error.log
104
+
105
+ .byebug_history
106
+ /public/packs
107
+ /public/packs-test
108
+ /node_modules
109
+ passenger.*.pid.lock
data/.rspec ADDED
@@ -0,0 +1,4 @@
1
+ --color
2
+ --tty
3
+ --format documentation
4
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,89 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.5
3
+ Exclude:
4
+ - 'storage/**/*'
5
+ - 'docker/**/*'
6
+
7
+ Style/AsciiComments:
8
+ Enabled: false
9
+
10
+ Style/RedundantBegin:
11
+ Enabled: false
12
+
13
+ Style/GlobalVars:
14
+ AllowedVariables: ['$logger', '$root']
15
+
16
+ Metrics/BlockLength:
17
+ Exclude:
18
+ - 'spec/**/*.rb'
19
+
20
+ Metrics/MethodLength:
21
+ Max: 20
22
+
23
+ Style/ClassAndModuleChildren:
24
+ EnforcedStyle: compact
25
+ Enabled: false
26
+
27
+ Style/Documentation:
28
+ Enabled: false
29
+
30
+ Style/Lambda:
31
+ Enabled: false
32
+
33
+
34
+ Style/RaiseArgs:
35
+ EnforcedStyle: compact
36
+
37
+ Metrics/LineLength:
38
+ Max: 100
39
+
40
+ #Layout/IndentationWidth:
41
+ # Enabled: true
42
+
43
+ #Layout/IndentAssignment:
44
+ # Enabled: false
45
+ # IndentationWidth: false
46
+
47
+ #Layout/ElseAlignment:
48
+ # Enabled: false
49
+
50
+ #Layout/EndAlignment:
51
+ # Enabled: false
52
+
53
+ #Lint/AssignmentInCondition:
54
+ # Enabled: false
55
+
56
+ Layout/IndentationConsistency:
57
+ EnforcedStyle: rails
58
+
59
+ Layout/EmptyLines:
60
+ Enabled: false
61
+
62
+ Layout/EmptyLinesAroundClassBody:
63
+ EnforcedStyle: empty_lines
64
+
65
+ Layout/EmptyLinesAroundModuleBody:
66
+ EnforcedStyle: empty_lines
67
+
68
+ Layout/SpaceInsideBlockBraces:
69
+ EnforcedStyle: space
70
+ SpaceBeforeBlockParameters: false
71
+
72
+ Layout/SpaceAroundBlockParameters:
73
+ EnforcedStyleInsidePipes: no_space
74
+
75
+ Layout/SpaceBeforeBlockBraces:
76
+ Enabled: false
77
+
78
+ Style/NumericPredicate:
79
+ Enabled: false
80
+
81
+ Style/FrozenStringLiteralComment:
82
+ Enabled: false
83
+
84
+ Style/DoubleNegation:
85
+ Enabled: false
86
+
87
+ Style/SymbolArray:
88
+ Enabled: false
89
+
data/.travis.yml ADDED
@@ -0,0 +1,12 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1
4
+ - 2.5
5
+
6
+ services:
7
+ - docker
8
+
9
+ stage: test
10
+
11
+ script:
12
+ - cd docker && ./run_tests.sh
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in aggredator.gemspec
4
+ gemspec
5
+
6
+
7
+ group :test do
8
+ gem 'awesome_print'
9
+ gem 'faker'
10
+ gem 'faker-russian'
11
+ gem 'rspec'
12
+ gem 'rspec-retry'
13
+ gem 'rspec-set'
14
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,59 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ docker_toolkit (0.1.0)
5
+ diplomat
6
+ json
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ awesome_print (1.8.0)
12
+ concurrent-ruby (1.0.5)
13
+ diff-lcs (1.3)
14
+ diplomat (2.0.2)
15
+ faraday (~> 0.9)
16
+ json
17
+ faker (1.9.1)
18
+ i18n (>= 0.7)
19
+ faker-russian (0.0.6)
20
+ faraday (0.15.2)
21
+ multipart-post (>= 1.2, < 3)
22
+ i18n (1.0.1)
23
+ concurrent-ruby (~> 1.0)
24
+ json (2.1.0)
25
+ multipart-post (2.0.0)
26
+ rake (10.5.0)
27
+ rspec (3.7.0)
28
+ rspec-core (~> 3.7.0)
29
+ rspec-expectations (~> 3.7.0)
30
+ rspec-mocks (~> 3.7.0)
31
+ rspec-core (3.7.1)
32
+ rspec-support (~> 3.7.0)
33
+ rspec-expectations (3.7.0)
34
+ diff-lcs (>= 1.2.0, < 2.0)
35
+ rspec-support (~> 3.7.0)
36
+ rspec-mocks (3.7.0)
37
+ diff-lcs (>= 1.2.0, < 2.0)
38
+ rspec-support (~> 3.7.0)
39
+ rspec-retry (0.6.1)
40
+ rspec-core (> 3.3)
41
+ rspec-set (0.1.3)
42
+ rspec-support (3.7.1)
43
+
44
+ PLATFORMS
45
+ ruby
46
+
47
+ DEPENDENCIES
48
+ awesome_print
49
+ bundler (~> 1.14)
50
+ docker_toolkit!
51
+ faker
52
+ faker-russian
53
+ rake (~> 10.0)
54
+ rspec
55
+ rspec-retry
56
+ rspec-set
57
+
58
+ BUNDLED WITH
59
+ 1.16.1
data/README.md ADDED
@@ -0,0 +1,4 @@
1
+ # docker_toolkit
2
+ Helper tools for work with docker and consul
3
+
4
+ [![Build Status](https://travis-ci.com/RnD-Soft/docker_toolkit.svg?branch=master)](https://travis-ci.com/RnD-Soft/docker_toolkit)
data/bin/consul.rb ADDED
@@ -0,0 +1,222 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'diplomat'
4
+ require 'optparse'
5
+ require 'English'
6
+ require 'yaml'
7
+
8
+ STDOUT.sync = true
9
+ STDERR.sync = true
10
+
11
+ @opts = {}
12
+
13
+ @opts[:exec] = (begin
14
+ ARGV.join(' ').split(' -- ')[1].strip
15
+ rescue StandardError
16
+ nil
17
+ end)
18
+
19
+ parser = OptionParser.new do |o|
20
+ o.banner = 'Usage: consul.rb [options] -- exec'
21
+
22
+ o.on('--consul url', 'Set up a custom Consul URL') do |url|
23
+ Diplomat.configure do |config|
24
+ config.url = url.strip
25
+ end
26
+ end
27
+
28
+ o.on('--token token', 'Connect into consul with custom access token (ACL)') do |token|
29
+ Diplomat.configure do |config|
30
+ config.acl_token = token.strip
31
+ end
32
+ end
33
+
34
+ o.on('--init [service]', 'Initialize Consul services from config') do |service|
35
+ @opts[:service] = service
36
+ @opts[:init] = true
37
+ end
38
+
39
+ o.on('--config file', 'Read service configulation from file') do |file|
40
+ @opts[:config] = file.strip
41
+ end
42
+
43
+ o.on('--upload', 'Upload files to variables') do
44
+ @opts[:upload] = true
45
+ end
46
+
47
+ o.on('--show [service]', 'Show service configulation from Consul') do |service|
48
+ @opts[:service] = service
49
+ @opts[:show] = true
50
+ end
51
+
52
+ o.on('--override', 'override existed keys') do
53
+ @opts[:override] = true
54
+ end
55
+
56
+ o.on('-d', '--dereference', 'dereference consul values in form of "consul://key/subkey"') do
57
+ @opts[:dereference] = true
58
+ end
59
+
60
+ o.on('--env prefix', 'export KV values from prefix as env varaibles') do |prefix|
61
+ @opts[:env] = (prefix + '/').gsub('//', '/')
62
+ end
63
+
64
+ o.on('--export', 'add export to --env output') do
65
+ @opts[:export] = true
66
+ end
67
+
68
+ o.on('--pristine', "not include the parent processes' environment when exec child process") do
69
+ @opts[:pristine] = true
70
+ end
71
+
72
+ o.on('--put path:value', 'put value to path') do |path|
73
+ @opts[:put] = path.strip
74
+ end
75
+
76
+ o.on('--get path', 'get value from') do |path|
77
+ @opts[:get] = path.strip
78
+ end
79
+ end
80
+ parser.parse!
81
+
82
+ def die(message)
83
+ STDERR.puts "Error: #{message}"
84
+ exit 1
85
+ end
86
+
87
+ def key_to_consul(key)
88
+ key.downcase.gsub(/[^0-9a-z]/i, '_')
89
+ end
90
+
91
+ def key_to_env(key)
92
+ key.upcase.gsub(/[^0-9a-z]/i, '_')
93
+ end
94
+
95
+ def dereferenced_value(value)
96
+ if @opts[:dereference] && value && value[/^consul:\/\//]
97
+ reference_path = value.gsub(/^consul:\/\//, '')
98
+ dereferenced_value(Diplomat::Kv.get(reference_path))
99
+ else
100
+ value
101
+ end
102
+ end
103
+
104
+ if config = @opts[:config]
105
+ @opts[:config] = YAML.safe_load(config == '-' ? STDIN.read : File.read(config), [], [], true)
106
+ end
107
+
108
+ if @opts[:init]
109
+ raise OptionParser::MissingArgument.new('config') unless @opts[:config]
110
+
111
+ services = if service = @opts[:service]
112
+ {
113
+ service => @opts[:config][service]
114
+ }
115
+ else
116
+ @opts[:config]
117
+ end
118
+
119
+ services.each_pair do |service, config|
120
+ next unless config
121
+ next if service[/^\./] # skip hidden keys
122
+
123
+ path = "services/env/#{service}"
124
+ config.each_pair do |env, item|
125
+ key = "#{path}/#{key_to_consul(env)}"
126
+ value = if @opts[:upload] && item['file']
127
+ File.read(item['file'])
128
+ else
129
+ item['value'] || item['default'] || item['file']
130
+ end
131
+
132
+ empty = begin
133
+ Diplomat::Kv.get(key)
134
+ false
135
+ rescue Diplomat::KeyNotFound
136
+ true
137
+ end
138
+
139
+ Diplomat::Kv.put(key, value.to_s.strip) || die("Can't put #{key} to Consul") if empty || @opts[:override]
140
+ end
141
+ end
142
+
143
+ exit 0
144
+ end
145
+
146
+ if @opts[:show]
147
+ config = {}
148
+
149
+ path = if service = @opts[:service]
150
+ "services/env/#{service}/"
151
+ else
152
+ 'services/env/'
153
+ end
154
+
155
+ answer = Diplomat::Kv.get(path, recurse: true, convert_to_hash: true) || die("Can't get #{path} from Consul")
156
+ answer['services']['env'].each_pair do |service, env|
157
+ cfg = config[service] ||= {}
158
+
159
+ env.each_pair do |key, value|
160
+ value = dereferenced_value(value)
161
+
162
+ cfg[key_to_env(key)] = {
163
+ env: key_to_env(key),
164
+ value: value
165
+ }
166
+ end
167
+ end
168
+
169
+ STDOUT.puts JSON.parse(config.to_json).to_yaml
170
+
171
+ exit 0
172
+ end
173
+
174
+ if put = @opts[:put]
175
+ path, *value = put.split(':').map(&:strip)
176
+ value = value.join(':')
177
+ value = File.read(value) if @opts[:upload] && value && File.exist?(value)
178
+
179
+ Diplomat::Kv.put(path, value.to_s.strip) || die("Can't put #{path} to Consul")
180
+
181
+ exit 0
182
+ end
183
+
184
+ if path = @opts[:get]
185
+ value = dereferenced_value(Diplomat::Kv.get(path))
186
+
187
+ STDOUT.puts value.to_s.strip
188
+
189
+ exit 0
190
+ end
191
+
192
+ if prefix = @opts[:env]
193
+ keys = begin
194
+ Diplomat::Kv.get(prefix, keys: true)
195
+ rescue Diplomat::KeyNotFound => e
196
+ []
197
+ rescue StandardError
198
+ die("Can't get keys at #{prefix} from Consul")
199
+ end
200
+
201
+ env = keys.reduce({}) do |e, key|
202
+ value = dereferenced_value(Diplomat::Kv.get(key))
203
+
204
+ e.merge(key_to_env(key.gsub(prefix, '')) => value)
205
+ end
206
+
207
+ if cmd = @opts[:exec]
208
+ env = ENV.to_h.merge(env) unless @opts[:pristine]
209
+
210
+ exec(env, cmd, unsetenv_others: true)
211
+ else
212
+ env.each_pair do |k, v|
213
+ STDOUT.puts "#{@opts[:export] ? 'export ' : ''}#{k}=\"#{v}\""
214
+ end
215
+ end
216
+
217
+
218
+ exit 0
219
+ end
220
+
221
+ STDOUT.puts parser.help
222
+ exit 1
data/bin/merger.rb ADDED
@@ -0,0 +1,116 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'English'
4
+ require 'yaml'
5
+
6
+ if File.basename($PROGRAM_NAME) == File.basename(__FILE__)
7
+ unless ENV['COMPOSE_FILE']
8
+ STDERR.puts 'COMPOSE_FILE environment must point to one on mo files'
9
+ exit 1
10
+ end
11
+ end
12
+
13
+
14
+ class Hash
15
+
16
+ def deep_dup
17
+ Marshal.load(Marshal.dump(self))
18
+ end
19
+
20
+ end
21
+
22
+ class Array
23
+
24
+ def deep_dup
25
+ Marshal.load(Marshal.dump(self))
26
+ end
27
+
28
+ end
29
+
30
+
31
+
32
+ def extend_hash(first, second)
33
+ raise ArgumentError.new('First and second args equal nil') if [first, second].all? &:nil?
34
+ return second if first.nil?
35
+ return first if second.nil?
36
+
37
+ first.each_pair do |fk, fv|
38
+ next unless second.key?(fk)
39
+
40
+ sv = second[fk]
41
+ raise "Types of values not match(#{fv.class}, #{sv.class})" if fv.class != sv.class
42
+
43
+ # Специальный случай потому что command не мерджится а заменяется
44
+ if fk == 'command'
45
+ first[fk] = sv
46
+ elsif fv.is_a? Hash
47
+ extend_hash(fv, sv)
48
+ elsif fv.is_a? Array
49
+ fv |= sv
50
+ first[fk] = fv
51
+ else
52
+ first[fk] = sv
53
+ end
54
+ end
55
+
56
+ second.each_pair do |sk, sv|
57
+ next if first.key?(sk)
58
+
59
+ first[sk] = sv
60
+ end
61
+
62
+ first
63
+ end
64
+
65
+ def process_compose_hash(yml, dirname, parent = {})
66
+ (yml['services'] || {}).each_pair do |name, service|
67
+ next unless ext = service['extends']
68
+ base = if ext.is_a? String
69
+ template = yml['services'][ext]
70
+ parent_service = (parent['services'] || {})[ext] || {}
71
+ extend_hash(parent_service.deep_dup, template)
72
+ elsif file = ext['file']
73
+ ENV.each_pair do |k, v|
74
+ file.gsub!("$#{k}", v)
75
+ file.gsub!("${#{k}}", v)
76
+ end
77
+
78
+ tmp = if File.exist?(dirname + '/' + file)
79
+ YAML.safe_load(File.read(dirname + '/' + file))
80
+ else
81
+ YAML.safe_load(File.read(file))
82
+ end
83
+
84
+ begin
85
+ (tmp['services'][ext['service']] || {})
86
+ rescue StandardError
87
+ {}
88
+ end
89
+ else
90
+ yml['services'][ext['service']]
91
+ end.deep_dup
92
+
93
+ service.delete 'extends'
94
+
95
+ yml['services'][name] = extend_hash(base, service)
96
+ end
97
+ yml
98
+ end
99
+
100
+ if File.basename($PROGRAM_NAME) == File.basename(__FILE__)
101
+ result = ENV['COMPOSE_FILE'].split(':').reduce({}) do |parent, file|
102
+ yml = process_compose_hash(YAML.safe_load(File.read(file)), File.dirname(file), parent)
103
+ if yml['version'] && parent['version'] && yml['version'] != parent['version']
104
+ raise "version mismatch: #{file}"
105
+ end
106
+ ret = extend_hash(parent.deep_dup, yml)
107
+ ret
108
+ end
109
+
110
+ if ARGV[0].nil? || ARGV[0].strip == '-'
111
+ puts YAML.dump(result)
112
+ else
113
+ File.write(ARGV[0].strip, YAML.dump(result))
114
+ end
115
+
116
+ end
data/bin/waiter.rb ADDED
@@ -0,0 +1,246 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'securerandom'
5
+ require 'English'
6
+ require 'openssl'
7
+ require 'tempfile'
8
+
9
+ STDOUT.sync = true
10
+ STDERR.sync = true
11
+
12
+ TIMEOUT = 15
13
+ INTERVAL = 3
14
+
15
+ @opts = {}
16
+
17
+ @opts[:exec] = (begin
18
+ ARGV.join(' ').split(' -- ')[1].strip
19
+ rescue StandardError
20
+ nil
21
+ end)
22
+ @opts[:timeout] = TIMEOUT
23
+ @opts[:interval] = INTERVAL
24
+ @opts[:consul_addr] = 'http://localhost:8500'
25
+
26
+
27
+ OptionParser.new do |o|
28
+ o.banner = 'Usage: waiter.rb [options] -- exec'
29
+
30
+ o.on('--tcp host:port', 'Wait for tcp accepts on host:port') do |addr|
31
+ host, port = addr.split(':')
32
+ @opts[:tcp] = addr.strip
33
+ @opts[:host] = host.strip
34
+ @opts[:port] = port.strip
35
+ end
36
+
37
+ o.on('--db dbname', 'Wait for PG database exists. Using --tcp to conenct PG') do |db|
38
+ @opts[:db] = db.strip
39
+ end
40
+
41
+ o.on('--tb tablename', 'Wait for PG table exists. Using --tcp to conenct PG') do |tb|
42
+ @opts[:tb] = tb.strip
43
+ end
44
+
45
+ o.on('-f', '--file filename', 'Wait for file exists.') do |file|
46
+ @opts[:file] = file.strip
47
+ end
48
+
49
+ o.on("--consul-addr addr=#{@opts[:consul_addr]}", 'HTTP addres to connect to consul') do |addr|
50
+ @opts[:consul_addr] = addr.strip
51
+ end
52
+
53
+ o.on('--consul', 'Wait for local consul agent to be ready') do
54
+ @opts[:consul] = true
55
+ end
56
+
57
+ o.on('--consul-service service', 'Wait for service appear in consul') do |service|
58
+ @opts[:consul_service] = service
59
+ end
60
+
61
+ o.on('--user user', 'username') do |user|
62
+ @opts[:user] = user.strip
63
+ end
64
+
65
+ o.on('--pass pass', 'password') do |pass|
66
+ @opts[:pass] = pass.strip
67
+ end
68
+
69
+ o.on('-t', '--timeout secs=15', 'Total timeout') do |timeout|
70
+ @opts[:timeout] = timeout.to_i
71
+ end
72
+
73
+ o.on('-i', '--interval secs=2', 'Interval between attempts') do |interval|
74
+ @opts[:interval] = interval.to_i
75
+ end
76
+
77
+ o.on('-q', '--quiet', 'Do not output any status messages') do
78
+ @opts[:quiet] = true
79
+ end
80
+ end.parse!
81
+
82
+ def log(message)
83
+ puts message unless @opts[:quiet]
84
+ end
85
+
86
+ @opts[:timeout] = @opts[:timeout].to_i
87
+ @opts[:interval] = @opts[:interval].to_i
88
+
89
+ if @opts[:db]
90
+ @pg = {}
91
+ @pg[:db] = "-d #{@opts[:db]}"
92
+ @pg[:user] = "-U #{@opts[:user]}" if @opts[:user]
93
+ @pg[:pass] = if @opts[:pass] && !@opts[:pass].empty?
94
+ "-W #{@opts[:pass]}"
95
+ else
96
+ '-w'
97
+ end
98
+
99
+ @pg[:host] = "-h #{@opts[:host]}" if @opts[:host]
100
+ @pg[:port] = "-p #{@opts[:port]}" if @opts[:port]
101
+
102
+ @pg[:tb] = @opts[:tb] if @opts[:tb]
103
+ end
104
+
105
+ def wait_for(timeout)
106
+ starttime = Time.now
107
+ loop do
108
+ success = yield
109
+
110
+ return success if success
111
+
112
+ return false if (Time.now - starttime) > timeout
113
+ sleep @opts[:interval]
114
+ end
115
+
116
+ false
117
+ end
118
+
119
+ def complete!(success)
120
+ if success
121
+ if @opts[:exec]
122
+ exec @opts[:exec]
123
+ else
124
+ exit 0
125
+ end
126
+ end
127
+
128
+ STDERR.puts 'Operation timed out'
129
+ exit 1
130
+ end
131
+
132
+ def wait_for_consul
133
+ log('Waiting for consul...')
134
+ ret = wait_for @opts[:timeout] do
135
+ cmd = "consul operator raft list-peers -http-addr=#{@opts[:consul_addr]} > /dev/null 2>&1"
136
+ system(cmd)
137
+ $CHILD_STATUS.success?
138
+ end
139
+
140
+ yield(ret)
141
+ end
142
+
143
+ def wait_for_consul_service(service)
144
+ log("Waiting for consul service #{service}...")
145
+ ret = wait_for @opts[:timeout] do
146
+ cmd = "curl -s #{@opts[:consul_addr]}/v1/health/service/#{service}?passing | wc -c"
147
+ bytes = `#{cmd}`.to_i
148
+ bytes > 10
149
+ end
150
+
151
+ yield(ret)
152
+ end
153
+
154
+ def wait_for_tcp
155
+ log("Waiting for TCP: #{@opts[:host]}:#{@opts[:port]}...")
156
+ ret = wait_for @opts[:timeout] do
157
+ cmd = "nc -z #{@opts[:host]} #{@opts[:port]} > /dev/null 2>&1"
158
+ system(cmd)
159
+ $CHILD_STATUS.success?
160
+ end
161
+
162
+ yield(ret)
163
+ end
164
+
165
+ def wait_for_db
166
+ log("Waiting for DB: pg://#{@opts[:user]}:#{@opts[:pass]}@#{@opts[:host]}:#{@opts[:port]}/#{@opts[:db]}...")
167
+ ret = wait_for @opts[:timeout] do
168
+ cmd = "psql -lqt #{@pg[:user]} #{@pg[:pass]} #{@pg[:host]} #{@pg[:port]} #{@pg[:db]} 2>/dev/null | cut -d \\| -f 1 | grep -qw #{@opts[:db]} > /dev/null 2>&1"
169
+ system(cmd)
170
+ $CHILD_STATUS.success?
171
+ end
172
+
173
+ yield(ret)
174
+ end
175
+
176
+ def wait_for_tb
177
+ log("Waiting for TABLE: pg://#{@opts[:user]}:#{@opts[:pass]}@#{@opts[:host]}:#{@opts[:port]}/#{@opts[:db]}##{@opts[:tb]}...")
178
+ ret = wait_for @opts[:timeout] do
179
+ cmd = "echo \"\\dt\" | psql -qt #{@pg[:user]} #{@pg[:pass]} #{@pg[:host]} #{@pg[:port]} #{@pg[:db]} 2>/dev/null | cut -d \\| -f 2 | grep -qw #{@pg[:tb]} > /dev/null 2>&1"
180
+ system(cmd)
181
+ $CHILD_STATUS.success?
182
+ end
183
+
184
+ yield(ret)
185
+ end
186
+
187
+ def wait_for_file(file = @opts[:file], timeout = @opts[:timeout])
188
+ log("Waiting for FILE: #{file}")
189
+ ret = wait_for timeout do
190
+ File.exist? file
191
+ end
192
+ yield(ret)
193
+ end
194
+
195
+ if @opts[:tb]
196
+ wait_for_tcp do |success|
197
+ if success
198
+ wait_for_db do |success|
199
+ if success
200
+ wait_for_tb do |success|
201
+ complete!(success)
202
+ end
203
+ end
204
+ end
205
+ end
206
+
207
+ complete!(false)
208
+ end
209
+ end
210
+
211
+ if @opts[:db]
212
+ wait_for_tcp do |success|
213
+ if success
214
+ wait_for_db do |success|
215
+ complete!(success)
216
+ end
217
+ end
218
+
219
+ complete!(false)
220
+ end
221
+ end
222
+
223
+
224
+ if @opts[:consul]
225
+ wait_for_consul do |success|
226
+ complete!(success)
227
+ end
228
+ end
229
+
230
+ if @opts[:consul_service]
231
+ wait_for_consul_service(@opts[:consul_service]) do |success|
232
+ complete!(success)
233
+ end
234
+ end
235
+
236
+ if @opts[:tcp]
237
+ wait_for_tcp do |success|
238
+ complete!(success)
239
+ end
240
+ end
241
+
242
+ if @opts[:file]
243
+ wait_for_file(@opts[:file], @opts[:timeout]) do |success|
244
+ complete!(success)
245
+ end
246
+ end
data/docker/Dockerfile ADDED
@@ -0,0 +1,53 @@
1
+ FROM ruby:2.5.0-alpine
2
+ MAINTAINER Firmhouse "kinnalru@gmail.com"
3
+
4
+ WORKDIR /home/app
5
+
6
+ RUN mkdir -p ~/.ssh && echo -e "Host * \
7
+ \n StrictHostKeyChecking no \
8
+ \n UserKnownHostsFile=/dev/null\n" >> ~/.ssh/config
9
+
10
+ RUN set -ex \
11
+ && apk add --no-cache \
12
+ bash \
13
+ libstdc++ \
14
+ libxml2 \
15
+ ruby-libs \
16
+ wget \
17
+ curl \
18
+ libcurl \
19
+ ruby \
20
+ git \
21
+ tzdata
22
+
23
+ RUN set -ex \
24
+ && curl -sSLo /tmp/consul.zip https://releases.hashicorp.com/consul/1.2.1/consul_1.2.1_linux_amd64.zip \
25
+ && unzip -d /bin /tmp/consul.zip \
26
+ && rm -rf /tmp/consul.zip \
27
+ && addgroup consul \
28
+ && adduser -D -g "" -s /bin/sh -G consul consul \
29
+ && mkdir -p /tmp/consul \
30
+ && chown -R consul:consul /tmp/consul
31
+
32
+ RUN set -ex \
33
+ && curl -so envconsul.tgz https://releases.hashicorp.com/envconsul/0.7.3/envconsul_0.7.3_linux_amd64.tgz \
34
+ && tar -xvzf envconsul.tgz \
35
+ && rm -rf envconsul.tgz \
36
+ && mv envconsul /bin/envconsul \
37
+ && chmod +x /bin/envconsul
38
+
39
+ ADD Gemfile Gemfile.lock docker_toolkit.gemspec /home/app/
40
+ ADD lib/ /home/app/lib
41
+
42
+ RUN set -ex \
43
+ && bundle install \
44
+ && cd / \
45
+ && rm -rf /usr/src/ruby
46
+
47
+ ADD . /home/app
48
+
49
+
50
+
51
+ SHELL ["/bin/sh", "-c", "-l"]
52
+
53
+
@@ -0,0 +1,12 @@
1
+ version: "2"
2
+ services:
3
+ tests:
4
+ build:
5
+ context: ../
6
+ dockerfile: docker/Dockerfile
7
+ image: docker_toolkit_tests:latest
8
+ working_dir: /home/app
9
+ command: ["tail", "-f", "/dev/null"]
10
+
11
+
12
+
data/docker/down.sh ADDED
@@ -0,0 +1,4 @@
1
+ #!/bin/sh
2
+ docker-compose down -v || true
3
+
4
+
@@ -0,0 +1,17 @@
1
+ #!/bin/sh
2
+ SELF=$(readlink -f $0)
3
+ export ENV_ROOT=$(dirname "${SELF}")
4
+
5
+ trap '$ENV_ROOT/down.sh' EXIT
6
+
7
+ cd $ENV_ROOT
8
+
9
+ docker-compose up -d --force-recreate --build || exit 1
10
+ docker-compose exec -T tests bundle exec rspec $@
11
+
12
+ code=$?
13
+ if [ $code -ne 0 ]; then
14
+ docker-compose logs
15
+ fi
16
+
17
+ exit $code
@@ -0,0 +1,33 @@
1
+ lib = File.expand_path('lib', __dir__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'docker_toolkit/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'docker_toolkit'
7
+ spec.version = DockerToolkit::VERSION
8
+ spec.authors = ['Godko Ivan', 'Samoilenko Yuri']
9
+ spec.email = ['igodko@rnds.pro', 'kinnalru@gmail.com']
10
+ spec.homepage = 'https://github.com/RnD-Soft/docker_toolkit'
11
+ spec.required_ruby_version = '>= 2.1.0'
12
+
13
+ spec.summary = 'Helper scripts for work with docker and consul'
14
+ spec.description = 'Advanced docker and consul control scripts'
15
+
16
+ spec.bindir = 'bin'
17
+ spec.require_paths = ['lib']
18
+
19
+ if File.exist?(File.join(__dir__, '/', '.git'))
20
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
21
+ f.match(%r{^(test|spec|features)/})
22
+ end
23
+
24
+ spec.executables = `git ls-files -- bin/*`.split("\n").map{|f| File.basename(f) }
25
+ end
26
+
27
+
28
+ spec.add_dependency 'diplomat'
29
+ spec.add_dependency 'json'
30
+
31
+ spec.add_development_dependency 'bundler', '~> 1.14'
32
+ spec.add_development_dependency 'rake', '~> 10.0'
33
+ end
@@ -0,0 +1,5 @@
1
+ module DockerToolkit
2
+
3
+ VERSION = '0.1.0'.freeze
4
+
5
+ end
@@ -0,0 +1,10 @@
1
+ require 'diplomat'
2
+ require 'English'
3
+ require 'optparse'
4
+
5
+ require 'docker_toolkit/version'
6
+
7
+ module DockerToolkit
8
+
9
+
10
+ end
metadata ADDED
@@ -0,0 +1,122 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: docker_toolkit
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Godko Ivan
8
+ - Samoilenko Yuri
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2018-08-10 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: diplomat
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: json
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: bundler
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '1.14'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '1.14'
56
+ - !ruby/object:Gem::Dependency
57
+ name: rake
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: '10.0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '10.0'
70
+ description: Advanced docker and consul control scripts
71
+ email:
72
+ - igodko@rnds.pro
73
+ - kinnalru@gmail.com
74
+ executables:
75
+ - consul.rb
76
+ - merger.rb
77
+ - waiter.rb
78
+ extensions: []
79
+ extra_rdoc_files: []
80
+ files:
81
+ - ".dockerignore"
82
+ - ".gitignore"
83
+ - ".rspec"
84
+ - ".rubocop.yml"
85
+ - ".travis.yml"
86
+ - Gemfile
87
+ - Gemfile.lock
88
+ - README.md
89
+ - bin/consul.rb
90
+ - bin/merger.rb
91
+ - bin/waiter.rb
92
+ - docker/Dockerfile
93
+ - docker/docker-compose.yml
94
+ - docker/down.sh
95
+ - docker/run_tests.sh
96
+ - docker_toolkit.gemspec
97
+ - lib/docker_toolkit.rb
98
+ - lib/docker_toolkit/version.rb
99
+ homepage: https://github.com/RnD-Soft/docker_toolkit
100
+ licenses: []
101
+ metadata: {}
102
+ post_install_message:
103
+ rdoc_options: []
104
+ require_paths:
105
+ - lib
106
+ required_ruby_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: 2.1.0
111
+ required_rubygems_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ requirements: []
117
+ rubyforge_project:
118
+ rubygems_version: 2.7.3
119
+ signing_key:
120
+ specification_version: 4
121
+ summary: Helper scripts for work with docker and consul
122
+ test_files: []