kontena-cli 1.4.2.pre1 → 1.4.2.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1d83ecd393990f31582a50935e3f654d2bb80d800f5b5d196aa3dd37fb8384fb
4
- data.tar.gz: '06882cc66e76fea42a919d1d8b3df32980f3f28bd20e5f72252f14ccb2537cb0'
3
+ metadata.gz: d80c5a60886f305951632390349ef6168fc24b69542c108309fa0119e912c79e
4
+ data.tar.gz: f8cfba36671e56f8262aa6e90a41547ee229434f96ca5409e48c79b4deca8b68
5
5
  SHA512:
6
- metadata.gz: 7cb24f24e500a85564e50180cdf1f846f168320aafb4c612df7c112dcf8b090e3d085d0933550d080629743f97988a8ece671d4d11ca1df89a3c8ca1d113a42c
7
- data.tar.gz: 4a3bd5066d50938bcd3dba051f4a61cfdf89e7cad81af0eb01a2297c3027db3aafd45ee773d9da33681cbffa6ab550ba2ef6bfcd650139337f83c25fac488043
6
+ metadata.gz: b71ece37a3830283045dac25fb34d4f3f844df2954a83d3f0e6d88236477f334e9a65dc0fc74ac557eb75c0218f5dc691568ee96789f590479b76d43c02a525b
7
+ data.tar.gz: fdc0e18068f530dfc3fc06a403f4b002424cfb4d9c8cfc53e26b68570a8502ef5677c4959a90be85bf24f6d26c725596acf2c9be63d9ff8fa4fa064b15f23f1d
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.4.2.pre1
1
+ 1.4.2.rc1
@@ -40,53 +40,94 @@ module Kontena
40
40
  def initialize
41
41
  super
42
42
  @logger = Kontena.logger
43
- load_settings_from_env || load_settings_from_config_file
44
43
 
45
- debug { "Configuration loaded with #{servers.count} servers." }
44
+ load_settings_from_config_file
45
+
46
+ override_master_settings_from_env
47
+ override_cloud_settings_from_env
48
+
49
+ debug { "Configuration loaded with #{servers.count} servers and #{accounts.count} accounts." }
46
50
  debug { "Current master: #{current_server || '(not selected)'}" }
47
51
  debug { "Current grid: #{current_grid || '(not selected)'}" }
52
+ debug { "Current account: #{current_account.nil? ? '(not selected)' : current_account.name}" }
48
53
  end
49
54
 
50
55
  def debug(&block)
51
56
  Kontena.logger.add(Logger::DEBUG, nil, 'CONFIG', &block)
52
57
  end
53
58
 
54
- # Craft a regular looking configuration based on ENV variables
55
- def load_settings_from_env
56
- load_cloud_settings_from_env
57
- load_master_settings_from_env
58
- end
59
+ def override_master_settings_from_env
60
+ if ENV['KONTENA_URL']
61
+ server = find_server_by(url: ENV['KONTENA_URL'])
62
+ if server.nil?
63
+ debug { 'Using new master url from env KONTENA_URL' }
64
+ server = Server.new(
65
+ url: ENV['KONTENA_URL'],
66
+ name: ENV['KONTENA_MASTER'] || 'default'
67
+ )
68
+ servers << server
69
+ else
70
+ debug { "Using master #{server.name} in config found via url in env KONTENA_URL" }
71
+ end
72
+ elsif ENV['KONTENA_MASTER']
73
+ server = find_server_by(name: ENV['KONTENA_MASTER'])
74
+ if server
75
+ debug { "Using master #{ENV['KONTENA_MASTER']} set via env KONTENA_MASTER" }
76
+ end
77
+ elsif current_master
78
+ server = current_master
79
+ end
59
80
 
60
- def load_master_settings_from_env
61
- return nil unless ENV['KONTENA_URL']
81
+ if server.nil?
82
+ debug { 'Could not determine a master through config or env' }
83
+ self.current_master = nil
84
+ return
85
+ else
86
+ self.current_master = server.name
87
+ end
62
88
 
63
- debug { 'Loading master configuration from ENV' }
64
- servers << Server.new(
65
- url: ENV['KONTENA_URL'],
66
- name: 'default',
67
- token: Token.new(
68
- access_token: ENV['KONTENA_TOKEN'],
69
- parent_type: :master, parent_name: 'default'
70
- ),
71
- grid: ENV['KONTENA_GRID'],
72
- parent_type: :master,
73
- parent_name: 'default'
74
- )
89
+ if ENV['KONTENA_GRID']
90
+ debug { "Using grid #{ENV['KONTENA_GRID']} from env KONTENA_GRID" }
91
+ server.grid = ENV['KONTENA_GRID']
92
+ end
75
93
 
76
- self.current_master = 'default'
94
+ if ENV['KONTENA_TOKEN']
95
+ debug { 'Using master token from env KONTENA_TOKEN' }
96
+ server.token ||= Token.new(parent_type: :master, parent_name: server.name)
97
+ server.token.access_token = ENV['KONTENA_TOKEN']
98
+ server.token.refresh_token = nil
99
+ server.token.expires_at = nil
100
+ end
77
101
  end
78
102
 
79
- def load_cloud_settings_from_env
80
- return unless ENV['KONTENA_CLOUD_TOKEN']
103
+ def override_cloud_settings_from_env
104
+ if ENV['KONTENA_CLOUD']
105
+ account = find_account(ENV['KONTENA_CLOUD'])
106
+ if account
107
+ debug { "Using cloud account #{ENV['KONTENA_CLOUD']} from config selected by env KONTENA_CLOUD" }
108
+ self.current_account = account.name
109
+ else
110
+ debug { "Using new cloud account #{ENV['KONTENA_CLOUD']} from env" }
111
+ account = Accout.new(kontena_account_data.merge(name: ENV['KONTENA_CLOUD']))
112
+ accounts << account
113
+ end
114
+ elsif current_account
115
+ account = current_account
116
+ end
81
117
 
82
- debug { 'Loading cloud configuration from ENV' }
83
- accounts << Account.new(kontena_account_data.merge(
84
- token: Token.new(
85
- access_token: ENV['KONTENA_CLOUD_TOKEN'],
86
- parent_type: :account, parent_name: 'default'
87
- )
88
- ))
89
- self.current_account = 'kontena'
118
+ if account.nil?
119
+ debug { 'No account data from config or env' }
120
+ self.current_account = nil
121
+ return
122
+ end
123
+
124
+ if ENV['KONTENA_CLOUD_TOKEN']
125
+ debug { 'Using cloud token from env KONTENA_CLOUD_TOKEN' }
126
+ account.token ||= Token.new(parent_type: :account, parent_name: account.name)
127
+ account.token.access_token = ENV['KONTENA_CLOUD_TOKEN']
128
+ account.token.refresh_token = nil
129
+ account.token.expires_at = nil
130
+ end
90
131
  end
91
132
 
92
133
  def extract_token!(hash={})
@@ -120,7 +161,7 @@ module Kontena
120
161
  servers << server
121
162
  end
122
163
 
123
- self.current_server = ENV['KONTENA_MASTER'] || settings['current_server']
164
+ self.current_server = settings['current_server']
124
165
 
125
166
  Array(settings['accounts']).each do |account_data|
126
167
  if account_data['token']
@@ -146,7 +187,7 @@ module Kontena
146
187
  accounts.delete_at(master_index) if master_index
147
188
  accounts << Account.new(master_account_data)
148
189
 
149
- self.current_account = ENV['KONTENA_CLOUD'] || settings['current_account'] || 'kontena'
190
+ self.current_account = settings['current_account'] || 'kontena'
150
191
  end
151
192
 
152
193
  def kontena_account_data
@@ -232,7 +273,13 @@ module Kontena
232
273
  #
233
274
  # @return [String] path
234
275
  def config_filename
235
- @config_filename ||= ENV['KONTENA_CONFIG'] || default_config_filename
276
+ return @config_filename if @config_filename
277
+ if ENV['KONTENA_CONFIG']
278
+ debug { "Using #{ENV['KONTENA_CONFIG']} as config file set through env KONTENA_CONFIG"}
279
+ @config_filename = ENV['KONTENA_CONFIG']
280
+ else
281
+ @config_filename = default_config_filename
282
+ end
236
283
  end
237
284
 
238
285
  # Generate the default configuration filename
@@ -401,7 +448,9 @@ module Kontena
401
448
  #
402
449
  # @return [String, NilClass]
403
450
  def current_grid
404
- ENV['KONTENA_GRID'] || (current_master && current_master.grid)
451
+ return ENV['KONTENA_GRID'] unless ENV['KONTENA_GRID'].to_s.empty?
452
+ return nil unless current_master
453
+ current_master.grid
405
454
  end
406
455
 
407
456
  # Set the current grid name.
@@ -19,6 +19,7 @@ module Kontena::Cli::Stacks
19
19
  option '--dependency-tree', :flag, "Show dependency tree"
20
20
  option '--[no-]dependencies', :flag, "Validate dependencies", default: true
21
21
  option '--parent-name', '[PARENT_NAME]', "Set parent name", hidden: true
22
+ option '--format', 'yaml|api-json', "Output Format", default: 'yaml'
22
23
 
23
24
  def validate_dependencies
24
25
  dependencies = loader.dependencies
@@ -59,18 +60,16 @@ module Kontena::Cli::Stacks
59
60
 
60
61
  dump_variables if values_to
61
62
 
62
- result = stack.reject { |k, _| k == 'source' }
63
- result.merge!(
64
- 'variables' => Kontena::Util.stringify_keys(
65
- reader.variable_values(without_defaults: true, without_vault: true, with_errors: true)
66
- )
67
- )
68
- if dependencies?
69
- puts ::YAML.dump(result).sub(/\A---$/, "---\n# #{loader.source}")
63
+ case self.format
64
+ when 'api-json'
65
+ puts JSON.pretty_generate(stack)
66
+ when 'yaml'
67
+ result = ::YAML.dump(reader.fully_interpolated_yaml)
68
+ result = result.sub(/\A---$/, "---\n# #{loader.source}") if dependencies?
69
+ puts result
70
70
  else
71
- puts ::YAML.dump(result)
71
+ exit_with_error "Unknown --format=#{self.format}"
72
72
  end
73
73
  end
74
74
  end
75
75
  end
76
-
@@ -273,6 +273,7 @@ module Kontena::Cli::Stacks
273
273
  # @param [String] service_name - optional service to parse
274
274
  # @return [Hash]
275
275
  def parse_services(service_name = nil)
276
+ services = self.services.dup # do not modify the fully_interpolated_yaml['services'] hash in-place
276
277
  if service_name.nil?
277
278
  services.each do |name, config|
278
279
  services[name] = process_config(config, name)
@@ -5,26 +5,71 @@ describe Kontena::Cli::Stacks::UpgradeCommand do
5
5
  include ClientHelpers
6
6
  include RequirementsHelper
7
7
  include FixturesHelpers
8
+ include OutputHelpers
8
9
 
9
10
  context 'without dependencies' do
10
11
  before do
11
12
  [:read, :exist?].each do |meth|
12
13
  allow(File).to receive(meth).with(fixture_path('kontena_v3.yml')).and_call_original
13
14
  allow(File).to receive(meth).with(fixture_path('docker-compose_v2.yml')).and_call_original
15
+ allow(File).to receive(meth).with(fixture_path('stack-with-liquid.yml')).and_call_original
14
16
  end
15
17
  end
16
18
 
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
19
+ it 'outputs interpolated YAML' do
20
+ expect{Kontena.run!('stack', 'validate', fixture_path('stack-with-liquid.yml'))}.to output_yaml(
21
+ 'stack' => 'user/stackname',
22
+ 'version' => '0.1.1',
23
+ 'variables' => {
24
+ 'grid_name' => hash_including(
25
+ 'value' => 'validate stackname',
26
+ ),
27
+ 'copies' => {
28
+ 'type' => 'integer',
29
+ 'value' => 5,
30
+ }
31
+ },
32
+ 'services' => hash_including(
33
+ 'service-1' => hash_including(
34
+ 'image' => 'foo:1',
35
+ ),
36
+ ),
37
+ )
38
+ end
39
+
40
+ it 'outputs API JSON' do
41
+ expect{Kontena.run!('stack', 'validate', '-v', 'copies=2', '--format=api-json', fixture_path('stack-with-liquid.yml'))}.to output_json(hash_including(
42
+ 'stack' => 'user/stackname',
43
+ 'version' => '0.1.1',
44
+ 'name' => 'stackname',
45
+ 'registry' => 'file://',
46
+ 'expose' => nil,
47
+ 'volumes' => [ ],
48
+ 'dependencies' => nil,
49
+ 'source' => a_string_matching(/.+/),
50
+ 'parent_name' => nil,
51
+ 'variables' => {
52
+ 'grid_name' => '{{ GRID }} stackname',
53
+ 'copies' => 2,
54
+ },
55
+ 'services' => [
56
+ hash_including(
57
+ 'name' => 'service-1',
58
+ 'image' => 'foo:1',
59
+ ),
60
+ hash_including(
61
+ 'name' => 'service-2',
62
+ 'image' => 'foo:2',
63
+ ),
64
+ ],
65
+ ))
20
66
  end
21
67
 
22
68
  context '--online' do
23
69
  it 'validates a yaml file' do
24
- expect{Kontena.run!('stack', 'validate', '--online', fixture_path('kontena_v3.yml'))}.to output(/stack:.*version:.*services:.*variables:/m).to_stdout
70
+ expect{Kontena.run!('stack', 'validate', '--online', fixture_path('kontena_v3.yml'))}.to output(/stack:.*version:.*services:/m).to_stdout
25
71
  end
26
72
  end
27
-
28
73
  end
29
74
 
30
75
  context 'with dependencies' do
@@ -1,3 +1,4 @@
1
+ RSpec::Matchers.define_negated_matcher :exit_without_error, :exit_with_error
1
2
  RSpec::Matchers.define :exit_with_error do
2
3
 
3
4
  def supports_block_expectations?
@@ -97,6 +97,44 @@ module OutputHelpers
97
97
  end
98
98
  end
99
99
 
100
+ matcher :output_yaml do |expected|
101
+ supports_block_expectations
102
+
103
+ match do |block|
104
+ output = CaptureStdout.capture(block)
105
+ actual = ::YAML.safe_load(output)
106
+
107
+ values_match?(expected, actual)
108
+ end
109
+ end
110
+
111
+ matcher :output_json do |expected|
112
+ supports_block_expectations
113
+
114
+ match do |block|
115
+ output = CaptureStdout.capture(block)
116
+ @actual = JSON.parse(output)
117
+
118
+ values_match?(expected, @actual)
119
+ end
120
+
121
+ failure_message do |block|
122
+ return "expected block to return #{expected}, but returned #{@actual}"
123
+ end
124
+ end
125
+
126
+ module CaptureStdout
127
+ def self.capture(block)
128
+ capture = StringIO.new
129
+ original = $stdout
130
+ $stdout = capture
131
+ block.call
132
+ capture.string
133
+ ensure
134
+ $stdout = original
135
+ end
136
+ end
137
+
100
138
  module CaptureStdoutLines
101
139
  def self.capture(block)
102
140
  capture = StringIO.new
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kontena-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.2.pre1
4
+ version: 1.4.2.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kontena, Inc
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-12-07 00:00:00.000000000 Z
11
+ date: 2017-12-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler