dip 3.0.0
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/LICENSE.txt +20 -0
- data/README.md +206 -0
- data/exe/dip +37 -0
- data/lib/dip.rb +36 -0
- data/lib/dip/cli.rb +90 -0
- data/lib/dip/cli/dns.rb +89 -0
- data/lib/dip/cli/nginx.rb +71 -0
- data/lib/dip/cli/ssh.rb +71 -0
- data/lib/dip/command.rb +41 -0
- data/lib/dip/commands/compose.rb +68 -0
- data/lib/dip/commands/dns.rb +64 -0
- data/lib/dip/commands/nginx.rb +50 -0
- data/lib/dip/commands/provision.rb +15 -0
- data/lib/dip/commands/run.rb +63 -0
- data/lib/dip/commands/ssh.rb +52 -0
- data/lib/dip/config.rb +46 -0
- data/lib/dip/environment.rb +51 -0
- data/lib/dip/version.rb +5 -0
- metadata +177 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 6a9ad2527f29216fd1a230c2c8acc9032f08cd1eea686f89df433f8c59be50fb
|
4
|
+
data.tar.gz: d84a3f71b392136dd0d275391ec0c58424b91a00e3ae0a1ea93233ec3a718026
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 99e059244669e8aa9a7ab9393aaad1461231667ef66ce0073ad417462bae8996c9819794e8fba8006ea4fabf6296426b006ae5ff485afb0b92aefaafd5719bf2
|
7
|
+
data.tar.gz: 5497a34f27a83e88f91eadca30dbaf3732f38da9b70c5d7bbfbe994ab3b0293156966bb187c3394120ab35a992995d3ea8b7d1e6e4b7d4384b55e141badfd28e
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2018 bibendi
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,206 @@
|
|
1
|
+
# DIP [](https://travis-ci.org/bibendi/dip)
|
2
|
+
|
3
|
+
Docker Interaction Process
|
4
|
+
|
5
|
+
CLI utility for straightforward provisioning and interacting with an application configured by docker-compose.
|
6
|
+
|
7
|
+
DIP also contains commands for running support containers such as ssh-agent and DNS server.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
```sh
|
12
|
+
gem install dip
|
13
|
+
```
|
14
|
+
|
15
|
+
## Changelog
|
16
|
+
|
17
|
+
https://github.com/bibendi/dip/releases
|
18
|
+
|
19
|
+
|
20
|
+
## Docker installation
|
21
|
+
|
22
|
+
- [Ubuntu](docs/docker-ubuntu-install.md)
|
23
|
+
- [Mac OS](docs/docker-for-mac-install.md)
|
24
|
+
|
25
|
+
## Usage
|
26
|
+
|
27
|
+
```sh
|
28
|
+
dip --help
|
29
|
+
dip SUBCOMMAND --help
|
30
|
+
```
|
31
|
+
|
32
|
+
### dip.yml
|
33
|
+
|
34
|
+
```yml
|
35
|
+
version: '2'
|
36
|
+
|
37
|
+
environment:
|
38
|
+
COMPOSE_EXT: development
|
39
|
+
RAILS_ENV: development
|
40
|
+
|
41
|
+
compose:
|
42
|
+
files:
|
43
|
+
- docker/docker-compose.yml
|
44
|
+
- docker/docker-compose.$COMPOSE_EXT.yml
|
45
|
+
- docker/docker-compose.$DIP_OS.yml
|
46
|
+
project_name: bear-$RAILS_ENV
|
47
|
+
|
48
|
+
interaction:
|
49
|
+
sh:
|
50
|
+
service: foo-app
|
51
|
+
compose_run_options: [no-deps]
|
52
|
+
|
53
|
+
bundle:
|
54
|
+
service: foo-app
|
55
|
+
command: bundle
|
56
|
+
|
57
|
+
rake:
|
58
|
+
service: foo-app
|
59
|
+
command: bundle exec rake
|
60
|
+
|
61
|
+
rspec:
|
62
|
+
service: foo-app
|
63
|
+
environment:
|
64
|
+
RAILS_ENV: test
|
65
|
+
command: bundle exec rspec
|
66
|
+
|
67
|
+
rails:
|
68
|
+
service: foo-app
|
69
|
+
command: bundle exec rails
|
70
|
+
subcommands:
|
71
|
+
s:
|
72
|
+
service: foo-web
|
73
|
+
compose_method: up
|
74
|
+
|
75
|
+
psql:
|
76
|
+
service: foo-app
|
77
|
+
command: psql -h pg -U postgres
|
78
|
+
|
79
|
+
provision:
|
80
|
+
- dip compose up -d foo-pg foo-redis
|
81
|
+
- dip bundle install
|
82
|
+
- dip rake db:migrate
|
83
|
+
```
|
84
|
+
|
85
|
+
### dip run
|
86
|
+
|
87
|
+
Run commands defined within `interaction` section of dip.yml
|
88
|
+
|
89
|
+
```sh
|
90
|
+
dip run rails c
|
91
|
+
dip run rake db:migrate
|
92
|
+
```
|
93
|
+
|
94
|
+
`run` argument can be ommited
|
95
|
+
|
96
|
+
```sh
|
97
|
+
dip rake db:migrate
|
98
|
+
dip VERSION=12352452 rake db:rollback
|
99
|
+
```
|
100
|
+
|
101
|
+
### dip provision
|
102
|
+
|
103
|
+
Run commands each by each from `provision` section of dip.yml
|
104
|
+
|
105
|
+
### dip compose
|
106
|
+
|
107
|
+
Run docker-compose commands that are configured according with application dip.yml
|
108
|
+
|
109
|
+
```sh
|
110
|
+
dip compose COMMAND [OPTIONS]
|
111
|
+
|
112
|
+
dip compose up -d redis
|
113
|
+
```
|
114
|
+
|
115
|
+
### dip ssh
|
116
|
+
|
117
|
+
Runs ssh-agent container based on https://github.com/whilp/ssh-agent with your ~/.ssh/id_rsa.
|
118
|
+
It creates a named volume `ssh_data` with ssh socket.
|
119
|
+
An application's docker-compose.yml should contains environment variable `SSH_AUTH_SOCK=/ssh/auth/sock` and connects to external volume `ssh_data`.
|
120
|
+
|
121
|
+
```sh
|
122
|
+
dip ssh up
|
123
|
+
```
|
124
|
+
|
125
|
+
docker-compose.yml
|
126
|
+
|
127
|
+
```yml
|
128
|
+
services:
|
129
|
+
web:
|
130
|
+
environment:
|
131
|
+
- SSH_AUTH_SOCK=/ssh/auth/sock
|
132
|
+
volumes:
|
133
|
+
- ssh-data:/ssh:ro
|
134
|
+
|
135
|
+
volumes:
|
136
|
+
ssh-data:
|
137
|
+
external:
|
138
|
+
name: ssh_data
|
139
|
+
```
|
140
|
+
|
141
|
+
### dip nginx
|
142
|
+
|
143
|
+
Runs Nginx server container based on [bibendi/nginx-proxy](https://github.com/bibendi/nginx-proxy) image. An application's docker-compose.yml should contains environment variable `VIRTUAL_HOST` and `VIRTUAL_PATH` and connects to external network `frontend`.
|
144
|
+
|
145
|
+
foo-project/docker-compose.yml
|
146
|
+
|
147
|
+
```yml
|
148
|
+
version: '2'
|
149
|
+
|
150
|
+
services:
|
151
|
+
foo-web:
|
152
|
+
image: company/foo_image
|
153
|
+
environment:
|
154
|
+
- VIRTUAL_HOST=*.bar-app.docker
|
155
|
+
- VIRTUAL_PATH=/
|
156
|
+
networks:
|
157
|
+
- default
|
158
|
+
- frontend
|
159
|
+
dns: $DIP_DNS
|
160
|
+
|
161
|
+
networks:
|
162
|
+
frontend:
|
163
|
+
external:
|
164
|
+
name: frontend
|
165
|
+
```
|
166
|
+
|
167
|
+
baz-project/docker-compose.yml
|
168
|
+
|
169
|
+
```yml
|
170
|
+
version: '2'
|
171
|
+
|
172
|
+
services:
|
173
|
+
baz-web:
|
174
|
+
image: company/baz_image
|
175
|
+
environment:
|
176
|
+
- VIRTUAL_HOST=*.bar-app.docker
|
177
|
+
- VIRTUAL_PATH=/api/v1/baz_service,/api/v2/baz_service
|
178
|
+
networks:
|
179
|
+
- default
|
180
|
+
- frontend
|
181
|
+
dns: $DIP_DNS
|
182
|
+
|
183
|
+
networks:
|
184
|
+
frontend:
|
185
|
+
external:
|
186
|
+
name: frontend
|
187
|
+
```
|
188
|
+
|
189
|
+
```sh
|
190
|
+
dip nginx up
|
191
|
+
cd foo-project && dip compose up
|
192
|
+
cd baz-project && dip compose up
|
193
|
+
curl www.bar-app.docker/api/v1/quz
|
194
|
+
curl www.bar-app.docker/api/v1/baz_service/qzz
|
195
|
+
```
|
196
|
+
|
197
|
+
### dip dns
|
198
|
+
|
199
|
+
Runs DNS server container based on https://github.com/aacebedo/dnsdock It used for container to container requests through nginx. An application's docker-compose.yml should define `dns` configuration with environment variable `$DIP_DNS` and connect to external network `frontend`. `$DIP_DNS` will be automatically assigned by dip.
|
200
|
+
|
201
|
+
```sh
|
202
|
+
dip dns up
|
203
|
+
|
204
|
+
cd foo-project
|
205
|
+
dip compose exec foo-web curl http://www.bar-app.docker/api/v1/baz_service
|
206
|
+
```
|
data/exe/dip
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
lib_path = File.expand_path('../lib', __dir__)
|
5
|
+
$LOAD_PATH.unshift(lib_path) unless $LOAD_PATH.include?(lib_path)
|
6
|
+
|
7
|
+
require 'dip'
|
8
|
+
require 'dip/cli'
|
9
|
+
require 'pry-byebug' if Dip.debug?
|
10
|
+
|
11
|
+
Signal.trap('INT') do
|
12
|
+
warn("\n#{caller.join("\n")}: interrupted")
|
13
|
+
exit(1)
|
14
|
+
end
|
15
|
+
|
16
|
+
begin
|
17
|
+
run_vars = []
|
18
|
+
|
19
|
+
ARGV.each do |arg|
|
20
|
+
if !run_vars.frozen? && arg.include?("=")
|
21
|
+
key, val = arg.split("=", 2)
|
22
|
+
run_vars << "#{'--x-dip-run-vars=' if run_vars.empty?}#{key}:#{val}"
|
23
|
+
else
|
24
|
+
run_vars.freeze
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
unless run_vars.empty?
|
29
|
+
ARGV.shift(run_vars.size)
|
30
|
+
ARGV.push(*run_vars)
|
31
|
+
end
|
32
|
+
|
33
|
+
Dip::CLI.start
|
34
|
+
rescue Dip::Error => err
|
35
|
+
puts "ERROR: #{err.message}"
|
36
|
+
exit 1
|
37
|
+
end
|
data/lib/dip.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dip/version"
|
4
|
+
require "dip/config"
|
5
|
+
require "dip/environment"
|
6
|
+
|
7
|
+
module Dip
|
8
|
+
Error = Class.new(StandardError)
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def config_path
|
12
|
+
ENV["DIP_FILE"] || "./dip.yml"
|
13
|
+
end
|
14
|
+
|
15
|
+
def config
|
16
|
+
@config ||= Dip::Config.new(config_path)
|
17
|
+
end
|
18
|
+
|
19
|
+
def env
|
20
|
+
@env ||= Dip::Environment.new(config.environment)
|
21
|
+
end
|
22
|
+
|
23
|
+
def test?
|
24
|
+
ENV["DIP_ENV"] == "test"
|
25
|
+
end
|
26
|
+
|
27
|
+
def debug?
|
28
|
+
ENV["DIP_ENV"] == "debug"
|
29
|
+
end
|
30
|
+
|
31
|
+
def reset!
|
32
|
+
@config = nil
|
33
|
+
@env = nil
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/dip/cli.rb
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'thor'
|
4
|
+
|
5
|
+
module Dip
|
6
|
+
class CLI < Thor
|
7
|
+
class << self
|
8
|
+
def retrieve_command_name(args)
|
9
|
+
meth = args.first.to_sym unless args.empty?
|
10
|
+
args.unshift("run") if meth && ::Dip.config.interaction.key?(meth.to_sym)
|
11
|
+
|
12
|
+
super(args)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Hackery. Take the run method away from Thor so that we can redefine it.
|
16
|
+
def is_thor_reserved_word?(word, type)
|
17
|
+
return false if word == "run"
|
18
|
+
|
19
|
+
super
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
desc 'version', 'dip version'
|
24
|
+
def version
|
25
|
+
require_relative 'version'
|
26
|
+
puts Dip::VERSION
|
27
|
+
end
|
28
|
+
map %w(--version -v) => :version
|
29
|
+
|
30
|
+
desc 'compose CMD [OPTIONS]', 'Run docker-compose commands'
|
31
|
+
method_option :help, aliases: '-h', type: :boolean,
|
32
|
+
desc: 'Display usage information'
|
33
|
+
def compose(cmd, *argv)
|
34
|
+
if options[:help]
|
35
|
+
invoke :help, ['compose']
|
36
|
+
else
|
37
|
+
require_relative 'commands/compose'
|
38
|
+
Dip::Commands::Compose.new(cmd, argv).execute
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
desc 'CMD or dip run CMD [OPTIONS]', 'Run configured command in a docker-compose service'
|
43
|
+
method_option :help, aliases: '-h', type: :boolean,
|
44
|
+
desc: 'Display usage information'
|
45
|
+
method_option :x_dip_run_vars,
|
46
|
+
type: :hash,
|
47
|
+
desc: "Enforce environment variables into container, recommended run like 'dip FOO=bar cmd'"
|
48
|
+
def run(cmd, subcmd = nil, *argv)
|
49
|
+
if options[:help]
|
50
|
+
invoke :help, ['run']
|
51
|
+
else
|
52
|
+
require_relative 'commands/run'
|
53
|
+
Dip::Commands::Run.
|
54
|
+
new(cmd, subcmd, argv,
|
55
|
+
run_vars: options[:x_dip_run_vars]).
|
56
|
+
execute
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
desc "provision", "Execute commands within provision section"
|
61
|
+
method_option :help, aliases: '-h', type: :boolean,
|
62
|
+
desc: 'Display usage information'
|
63
|
+
def provision
|
64
|
+
if options[:help]
|
65
|
+
invoke :help, ['provision']
|
66
|
+
else
|
67
|
+
require_relative 'commands/provision'
|
68
|
+
Dip::Commands::Provision.new.execute
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
desc "ssh", "ssh-agent container commands"
|
73
|
+
def ssh(*args)
|
74
|
+
require_relative 'cli/ssh'
|
75
|
+
Dip::CLI::SSH.start(args)
|
76
|
+
end
|
77
|
+
|
78
|
+
desc "dns", "DNS server for automatic docker container discovery"
|
79
|
+
def dns(*args)
|
80
|
+
require_relative 'cli/dns'
|
81
|
+
Dip::CLI::DNS.start(args)
|
82
|
+
end
|
83
|
+
|
84
|
+
desc "nginx", "Nginx reverse proxy server"
|
85
|
+
def nginx(*args)
|
86
|
+
require_relative 'cli/nginx'
|
87
|
+
Dip::CLI::Nginx.start(args)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
data/lib/dip/cli/dns.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'thor'
|
4
|
+
require_relative "../commands/dns"
|
5
|
+
|
6
|
+
module Dip
|
7
|
+
class CLI
|
8
|
+
# See more https://github.com/aacebedo/dnsdock
|
9
|
+
class DNS < Thor
|
10
|
+
desc "dns up", "Run dnsdock container"
|
11
|
+
method_option :help, aliases: '-h', type: :boolean,
|
12
|
+
desc: 'Display usage information'
|
13
|
+
method_option :name, aliases: '-n', type: :string, default: "dnsdock",
|
14
|
+
desc: 'Container name'
|
15
|
+
method_option :socket, aliases: '-s', type: :string, default: "/var/run/docker.sock",
|
16
|
+
desc: 'Path to docker socket'
|
17
|
+
method_option :net, aliases: '-t', type: :string, default: "frontend",
|
18
|
+
desc: 'Container network name'
|
19
|
+
method_option :publish, aliases: '-p', type: :string, default: "53/udp",
|
20
|
+
desc: 'Container port'
|
21
|
+
method_option :image, aliases: '-i', type: :string, default: "aacebedo/dnsdock:latest-amd64",
|
22
|
+
desc: 'Docker image name'
|
23
|
+
method_option :domain, aliases: '-d', type: :string, default: "docker",
|
24
|
+
desc: 'Top level domain'
|
25
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
26
|
+
def up
|
27
|
+
if options[:help]
|
28
|
+
invoke :help, ['up']
|
29
|
+
else
|
30
|
+
Dip::Commands::DNS::Up.new(
|
31
|
+
name: options.fetch(:name),
|
32
|
+
socket: options.fetch(:socket),
|
33
|
+
net: options.fetch(:net),
|
34
|
+
publish: options.fetch(:publish),
|
35
|
+
image: options.fetch(:image),
|
36
|
+
domain: options.fetch(:domain)
|
37
|
+
).execute
|
38
|
+
end
|
39
|
+
end
|
40
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
41
|
+
|
42
|
+
desc "dns down", "Stop dnsdock container"
|
43
|
+
method_option :help, aliases: '-h', type: :boolean,
|
44
|
+
desc: 'Display usage information'
|
45
|
+
method_option :name, aliases: '-n', type: :string, default: "dnsdock",
|
46
|
+
desc: 'Container name'
|
47
|
+
def down
|
48
|
+
if options[:help]
|
49
|
+
invoke :help, ['down']
|
50
|
+
else
|
51
|
+
Dip::Commands::DNS::Down.new(
|
52
|
+
name: options.fetch(:name)
|
53
|
+
).execute
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
desc "dns restart", "Stop and start dnsdock container"
|
58
|
+
method_option :help, aliases: '-h', type: :boolean,
|
59
|
+
desc: 'Display usage information'
|
60
|
+
def restart(*args)
|
61
|
+
if options[:help]
|
62
|
+
invoke :help, ['restart']
|
63
|
+
else
|
64
|
+
Dip::CLI::DNS.start(["down"] + args)
|
65
|
+
sleep 1
|
66
|
+
Dip::CLI::DNS.start(["up"] + args)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
desc "dns ip", "Get ip address of dnsdock container"
|
71
|
+
method_option :help, aliases: '-h', type: :boolean,
|
72
|
+
desc: 'Display usage information'
|
73
|
+
method_option :name, aliases: '-n', type: :string, default: "dnsdock",
|
74
|
+
desc: 'Container name'
|
75
|
+
method_option :net, aliases: '-t', type: :string, default: "frontend",
|
76
|
+
desc: 'Container network name'
|
77
|
+
def ip
|
78
|
+
if options[:help]
|
79
|
+
invoke :help, ['status']
|
80
|
+
else
|
81
|
+
Dip::Commands::DNS::IP.new(
|
82
|
+
name: options.fetch(:name),
|
83
|
+
net: options.fetch(:net)
|
84
|
+
).execute
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'thor'
|
4
|
+
require_relative "../commands/nginx"
|
5
|
+
|
6
|
+
module Dip
|
7
|
+
class CLI
|
8
|
+
# See more https://github.com/bibendi/nginx-proxy
|
9
|
+
class Nginx < Thor
|
10
|
+
desc "nginx up", "Run nginx container"
|
11
|
+
method_option :help, aliases: '-h', type: :boolean,
|
12
|
+
desc: 'Display usage information'
|
13
|
+
method_option :name, aliases: '-n', type: :string, default: "nginx",
|
14
|
+
desc: 'Container name'
|
15
|
+
method_option :socket, aliases: '-s', type: :string, default: "/var/run/docker.sock",
|
16
|
+
desc: 'Path to docker socket'
|
17
|
+
method_option :net, aliases: '-t', type: :string, default: "frontend",
|
18
|
+
desc: 'Container network name'
|
19
|
+
method_option :publish, aliases: '-p', type: :string, default: "80:80",
|
20
|
+
desc: 'Container port'
|
21
|
+
method_option :image, aliases: '-i', type: :string, default: "bibendi/nginx-proxy:latest",
|
22
|
+
desc: 'Docker image name'
|
23
|
+
method_option :domain, aliases: '-d', type: :string, default: "docker",
|
24
|
+
desc: 'Top level domain'
|
25
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
26
|
+
def up
|
27
|
+
if options[:help]
|
28
|
+
invoke :help, ['up']
|
29
|
+
else
|
30
|
+
Dip::Commands::Nginx::Up.new(
|
31
|
+
name: options.fetch(:name),
|
32
|
+
socket: options.fetch(:socket),
|
33
|
+
net: options.fetch(:net),
|
34
|
+
publish: options.fetch(:publish),
|
35
|
+
image: options.fetch(:image),
|
36
|
+
domain: options.fetch(:domain)
|
37
|
+
).execute
|
38
|
+
end
|
39
|
+
end
|
40
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
41
|
+
|
42
|
+
desc "nginx down", "Stop nginx container"
|
43
|
+
method_option :help, aliases: '-h', type: :boolean,
|
44
|
+
desc: 'Display usage information'
|
45
|
+
method_option :name, aliases: '-n', type: :string, default: "nginx",
|
46
|
+
desc: 'Container name'
|
47
|
+
def down
|
48
|
+
if options[:help]
|
49
|
+
invoke :help, ['down']
|
50
|
+
else
|
51
|
+
Dip::Commands::Nginx::Down.new(
|
52
|
+
name: options.fetch(:name)
|
53
|
+
).execute
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
desc "nginx restart", "Stop and start nginx container"
|
58
|
+
method_option :help, aliases: '-h', type: :boolean,
|
59
|
+
desc: 'Display usage information'
|
60
|
+
def restart(*args)
|
61
|
+
if options[:help]
|
62
|
+
invoke :help, ['restart']
|
63
|
+
else
|
64
|
+
Dip::CLI::Nginx.start(["down"] + args)
|
65
|
+
sleep 1
|
66
|
+
Dip::CLI::Nginx.start(["up"] + args)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/dip/cli/ssh.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'thor'
|
4
|
+
require_relative "../commands/ssh"
|
5
|
+
|
6
|
+
module Dip
|
7
|
+
class CLI
|
8
|
+
class SSH < Thor
|
9
|
+
desc "ssh up", "Run ssh-agent container"
|
10
|
+
method_option :help, aliases: '-h', type: :boolean,
|
11
|
+
desc: 'Display usage information'
|
12
|
+
method_option :key, aliases: '-k', type: :string, default: "$HOME/.ssh/id_rsa",
|
13
|
+
desc: 'Path to ssh key'
|
14
|
+
method_option :volume, aliases: '-v', type: :string, default: "$HOME",
|
15
|
+
desc: 'Mounted docker volume'
|
16
|
+
method_option :interactive, aliases: '-t', type: :boolean, default: true,
|
17
|
+
desc: 'Run in interactive mode'
|
18
|
+
# Backward compatibility
|
19
|
+
method_option :nonteractive, aliases: '-T', type: :boolean,
|
20
|
+
desc: 'Run in noninteractive mode'
|
21
|
+
def up
|
22
|
+
if options[:help]
|
23
|
+
invoke :help, ['up']
|
24
|
+
else
|
25
|
+
Dip::Commands::SSH::Up.new(
|
26
|
+
key: options.fetch(:key),
|
27
|
+
volume: options.fetch(:volume),
|
28
|
+
interactive: options.nonteractive? ? false : options.interactive?
|
29
|
+
).execute
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
map add: :up
|
34
|
+
|
35
|
+
desc "ssh down", "Stop ssh-agent container"
|
36
|
+
method_option :help, aliases: '-h', type: :boolean,
|
37
|
+
desc: 'Display usage information'
|
38
|
+
def down
|
39
|
+
if options[:help]
|
40
|
+
invoke :help, ['down']
|
41
|
+
else
|
42
|
+
Dip::Commands::SSH::Down.new.execute
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
desc "ssh restart", "Stop and start ssh-agent container"
|
47
|
+
method_option :help, aliases: '-h', type: :boolean,
|
48
|
+
desc: 'Display usage information'
|
49
|
+
def restart(*args)
|
50
|
+
if options[:help]
|
51
|
+
invoke :help, ['restart']
|
52
|
+
else
|
53
|
+
Dip::CLI::SSH.start(["down"] + args)
|
54
|
+
sleep 1
|
55
|
+
Dip::CLI::SSH.start(["up"] + args)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
desc "ssh status", "Show status of ssh-agent container"
|
60
|
+
method_option :help, aliases: '-h', type: :boolean,
|
61
|
+
desc: 'Display usage information'
|
62
|
+
def status
|
63
|
+
if options[:help]
|
64
|
+
invoke :help, ['status']
|
65
|
+
else
|
66
|
+
Dip::Commands::SSH::Status.new.execute
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/dip/command.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "forwardable"
|
4
|
+
|
5
|
+
module Dip
|
6
|
+
class Command
|
7
|
+
extend Forwardable
|
8
|
+
|
9
|
+
def_delegators self, :shell, :subshell
|
10
|
+
|
11
|
+
class ExecRunner
|
12
|
+
def self.call(cmd, argv, env: {}, **options)
|
13
|
+
::Process.exec(env, cmd, *argv, options)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class SubshellRunner
|
18
|
+
def self.call(cmd, argv, env: {}, panic: true, **options)
|
19
|
+
return if ::Kernel.system(env, cmd, *argv, options)
|
20
|
+
raise Dip::Error, "Command '#{([cmd] + argv).join(' ')}' executed with error." if panic
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class << self
|
25
|
+
def shell(cmd, argv = [], subshell: false, **options)
|
26
|
+
cmd = Dip.env.interpolate(cmd)
|
27
|
+
argv = argv.map { |arg| Dip.env.interpolate(arg) }
|
28
|
+
|
29
|
+
puts [Dip.env.vars, cmd, argv].inspect if Dip.debug?
|
30
|
+
|
31
|
+
runner = subshell ? SubshellRunner : ExecRunner
|
32
|
+
runner.call(cmd, argv, env: Dip.env.vars, **options)
|
33
|
+
end
|
34
|
+
|
35
|
+
def subshell(*args, **kwargs)
|
36
|
+
kwargs[:subshell] = true
|
37
|
+
shell(*args, **kwargs)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../command'
|
4
|
+
require_relative 'dns'
|
5
|
+
|
6
|
+
module Dip
|
7
|
+
module Commands
|
8
|
+
class Compose < Dip::Command
|
9
|
+
DOCKER_EMBEDDED_DNS = "127.0.0.11"
|
10
|
+
|
11
|
+
def initialize(cmd, argv = [])
|
12
|
+
@cmd = cmd
|
13
|
+
@argv = argv
|
14
|
+
@config = ::Dip.config.compose
|
15
|
+
end
|
16
|
+
|
17
|
+
def execute
|
18
|
+
compose_argv = Array(find_files) + Array(find_project_name)
|
19
|
+
compose_argv << @cmd
|
20
|
+
compose_argv += @argv
|
21
|
+
|
22
|
+
Dip.env["DIP_DNS"] ||= find_dns
|
23
|
+
|
24
|
+
shell("docker-compose", compose_argv)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def find_files
|
30
|
+
return unless (files = @config[:files])
|
31
|
+
|
32
|
+
if files.is_a?(Array)
|
33
|
+
files.each_with_object([]) do |file_name, memo|
|
34
|
+
file_name = ::Dip.env.interpolate(file_name)
|
35
|
+
next unless File.exist?(file_name)
|
36
|
+
|
37
|
+
memo << "--file"
|
38
|
+
memo << file_name
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def find_project_name
|
44
|
+
return unless (project_name = @config[:project_name])
|
45
|
+
|
46
|
+
if project_name.is_a?(String)
|
47
|
+
project_name = ::Dip.env.interpolate(project_name)
|
48
|
+
["--project-name", project_name]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def find_dns
|
53
|
+
name = Dip.env["DNSDOCK_CONTAINER"] || "dnsdock"
|
54
|
+
net = Dip.env["FRONTEND_NETWORK"] || "frontend"
|
55
|
+
|
56
|
+
IO.pipe do |r, w|
|
57
|
+
Dip::Commands::DNS::IP.
|
58
|
+
new(name: name, net: net).
|
59
|
+
execute(out: w, err: File::NULL, panic: false)
|
60
|
+
|
61
|
+
w.close_write
|
62
|
+
ip = r.readlines[0].to_s.strip
|
63
|
+
ip.empty? ? DOCKER_EMBEDDED_DNS : ip
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "shellwords"
|
4
|
+
require_relative '../command'
|
5
|
+
|
6
|
+
module Dip
|
7
|
+
module Commands
|
8
|
+
module DNS
|
9
|
+
class Up < Dip::Command
|
10
|
+
def initialize(name:, socket:, net:, publish:, image:, domain:)
|
11
|
+
@name = name
|
12
|
+
@socket = socket
|
13
|
+
@net = net
|
14
|
+
@publish = publish
|
15
|
+
@image = image
|
16
|
+
@domain = domain
|
17
|
+
end
|
18
|
+
|
19
|
+
def execute
|
20
|
+
subshell("docker", "network create #{@net}".shellsplit, panic: false, err: File::NULL)
|
21
|
+
subshell("docker", "run #{container_args} #{@image} --domain=#{@domain}".shellsplit)
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def container_args
|
27
|
+
result = %w(--detach)
|
28
|
+
result << "--volume #{@socket}:/var/run/docker.sock:ro"
|
29
|
+
result << "--restart always"
|
30
|
+
result << "--publish #{@publish}"
|
31
|
+
result << "--net #{@net}"
|
32
|
+
result << "--name #{@name}"
|
33
|
+
result.join(' ')
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class Down < Dip::Command
|
38
|
+
def initialize(name:)
|
39
|
+
@name = name
|
40
|
+
end
|
41
|
+
|
42
|
+
def execute
|
43
|
+
subshell("docker", "stop #{@name}".shellsplit, panic: false, out: File::NULL, err: File::NULL)
|
44
|
+
subshell("docker", "rm -v #{@name}".shellsplit, panic: false, out: File::NULL, err: File::NULL)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class IP < Dip::Command
|
49
|
+
def initialize(name:, net:)
|
50
|
+
@name = name
|
51
|
+
@net = net
|
52
|
+
end
|
53
|
+
|
54
|
+
def execute(**options)
|
55
|
+
subshell("docker",
|
56
|
+
"inspect " \
|
57
|
+
"--format '{{ .NetworkSettings.Networks.#{@net}.IPAddress }}' " \
|
58
|
+
"#{@name}".shellsplit,
|
59
|
+
**options)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "shellwords"
|
4
|
+
require_relative '../command'
|
5
|
+
|
6
|
+
module Dip
|
7
|
+
module Commands
|
8
|
+
module Nginx
|
9
|
+
class Up < Dip::Command
|
10
|
+
def initialize(name:, socket:, net:, publish:, image:, domain:)
|
11
|
+
@name = name
|
12
|
+
@socket = socket
|
13
|
+
@net = net
|
14
|
+
@publish = publish
|
15
|
+
@image = image
|
16
|
+
@domain = domain
|
17
|
+
end
|
18
|
+
|
19
|
+
def execute
|
20
|
+
subshell("docker", "network create #{@net}".shellsplit, panic: false, err: File::NULL)
|
21
|
+
subshell("docker", "run #{container_args} #{@image}".shellsplit)
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def container_args
|
27
|
+
result = %w(--detach)
|
28
|
+
result << "--volume #{@socket}:/tmp/docker.sock:ro"
|
29
|
+
result << "--restart always"
|
30
|
+
result << "--publish #{@publish}"
|
31
|
+
result << "--net #{@net}"
|
32
|
+
result << "--name #{@name}"
|
33
|
+
result << "--label com.dnsdock.alias=#{@domain}"
|
34
|
+
result.join(' ')
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class Down < Dip::Command
|
39
|
+
def initialize(name:)
|
40
|
+
@name = name
|
41
|
+
end
|
42
|
+
|
43
|
+
def execute
|
44
|
+
subshell("docker", "stop #{@name}".shellsplit, panic: false, out: File::NULL, err: File::NULL)
|
45
|
+
subshell("docker", "rm -v #{@name}".shellsplit, panic: false, out: File::NULL, err: File::NULL)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'shellwords'
|
4
|
+
require_relative '../command'
|
5
|
+
require_relative 'compose'
|
6
|
+
|
7
|
+
module Dip
|
8
|
+
module Commands
|
9
|
+
class Run < Dip::Command
|
10
|
+
def initialize(cmd, subcmd = nil, argv = [], run_vars: nil)
|
11
|
+
@cmd = cmd.to_sym
|
12
|
+
@subcmd = subcmd.to_sym if subcmd
|
13
|
+
@argv = argv
|
14
|
+
@run_vars = run_vars
|
15
|
+
@config = ::Dip.config.interaction
|
16
|
+
end
|
17
|
+
|
18
|
+
# TODO: Refactor
|
19
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
20
|
+
def execute
|
21
|
+
command = @config.fetch(@cmd)
|
22
|
+
command[:subcommands] ||= {}
|
23
|
+
|
24
|
+
if (subcommand = command[:subcommands].fetch(@subcmd, {})).any?
|
25
|
+
subcommand[:command] ||= nil
|
26
|
+
command.merge!(subcommand)
|
27
|
+
elsif @subcmd
|
28
|
+
@argv.unshift(@subcmd.to_s)
|
29
|
+
end
|
30
|
+
|
31
|
+
Dip.env.merge(command[:environment]) if command[:environment]
|
32
|
+
|
33
|
+
compose_method = command.fetch(:compose_method, "run").to_s
|
34
|
+
|
35
|
+
compose_argv = []
|
36
|
+
compose_argv.concat(prepare_compose_run_options(command[:compose_run_options]))
|
37
|
+
compose_argv.concat(run_vars)
|
38
|
+
compose_argv << "--rm" if compose_method == "run"
|
39
|
+
compose_argv << command.fetch(:service).to_s
|
40
|
+
compose_argv += command[:command].to_s.shellsplit
|
41
|
+
compose_argv.concat(@argv)
|
42
|
+
|
43
|
+
Dip::Commands::Compose.new(compose_method, compose_argv).execute
|
44
|
+
end
|
45
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
46
|
+
|
47
|
+
def prepare_compose_run_options(value)
|
48
|
+
return [] unless value
|
49
|
+
|
50
|
+
value.map do |o|
|
51
|
+
o = o.start_with?("-") ? o : "--#{o}"
|
52
|
+
o.shellsplit
|
53
|
+
end.flatten
|
54
|
+
end
|
55
|
+
|
56
|
+
def run_vars
|
57
|
+
return [] unless @run_vars
|
58
|
+
|
59
|
+
@run_vars.map { |k, v| ["-e", "#{k}=#{v}"] }.flatten
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "shellwords"
|
4
|
+
require_relative '../command'
|
5
|
+
|
6
|
+
module Dip
|
7
|
+
module Commands
|
8
|
+
module SSH
|
9
|
+
class Up < Dip::Command
|
10
|
+
def initialize(key:, volume:, interactive:)
|
11
|
+
@key = key
|
12
|
+
@volume = volume
|
13
|
+
@interactive = interactive
|
14
|
+
end
|
15
|
+
|
16
|
+
def execute
|
17
|
+
subshell("docker", "volume create --name ssh_data".shellsplit, out: File::NULL, err: File::NULL)
|
18
|
+
|
19
|
+
subshell("docker", "run --detach --volume ssh_data:/ssh --name=ssh-agent whilp/ssh-agent".shellsplit)
|
20
|
+
|
21
|
+
key = Dip.env.interpolate(@key)
|
22
|
+
subshell("docker", "run #{container_args} whilp/ssh-agent ssh-add #{key}".shellsplit)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def container_args
|
28
|
+
result = %w(--rm)
|
29
|
+
volume = Dip.env.interpolate(@volume)
|
30
|
+
result << "--volume ssh_data:/ssh"
|
31
|
+
result << "--volume #{volume}:#{volume}"
|
32
|
+
result << "--interactive --tty" if @interactive
|
33
|
+
result.join(' ')
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class Down < Dip::Command
|
38
|
+
def execute
|
39
|
+
subshell("docker", "stop ssh-agent".shellsplit, panic: false, out: File::NULL, err: File::NULL)
|
40
|
+
subshell("docker", "rm -v ssh-agent".shellsplit, panic: false, out: File::NULL, err: File::NULL)
|
41
|
+
subshell("docker", "volume rm ssh_data".shellsplit, panic: false, out: File::NULL, err: File::NULL)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class Status < Dip::Command
|
46
|
+
def execute
|
47
|
+
subshell("docker", "inspect --format '{{.State.Status}}' ssh-agent".shellsplit)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/dip/config.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "yaml"
|
4
|
+
require "erb"
|
5
|
+
|
6
|
+
module Dip
|
7
|
+
class Config
|
8
|
+
def initialize(config_path)
|
9
|
+
load_or_default(config_path)
|
10
|
+
end
|
11
|
+
|
12
|
+
def merge(config)
|
13
|
+
@config.merge!(config)
|
14
|
+
end
|
15
|
+
|
16
|
+
def environment
|
17
|
+
@config.fetch(:environment, {})
|
18
|
+
end
|
19
|
+
|
20
|
+
def compose
|
21
|
+
@config.fetch(:compose, {})
|
22
|
+
end
|
23
|
+
|
24
|
+
def interaction
|
25
|
+
@config.fetch(:interaction, {})
|
26
|
+
end
|
27
|
+
|
28
|
+
def provision
|
29
|
+
@config.fetch(:provision, [])
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def load_or_default(config_path)
|
35
|
+
@config ||= if File.exist?(config_path) && !Dip.test?
|
36
|
+
YAML.safe_load(
|
37
|
+
ERB.new(File.read(config_path)).result,
|
38
|
+
[], [], true,
|
39
|
+
symbolize_names: true
|
40
|
+
)
|
41
|
+
else
|
42
|
+
{}
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dip
|
4
|
+
class Environment
|
5
|
+
VAR_REGEX = /\$[\{]?(?<var_name>[a-zA-Z_][a-zA-Z0-9_]*)[\}]?/
|
6
|
+
SPECIAL_VARS = {"DIP_OS" => :find_dip_os}.freeze
|
7
|
+
|
8
|
+
attr_reader :vars
|
9
|
+
|
10
|
+
def initialize(default_vars)
|
11
|
+
@vars = {}
|
12
|
+
|
13
|
+
merge(default_vars)
|
14
|
+
end
|
15
|
+
|
16
|
+
def merge(new_vars)
|
17
|
+
new_vars.each do |key, value|
|
18
|
+
key = key.to_s
|
19
|
+
@vars[key] = ENV.fetch(key) { interpolate(value.to_s) }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def [](name)
|
24
|
+
vars.fetch(name) { ENV[name] }
|
25
|
+
end
|
26
|
+
|
27
|
+
def []=(key, value)
|
28
|
+
@vars[key] = value
|
29
|
+
end
|
30
|
+
|
31
|
+
def interpolate(value)
|
32
|
+
value.gsub(VAR_REGEX) do
|
33
|
+
var_name = Regexp.last_match[:var_name]
|
34
|
+
|
35
|
+
if SPECIAL_VARS.key?(var_name)
|
36
|
+
self[var_name] || send(SPECIAL_VARS[var_name])
|
37
|
+
else
|
38
|
+
self[var_name]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
alias replace interpolate
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def find_dip_os
|
48
|
+
@dip_os ||= Gem::Platform.local.os
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/dip/version.rb
ADDED
metadata
ADDED
@@ -0,0 +1,177 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dip
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 3.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- bibendi
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-09-25 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: thor
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.20.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.20.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.16'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.16'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: pry-byebug
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '10.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '10.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '3.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rubocop
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0.59'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0.59'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: simplecov
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0.16'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0.16'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: test-unit
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '3'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '3'
|
125
|
+
description: DIP - Docker Interaction Process.CLI tool for better development experience
|
126
|
+
when interacting with docker and docker-compose.
|
127
|
+
email:
|
128
|
+
- merkushin.m.s@gmail.com
|
129
|
+
executables:
|
130
|
+
- dip
|
131
|
+
extensions: []
|
132
|
+
extra_rdoc_files: []
|
133
|
+
files:
|
134
|
+
- LICENSE.txt
|
135
|
+
- README.md
|
136
|
+
- exe/dip
|
137
|
+
- lib/dip.rb
|
138
|
+
- lib/dip/cli.rb
|
139
|
+
- lib/dip/cli/dns.rb
|
140
|
+
- lib/dip/cli/nginx.rb
|
141
|
+
- lib/dip/cli/ssh.rb
|
142
|
+
- lib/dip/command.rb
|
143
|
+
- lib/dip/commands/compose.rb
|
144
|
+
- lib/dip/commands/dns.rb
|
145
|
+
- lib/dip/commands/nginx.rb
|
146
|
+
- lib/dip/commands/provision.rb
|
147
|
+
- lib/dip/commands/run.rb
|
148
|
+
- lib/dip/commands/ssh.rb
|
149
|
+
- lib/dip/config.rb
|
150
|
+
- lib/dip/environment.rb
|
151
|
+
- lib/dip/version.rb
|
152
|
+
homepage: https://github.com/bibendi/dip
|
153
|
+
licenses:
|
154
|
+
- MIT
|
155
|
+
metadata:
|
156
|
+
allowed_push_host: https://rubygems.org/
|
157
|
+
post_install_message:
|
158
|
+
rdoc_options: []
|
159
|
+
require_paths:
|
160
|
+
- lib
|
161
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
162
|
+
requirements:
|
163
|
+
- - ">="
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '0'
|
166
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
167
|
+
requirements:
|
168
|
+
- - ">="
|
169
|
+
- !ruby/object:Gem::Version
|
170
|
+
version: '0'
|
171
|
+
requirements: []
|
172
|
+
rubyforge_project:
|
173
|
+
rubygems_version: 2.7.6
|
174
|
+
signing_key:
|
175
|
+
specification_version: 4
|
176
|
+
summary: Ruby gem CLI tool for better interacting docker-compose files.
|
177
|
+
test_files: []
|