vagrant-service-manager 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.ci/ansible/roles/centos/tasks/main.yml +3 -2
  3. data/.ci/jenkins-execute-script.py +6 -4
  4. data/.gitignore +1 -0
  5. data/.rubocop.yml +13 -0
  6. data/.rubocop_todo.yml +55 -0
  7. data/CHANGELOG.md +22 -1
  8. data/CONTRIBUTING.adoc +6 -6
  9. data/Gemfile +12 -4
  10. data/README.adoc +104 -70
  11. data/Rakefile +235 -66
  12. data/features/box-command.feature +26 -1
  13. data/features/env-command.feature +20 -3
  14. data/features/help-command.feature +4 -1
  15. data/features/install-cli.feature +58 -0
  16. data/features/openshift.feature +2 -1
  17. data/features/service-operation.feature +76 -3
  18. data/features/support/env.rb +26 -10
  19. data/lib/vagrant-service-manager.rb +7 -2
  20. data/lib/vagrant-service-manager/action/setup_network.rb +0 -2
  21. data/lib/vagrant-service-manager/archive_handlers/tar_handler.rb +26 -0
  22. data/lib/vagrant-service-manager/archive_handlers/zip_handler.rb +25 -0
  23. data/lib/vagrant-service-manager/binary_handlers/adb_binary_handler.rb +55 -0
  24. data/lib/vagrant-service-manager/binary_handlers/adb_docker_binary_handler.rb +38 -0
  25. data/lib/vagrant-service-manager/binary_handlers/adb_openshift_binary_handler.rb +49 -0
  26. data/lib/vagrant-service-manager/binary_handlers/binary_handler.rb +119 -0
  27. data/lib/vagrant-service-manager/binary_handlers/cdk_binary_handler.rb +33 -0
  28. data/lib/vagrant-service-manager/binary_handlers/cdk_docker_binary_handler.rb +9 -0
  29. data/lib/vagrant-service-manager/binary_handlers/cdk_openshift_binary_handler.rb +9 -0
  30. data/lib/vagrant-service-manager/command.rb +90 -15
  31. data/lib/vagrant-service-manager/config.rb +8 -8
  32. data/lib/vagrant-service-manager/installer.rb +49 -0
  33. data/lib/vagrant-service-manager/plugin.rb +2 -2
  34. data/lib/vagrant-service-manager/plugin_logger.rb +2 -2
  35. data/lib/vagrant-service-manager/plugin_util.rb +29 -6
  36. data/lib/vagrant-service-manager/service.rb +4 -3
  37. data/lib/vagrant-service-manager/service_base.rb +11 -0
  38. data/lib/vagrant-service-manager/services/docker.rb +29 -29
  39. data/lib/vagrant-service-manager/services/kubernetes.rb +7 -7
  40. data/lib/vagrant-service-manager/services/open_shift.rb +42 -41
  41. data/lib/vagrant-service-manager/version.rb +1 -1
  42. data/locales/en.yml +42 -4
  43. data/plugins/guests/redhat/cap/machine_ip.rb +2 -1
  44. data/plugins/guests/redhat/plugin.rb +1 -1
  45. data/plugins/hosts/darwin/cap/os_arch.rb +11 -0
  46. data/plugins/hosts/darwin/plugin.rb +13 -0
  47. data/plugins/hosts/linux/cap/os_arch.rb +11 -0
  48. data/plugins/hosts/linux/plugin.rb +13 -0
  49. data/plugins/hosts/windows/cap/os_arch.rb +18 -0
  50. data/plugins/hosts/windows/plugin.rb +13 -0
  51. data/test/test_data/docker-1.10.0.tar.gz +0 -0
  52. data/test/test_data/docker-1.11.0.tgz +0 -0
  53. data/test/test_data/docker-1.9.1.zip +0 -0
  54. data/test/test_data/openshift-origin-client-tools-v1.2.0-2e62fab-linux-64bit.tar.gz +0 -0
  55. data/test/test_data/openshift-origin-client-tools-v1.2.0-2e62fab-linux-64bit.zip +0 -0
  56. data/test/test_data/openshift-origin-client-tools-v1.2.0-2e62fab-mac.zip +0 -0
  57. data/test/test_helper.rb +121 -0
  58. data/test/vagrant-service-manager/archive_handler_test.rb +49 -0
  59. data/test/vagrant-service-manager/binary_handlers/adb_docker_binary_handler_test.rb +111 -0
  60. data/test/vagrant-service-manager/binary_handlers/adb_openshift_binary_handler_test.rb +107 -0
  61. data/test/vagrant-service-manager/installer_test.rb +96 -0
  62. data/vagrant-service-manager.gemspec +4 -3
  63. metadata +43 -16
  64. data/TODO +0 -24
  65. data/Vagrantfile +0 -29
  66. data/lib/vagrant-service-manager/os.rb +0 -22
  67. data/vagrant-service-manager.spec +0 -215
data/Rakefile CHANGED
@@ -1,33 +1,40 @@
1
1
  require 'bundler/gem_tasks'
2
2
  require 'rake/clean'
3
+ require 'rake/testtask'
3
4
  require 'cucumber/rake/task'
5
+ require 'rubocop/rake_task'
4
6
  require 'mechanize'
5
7
  require 'fileutils'
6
8
  require 'yaml'
7
9
  require 'launchy'
8
-
9
- CDK_DOWNLOAD_URL='https://access.redhat.com/downloads/content/293/ver=2/rhel---7/2.0.0/x86_64/product-software'
10
- CDK_BOX_BASE_NAME='rhel-cdk-kubernetes-7.2-23.x86_64.vagrant'
11
-
12
- CDK_DOWNLOAD_URL_NIGHTLY='http://cdk-builds.usersys.redhat.com/builds/nightly/latest-build'
13
-
14
- ADB_DOWNLOAD_URL='http://cloud.centos.org/centos/7/atomic/images'
15
- ADB_BOX_BASE_NAME='AtomicDeveloperBundle-2.1.0-CentOS7'
10
+ require 'date'
16
11
 
17
12
  CLOBBER.include('pkg')
18
13
  CLEAN.include('build')
19
14
 
15
+ BOX_DIR = '.boxes'.freeze
16
+
20
17
  task :init do
21
18
  FileUtils.mkdir_p 'build'
22
19
  end
23
20
 
24
- task :clean_for_testing do
25
- FileUtils.rm_rf ['build/aruba', 'build/vagrant.d', 'build/features_report.html']
21
+ desc 'Removes all cached box files'
22
+ task :clean_boxes do
23
+ FileUtils.rmtree '.boxes'
24
+ end
25
+
26
+ RuboCop::RakeTask.new
27
+
28
+ # Default unit test task
29
+ desc 'Run all unit tests'
30
+ Rake::TestTask.new do |t|
31
+ t.pattern = 'test/**/*_test.rb'
32
+ t.libs << 'test'
26
33
  end
27
34
 
28
35
  # Cucumber acceptance test tasks
29
36
  Cucumber::Rake::Task.new(:features)
30
- task :features => [:init, :clean_for_testing]
37
+ task features: [:clean, :init, :get_boxes]
31
38
 
32
39
  namespace :features do
33
40
  desc 'Opens the HTML Cucumber test report'
@@ -36,39 +43,226 @@ namespace :features do
36
43
  end
37
44
  end
38
45
 
39
- desc 'Download latest publicly released / latest nightly build of CDK Vagrant box using the specified provider (default \'virtualbox\', \'false\')'
40
- task :get_cdk, [:provider, :nightly] do |t, args|
41
- provider = args[:provider].nil? ? 'virtualbox' : args[:provider]
42
- use_nightly = args[:nightly].nil? ? false : !!(args[:nightly] =~ /true/)
43
- agent = Mechanize.new
44
- agent.follow_meta_refresh = true
46
+ desc 'Download the required Vagrant boxes for the Cucumber tests'
47
+ task get_boxes: :init do
48
+ box_dir = File.join(File.dirname(__FILE__), BOX_DIR)
45
49
 
46
- if use_nightly
47
- agent.ignore_bad_chunking = true
48
- agent.get(CDK_DOWNLOAD_URL_NIGHTLY) do |page|
49
- page.links.each do |link|
50
- if link.href.match(/.*#{Regexp.quote(provider)}.box$/)
51
- download_dir = File.join(File.dirname(__FILE__), 'build', 'boxes')
52
- unless File.directory?(download_dir)
53
- FileUtils.mkdir_p(download_dir)
54
- end
55
- agent.pluggable_parser.default = Mechanize::Download
56
- puts "Downloading #{CDK_DOWNLOAD_URL_NIGHTLY}/#{link.href}"
57
- agent.get(link.href).save(File.join(download_dir, "cdk-#{provider}.box"))
50
+ requested_providers = ENV.key?('PROVIDER') ? ENV['PROVIDER'].split(',').collect(&:strip) : ['virtualbox']
51
+ requested_boxes = ENV.key?('BOX') ? ENV['BOX'].split(',').collect(&:strip) : ['adb']
52
+ nightly_cdk_builds = ENV.key?('NIGHTLY') ? ENV['NIGHTLY'].eql?('true') : false
53
+
54
+ download_tasks = requested_boxes.map do |box|
55
+ requested_providers.map do |provider|
56
+ case box
57
+ when 'cdk'
58
+ if nightly_cdk_builds
59
+ NightlyCDKDownloader.new(box_dir, provider)
60
+ else
61
+ PublicCDKDownloader.new(box_dir, provider)
58
62
  end
63
+ when 'adb'
64
+ ADBDownloader.new(box_dir, provider)
65
+ else
66
+ raise "Unknown provider #{provider}"
59
67
  end
60
68
  end
61
- else
62
- agent.get(CDK_DOWNLOAD_URL) do |page|
69
+ end.flatten!
70
+
71
+ threads = download_tasks.map do |task|
72
+ Thread.new do
73
+ task.execute
74
+ end
75
+ end
76
+
77
+ while threads.any?(&:alive?)
78
+ pinwheel = %w(| / - \\)
79
+ 4.times do
80
+ print "\b" + pinwheel.rotate!.first
81
+ sleep(0.3)
82
+ end
83
+ end
84
+ end
85
+
86
+ # Helper classes for handling of Vagrant box downloading
87
+ class DownloadTask
88
+ attr_reader :provider
89
+ attr_reader :box_dir
90
+ attr_reader :agent
91
+ attr_reader :meta
92
+
93
+ def initialize(box_dir, provider)
94
+ FileUtils.mkdir_p(box_dir) unless File.directory?(box_dir)
95
+ @box_dir = box_dir
96
+ @provider = provider
97
+
98
+ @meta_file_name = File.join(box_dir, "#{name}-#{provider}.yml")
99
+ @meta = read_meta
100
+
101
+ @agent = Mechanize.new
102
+ @agent.follow_meta_refresh = true
103
+ @agent.ignore_bad_chunking = true
104
+ end
105
+
106
+ def needed?
107
+ true
108
+ end
109
+
110
+ def execute
111
+ download if needed?
112
+ end
113
+
114
+ def download
115
+ end
116
+
117
+ def name
118
+ raise 'Needs to be overridden'
119
+ end
120
+
121
+ def box_file
122
+ File.join(box_dir, "#{name}-#{provider}.box")
123
+ end
124
+
125
+ def read_meta
126
+ if File.exist?(@meta_file_name)
127
+ YAML.load_file(@meta_file_name)
128
+ else
129
+ {}
130
+ end
131
+ end
132
+
133
+ def save_meta
134
+ File.open(@meta_file_name, 'w+') do |file|
135
+ file.write(meta.to_yaml)
136
+ end
137
+ end
138
+ end
139
+
140
+ class ADBDownloader < DownloadTask
141
+ ADB_DOWNLOAD_URL = 'http://cloud.centos.org/centos/7/atomic/images'.freeze
142
+ ADB_BOX_BASE_NAME = 'AtomicDeveloperBundle'.freeze
143
+
144
+ def initialize(box_dir, provider)
145
+ super(box_dir, provider)
146
+ end
147
+
148
+ def needed?
149
+ latest_version = versions[-1]
150
+ if meta.fetch(:current_version, nil).eql?(latest_version) && File.file?(box_file)
151
+ puts "Using existing ADB box (version #{latest_version}) in #{box_dir}"
152
+ return false
153
+ else
154
+ File.delete(box_file) if File.exist?(box_file)
155
+ meta[:current_version] = latest_version
156
+ save_meta
157
+ true
158
+ end
159
+ end
160
+
161
+ def download
162
+ agent.get(ADB_DOWNLOAD_URL) do |page|
163
+ page.links.each do |link|
164
+ next unless link.href =~ /#{Regexp.quote(ADB_BOX_BASE_NAME)}-#{Regexp.quote(@meta[:current_version])}-CentOS7-#{Regexp.quote(provider)}.box/i
165
+ agent.pluggable_parser.default = Mechanize::Download
166
+ puts "Downloading ADB box #{ADB_DOWNLOAD_URL}/#{link.href}"
167
+ agent.get(link.href).save(box_file)
168
+ end
169
+ end
170
+ end
63
171
 
172
+ def name
173
+ 'adb'
174
+ end
175
+
176
+ private
177
+
178
+ def versions
179
+ agent.get(ADB_DOWNLOAD_URL) do |page|
180
+ return page.links.select { |link| link.href =~ /#{Regexp.quote(ADB_BOX_BASE_NAME)}.*/ }
181
+ .map { |link| link.href.match(/^.*-(\d+\.\d+.\d+)-.*/i).captures[0] }
182
+ .uniq
183
+ .sort
184
+ end
185
+ end
186
+ end
187
+
188
+ class NightlyCDKDownloader < DownloadTask
189
+ CDK_DOWNLOAD_URL_NIGHTLY = 'http://cdk-builds.usersys.redhat.com/builds/nightly'.freeze
190
+
191
+ def initialize(box_dir, provider)
192
+ super(box_dir, provider)
193
+ end
194
+
195
+ def needed?
196
+ latest_version = versions[-1]
197
+ if meta.fetch(:current_version, nil).eql?(latest_version) && File.file?(box_file)
198
+ puts "Using existing CDK box (from #{latest_version}) in #{box_dir}"
199
+ return false
200
+ else
201
+ File.delete(box_file) if File.exist?(box_file)
202
+ meta[:current_version] = latest_version
203
+ save_meta
204
+ true
205
+ end
206
+ end
207
+
208
+ def download
209
+ download_base_url = "#{CDK_DOWNLOAD_URL_NIGHTLY}/#{meta[:current_version]}"
210
+ agent.get(download_base_url) do |page|
211
+ page.links.each do |link|
212
+ next unless link.href =~ /.*#{Regexp.quote(provider)}.box$/
213
+ agent.pluggable_parser.default = Mechanize::Download
214
+ puts "Downloading #{download_base_url}/#{link.href}"
215
+ agent.get(link.href).save(box_file)
216
+ end
217
+ end
218
+ end
219
+
220
+ def name
221
+ 'cdk'
222
+ end
223
+
224
+ private
225
+
226
+ def versions
227
+ agent.get(CDK_DOWNLOAD_URL_NIGHTLY) do |page|
228
+ return page.links.select { |link| link.href =~ /\d{1,2}-[a-zA-Z]{3}-\d{4}/ }
229
+ .map { |link| link.href.chomp('/') }
230
+ .sort { |a, b| DateTime.strptime(a, '%d-%b-%Y') <=> DateTime.strptime(b, '%d-%b-%Y') }
231
+ end
232
+ end
233
+ end
234
+
235
+ class PublicCDKDownloader < DownloadTask
236
+ CDK_DOWNLOAD_URL = 'https://access.redhat.com/downloads/content/293/ver=2.1/rhel---7/2.1.0/x86_64/product-software'.freeze
237
+ CDK_BOX_BASE_NAME = 'rhel-cdk-kubernetes-7.2-25.x86_64.vagrant'.freeze
238
+ LATEST_VERSION = 'v. 2.1.0 for x86_64'.freeze
239
+
240
+ def initialize(box_dir, provider)
241
+ super(box_dir, provider)
242
+ end
243
+
244
+ def needed?
245
+ if meta.fetch(:current_version, nil).eql?(LATEST_VERSION) && File.file?(box_file)
246
+ puts "Using existing public releaase CDK box (version #{LATEST_VERSION}) in #{box_dir}"
247
+ return false
248
+ else
249
+ File.delete(box_file) if File.exist?(box_file)
250
+ meta[:current_version] = LATEST_VERSION
251
+ save_meta
252
+ true
253
+ end
254
+ end
255
+
256
+ def download
257
+ agent.get(CDK_DOWNLOAD_URL) do |page|
64
258
  # Submit first form which is the redirect to login page form
65
259
  login_page = page.forms.first.submit
66
260
 
67
261
  # Submit the login form
68
- after_login = login_page.form_with(:name => 'login_form') do |f|
69
- username_field = f.field_with(:id => 'username')
262
+ after_login = login_page.form_with(id: 'kc-form-login') do |f|
263
+ username_field = f.field_with(id: 'username')
70
264
  username_field.value = 'service-manager@mailinator.com'
71
- password_field = f.field_with(:id => 'password')
265
+ password_field = f.field_with(id: 'password')
72
266
  password_field.value = 'service-manager'
73
267
  end.click_button
74
268
 
@@ -76,40 +270,15 @@ task :get_cdk, [:provider, :nightly] do |t, args|
76
270
  download_page = after_login.forms.first.submit
77
271
 
78
272
  download_page.links.each do |link|
79
- if link.href =~ /#{Regexp.quote(CDK_BOX_BASE_NAME)}-#{Regexp.quote(provider)}.box/
80
- download_dir = File.join(File.dirname(__FILE__), 'build', 'boxes')
81
- unless File.directory?(download_dir)
82
- FileUtils.mkdir_p(download_dir)
83
- end
84
- agent.pluggable_parser.default = Mechanize::Download
85
- puts "Downloading #{link.href}"
86
- agent.get(link.href).save(File.join(download_dir, "cdk-#{provider}.box"))
87
- end
273
+ next unless link.href =~ /#{Regexp.quote(CDK_BOX_BASE_NAME)}-#{Regexp.quote(provider)}.box/
274
+ agent.pluggable_parser.default = Mechanize::Download
275
+ puts "Downloading public release CDK #{link.href}"
276
+ agent.get(link.href).save(box_file)
88
277
  end
89
278
  end
90
279
  end
91
- end
92
- task :get_cdk => :init
93
-
94
- desc 'Download ADB Vagrant box using the specified provider (default \'virtualbox\')'
95
- task :get_adb, [:provider] do |t, args|
96
- provider = args[:provider].nil? ? 'virtualbox' : args[:provider]
97
- agent = Mechanize.new
98
- agent.follow_meta_refresh = true
99
- agent.get(ADB_DOWNLOAD_URL) do |page|
100
- page.links.each do |link|
101
- if match = link.href.match(/#{Regexp.quote(ADB_BOX_BASE_NAME)}-(.*).box/)
102
- if match.captures[0].downcase == provider
103
- download_dir = File.join(File.dirname(__FILE__), 'build', 'boxes')
104
- unless File.directory?(download_dir)
105
- FileUtils.mkdir_p(download_dir)
106
- end
107
- agent.pluggable_parser.default = Mechanize::Download
108
- puts "Downloading #{ADB_DOWNLOAD_URL}/#{link.href}"
109
- agent.get(link.href).save(File.join(download_dir, "adb-#{provider}.box"))
110
- end
111
- end
112
- end
280
+
281
+ def name
282
+ 'cdk'
113
283
  end
114
284
  end
115
- task :get_adb => :init
@@ -15,7 +15,7 @@ Feature: Command output from box command
15
15
 
16
16
  Vagrant.configure('2') do |config|
17
17
  config.vm.box = '<box>'
18
- config.vm.box_url = 'file://../boxes/<box>-<provider>.box'
18
+ config.vm.box_url = 'file://../../.boxes/<box>-<provider>.box'
19
19
  config.vm.network :private_network, ip: '<ip>'
20
20
  config.vm.synced_folder '.', '/vagrant', disabled: true
21
21
  config.servicemanager.services = 'docker'
@@ -38,9 +38,34 @@ Feature: Command output from box command
38
38
  -h, --help print this help
39
39
  """
40
40
 
41
+ When I successfully run `bundle exec vagrant service-manager box --help`
42
+ Then the exit status should be 0
43
+ And stdout from "bundle exec vagrant service-manager box --help" should contain:
44
+ """
45
+ Usage: vagrant service-manager box <sub-command> [options]
46
+
47
+ Sub-Command:
48
+ version display version and release information about the running VM
49
+ ip display routable IP address of the running VM
50
+
51
+ Options:
52
+ --script-readable display information in a script readable format
53
+ -h, --help print this help
54
+
55
+ Examples:
56
+ vagrant service-manager box version
57
+ vagrant service-manager box version --script-readable
58
+ vagrant service-manager box ip
59
+ vagrant service-manager box ip --script-readable
60
+ """
61
+
41
62
  When I successfully run `bundle exec vagrant service-manager box ip`
42
63
  Then stdout from "bundle exec vagrant service-manager box ip" should contain "<ip>"
43
64
 
65
+ When I successfully run `bundle exec vagrant service-manager box ip --script-readable`
66
+ Then stdout from "bundle exec vagrant service-manager box ip --script-readable" should contain "IP=<ip>"
67
+ And stdout from "bundle exec vagrant service-manager box ip --script-readable" should be script readable
68
+
44
69
  Examples:
45
70
  | box | provider | ip |
46
71
  | cdk | virtualbox | 10.10.10.42 |
@@ -15,7 +15,7 @@ Feature: Command output from env command
15
15
 
16
16
  Vagrant.configure('2') do |config|
17
17
  config.vm.box = '<box>'
18
- config.vm.box_url = 'file://../boxes/<box>-<provider>.box'
18
+ config.vm.box_url = 'file://../../.boxes/<box>-<provider>.box'
19
19
  config.vm.network :private_network, ip: '<ip>'
20
20
  config.vm.synced_folder '.', '/vagrant', disabled: true
21
21
  config.servicemanager.services = 'docker'
@@ -23,7 +23,24 @@ Feature: Command output from env command
23
23
  """
24
24
 
25
25
  When I successfully run `bundle exec vagrant up --provider <provider>`
26
- And I successfully run `bundle exec vagrant service-manager env`
26
+ And I successfully run `bundle exec vagrant service-manager env --help`
27
+ Then the exit status should be 0
28
+ And stdout from "bundle exec vagrant service-manager env --help" should contain:
29
+ """
30
+ Usage: vagrant service-manager env [object] [options]
31
+
32
+ Objects:
33
+ docker display information and environment variables for docker
34
+ openshift display information and environment variables for openshift
35
+
36
+ If OBJECT is omitted, display the information for all active services
37
+
38
+ Options:
39
+ --script-readable display information in a script readable format.
40
+ -h, --help print this help
41
+ """
42
+
43
+ When I successfully run `bundle exec vagrant service-manager env`
27
44
  Then stdout from "bundle exec vagrant service-manager env" should be evaluable in a shell
28
45
 
29
46
  When I successfully run `bundle exec vagrant service-manager env --script-readable`
@@ -34,7 +51,7 @@ Feature: Command output from env command
34
51
  And stdout from "bundle exec vagrant service-manager env docker" should contain "export DOCKER_HOST=tcp://<ip>:2376"
35
52
  And stdout from "bundle exec vagrant service-manager env docker" should match /export DOCKER_CERT_PATH=.*\/.vagrant\/machines\/cdk\/virtualbox\/docker/
36
53
  And stdout from "bundle exec vagrant service-manager env docker" should contain "export DOCKER_TLS_VERIFY=1"
37
- And stdout from "bundle exec vagrant service-manager env docker" should contain "export DOCKER_API_VERSION=1.21"
54
+ And stdout from "bundle exec vagrant service-manager env docker" should match /export DOCKER_API_VERSION=1.2\d/
38
55
  And stdout from "bundle exec vagrant service-manager env docker" should match /# eval "\$\(vagrant service-manager env docker\)"/
39
56
 
40
57
  When I successfully run `bundle exec vagrant service-manager env docker --script-readable`
@@ -15,7 +15,7 @@ Feature: Command output from help command
15
15
 
16
16
  Vagrant.configure('2') do |config|
17
17
  config.vm.box = '<box>'
18
- config.vm.box_url = 'file://../boxes/<box>-<provider>.box'
18
+ config.vm.box_url = 'file://../../.boxes/<box>-<provider>.box'
19
19
  config.vm.network :private_network, ip: '<ip>'
20
20
  config.vm.synced_folder '.', '/vagrant', disabled: true
21
21
  config.servicemanager.services = 'docker'
@@ -35,6 +35,7 @@ Feature: Command output from help command
35
35
  start starts the given service in the box
36
36
  stop stops the given service in the box
37
37
  status list services and their running state
38
+ install-cli install the client binary for the specified service
38
39
 
39
40
  Options:
40
41
  -h, --help print this help
@@ -54,6 +55,7 @@ Feature: Command output from help command
54
55
  start starts the given service in the box
55
56
  stop stops the given service in the box
56
57
  status list services and their running state
58
+ install-cli install the client binary for the specified service
57
59
 
58
60
  Options:
59
61
  -h, --help print this help
@@ -74,6 +76,7 @@ Feature: Command output from help command
74
76
  start starts the given service in the box
75
77
  stop stops the given service in the box
76
78
  status list services and their running state
79
+ install-cli install the client binary for the specified service
77
80
 
78
81
  Options:
79
82
  -h, --help print this help