kontena-cli 1.3.5 → 1.4.0.pre1

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 (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'}"