kontena-plugin-cloud 1.0.0.pre1 → 1.0.0.pre2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 59e599cd1a6b5a74ff9854efbffc34bc2faba4fc
4
- data.tar.gz: 114cbd20de9d08e733c9790e113473dfabbda920
3
+ metadata.gz: 4ba51db007412d9c1f0cc5153e7972712627866d
4
+ data.tar.gz: dfb686674f831a540a732277ed44bdd824a2d3b1
5
5
  SHA512:
6
- metadata.gz: 6c59729a771e4d39e6a6a84a7e1db59803c7779e14dd907f4fa82e77413b971227c10a1f2dce3dec558c9b1a1940a986a26e16077618cbba652c2b6f0c0d1f6d
7
- data.tar.gz: 41c156dad9f34cfd32990ccbde6655fc6c1708113350be06c7c4981859ad50a84c3aacb92f17c11344c86f3e5e0fa5799f09ba177887d16b42b35cf22117c64c
6
+ metadata.gz: 37d98e085cf4ca833fb93152d9be9e178c54c04c743093b2233c247f5b1debef5c6b3cef310c1d789aefe9d9387f2c2cf80a149bb33af49a3fc62ec65d7cf6a9
7
+ data.tar.gz: 949e677350a6b488bd7c7984f757733acb70e9b570baf55400d886539b82da49218465a5747a70eabb5cd6c897c5496d5e1b091dc233683456cc026a1fc0de11
data/Gemfile CHANGED
@@ -5,5 +5,4 @@ gemspec
5
5
 
6
6
  group :development do
7
7
  gem 'rspec'
8
- gem 'kontena-plugin-digitalocean'
9
8
  end
@@ -0,0 +1,26 @@
1
+ module Kontena::Cli::Models
2
+ module CloudApiModel
3
+
4
+ attr_reader :api_data
5
+
6
+ def initialize(api_data)
7
+ @api_data = api_data || {}
8
+ end
9
+
10
+ def id
11
+ api_data['id']
12
+ end
13
+
14
+ def method_missing(method, *args, &block)
15
+ key = method.to_s.gsub('_', '-')
16
+
17
+ return api_data['attributes'].has_key?(key) && api_data['attributes'][key] if key.end_with?('?'.freeze)
18
+
19
+ if api_data['attributes'].has_key?(key)
20
+ api_data['attributes'][key]
21
+ else
22
+ raise ArgumentError.new("Method `#{m}` doesn't exist.")
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,33 @@
1
+ require_relative 'master_api_model'
2
+
3
+ module Kontena::Cli::Models
4
+ class Grid
5
+ include MasterApiModel
6
+
7
+ class Stats
8
+ include MasterApiModel
9
+
10
+ Statsd = Struct.new(:server, :port)
11
+
12
+ def statsd
13
+ @statsd ||= Statsd.new(@api_data.dig('statsd', 'server'), @api_data.dig('statsd', 'port'))
14
+ end
15
+ end
16
+
17
+ class Logs
18
+ include MasterApiModel
19
+ end
20
+
21
+ def id
22
+ api_data['id']
23
+ end
24
+
25
+ def logs
26
+ @logs ||= Logs.new(api_data['logs'])
27
+ end
28
+
29
+ def stats
30
+ @stats ||= Stats.new(api_data['stats'])
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,22 @@
1
+ module Kontena::Cli::Models
2
+ module MasterApiModel
3
+
4
+ attr_reader :api_data
5
+
6
+ def initialize(api_data)
7
+ @api_data = api_data || {}
8
+ end
9
+
10
+ def method_missing(method, *args, &block)
11
+ key = method.to_s
12
+
13
+ return @api_data.has_key?(key) && @api_data[key] if key.end_with?('?'.freeze)
14
+
15
+ if @api_data.has_key?(key)
16
+ @api_data[key]
17
+ else
18
+ raise ArgumentError.new("Method `#{m}` doesn't exist.")
19
+ end
20
+ end
21
+ end
22
+ end
@@ -1,16 +1,11 @@
1
+ require_relative 'cloud_api_model'
2
+
1
3
  module Kontena::Cli::Models
2
4
  class Platform
3
-
4
- def initialize(api_data)
5
- @api_data = api_data
6
- end
7
-
8
- def id
9
- @api_data['id']
10
- end
5
+ include CloudApiModel
11
6
 
12
7
  def region
13
- @api_data.dig('relationships', 'datacenter', 'data', 'id')
8
+ @api_data.dig('relationships', 'region', 'data', 'id')
14
9
  end
15
10
 
16
11
  def online?
@@ -20,14 +15,5 @@ module Kontena::Cli::Models
20
15
  def organization
21
16
  @api_data.dig('relationships', 'organization', 'data', 'id')
22
17
  end
23
-
24
- def method_missing(method, *args, &block)
25
- key = method.to_s.gsub('_', '-')
26
- if @api_data['attributes'].has_key?(key)
27
- @api_data['attributes'][key]
28
- else
29
- raise ArgumentError.new("Method `#{m}` doesn't exist.")
30
- end
31
- end
32
18
  end
33
19
  end
@@ -10,18 +10,6 @@ class Kontena::Plugin::Cloud::Organization::User::AddCommand < Kontena::Command
10
10
 
11
11
  def execute
12
12
  members = []
13
- spinner "Resolving organization #{pastel.cyan(name)} current members" do
14
- members = cloud_client.get("/organizations/#{name}/members")['data']
15
- members = members.map { |m|
16
- {
17
- type: 'users',
18
- id: m.dig('attributes', 'username'),
19
- meta: {
20
- role: m.dig('attributes', 'role')
21
- }
22
- }
23
- }
24
- end
25
13
  username_list.each do |u|
26
14
  members << {
27
15
  type: 'users',
@@ -31,7 +19,7 @@ class Kontena::Plugin::Cloud::Organization::User::AddCommand < Kontena::Command
31
19
  end
32
20
  spinner "Adding #{pastel.cyan(username_list.join(', '))} to organization #{pastel.cyan(name)} with role #{pastel.cyan(role)}" do
33
21
  data = {data: members}
34
- cloud_client.put("/organizations/#{name}/relationships/members", data)
22
+ cloud_client.post("/organizations/#{name}/relationships/members", data)
35
23
  end
36
24
  end
37
25
  end
@@ -12,22 +12,15 @@ class Kontena::Plugin::Cloud::Organization::User::RemoveCommand < Kontena::Comma
12
12
  confirm_command(username_list.join(',')) unless forced?
13
13
 
14
14
  members = []
15
- spinner "Resolving organization #{pastel.cyan(name)} current members" do
16
- members = cloud_client.get("/organizations/#{name}/members")['data']
17
- members = members.map { |m|
18
- {
19
- type: 'users',
20
- id: m.dig('attributes', 'username'),
21
- meta: {
22
- role: m.dig('attributes', 'role')
23
- }
24
- }
15
+ username_list.each do |u|
16
+ members << {
17
+ type: 'users',
18
+ id: u
25
19
  }
26
20
  end
27
- members.delete_if { |m| username_list.include?(m[:id]) }
28
21
  spinner "Removing #{pastel.cyan(username_list.join(', '))} from organization #{pastel.cyan(name)}" do
29
22
  data = {data: members}
30
- cloud_client.put("/organizations/#{name}/relationships/members", data)
23
+ cloud_client.delete("/organizations/#{name}/relationships/members", data)
31
24
  end
32
25
  end
33
26
  end
@@ -5,8 +5,8 @@ class Kontena::Plugin::Cloud::Region::ListCommand < Kontena::Command
5
5
  requires_current_account_token
6
6
 
7
7
  def execute
8
- datacenters = cloud_client.get('/datacenters')['data']
9
- print_table(datacenters) do |row|
8
+ regions = cloud_client.get('/regions')['data']
9
+ print_table(regions) do |row|
10
10
  row.merge!(row['attributes'])
11
11
  end
12
12
  end
@@ -1,18 +1,16 @@
1
1
  module Kontena
2
2
  module Plugin
3
3
  module Cloud
4
- VERSION = "1.0.0.pre1"
4
+ VERSION = "1.0.0.pre2"
5
5
 
6
6
  module Organization
7
- module User
8
- end
9
- end
10
-
11
- module Region
7
+ module User; end
12
8
  end
9
+ module Region; end
13
10
  end
14
11
 
15
12
  module Platform
13
+ module TrustedSubnet; end
16
14
  end
17
15
 
18
16
  module Grid
@@ -31,12 +31,7 @@ module Kontena::Plugin::Platform::Common
31
31
 
32
32
  # @param [String] name
33
33
  def require_platform(name)
34
- unless name.include?('/')
35
- name = "#{current_organization}/#{name}"
36
- end
37
- org, platform = name.split('/')
38
-
39
- raise ArgumentError, "Organization missing" unless org
34
+ org, platform = parse_platform_name(name)
40
35
 
41
36
  @current_organization = org
42
37
 
@@ -50,6 +45,19 @@ module Kontena::Plugin::Platform::Common
50
45
  self.current_grid = platform
51
46
  end
52
47
 
48
+ # @param [String] name
49
+ # @return [Array<String>] organization, platform
50
+ def parse_platform_name(name)
51
+ unless name.include?('/')
52
+ name = "#{current_organization}/#{name}"
53
+ end
54
+ org, platform = name.split('/')
55
+
56
+ raise ArgumentError, "Organization missing" unless org
57
+
58
+ [org, platform]
59
+ end
60
+
53
61
  def platform_config_exists?(name)
54
62
  !self.config.find_server_by(name: name).nil?
55
63
  end
@@ -54,9 +54,9 @@ class Kontena::Plugin::Platform::CreateCommand < Kontena::Command
54
54
  end
55
55
 
56
56
  def prompt_region
57
- datacenters = cloud_client.get('/datacenters')['data']
57
+ regions = cloud_client.get('/regions')['data']
58
58
  prompt.select("Choose region:") do |menu|
59
- datacenters.each do |d|
59
+ regions.each do |d|
60
60
  menu.choice d.dig('attributes', 'name'), d['id']
61
61
  end
62
62
  end
@@ -74,8 +74,8 @@ class Kontena::Plugin::Platform::CreateCommand < Kontena::Command
74
74
  data = {
75
75
  attributes: { "name": name, "initial-size": initial_size },
76
76
  relationships: {
77
- datacenter: {
78
- "data": { "type": "datacenters", "id": region }
77
+ region: {
78
+ "data": { "type": "region", "id": region }
79
79
  }
80
80
  }
81
81
  }
@@ -7,21 +7,21 @@ class Kontena::Plugin::Platform::ListCommand < Kontena::Command
7
7
 
8
8
  requires_current_account_token
9
9
 
10
- parameter "[ORG]", "Organization name", environment_variable: "KONTENA_ORGANIZATION"
10
+ option ["--organization", "--org"], "ORG", "Organization", environment_variable: "KONTENA_ORGANIZATION"
11
11
 
12
12
  def execute
13
- platforms = cloud_client.get("/organizations/#{org}/platforms")['data']
13
+ platforms = cloud_client.get("/organizations/#{organization}/platforms")['data']
14
14
 
15
15
  print_table(platforms) do |p|
16
16
  platform = Kontena::Cli::Models::Platform.new(p)
17
- p['name'] = "#{state_icon(platform.state)} #{org}/#{platform.name}"
17
+ p['name'] = "#{state_icon(platform.state)} #{organization}/#{platform.name}"
18
18
  p['organization'] = platform.organization
19
19
  p['url'] = platform.url
20
20
  p['region'] = platform.region
21
21
  end
22
22
  end
23
23
 
24
- def default_org
24
+ def default_organization
25
25
  current_account.username
26
26
  end
27
27
 
@@ -11,7 +11,7 @@ class Kontena::Plugin::Platform::RemoveCommand < Kontena::Command
11
11
 
12
12
  def execute
13
13
  require_platform(name)
14
- platform = find_platform_by_name(name)
14
+ platform = find_platform_by_name(current_platform, current_organization)
15
15
 
16
16
  confirm_command(name) unless forced?
17
17
 
@@ -1,8 +1,11 @@
1
+ require 'kontena/cli/grids/common'
1
2
  require_relative 'common'
3
+ require_relative '../../cli/models/grid'
2
4
 
3
5
  class Kontena::Plugin::Platform::ShowCommand < Kontena::Command
4
6
  include Kontena::Cli::Common
5
7
  include Kontena::Plugin::Platform::Common
8
+ include Kontena::Cli::Grids::Common
6
9
 
7
10
  requires_current_account_token
8
11
 
@@ -14,12 +17,42 @@ class Kontena::Plugin::Platform::ShowCommand < Kontena::Command
14
17
  platform = find_platform_by_name(current_platform, current_organization)
15
18
 
16
19
  puts "#{name}:"
17
- puts " id: #{platform.id}"
18
20
  puts " name: #{platform.name}"
19
21
  puts " organization: #{current_organization}"
20
22
  puts " state: #{platform.state}"
21
23
  puts " region: #{platform.region || '-'}"
22
24
  puts " initial_size: #{platform.initial_size}"
23
25
  puts " master: #{platform.url}"
26
+
27
+ grid = nil
28
+ begin
29
+ data = client.get("grids/#{platform.grid_id}")
30
+ grid = Kontena::Cli::Models::Grid.new(data)
31
+ rescue Kontena::Errors::StandardError
32
+ exit_with_error "Cannot fetch grid information"
33
+ end
34
+
35
+ if grid.default_affinity?
36
+ puts " default_affinity: "
37
+ grid.default_affinity.to_a.each do |a|
38
+ puts " - #{a}"
39
+ end
40
+ else
41
+ puts " default_affinity: -"
42
+ end
43
+ puts " subnet: #{grid.subnet}"
44
+ puts " supernet: #{grid.supernet}"
45
+ if grid.stats.statsd?
46
+ statsd = grid.stats.statsd
47
+ puts " exports:"
48
+ puts " statsd: #{statsd.server}:#{statsd.port}"
49
+ end
50
+ if grid.logs.forwarder?
51
+ puts "logs:"
52
+ puts " forwarder: #{grid.logs.forwarder}"
53
+ grid.logs.opts.each do |k,v|
54
+ puts " #{k}: #{v}"
55
+ end
56
+ end
24
57
  end
25
58
  end
@@ -0,0 +1,20 @@
1
+ require_relative '../../../cli/models/grid'
2
+ require_relative '../common'
3
+
4
+ class Kontena::Plugin::Platform::TrustedSubnet::AddCommand < Kontena::Command
5
+ include Kontena::Cli::Common
6
+ include Kontena::Plugin::Platform::Common
7
+
8
+ parameter "NAME", "Platform name"
9
+ parameter "SUBNET", "Subnet"
10
+
11
+ def execute
12
+ require_platform(name)
13
+
14
+ grid = client.get("grids/#{current_grid}")
15
+ data = {trusted_subnets: grid['trusted_subnets'] + [self.subnet]}
16
+ spinner "Adding #{subnet.colorize(:cyan)} as a trusted subnet in #{current_grid.colorize(:cyan)} platform " do
17
+ client.put("grids/#{current_grid}", data)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,51 @@
1
+ require_relative '../../../cli/models/grid'
2
+ require_relative '../common'
3
+ require 'ipaddr'
4
+
5
+ class Kontena::Plugin::Platform::TrustedSubnet::ListCommand < Kontena::Command
6
+ include Kontena::Cli::Common
7
+ include Kontena::Plugin::Platform::Common
8
+ include Kontena::Cli::TableGenerator::Helper
9
+
10
+ parameter "NAME", "Platform name"
11
+
12
+ def execute
13
+ require_platform(name)
14
+ grid = Kontena::Cli::Models::Grid.new(client.get("grids/#{current_grid}"))
15
+ if grid.trusted_subnets.size > 0
16
+ nodes = client.get("grids/#{current_grid}/nodes")['nodes']
17
+ else
18
+ nodes = []
19
+ end
20
+ items = grid.trusted_subnets.map { |s|
21
+ item = {
22
+ 'subnet' => s
23
+ }
24
+ subnet = IPAddr.new(s)
25
+ item['nodes'] = trusted_nodes(subnet, nodes).map { |n| n['name'] }.join(',')
26
+
27
+ item
28
+ }
29
+
30
+ print_table(items)
31
+ end
32
+
33
+ # @param [IPAddr] subnet
34
+ # @param [Array<Hash>] nodes
35
+ def trusted_nodes(subnet, nodes)
36
+ nodes.select { |n|
37
+ begin
38
+ n['private_ip'] && subnet.include?( IPAddr.new(n['private_ip']) )
39
+ rescue => exc
40
+ STDERR.puts "Failed to parse #{n['private_ip']} (#{n['name']}): #{exc.message}"
41
+ end
42
+ }
43
+ end
44
+
45
+ def fields
46
+ {
47
+ subnet: 'subnet',
48
+ nodes: 'nodes'
49
+ }
50
+ end
51
+ end
@@ -0,0 +1,27 @@
1
+ require_relative '../../../cli/models/grid'
2
+ require_relative '../common'
3
+
4
+ class Kontena::Plugin::Platform::TrustedSubnet::RemoveCommand < Kontena::Command
5
+ include Kontena::Cli::Common
6
+ include Kontena::Plugin::Platform::Common
7
+
8
+ parameter "NAME", "Platform name"
9
+ parameter "SUBNET", "Subnet"
10
+
11
+ option "--force", :flag, "Force remove", default: false, attribute_name: :forced
12
+
13
+ def execute
14
+ require_platform(name)
15
+
16
+ grid = client.get("grids/#{current_grid}")
17
+ confirm_command(subnet) unless forced?
18
+ trusted_subnets = grid['trusted_subnets'] || []
19
+ unless trusted_subnets.delete(self.subnet)
20
+ exit_with_error("Platform #{name.colorize(:cyan)} does not have trusted subnet #{subnet.colorize(:cyan)}")
21
+ end
22
+ data = {trusted_subnets: trusted_subnets}
23
+ spinner "Removing trusted subnet #{subnet.colorize(:cyan)} from #{name.colorize(:cyan)} platform " do
24
+ client.put("grids/#{current_grid}", data)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,11 @@
1
+ require_relative 'common'
2
+
3
+ class Kontena::Plugin::Platform::TrustedSubnetCommand < Kontena::Command
4
+
5
+ subcommand ["list", "ls"], "List trusted subnets", load_subcommand('kontena/plugin/platform/trusted_subnet/list_command')
6
+ subcommand ["add"], "Add trusted subnet", load_subcommand('kontena/plugin/platform/trusted_subnet/add_command')
7
+ subcommand ["remove", "rm"], "Remove trusted subnet", load_subcommand('kontena/plugin/platform/trusted_subnet/remove_command')
8
+
9
+ def execute
10
+ end
11
+ end
@@ -7,6 +7,7 @@ class Kontena::Plugin::PlatformCommand < Kontena::Command
7
7
  subcommand ['remove', 'rm'], 'Remove platform', load_subcommand('kontena/plugin/platform/remove_command')
8
8
  subcommand 'audit-log', 'Show platform audit logs', load_subcommand('kontena/plugin/platform/audit_log_command')
9
9
  subcommand 'health', 'Show platform health', load_subcommand('kontena/plugin/platform/health_command')
10
+ subcommand 'trusted-subnet', 'Trusted subnet specific commands', load_subcommand('kontena/plugin/platform/trusted_subnet_command')
10
11
  subcommand 'import-grid', 'Import grid as Kontena Platform', load_subcommand('kontena/plugin/platform/import_grid_command')
11
12
 
12
13
  def execute
@@ -48,4 +48,26 @@ module Kontena
48
48
  class Command < Clamp::Command
49
49
  prepend CloudCommand
50
50
  end
51
+
52
+ module CloudClient
53
+ def parse_response(response)
54
+ data = super(response)
55
+ if data.is_a?(Hash) && data['errors']
56
+ data['error'] = {}
57
+ errors = data.delete('errors')
58
+ if errors.size == 1
59
+ data['error'] = errors[0]['title']
60
+ else
61
+ errors.each do |e|
62
+ data['error'][e['id']] = e['title']
63
+ end
64
+ end
65
+ end
66
+ data
67
+ end
68
+ end
69
+
70
+ class Client
71
+ prepend CloudClient
72
+ end
51
73
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kontena-plugin-cloud
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.pre1
4
+ version: 1.0.0.pre2
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-08-09 00:00:00.000000000 Z
11
+ date: 2017-08-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: kontena-cli
@@ -67,6 +67,9 @@ files:
67
67
  - Rakefile
68
68
  - kontena-plugin-cloud.gemspec
69
69
  - lib/kontena/cli/master_code_exchanger.rb
70
+ - lib/kontena/cli/models/cloud_api_model.rb
71
+ - lib/kontena/cli/models/grid.rb
72
+ - lib/kontena/cli/models/master_api_model.rb
70
73
  - lib/kontena/cli/models/platform.rb
71
74
  - lib/kontena/plugin/cloud.rb
72
75
  - lib/kontena/plugin/cloud/organization/list_command.rb
@@ -87,6 +90,10 @@ files:
87
90
  - lib/kontena/plugin/platform/list_command.rb
88
91
  - lib/kontena/plugin/platform/remove_command.rb
89
92
  - lib/kontena/plugin/platform/show_command.rb
93
+ - lib/kontena/plugin/platform/trusted_subnet/add_command.rb
94
+ - lib/kontena/plugin/platform/trusted_subnet/list_command.rb
95
+ - lib/kontena/plugin/platform/trusted_subnet/remove_command.rb
96
+ - lib/kontena/plugin/platform/trusted_subnet_command.rb
90
97
  - lib/kontena/plugin/platform/use_command.rb
91
98
  - lib/kontena/plugin/platform_command.rb
92
99
  - lib/kontena_cli_plugin.rb