kontena-cli 1.4.0.pre6 → 1.4.0.pre7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/VERSION +1 -1
- data/bin/kontena +1 -1
- data/kontena-cli.gemspec +3 -3
- data/lib/kontena/cli/certificate/authorize_command.rb +67 -6
- data/lib/kontena/cli/certificate/get_command.rb +7 -0
- data/lib/kontena/cli/certificate/list_command.rb +75 -0
- data/lib/kontena/cli/certificate/register_command.rb +13 -2
- data/lib/kontena/cli/certificate/request_command.rb +20 -0
- data/lib/kontena/cli/certificate/show_command.rb +19 -0
- data/lib/kontena/cli/certificate_command.rb +4 -1
- data/lib/kontena/cli/cloud/master/add_command.rb +1 -1
- data/lib/kontena/cli/common.rb +21 -33
- data/lib/kontena/cli/etcd/health_command.rb +21 -27
- data/lib/kontena/cli/helpers/exec_helper.rb +15 -6
- data/lib/kontena/cli/helpers/health_helper.rb +12 -0
- data/lib/kontena/cli/helpers/log_helper.rb +2 -2
- data/lib/kontena/cli/helpers/time_helper.rb +29 -0
- data/lib/kontena/cli/master/init_cloud_command.rb +19 -0
- data/lib/kontena/cli/master/list_command.rb +1 -1
- data/lib/kontena/cli/master/ssh_command.rb +3 -1
- data/lib/kontena/cli/master/use_command.rb +1 -2
- data/lib/kontena/cli/node_command.rb +1 -0
- data/lib/kontena/cli/nodes/health_command.rb +28 -13
- data/lib/kontena/cli/nodes/list_command.rb +19 -3
- data/lib/kontena/cli/nodes/show_command.rb +4 -2
- data/lib/kontena/cli/nodes/ssh_command.rb +5 -2
- data/lib/kontena/cli/nodes/update_command.rb +2 -0
- data/lib/kontena/cli/plugins/install_command.rb +11 -8
- data/lib/kontena/cli/plugins/list_command.rb +5 -3
- data/lib/kontena/cli/plugins/search_command.rb +4 -2
- data/lib/kontena/cli/plugins/show_command.rb +17 -0
- data/lib/kontena/cli/plugins/uninstall_command.rb +9 -13
- data/lib/kontena/cli/registry/create_command.rb +1 -1
- data/lib/kontena/cli/services/create_command.rb +6 -0
- data/lib/kontena/cli/services/services_helper.rb +33 -6
- data/lib/kontena/cli/services/update_command.rb +6 -0
- data/lib/kontena/cli/stacks/build_command.rb +3 -3
- data/lib/kontena/cli/stacks/common.rb +105 -90
- data/lib/kontena/cli/stacks/deploy_command.rb +7 -3
- data/lib/kontena/cli/stacks/install_command.rb +39 -6
- data/lib/kontena/cli/stacks/list_command.rb +36 -4
- data/lib/kontena/cli/stacks/logs_command.rb +9 -2
- data/lib/kontena/cli/stacks/registry/pull_command.rb +2 -2
- data/lib/kontena/cli/stacks/registry/push_command.rb +20 -9
- data/lib/kontena/cli/stacks/registry/remove_command.rb +4 -4
- data/lib/kontena/cli/stacks/registry/show_command.rb +4 -4
- data/lib/kontena/cli/stacks/remove_command.rb +27 -1
- data/lib/kontena/cli/stacks/service_generator.rb +12 -2
- data/lib/kontena/cli/stacks/show_command.rb +35 -5
- data/lib/kontena/cli/stacks/stack_name.rb +71 -0
- data/lib/kontena/cli/stacks/upgrade_command.rb +127 -14
- data/lib/kontena/cli/stacks/validate_command.rb +38 -10
- data/lib/kontena/cli/stacks/yaml/custom_validators/certificates_validator.rb +22 -0
- data/lib/kontena/cli/stacks/yaml/opto/prompt_resolver.rb +1 -2
- data/lib/kontena/cli/stacks/yaml/reader.rb +211 -185
- data/lib/kontena/cli/stacks/yaml/service_extender.rb +6 -12
- data/lib/kontena/cli/stacks/yaml/stack_file_loader.rb +97 -0
- data/lib/kontena/cli/stacks/yaml/stack_file_loader/file_loader.rb +41 -0
- data/lib/kontena/cli/stacks/yaml/stack_file_loader/registry_loader.rb +24 -0
- data/lib/kontena/cli/stacks/yaml/stack_file_loader/uri_loader.rb +23 -0
- data/lib/kontena/cli/stacks/yaml/validations.rb +16 -0
- data/lib/kontena/cli/stacks/yaml/validator_v3.rb +25 -8
- data/lib/kontena/client.rb +2 -2
- data/lib/kontena/command.rb +11 -0
- data/lib/kontena/main_command.rb +3 -1
- data/lib/kontena/plugin_manager.rb +11 -198
- data/lib/kontena/plugin_manager/cleaner.rb +33 -0
- data/lib/kontena/plugin_manager/common.rb +86 -0
- data/lib/kontena/plugin_manager/installer.rb +54 -0
- data/lib/kontena/plugin_manager/loader.rb +93 -0
- data/lib/kontena/plugin_manager/rubygems_client.rb +42 -23
- data/lib/kontena/plugin_manager/uninstaller.rb +34 -0
- data/lib/kontena/util.rb +24 -0
- data/lib/kontena_cli.rb +1 -0
- data/omnibus/config/projects/kontena.rb +7 -1
- data/omnibus/config/software/{kontena.rb → kontena-cli.rb} +2 -0
- data/spec/fixtures/api/node.json +2 -1
- data/spec/fixtures/stack-internal-extend.yml +6 -1
- data/spec/fixtures/stack-with-dependencies-dep-1-1.yml +8 -0
- data/spec/fixtures/stack-with-dependencies-dep-1.yml +17 -0
- data/spec/fixtures/stack-with-dependencies-dep-2.yml +8 -0
- data/spec/fixtures/stack-with-dependencies-dep-3.yml +5 -0
- data/spec/fixtures/stack-with-dependencies-dep_2-removed.yml +17 -0
- data/spec/fixtures/stack-with-dependencies-dep_3-added.yml +25 -0
- data/spec/fixtures/stack-with-dependencies.yml +22 -0
- data/spec/fixtures/stack-with-variables.yml +3 -0
- data/spec/kontena/cli/etcd/health_command_spec.rb +45 -33
- data/spec/kontena/cli/helpers/exec_helper_spec.rb +2 -1
- data/spec/kontena/cli/master/init_cloud_command_spec.rb +14 -0
- data/spec/kontena/cli/nodes/health_command_spec.rb +74 -10
- data/spec/kontena/cli/nodes/list_command_spec.rb +381 -232
- data/spec/kontena/cli/nodes/show_command_spec.rb +31 -0
- data/spec/kontena/cli/nodes/ssh_command_spec.rb +18 -3
- data/spec/kontena/cli/plugins/install_command_spec.rb +1 -1
- data/spec/kontena/cli/stacks/build_command_spec.rb +6 -12
- data/spec/kontena/cli/stacks/common_spec.rb +42 -69
- data/spec/kontena/cli/stacks/install_command_spec.rb +57 -31
- data/spec/kontena/cli/stacks/list_command_spec.rb +44 -0
- data/spec/kontena/cli/stacks/logs_command_spec.rb +12 -1
- data/spec/kontena/cli/stacks/remove_command_spec.rb +39 -0
- data/spec/kontena/cli/stacks/show_command_spec.rb +16 -0
- data/spec/kontena/cli/stacks/stack_name_spec.rb +21 -0
- data/spec/kontena/cli/stacks/upgrade_command_spec.rb +73 -56
- data/spec/kontena/cli/stacks/validate_command_spec.rb +81 -0
- data/spec/kontena/cli/stacks/yaml/custom_validators/affinities_validator_spec.rb +22 -0
- data/spec/kontena/cli/stacks/yaml/reader_spec.rb +173 -169
- data/spec/kontena/cli/stacks/yaml/service_extender_spec.rb +12 -3
- data/spec/kontena/cli/stacks/yaml/stack_file_loader/file_loader_spec.rb +47 -0
- data/spec/kontena/cli/stacks/yaml/stack_file_loader/registry_loader_spec.rb +53 -0
- data/spec/kontena/cli/stacks/yaml/stack_file_loader/uri_loader_spec.rb +53 -0
- data/spec/kontena/cli/stacks/yaml/stack_file_loader_spec.rb +104 -0
- data/spec/kontena/cli/stacks/yaml/validator_v3_spec.rb +19 -0
- data/spec/kontena/plugin_manager/cleaner_spec.rb +20 -0
- data/spec/kontena/plugin_manager/common_spec.rb +39 -0
- data/spec/kontena/plugin_manager/installer_spec.rb +50 -0
- data/spec/kontena/plugin_manager/loader_spec.rb +5 -0
- data/spec/kontena/plugin_manager/rubygems_client_spec.rb +11 -25
- data/spec/kontena/plugin_manager/uninstaller_spec.rb +19 -0
- data/spec/kontena/plugin_manager_spec.rb +7 -7
- metadata +64 -97
- data/lib/kontena/cli/app_command.rb +0 -22
- data/lib/kontena/cli/apps/build_command.rb +0 -28
- data/lib/kontena/cli/apps/common.rb +0 -172
- data/lib/kontena/cli/apps/config_command.rb +0 -25
- data/lib/kontena/cli/apps/deploy_command.rb +0 -137
- data/lib/kontena/cli/apps/docker_compose_generator.rb +0 -61
- data/lib/kontena/cli/apps/docker_helper.rb +0 -80
- data/lib/kontena/cli/apps/dockerfile_generator.rb +0 -16
- data/lib/kontena/cli/apps/init_command.rb +0 -89
- data/lib/kontena/cli/apps/kontena_yml_generator.rb +0 -105
- data/lib/kontena/cli/apps/list_command.rb +0 -59
- data/lib/kontena/cli/apps/logs_command.rb +0 -37
- data/lib/kontena/cli/apps/monitor_command.rb +0 -93
- data/lib/kontena/cli/apps/remove_command.rb +0 -74
- data/lib/kontena/cli/apps/restart_command.rb +0 -39
- data/lib/kontena/cli/apps/scale_command.rb +0 -33
- data/lib/kontena/cli/apps/service_generator.rb +0 -114
- data/lib/kontena/cli/apps/service_generator_v2.rb +0 -27
- data/lib/kontena/cli/apps/show_command.rb +0 -23
- data/lib/kontena/cli/apps/start_command.rb +0 -40
- data/lib/kontena/cli/apps/stop_command.rb +0 -40
- data/lib/kontena/cli/apps/yaml/custom_validators/affinities_validator.rb +0 -19
- data/lib/kontena/cli/apps/yaml/custom_validators/build_validator.rb +0 -22
- data/lib/kontena/cli/apps/yaml/custom_validators/extends_validator.rb +0 -20
- data/lib/kontena/cli/apps/yaml/custom_validators/hooks_validator.rb +0 -54
- data/lib/kontena/cli/apps/yaml/custom_validators/secrets_validator.rb +0 -22
- data/lib/kontena/cli/apps/yaml/reader.rb +0 -213
- data/lib/kontena/cli/apps/yaml/service_extender.rb +0 -77
- data/lib/kontena/cli/apps/yaml/validations.rb +0 -71
- data/lib/kontena/cli/apps/yaml/validator.rb +0 -38
- data/lib/kontena/cli/apps/yaml/validator_v2.rb +0 -53
- data/spec/fixtures/app.json +0 -42
- data/spec/fixtures/health.yml +0 -26
- data/spec/fixtures/kontena-build.yml +0 -16
- data/spec/fixtures/kontena-internal-extend.yml +0 -8
- data/spec/fixtures/kontena-invalid.yml +0 -4
- data/spec/fixtures/kontena-with-env-file.yml +0 -18
- data/spec/fixtures/kontena-with-variables.yml +0 -19
- data/spec/fixtures/kontena.yml +0 -17
- data/spec/fixtures/kontena_build_v2.yml +0 -26
- data/spec/fixtures/kontena_numeric_version.yml +0 -9
- data/spec/fixtures/kontena_v2.yml +0 -35
- data/spec/fixtures/mysql.yml +0 -3
- data/spec/fixtures/wordpress-scaled.yml +0 -3
- data/spec/fixtures/wordpress.yml +0 -2
- data/spec/kontena/cli/app/build_command_spec.rb +0 -55
- data/spec/kontena/cli/app/common_spec.rb +0 -110
- data/spec/kontena/cli/app/config_command_spec.rb +0 -78
- data/spec/kontena/cli/app/deploy_command_spec.rb +0 -217
- data/spec/kontena/cli/app/docker_helper_spec.rb +0 -155
- data/spec/kontena/cli/app/init_command_spec.rb +0 -109
- data/spec/kontena/cli/app/logs_command_spec.rb +0 -131
- data/spec/kontena/cli/app/scale_spec.rb +0 -51
- data/spec/kontena/cli/app/service_generator_spec.rb +0 -384
- data/spec/kontena/cli/app/service_generator_v2_spec.rb +0 -73
- data/spec/kontena/cli/app/yaml/reader_spec.rb +0 -457
- data/spec/kontena/cli/app/yaml/service_extender_spec.rb +0 -127
- data/spec/kontena/cli/app/yaml/validator_spec.rb +0 -380
- data/spec/kontena/cli/app/yaml/validator_v2_spec.rb +0 -301
@@ -6,12 +6,14 @@ describe Kontena::Cli::Stacks::RemoveCommand do
|
|
6
6
|
|
7
7
|
describe '#execute' do
|
8
8
|
it 'sends remove command to master' do
|
9
|
+
allow(subject).to receive(:fetch_stack).and_return({})
|
9
10
|
allow(subject).to receive(:wait_stack_removal)
|
10
11
|
expect(client).to receive(:delete).with('stacks/test-grid/test-stack')
|
11
12
|
subject.run(['--force', 'test-stack'])
|
12
13
|
end
|
13
14
|
|
14
15
|
it 'waits until service is removed' do
|
16
|
+
allow(subject).to receive(:fetch_stack).and_return({})
|
15
17
|
allow(client).to receive(:delete).with('stacks/test-grid/test-stack')
|
16
18
|
expect(client).to receive(:get).with('stacks/test-grid/test-stack')
|
17
19
|
.and_raise(Kontena::Errors::StandardError.new(404, 'Not Found'))
|
@@ -19,6 +21,7 @@ describe Kontena::Cli::Stacks::RemoveCommand do
|
|
19
21
|
end
|
20
22
|
|
21
23
|
it 'raises exception on server error' do
|
24
|
+
allow(subject).to receive(:fetch_stack).and_return({})
|
22
25
|
expect(client).to receive(:delete).with('stacks/test-grid/test-stack')
|
23
26
|
expect(client).to receive(:get).with('stacks/test-grid/test-stack')
|
24
27
|
.and_raise(Kontena::Errors::StandardError.new(500, 'internal error'))
|
@@ -26,5 +29,41 @@ describe Kontena::Cli::Stacks::RemoveCommand do
|
|
26
29
|
subject.run(['--force', 'test-stack'])
|
27
30
|
}.to exit_with_error
|
28
31
|
end
|
32
|
+
|
33
|
+
describe 'with stack dependencies' do
|
34
|
+
context 'when stack has a parent' do
|
35
|
+
let(:stack_response_with_parent) do
|
36
|
+
{ 'parent' => { 'name' => 'foofoo' } }
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'warns' do
|
40
|
+
expect(client).to receive(:get).with('stacks/test-grid/test-stack').and_return(
|
41
|
+
stack_response_with_parent
|
42
|
+
)
|
43
|
+
expect(subject).to receive(:confirm_command).and_raise "foo"
|
44
|
+
expect{subject.run(['test-stack'])}.to exit_with_error.and output(/depends on/).to_stdout
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'when stack has children' do
|
49
|
+
let(:stack_response_with_children) do
|
50
|
+
{ 'children' => [ { 'name' => 'foofoo' }, { 'name' => 'foobar' } ] }
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'removes the children' do
|
54
|
+
allow(subject).to receive(:wait_stack_removal)
|
55
|
+
|
56
|
+
expect(client).to receive(:get).with('stacks/test-grid/test-stack').and_return(
|
57
|
+
stack_response_with_children
|
58
|
+
)
|
59
|
+
|
60
|
+
expect(Kontena).to receive(:run!).with(['stack', 'remove', '--force', 'foofoo'])
|
61
|
+
expect(Kontena).to receive(:run!).with(['stack', 'remove', '--force', 'foobar'])
|
62
|
+
|
63
|
+
expect(subject).to receive(:remove_stack).with('test-stack')
|
64
|
+
expect{subject.run(['--force', 'test-stack'])}.not_to exit_with_error
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
29
68
|
end
|
30
69
|
end
|
@@ -9,5 +9,21 @@ describe Kontena::Cli::Stacks::ShowCommand do
|
|
9
9
|
expect(client).to receive(:get).with('stacks/test-grid/test-stack').and_return(spy())
|
10
10
|
subject.run(['test-stack'])
|
11
11
|
end
|
12
|
+
|
13
|
+
context '--values option' do
|
14
|
+
let(:stack_response) do
|
15
|
+
{
|
16
|
+
'name' => 'stack-a',
|
17
|
+
'stack' => 'foo/stack-a',
|
18
|
+
'services' => [],
|
19
|
+
'variables' => { 'foo' => 'bar' }
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'outputs a yaml of the stack variables and values' do
|
24
|
+
expect(client).to receive(:get).with('stacks/test-grid/test-stack').and_return(stack_response)
|
25
|
+
expect{subject.run(['--values', 'test-stack'])}.to output(/^foo: bar$/).to_stdout
|
26
|
+
end
|
27
|
+
end
|
12
28
|
end
|
13
29
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'kontena/cli/stacks/stack_name'
|
2
|
+
|
3
|
+
describe Kontena::Cli::Stacks::StackName do
|
4
|
+
it 'can parse a stack string' do
|
5
|
+
expect(described_class.new('user/stack').to_s).to eq 'user/stack'
|
6
|
+
expect(described_class.new('user/stack:0.1.0').to_s).to eq 'user/stack:0.1.0'
|
7
|
+
expect(described_class.new('user/stack', '0.1.0').to_s).to eq 'user/stack:0.1.0'
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'can take a hash' do
|
11
|
+
expect(described_class.new(user: 'foo', stack: 'stack', version: '0.1.0').to_s).to eq 'foo/stack:0.1.0'
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'has accessors' do
|
15
|
+
result = described_class.new('user/stack:0.1.0')
|
16
|
+
expect(result.stack_name).to eq 'user/stack'
|
17
|
+
expect(result.user).to eq 'user'
|
18
|
+
expect(result.stack).to eq 'stack'
|
19
|
+
expect(result.version).to eq '0.1.0'
|
20
|
+
end
|
21
|
+
end
|
@@ -1,108 +1,125 @@
|
|
1
1
|
require "kontena/cli/stacks/upgrade_command"
|
2
|
+
require 'json'
|
2
3
|
|
3
4
|
describe Kontena::Cli::Stacks::UpgradeCommand do
|
4
5
|
|
5
6
|
include ClientHelpers
|
6
7
|
include RequirementsHelper
|
8
|
+
include FixturesHelpers
|
7
9
|
|
8
10
|
mock_current_master
|
9
11
|
|
10
|
-
|
12
|
+
before(:each) do
|
13
|
+
ENV['STACK'] = nil
|
14
|
+
end
|
11
15
|
|
12
|
-
|
13
|
-
{
|
14
|
-
'name' => 'stack-a',
|
15
|
-
'stack' => 'foo/stack-a',
|
16
|
-
'services' => []
|
17
|
-
}
|
18
|
-
end
|
16
|
+
describe '#execute' do
|
19
17
|
|
20
|
-
let(:
|
18
|
+
let(:stack_expectation) do
|
21
19
|
{
|
22
|
-
'name' => 'stack-
|
23
|
-
'stack' => '
|
24
|
-
'
|
20
|
+
'name' => 'stack-name',
|
21
|
+
'stack' => 'user/stackname',
|
22
|
+
'version' => '0.1.1',
|
23
|
+
'registry' => 'file://',
|
24
|
+
'services' => array_including(hash_including('name', 'image')),
|
25
|
+
'variables' => {},
|
26
|
+
'volumes' => [],
|
27
|
+
'dependencies' => nil,
|
28
|
+
'source' => /stack:/,
|
29
|
+
'expose' => nil
|
25
30
|
}
|
26
31
|
end
|
27
32
|
|
28
|
-
let(:defaults) do
|
29
|
-
{ 'foo' => 'bar' }
|
30
|
-
end
|
31
|
-
|
32
33
|
let(:stack_response) do
|
33
|
-
{
|
34
|
-
'name' => 'stack-a',
|
35
|
-
'stack' => 'foo/stack-a',
|
36
|
-
'services' => [],
|
37
|
-
'variables' => defaults
|
38
|
-
}
|
34
|
+
stack_expectation.merge('services' => [{'name' => 'foo', 'image' => 'bar'}], 'source' => 'foo')
|
39
35
|
end
|
40
36
|
|
41
37
|
before(:each) do
|
42
|
-
allow(File).to receive(:
|
38
|
+
allow(File).to receive(:read).with('kontena.yml').and_return(fixture('kontena_v3.yml'))
|
39
|
+
allow(File).to receive(:exist?).with('kontena.yml').and_return(true)
|
40
|
+
allow(subject.loader_class).to receive(:for).and_call_original
|
43
41
|
end
|
44
42
|
|
45
43
|
expect_to_require_current_master
|
46
44
|
expect_to_require_current_master_token
|
47
45
|
|
48
46
|
it 'uses kontena.yml as default stack file' do
|
49
|
-
expect(
|
50
|
-
expect(subject
|
51
|
-
expect(client).to receive(:put).with('stacks/test-grid/stack-name', stack)
|
52
|
-
subject.run(['stack-name'])
|
47
|
+
expect(subject.instance(['stack-name']).source).to eq 'kontena.yml'
|
48
|
+
expect(subject.instance(['stack-name']).stack_name).to eq 'stack-name'
|
53
49
|
end
|
54
50
|
|
55
51
|
it 'sends stack to master' do
|
56
52
|
expect(client).to receive(:get).with('stacks/test-grid/stack-a').and_return(stack_response)
|
57
|
-
|
58
|
-
|
59
|
-
expect(client).to receive(:put).with(
|
60
|
-
'stacks/test-grid/stack-a', anything
|
61
|
-
)
|
62
|
-
subject.run(['stack-a', './path/to/kontena.yml'])
|
63
|
-
end
|
64
|
-
|
65
|
-
it 'allows to override stack name' do
|
66
|
-
expect(client).to receive(:get).with('stacks/test-grid/stack-b').and_return(stack_response)
|
67
|
-
allow(subject).to receive(:require_config_file).with('./path/to/kontena.yml').and_return(true)
|
68
|
-
allow(subject).to receive(:stack_read_and_dump).with('./path/to/kontena.yml', name: 'stack-b', values: nil, defaults: defaults).and_return(stack)
|
69
|
-
stack_b = stack
|
70
|
-
stack_b[:name] = 'stack-b'
|
71
|
-
expect(client).to receive(:put).with(
|
72
|
-
'stacks/test-grid/stack-b', anything
|
73
|
-
)
|
74
|
-
subject.run(['stack-b', './path/to/kontena.yml'])
|
53
|
+
expect(client).to receive(:put).with('stacks/test-grid/stack-a', hash_including(stack_expectation.merge('name' => 'stack-a'))).and_return(true)
|
54
|
+
subject.run(['--no-deploy', 'stack-a', fixture_path('kontena_v3.yml')])
|
75
55
|
end
|
76
56
|
|
77
57
|
it 'requires confirmation when master stack is different than input stack' do
|
78
|
-
expect(client).to receive(:get).with('stacks/test-grid/stack-b').and_return(stack_response)
|
79
|
-
|
80
|
-
|
81
|
-
expect(subject).to receive(:confirm).and_call_original
|
82
|
-
expect{subject.run(['stack-b', './path/to/kontena.yml'])}.to exit_with_error
|
58
|
+
expect(client).to receive(:get).with('stacks/test-grid/stack-b').and_return(stack_response.merge('stack' => 'foo/otherstack'))
|
59
|
+
expect(subject).to receive(:confirm).with(/Replacing stack foo\/otherstack on master with user\/stackname/).and_call_original
|
60
|
+
expect{subject.run(['stack-b', fixture_path('kontena_v3.yml')])}.to exit_with_error
|
83
61
|
end
|
84
62
|
|
85
63
|
it 'triggers deploy by default' do
|
86
64
|
expect(client).to receive(:get).with('stacks/test-grid/stack-a').and_return(stack_response)
|
87
|
-
allow(subject).to receive(:require_config_file).with('./path/to/kontena.yml').and_return(true)
|
88
|
-
allow(subject).to receive(:stack_read_and_dump).with('./path/to/kontena.yml', name: 'stack-a', values: nil, defaults: defaults).and_return(stack)
|
89
65
|
allow(client).to receive(:put).with(
|
90
66
|
'stacks/test-grid/stack-a', anything
|
91
67
|
).and_return({})
|
92
68
|
expect(Kontena).to receive(:run!).with(['stack', 'deploy', 'stack-a']).once
|
93
|
-
subject.run(['stack-a', '
|
69
|
+
subject.run(['stack-a', fixture_path('kontena_v3.yml')])
|
94
70
|
end
|
95
71
|
|
96
72
|
context '--no-deploy option' do
|
97
73
|
it 'does not trigger deploy' do
|
98
74
|
expect(client).to receive(:get).with('stacks/test-grid/stack-a').and_return(stack_response)
|
99
|
-
allow(subject).to receive(:require_config_file).with('./path/to/kontena.yml').and_return(true)
|
100
|
-
allow(subject).to receive(:stack_read_and_dump).with('./path/to/kontena.yml', name: 'stack-a', values: nil, defaults: defaults).and_return(stack)
|
101
75
|
allow(client).to receive(:put).with(
|
102
76
|
'stacks/test-grid/stack-a', anything
|
103
77
|
).and_return({})
|
104
78
|
expect(Kontena).not_to receive(:run!).with(['stack', 'deploy', 'stack-a'])
|
105
|
-
subject.run(['--no-deploy', 'stack-a', '
|
79
|
+
subject.run(['--no-deploy', 'stack-a', fixture_path('kontena_v3.yml')])
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context 'with a stack including dependencies' do
|
84
|
+
|
85
|
+
let(:expectation) {{ 'name' => 'deptest', 'stack' => 'user/depstack1' }}
|
86
|
+
let(:expectation_1) {{ 'name' => 'deptest-dep_1', 'stack' => 'user/depstack1child1' }}
|
87
|
+
let(:expectation_1_1) {{ 'name' => 'deptest-dep_1-dep_1', 'stack' => 'user/depstack1child1child1', 'services' => array_including(hash_including('image' => 'image:2')) }}
|
88
|
+
let(:expectation_2) {{ 'name' => 'deptest-dep_2', 'stack' => 'user/depstack1child2', 'services' => array_including(hash_including('image' => 'image:1')), 'variables' => hash_including('dep_var' => 1) }}
|
89
|
+
|
90
|
+
let(:response) { expectation.merge('parent' => nil, 'children' => [{'name' => 'deptest-dep_1'}, {'name' => 'deptest-dep_2'}]) }
|
91
|
+
let(:response_1) { expectation_1.merge('parent' => { 'name' => 'deptest' }, 'children' => [{'name' => 'deptest-dep_1-dep_1'}]) }
|
92
|
+
let(:response_1_1) { expectation_1_1.merge('parent' => { 'name' => 'deptest-dep_1' }, 'children' => []) }
|
93
|
+
let(:response_2) { expectation_2.merge('parent' => { 'name' => 'deptest' }, 'children' => [], 'variables' => {}, 'services' => []) }
|
94
|
+
|
95
|
+
before do
|
96
|
+
allow(subject).to receive(:fetch_master_data).with('deptest').and_return(response)
|
97
|
+
allow(subject).to receive(:fetch_master_data).with('deptest-dep_1').and_return(response_1)
|
98
|
+
allow(subject).to receive(:fetch_master_data).with('deptest-dep_1-dep_1').and_return(response_1_1)
|
99
|
+
allow(subject).to receive(:fetch_master_data).with('deptest-dep_2').and_return(response_2)
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'upgrades all dependencies' do
|
103
|
+
expect(client).to receive(:put).with('stacks/test-grid/deptest-dep_2', hash_including(expectation_2)).and_return(true)
|
104
|
+
expect(client).to receive(:put).with('stacks/test-grid/deptest-dep_1-dep_1', hash_including(expectation_1_1)).and_return(true)
|
105
|
+
expect(client).to receive(:put).with('stacks/test-grid/deptest-dep_1', hash_including(expectation_1)).and_return(true)
|
106
|
+
expect(client).to receive(:put).with('stacks/test-grid/deptest', hash_including(expectation)).and_return(true)
|
107
|
+
subject.run(['--no-deploy', '-v', 'dep_2.dep_var=1', 'deptest', fixture_path('stack-with-dependencies.yml')])
|
108
|
+
end
|
109
|
+
|
110
|
+
context 'when a dependency has been removed' do
|
111
|
+
it 'warns if a stack no longer in the dependency chain would be removed' do
|
112
|
+
expect(subject).to receive(:confirm).and_call_original
|
113
|
+
expect{subject.run(['--no-deploy', 'deptest', fixture_path('stack-with-dependencies-dep_2-removed.yml')])}.to exit_with_error.and output(/- deptest-dep_2.*data will be lost/m).to_stdout
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
context 'when a dependency has been added' do
|
118
|
+
it 'installs any new stacks in the dependency chain' do
|
119
|
+
allow(client).to receive(:put).and_return(true)
|
120
|
+
expect(Kontena).to receive(:run!).with(["stack", "install", "--name", "deptest-dep_3", "--parent-name", "deptest", "--no-deploy", fixture_path('stack-with-dependencies-dep-3.yml')]).and_return(true)
|
121
|
+
subject.run(['--no-deploy', '-v', 'dep_2.dep_var=1', 'deptest', fixture_path('stack-with-dependencies-dep_3-added.yml')])
|
122
|
+
end
|
106
123
|
end
|
107
124
|
end
|
108
125
|
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require "kontena/cli/stacks/upgrade_command"
|
2
|
+
|
3
|
+
describe Kontena::Cli::Stacks::UpgradeCommand do
|
4
|
+
|
5
|
+
include ClientHelpers
|
6
|
+
include RequirementsHelper
|
7
|
+
include FixturesHelpers
|
8
|
+
|
9
|
+
context 'without dependencies' do
|
10
|
+
before do
|
11
|
+
[:read, :exist?].each do |meth|
|
12
|
+
allow(File).to receive(meth).with(fixture_path('kontena_v3.yml')).and_call_original
|
13
|
+
allow(File).to receive(meth).with(fixture_path('docker-compose_v2.yml')).and_call_original
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'validates a yaml file' do
|
18
|
+
expect{Kontena.run!('stack', 'validate', fixture_path('kontena_v3.yml'))}.not_to exit_with_error
|
19
|
+
expect{Kontena.run!('stack', 'validate', fixture_path('kontena_v3.yml'))}.to output(/stack:.*version:.*services:.*variables:/m).to_stdout
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'with dependencies' do
|
24
|
+
before do
|
25
|
+
Dir.glob(File.join(File.dirname(fixture_path('stack-with-dependencies.yml')), 'stack-with-dependencies*yml')).each do |file|
|
26
|
+
[:read, :exist?].each do |meth|
|
27
|
+
allow(File).to receive(meth).with(file).and_call_original
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'validates all depended yaml files' do
|
33
|
+
output = OutputHelpers::CaptureStdoutLines.capture(proc {Kontena.run!('stack', 'validate', fixture_path('stack-with-dependencies.yml'))})
|
34
|
+
expect{Kontena.run!('stack', 'validate', fixture_path('stack-with-dependencies.yml'))}.not_to exit_with_error
|
35
|
+
expect(output.select { |line| line.start_with?('---') }.size).to eq 4
|
36
|
+
expect(output).to include('stack: user/depstack1')
|
37
|
+
expect(output).to include('stack: user/depstack1child1')
|
38
|
+
expect(output).to include('stack: user/depstack1child1child1')
|
39
|
+
expect(output).to include('stack: user/depstack1child2')
|
40
|
+
expect(output.select { |line| line.start_with?('stack') }.size).to eq 4
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '--dependency-tree' do
|
44
|
+
let(:expectation) do
|
45
|
+
{
|
46
|
+
"name" => "depstack1",
|
47
|
+
"stack" => /stack-with-dependencies.yml$/,
|
48
|
+
"depends" => [
|
49
|
+
{
|
50
|
+
"name" => "dep_1",
|
51
|
+
"stack" => /stack-with-dependencies-dep-1.yml$/,
|
52
|
+
"variables" => {},
|
53
|
+
"depends" => [
|
54
|
+
{
|
55
|
+
"name" => "dep_1",
|
56
|
+
"stack" => /stack-with-dependencies-dep-1-1.yml$/,
|
57
|
+
"variables" => {
|
58
|
+
"dep_var" => 2
|
59
|
+
}
|
60
|
+
}
|
61
|
+
]
|
62
|
+
},
|
63
|
+
{
|
64
|
+
"name" => "dep_2",
|
65
|
+
"stack" => /stack-with-dependencies-dep-2.yml$/,
|
66
|
+
"variables" => {
|
67
|
+
"dep_var" => 1
|
68
|
+
}
|
69
|
+
}
|
70
|
+
]
|
71
|
+
}
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'outputs the dependency tree' do
|
75
|
+
output = OutputHelpers::CaptureStdoutLines.capture(proc {Kontena.run!('stack', 'validate', '--dependency-tree', fixture_path('stack-with-dependencies.yml'))})
|
76
|
+
yaml = ::YAML.safe_load(output.join("\n"))
|
77
|
+
expect(yaml).to match hash_including(expectation)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'kontena/cli/stacks/yaml/validator_v3'
|
2
|
+
require 'kontena/cli/stacks/yaml/custom_validators/affinities_validator'
|
3
|
+
|
4
|
+
describe Kontena::Cli::Stacks::YAML::Validations::CustomValidators::AffinitiesValidator do
|
5
|
+
|
6
|
+
let(:errors) { Hash.new }
|
7
|
+
|
8
|
+
it 'accepts valid affinity' do
|
9
|
+
subject.validate('affinity', ['foo==bar'], [], errors)
|
10
|
+
expect(errors.size).to eq(0)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'accepts valid soft affinity' do
|
14
|
+
subject.validate('affinity', ['foo==~bar'], [], errors)
|
15
|
+
expect(errors.size).to eq(0)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'does not accept invalid affinity' do
|
19
|
+
subject.validate('affinity', ['foo=bar'], [], errors)
|
20
|
+
expect(errors.size).to eq(1)
|
21
|
+
end
|
22
|
+
end
|
@@ -1,12 +1,9 @@
|
|
1
1
|
require 'kontena/cli/stacks/yaml/reader'
|
2
|
-
require 'liquid'
|
3
2
|
|
4
3
|
describe Kontena::Cli::Stacks::YAML::Reader do
|
5
4
|
include FixturesHelpers
|
6
5
|
|
7
|
-
let(:service_extender)
|
8
|
-
spy
|
9
|
-
end
|
6
|
+
let(:service_extender) { spy("Kontena::Cli::Stacks::YAML::ServiceExtender") }
|
10
7
|
|
11
8
|
let(:env_file) do
|
12
9
|
['APIKEY=12345
|
@@ -14,34 +11,9 @@ describe Kontena::Cli::Stacks::YAML::Reader do
|
|
14
11
|
', 'WP_ADMIN_PASSWORD=verysecret']
|
15
12
|
end
|
16
13
|
|
17
|
-
let(:valid_v3_result) do
|
18
|
-
{
|
19
|
-
'stack' => 'user/stackname',
|
20
|
-
'version' => '2',
|
21
|
-
'services' => {
|
22
|
-
'wordpress' => {
|
23
|
-
'image' => 'wordpress:4.1',
|
24
|
-
'ports' => ['80:80'],
|
25
|
-
'depends_on' => ['mysql'],
|
26
|
-
'stateful' => true,
|
27
|
-
'environment' => ['WORDPRESS_DB_PASSWORD=test_secret'],
|
28
|
-
'instances' => 2,
|
29
|
-
'deploy' => { 'strategy' => 'ha' },
|
30
|
-
'secrets' => []
|
31
|
-
},
|
32
|
-
'mysql' => {
|
33
|
-
'image' => 'mysql:5.6',
|
34
|
-
'stateful' => true,
|
35
|
-
'environment' => ['MYSQL_ROOT_PASSWORD=test_secret'],
|
36
|
-
'secrets' => []
|
37
|
-
}
|
38
|
-
}
|
39
|
-
}
|
40
|
-
end
|
41
|
-
|
42
14
|
before(:each) do
|
43
15
|
allow_any_instance_of(described_class).to receive(:env)
|
44
|
-
.and_return( { 'STACK' => 'test', 'GRID' => 'test-grid' } )
|
16
|
+
.and_return( { 'STACK' => 'test', 'GRID' => 'test-grid', 'PLATFORM' => 'test-grid' } )
|
45
17
|
end
|
46
18
|
|
47
19
|
describe '#initialize' do
|
@@ -76,85 +48,118 @@ describe Kontena::Cli::Stacks::YAML::Reader do
|
|
76
48
|
end
|
77
49
|
|
78
50
|
it 'returns error' do
|
79
|
-
|
80
|
-
expect(
|
51
|
+
subject.execute
|
52
|
+
expect(subject.errors.size).to eq(1)
|
81
53
|
end
|
82
54
|
end
|
83
55
|
|
84
56
|
describe '#execute' do
|
85
|
-
|
57
|
+
|
58
|
+
let(:subject) do
|
86
59
|
described_class.new(fixture_path('kontena_v3.yml'))
|
87
60
|
end
|
88
61
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
},
|
107
|
-
'stateful' => true,
|
108
|
-
'environment' => ['MYSQL_ROOT_PASSWORD=test_secret']
|
109
|
-
}
|
110
|
-
expect(Kontena::Cli::Stacks::YAML::ServiceExtender).to receive(:new)
|
111
|
-
.with(wordpress_options)
|
112
|
-
.once
|
113
|
-
.and_return(service_extender)
|
114
|
-
expect(Kontena::Cli::Stacks::YAML::ServiceExtender).to receive(:new)
|
115
|
-
.with(mysql_options)
|
116
|
-
.once
|
117
|
-
.and_return(service_extender)
|
118
|
-
expect(service_extender).to receive(:extend_from).with(docker_compose_yml['services']['wordpress'])
|
119
|
-
expect(service_extender).to receive(:extend_from).with(docker_compose_yml['services']['mysql'])
|
120
|
-
|
121
|
-
subject.execute
|
62
|
+
it 'returns result hash' do
|
63
|
+
result = subject.execute
|
64
|
+
expect(result).to be_kind_of(Hash)
|
65
|
+
%w(
|
66
|
+
stack
|
67
|
+
version
|
68
|
+
name
|
69
|
+
registry
|
70
|
+
expose
|
71
|
+
services
|
72
|
+
volumes
|
73
|
+
dependencies
|
74
|
+
source
|
75
|
+
variables
|
76
|
+
parent_name
|
77
|
+
).each do |k|
|
78
|
+
expect(result.key?(k)).to be_truthy
|
122
79
|
end
|
80
|
+
end
|
123
81
|
|
124
|
-
|
125
|
-
|
82
|
+
context 'when extending services' do
|
83
|
+
context 'from external file' do
|
84
|
+
let(:subject) do
|
85
|
+
described_class.new(fixture_path('kontena_v3.yml'))
|
86
|
+
end
|
126
87
|
|
127
|
-
|
88
|
+
before do
|
89
|
+
[:exist?, :read].each do |meth|
|
90
|
+
allow(File).to receive(meth).with(fixture_path('docker-compose_v2.yml')).and_call_original
|
91
|
+
allow(File).to receive(meth).with(fixture_path('kontena_v3.yml')).and_call_original
|
92
|
+
end
|
93
|
+
end
|
128
94
|
|
129
|
-
|
130
|
-
.with(
|
131
|
-
.
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
95
|
+
it 'extends services from an external file' do
|
96
|
+
expect(File).to receive(:read).with(fixture_path('docker-compose_v2.yml')).and_call_original
|
97
|
+
expect(subject.execute['services']).to match array_including(
|
98
|
+
hash_including(
|
99
|
+
"instances"=>2,
|
100
|
+
"image"=>"wordpress:4.1",
|
101
|
+
"env"=>["WORDPRESS_DB_PASSWORD=test_secret"],
|
102
|
+
"links"=>[{"name"=>"mysql", "alias"=>"mysql"}],
|
103
|
+
"ports"=>[{"ip"=>"0.0.0.0", "container_port"=>80, "node_port"=>80, "protocol"=>"tcp"}],
|
104
|
+
"stateful"=>true,
|
105
|
+
"strategy"=>"ha",
|
106
|
+
"name"=>"wordpress"
|
107
|
+
),
|
108
|
+
hash_including(
|
109
|
+
"instances"=>nil,
|
110
|
+
"image"=>"mysql:5.6",
|
111
|
+
"env"=>["MYSQL_ROOT_PASSWORD=test_secret"],
|
112
|
+
"links"=>[],
|
113
|
+
"ports"=>[],
|
114
|
+
"stateful"=>true,
|
115
|
+
"name"=>"mysql"
|
116
|
+
)
|
117
|
+
)
|
118
|
+
end
|
136
119
|
|
137
|
-
|
138
|
-
|
139
|
-
.
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
{
|
148
|
-
'services' => {
|
149
|
-
'wordpress' => {
|
150
|
-
'networks' => 'key not expected'
|
120
|
+
it 'merges validation errors' do
|
121
|
+
expect(File).to receive(:read).with(fixture_path('docker-compose_v2.yml')).and_return(fixture('docker-compose-invalid.yml'))
|
122
|
+
outcome = subject.execute
|
123
|
+
expect(outcome['errors']).to eq([{
|
124
|
+
'docker-compose_v2.yml' =>[
|
125
|
+
{
|
126
|
+
'services' => {
|
127
|
+
'wordpress' => {
|
128
|
+
'networks' => 'key not expected'
|
129
|
+
}
|
151
130
|
}
|
152
131
|
}
|
153
|
-
|
154
|
-
]
|
155
|
-
|
132
|
+
]
|
133
|
+
}])
|
134
|
+
end
|
156
135
|
end
|
157
136
|
|
137
|
+
context 'from the same file' do
|
138
|
+
subject do
|
139
|
+
described_class.new(fixture_path('stack-internal-extend.yml'))
|
140
|
+
end
|
141
|
+
|
142
|
+
before do
|
143
|
+
[:exist?, :read].each do |meth|
|
144
|
+
allow(File).to receive(meth).with(fixture_path('stack-internal-extend.yml')).and_call_original
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'extends services from the same file' do
|
149
|
+
app_svc = subject.execute['services'].find { |s| s['name'] == 'app' }
|
150
|
+
expect(app_svc).not_to be_nil
|
151
|
+
puts app_svc.inspect
|
152
|
+
expect(app_svc).to match hash_including(
|
153
|
+
"image" => "base:latest",
|
154
|
+
"instances" => 2,
|
155
|
+
"env" => [
|
156
|
+
"TEST1=test1",
|
157
|
+
"TEST2=changed"
|
158
|
+
],
|
159
|
+
"stateful" => true
|
160
|
+
)
|
161
|
+
end
|
162
|
+
end
|
158
163
|
end
|
159
164
|
|
160
165
|
context 'variable interpolation' do
|
@@ -174,6 +179,7 @@ describe Kontena::Cli::Stacks::YAML::Reader do
|
|
174
179
|
{
|
175
180
|
'STACK' => 'test',
|
176
181
|
'GRID' => 'test-grid',
|
182
|
+
'PLATFORM' => 'test-grid',
|
177
183
|
'TAG' => '4.1'
|
178
184
|
}
|
179
185
|
)
|
@@ -183,15 +189,21 @@ describe Kontena::Cli::Stacks::YAML::Reader do
|
|
183
189
|
end
|
184
190
|
|
185
191
|
it 'interpolates $VAR variables' do
|
186
|
-
|
187
|
-
|
188
|
-
|
192
|
+
expect(subject.execute['services']).to match array_including(hash_including('image' => 'wordpress:4.1'))
|
193
|
+
end
|
194
|
+
|
195
|
+
it 'interpolates default variables' do
|
196
|
+
expect(subject.execute['services']).to match array_including(
|
197
|
+
hash_including(
|
198
|
+
'name' => 'wordpress', 'env' => array_including(
|
199
|
+
'STACK=test', 'GRID=test-grid', 'PLATFORM=test-grid'
|
200
|
+
)
|
201
|
+
)
|
202
|
+
)
|
189
203
|
end
|
190
204
|
|
191
205
|
it 'interpolates ${VAR} variables' do
|
192
|
-
|
193
|
-
services = result[:services]
|
194
|
-
expect(services['mysql']['image']).to eq('mariadb:latest')
|
206
|
+
expect(subject.execute['services']).to match array_including(hash_including('name' => 'mysql', 'image' => 'mariadb:latest'))
|
195
207
|
end
|
196
208
|
|
197
209
|
it 'warns about empty variables' do
|
@@ -217,8 +229,22 @@ describe Kontena::Cli::Stacks::YAML::Reader do
|
|
217
229
|
allow(ENV).to receive(:[]).with('TAG').and_return('4.1')
|
218
230
|
allow(ENV).to receive(:[]).with('TEST_ENV_VAR').and_return('foo')
|
219
231
|
allow(ENV).to receive(:[]).with('MYSQL_IMAGE').and_return('foo')
|
220
|
-
|
221
|
-
expect(
|
232
|
+
|
233
|
+
expect(subject.execute['services']).to match array_including(
|
234
|
+
hash_including('name' => 'mysql', 'env' => array_including('INTERNAL_VAR=$INTERNAL_VAR'))
|
235
|
+
)
|
236
|
+
end
|
237
|
+
|
238
|
+
it 'raises runtime error for undeclared variables' do
|
239
|
+
subject.variables.delete(subject.variables.option('test_var'))
|
240
|
+
expect{subject.execute}.to raise_error(RuntimeError, /Undeclared variable 'test_var'/)
|
241
|
+
end
|
242
|
+
|
243
|
+
it 'considers variables declared when they are listed as to: env targets' do
|
244
|
+
subject.variables.option('tag').to[:env] = "BAG"
|
245
|
+
expect{subject.execute}.to raise_error(RuntimeError, /Undeclared variable 'TAG'/)
|
246
|
+
subject.variables.option('tag').to[:env] = "TAG"
|
247
|
+
expect{subject.execute}.not_to raise_error
|
222
248
|
end
|
223
249
|
end
|
224
250
|
|
@@ -233,13 +259,13 @@ describe Kontena::Cli::Stacks::YAML::Reader do
|
|
233
259
|
end
|
234
260
|
|
235
261
|
it 'converts env hash to array' do
|
236
|
-
|
237
|
-
expect(result['wordpress']['environment']).to eq(['WORDPRESS_DB_PASSWORD=test_secret'])
|
262
|
+
expect(subject.execute['services']).to match array_including(hash_including('name' => 'wordpress', 'env' => ['WORDPRESS_DB_PASSWORD=test_secret']))
|
238
263
|
end
|
239
264
|
|
240
265
|
it 'does nothing to env array' do
|
241
|
-
|
242
|
-
|
266
|
+
expect(subject.execute['services']).to match array_including(
|
267
|
+
hash_including('name' => 'mysql', 'env' => ['MYSQL_ROOT_PASSWORD=test_secret'])
|
268
|
+
)
|
243
269
|
end
|
244
270
|
end
|
245
271
|
|
@@ -275,31 +301,18 @@ describe Kontena::Cli::Stacks::YAML::Reader do
|
|
275
301
|
end
|
276
302
|
|
277
303
|
it 'merges variables' do
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
304
|
+
expect(subject.execute['services']).to match array_including(
|
305
|
+
hash_including(
|
306
|
+
'name' => 'wordpress',
|
307
|
+
'env' => [
|
308
|
+
'WORDPRESS_DB_PASSWORD=test_secret',
|
309
|
+
'APIKEY=12345',
|
310
|
+
'MYSQL_ROOT_PASSWORD=secret',
|
311
|
+
'WP_ADMIN_PASSWORD=verysecret'
|
312
|
+
]
|
313
|
+
)
|
314
|
+
)
|
285
315
|
end
|
286
|
-
|
287
|
-
end
|
288
|
-
end
|
289
|
-
|
290
|
-
it 'returns result hash' do
|
291
|
-
outcome = subject.execute
|
292
|
-
expect(outcome[:services]).to eq(valid_v3_result['services'])
|
293
|
-
end
|
294
|
-
|
295
|
-
context "For an invalid stack file" do
|
296
|
-
subject do
|
297
|
-
described_class.new(fixture_path('stack-invalid.yml'))
|
298
|
-
end
|
299
|
-
|
300
|
-
it 'returns validation errors' do
|
301
|
-
outcome = subject.execute
|
302
|
-
expect(outcome[:errors].size).to eq(1)
|
303
316
|
end
|
304
317
|
end
|
305
318
|
end
|
@@ -311,7 +324,7 @@ describe Kontena::Cli::Stacks::YAML::Reader do
|
|
311
324
|
|
312
325
|
it 'expands build option to absolute path' do
|
313
326
|
outcome = subject.execute
|
314
|
-
expect(outcome[
|
327
|
+
expect(outcome['services']['webapp']['build']['context']).to eq(fixture_path(''))
|
315
328
|
end
|
316
329
|
end
|
317
330
|
|
@@ -322,7 +335,7 @@ describe Kontena::Cli::Stacks::YAML::Reader do
|
|
322
335
|
|
323
336
|
it 'expands build context to absolute path' do
|
324
337
|
outcome = subject.execute
|
325
|
-
expect(outcome[
|
338
|
+
expect(outcome['services']['webapp']['build']['context']).to eq(fixture_path(''))
|
326
339
|
end
|
327
340
|
end
|
328
341
|
|
@@ -370,7 +383,7 @@ describe Kontena::Cli::Stacks::YAML::Reader do
|
|
370
383
|
}
|
371
384
|
|
372
385
|
subject.send(:normalize_build_args, options)
|
373
|
-
expect(options
|
386
|
+
expect(options['build']['args']).to eq({
|
374
387
|
'foo' => 'bar'
|
375
388
|
})
|
376
389
|
end
|
@@ -383,53 +396,42 @@ describe Kontena::Cli::Stacks::YAML::Reader do
|
|
383
396
|
end
|
384
397
|
|
385
398
|
it 'returns name for v3' do
|
386
|
-
name = subject.stack_name
|
399
|
+
name = subject.loader.stack_name.stack
|
387
400
|
expect(name).to eq('stackname')
|
388
401
|
end
|
389
402
|
end
|
390
403
|
|
391
404
|
context 'origins' do
|
392
405
|
before do
|
393
|
-
|
394
|
-
.
|
395
|
-
|
406
|
+
['docker-compose_v2.yml', 'kontena_v3.yml'].each do |file|
|
407
|
+
[:exist?, :read].each do |meth|
|
408
|
+
allow(File).to receive(meth)
|
409
|
+
.with(fixture_path(file))
|
410
|
+
.and_call_original
|
411
|
+
end
|
412
|
+
end
|
396
413
|
end
|
397
414
|
|
398
415
|
it 'can read from a file' do
|
399
|
-
allow(File).to receive(:read)
|
400
|
-
.with(fixture_path('docker-compose_v2.yml'))
|
401
|
-
.and_return(fixture('docker-compose-invalid.yml'))
|
402
|
-
|
403
416
|
subject = described_class.new(fixture_path('kontena_v3.yml'))
|
404
|
-
|
405
|
-
expect(subject.
|
406
|
-
expect(subject.execute[:registry]).to eq 'file://'
|
417
|
+
expect(subject.loader.origin).to eq 'file'
|
418
|
+
expect(subject.execute['registry']).to eq 'file://'
|
407
419
|
end
|
408
420
|
|
409
421
|
it 'can read from the registry' do
|
410
|
-
allow(File).to receive(:
|
411
|
-
.with(
|
412
|
-
.and_return(
|
413
|
-
|
414
|
-
stack_double = double
|
415
|
-
allow_any_instance_of(Kontena::StacksCache::RegistryClientFactory).to receive(:cloud_auth?).and_return(true)
|
416
|
-
expect(Kontena::StacksCache).to receive(:cache).with('foo/foo', nil).and_return(stack_double)
|
417
|
-
expect(stack_double).to receive(:read).and_return(fixture('kontena_v3.yml'))
|
422
|
+
allow(File).to receive(:exist?)
|
423
|
+
.with(/foo\/foo$/)
|
424
|
+
.and_return(false)
|
418
425
|
instance = described_class.new('foo/foo')
|
419
|
-
expect(instance.
|
420
|
-
expect(instance.execute[:registry]).to eq instance.current_account.stacks_url
|
426
|
+
expect(instance.loader.origin).to eq 'registry'
|
421
427
|
end
|
422
428
|
|
423
429
|
it 'can read from an url' do
|
424
|
-
allow(File).to receive(:
|
425
|
-
.with(
|
426
|
-
.and_return(
|
427
|
-
|
428
|
-
stub_request(:get, "http://foo.example.com/foo").to_return(:status => 200, :body => fixture('stack-with-liquid.yml'), :headers => {})
|
429
|
-
allow_any_instance_of(described_class).to receive(:load_from_url).and_return(fixture('stack-with-liquid.yml'))
|
430
|
+
allow(File).to receive(:exist?)
|
431
|
+
.with(/\/foo$/)
|
432
|
+
.and_return(false)
|
430
433
|
instance = described_class.new('http://foo.example.com/foo')
|
431
|
-
expect(instance.
|
432
|
-
expect(instance.execute[:registry]).to eq 'file://'
|
434
|
+
expect(instance.loader.origin).to eq 'uri'
|
433
435
|
end
|
434
436
|
end
|
435
437
|
|
@@ -444,7 +446,7 @@ describe Kontena::Cli::Stacks::YAML::Reader do
|
|
444
446
|
end
|
445
447
|
|
446
448
|
it 'interpolates variables into services' do
|
447
|
-
expect(subject.execute[
|
449
|
+
expect(subject.execute['services'].size).to eq 5
|
448
450
|
end
|
449
451
|
end
|
450
452
|
|
@@ -479,10 +481,11 @@ describe Kontena::Cli::Stacks::YAML::Reader do
|
|
479
481
|
end
|
480
482
|
|
481
483
|
it "omits the env" do
|
482
|
-
|
483
|
-
|
484
|
-
expect(
|
485
|
-
|
484
|
+
result = subject.execute
|
485
|
+
expect(result['variables']).to match hash_including('asdf' => nil)
|
486
|
+
expect(result['services']).to match array_including(
|
487
|
+
hash_including('name' => 'test', 'env' => nil)
|
488
|
+
)
|
486
489
|
end
|
487
490
|
end
|
488
491
|
|
@@ -497,9 +500,10 @@ describe Kontena::Cli::Stacks::YAML::Reader do
|
|
497
500
|
|
498
501
|
it "defines the env" do
|
499
502
|
outcome = subject.execute
|
500
|
-
|
501
|
-
expect(outcome[
|
502
|
-
|
503
|
+
expect(outcome['variables']).to match hash_including('asdf' => 'test')
|
504
|
+
expect(outcome['services']).to match array_including(
|
505
|
+
hash_including('name' => 'test', 'env' => ['ASDF=test'])
|
506
|
+
)
|
503
507
|
end
|
504
508
|
end
|
505
509
|
end
|