kontena-cli 0.8.4 → 0.9.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 (90) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/bin/kontena +4 -0
  4. data/lib/kontena/cli/app_command.rb +2 -0
  5. data/lib/kontena/cli/apps/build_command.rb +26 -0
  6. data/lib/kontena/cli/apps/common.rb +41 -12
  7. data/lib/kontena/cli/apps/deploy_command.rb +31 -13
  8. data/lib/kontena/cli/apps/docker_helper.rb +34 -0
  9. data/lib/kontena/cli/apps/init_command.rb +130 -10
  10. data/lib/kontena/cli/apps/list_command.rb +4 -2
  11. data/lib/kontena/cli/apps/logs_command.rb +4 -2
  12. data/lib/kontena/cli/apps/remove_command.rb +4 -2
  13. data/lib/kontena/cli/apps/start_command.rb +4 -2
  14. data/lib/kontena/cli/apps/stop_command.rb +4 -2
  15. data/lib/kontena/cli/common.rb +3 -3
  16. data/lib/kontena/cli/container_command.rb +3 -0
  17. data/lib/kontena/cli/containers/inspect_command.rb +16 -0
  18. data/lib/kontena/cli/deploy_command.rb +3 -0
  19. data/lib/kontena/cli/etcd/get_command.rb +21 -0
  20. data/lib/kontena/cli/etcd/list_command.rb +26 -0
  21. data/lib/kontena/cli/etcd/mkdir_command.rb +17 -0
  22. data/lib/kontena/cli/etcd/remove_command.rb +21 -0
  23. data/lib/kontena/cli/etcd/set_command.rb +18 -0
  24. data/lib/kontena/cli/etcd_command.rb +17 -0
  25. data/lib/kontena/cli/grid_command.rb +2 -0
  26. data/lib/kontena/cli/grids/logs_command.rb +71 -0
  27. data/lib/kontena/cli/master/aws/create_command.rb +33 -0
  28. data/lib/kontena/cli/master/aws_command.rb +8 -0
  29. data/lib/kontena/cli/master/azure/create_command.rb +33 -0
  30. data/lib/kontena/cli/master/azure_command.rb +13 -0
  31. data/lib/kontena/cli/master/digital_ocean/create_command.rb +30 -0
  32. data/lib/kontena/cli/master/digital_ocean_command.rb +13 -0
  33. data/lib/kontena/cli/master/vagrant/create_command.rb +19 -0
  34. data/lib/kontena/cli/master/vagrant/restart_command.rb +20 -0
  35. data/lib/kontena/cli/master/vagrant/ssh_command.rb +15 -0
  36. data/lib/kontena/cli/master/vagrant/start_command.rb +20 -0
  37. data/lib/kontena/cli/master/vagrant/stop_command.rb +20 -0
  38. data/lib/kontena/cli/master/vagrant/terminate_command.rb +13 -0
  39. data/lib/kontena/cli/master/vagrant_command.rb +23 -0
  40. data/lib/kontena/cli/master_command.rb +15 -0
  41. data/lib/kontena/cli/node_command.rb +4 -0
  42. data/lib/kontena/cli/nodes/aws/create_command.rb +39 -0
  43. data/lib/kontena/cli/nodes/aws/restart_command.rb +28 -0
  44. data/lib/kontena/cli/nodes/aws/terminate_command.rb +20 -0
  45. data/lib/kontena/cli/nodes/aws_command.rb +15 -0
  46. data/lib/kontena/cli/nodes/azure/create_command.rb +39 -0
  47. data/lib/kontena/cli/nodes/azure/restart_command.rb +31 -0
  48. data/lib/kontena/cli/nodes/azure/terminate_command.rb +20 -0
  49. data/lib/kontena/cli/nodes/azure_command.rb +15 -0
  50. data/lib/kontena/cli/nodes/digital_ocean/create_command.rb +1 -1
  51. data/lib/kontena/cli/nodes/vagrant/create_command.rb +1 -1
  52. data/lib/kontena/cli/service_command.rb +4 -0
  53. data/lib/kontena/cli/services/add_env_command.rb +18 -0
  54. data/lib/kontena/cli/services/create_command.rb +8 -0
  55. data/lib/kontena/cli/services/remove_env_command.rb +17 -0
  56. data/lib/kontena/cli/services/services_helper.rb +20 -1
  57. data/lib/kontena/cli/services/update_command.rb +10 -0
  58. data/lib/kontena/client.rb +22 -1
  59. data/lib/kontena/machine/aws.rb +13 -0
  60. data/lib/kontena/machine/aws/cloudinit.yml +66 -0
  61. data/lib/kontena/machine/aws/cloudinit_master.yml +105 -0
  62. data/lib/kontena/machine/aws/master_provisioner.rb +161 -0
  63. data/lib/kontena/machine/aws/node_destroyer.rb +39 -0
  64. data/lib/kontena/machine/aws/node_provisioner.rb +168 -0
  65. data/lib/kontena/machine/azure.rb +13 -0
  66. data/lib/kontena/machine/azure/cloudinit.yml +59 -0
  67. data/lib/kontena/machine/azure/cloudinit_master.yml +105 -0
  68. data/lib/kontena/machine/azure/logger.rb +27 -0
  69. data/lib/kontena/machine/azure/master_provisioner.rb +126 -0
  70. data/lib/kontena/machine/azure/node_destroyer.rb +53 -0
  71. data/lib/kontena/machine/azure/node_provisioner.rb +128 -0
  72. data/lib/kontena/machine/digital_ocean.rb +1 -0
  73. data/lib/kontena/machine/digital_ocean/cloudinit.yml +1 -0
  74. data/lib/kontena/machine/digital_ocean/cloudinit_master.yml +105 -0
  75. data/lib/kontena/machine/digital_ocean/master_provisioner.rb +94 -0
  76. data/lib/kontena/machine/digital_ocean/node_provisioner.rb +8 -1
  77. data/lib/kontena/machine/vagrant.rb +2 -0
  78. data/lib/kontena/machine/vagrant/Vagrantfile.master.rb.erb +101 -0
  79. data/lib/kontena/machine/vagrant/{Vagrantfile.coreos.rb.erb → Vagrantfile.node.rb.erb} +0 -0
  80. data/lib/kontena/machine/vagrant/cloudinit.yml +2 -1
  81. data/lib/kontena/machine/vagrant/master_destroyer.rb +37 -0
  82. data/lib/kontena/machine/vagrant/master_provisioner.rb +75 -0
  83. data/lib/kontena/machine/vagrant/node_destroyer.rb +4 -0
  84. data/lib/kontena/machine/vagrant/node_provisioner.rb +1 -1
  85. data/lib/kontena/scripts/completer +29 -3
  86. data/spec/kontena/cli/app/common_spec.rb +61 -0
  87. data/spec/kontena/cli/app/deploy_command_spec.rb +25 -6
  88. data/spec/kontena/cli/app/docker_helper_spec.rb +32 -0
  89. data/spec/kontena/cli/common_spec.rb +53 -0
  90. metadata +61 -3
@@ -14,9 +14,11 @@ module Kontena::Cli::Apps
14
14
  attr_reader :services, :service_prefix
15
15
 
16
16
  def execute
17
- @services = load_services_from_yml
17
+ require_config_file(filename)
18
+
19
+ @service_prefix = project_name || current_dir
20
+ @services = load_services(filename, service_list, service_prefix)
18
21
  if services.size > 0
19
- Dir.chdir(File.dirname(filename))
20
22
  show_services(services)
21
23
  elsif !service_list.empty?
22
24
  puts "No such service: #{service_list.join(', ')}".colorize(:red)
@@ -14,9 +14,11 @@ module Kontena::Cli::Apps
14
14
  attr_reader :services, :service_prefix
15
15
 
16
16
  def execute
17
- @services = load_services_from_yml
17
+ require_config_file(filename)
18
+
19
+ @service_prefix = project_name || current_dir
20
+ @services = load_services(filename, service_list, service_prefix)
18
21
  if services.size > 0
19
- Dir.chdir(File.dirname(filename))
20
22
  show_logs(services)
21
23
  elsif !service_list.empty?
22
24
  puts "No such service: #{service_list.join(', ')}".colorize(:red)
@@ -16,10 +16,12 @@ module Kontena::Cli::Apps
16
16
  def execute
17
17
  require_api_url
18
18
  require_token
19
+ require_config_file(filename)
19
20
 
20
- @services = load_services_from_yml
21
+ @service_prefix = project_name || current_dir
22
+ #Dir.chdir(File.dirname(filename))
23
+ @services = load_services(filename, service_list, service_prefix)
21
24
  if services.size > 0
22
- Dir.chdir(File.dirname(filename))
23
25
  remove_services(services)
24
26
  elsif !service_list.empty?
25
27
  puts "No such service: #{service_list.join(', ')}".colorize(:red)
@@ -14,9 +14,11 @@ module Kontena::Cli::Apps
14
14
  attr_reader :services, :service_prefix
15
15
 
16
16
  def execute
17
- @services = load_services_from_yml
17
+ require_config_file(filename)
18
+
19
+ @service_prefix = project_name || current_dir
20
+ @services = load_services(filename, service_list, service_prefix)
18
21
  if services.size > 0
19
- Dir.chdir(File.dirname(filename))
20
22
  start_services(services)
21
23
  elsif !service_list.empty?
22
24
  puts "No such service: #{service_list.join(', ')}".colorize(:red)
@@ -14,9 +14,11 @@ module Kontena::Cli::Apps
14
14
  attr_reader :services, :service_prefix
15
15
 
16
16
  def execute
17
- @services = load_services_from_yml
17
+ require_config_file(filename)
18
+
19
+ @service_prefix = project_name || current_dir
20
+ @services = load_services(filename, service_list, service_prefix)
18
21
  if services.size > 0
19
- Dir.chdir(File.dirname(filename))
20
22
  stop_services(services)
21
23
  elsif !service_list.empty?
22
24
  puts "No such service: #{service_list.join(', ')}".colorize(:red)
@@ -8,7 +8,7 @@ module Kontena
8
8
  end
9
9
 
10
10
  def require_token
11
- token = settings['server']['token']
11
+ token = ENV['KONTENA_TOKEN'] || settings['server']['token']
12
12
  unless token
13
13
  raise ArgumentError.new("Please login first using: kontena login")
14
14
  end
@@ -48,7 +48,7 @@ module Kontena
48
48
  end
49
49
 
50
50
  def api_url
51
- url = settings['server']['url']
51
+ url = ENV['KONTENA_URL'] || settings['server']['url']
52
52
  unless url
53
53
  raise ArgumentError.new("It seem's that you are not logged into Kontena master, please login with: kontena login")
54
54
  end
@@ -72,7 +72,7 @@ module Kontena
72
72
  end
73
73
 
74
74
  def current_grid
75
- settings['server']['grid']
75
+ ENV['KONTENA_GRID'] || settings['server']['grid']
76
76
  end
77
77
 
78
78
  def save_settings
@@ -1,9 +1,12 @@
1
1
  require_relative 'containers/exec_command'
2
+ require_relative 'containers/inspect_command'
2
3
 
3
4
  class Kontena::Cli::ContainerCommand < Clamp::Command
4
5
 
5
6
  subcommand "exec", "Execute command inside a container", Kontena::Cli::Containers::ExecCommand
6
7
 
8
+ subcommand "inspect", "Inspect the container", Kontena::Cli::Containers::InspectCommand
9
+
7
10
  def execute
8
11
  end
9
12
  end
@@ -0,0 +1,16 @@
1
+ module Kontena::Cli::Containers
2
+ class InspectCommand < Clamp::Command
3
+ include Kontena::Cli::Common
4
+
5
+ parameter "CONTAINER_ID", "Container id"
6
+
7
+ def execute
8
+ require_api_url
9
+ token = require_token
10
+
11
+ service_name = container_id.match(/(.+)-(\d+)/)[1]
12
+ result = client(token).get("containers/#{current_grid}/#{service_name}/#{container_id}/inspect")
13
+ puts JSON.pretty_generate(result)
14
+ end
15
+ end
16
+ end
@@ -148,6 +148,9 @@ class Kontena::Cli::DeployCommand < Clamp::Command
148
148
  data[:stateful] = options['stateful'] == true
149
149
  data[:cap_add] = options['cap_add'] if options['cap_add']
150
150
  data[:cap_drop] = options['cap_drop'] if options['cap_drop']
151
+ data[:log_driver] = options['log_driver'] if options['log_driver']
152
+ data[:log_opts] = options['log_opt'] if options['log_opt'] && !options['log_opt'].empty?
153
+
151
154
  data
152
155
  end
153
156
 
@@ -0,0 +1,21 @@
1
+
2
+ module Kontena::Cli::Etcd
3
+ class GetCommand < Clamp::Command
4
+ include Kontena::Cli::Common
5
+
6
+ parameter "KEY", "Etcd key"
7
+
8
+ def execute
9
+ require_api_url
10
+ token = require_token
11
+ response = client(token).get("etcd/#{current_grid}/#{key}")
12
+ if response['value']
13
+ puts response['value']
14
+ elsif response['children']
15
+ abort "Cannot get value from a directory"
16
+ elsif response['error']
17
+ abort response['error']
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,26 @@
1
+
2
+ module Kontena::Cli::Etcd
3
+ class ListCommand < Clamp::Command
4
+ include Kontena::Cli::Common
5
+
6
+ parameter "KEY", "Etcd key"
7
+
8
+ option "--recursive", :flag, "List keys recursively", default: false
9
+
10
+ def execute
11
+ require_api_url
12
+ token = require_token
13
+ opts = []
14
+ opts << 'recursive=true' if recursive?
15
+ response = client(token).get("etcd/#{current_grid}/#{key}?#{opts.join('&')}")
16
+ if response['children']
17
+ children = response['children'].map{|c| c['key'] }
18
+ puts children.join("\n")
19
+ elsif response['value']
20
+ abort "Not a directory"
21
+ elsif response['error']
22
+ abort response['error']
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,17 @@
1
+ module Kontena::Cli::Etcd
2
+ class MkdirCommand < Clamp::Command
3
+ include Kontena::Cli::Common
4
+
5
+ parameter "KEY", "Etcd key"
6
+
7
+ def execute
8
+ require_api_url
9
+ token = require_token
10
+ data = {}
11
+ response = client(token).post("etcd/#{current_grid}/#{key}", data)
12
+ if response['error']
13
+ abort response['error']
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,21 @@
1
+ module Kontena::Cli::Etcd
2
+ class RemoveCommand < Clamp::Command
3
+ include Kontena::Cli::Common
4
+
5
+ parameter "KEY", "Etcd key"
6
+
7
+ option "--recursive", :flag, "Remove keys recursively"
8
+
9
+ def execute
10
+ require_api_url
11
+ token = require_token
12
+ data = {}
13
+ data[:recursive] = true if recursive?
14
+ response = client(token).delete("etcd/#{current_grid}/#{key}", data)
15
+
16
+ if response['error']
17
+ abort response['error']
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,18 @@
1
+ module Kontena::Cli::Etcd
2
+ class SetCommand < Clamp::Command
3
+ include Kontena::Cli::Common
4
+
5
+ parameter "KEY", "Etcd key"
6
+ parameter "VALUE", "Etcd value"
7
+
8
+ def execute
9
+ require_api_url
10
+ token = require_token
11
+ data = {value: value}
12
+ response = client(token).post("etcd/#{current_grid}/#{key}", data)
13
+ if response['error']
14
+ abort response['error']
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,17 @@
1
+ require_relative 'etcd/get_command'
2
+ require_relative 'etcd/set_command'
3
+ require_relative 'etcd/mkdir_command'
4
+ require_relative 'etcd/list_command'
5
+ require_relative 'etcd/remove_command'
6
+
7
+ class Kontena::Cli::EtcdCommand < Clamp::Command
8
+
9
+ subcommand "get", "Get the current value for a single key", Kontena::Cli::Etcd::GetCommand
10
+ subcommand "set", "Set a value on the specified key", Kontena::Cli::Etcd::SetCommand
11
+ subcommand "mk", "Create a directory", Kontena::Cli::Etcd::MkdirCommand
12
+ subcommand "ls", "List a directory", Kontena::Cli::Etcd::ListCommand
13
+ subcommand "rm", "Remove a key or a directory", Kontena::Cli::Etcd::RemoveCommand
14
+
15
+ def execute
16
+ end
17
+ end
@@ -2,6 +2,7 @@ require_relative 'grids/list_command'
2
2
  require_relative 'grids/create_command'
3
3
  require_relative 'grids/use_command'
4
4
  require_relative 'grids/show_command'
5
+ require_relative 'grids/logs_command'
5
6
  require_relative 'grids/remove_command'
6
7
  require_relative 'grids/current_command'
7
8
  require_relative 'grids/audit_log_command'
@@ -15,6 +16,7 @@ class Kontena::Cli::GridCommand < Clamp::Command
15
16
  subcommand "create", "Create a new grid", Kontena::Cli::Grids::CreateCommand
16
17
  subcommand "use", "Switch to use specific grid", Kontena::Cli::Grids::UseCommand
17
18
  subcommand "show", "Show grid details", Kontena::Cli::Grids::ShowCommand
19
+ subcommand "logs", "Show logs from grid containers", Kontena::Cli::Grids::LogsCommand
18
20
  subcommand "remove", "Remove a grid", Kontena::Cli::Grids::RemoveCommand
19
21
  subcommand "current", "Show current grid details", Kontena::Cli::Grids::CurrentCommand
20
22
  subcommand "audit-log", "Show audit log of the current grid", Kontena::Cli::Grids::AuditLogCommand
@@ -0,0 +1,71 @@
1
+ module Kontena::Cli::Grids
2
+ class LogsCommand < Clamp::Command
3
+ include Kontena::Cli::Common
4
+
5
+ option ["-f", "--follow"], :flag, "Follow (tail) logs", default: false
6
+ option ["-s", "--search"], "SEARCH", "Search from logs"
7
+ option "--lines", "LINES", "Number of lines to show from the end of the logs"
8
+ option "--node", "NODE", "Filter by node name", multivalued: true
9
+ option "--service", "SERVICE", "Filter by service name", multivalued: true
10
+ option ["-c", "--container"], "CONTAINER", "Filter by container", multivalued: true
11
+
12
+ def execute
13
+ require_api_url
14
+ token = require_token
15
+
16
+ query_params = {}
17
+ query_params[:nodes] = node_list.join(",") unless node_list.empty?
18
+ query_params[:services] = service_list.join(",") unless service_list.empty?
19
+ query_params[:containers] = container_list.join(",") unless container_list.empty?
20
+ query_params[:search] = search if search
21
+ query_params[:limit] = lines if lines
22
+
23
+
24
+ if follow?
25
+ query_params[:follow] = 1
26
+ stream_logs(token, query_params)
27
+ else
28
+ list_logs(token, query_params)
29
+ end
30
+ end
31
+
32
+ def list_logs(token, query_params)
33
+ result = client(token).get("grids/#{current_grid}/container_logs", query_params)
34
+ result['logs'].each do |log|
35
+ color = color_for_container(log['name'])
36
+ puts "#{log['name'].colorize(color)} | #{log['data']}"
37
+ end
38
+ end
39
+
40
+ def stream_logs(token, query_params)
41
+ streamer = lambda do |chunk, remaining_bytes, total_bytes|
42
+ log = JSON.parse(chunk)
43
+ if log
44
+ color = color_for_container(log['name'])
45
+ puts "#{log['name'].colorize(color)} | #{log['data']}"
46
+ end
47
+ end
48
+
49
+ result = client(token).get_stream(
50
+ "grids/#{current_grid}/container_logs", streamer, query_params
51
+ )
52
+ end
53
+
54
+ def color_for_container(container_id)
55
+ color_maps[container_id] = colors.shift unless color_maps[container_id]
56
+ color_maps[container_id].to_sym
57
+ end
58
+
59
+ def color_maps
60
+ @color_maps ||= {}
61
+ end
62
+
63
+ def colors
64
+ if(@colors.nil? || @colors.size == 0)
65
+ @colors = [:green, :yellow, :magenta, :cyan, :red,
66
+ :light_green, :light_yellow, :ligh_magenta, :light_cyan, :light_red]
67
+ end
68
+ @colors
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,33 @@
1
+ module Kontena::Cli::Master::Aws
2
+ class CreateCommand < Clamp::Command
3
+ include Kontena::Cli::Common
4
+
5
+ option "--access-key", "ACCESS_KEY", "AWS access key ID", required: true
6
+ option "--secret-key", "SECRET_KEY", "AWS secret key", required: true
7
+ option "--region", "REGION", "EC2 Region", default: 'eu-west-1'
8
+ option "--zone", "ZONE", "EC2 Availability Zone", default: 'a'
9
+ option "--vpc-id", "VPC ID", "Virtual Private Cloud (VPC) ID"
10
+ option "--subnet-id", "SUBNET ID", "VPC option to specify subnet to launch instance into"
11
+ option "--key-pair", "KEY_PAIR", "EC2 Key Pair", required: true
12
+ option "--type", "SIZE", "Instance type", default: 't2.small'
13
+ option "--storage", "STORAGE", "Storage size (GiB)", default: '30'
14
+ option "--version", "VERSION", "Define installed Kontena version", default: 'latest'
15
+ option "--auth-provider-url", "AUTH_PROVIDER_URL", "Define authentication provider url"
16
+
17
+ def execute
18
+ require 'kontena/machine/aws'
19
+
20
+ provisioner = Kontena::Machine::Aws::MasterProvisioner.new(access_key, secret_key, region)
21
+ provisioner.run!(
22
+ type: type,
23
+ vpc: vpc_id,
24
+ zone: zone,
25
+ subnet: subnet_id,
26
+ storage: storage,
27
+ version: version,
28
+ key_pair: key_pair,
29
+ auth_server: auth_provider_url
30
+ )
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,8 @@
1
+ module Kontena::Cli::Master
2
+
3
+ require_relative 'aws/create_command'
4
+
5
+ class AwsCommand < Clamp::Command
6
+ subcommand "create", "Create a new AWS master", Aws::CreateCommand
7
+ end
8
+ end
@@ -0,0 +1,33 @@
1
+ module Kontena::Cli::Master::Azure
2
+ class CreateCommand < Clamp::Command
3
+ include Kontena::Cli::Common
4
+
5
+ option "--subscription-id", "SUBSCRIPTION ID", "Azure subscription id", required: true
6
+ option "--subscription-cert", "CERTIFICATE", "Path to Azure management certificate", attribute_name: :certificate, required: true
7
+ option "--size", "SIZE", "SIZE", default: 'Small'
8
+ option "--network", "NETWORK", "Virtual Network name"
9
+ option "--subnet", "SUBNET", "Subnet name"
10
+ option "--ssh-key", "SSH KEY", "SSH private key file", required: true
11
+ option "--password", "PASSWORD", "Password"
12
+ option "--location", "LOCATION", "Location", default: 'West Europe'
13
+ option "--ssl-cert", "SSL CERT", "SSL certificate file"
14
+ option "--auth-provider-url", "AUTH_PROVIDER_URL", "Define authentication provider url"
15
+ option "--version", "VERSION", "Define installed Kontena version", default: 'latest'
16
+
17
+ def execute
18
+ require 'kontena/machine/azure'
19
+ provisioner = Kontena::Machine::Azure::MasterProvisioner.new(subscription_id, certificate)
20
+ provisioner.run!(
21
+ password: password,
22
+ ssh_key: ssh_key,
23
+ ssl_cert: ssl_cert,
24
+ size: size,
25
+ virtual_network: network,
26
+ subnet: subnet,
27
+ location: location,
28
+ auth_server: auth_provider_url,
29
+ version: version
30
+ )
31
+ end
32
+ end
33
+ end