dip 7.3.1 → 7.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 60d7a15f7de7909f0e61a3e3f9ca8112cf2a94cf21bccfb813be9a209f83e2db
4
- data.tar.gz: d9dd72eff516119adb097147dd566ae1688fed731153617e81d16ed8eb9c54a1
3
+ metadata.gz: be7ef96533ac533734f04b61b49864b8db104269813c5dd00d8192d968c0c1dd
4
+ data.tar.gz: 74d31efceda6300bd5f93023f5a108c3a9972d2b4416d0e4433e98f7ec76f61e
5
5
  SHA512:
6
- metadata.gz: 5e7d3fb075dea8f3be052cbcc8bde8083fd9c967dbce8ab852aefc5ba21bc885f787794dbaf81b68bf5a5e282d7272b6a4495ab567df305e70845e1b5dd14d00
7
- data.tar.gz: 07e3051d76cd9a7af8a51422024c6865feb2b2c7cf59f1865a1d162a133d513565c9a4214cfa8441291694ba85a9e8562bb98a95cd392839d5d69a7a90f70982
6
+ metadata.gz: aafe6a31332d687c065c29e34d3c8fdc69bdc6c0507aa4a4c1d3fc1c68d5ded516c4f52e2b7092b34cf585a3ceb9f69ad4a6b764a41863ea090323d5b0a5b2c2
7
+ data.tar.gz: 6d801682b927567b84f07a0f7df75535d35ac1f11a953f286cc9785a8d415d55d5940b72a68365d2cafaa13e02b9aafa01f6f58282a41e2c37546274553fbf74
data/README.md CHANGED
@@ -30,14 +30,15 @@ Dip can be injected into the current shell (ZSH or Bash).
30
30
  eval "$(dip console)"
31
31
  ```
32
32
 
33
+ **IMPORTANT**: Beware of possible collisions with local tools. One particular example is supporting both local and Docker frontend build tools, such as Yarn. If you want some developer to run `yarn` locally and other to use Docker for that, you should either avoid adding the `yarn` command to the `dip.yml` or avoid using the shell integration for hybrid development.
34
+
33
35
  After that we can type commands without `dip` prefix. For example:
34
36
 
35
37
  ```sh
36
38
  <run-command> *any-args
37
39
  compose *any-compose-arg
38
40
  up <service>
39
- build
40
- down
41
+ ktl *any-kubectl-arg
41
42
  provision
42
43
  ```
43
44
 
@@ -79,10 +80,11 @@ Also, you can check out examples at the top.
79
80
 
80
81
  ```yml
81
82
  # Required minimum dip version
82
- version: '7.1'
83
+ version: '7.5'
83
84
 
84
85
  environment:
85
86
  COMPOSE_EXT: development
87
+ STAGE: "staging"
86
88
 
87
89
  compose:
88
90
  files:
@@ -91,6 +93,9 @@ compose:
91
93
  - docker/docker-compose.$DIP_OS.yml
92
94
  project_name: bear
93
95
 
96
+ kubectl:
97
+ namespace: rocket-$STAGE
98
+
94
99
  interaction:
95
100
  shell:
96
101
  description: Open the Bash shell in app's container
@@ -140,6 +145,22 @@ interaction:
140
145
  default_args: db_dev
141
146
  command: psql -h pg -U postgres
142
147
 
148
+ k:
149
+ description: Run commands in Kubernetes cluster
150
+ pod: svc/rocket-app:app-container
151
+ entrypoint: /env-entrypoint
152
+ subcommands:
153
+ bash:
154
+ description: Get a shell to the running container
155
+ command: /bin/bash
156
+ rails:
157
+ description: Run Rails commands
158
+ command: bundle exec rails
159
+ kafka-topics:
160
+ description: Manage Kafka topics
161
+ pod: svc/rocket-kafka
162
+ command: kafka-topics.sh --zookeeper zookeeper:2181
163
+
143
164
  setup_key:
144
165
  description: Copy key
145
166
  service: app
@@ -199,7 +220,13 @@ returned is `/app/sub-project-dir`.
199
220
 
200
221
  Run commands defined within the `interaction` section of dip.yml
201
222
 
202
- By default, a command will be executed using [`docker compose`](https://docs.docker.com/compose/install/) command. If you are still using `docker-compose` binary (i.e., prior to Compose V2 changes), a command would be run through it. You can disable using of Compose V2 by passing an environment variable `DIP_COMPOSE_V2=false dip run`.
223
+ A command will be executed by specified runner. Dip has three types of them:
224
+
225
+ - `docker-compose` runner — used when the `service` option is defined.
226
+ - `kubectl` runner — used when the `pod` option is defined.
227
+ - `local` runner — used when the previous ones are not defined.
228
+
229
+ If you are still using `docker-compose` binary (i.e., prior to Compose V2 changes), a command would be run through it. You can disable using of Compose V2 by passing an environment variable `DIP_COMPOSE_V2=false dip run`.
203
230
 
204
231
  ```sh
205
232
  dip run rails c
@@ -252,7 +279,7 @@ Run commands each by each from `provision` section of dip.yml
252
279
 
253
280
  ### dip compose
254
281
 
255
- Run docker-compose commands that are configured according to the application's dip.yml :
282
+ Run docker-compose commands that are configured according to the application's dip.yml:
256
283
 
257
284
  ```sh
258
285
  dip compose COMMAND [OPTIONS]
@@ -260,6 +287,16 @@ dip compose COMMAND [OPTIONS]
260
287
  dip compose up -d redis
261
288
  ```
262
289
 
290
+ ### dip ktl
291
+
292
+ Run kubectl commands that are configured according to the application's dip.yml:
293
+
294
+ ```sh
295
+ dip ktl COMMAND [OPTIONS]
296
+
297
+ STAGE=some dip ktl get pods
298
+ ```
299
+
263
300
  ### dip ssh
264
301
 
265
302
  Runs ssh-agent container based on https://github.com/whilp/ssh-agent with your ~/.ssh/id_rsa.
data/lib/dip/cli.rb CHANGED
@@ -32,7 +32,7 @@ module Dip
32
32
  end
33
33
  end
34
34
 
35
- stop_on_unknown_option! :run
35
+ stop_on_unknown_option! :run, :ktl
36
36
 
37
37
  desc "version", "dip version"
38
38
  def version
@@ -69,11 +69,26 @@ module Dip
69
69
  end
70
70
 
71
71
  desc "down [OPTIONS]", "Run `docker-compose down` command"
72
+ method_option :help, aliases: "-h", type: :boolean, desc: "Display usage information"
73
+ method_option :all, aliases: "-A", type: :boolean, desc: "Shutdown all running docker-compose projects"
72
74
  def down(*argv)
73
- compose("down", *argv)
75
+ if options[:help]
76
+ invoke :help, ["down"]
77
+ elsif options[:all]
78
+ require_relative "commands/down_all"
79
+ Dip::Commands::DownAll.new.execute
80
+ else
81
+ compose("down", *argv)
82
+ end
74
83
  end
75
84
 
76
- desc "run [OPTIONS] CMD [ARGS]", "Run configured command in a docker-compose service. `run` prefix may be omitted"
85
+ desc "ktl CMD [OPTIONS]", "Run kubectl commands"
86
+ def ktl(*argv)
87
+ require_relative "commands/kubectl"
88
+ Dip::Commands::Kubectl.new(*argv).execute
89
+ end
90
+
91
+ desc "run [OPTIONS] CMD [ARGS]", "Run configured command (`run` prefix may be omitted)"
77
92
  method_option :publish, aliases: "-p", type: :string, repeatable: true,
78
93
  desc: "Publish a container's port(s) to the host"
79
94
  method_option :help, aliases: "-h", type: :boolean, desc: "Display usage information"
@@ -82,7 +97,11 @@ module Dip
82
97
  invoke :help, ["run"]
83
98
  else
84
99
  require_relative "commands/run"
85
- Dip::Commands::Run.new(*argv, publish: options[:publish]).execute
100
+
101
+ Dip::Commands::Run.new(
102
+ *argv,
103
+ **options.to_h.transform_keys!(&:to_sym)
104
+ ).execute
86
105
  end
87
106
  end
88
107
 
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../command"
4
+
5
+ module Dip
6
+ module Commands
7
+ class DownAll < Dip::Command
8
+ def execute
9
+ exec_subprocess(
10
+ "docker rm --volumes $(docker stop $(docker ps --filter 'label=com.docker.compose.project' -q))"
11
+ )
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../command"
4
+
5
+ module Dip
6
+ module Commands
7
+ class Kubectl < Dip::Command
8
+ attr_reader :argv, :config
9
+
10
+ def initialize(*argv)
11
+ @argv = argv
12
+ @config = ::Dip.config.kubectl || {}
13
+ end
14
+
15
+ def execute
16
+ k_argv = cli_options + argv
17
+
18
+ exec_program("kubectl", k_argv)
19
+ end
20
+
21
+ private
22
+
23
+ def cli_options
24
+ %i[namespace].flat_map do |name|
25
+ next unless (value = config[name])
26
+ next unless value.is_a?(String)
27
+
28
+ value = ::Dip.env.interpolate(value).delete_suffix("-")
29
+ ["--#{name.to_s.tr("_", "-")}", value]
30
+ end.compact
31
+ end
32
+ end
33
+ end
34
+ end
@@ -4,13 +4,17 @@ require "shellwords"
4
4
  require_relative "../../../lib/dip/run_vars"
5
5
  require_relative "../command"
6
6
  require_relative "../interaction_tree"
7
- require_relative "compose"
7
+ require_relative "runners/local_runner"
8
+ require_relative "runners/docker_compose_runner"
9
+ require_relative "runners/kubectl_runner"
10
+
11
+ require_relative "kubectl"
8
12
 
9
13
  module Dip
10
14
  module Commands
11
15
  class Run < Dip::Command
12
- def initialize(cmd, *argv, publish: nil)
13
- @publish = publish
16
+ def initialize(cmd, *argv, **options)
17
+ @options = options
14
18
 
15
19
  @command, @argv = InteractionTree
16
20
  .new(Dip.config.interaction)
@@ -22,75 +26,25 @@ module Dip
22
26
  end
23
27
 
24
28
  def execute
25
- if command[:service].nil?
26
- exec_program(command[:command], get_args, shell: command[:shell])
27
- else
28
- Dip::Commands::Compose.new(
29
- command[:compose][:method],
30
- *compose_arguments,
31
- shell: command[:shell]
32
- ).execute
33
- end
29
+ lookup_runner
30
+ .new(command, argv, **options)
31
+ .execute
34
32
  end
35
33
 
36
34
  private
37
35
 
38
- attr_reader :command, :argv, :publish
39
-
40
- def compose_arguments
41
- compose_argv = command[:compose][:run_options].dup
42
-
43
- if command[:compose][:method] == "run"
44
- compose_argv.concat(run_vars)
45
- compose_argv.concat(published_ports)
46
- compose_argv << "--rm"
47
- end
48
-
49
- compose_argv << command.fetch(:service)
50
-
51
- unless (cmd = command[:command]).empty?
52
- if command[:shell]
53
- compose_argv << cmd
54
- else
55
- compose_argv.concat(cmd.shellsplit)
56
- end
57
- end
58
-
59
- compose_argv.concat(get_args)
60
-
61
- compose_argv
62
- end
63
-
64
- def run_vars
65
- run_vars = Dip::RunVars.env
66
- return [] unless run_vars
67
-
68
- run_vars.map { |k, v| ["-e", "#{k}=#{Shellwords.escape(v)}"] }.flatten
69
- end
70
-
71
- def published_ports
72
- if publish.respond_to?(:each)
73
- publish.map { |p| "--publish=#{p}" }
74
- else
75
- []
76
- end
77
- end
36
+ attr_reader :command, :argv, :options
78
37
 
79
- def get_args
80
- if argv.any?
81
- if command[:shell]
82
- [argv.shelljoin]
83
- else
84
- Array(argv)
85
- end
86
- elsif !(default_args = command[:default_args]).empty?
87
- if command[:shell]
88
- default_args.shellsplit
89
- else
90
- Array(default_args)
91
- end
38
+ def lookup_runner
39
+ if (runner = command[:runner])
40
+ camelized_runner = runner.split("_").collect(&:capitalize).join
41
+ Runners.const_get("#{camelized_runner}Runner")
42
+ elsif command[:service]
43
+ Runners::DockerComposeRunner
44
+ elsif command[:pod]
45
+ Runners::KubectlRunner
92
46
  else
93
- []
47
+ Runners::LocalRunner
94
48
  end
95
49
  end
96
50
  end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dip
4
+ module Commands
5
+ module Runners
6
+ class Base
7
+ def initialize(command, argv, **options)
8
+ @command = command
9
+ @argv = argv
10
+ @options = options
11
+ end
12
+
13
+ def execute
14
+ raise NotImplementedError
15
+ end
16
+
17
+ private
18
+
19
+ attr_reader :command, :argv, :options
20
+
21
+ def command_args
22
+ if argv.any?
23
+ if command[:shell]
24
+ [argv.shelljoin]
25
+ else
26
+ Array(argv)
27
+ end
28
+ elsif !(default_args = command[:default_args]).empty?
29
+ if command[:shell]
30
+ default_args.shellsplit
31
+ else
32
+ Array(default_args)
33
+ end
34
+ else
35
+ []
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+ require_relative "../compose"
5
+
6
+ module Dip
7
+ module Commands
8
+ module Runners
9
+ class DockerComposeRunner < Base
10
+ def execute
11
+ Commands::Compose.new(
12
+ command[:compose][:method],
13
+ *compose_arguments,
14
+ shell: command[:shell]
15
+ ).execute
16
+ end
17
+
18
+ private
19
+
20
+ def compose_arguments
21
+ compose_argv = command[:compose][:run_options].dup
22
+
23
+ if command[:compose][:method] == "run"
24
+ compose_argv.concat(run_vars)
25
+ compose_argv.concat(published_ports)
26
+ compose_argv << "--rm"
27
+ end
28
+
29
+ compose_argv << command.fetch(:service)
30
+
31
+ unless (cmd = command[:command]).empty?
32
+ if command[:shell]
33
+ compose_argv << cmd
34
+ else
35
+ compose_argv.concat(cmd.shellsplit)
36
+ end
37
+ end
38
+
39
+ compose_argv.concat(command_args)
40
+
41
+ compose_argv
42
+ end
43
+
44
+ def run_vars
45
+ run_vars = Dip::RunVars.env
46
+ return [] unless run_vars
47
+
48
+ run_vars.map { |k, v| ["-e", "#{k}=#{Shellwords.escape(v)}"] }.flatten
49
+ end
50
+
51
+ def published_ports
52
+ publish = options[:publish]
53
+
54
+ if publish.respond_to?(:each)
55
+ publish.map { |p| "--publish=#{p}" }
56
+ else
57
+ []
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+ require_relative "../kubectl"
5
+
6
+ module Dip
7
+ module Commands
8
+ module Runners
9
+ class KubectlRunner < Base
10
+ def execute
11
+ Commands::Kubectl.new(*kubectl_arguments).execute
12
+ end
13
+
14
+ private
15
+
16
+ def kubectl_arguments
17
+ argv = ["exec", "--tty", "--stdin"]
18
+
19
+ pod, container = command.fetch(:pod).split(":")
20
+ argv.push("--container", container) unless container.nil?
21
+ argv.push(pod, "--")
22
+
23
+ unless (entrypoint = command[:entrypoint]).nil?
24
+ argv << entrypoint
25
+ end
26
+ argv << command.fetch(:command)
27
+ argv.concat(command_args)
28
+
29
+ argv
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+ require_relative "../../command"
5
+
6
+ module Dip
7
+ module Commands
8
+ module Runners
9
+ class LocalRunner < Base
10
+ def execute
11
+ Dip::Command.exec_program(
12
+ command[:command],
13
+ command_args,
14
+ shell: command[:shell]
15
+ )
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
data/lib/dip/config.rb CHANGED
@@ -16,6 +16,7 @@ module Dip
16
16
  CONFIG_DEFAULTS = {
17
17
  environment: {},
18
18
  compose: {},
19
+ kubectl: {},
19
20
  interation: {},
20
21
  provision: []
21
22
  }.freeze
@@ -94,7 +95,7 @@ module Dip
94
95
  config
95
96
  end
96
97
 
97
- %i[environment compose interaction provision].each do |key|
98
+ %i[environment compose kubectl interaction provision].each do |key|
98
99
  define_method(key) do
99
100
  config[key] || (raise config_missing_error(key))
100
101
  end
@@ -58,7 +58,10 @@ module Dip
58
58
  def build_command(entry)
59
59
  {
60
60
  description: entry[:description],
61
+ runner: entry[:runner],
61
62
  service: entry[:service],
63
+ pod: entry[:pod],
64
+ entrypoint: entry[:entrypoint],
62
65
  command: entry[:command].to_s.strip,
63
66
  shell: entry.fetch(:shell, true),
64
67
  default_args: entry[:default_args].to_s.strip,
data/lib/dip/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dip
4
- VERSION = "7.3.1"
4
+ VERSION = "7.5.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dip
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.3.1
4
+ version: 7.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - bibendi
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-05-07 00:00:00.000000000 Z
11
+ date: 2022-11-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -179,10 +179,16 @@ files:
179
179
  - lib/dip/commands/compose.rb
180
180
  - lib/dip/commands/console.rb
181
181
  - lib/dip/commands/dns.rb
182
+ - lib/dip/commands/down_all.rb
183
+ - lib/dip/commands/kubectl.rb
182
184
  - lib/dip/commands/list.rb
183
185
  - lib/dip/commands/nginx.rb
184
186
  - lib/dip/commands/provision.rb
185
187
  - lib/dip/commands/run.rb
188
+ - lib/dip/commands/runners/base.rb
189
+ - lib/dip/commands/runners/docker_compose_runner.rb
190
+ - lib/dip/commands/runners/kubectl_runner.rb
191
+ - lib/dip/commands/runners/local_runner.rb
186
192
  - lib/dip/commands/ssh.rb
187
193
  - lib/dip/config.rb
188
194
  - lib/dip/environment.rb