kontena-cli 0.13.4 → 0.14.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.
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