kontena-cli 0.13.4 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/kontena-cli.gemspec +2 -0
  4. data/lib/kontena/cli/app_command.rb +2 -0
  5. data/lib/kontena/cli/apps/common.rb +80 -74
  6. data/lib/kontena/cli/apps/config_command.rb +29 -0
  7. data/lib/kontena/cli/apps/deploy_command.rb +12 -81
  8. data/lib/kontena/cli/apps/docker_helper.rb +3 -3
  9. data/lib/kontena/cli/apps/init_command.rb +0 -3
  10. data/lib/kontena/cli/apps/list_command.rb +2 -3
  11. data/lib/kontena/cli/apps/logs_command.rb +2 -3
  12. data/lib/kontena/cli/apps/monitor_command.rb +3 -4
  13. data/lib/kontena/cli/apps/remove_command.rb +4 -4
  14. data/lib/kontena/cli/apps/restart_command.rb +2 -3
  15. data/lib/kontena/cli/apps/scale_command.rb +3 -5
  16. data/lib/kontena/cli/apps/service_generator.rb +123 -0
  17. data/lib/kontena/cli/apps/service_generator_v2.rb +26 -0
  18. data/lib/kontena/cli/apps/show_command.rb +1 -2
  19. data/lib/kontena/cli/apps/start_command.rb +2 -3
  20. data/lib/kontena/cli/apps/stop_command.rb +2 -3
  21. data/lib/kontena/cli/apps/yaml/reader.rb +150 -0
  22. data/lib/kontena/cli/apps/yaml/service_extender.rb +60 -0
  23. data/lib/kontena/cli/apps/yaml/validations.rb +79 -0
  24. data/lib/kontena/cli/apps/yaml/validator.rb +55 -0
  25. data/lib/kontena/cli/apps/yaml/validator_v2.rb +74 -0
  26. data/lib/kontena/cli/common.rb +23 -0
  27. data/lib/kontena/cli/etcd/remove_command.rb +2 -0
  28. data/lib/kontena/cli/grids/remove_command.rb +2 -0
  29. data/lib/kontena/cli/grids/users/remove_command.rb +3 -0
  30. data/lib/kontena/cli/master/azure/create_command.rb +0 -2
  31. data/lib/kontena/cli/master/packet/create_command.rb +42 -0
  32. data/lib/kontena/cli/master/packet_command.rb +14 -0
  33. data/lib/kontena/cli/master/upcloud/create_command.rb +39 -0
  34. data/lib/kontena/cli/master/upcloud_command.rb +13 -0
  35. data/lib/kontena/cli/master/users/remove_command.rb +3 -0
  36. data/lib/kontena/cli/master/users/roles/remove_command.rb +2 -0
  37. data/lib/kontena/cli/master_command.rb +4 -0
  38. data/lib/kontena/cli/node_command.rb +4 -0
  39. data/lib/kontena/cli/nodes/azure/create_command.rb +0 -2
  40. data/lib/kontena/cli/nodes/list_command.rb +4 -8
  41. data/lib/kontena/cli/nodes/packet/create_command.rb +35 -0
  42. data/lib/kontena/cli/nodes/packet/restart_command.rb +17 -0
  43. data/lib/kontena/cli/nodes/packet/terminate_command.rb +20 -0
  44. data/lib/kontena/cli/nodes/packet_command.rb +15 -0
  45. data/lib/kontena/cli/nodes/remove_command.rb +2 -0
  46. data/lib/kontena/cli/nodes/show_command.rb +3 -1
  47. data/lib/kontena/cli/nodes/upcloud/create_command.rb +33 -0
  48. data/lib/kontena/cli/nodes/upcloud/restart_command.rb +20 -0
  49. data/lib/kontena/cli/nodes/upcloud/terminate_command.rb +20 -0
  50. data/lib/kontena/cli/nodes/upcloud_command.rb +15 -0
  51. data/lib/kontena/cli/registry/remove_command.rb +3 -0
  52. data/lib/kontena/cli/services/remove_command.rb +2 -0
  53. data/lib/kontena/cli/services/services_helper.rb +1 -0
  54. data/lib/kontena/cli/vault/list_command.rb +2 -0
  55. data/lib/kontena/cli/vault/read_command.rb +2 -0
  56. data/lib/kontena/cli/vault/remove_command.rb +4 -0
  57. data/lib/kontena/cli/vault/update_command.rb +8 -1
  58. data/lib/kontena/cli/vault/write_command.rb +2 -0
  59. data/lib/kontena/cli/vpn/remove_command.rb +3 -0
  60. data/lib/kontena/machine/azure/master_provisioner.rb +2 -2
  61. data/lib/kontena/machine/azure/node_provisioner.rb +7 -4
  62. data/lib/kontena/machine/digital_ocean/node_provisioner.rb +1 -1
  63. data/lib/kontena/machine/packet.rb +17 -0
  64. data/lib/kontena/machine/packet/cloudinit.yml +66 -0
  65. data/lib/kontena/machine/packet/cloudinit_master.yml +118 -0
  66. data/lib/kontena/machine/packet/master_provisioner.rb +93 -0
  67. data/lib/kontena/machine/packet/node_destroyer.rb +42 -0
  68. data/lib/kontena/machine/packet/node_provisioner.rb +77 -0
  69. data/lib/kontena/machine/packet/node_restarter.rb +41 -0
  70. data/lib/kontena/machine/packet/packet_common.rb +89 -0
  71. data/lib/kontena/machine/upcloud.rb +9 -0
  72. data/lib/kontena/machine/upcloud/cloudinit.yml +64 -0
  73. data/lib/kontena/machine/upcloud/cloudinit_master.yml +118 -0
  74. data/lib/kontena/machine/upcloud/master_provisioner.rb +136 -0
  75. data/lib/kontena/machine/upcloud/node_destroyer.rb +82 -0
  76. data/lib/kontena/machine/upcloud/node_provisioner.rb +119 -0
  77. data/lib/kontena/machine/upcloud/node_restarter.rb +47 -0
  78. data/lib/kontena/machine/upcloud/upcloud_common.rb +70 -0
  79. data/lib/kontena/scripts/completer +8 -3
  80. data/spec/fixtures/docker-compose_v2.yml +10 -0
  81. data/spec/fixtures/kontena-invalid.yml +4 -0
  82. data/spec/fixtures/kontena-with-variables.yml +19 -0
  83. data/spec/fixtures/kontena.yml +2 -2
  84. data/spec/fixtures/kontena_v2.yml +35 -0
  85. data/spec/kontena/cli/app/common_spec.rb +39 -101
  86. data/spec/kontena/cli/app/deploy_command_spec.rb +37 -388
  87. data/spec/kontena/cli/app/docker_helper_spec.rb +4 -4
  88. data/spec/kontena/cli/app/service_generator_spec.rb +374 -0
  89. data/spec/kontena/cli/app/service_generator_v2_spec.rb +74 -0
  90. data/spec/kontena/cli/app/yaml/reader_spec.rb +249 -0
  91. data/spec/kontena/cli/app/yaml/service_extender_spec.rb +104 -0
  92. data/spec/kontena/cli/app/yaml/validator_spec.rb +263 -0
  93. data/spec/kontena/cli/app/yaml/validator_v2_spec.rb +309 -0
  94. data/spec/kontena/cli/common_spec.rb +39 -1
  95. data/spec/kontena/cli/master/users/remove_command_spec.rb +9 -0
  96. data/spec/kontena/cli/master/users/roles/remove_command_spec.rb +2 -0
  97. metadata +86 -2
@@ -0,0 +1,82 @@
1
+ require 'shell-spinner'
2
+
3
+ module Kontena
4
+ module Machine
5
+ module Upcloud
6
+ class NodeDestroyer
7
+ include RandomName
8
+ include UpcloudCommon
9
+
10
+ attr_reader :api_client, :username, :password
11
+
12
+ # @param [Kontena::Client] api_client Kontena api client
13
+ # @param [String] token Upcloud token
14
+ def initialize(api_client, upcloud_username, upcloud_password)
15
+ @api_client = api_client
16
+ @username = upcloud_username
17
+ @password = upcloud_password
18
+ end
19
+
20
+ def run!(grid, name)
21
+ servers = get('server')
22
+ unless servers && servers.has_key?(:servers)
23
+ abort('Upcloud API error')
24
+ end
25
+
26
+ server = servers[:servers][:server].find{|s| s[:hostname] == name}
27
+
28
+ abort "Cannot find node #{name.colorize(:cyan)} in Upcloud" unless server
29
+
30
+ server_data = get("server/#{server[:uuid]}")
31
+
32
+ storage_devices = server_data.fetch(:server, {}).fetch(:storage_devices, {}).fetch(:storage_device, [])
33
+ storage_uuids = storage_devices.map{|s| s[:storage]}
34
+
35
+ abort('No storage devices found for Upcloud node') if storage_uuids.empty?
36
+
37
+ if server
38
+ unless server[:state].eql?('stopped')
39
+ ShellSpinner "Shutting down Upcloud node #{name.colorize(:cyan)} " do
40
+ device_data = post(
41
+ "server/#{server[:uuid]}/stop", body: {
42
+ stop_server: {
43
+ stop_type: 'soft',
44
+ timeout: 120
45
+ }
46
+ }.to_json
47
+ )
48
+
49
+ until device_data && device_data.fetch(:state, nil).to_s.eql?('stopped')
50
+ device_data = get("server/#{server[:uuid]}").fetch(:server, {}) rescue nil
51
+ sleep 5
52
+ end
53
+ end
54
+ end
55
+
56
+ ShellSpinner "Terminating Upcloud node #{name.colorize(:cyan)} " do
57
+ response = delete("server/#{server[:uuid]}")
58
+ abort "Cannot delete node #{name.colorize(:cyan)} in Upcloud" unless response[:success]
59
+ end
60
+
61
+ storage_uuids.each do |uuid|
62
+ ShellSpinner "Deleting Upcloud storage device '#{uuid.colorize(:cyan)}' " do
63
+ response = delete("storage/#{uuid}")
64
+ unless response[:success]
65
+ puts "#{"WARNING".colorize(:red)}: Couldn't delete Upcloud storage '#{uuid.colorize(:cyan)}', check manually."
66
+ end
67
+ end
68
+ end
69
+ else
70
+ abort "Cannot find node #{name.colorize(:cyan)} in Upcloud"
71
+ end
72
+ node = api_client.get("grids/#{grid['id']}/nodes")['nodes'].find{|n| n['name'] == name}
73
+ if node
74
+ ShellSpinner "Removing node #{name.colorize(:cyan)} from grid #{grid['name'].colorize(:cyan)} " do
75
+ api_client.delete("grids/#{grid['id']}/nodes/#{name}")
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,119 @@
1
+ require 'fileutils'
2
+ require 'erb'
3
+ require 'open3'
4
+ require 'shell-spinner'
5
+
6
+ module Kontena
7
+ module Machine
8
+ module Upcloud
9
+ class NodeProvisioner
10
+ include RandomName
11
+ include UpcloudCommon
12
+
13
+ attr_reader :api_client, :username, :password
14
+
15
+ # @param [Kontena::Client] api_client Kontena api client
16
+ # @param [String] upcloud_username Upcloud username
17
+ # @param [String] upcloud_password Upcloud password
18
+ def initialize(api_client, upcloud_username, upcloud_password)
19
+ @api_client = api_client
20
+ @username = upcloud_username
21
+ @password = upcloud_password
22
+ end
23
+
24
+ def run!(opts)
25
+ if File.readable?(File.expand_path(opts[:ssh_key]))
26
+ ssh_key = File.read(File.expand_path(opts[:ssh_key])).strip
27
+ end
28
+
29
+ abort('Invalid ssh key') unless ssh_key && ssh_key.start_with?('ssh-')
30
+
31
+ userdata_vars = {
32
+ version: opts[:version],
33
+ master_uri: opts[:master_uri],
34
+ grid_token: opts[:grid_token],
35
+ }
36
+
37
+ abort('CoreOS template not found on Upcloud') unless coreos_template = find_template('CoreOS Stable')
38
+ abort('Server plan not found on Upcloud') unless plan = find_plan(opts[:plan])
39
+ abort('Zone not found on Upcloud') unless zone_exist?(opts[:zone])
40
+
41
+ hostname = generate_name
42
+
43
+ device_data = {
44
+ server: {
45
+ zone: opts[:zone],
46
+ title: "Kontena Grid #{opts[:grid]} Node #{hostname}",
47
+ hostname: hostname,
48
+ plan: plan[:name],
49
+ vnc: 'off',
50
+ timezone: 'UTC',
51
+ user_data: user_data(userdata_vars),
52
+ firewall: 'off',
53
+ storage_devices: {
54
+ storage_device: [
55
+ {
56
+ action: 'clone',
57
+ storage: coreos_template[:uuid],
58
+ title: "From template #{coreos_template[:title]}",
59
+ size: plan[:storage_size],
60
+ tier: 'maxiops'
61
+ }
62
+ ]
63
+ },
64
+ login_user: {
65
+ create_password: 'no',
66
+ username: 'root',
67
+ ssh_keys: {
68
+ ssh_key: [ssh_key]
69
+ }
70
+ }
71
+ }
72
+ }.to_json
73
+
74
+ ShellSpinner "Creating Upcloud node #{hostname.colorize(:cyan)} " do
75
+ response = post('server', body: device_data)
76
+
77
+ if response.has_key?(:error)
78
+ abort("\nUpcloud server creation failed (#{response[:error].fetch(:error_message, '')})")
79
+ end
80
+ device_data = response[:server]
81
+
82
+ until device_data && device_data.fetch(:state, nil).to_s == 'maintenance'
83
+ device_data = get("server/#{device[:uuid]}").fetch(:server, {}) rescue nil
84
+ sleep 5
85
+ end
86
+ end
87
+
88
+ node = nil
89
+ ShellSpinner "Waiting for node #{hostname.colorize(:cyan)} join to grid #{opts[:grid].colorize(:cyan)} " do
90
+ sleep 2 until node = node_exists_in_grid?(opts[:grid], hostname)
91
+ end
92
+ set_labels(node, ["region=#{opts[:zone]}", "provider=upcloud"])
93
+ end
94
+
95
+ def user_data(vars)
96
+ cloudinit_template = File.join(__dir__ , '/cloudinit.yml')
97
+ erb(File.read(cloudinit_template), vars)
98
+ end
99
+
100
+ def generate_name
101
+ "#{super}-#{rand(1..99)}"
102
+ end
103
+
104
+ def node_exists_in_grid?(grid, hostname)
105
+ api_client.get("grids/#{grid}/nodes")['nodes'].find{|n| n['name'] == hostname}
106
+ end
107
+
108
+ def erb(template, vars)
109
+ ERB.new(template).result(OpenStruct.new(vars).instance_eval { binding })
110
+ end
111
+
112
+ def set_labels(node, labels)
113
+ data = {labels: labels}
114
+ api_client.put("nodes/#{node['id']}", data, {}, {'Kontena-Grid-Token' => node['grid']['token']})
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,47 @@
1
+ require 'shell-spinner'
2
+
3
+ module Kontena
4
+ module Machine
5
+ module Upcloud
6
+ class NodeRestarter
7
+ include RandomName
8
+ include UpcloudCommon
9
+
10
+ attr_reader :username, :password
11
+
12
+ # @param [String] upcloud_username Upcloud username
13
+ # @param [String] upcloud_password Upcloud password
14
+ def initialize(upcloud_username, upcloud_password)
15
+ @username = upcloud_username
16
+ @password = upcloud_password
17
+ end
18
+
19
+ def run!(name)
20
+ servers = get('server')
21
+ unless servers && servers.has_key?(:servers)
22
+ abort('Upcloud API error')
23
+ end
24
+
25
+ server = servers[:servers][:server].find{|s| s[:hostname] == name}
26
+
27
+ if server
28
+ ShellSpinner "Restarting Upcloud node #{name.colorize(:cyan)} " do
29
+ result = post(
30
+ "server/#{server[:uuid]}/restart", body: {
31
+ restart_server: {
32
+ stop_type: 'soft',
33
+ timeout: 600,
34
+ timeout_action: 'ignore'
35
+ }
36
+ }.to_json
37
+ )
38
+ end
39
+ else
40
+ abort "Cannot find node #{name.colorize(:cyan)} in Upcloud"
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+
@@ -0,0 +1,70 @@
1
+ require 'excon'
2
+ require 'json'
3
+
4
+ module Kontena
5
+ module Machine
6
+ module Upcloud
7
+ module UpcloudCommon
8
+
9
+ attr_reader :username
10
+ attr_reader :password
11
+
12
+ def client
13
+ @client ||= Excon.new(
14
+ 'https://api.upcloud.com',
15
+ omit_default_port: true,
16
+ user: username,
17
+ password: password,
18
+ headers: { "Accept-Encoding" => 'application/json' }
19
+ )
20
+ end
21
+
22
+ def find_template(name)
23
+ get('storage/template')[:storages][:storage].find{|s| s[:title].downcase.start_with?(name.downcase)}
24
+ end
25
+
26
+ def find_plan(name)
27
+ get('plan')[:plans][:plan].find{|s| s[:name].downcase.eql?(name.downcase)}
28
+ end
29
+
30
+ def zone_exist?(name)
31
+ get('zone')[:zones][:zone].map{|p| p[:id]}.include?(name)
32
+ end
33
+
34
+ def get_server(id)
35
+ get("server/#{id}").fetch(:server, nil)
36
+ end
37
+
38
+ [:get, :post, :delete].each do |http_method|
39
+ define_method http_method do |path, opts={}|
40
+ response = client.send(
41
+ http_method,
42
+ opts.merge(
43
+ path: File.join('/1.2', path),
44
+ headers: {
45
+ 'Content-Type': 'application/json'
46
+ }
47
+ )
48
+ )
49
+ if response.body && response.body.start_with?('{')
50
+ JSON.parse(response.body, symbolize_names: true)
51
+ elsif response.status.to_s.start_with?('2')
52
+ {success: true}
53
+ else
54
+ {error: response.status}
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+ class Testing
64
+ include Kontena::Machine::Upcloud::UpcloudCommon
65
+ def initialize(user, pass)
66
+ @username = user
67
+ @password = pass
68
+ end
69
+ end
70
+
@@ -55,8 +55,13 @@ class Helper
55
55
  end
56
56
 
57
57
  def yml_services
58
- if File.exist?('kontena.yml')
59
- services = YAML.load(File.read('kontena.yml'))
58
+ if File.exist?('kontena.yml')
59
+ yaml = YAML.load(File.read('kontena.yml'))
60
+ if yaml['version'] == '2'
61
+ services = yaml['services']
62
+ else
63
+ services = yaml
64
+ end
60
65
  services.keys
61
66
  end
62
67
  rescue
@@ -144,7 +149,7 @@ if words.size > 0
144
149
  completion.push %w(add list delete)
145
150
  when 'app'
146
151
  completion.clear
147
- sub_commands = %w(init build deploy start stop remove rm ps list
152
+ sub_commands = %w(init build config deploy start stop remove rm ps list
148
153
  logs monitor show)
149
154
  if words[1]
150
155
  completion.push(sub_commands) unless sub_commands.include?(words[1])
@@ -0,0 +1,10 @@
1
+ version: '2'
2
+ services:
3
+ wordpress:
4
+ image: wordpress:4.1
5
+ ports:
6
+ - 80:80
7
+ depends_on:
8
+ - mysql
9
+ mysql:
10
+ image: mysql:5.6
@@ -0,0 +1,4 @@
1
+ wordpress:
2
+ stateful: 'true'
3
+ environment:
4
+ WORDPRESS_DB_PASSWORD: %{project}_secret
@@ -0,0 +1,19 @@
1
+ wordpress:
2
+ extends:
3
+ file: docker-compose.yml
4
+ service: wordpress
5
+ image: wordpress:$TAG
6
+ stateful: true
7
+ environment:
8
+ - WORDPRESS_DB_PASSWORD=%{project}_secret
9
+ instances: 2
10
+ deploy:
11
+ strategy: ha
12
+ mysql:
13
+ extends:
14
+ file: docker-compose.yml
15
+ service: mysql
16
+ image: ${MYSQL_IMAGE}
17
+ stateful: true
18
+ environment:
19
+ - INTERNAL_VAR=$$INTERNAL_VAR
@@ -4,7 +4,7 @@ wordpress:
4
4
  service: wordpress
5
5
  stateful: true
6
6
  environment:
7
- - WORDPRESS_DB_PASSWORD=%{project}_secret
7
+ WORDPRESS_DB_PASSWORD: %{project}_secret
8
8
  instances: 2
9
9
  deploy:
10
10
  strategy: ha
@@ -14,4 +14,4 @@ mysql:
14
14
  service: mysql
15
15
  stateful: true
16
16
  environment:
17
- - MYSQL_ROOT_PASSWORD=%{project}_secret
17
+ - MYSQL_ROOT_PASSWORD=%{project}_secret
@@ -0,0 +1,35 @@
1
+ version: '2'
2
+ name: test-project
3
+ services:
4
+ wordpress:
5
+ extends:
6
+ file: docker-compose_v2.yml
7
+ service: wordpress
8
+ stateful: true
9
+ environment:
10
+ WORDPRESS_DB_PASSWORD: ${project}_secret
11
+ instances: 2
12
+ deploy:
13
+ strategy: ha
14
+ networks:
15
+ - front-tier
16
+ - back-tier
17
+ mysql:
18
+ extends:
19
+ file: docker-compose_v2.yml
20
+ service: mysql
21
+ stateful: true
22
+ environment:
23
+ - MYSQL_ROOT_PASSWORD=${project}_secret
24
+ volumes:
25
+ - mysql-data:/var/lib/mysql
26
+ networks:
27
+ - back-tier
28
+ volumes:
29
+ mysql-data:
30
+ driver: local
31
+ networks:
32
+ front-tier:
33
+ driver: bridge
34
+ back-tier:
35
+ driver: bridge
@@ -13,6 +13,10 @@ describe Kontena::Cli::Apps::Common do
13
13
  fixture('kontena.yml')
14
14
  end
15
15
 
16
+ let(:kontena_v2_yml) do
17
+ fixture('kontena_v2.yml')
18
+ end
19
+
16
20
  let(:docker_compose_yml) do
17
21
  fixture('docker-compose.yml')
18
22
  end
@@ -30,122 +34,56 @@ describe Kontena::Cli::Apps::Common do
30
34
  }
31
35
  end
32
36
 
33
- describe '#parse_services' do
34
-
35
- it 'returns services from given YAML file' do
36
- allow(File).to receive(:read).with("#{Dir.getwd}/kontena.yml").and_return(kontena_yml)
37
- allow(File).to receive(:read).with("#{Dir.getwd}/docker-compose.yml").and_return(docker_compose_yml)
38
- services = subject.parse_services('kontena.yml')
39
- expect(services['wordpress']).not_to be_nil
37
+ describe '#service_prefix' do
38
+ it 'returns given project name' do
39
+ allow(subject).to receive(:project_name).and_return('test')
40
+ expect(subject.service_prefix).to eq('test')
40
41
  end
41
42
 
42
- it 'raises error if extended service is not found from base file' do
43
- allow(File).to receive(:read).with("#{Dir.getwd}/kontena.yml").and_return(kontena_yml)
44
- allow(File).to receive(:read).with("#{Dir.getwd}/docker-compose.yml").and_return(mysql_yml)
45
-
46
- expect {
47
- subject.parse_services('kontena.yml')
48
- }.to raise_error(SystemExit)
43
+ it 'returns app name from yaml if project name not given' do
44
+ allow(subject).to receive(:project_name).and_return(nil)
45
+ allow(subject).to receive(:filename).and_return('kontena.yml')
46
+ allow(File).to receive(:read).with("#{Dir.getwd}/docker-compose_v2.yml").and_return(docker_compose_yml)
47
+ allow(File).to receive(:read).with("#{Dir.getwd}/kontena.yml").and_return(kontena_v2_yml)
48
+ expect(subject.service_prefix).to eq('test-project')
49
49
  end
50
- end
51
50
 
52
- describe '#normalize_env_vars' do
53
- it 'converts env hash to array' do
54
- opts = {
55
- 'environment' => {
56
- 'FOO' => 'bar',
57
- 'BAR' => 'baz'
58
- }
59
- }
60
- subject.normalize_env_vars(opts)
61
- env = opts['environment']
62
- expect(env).to include('FOO=bar')
63
- expect(env).to include('BAR=baz')
64
- end
65
-
66
- it 'does nothing to env array' do
67
- opts = {
68
- 'environment' => [
69
- 'FOO=bar', 'BAR=baz'
70
- ]
71
- }
72
- subject.normalize_env_vars(opts)
73
- env = opts['environment']
74
- expect(env).to include('FOO=bar')
75
- expect(env).to include('BAR=baz')
51
+ it 'returns current dir as default' do
52
+ allow(subject).to receive(:project_name).and_return(nil)
53
+ allow(subject).to receive(:filename).and_return('kontena.yml')
54
+ allow(subject).to receive(:project_name_from_yaml).and_return(nil)
55
+ allow(subject).to receive(:current_dir).and_return('working_dir')
56
+ expect(subject.service_prefix).to eq('working_dir')
76
57
  end
77
58
  end
78
59
 
79
- describe '#extend_env_vars' do
80
- it 'inherites env vars from upper level' do
81
- from = ['FOO=bar']
82
- to = nil
83
- env_vars = subject.extend_env_vars(from, to)
84
- expect(env_vars).to eq(['FOO=bar'])
85
- end
86
-
87
- it 'overrides values' do
88
- from = ['FOO=bar']
89
- to = ['FOO=baz']
90
- env_vars = subject.extend_env_vars(from, to)
91
- expect(env_vars).to eq(['FOO=baz'])
60
+ describe '#load_from_yaml' do
61
+ before(:each) do
62
+ allow(File).to receive(:read).with("#{Dir.getwd}/kontena.yml").and_return(kontena_yml)
63
+ allow(File).to receive(:read).with("#{Dir.getwd}/docker-compose.yml").and_return(docker_compose_yml)
92
64
  end
93
65
 
94
- it 'combines variables' do
95
- from = ['FOO=bar']
96
- to = ['BAR=baz']
97
- env_vars = subject.extend_env_vars(from, to)
98
- expect(env_vars).to eq(['BAR=baz', 'FOO=bar'])
66
+ it 'populates env variables' do
67
+ services = subject.services_from_yaml('kontena.yml',[],'load-test')
68
+ expect(ENV['grid']).to eq('test-grid')
69
+ expect(ENV['project']).to eq('load-test')
99
70
  end
100
- end
101
71
 
102
- describe '#extend_secrets' do
103
- it 'inherites secrets from upper level' do
104
- secret = {
105
- 'secret' => 'CUSTOMER_DB_PASSWORD',
106
- 'name' => 'MYSQL_PASSWORD',
107
- 'type' => 'env'
108
- }
109
- from = [secret]
110
- to = nil
111
- secrets = subject.extend_secrets(from, to)
112
- expect(secrets).to eq([secret])
72
+ it 'returns services from given YAML file' do
73
+ services = subject.services_from_yaml('kontena.yml',[],'')
74
+ expect(services['wordpress']).not_to be_nil
113
75
  end
114
76
 
115
- it 'overrides secrets' do
116
- from_secret = {
117
- 'secret' => 'CUSTOMER_DB_PASSWORD',
118
- 'name' => 'MYSQL_PASSWORD',
119
- 'type' => 'env'
120
- }
121
-
122
- to_secret = {
123
- 'secret' => 'CUSTOMER_DB_PASSWORD',
124
- 'name' => 'MYSQL_ROOT_PASSWORD',
125
- 'type' => 'env'
126
- }
127
- from = [from_secret]
128
- to = [to_secret]
129
- secrets = subject.extend_secrets(from, to)
130
- expect(secrets).to eq([to_secret])
77
+ it 'aborts on validation failure' do
78
+ allow_any_instance_of(Kontena::Cli::Apps::YAML::Validator).to receive(:validate)
79
+ .and_return({ :errors => [{ 'wordress' => [] }], :notifications => [] })
80
+ expect { subject.services_from_yaml('kontena.yml',[],'') }.to raise_error(SystemExit)
131
81
  end
132
82
 
133
- it 'combines secrets' do
134
- from_secret = {
135
- 'secret' => 'CUSTOMER_DB_PASSWORD',
136
- 'name' => 'MYSQL_PASSWORD',
137
- 'type' => 'env'
138
- }
139
-
140
- to_secret = {
141
- 'secret' => 'CUSTOMER_API_TOKEN',
142
- 'name' => 'API_TOKEN',
143
- 'type' => 'env'
144
- }
145
- from = [from_secret]
146
- to = [to_secret]
147
- secrets = subject.extend_secrets(from, to)
148
- expect(secrets).to eq([to_secret, from_secret])
83
+ it 'returns given service from given YAML file' do
84
+ services = subject.services_from_yaml('kontena.yml',['wordpress'],'')
85
+ expect(services['wordpress']).not_to be_nil
86
+ expect(services.size).to eq(1)
149
87
  end
150
88
  end
151
89
  end