kontena-cli 0.12.0 → 0.12.1

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: 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