kontena-cli 1.3.5 → 1.4.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +5 -5
  2. data/VERSION +1 -1
  3. data/lib/kontena/cli/etcd/health_command.rb +1 -1
  4. data/lib/kontena/cli/grids/common.rb +51 -0
  5. data/lib/kontena/cli/grids/create_command.rb +13 -9
  6. data/lib/kontena/cli/grids/update_command.rb +11 -44
  7. data/lib/kontena/cli/node_command.rb +3 -0
  8. data/lib/kontena/cli/nodes/create_command.rb +25 -0
  9. data/lib/kontena/cli/nodes/env_command.rb +32 -0
  10. data/lib/kontena/cli/nodes/health_command.rb +2 -2
  11. data/lib/kontena/cli/nodes/labels/add_command.rb +3 -3
  12. data/lib/kontena/cli/nodes/labels/list_command.rb +2 -2
  13. data/lib/kontena/cli/nodes/labels/remove_command.rb +3 -3
  14. data/lib/kontena/cli/nodes/remove_command.rb +9 -7
  15. data/lib/kontena/cli/nodes/reset_token_command.rb +31 -0
  16. data/lib/kontena/cli/nodes/show_command.rb +4 -4
  17. data/lib/kontena/cli/nodes/ssh_command.rb +4 -4
  18. data/lib/kontena/cli/nodes/update_command.rb +13 -8
  19. data/lib/kontena/cli/services/create_command.rb +4 -0
  20. data/lib/kontena/cli/services/services_helper.rb +2 -0
  21. data/lib/kontena/cli/services/update_command.rb +2 -0
  22. data/lib/kontena/cli/stacks/service_generator.rb +2 -0
  23. data/lib/kontena/cli/stacks/show_command.rb +1 -0
  24. data/lib/kontena/cli/stacks/stacks_helper.rb +2 -3
  25. data/lib/kontena/cli/stacks/yaml/validations.rb +3 -1
  26. data/lib/kontena/machine/cloud_config/cloudinit.yml +17 -4
  27. data/omnibus/package-scripts/kontena/postinst +0 -4
  28. data/omnibus/package-scripts/kontena/postrm +1 -1
  29. data/omnibus/package-scripts/kontena/preinst +0 -2
  30. data/spec/fixtures/api/node.json +93 -0
  31. data/spec/kontena/cli/containers/logs_command_spec.rb +0 -4
  32. data/spec/kontena/cli/etcd/health_command_spec.rb +128 -63
  33. data/spec/kontena/cli/nodes/create_command_spec.rb +24 -0
  34. data/spec/kontena/cli/nodes/env_command_spec.rb +49 -0
  35. data/spec/kontena/cli/nodes/health_command_spec.rb +15 -173
  36. data/spec/kontena/cli/nodes/labels/add_command_spec.rb +56 -0
  37. data/spec/kontena/cli/nodes/labels/list_command_spec.rb +43 -0
  38. data/spec/kontena/cli/nodes/labels/remove_command_spec.rb +57 -0
  39. data/spec/kontena/cli/nodes/list_command_spec.rb +0 -2
  40. data/spec/kontena/cli/nodes/remove_command_spec.rb +76 -0
  41. data/spec/kontena/cli/nodes/reset_token_command_spec.rb +38 -0
  42. data/spec/kontena/cli/nodes/show_command_spec.rb +46 -0
  43. data/spec/kontena/cli/nodes/ssh_command_spec.rb +5 -0
  44. data/spec/kontena/cli/nodes/update_command_spec.rb +24 -0
  45. data/spec/kontena/cli/stacks/deploy_command_spec.rb +21 -0
  46. data/spec/kontena/cli/stacks/logs_command_spec.rb +0 -4
  47. data/spec/kontena/cli/table_generator_spec.rb +0 -4
  48. data/spec/spec_helper.rb +5 -0
  49. data/spec/support/output_helpers.rb +3 -14
  50. data/tasks/release.rake +2 -2
  51. metadata +28 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: dd4f482967a7d7f9843c3f4192e3602f95a950f179c5997544c6e0e37accfedf
4
- data.tar.gz: a9f6ce7ce8c20881cfbfab58dc5bc446bb32d8f23703e8a61f8805c32ed50a47
2
+ SHA1:
3
+ metadata.gz: 69a344212c91c304c80efd5073e2b3d3e9003b66
4
+ data.tar.gz: 04ba668d77961f031b6bdd1bad7cbeacab5dfac9
5
5
  SHA512:
6
- metadata.gz: f1219cf89c19a806cbce2f1ffa477d954cec6c5e23a18bf75d3142aef26b9e3735258c414d03da188ed7e5903d2c43e6e042d5a5b263f99c3fa2306466319893
7
- data.tar.gz: 5b7a1bc7d23c736200ca65411bce69a9f6fbf93dc71ea2adb1a01b6eb277a2a52ea36d3edd99522a2961090cd11018ef35adfd67086c32a1d826b2d4a7a0650a
6
+ metadata.gz: 5fb80753ebfd53b27841cedaa60b2de9af188b6448691b7cc5e9f02410e644d44115b8f873295c7cf2eef823fa929911069d7032ebe5334ffbadd46b52d18b35
7
+ data.tar.gz: 32129fc7dd6d6ba258238a47799d085d639d5ae0168ee64a90de78756c8984dbfc88885324ce06f5cb4ffe8a76286cb97f119479c3c41e7e4430b6fa6241befc
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.3.5
1
+ 1.4.0.pre1
@@ -26,7 +26,7 @@ module Kontena::Cli::Etcd
26
26
  nodes = client.get("grids/#{current_grid}/nodes")['nodes']
27
27
 
28
28
  nodes.each do |node|
29
- node_health = client.get("nodes/#{current_grid}/#{node['name']}/health")
29
+ node_health = client.get("nodes/#{node['id']}/health")
30
30
 
31
31
  if !show_node_health(node_health)
32
32
  health = false
@@ -117,5 +117,56 @@ module Kontena::Cli::Grids
117
117
  exit_with_error "No grid given or selected"
118
118
  end
119
119
  end
120
+
121
+ module Parameters
122
+ def self.included(base)
123
+ base.option "--default-affinity", "[AFFINITY]", "Default affinity rule for the grid", multivalued: true
124
+ base.option "--statsd-server", "STATSD_SERVER", "Statsd server address (host:port)"
125
+ base.option "--log-forwarder", "LOG_FORWARDER", "Set grid wide log forwarder (set to 'none' to disable)"
126
+ base.option "--log-opt", "[LOG_OPT]", "Set log options (key=value)", multivalued: true
127
+ end
128
+
129
+ def validate_log_opts
130
+ if !log_opt_list.empty? && log_forwarder.nil?
131
+ raise Kontena::Errors::StandardError.new(1, "Need to specify --log-forwarder when using --log-opt")
132
+ end
133
+ end
134
+
135
+ def parse_log_opts
136
+ opts = {}
137
+ log_opt_list.each do |opt|
138
+ key, value = opt.split('=')
139
+ opts[key.to_sym] = value
140
+ end
141
+ opts
142
+ end
143
+
144
+ def validate_grid_parameters
145
+ validate_log_opts
146
+ end
147
+
148
+ def build_grid_parameters(payload)
149
+ if statsd_server
150
+ server, port = statsd_server.split(':')
151
+ payload[:stats] = {
152
+ statsd: {
153
+ server: server,
154
+ port: port || 8125
155
+ }
156
+ }
157
+ end
158
+
159
+ if log_forwarder
160
+ payload[:logs] = {
161
+ forwarder: log_forwarder,
162
+ opts: parse_log_opts
163
+ }
164
+ end
165
+
166
+ unless default_affinity_list.empty?
167
+ payload[:default_affinity] = default_affinity_list
168
+ end
169
+ end
170
+ end
120
171
  end
121
172
  end
@@ -10,28 +10,32 @@ module Kontena::Cli::Grids
10
10
  option "--initial-size", "INITIAL_SIZE", "Initial grid size (number of nodes)", default: 1
11
11
  option "--silent", :flag, "Reduce output verbosity"
12
12
  option "--token", "[TOKEN]", "Set grid token"
13
- option "--default-affinity", "[AFFINITY]", "Default affinity rule for the grid", multivalued: true
14
13
  option "--subnet", "[CIDR]", "Configure grid overlay subnet"
15
14
  option "--supernet", "[CIDR]", "Configure grid IPAM supernet"
16
15
 
16
+ include Common::Parameters
17
+
17
18
  requires_current_master_token
18
19
 
19
20
  def execute
21
+ validate_grid_parameters
22
+
23
+ if initial_size == 1
24
+ warning "Option --initial-size=1 is only recommended for test/dev usage" unless running_silent?
25
+ end
26
+
20
27
  payload = {
21
28
  name: name
22
29
  }
23
30
  payload[:token] = self.token if self.token
24
31
  payload[:initial_size] = self.initial_size if self.initial_size
25
- payload[:default_affinity] = self.default_affinity_list unless self.default_affinity_list.empty?
26
32
  payload[:subnet] = subnet if subnet
27
33
  payload[:supernet] = supernet if supernet
28
-
29
- grid = nil
30
- if initial_size == 1
31
- warning "Option --initial-size=1 is only recommended for test/dev usage" unless running_silent?
32
- end
33
- spinner "Creating #{pastel.cyan(name)} grid " do
34
- grid = client.post('grids', payload)
34
+
35
+ build_grid_parameters(payload)
36
+
37
+ grid = spinner "Creating #{pastel.cyan(name)} grid " do
38
+ client.post('grids', payload)
35
39
  end
36
40
  if grid
37
41
  spinner "Switching scope to #{pastel.cyan(name)} grid " do
@@ -6,63 +6,30 @@ module Kontena::Cli::Grids
6
6
  include Common
7
7
 
8
8
  parameter "NAME", "Grid name"
9
- option "--statsd-server", "STATSD_SERVER", "Statsd server address (host:port)"
10
- option "--no-statsd-server", :flag, "Unset statsd server setting"
11
- option "--default-affinity", "[AFFINITY]", "Default affinity rule for the grid", multivalued: true
9
+
10
+ include Common::Parameters
11
+
12
12
  option "--no-default-affinity", :flag, "Unset grid default affinity"
13
- option "--log-forwarder", "LOG_FORWARDER", "Set grid wide log forwarder (set to 'none' to disable)"
14
- option "--log-opt", "[LOG_OPT]", "Set log options (key=value)", multivalued: true
13
+ option "--no-statsd-server", :flag, "Unset statsd server setting"
14
+
15
+ requires_current_master_token
15
16
 
16
17
  def execute
17
- require_api_url
18
- token = require_token
19
- validate_log_opts
18
+ validate_grid_parameters
19
+
20
20
  payload = {}
21
- if statsd_server
22
- server, port = statsd_server.split(':')
23
- payload[:stats] = {
24
- statsd: {
25
- server: server,
26
- port: port || 8125
27
- }
28
- }
29
- end
21
+
22
+ build_grid_parameters(payload)
30
23
 
31
24
  if no_statsd_server?
32
25
  payload[:stats] = { statsd: nil }
33
26
  end
34
27
 
35
- if log_forwarder
36
- payload[:logs] = {
37
- forwarder: log_forwarder,
38
- opts: parse_log_opts
39
- }
40
- end
41
-
42
- unless default_affinity_list.empty?
43
- payload[:default_affinity] = default_affinity_list
44
- end
45
-
46
28
  if no_default_affinity?
47
29
  payload[:default_affinity] = []
48
30
  end
49
31
 
50
- client(token).put("grids/#{name}", payload)
51
- end
52
-
53
- def validate_log_opts
54
- if !log_opt_list.empty? && log_forwarder.nil?
55
- raise Kontena::Errors::StandardError.new(1, "Need to specify --log-forwarder when using --log-opt")
56
- end
57
- end
58
-
59
- def parse_log_opts
60
- opts = {}
61
- log_opt_list.each do |opt|
62
- key, value = opt.split('=')
63
- opts[key.to_sym] = value
64
- end
65
- opts
32
+ client.put("grids/#{name}", payload)
66
33
  end
67
34
  end
68
35
  end
@@ -3,10 +3,13 @@ class Kontena::Cli::NodeCommand < Kontena::Command
3
3
  subcommand ["list","ls"], "List grid nodes", load_subcommand('nodes/list_command')
4
4
  subcommand "show", "Show node", load_subcommand('nodes/show_command')
5
5
  subcommand "ssh", "Ssh into node", load_subcommand('nodes/ssh_command')
6
+ subcommand "create", "Create node", load_subcommand('nodes/create_command')
6
7
  subcommand "update", "Update node", load_subcommand('nodes/update_command')
8
+ subcommand "reset-token", "Reset node token for agent websocket connection", load_subcommand('nodes/reset_token_command')
7
9
  subcommand ["remove","rm"], "Remove node", load_subcommand('nodes/remove_command')
8
10
  subcommand "label", "Node label specific commands", load_subcommand('nodes/label_command')
9
11
  subcommand "health", "Check node health", load_subcommand('nodes/health_command')
12
+ subcommand "env", "Generate kontena-agent.env configuration", load_subcommand('nodes/env_command')
10
13
 
11
14
  def execute
12
15
  end
@@ -0,0 +1,25 @@
1
+ module Kontena::Cli::Nodes
2
+ class CreateCommand < Kontena::Command
3
+ include Kontena::Cli::Common
4
+ include Kontena::Cli::GridOptions
5
+
6
+ requires_current_master
7
+ requires_current_master_token
8
+ requires_current_grid
9
+
10
+ parameter "NAME", "Node name"
11
+ option ["--token"], "TOKEN", "Node token"
12
+ option ["-l", "--label"], "LABEL", "Node label", multivalued: true
13
+
14
+ def execute
15
+ data = { name: name }
16
+
17
+ data[:token] = token if token
18
+ data[:labels] = label_list
19
+
20
+ spinner "Creating #{name.colorize(:cyan)} node " do
21
+ client.post("grids/#{current_grid}/nodes", data)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,32 @@
1
+ module Kontena::Cli::Nodes
2
+ class EnvCommand < Kontena::Command
3
+ include Kontena::Cli::Common
4
+ include Kontena::Cli::GridOptions
5
+
6
+ requires_current_master
7
+ requires_current_master_token
8
+ requires_current_grid
9
+
10
+ parameter "NAME", "Node name"
11
+ option ['--token'], :flag, 'Only show token', default: false
12
+
13
+ def grid_uri
14
+ grid_uri = self.current_master['url'].sub('http', 'ws')
15
+ end
16
+
17
+ def execute
18
+ token_node = client.get("nodes/#{current_grid}/#{name}/token")
19
+
20
+ unless token_node['token']
21
+ exit_with_error "Node #{name} was not created with a node token. Use `kontena grid env` instead"
22
+ end
23
+
24
+ if self.token?
25
+ puts token_node['token']
26
+ else
27
+ puts "KONTENA_URI=#{grid_uri}"
28
+ puts "KONTENA_NODE_TOKEN=#{token_node['token']}"
29
+ end
30
+ end
31
+ end
32
+ end
@@ -6,14 +6,14 @@ module Kontena::Cli::Nodes
6
6
  include Kontena::Cli::GridOptions
7
7
  include Kontena::Cli::Helpers::HealthHelper
8
8
 
9
- parameter "NODE_ID", "Node id"
9
+ parameter "NODE", "Node name"
10
10
 
11
11
  def execute
12
12
  require_api_url
13
13
  require_current_grid
14
14
  token = require_token
15
15
 
16
- node = client(token).get("nodes/#{current_grid}/#{node_id}")
16
+ node = client(token).get("nodes/#{current_grid}/#{self.node}")
17
17
 
18
18
  return show_node_health(node)
19
19
  end
@@ -2,7 +2,7 @@ module Kontena::Cli::Nodes::Labels
2
2
  class AddCommand < Kontena::Command
3
3
  include Kontena::Cli::Common
4
4
 
5
- parameter "NODE_ID", "Node id"
5
+ parameter "NODE", "Node name"
6
6
  parameter "LABEL ...", "Labels"
7
7
 
8
8
  requires_current_master
@@ -10,9 +10,9 @@ module Kontena::Cli::Nodes::Labels
10
10
  requires_current_grid
11
11
 
12
12
  def execute
13
- node = client.get("nodes/#{current_grid}/#{node_id}")
13
+ node = client.get("nodes/#{current_grid}/#{self.node}")
14
14
  data = { labels: (Array(node['labels']) + label_list).uniq }
15
- client.put("nodes/#{current_grid}/#{node_id}", data)
15
+ client.put("nodes/#{node['id']}", data)
16
16
  end
17
17
  end
18
18
  end
@@ -2,7 +2,7 @@ module Kontena::Cli::Nodes::Labels
2
2
  class ListCommand < Kontena::Command
3
3
  include Kontena::Cli::Common
4
4
 
5
- parameter "NODE_ID", "Node id"
5
+ parameter "NODE", "Node name"
6
6
 
7
7
  # the command outputs id info only anyway, this is here strictly for ignoring purposes
8
8
  option ['-q', '--quiet'], :flag, "Output the identifying column only", hidden: true
@@ -12,7 +12,7 @@ module Kontena::Cli::Nodes::Labels
12
12
  requires_current_grid
13
13
 
14
14
  def execute
15
- node = client.get("nodes/#{current_grid}/#{node_id}")
15
+ node = client.get("nodes/#{current_grid}/#{self.node}")
16
16
  puts Array(node['labels']).join("\n")
17
17
  end
18
18
  end
@@ -2,7 +2,7 @@ module Kontena::Cli::Nodes::Labels
2
2
  class RemoveCommand < Kontena::Command
3
3
  include Kontena::Cli::Common
4
4
 
5
- parameter "NODE_ID", "Node id"
5
+ parameter "NODE", "Node name"
6
6
  parameter "LABEL ...", "Labels"
7
7
 
8
8
  requires_current_master
@@ -10,9 +10,9 @@ module Kontena::Cli::Nodes::Labels
10
10
  requires_current_grid
11
11
 
12
12
  def execute
13
- node = client.get("nodes/#{current_grid}/#{node_id}")
13
+ node = client.get("nodes/#{current_grid}/#{self.node}")
14
14
  data = { labels: Array(node['labels']).reject {|label| label_list.include?(label) } }
15
- client.put("nodes/#{current_grid}/#{node['id']}", data)
15
+ client.put("nodes/#{node['id']}", data)
16
16
  end
17
17
  end
18
18
  end
@@ -3,7 +3,7 @@ module Kontena::Cli::Nodes
3
3
  include Kontena::Cli::Common
4
4
  include Kontena::Cli::GridOptions
5
5
 
6
- parameter "NODE_ID", "Node id"
6
+ parameter "NODE", "Node name"
7
7
  option "--force", :flag, "Force remove", default: false, attribute_name: :forced
8
8
 
9
9
  def execute
@@ -11,16 +11,18 @@ module Kontena::Cli::Nodes
11
11
  require_current_grid
12
12
  token = require_token
13
13
 
14
- node = client(token).get("nodes/#{current_grid}/#{node_id}")
14
+ node = client(token).get("nodes/#{current_grid}/#{self.node}")
15
15
 
16
- if node['connected']
17
- exit_with_error "Node #{node['name']} is still online. You must terminate the node before removing it."
16
+ if node['has_token'] && node['connected']
17
+ warning "Node #{node['name']} is still connected using a node token, but will be force-disconnected"
18
+ elsif node['connected']
19
+ exit_with_error "Node #{node['name']} is still connected using a grid token. You must terminate the node before removing it."
18
20
  end
19
21
 
20
- confirm_command(node_id) unless forced?
22
+ confirm_command(self.node) unless forced?
21
23
 
22
- spinner "Removing #{node_id.colorize(:cyan)} node from #{current_grid.colorize(:cyan)} grid " do
23
- client(token).delete("nodes/#{current_grid}/#{node_id}")
24
+ spinner "Removing #{self.node.colorize(:cyan)} node from #{current_grid.colorize(:cyan)} grid " do
25
+ client(token).delete("nodes/#{node['id']}")
24
26
  end
25
27
  end
26
28
  end
@@ -0,0 +1,31 @@
1
+ module Kontena::Cli::Nodes
2
+ class ResetTokenCommand < Kontena::Command
3
+ include Kontena::Cli::Common
4
+ include Kontena::Cli::GridOptions
5
+
6
+ requires_current_master
7
+ requires_current_master_token
8
+ requires_current_grid
9
+
10
+ parameter "NODE", "Node name"
11
+
12
+ option ["--token"], "TOKEN", "Use given node token instead of generating a random token"
13
+ option ["--clear-token"], :flag, "Clear node token, reverting to grid token"
14
+ option "--[no-]reset-connection", :flag, "Reset agent websocket connection", default: true
15
+ option "--force", :flag, "Force token update"
16
+
17
+ def execute
18
+ confirm("Resetting the node token will disconnect the agent (unless using --no-reset-connection), and require you to reconfigure the kontena-agent using the new `kontena node env` values before it will be able to reconnect. Are you sure?")
19
+
20
+ data = {}
21
+
22
+ data[:token] = self.token
23
+ data[:token] = '' if self.clear_token?
24
+ data[:reset_connection] = self.reset_connection?
25
+
26
+ spinner "Resetting node #{self.node.colorize(:cyan)} websocket connection token" do
27
+ client.put("nodes/#{current_grid}/#{self.node}/token", data)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -4,16 +4,16 @@ module Kontena::Cli::Nodes
4
4
  include Kontena::Cli::GridOptions
5
5
  include Kontena::Cli::BytesHelper
6
6
 
7
- parameter "NODE_ID", "Node id"
7
+ parameter "NODE", "Node name"
8
8
 
9
9
  def execute
10
10
  require_api_url
11
11
  require_current_grid
12
12
  token = require_token
13
13
 
14
- node = client(token).get("nodes/#{current_grid}/#{node_id}")
15
- puts "#{node['name']}:"
16
- puts " id: #{node['id']}"
14
+ node = client(token).get("nodes/#{current_grid}/#{self.node}")
15
+ puts "#{node['id']}:"
16
+ puts " id: #{node['node_id']}"
17
17
  puts " agent version: #{node['agent_version']}"
18
18
  puts " docker version: #{node['docker_version']}"
19
19
  puts " connected: #{node['connected'] ? 'yes': 'no'}"