dip 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 [![Build Status](https://travis-ci.org/bibendi/dip.svg?branch=master)](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: []
|