kontena-cli 0.12.0 → 0.12.1

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
  SHA1:
3
- metadata.gz: 09a43f90d845f6046491b8b9636cae6201fc0602
4
- data.tar.gz: 357fcf2a78efd43d5371056837a188b7225bd016
3
+ metadata.gz: b4c7616444c2dfd31cc66c625d49168d8ab8623d
4
+ data.tar.gz: f28c78f100bed2695c99b12d5ed757dfd0e4eaa3
5
5
  SHA512:
6
- metadata.gz: 076aa681b8e39964cbe93b9ae29279ee443f36fa0e73e6a054aef32852f93e5bb1502a318c556da5505eb6aaa13ec1b80a0d6d617b00466c8529c8f3cbeb80ba
7
- data.tar.gz: 40fe038531ef0e8cda9fa1af4c1a1df6f25a79088e7f8311b3d1c29b833762d145d26441e09f9ddc105419ae414866cd077a88dfd9a51fbc0b087c2cfad64e85
6
+ metadata.gz: b594019efe570386ebbf644888636a28f31ed88c0fe01425322dce0057fd232f1707d70e82899aefac3576a179ebccc87726a4b90e53a5c473bc354320947dcb
7
+ data.tar.gz: 9202690e4f3cff809576272a11108351266b97c421c189fbfe742c4f7d0ccc1c90e143a182f754c09a586f37a4f1a23a33724ea8f848352f0167fce50045c06f
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.12.0
1
+ 0.12.1
@@ -21,10 +21,8 @@ module Kontena::Cli::Grids
21
21
  puts " load: #{(loads[:'1m'] || 0.0).round(2)} #{(loads[:'5m'] || 0.0).round(2)} #{(loads[:'15m'] || 0.0).round(2)}"
22
22
 
23
23
  mem_total = nodes.map{|n| n['mem_total'].to_i}.inject(:+)
24
- mem_wired = nodes.map{|n|
25
- n.dig('resource_usage', 'memory', 'active').to_f
26
- }.inject(:+)
27
- puts " memory: #{to_gigabytes(mem_wired)} of #{to_gigabytes(mem_total)} GB"
24
+ mem_used = calculate_mem_used(nodes)
25
+ puts " memory: #{to_gigabytes(mem_used)} of #{to_gigabytes(mem_total)} GB"
28
26
 
29
27
  total_fs = calculate_filesystem_stats(nodes)
30
28
  puts " filesystem: #{to_gigabytes(total_fs['used'])} of #{to_gigabytes(total_fs['total'])} GB"
@@ -55,6 +53,19 @@ module Kontena::Cli::Grids
55
53
  loads
56
54
  end
57
55
 
56
+ # @param [Array<Hash>] nodes
57
+ # @return [Float]
58
+ def calculate_mem_used(nodes)
59
+ nodes.map{|n|
60
+ mem = n.dig('resource_usage', 'memory')
61
+ if mem
62
+ mem['used'] - (mem['cached'] + mem['buffers'])
63
+ else
64
+ 0.0
65
+ end
66
+ }.inject(:+)
67
+ end
68
+
58
69
  # @param [Array<Hash>] nodes
59
70
  # @return [Hash]
60
71
  def calculate_filesystem_stats(nodes)
@@ -9,7 +9,7 @@ module Kontena::Cli::Grids
9
9
  require_api_url
10
10
 
11
11
  if grids['grids'].size == 0
12
- puts "You don't have any grids yet. Create first one with 'kontena grids create' command".colorize(:yellow)
12
+ puts "You don't have any grids yet. Create first one with 'kontena grid create' command".colorize(:yellow)
13
13
  end
14
14
 
15
15
  puts '%-30.30s %-8s %-12s %-10s' % ['Name', 'Nodes', 'Services', 'Users']
@@ -6,18 +6,18 @@ module Kontena::Cli::Master::Aws
6
6
 
7
7
  option "--access-key", "ACCESS_KEY", "AWS access key ID", required: true
8
8
  option "--secret-key", "SECRET_KEY", "AWS secret key", required: true
9
- option "--key-pair", "KEY_PAIR", "EC2 Key Pair", required: true
10
- option "--ssl-cert", "SSL CERT", "SSL certificate file"
9
+ option "--key-pair", "KEY_PAIR", "EC2 key pair name", required: true
10
+ option "--ssl-cert", "SSL CERT", "SSL certificate file (default: generate self-signed cert)"
11
11
  option "--region", "REGION", "EC2 Region", default: 'eu-west-1'
12
12
  option "--zone", "ZONE", "EC2 Availability Zone", default: 'a'
13
- option "--vpc-id", "VPC ID", "Virtual Private Cloud (VPC) ID"
14
- option "--subnet-id", "SUBNET ID", "VPC option to specify subnet to launch instance into"
13
+ option "--vpc-id", "VPC ID", "Virtual Private Cloud (VPC) ID (default: default vpc)"
14
+ option "--subnet-id", "SUBNET ID", "VPC option to specify subnet to launch instance into (default: first subnet from vpc/az)"
15
15
  option "--type", "SIZE", "Instance type", default: 't2.small'
16
16
  option "--storage", "STORAGE", "Storage size (GiB)", default: '30'
17
- option "--vault-secret", "VAULT_SECRET", "Secret key for Vault"
18
- option "--vault-iv", "VAULT_IV", "Initialization vector for Vault"
17
+ option "--vault-secret", "VAULT_SECRET", "Secret key for Vault (default: generate random secret)"
18
+ option "--vault-iv", "VAULT_IV", "Initialization vector for Vault (default: generate random iv)"
19
19
  option "--version", "VERSION", "Define installed Kontena version", default: 'latest'
20
- option "--auth-provider-url", "AUTH_PROVIDER_URL", "Define authentication provider url"
20
+ option "--auth-provider-url", "AUTH_PROVIDER_URL", "Define authentication provider url (optional)"
21
21
 
22
22
  def execute
23
23
  require 'kontena/machine/aws'
@@ -0,0 +1,22 @@
1
+ require_relative '../../common'
2
+
3
+ module Kontena::Cli::Master::Users
4
+ class RemoveCommand < Clamp::Command
5
+ include Kontena::Cli::Common
6
+
7
+ parameter "EMAIL ...", "List of emails"
8
+
9
+ def execute
10
+ require_api_url
11
+ token = require_token
12
+ email_list.each do |email|
13
+ begin
14
+ client(token).delete("users/#{email}")
15
+ rescue => exc
16
+ STDERR.puts "Failed to remove user #{email}".colorize(:red)
17
+ STDERR.puts exc.message
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -1,12 +1,14 @@
1
1
  module Kontena::Cli::Master
2
2
 
3
- require_relative 'users/add_role_command'
4
3
  require_relative 'users/invite_command'
4
+ require_relative 'users/remove_command'
5
5
  require_relative 'users/list_command'
6
+ require_relative 'users/add_role_command'
6
7
  require_relative 'users/remove_role_command'
7
8
 
8
9
  class UsersCommand < Clamp::Command
9
10
  subcommand "invite", "Invite user to Kontena Master", Users::InviteCommand
11
+ subcommand ["remove", "rm"], "Remove user from Kontena Master", Users::RemoveCommand
10
12
  subcommand ["list", "ls"], "List users", Users::ListCommand
11
13
  subcommand "add-role", "Add role to user", Users::AddRoleCommand
12
14
  subcommand "remove-role", "Remove role from user", Users::RemoveRoleCommand
@@ -6,11 +6,11 @@ module Kontena::Cli::Nodes::Aws
6
6
  parameter "[NAME]", "Node name"
7
7
  option "--access-key", "ACCESS_KEY", "AWS access key ID", required: true
8
8
  option "--secret-key", "SECRET_KEY", "AWS secret key", required: true
9
+ option "--key-pair", "KEY_PAIR", "EC2 Key Pair", required: true
9
10
  option "--region", "REGION", "EC2 Region", default: 'eu-west-1'
10
11
  option "--zone", "ZONE", "EC2 Availability Zone", default: 'a'
11
- option "--vpc-id", "VPC ID", "Virtual Private Cloud (VPC) ID"
12
- option "--subnet-id", "SUBNET ID", "VPC option to specify subnet to launch instance into"
13
- option "--key-pair", "KEY_PAIR", "EC2 Key Pair", required: true
12
+ option "--vpc-id", "VPC ID", "Virtual Private Cloud (VPC) ID (default: default vpc)"
13
+ option "--subnet-id", "SUBNET ID", "VPC option to specify subnet to launch instance into (default: first subnet in vpc/az)"
14
14
  option "--type", "SIZE", "Instance type", default: 't2.small'
15
15
  option "--storage", "STORAGE", "Storage size (GiB)", default: '30'
16
16
  option "--version", "VERSION", "Define installed Kontena version", default: 'latest'
@@ -6,7 +6,7 @@ module Kontena::Cli::Nodes::Aws
6
6
  parameter "NAME", "Node name"
7
7
  option "--access-key", "ACCESS_KEY", "AWS access key ID", required: true
8
8
  option "--secret-key", "SECRET_KEY", "AWS secret key", required: true
9
- option "--region", "REGION", "EC2 Region", required: true
9
+ option "--region", "REGION", "EC2 Region", default: 'eu-west-1'
10
10
 
11
11
  def execute
12
12
  require_api_url
@@ -18,7 +18,7 @@ module Kontena::Cli::Services
18
18
  puts " rev: #{container['deploy_rev']}"
19
19
  puts " node: #{container['node']['name']}"
20
20
  puts " dns: #{container['name']}.#{current_grid}.kontena.local"
21
- puts " ip: #{container['overlay_cidr'].split('/')[0]}"
21
+ puts " ip: #{container['overlay_cidr'].to_s.split('/')[0]}"
22
22
  puts " public ip: #{container['node']['public_ip']}"
23
23
  if container['status'] == 'unknown'
24
24
  puts " status: #{container['status'].colorize(:yellow)}"
@@ -7,9 +7,11 @@ module Kontena::Cli::Vault
7
7
  require_api_url
8
8
  token = require_token
9
9
  result = client(token).get("grids/#{current_grid}/secrets")
10
- puts '%-30.30s %-30.30s' % ['NAME', 'CREATED AT']
10
+
11
+ column_width_paddings = '%-54s %-25.25s'
12
+ puts column_width_paddings % ['NAME', 'CREATED AT']
11
13
  result['secrets'].each do |secret|
12
- puts '%-30.30s %-30.30s' % [secret['name'], secret['created_at']]
14
+ puts column_width_paddings % [secret['name'], secret['created_at']]
13
15
  end
14
16
  end
15
17
  end
@@ -1,13 +1,13 @@
1
1
  begin
2
- require "fog/aws"
2
+ require "aws-sdk"
3
3
  rescue LoadError
4
4
  puts "It seems that you don't have gem for AWS API installed."
5
- puts "Install it using: gem install fog-aws"
5
+ puts "Install it using: gem install aws-sdk"
6
6
  exit 1
7
7
  end
8
8
 
9
9
  require_relative 'random_name'
10
+ require_relative 'cert_helper'
10
11
  require_relative 'aws/master_provisioner'
11
12
  require_relative 'aws/node_provisioner'
12
13
  require_relative 'aws/node_destroyer'
13
-
@@ -20,7 +20,23 @@ module Kontena
20
20
  }
21
21
  images[region]
22
22
  end
23
-
23
+
24
+ # @param [String] vpc_id
25
+ # @param [String] zone
26
+ # @return [Aws::EC2::Types::Subnet, NilClass]
27
+ def default_subnet(vpc_id, zone)
28
+ ec2.subnets({
29
+ filters: [
30
+ {name: "vpc-id", values: [vpc_id]},
31
+ {name: "availability-zone", values: [zone]}
32
+ ]
33
+ }).first
34
+ end
35
+
36
+ # @return [Aws::EC2::Types::Vpc, NilClass]
37
+ def default_vpc
38
+ ec2.vpcs({filters: [{name: "is-default", values: ["true"]}]}).first
39
+ end
24
40
  end
25
41
  end
26
42
  end
@@ -10,35 +10,37 @@ module Kontena
10
10
  class MasterProvisioner
11
11
  include RandomName
12
12
  include Common
13
- attr_reader :client, :http_client, :region
13
+ include Machine::CertHelper
14
+ attr_reader :ec2, :http_client, :region
14
15
 
15
16
  # @param [String] access_key_id aws_access_key_id
16
17
  # @param [String] secret_key aws_secret_access_key
17
18
  # @param [String] region
18
19
  def initialize(access_key_id, secret_key, region)
19
- @client = Fog::Compute.new(
20
- :provider => 'AWS',
21
- :aws_access_key_id => access_key_id,
22
- :aws_secret_access_key => secret_key,
23
- :region => region
20
+ @ec2 = ::Aws::EC2::Resource.new(
21
+ region: region, credentials: ::Aws::Credentials.new(access_key_id, secret_key)
24
22
  )
25
23
  end
26
24
 
27
25
  # @param [Hash] opts
28
26
  def run!(opts)
27
+ ssl_cert = nil
29
28
  if opts[:ssl_cert]
30
29
  abort('Invalid ssl cert') unless File.exists?(File.expand_path(opts[:ssl_cert]))
31
30
  ssl_cert = File.read(File.expand_path(opts[:ssl_cert]))
31
+ else
32
+ ShellSpinner "Generating self-signed SSL certificate" do
33
+ ssl_cert = generate_self_signed_cert
34
+ end
32
35
  end
33
36
 
34
- ami = resolve_ami(client.region)
37
+ ami = resolve_ami(region)
35
38
  abort('No valid AMI found for region') unless ami
36
- opts[:vpc] = default_vpc.id unless opts[:vpc]
39
+ opts[:vpc] = default_vpc.vpc_id unless opts[:vpc]
37
40
  if opts[:subnet].nil?
38
- subnet = default_subnet(opts[:vpc], client.region+opts[:zone])
39
- opts[:subnet] = subnet.subnet_id
41
+ subnet = default_subnet(opts[:vpc], region+opts[:zone])
40
42
  else
41
- subnet = client.subnets.get(opts[:subnet])
43
+ subnet = ec2.subnet(opts[:subnet])
42
44
  end
43
45
  userdata_vars = {
44
46
  ssl_cert: ssl_cert,
@@ -50,41 +52,39 @@ module Kontena
50
52
 
51
53
  security_group = ensure_security_group(opts[:vpc])
52
54
  name = generate_name
53
- response = client.run_instances(
54
- ami,
55
- 1,
56
- 1,
57
- 'InstanceType' => opts[:type],
58
- 'SecurityGroupId' => security_group.group_id,
59
- 'KeyName' => opts[:key_pair],
60
- 'SubnetId' => opts[:subnet],
61
- 'UserData' => user_data(userdata_vars),
62
- 'BlockDeviceMapping' => [
63
- {
64
- 'DeviceName' => '/dev/xvda',
65
- 'VirtualName' => 'Root',
66
- 'Ebs.VolumeSize' => opts[:storage],
67
- 'Ebs.VolumeType' => 'gp2'
68
- }
69
- ]
70
-
71
- )
72
- instance_id = response.body['instancesSet'].first['instanceId']
73
-
74
- instance = client.servers.get(instance_id)
55
+ ec2_instance = ec2.create_instances({
56
+ image_id: ami,
57
+ min_count: 1,
58
+ max_count: 1,
59
+ instance_type: opts[:type],
60
+ security_group_ids: [security_group.group_id],
61
+ key_name: opts[:key_pair],
62
+ subnet_id: subnet.subnet_id,
63
+ user_data: Base64.encode64(user_data(userdata_vars)),
64
+ block_device_mappings: [
65
+ {
66
+ device_name: '/dev/xvda',
67
+ virtual_name: 'Root',
68
+ ebs: {
69
+ volume_size: opts[:storage],
70
+ volume_type: 'gp2'
71
+ }
72
+ }
73
+ ]
74
+ }).first
75
+ ec2_instance.create_tags({
76
+ tags: [
77
+ {key: 'Name', value: name}
78
+ ]
79
+ })
75
80
  ShellSpinner "Creating AWS instance #{name.colorize(:cyan)} " do
76
- instance.wait_for { ready? }
77
- end
78
- if opts[:ssl_cert]
79
- master_url = "https://#{instance.public_ip_address}"
80
- else
81
- master_url = "http://#{instance.public_ip_address}"
81
+ sleep 5 until ec2_instance.reload.state.name == 'running'
82
82
  end
83
+ master_url = "https://#{ec2_instance.public_ip_address}"
83
84
  Excon.defaults[:ssl_verify_peer] = false
84
- @http_client = Excon.new("#{master_url}", :connect_timeout => 10)
85
-
85
+ http_client = Excon.new(master_url, :connect_timeout => 10)
86
86
  ShellSpinner "Waiting for #{name.colorize(:cyan)} to start" do
87
- sleep 5 until master_running?
87
+ sleep 5 until master_running?(http_client)
88
88
  end
89
89
 
90
90
  puts "Kontena Master is now running at #{master_url}"
@@ -92,38 +92,57 @@ module Kontena
92
92
  end
93
93
 
94
94
  ##
95
- # @param [String] grid
96
- # @return Fog::Compute::AWS::SecurityGroup
95
+ # @param [String] vpc_id
96
+ # @return [Aws::EC2::SecurityGroup]
97
97
  def ensure_security_group(vpc_id)
98
98
  group_name = "kontena_master"
99
- if vpc_id
100
- client.security_groups.all({'group-name' => group_name, 'vpc-id' => vpc_id}).first || create_security_group(group_name, vpc_id)
101
- else
102
- client.security_groups.get(group_name) || create_security_group(group_name)
99
+ sg = ec2.security_groups({
100
+ filters: [
101
+ {name: 'group-name', values: [group_name]},
102
+ {name: 'vpc-id', values: [vpc_id]}
103
+ ]
104
+ }).first
105
+ unless sg
106
+ ShellSpinner "Creating AWS security group" do
107
+ sg = create_security_group(group_name, vpc_id)
108
+ end
103
109
  end
110
+ sg
104
111
  end
105
112
 
106
113
  ##
107
114
  # creates security_group and authorizes default port ranges
108
115
  #
109
116
  # @param [String] name
110
- # @return Fog::Compute::AWS::SecurityGroup
117
+ # @param [String, NilClass] vpc_id
118
+ # @return Aws::EC2::SecurityGroup
111
119
  def create_security_group(name, vpc_id = nil)
112
- security_group = client.security_groups.new(:name => name, :description => "Kontena Master", :vpc_id => vpc_id)
113
- security_group.save
114
-
115
- security_group.authorize_port_range(80..80)
116
- security_group.authorize_port_range(443..443)
117
- security_group.authorize_port_range(22..22)
118
- security_group
120
+ sg = ec2.create_security_group({
121
+ group_name: name,
122
+ description: "Kontena Master",
123
+ vpc_id: vpc_id
124
+ })
125
+
126
+ sg.authorize_ingress({
127
+ ip_protocol: 'tcp',
128
+ from_port: 443,
129
+ to_port: 443,
130
+ cidr_ip: '0.0.0.0/0'
131
+ })
132
+
133
+ sg.authorize_ingress({
134
+ ip_protocol: 'tcp',
135
+ from_port: 22,
136
+ to_port: 22,
137
+ cidr_ip: '0.0.0.0/0'
138
+ })
139
+
140
+ sg
119
141
  end
120
142
 
121
- def default_subnet(vpc, zone)
122
- client.subnets.all('vpc-id' => vpc, 'availabilityZone' => zone).first
123
- end
124
-
125
- def default_vpc
126
- client.vpcs.all('isDefault' => true).first
143
+ # @return [String]
144
+ def region
145
+ ec2.client.config.region
127
146
  end
128
147
 
129
148
  def user_data(vars)
@@ -135,14 +154,16 @@ module Kontena
135
154
  "kontena-master-#{super}-#{rand(1..99)}"
136
155
  end
137
156
 
138
- def master_running?
157
+ def master_running?(http_client)
139
158
  http_client.get(path: '/').status == 200
140
159
  rescue
141
160
  false
142
161
  end
143
162
 
144
163
  def erb(template, vars)
145
- ERB.new(template).result(OpenStruct.new(vars).instance_eval { binding })
164
+ ERB.new(template).result(
165
+ OpenStruct.new(vars).instance_eval { binding }
166
+ )
146
167
  end
147
168
  end
148
169
  end
@@ -5,7 +5,7 @@ module Kontena
5
5
  module Aws
6
6
  class NodeDestroyer
7
7
 
8
- attr_reader :client, :api_client
8
+ attr_reader :ec2, :api_client
9
9
 
10
10
  # @param [Kontena::Client] api_client Kontena api client
11
11
  # @param [String] access_key_id aws_access_key_id
@@ -13,15 +13,27 @@ module Kontena
13
13
  # @param [String] region
14
14
  def initialize(api_client, access_key_id, secret_key, region = 'eu-west-1')
15
15
  @api_client = api_client
16
- @client = Fog::Compute.new(:provider => 'AWS', :aws_access_key_id => access_key_id, :aws_secret_access_key => secret_key, :region => region)
16
+ @ec2 = ::Aws::EC2::Resource.new(
17
+ region: region,
18
+ credentials: ::Aws::Credentials.new(access_key_id, secret_key)
19
+ )
17
20
  end
18
21
 
19
22
  def run!(grid, name)
20
- instance = client.servers.all({'tag:Name' => name}).first
23
+ instances = ec2.instances({
24
+ filters: [
25
+ {name: 'tag:Name', values: [name]}
26
+ ]
27
+ })
28
+ abort("Cannot find AWS instance #{name}") if instances.to_a.size == 0
29
+ abort("There are multiple instances with name #{name}") if instances.to_a.size > 1
30
+ instance = instances.first
21
31
  if instance
22
32
  ShellSpinner "Terminating AWS instance #{name.colorize(:cyan)} " do
23
- instance.destroy
24
- sleep 2 until client.servers.get(instance.id).state == 'terminated'
33
+ instance.terminate
34
+ until instance.reload.state.name.to_s == 'terminated'
35
+ sleep 2
36
+ end
25
37
  end
26
38
  else
27
39
  abort "Cannot find instance #{name.colorize(:cyan)} in AWS"
@@ -11,7 +11,7 @@ module Kontena
11
11
  include RandomName
12
12
  include Common
13
13
 
14
- attr_reader :client, :api_client, :region
14
+ attr_reader :ec2, :api_client
15
15
 
16
16
  # @param [Kontena::Client] api_client Kontena api client
17
17
  # @param [String] access_key_id aws_access_key_id
@@ -19,106 +19,141 @@ module Kontena
19
19
  # @param [String] region
20
20
  def initialize(api_client, access_key_id, secret_key, region)
21
21
  @api_client = api_client
22
- @client = Fog::Compute.new(
23
- :provider => 'AWS', :aws_access_key_id => access_key_id,
24
- :aws_secret_access_key => secret_key, :region => region
22
+ @ec2 = ::Aws::EC2::Resource.new(
23
+ region: region, credentials: ::Aws::Credentials.new(access_key_id, secret_key)
25
24
  )
26
25
  end
27
26
 
28
27
  # @param [Hash] opts
29
28
  def run!(opts)
30
- ami = resolve_ami(client.region)
29
+ ami = resolve_ami(region)
31
30
  abort('No valid AMI found for region') unless ami
32
31
 
32
+ opts[:vpc] = default_vpc.vpc_id unless opts[:vpc]
33
+
33
34
  security_group = ensure_security_group(opts[:grid], opts[:vpc])
34
35
  name = opts[:name ] || generate_name
35
36
 
36
- opts[:vpc] = default_vpc.id unless opts[:vpc]
37
+
37
38
  if opts[:subnet].nil?
38
- subnet = default_subnet(opts[:vpc], client.region+opts[:zone])
39
- opts[:subnet] = subnet.subnet_id
39
+ subnet = default_subnet(opts[:vpc], region+opts[:zone])
40
40
  else
41
- subnet = client.subnets.get(opts[:subnet])
41
+ subnet = ec2.subnet(opts[:subnet])
42
42
  end
43
43
  dns_server = aws_dns_supported?(opts[:vpc]) ? '169.254.169.253' : '8.8.8.8'
44
44
  userdata_vars = {
45
- name: name,
46
- version: opts[:version],
47
- master_uri: opts[:master_uri],
48
- grid_token: opts[:grid_token],
49
- dns_server: dns_server
45
+ name: name,
46
+ version: opts[:version],
47
+ master_uri: opts[:master_uri],
48
+ grid_token: opts[:grid_token],
49
+ dns_server: dns_server
50
50
  }
51
51
 
52
- response = client.run_instances(
53
- ami,
54
- 1,
55
- 1,
56
- 'InstanceType' => opts[:type],
57
- 'SecurityGroupId' => security_group.group_id,
58
- 'KeyName' => opts[:key_pair],
59
- 'SubnetId' => opts[:subnet],
60
- 'UserData' => user_data(userdata_vars),
61
- 'BlockDeviceMapping' => [
62
- {
63
- 'DeviceName' => '/dev/xvda',
64
- 'VirtualName' => 'Root',
65
- 'Ebs.VolumeSize' => opts[:storage],
66
- 'Ebs.VolumeType' => 'gp2'
67
- }
68
- ]
69
-
70
- )
71
- instance_id = response.body['instancesSet'].first['instanceId']
52
+ ec2_instance = ec2.create_instances({
53
+ image_id: ami,
54
+ min_count: 1,
55
+ max_count: 1,
56
+ instance_type: opts[:type],
57
+ security_group_ids: [security_group.group_id],
58
+ key_name: opts[:key_pair],
59
+ subnet_id: subnet.subnet_id,
60
+ user_data: Base64.encode64(user_data(userdata_vars)),
61
+ block_device_mappings: [
62
+ {
63
+ device_name: '/dev/xvda',
64
+ virtual_name: 'Root',
65
+ ebs: {
66
+ volume_size: opts[:storage],
67
+ volume_type: 'gp2'
68
+ }
69
+ }
70
+ ]
71
+ }).first
72
+ ec2_instance.create_tags({
73
+ tags: [
74
+ {key: 'Name', value: name},
75
+ {key: 'kontena_grid', value: opts[:grid]}
76
+ ]
77
+ })
72
78
 
73
- instance = client.servers.get(instance_id)
74
79
  ShellSpinner "Creating AWS instance #{name.colorize(:cyan)} " do
75
- instance.wait_for { ready? }
80
+ sleep 5 until ec2_instance.reload.state.name == 'running'
76
81
  end
77
- client.create_tags(instance.id, {'Name' => name, 'kontena_grid' => opts[:grid]})
78
82
  node = nil
79
83
  ShellSpinner "Waiting for node #{name.colorize(:cyan)} join to grid #{opts[:grid].colorize(:cyan)} " do
80
84
  sleep 2 until node = instance_exists_in_grid?(opts[:grid], name)
81
85
  end
82
- labels = ["region=#{client.region}", "az=#{opts[:zone]}"]
86
+ labels = ["region=#{region}", "az=#{opts[:zone]}"]
83
87
  set_labels(node, labels)
84
88
  end
85
89
 
86
90
  ##
87
91
  # @param [String] grid
88
- # @return Fog::Compute::AWS::SecurityGroup
92
+ # @return [Aws::EC2::SecurityGroup]
89
93
  def ensure_security_group(grid, vpc_id)
90
94
  group_name = "kontena_grid_#{grid}"
91
- if vpc_id
92
- client.security_groups.all({'group-name' => group_name, 'vpc-id' => vpc_id}).first || create_security_group(group_name, vpc_id)
93
- else
94
- client.security_groups.get(group_name) || create_security_group(group_name)
95
+ sg = ec2.security_groups({
96
+ filters: [
97
+ {name: 'group-name', values: [group_name]},
98
+ {name: 'vpc-id', values: [vpc_id]}
99
+ ]
100
+ }).first
101
+ unless sg
102
+ ShellSpinner "Creating AWS security group" do
103
+ sg = create_security_group(group_name, vpc_id)
104
+ end
95
105
  end
106
+ sg
96
107
  end
97
108
 
98
109
  ##
99
110
  # creates security_group and authorizes default port ranges
100
111
  #
101
112
  # @param [String] name
102
- # @return Fog::Compute::AWS::SecurityGroup
103
- def create_security_group(name, vpc_id = nil)
104
- security_group = client.security_groups.new(:name => name, :description => "Kontena Node", :vpc_id => vpc_id)
105
- security_group.save
106
-
107
- security_group.authorize_port_range(80..80)
108
- security_group.authorize_port_range(443..443)
109
- security_group.authorize_port_range(22..22)
110
- security_group.authorize_port_range(1194..1194, ip_protocol: 'udp')
111
- security_group.authorize_port_range(6783..6783, group: {security_group.owner_id => security_group.group_id}, ip_protocol: 'tcp')
112
- security_group.authorize_port_range(6783..6784, group: {security_group.owner_id => security_group.group_id}, ip_protocol: 'udp')
113
- security_group
114
- end
115
-
116
- def default_subnet(vpc, zone)
117
- client.subnets.all('vpc-id' => vpc, 'availabilityZone' => zone).first
113
+ # @param [String] vpc_id
114
+ # @return [Aws::EC2::SecurityGroup]
115
+ def create_security_group(name, vpc_id)
116
+ sg = ec2.create_security_group({
117
+ group_name: name,
118
+ description: "Kontena Grid",
119
+ vpc_id: vpc_id
120
+ })
121
+
122
+ sg.authorize_ingress({ # SSH
123
+ ip_protocol: 'tcp', from_port: 22, to_port: 22, cidr_ip: '0.0.0.0/0'
124
+ })
125
+ sg.authorize_ingress({ # HTTP
126
+ ip_protocol: 'tcp', from_port: 80, to_port: 80, cidr_ip: '0.0.0.0/0'
127
+ })
128
+ sg.authorize_ingress({ # HTTPS
129
+ ip_protocol: 'tcp', from_port: 443, to_port: 443, cidr_ip: '0.0.0.0/0'
130
+ })
131
+ sg.authorize_ingress({ # OpenVPN
132
+ ip_protocol: 'udp', from_port: 1194, to_port: 1194, cidr_ip: '0.0.0.0/0'
133
+ })
134
+ sg.authorize_ingress({ # Overlay / Weave network
135
+ ip_permissions: [
136
+ {
137
+ from_port: 6783, to_port: 6783, ip_protocol: 'tcp',
138
+ user_id_group_pairs: [
139
+ { group_id: sg.group_id, vpc_id: vpc_id }
140
+ ]
141
+ },
142
+ {
143
+ from_port: 6783, to_port: 6784, ip_protocol: 'udp',
144
+ user_id_group_pairs: [
145
+ { group_id: sg.group_id, vpc_id: vpc_id }
146
+ ]
147
+ }
148
+ ]
149
+ })
150
+
151
+ sg
118
152
  end
119
153
 
120
- def default_vpc
121
- client.vpcs.all('isDefault' => true).first
154
+ # @return [String]
155
+ def region
156
+ ec2.client.config.region
122
157
  end
123
158
 
124
159
  def user_data(vars)
@@ -138,15 +173,20 @@ module Kontena
138
173
  ERB.new(template).result(OpenStruct.new(vars).instance_eval { binding })
139
174
  end
140
175
 
176
+ # @param [Hash] node
177
+ # @param [Array<String>] labels
141
178
  def set_labels(node, labels)
142
179
  data = {}
143
180
  data[:labels] = labels
144
181
  api_client.put("nodes/#{node['id']}", data, {}, {'Kontena-Grid-Token' => node['grid']['token']})
145
182
  end
146
183
 
184
+ # @param [String] vpc_id
185
+ # @return [Boolean]
147
186
  def aws_dns_supported?(vpc_id)
148
- response = client.describe_vpc_attribute(vpc_id,'enableDnsSupport')
149
- response.data[:body]['enableDnsSupport']
187
+ vpc = ec2.vpc(vpc_id)
188
+ response = vpc.describe_attribute({attribute: 'enableDnsSupport'})
189
+ response.enable_dns_support
150
190
  end
151
191
  end
152
192
  end
@@ -0,0 +1,39 @@
1
+ require 'openssl'
2
+
3
+ module Kontena
4
+ module Machine
5
+ module CertHelper
6
+
7
+ def generate_self_signed_cert
8
+ key = OpenSSL::PKey::RSA.new(2048)
9
+ public_key = key.public_key
10
+
11
+ subject = "/C=FI/O=Test/OU=Test/CN=Test"
12
+
13
+ cert = OpenSSL::X509::Certificate.new
14
+ cert.subject = cert.issuer = OpenSSL::X509::Name.parse(subject)
15
+ cert.not_before = Time.now
16
+ cert.not_after = Time.now + (10 * 365 * 24 * 60 * 60)
17
+ cert.public_key = public_key
18
+ cert.serial = 0x0
19
+ cert.version = 2
20
+
21
+ ef = OpenSSL::X509::ExtensionFactory.new
22
+ ef.subject_certificate = cert
23
+ ef.issuer_certificate = cert
24
+ cert.extensions = [
25
+ ef.create_extension("basicConstraints","CA:TRUE", true),
26
+ ef.create_extension("subjectKeyIdentifier", "hash")
27
+ ]
28
+ cert.add_extension ef.create_extension("authorityKeyIdentifier",
29
+ "keyid:always,issuer:always")
30
+
31
+ cert.sign key, OpenSSL::Digest::SHA1.new
32
+
33
+ pem = cert.to_pem
34
+ pem << key.to_s
35
+ pem
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,28 @@
1
+ require_relative "../../../../spec_helper"
2
+ require 'kontena/cli/master/users_command'
3
+ require "kontena/cli/master/users/remove_command"
4
+
5
+ describe Kontena::Cli::Master::Users::RemoveCommand do
6
+
7
+ include ClientHelpers
8
+
9
+ describe '#execute' do
10
+
11
+ it 'requires api url' do
12
+ expect(subject).to receive(:require_api_url).once
13
+ subject.run(['john@domain.com'])
14
+ end
15
+
16
+ it 'requires token' do
17
+ expect(subject).to receive(:require_token).and_return(token)
18
+ subject.run(['john@domain.com'])
19
+ end
20
+
21
+ it 'sends email to master' do
22
+ expect(client).to receive(:delete).with(
23
+ 'users/john@domain.com'
24
+ )
25
+ subject.run(['john@domain.com'])
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,48 @@
1
+ require_relative "../../../spec_helper"
2
+ require "kontena/cli/services/containers_command"
3
+
4
+ describe Kontena::Cli::Services::ContainersCommand do
5
+
6
+ include ClientHelpers
7
+
8
+ describe '#execute' do
9
+
10
+ before(:each) do
11
+ allow(client).to receive(:get).and_return({
12
+ 'containers' => []
13
+ })
14
+ end
15
+
16
+ it 'requires api url' do
17
+ expect(subject).to receive(:require_api_url).once
18
+ subject.run(['service-a'])
19
+ end
20
+
21
+ it 'requires token' do
22
+ expect(subject).to receive(:require_token).and_return(token)
23
+ subject.run(['service-a'])
24
+ end
25
+
26
+ it 'to not throw on missing "overlay_cidr" property' do
27
+ allow(client).to receive(:get).and_return({
28
+ 'containers' => [
29
+ {'id' => "service-a-id", 'node' => {'public_ip' => ""}}
30
+ ]
31
+ })
32
+ expect {
33
+ subject.run(['service-a'])
34
+ }.to_not raise_error(NoMethodError)
35
+ end
36
+
37
+ it 'to not throw on nil "overlay_cidr" property' do
38
+ allow(client).to receive(:get).and_return({
39
+ 'containers' => [
40
+ {'id' => "service-a-id", 'node' => {'public_ip' => ""}, 'overlay_cidr' => nil}
41
+ ]
42
+ })
43
+ expect {
44
+ subject.run(['service-a'])
45
+ }.to_not raise_error(NoMethodError)
46
+ end
47
+ end
48
+ end
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: 0.12.0
4
+ version: 0.12.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kontena, Inc
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-04-04 00:00:00.000000000 Z
11
+ date: 2016-04-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -205,6 +205,7 @@ files:
205
205
  - lib/kontena/cli/master/users/add_role_command.rb
206
206
  - lib/kontena/cli/master/users/invite_command.rb
207
207
  - lib/kontena/cli/master/users/list_command.rb
208
+ - lib/kontena/cli/master/users/remove_command.rb
208
209
  - lib/kontena/cli/master/users/remove_role_command.rb
209
210
  - lib/kontena/cli/master/users_command.rb
210
211
  - lib/kontena/cli/master/vagrant/create_command.rb
@@ -305,6 +306,7 @@ files:
305
306
  - lib/kontena/machine/azure/master_provisioner.rb
306
307
  - lib/kontena/machine/azure/node_destroyer.rb
307
308
  - lib/kontena/machine/azure/node_provisioner.rb
309
+ - lib/kontena/machine/cert_helper.rb
308
310
  - lib/kontena/machine/cloud_config/cloudinit.yml
309
311
  - lib/kontena/machine/cloud_config/node_generator.rb
310
312
  - lib/kontena/machine/common.rb
@@ -339,9 +341,11 @@ files:
339
341
  - spec/kontena/cli/master/use_command_spec.rb
340
342
  - spec/kontena/cli/master/users/add_role_command_spec.rb
341
343
  - spec/kontena/cli/master/users/invite_command_spec.rb
344
+ - spec/kontena/cli/master/users/remove_command_spec.rb
342
345
  - spec/kontena/cli/master/users/remove_role_command_spec.rb
343
346
  - spec/kontena/cli/register_command_spec.rb
344
347
  - spec/kontena/cli/services/add_secret_command_spec.rb
348
+ - spec/kontena/cli/services/containers_command_spec.rb
345
349
  - spec/kontena/cli/services/link_command_spec.rb
346
350
  - spec/kontena/cli/services/remove_secret_command_spec.rb
347
351
  - spec/kontena/cli/services/restart_command_spec.rb
@@ -391,9 +395,11 @@ test_files:
391
395
  - spec/kontena/cli/master/use_command_spec.rb
392
396
  - spec/kontena/cli/master/users/add_role_command_spec.rb
393
397
  - spec/kontena/cli/master/users/invite_command_spec.rb
398
+ - spec/kontena/cli/master/users/remove_command_spec.rb
394
399
  - spec/kontena/cli/master/users/remove_role_command_spec.rb
395
400
  - spec/kontena/cli/register_command_spec.rb
396
401
  - spec/kontena/cli/services/add_secret_command_spec.rb
402
+ - spec/kontena/cli/services/containers_command_spec.rb
397
403
  - spec/kontena/cli/services/link_command_spec.rb
398
404
  - spec/kontena/cli/services/remove_secret_command_spec.rb
399
405
  - spec/kontena/cli/services/restart_command_spec.rb