pygmy-traefik 0.9.10

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 912636babd6e8183bc92c9030ca4a5d8b669e53b
4
+ data.tar.gz: 2911b44d98e787055cd03f22fd85a214a4b51f48
5
+ SHA512:
6
+ metadata.gz: 339d451345b29a038989c932fc4ce99bcaf4924f4907f096de87d5053358f0bf3df3f753f7b11bc2ae0594952ec545ca84fa0f94a65c6dcd7f9791eddb2b9bce
7
+ data.tar.gz: e910eb818a6dc1e303f5836a0fc8432517955b8d161a8ed598b00db2dbf484da86838aeb7d1d53d610764864b0d4187c19f1bc59c97add9779d180c5912bea05
@@ -0,0 +1,371 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'thor'
4
+ require 'yaml'
5
+
6
+ require 'pygmy'
7
+
8
+ class PygmyBin < Thor
9
+ class_option :verbose, type: :boolean, aliases: '-v', default: false
10
+
11
+ desc 'up', 'Bring up pygmy services (dnsmasq, haproxy, mailhog, resolv, ssh-agent)'
12
+ long_desc <<-LONGDESC
13
+ Bring up pygmy services (dnsmasq, haproxy, resolv, ssh-agent)
14
+
15
+ When run, there will be two docker containers started:
16
+
17
+ - dnsmasq: to resolve DNS requests for your the domain *.docker.amazee.io (unless you add --no-resolver)
18
+
19
+ - haproxy: to forward HTTP and HTTPs requests to the docker containers running Drupal.
20
+
21
+ - traefik: optional alternative to haproxy. (add --traefik to enable)
22
+
23
+ - ssh-agent: to keep the ssh-agent at one single place, so that all other docker containers
24
+ can consume the ssh key. You can bypass automatically adding keys to the agent by using --no-addkey.
25
+
26
+ On Linux: The local resolver (/etc/resolv.conf) will be configured to use the dnsmasq
27
+ instance as a nameserver. (unless you add --no-resolver)
28
+
29
+ On Mac: A resolver file (/etc/resolver/docker.amazee.io) will be created to use the dnsmasq
30
+ instance as a nameserver for all *.docker.amazee.io domains. (unless you add --no-resolver)
31
+
32
+ > $ pygmy up
33
+ LONGDESC
34
+ option :addkey, type: :boolean, default:true
35
+ option :resolver, type: :boolean, default: true
36
+ option :traefik, type: :boolean, default: false
37
+ def up
38
+ exec_up(options)
39
+ end
40
+
41
+ desc 'update', 'Pulls Docker Images and recreates the Containers'
42
+ long_desc <<-LONGDESC
43
+ Runs 'docker pull' on the Docker images in order to get their newest versions.
44
+ After that restarts all containers with removing them, so that the new images are used.
45
+ LONGDESC
46
+ option :resolver, type: :boolean, default: true
47
+ option :traefik, type: :boolean, default: false
48
+ def update
49
+ exec_update
50
+ end
51
+
52
+ desc 'stop', 'Stop all pygmy services'
53
+ long_desc <<-LONGDESC
54
+ Stops all pygmy services. Can optionally pass [-d|--destroy]
55
+ to destroy the containers when they stop.
56
+
57
+ > $ pygmy stop [-d|--destroy]
58
+ LONGDESC
59
+ option :destroy, type: :boolean, aliases: '-d', default: false
60
+ def stop
61
+ exec_stop(options)
62
+ end
63
+
64
+ desc 'down', 'Stop and destroy all pygmy services'
65
+ long_desc <<-LONGDESC
66
+ Stops all pygmy services and destroy the containers when they stop.
67
+
68
+ > $ pygmy down
69
+ LONGDESC
70
+ def down
71
+ exec_stop({:destroy => true})
72
+ end
73
+
74
+ desc 'addkey [~/.ssh/id_rsa]', 'Add additional ssh-key'
75
+ long_desc <<-LONGDESC
76
+ Adds an additional ssh key to the ssh-agent.
77
+ Needs the absolute path to key as an argument
78
+ or uses ~/.ssh/id_rsa if none provided
79
+
80
+ > $ pygmy addkey [~/.ssh/other_key]
81
+ LONGDESC
82
+ def addkey(key = "#{Dir.home}/.ssh/id_rsa")
83
+ add_ssh_key(key)
84
+ end
85
+
86
+ desc 'version', 'Check current installed version of pygmy'
87
+ def version
88
+ puts "Pygmy - Version: #{Pygmy::VERSION}"
89
+ end
90
+
91
+ desc 'restart', 'Stop and restart all pygmy services'
92
+ long_desc <<-LONGDESC
93
+ Stop and restart pygmy services (dnsmasq, resolv, haproxy, mailhog, ssh-agent)
94
+
95
+ > $ pygmy restart [-d|--destroy]
96
+ LONGDESC
97
+ option :destroy, type: :boolean, aliases: '-d', default: false
98
+ option :resolver, type: :boolean, default: true
99
+ option :traefik, type: :boolean, default: false
100
+ def restart
101
+ exec_stop(options)
102
+ exec_up(options)
103
+ end
104
+
105
+ desc 'status', 'Report status of the pygmy services'
106
+ long_desc <<-LONGDESC
107
+ Checks the current status of the services managed by pygmy.
108
+ This includes dnsmasq, mailhog, and resolv
109
+
110
+ > $ pygmy status
111
+ LONGDESC
112
+ def status
113
+ exec_status(options)
114
+ end
115
+
116
+ private
117
+
118
+ def exec_update
119
+ Pygmy::Haproxy.pull
120
+ Pygmy::Mailhog.pull
121
+ Pygmy::SshAgent.pull
122
+ Pygmy::Traefik.pull
123
+ Pygmy::Amazee.pull_all
124
+ puts "Done. Recreating containers...".yellow
125
+ exec_stop({:destroy => true})
126
+ exec_up({})
127
+ end
128
+
129
+ def exec_up(options)
130
+
131
+ if options[:resolver]
132
+ if Pygmy::Dnsmasq.start
133
+ puts "Successfully started dnsmasq".green
134
+ else
135
+ puts "Error starting dnsmasq".red
136
+ end
137
+ end
138
+
139
+ unless options[:traefik]
140
+ if Pygmy::Traefik.running?
141
+ puts "[*] Traefik: Running as docker container #{Pygmy::Traefik.container_name}".red
142
+ elsif Pygmy::Haproxy.start
143
+ puts "Successfully started haproxy".green
144
+ else
145
+ puts "Error starting haproxy".red
146
+ end
147
+ end
148
+
149
+ if options[:traefik]
150
+ if Pygmy::Haproxy.running?
151
+ puts "[*] Haproxy: Running as docker container #{Pygmy::Haproxy.container_name}".red
152
+ elsif Pygmy::Traefik.start
153
+ puts "Successfully started traefik".green
154
+ else
155
+ puts "Error starting traefik".red
156
+ end
157
+ end
158
+
159
+ if Pygmy::DockerNetwork.create
160
+ puts "Successfully created amazeeio network".green
161
+ else
162
+ puts "Error creating amazeeio network".red
163
+ end
164
+
165
+ unless options[:traefik]
166
+ if Pygmy::Haproxy.running?
167
+ if Pygmy::DockerNetwork.connect
168
+ puts "Successfully connected haproxy to amazeeio network".green
169
+ else
170
+ puts "Error connecting haproxy to amazeeio network".red
171
+ end
172
+ end
173
+ end
174
+
175
+ if options[:traefik]
176
+ unless Pygmy::Haproxy.running?
177
+ if Pygmy::Traefik.connect
178
+ puts "Successfully connected traefik to amazeeio network".green
179
+ else
180
+ puts "Error connecting traefik to amazeeio network".red
181
+ end
182
+ end
183
+ end
184
+
185
+ if Pygmy::Mailhog.start
186
+ puts "Successfully started mailhog".green
187
+ else
188
+ puts "Error starting mailhog".red
189
+ end
190
+
191
+ if Pygmy::SshAgent.start
192
+ puts "Successfully started ssh-agent".green
193
+ else
194
+ puts "Error starting ssh-agent".red
195
+ end
196
+
197
+ if options[:resolver]
198
+ if Pygmy::Resolv.configure
199
+ puts "Successfully configured local resolver".green
200
+ else
201
+ puts "Error configuring local resolver".red
202
+ end
203
+ end
204
+
205
+ if options[:addkey]
206
+ if Pygmy::SshAgentAddKey.add_ssh_key
207
+ puts "Successfully injected ssh key".green
208
+ else
209
+ puts "Error injected ssh key".red
210
+ end
211
+ end
212
+ end
213
+
214
+ def exec_status(_options)
215
+
216
+ if Pygmy::Dnsmasq.running?
217
+ puts "[*] Dnsmasq: Running as docker container #{Pygmy::Dnsmasq.container_name}".green
218
+ else
219
+ puts "[*] Dnsmasq is not running".red
220
+ end
221
+
222
+ if Pygmy::Haproxy.running?
223
+ puts "[*] Haproxy: Running as docker container #{Pygmy::Haproxy.container_name}".green
224
+ else
225
+ puts "[*] Haproxy is not running".red
226
+ end
227
+
228
+ if Pygmy::DockerNetwork.exists?
229
+ puts "[*] Network: Exists as name #{Pygmy::DockerNetwork.network_name}".green
230
+ else
231
+ puts "[*] Network does not exist".red
232
+ end
233
+
234
+ if Pygmy::DockerNetwork.haproxy_connected?
235
+ puts "[*] Network: Haproxy #{Pygmy::DockerNetwork.haproxy_name} connected to #{Pygmy::DockerNetwork.network_name}".green
236
+ else
237
+ puts "[*] Haproxy is not connected to #{Pygmy::DockerNetwork.network_name}".red
238
+ end
239
+
240
+ if Pygmy::Traefik.running?
241
+ puts "[*] Traefik: Running as docker container #{Pygmy::Traefik.container_name}".green
242
+ else
243
+ puts "[*] Traefik is not running".red
244
+ end
245
+
246
+ if Pygmy::Traefik.connected?
247
+ puts "[*] Network: Traefik #{Pygmy::Traefik.container_name} connected to #{Pygmy::DockerNetwork.network_name}".green
248
+ else
249
+ puts "[*] Traefik is not connected to #{Pygmy::DockerNetwork.network_name}".red
250
+ end
251
+
252
+ if Pygmy::Mailhog.running?
253
+ puts "[*] Mailhog: Running as docker container #{Pygmy::Mailhog.container_name}".green
254
+ else
255
+ puts "[*] Mailhog is not running".red
256
+ end
257
+
258
+ if Pygmy::Resolv.has_our_nameserver?
259
+ puts "[*] Resolv is properly configured".green
260
+ else
261
+ puts "[*] Resolv is not configured".red
262
+ end
263
+
264
+ if Pygmy::SshAgent.running?
265
+ puts "[*] ssh-agent: Running as docker container #{Pygmy::SshAgent.container_name}, loaded keys:".green
266
+ Pygmy::SshAgentAddKey.show_ssh_keys
267
+ else
268
+ puts "[*] ssh-agent is not running".red
269
+ end
270
+
271
+ end
272
+
273
+
274
+ def add_ssh_key(key)
275
+
276
+ if Pygmy::SshAgent.running?
277
+ if Pygmy::SshAgentAddKey.add_ssh_key(key)
278
+ puts "Successfully added ssh key".green
279
+ else
280
+ puts "Error added ssh key".red
281
+ end
282
+ else
283
+ puts "ssh-agent is not running, cannot add key".red
284
+ end
285
+
286
+ end
287
+
288
+ def exec_stop(options)
289
+ if Pygmy::Resolv.clean
290
+ puts "Resolver removed".green
291
+ else
292
+ puts "Error while removing the resolver".red
293
+ end
294
+
295
+ if Pygmy::Dnsmasq.stop
296
+ puts "Dnsmasq container stopped".green
297
+ if options[:destroy]
298
+ if Pygmy::Dnsmasq.delete
299
+ puts "Dnsmasq container successfully deleted".green
300
+ else
301
+ puts "Dnsmasq container failed to delete".red
302
+ end
303
+ end
304
+ else
305
+ puts "Dnsmasq container failed to stop".red
306
+ end
307
+
308
+ if Pygmy::Mailhog.stop
309
+ puts "Mailhog container stopped".green
310
+ if options[:destroy]
311
+ if Pygmy::Mailhog.delete
312
+ puts "Mailhog container successfully deleted".green
313
+ else
314
+ puts "Mailhog container failed to delete".red
315
+ end
316
+ end
317
+ else
318
+ puts "Mailhog container failed to stop".red
319
+ end
320
+
321
+ if Pygmy::SshAgent.stop
322
+ puts "ssh-agent container stopped".green
323
+ if options[:destroy]
324
+ if Pygmy::SshAgent.delete
325
+ puts "ssh-agent container successfully deleted".green
326
+ else
327
+ puts "ssh-agent container failed to delete".red
328
+ end
329
+ end
330
+ else
331
+ puts "ssh-agent container failed to stop".red
332
+ end
333
+
334
+ if Pygmy::Haproxy.stop
335
+ puts "Haproxy container stopped".green
336
+ if options[:destroy]
337
+ if Pygmy::Haproxy.delete
338
+ puts "Haproxy container successfully deleted".green
339
+ else
340
+ puts "Haproxy container failed to delete".red
341
+ end
342
+ end
343
+ else
344
+ puts "Haproxy container failed to stop".red
345
+ end
346
+
347
+ if Pygmy::Traefik.stop
348
+ puts "Traefik container stopped".green
349
+ if options[:destroy]
350
+ if Pygmy::Traefik.delete
351
+ puts "Traefik container successfully deleted".green
352
+ else
353
+ puts "Traefik container failed to delete".red
354
+ end
355
+ end
356
+ else
357
+ puts "Traefik container failed to stop".red
358
+ end
359
+
360
+ end
361
+ end
362
+
363
+ aliases = {
364
+ 'start' => 'up',
365
+ }
366
+
367
+ if !ARGV.empty? && %w[-v --version].include?(ARGV.first)
368
+ puts "Pygmy - Version: #{Pygmy::VERSION}"
369
+ else
370
+ PygmyBin.start(ARGV.map { |a| aliases.keys.include?(a) ? aliases[a] : a })
371
+ end
@@ -0,0 +1,3 @@
1
+ Gem.find_files('pygmy/**/*.rb').each do |path|
2
+ require path.gsub(/\.rb$/, '') unless path =~ /bot.*cli/
3
+ end
@@ -0,0 +1,49 @@
1
+ require_relative 'docker_service'
2
+
3
+ module Pygmy
4
+ class Amazee
5
+ extend Pygmy::DockerService
6
+
7
+ def self.pull(image_name)
8
+ puts "Pulling Docker Image #{Shellwords.escape(image_name)}".yellow
9
+ pull_cmd = "docker pull #{Shellwords.escape(image_name)}"
10
+ success = Sh.run_command(pull_cmd).success?
11
+ unless success
12
+ raise RuntimeError.new(
13
+ "Failed to update #{self.container_name}. Command #{pull_cmd} failed"
14
+ )
15
+ end
16
+ end
17
+
18
+ def self.ls_cmd
19
+ cmd = 'docker image ls --format "{{.Repository}}:{{.Tag}}"'
20
+ list = Sh.run_command(cmd)
21
+
22
+ # For better handling of containers, we should compare our
23
+ # results against a whitelist instead of preferential
24
+ # treatment of linux pipes.
25
+ containers = list.stdout.split("\n")
26
+ amazee_containers = []
27
+ containers.each do |container|
28
+ # Selectively target amazeeio/* images.
29
+ if container.include?('amazeeio/')
30
+ # Filter out items which we don't want.
31
+ unless container.include?("none") || container.include?("ssh-agent") || container.include?("haproxy")
32
+ amazee_containers.push(container)
33
+ end
34
+ end
35
+ end
36
+ amazee_containers
37
+ end
38
+
39
+ def self.pull_all
40
+ list = self.ls_cmd
41
+ unless list.nil?
42
+ list.each do |image|
43
+ pull(image)
44
+ end
45
+ end
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,28 @@
1
+ require_relative 'docker_service'
2
+
3
+ module Pygmy
4
+ class Dnsmasq
5
+ extend Pygmy::DockerService
6
+
7
+ def self.image_name
8
+ 'andyshinn/dnsmasq:2.75'
9
+ end
10
+
11
+ def self.container_name
12
+ 'amazeeio-dnsmasq'
13
+ end
14
+
15
+ def self.domain
16
+ 'docker.amazee.io'
17
+ end
18
+
19
+ def self.addr
20
+ '127.0.0.1'
21
+ end
22
+
23
+ def self.run_cmd(domain = self.domain, addr = self.addr)
24
+ "docker run -d -p 53:53/tcp -p 53:53/udp --name=#{Shellwords.escape(self.container_name)} " \
25
+ "--cap-add=NET_ADMIN #{Shellwords.escape(self.image_name)} -A /#{Shellwords.escape(domain)}/#{Shellwords.escape(addr)}"
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,74 @@
1
+ require_relative 'docker_service'
2
+
3
+ module Pygmy
4
+ class DockerNetwork
5
+ extend Pygmy::DockerService
6
+
7
+ def self.network_name
8
+ 'amazeeio-network'
9
+ end
10
+
11
+ def self.haproxy_name
12
+ 'amazeeio-haproxy'
13
+ end
14
+
15
+ def self.create_cmd
16
+ "docker network create #{self.network_name}"
17
+ end
18
+
19
+ def self.connect_haproxy_cmd
20
+ "docker network connect #{self.network_name} #{self.haproxy_name}"
21
+ end
22
+
23
+ def self.create
24
+ unless self.exists?
25
+ unless Sh.run_command(self.create_cmd).success?
26
+ raise RuntimeError.new(
27
+ "Failed to create #{self.network_name}. Command #{self.create_cmd} failed"
28
+ )
29
+ end
30
+ end
31
+ self.exists?
32
+ end
33
+
34
+ def self.connect
35
+ unless self.haproxy_connected?
36
+ unless Sh.run_command(self.connect_haproxy_cmd).success?
37
+ raise RuntimeError.new(
38
+ "Failed to connect #{self.haproxy_name} to #{self.network_name}. Command #{self.connect_haproxy_cmd} failed"
39
+ )
40
+ end
41
+ end
42
+ self.haproxy_connected?
43
+ end
44
+
45
+ def self.haproxy_connected?(network_name = self.network_name, haproxy_name = self.haproxy_name)
46
+ !!(self.inspect_containers(network_name) =~ /#{haproxy_name}/)
47
+ end
48
+
49
+ def self.exists?(network_name = self.network_name)
50
+ !!(self.ls =~ /#{network_name}/)
51
+ end
52
+
53
+ def self.inspect_containers(network_name = self.network_name)
54
+ cmd = "docker network inspect #{self.network_name} -f '{{.Containers}}'"
55
+ ret = Sh.run_command(cmd)
56
+ if ret.success?
57
+ return ret.stdout
58
+ else
59
+ raise RuntimeError.new("Failure running command '#{cmd}'")
60
+ end
61
+ end
62
+
63
+ def self.ls
64
+ cmd = "docker network ls"
65
+ ret = Sh.run_command(cmd)
66
+ if ret.success?
67
+ return ret.stdout
68
+ else
69
+ raise RuntimeError.new("Failure running command '#{cmd}'")
70
+ end
71
+ end
72
+
73
+ end
74
+ end
@@ -0,0 +1,70 @@
1
+ require 'shellwords'
2
+
3
+ module Pygmy
4
+ module DockerService
5
+ def start
6
+ unless self.running?
7
+ success = if self.container_exists?
8
+ Sh.run_command(self.start_cmd).success?
9
+ else
10
+ Sh.run_command(self.run_cmd).success?
11
+ end
12
+ unless success
13
+ raise RuntimeError.new(
14
+ "Failed to run #{self.container_name}. Command #{self.run_cmd} failed"
15
+ )
16
+ end
17
+ end
18
+ self.running?
19
+ end
20
+
21
+ def pull
22
+ puts "Pulling Docker Image #{Shellwords.escape(self.image_name)}".yellow
23
+ success = Sh.run_command("docker pull #{Shellwords.escape(self.image_name)}").success?
24
+ unless success
25
+ raise RuntimeError.new(
26
+ "Failed to update #{self.container_name}. Command #{self.pull_cmd} failed"
27
+ )
28
+ end
29
+ end
30
+
31
+ def running?(container_name = self.container_name)
32
+ !!(self.ps =~ /#{container_name}/)
33
+ end
34
+
35
+ def container_exists?(container_name = self.container_name)
36
+ !!(self.ps(true) =~ /#{container_name}/)
37
+ end
38
+
39
+ def ps(all = false)
40
+ cmd = "docker ps#{all ? ' -a' : ''}"
41
+ ret = Sh.run_command(cmd)
42
+ if ret.success?
43
+ return ret.stdout
44
+ else
45
+ raise RuntimeError.new("Failure running command '#{cmd}'")
46
+ end
47
+ end
48
+
49
+ def has_docker_client?
50
+ Sh.run_command('which docker').success?
51
+ end
52
+
53
+ def stop(container_name = self.container_name)
54
+ Sh.run_command("docker stop -t 1 #{Shellwords.escape(container_name)}") if self.running?
55
+ !self.running?
56
+ end
57
+
58
+ def delete(container_name = self.container_name)
59
+ if self.container_exists?
60
+ self.stop if self.running?
61
+ Sh.run_command("docker rm #{Shellwords.escape(container_name)}")
62
+ end
63
+ !self.container_exists?
64
+ end
65
+
66
+ def start_cmd
67
+ "docker start #{Shellwords.escape(self.container_name)}"
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,24 @@
1
+ require_relative 'docker_service'
2
+
3
+ module Pygmy
4
+ class Haproxy
5
+ extend Pygmy::DockerService
6
+
7
+ def self.image_name
8
+ 'amazeeio/haproxy'
9
+ end
10
+
11
+ def self.container_name
12
+ 'amazeeio-haproxy'
13
+ end
14
+
15
+ def self.run_cmd
16
+ "docker run -d " \
17
+ "-p 80:80 -p 443:443 " \
18
+ "--volume=/var/run/docker.sock:/tmp/docker.sock " \
19
+ "--restart=always " \
20
+ "--name=#{Shellwords.escape(self.container_name)} " \
21
+ "#{Shellwords.escape(self.image_name)}"
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,53 @@
1
+ module Pygmy
2
+ module Linux
3
+ def self.bash(command)
4
+ system("bash -c '#{command}'")
5
+ end
6
+
7
+ def self.ubuntu?
8
+ self.bash(self.ubuntu_cmd)
9
+ end
10
+
11
+ def self.fedora?
12
+ self.bash(self.fedora_cmd)
13
+ end
14
+
15
+ def self.arch?
16
+ self.bash(self.arch_cmd)
17
+ end
18
+
19
+ def self.osx?
20
+ self.bash('uname -a | grep "Darwin" > /dev/null')
21
+ end
22
+
23
+ def self.ubuntu_cmd
24
+ %q(
25
+ if $(which lsb_release >/dev/null 2>&1); then
26
+ lsb_release -d | grep --color=auto "Ubuntu" > /dev/null
27
+ else
28
+ uname -a | grep --color=auto "Ubuntu" > /dev/null
29
+ fi
30
+ )
31
+ end
32
+
33
+ def self.fedora_cmd
34
+ %q(
35
+ if $(which lsb_release >/dev/null 2>&1); then
36
+ lsb_release -d | grep --color=auto "Fedora" > /dev/null
37
+ else
38
+ uname -r | grep --color=auto "fc" > /dev/null
39
+ fi
40
+ )
41
+ end
42
+
43
+ def self.arch_cmd
44
+ %q(
45
+ if $(which lsb_release >/dev/null 2>&1); then
46
+ lsb_release -d | grep --color=auto "Arch" > /dev/null
47
+ else
48
+ uname -a | grep --color=auto "ARCH" > /dev/null
49
+ fi
50
+ )
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,33 @@
1
+ require_relative 'docker_service'
2
+
3
+ module Pygmy
4
+ class Mailhog
5
+ extend Pygmy::DockerService
6
+
7
+ def self.image_name
8
+ 'mailhog/mailhog'
9
+ end
10
+
11
+ def self.container_name
12
+ 'mailhog.docker.amazee.io'
13
+ end
14
+
15
+ def self.domain
16
+ 'docker.amazee.io'
17
+ end
18
+
19
+ def self.addr
20
+ '127.0.0.1'
21
+ end
22
+
23
+ def self.run_cmd(domain = self.domain, addr = self.addr)
24
+ "docker run --restart=always -d -p 1025:1025 --expose 80 -u 0 --name=#{Shellwords.escape(self.container_name)} " \
25
+ '-e "MH_UI_BIND_ADDR=0.0.0.0:80" ' \
26
+ '-e "MH_API_BIND_ADDR=0.0.0.0:80" ' \
27
+ '-e "AMAZEEIO=AMAZEEIO" ' \
28
+ "--label traefik.frontend.rule=Host:#{Shellwords.escape(self.container_name)} " \
29
+ "#{Shellwords.escape(self.image_name)}"
30
+ end
31
+ end
32
+ end
33
+
@@ -0,0 +1,99 @@
1
+ require 'colorize'
2
+ require 'tempfile'
3
+ require 'pathname'
4
+
5
+ module Pygmy
6
+ module Resolv
7
+ def self.common_resolv_file
8
+ '/etc/resolv.conf'
9
+ end
10
+
11
+ def self.ubuntu_resolv_file
12
+ #'/etc/resolvconf/resolv.conf.d/base'
13
+ # For now, use the common_resolv_file
14
+ self.common_resolv_file
15
+ end
16
+
17
+ def self.file_comment
18
+ '# added by amazee.io pygmy'
19
+ end
20
+
21
+ def self.nameserver
22
+ "127.0.0.1"
23
+ end
24
+
25
+ def self.file_nameserver_line
26
+ "nameserver #{self.nameserver}"
27
+ end
28
+
29
+ def self.nameserver_contents
30
+ "#{self.file_nameserver_line} #{self.file_comment}"
31
+ end
32
+
33
+ def self.resolv_file
34
+ if Linux.ubuntu?
35
+ return self.ubuntu_resolv_file
36
+ elsif Linux.fedora? || Linux.arch? || File.exist?(self.common_resolv_file)
37
+ return self.common_resolv_file
38
+ else
39
+ raise RuntimeError.new(
40
+ "Unable to determine location of resolv file"
41
+ )
42
+ end
43
+ end
44
+
45
+
46
+ def self.configure
47
+ if Linux.osx?
48
+ return ResolvOsx.create_resolver?
49
+ end
50
+ # we want to be the first nameserver in the list for performance reasons
51
+ # we only want to add the nameserver if it isn't already there
52
+ prev_conts = self.resolv_file_contents
53
+ unless self.contents_has_our_nameserver?(prev_conts)
54
+ if prev_conts =~ /nameserver/
55
+ prev_conts.sub!(/nameserver/, "#{self.nameserver_contents}\nnameserver")
56
+ else
57
+ prev_conts = "#{prev_conts}\n#{self.nameserver_contents}"
58
+ end
59
+ prev_conts.gsub!(/\s+$/, '')
60
+ self.write_to_file(prev_conts)
61
+ end
62
+ self.has_our_nameserver?
63
+ end
64
+
65
+ def self.clean
66
+ if Linux.osx?
67
+ return ResolvOsx.clean?
68
+ end
69
+ prev_conts = self.resolv_file_contents
70
+ if self.contents_has_our_nameserver?(prev_conts)
71
+ prev_conts.gsub!(/#{Regexp.escape(self.nameserver_contents + "\n")}/, '')
72
+ prev_conts.gsub!(/\s+$/, '')
73
+ self.write_to_file(prev_conts)
74
+ end
75
+ !self.has_our_nameserver?
76
+ end
77
+
78
+ def self.write_to_file(contents)
79
+ # have to use this hack cuz we don't run as root :-(
80
+ puts "Requesting sudo to write to #{self.resolv_file}".green
81
+ Bash.run_command("echo -e '#{contents}' | sudo tee #{Shellwords.escape(self.resolv_file)} >/dev/null")
82
+ end
83
+
84
+ def self.resolv_file_contents
85
+ File.read(self.resolv_file)
86
+ end
87
+
88
+ def self.has_our_nameserver?
89
+ if Linux.osx?
90
+ return ResolvOsx.resolver_file_exists?
91
+ end
92
+ self.contents_has_our_nameserver?(self.resolv_file_contents)
93
+ end
94
+
95
+ def self.contents_has_our_nameserver?(contents)
96
+ !!((contents =~ /#{self.file_comment}/) || (contents =~ /#{self.file_nameserver_line}/))
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,60 @@
1
+ require 'colorize'
2
+ require 'tempfile'
3
+ require 'pathname'
4
+
5
+ module Pygmy
6
+ module ResolvOsx
7
+ def self.resolver_dir
8
+ Pathname("/etc/resolver")
9
+ end
10
+
11
+ def self.resolver_file
12
+ "/etc/resolver/docker.amazee.io"
13
+ end
14
+
15
+ def self.create_resolver?
16
+ puts "setting up DNS resolution and loopback alias IP, this may require sudo".green
17
+ unless self.resolver_dir.directory?
18
+ self.system!("creating #{self.resolver_dir}", "sudo", "mkdir", "-p", self.resolver_dir)
19
+ end
20
+ Tempfile.open('amazeeio_pygmy-dnsmasq') do |f|
21
+ f.write(self.resolver_contents)
22
+ f.close
23
+ self.system!("creating #{self.resolver_file}", "sudo", "cp", f.path, self.resolver_file)
24
+ self.system!("creating #{self.resolver_file}", "sudo", "chmod", "644", self.resolver_file)
25
+ end
26
+ self.system!("creating loopback IP alias 172.16.172.16", "sudo", "ifconfig", "lo0", "alias", "172.16.172.16")
27
+ self.system!("restarting mDNSResponder", "sudo", "killall", "mDNSResponder")
28
+ end
29
+
30
+ def self.clean?
31
+ puts "Removing resolver file and loopback alias IP, this may require sudo".green
32
+ begin
33
+ self.system!("removing resolverfile", "sudo", "rm", "-f", self.resolver_file)
34
+ self.system!("removing loopback IP alias 172.16.172.16", "sudo", "ifconfig", "lo0", "-alias", "172.16.172.16")
35
+ system!("restarting mDNSResponder", "sudo", "killall", "mDNSResponder")
36
+ rescue Exception => e
37
+ puts e.message
38
+ end
39
+ end
40
+
41
+ def self.system!(step, *args)
42
+ system(*args.map(&:to_s)) || raise("Error with the #{name} daemon during #{step}")
43
+ end
44
+
45
+ def self.resolver_contents; <<-EOS.gsub(/^ /, '')
46
+ # Generated by amazeeio pygmy
47
+ nameserver 127.0.0.1
48
+ port 53
49
+ EOS
50
+ end
51
+
52
+ def self.resolver_file_contents
53
+ File.read(self.resolver_file) unless !File.file?(self.resolver_file)
54
+ end
55
+
56
+ def self.resolver_file_exists?
57
+ (self.resolver_file_contents == self.resolver_contents)
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,25 @@
1
+ require 'ostruct'
2
+
3
+ module Pygmy
4
+ module Sh
5
+ def self.run_command(command)
6
+ stdout = `#{command}`
7
+ OpenStruct.new({
8
+ success?: $?.exitstatus == 0,
9
+ exitstatus: $?.exitstatus,
10
+ stdout: stdout
11
+ })
12
+ end
13
+ end
14
+
15
+ module Bash
16
+ def self.run_command(command)
17
+ stdout = `bash -c "#{command}"`
18
+ OpenStruct.new({
19
+ success?: $?.exitstatus == 0,
20
+ exitstatus: $?.exitstatus,
21
+ stdout: stdout
22
+ })
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,22 @@
1
+ require_relative 'docker_service'
2
+
3
+ module Pygmy
4
+ class SshAgent
5
+ extend Pygmy::DockerService
6
+
7
+ def self.image_name
8
+ 'amazeeio/ssh-agent'
9
+ end
10
+
11
+ def self.container_name
12
+ 'amazeeio-ssh-agent'
13
+ end
14
+
15
+ def self.run_cmd
16
+ "docker run -d " \
17
+ "--restart=always " \
18
+ "--name=#{Shellwords.escape(self.container_name)} " \
19
+ "#{Shellwords.escape(self.image_name)}"
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,34 @@
1
+ module Pygmy
2
+ class SshAgentAddKey
3
+ def self.image_name
4
+ 'amazeeio/ssh-agent'
5
+ end
6
+
7
+ def self.container_name
8
+ 'amazeeio-ssh-agent-add-key'
9
+ end
10
+
11
+ def self.add_ssh_key(key = "#{Dir.home}/.ssh/id_rsa")
12
+ if File.file?(key)
13
+ system("docker run --rm -it " \
14
+ "--volume=#{key}:/#{key} " \
15
+ "--volumes-from=amazeeio-ssh-agent " \
16
+ "--name=#{Shellwords.escape(self.container_name)} " \
17
+ "#{Shellwords.escape(self.image_name)} " \
18
+ "ssh-add #{key}")
19
+ else
20
+ puts "ssh key: #{key}, does not exist, ignoring...".yellow
21
+ return false
22
+ end
23
+ end
24
+
25
+ def self.show_ssh_keys
26
+ system("docker run --rm -it " \
27
+ "--volumes-from=amazeeio-ssh-agent " \
28
+ "--name=#{Shellwords.escape(self.container_name)} " \
29
+ "#{Shellwords.escape(self.image_name)} " \
30
+ "ssh-add -l")
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,52 @@
1
+ require_relative 'docker_service'
2
+
3
+ module Pygmy
4
+ class Traefik
5
+ extend Pygmy::DockerService
6
+
7
+ def self.image_name
8
+ 'containous/traefik'
9
+ end
10
+
11
+ def self.container_name
12
+ 'traefik.docker.amazee.io'
13
+ end
14
+
15
+ def self.network_name
16
+ 'amazeeio-network'
17
+ end
18
+
19
+ def self.connect_cmd
20
+ "docker network connect #{self.network_name} #{self.container_name}"
21
+ end
22
+
23
+ def self.connected?
24
+ !!(Pygmy::DockerNetwork.inspect_containers(self.network_name) =~ /#{self.container_name}/)
25
+ end
26
+
27
+ def self.connect
28
+ unless self.connected?
29
+ unless Sh.run_command(self.connect_cmd).success?
30
+ raise RuntimeError.new(
31
+ "Failed to connect #{self.container_name} to #{self.network_name}. Command #{self.connect_cmd} failed"
32
+ )
33
+ end
34
+ end
35
+ self.connected?
36
+ end
37
+
38
+ def self.run_cmd
39
+ "docker run -d " \
40
+ "-p 80:80 -p 8080:8080 -p 443:443 " \
41
+ "--restart always " \
42
+ "--volume=/var/run/docker.sock:/var/run/docker.sock " \
43
+ "--name=#{Shellwords.escape(self.container_name)} " \
44
+ "--label traefik.frontend.rule=Host:#{Shellwords.escape(self.container_name)} " \
45
+ "#{Shellwords.escape(self.image_name)} " \
46
+ "--api --docker " \
47
+ '--docker.network=amazeeio-network ' \
48
+ "--docker.domain=docker.amazee.io"
49
+ end
50
+
51
+ end
52
+ end
@@ -0,0 +1,4 @@
1
+ module Pygmy
2
+ VERSION = '0.9.10'
3
+ DATE = '2018-11-19'
4
+ end
metadata ADDED
@@ -0,0 +1,164 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pygmy-traefik
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.10
5
+ platform: ruby
6
+ authors:
7
+ - Michael Schmid
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-11-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: colorize
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.7'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: thor
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.19'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.19'
41
+ - !ruby/object:Gem::Dependency
42
+ name: ptools
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.3'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.4'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.4'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '10.5'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '10.5'
83
+ - !ruby/object:Gem::Dependency
84
+ name: byebug
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '8.2'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '8.2'
97
+ - !ruby/object:Gem::Dependency
98
+ name: codeclimate-test-reporter
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '0.5'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '0.5'
111
+ description: To fully and easy run a local Drupal development system you need more
112
+ then just a docker container with the Drupal running. Default development workflows
113
+ involves running multiple sites at the same time, interacting with other services
114
+ which are authenticated via ssh and more.Pygmy makes usre that the required Docker
115
+ containers are started and that youcomfortably can access the Drupal Containers
116
+ just via the browser.
117
+ email: michael@amazee.io
118
+ executables:
119
+ - pygmy
120
+ extensions: []
121
+ extra_rdoc_files: []
122
+ files:
123
+ - bin/pygmy
124
+ - lib/pygmy.rb
125
+ - lib/pygmy/amazee.rb
126
+ - lib/pygmy/dnsmasq.rb
127
+ - lib/pygmy/docker_network.rb
128
+ - lib/pygmy/docker_service.rb
129
+ - lib/pygmy/haproxy.rb
130
+ - lib/pygmy/linux.rb
131
+ - lib/pygmy/mailhog.rb
132
+ - lib/pygmy/resolv.rb
133
+ - lib/pygmy/resolv_osx.rb
134
+ - lib/pygmy/shell.rb
135
+ - lib/pygmy/ssh_agent.rb
136
+ - lib/pygmy/ssh_agent_add_key.rb
137
+ - lib/pygmy/traefik.rb
138
+ - lib/pygmy/version.rb
139
+ homepage: https://github.com/amazeeio/pygmy
140
+ licenses:
141
+ - MIT
142
+ metadata: {}
143
+ post_install_message:
144
+ rdoc_options: []
145
+ require_paths:
146
+ - lib
147
+ required_ruby_version: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ required_rubygems_version: !ruby/object:Gem::Requirement
153
+ requirements:
154
+ - - ">="
155
+ - !ruby/object:Gem::Version
156
+ version: '0'
157
+ requirements: []
158
+ rubyforge_project:
159
+ rubygems_version: 2.5.2.3
160
+ signing_key:
161
+ specification_version: 4
162
+ summary: pygmy provides the required servies to run the amazee.io Drupal local development
163
+ environment on linux.
164
+ test_files: []