pygmy-traefik 0.9.10
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 +7 -0
- data/bin/pygmy +371 -0
- data/lib/pygmy.rb +3 -0
- data/lib/pygmy/amazee.rb +49 -0
- data/lib/pygmy/dnsmasq.rb +28 -0
- data/lib/pygmy/docker_network.rb +74 -0
- data/lib/pygmy/docker_service.rb +70 -0
- data/lib/pygmy/haproxy.rb +24 -0
- data/lib/pygmy/linux.rb +53 -0
- data/lib/pygmy/mailhog.rb +33 -0
- data/lib/pygmy/resolv.rb +99 -0
- data/lib/pygmy/resolv_osx.rb +60 -0
- data/lib/pygmy/shell.rb +25 -0
- data/lib/pygmy/ssh_agent.rb +22 -0
- data/lib/pygmy/ssh_agent_add_key.rb +34 -0
- data/lib/pygmy/traefik.rb +52 -0
- data/lib/pygmy/version.rb +4 -0
- metadata +164 -0
checksums.yaml
ADDED
@@ -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
|
data/bin/pygmy
ADDED
@@ -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
|
data/lib/pygmy.rb
ADDED
data/lib/pygmy/amazee.rb
ADDED
@@ -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
|
data/lib/pygmy/linux.rb
ADDED
@@ -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
|
+
|
data/lib/pygmy/resolv.rb
ADDED
@@ -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
|
data/lib/pygmy/shell.rb
ADDED
@@ -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
|
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: []
|