kontena-plugin-aws 0.2.0.pre1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/lib/kontena/machine/aws/cloudinit.yml +10 -1
- data/lib/kontena/machine/aws/cloudinit_master.yml +4 -4
- data/lib/kontena/machine/aws/master_provisioner.rb +15 -8
- data/lib/kontena/machine/aws/node_provisioner.rb +67 -54
- data/lib/kontena/plugin/aws.rb +1 -1
- data/lib/kontena/plugin/aws/master/create_command.rb +28 -16
- data/lib/kontena/plugin/aws/nodes/create_command.rb +36 -14
- data/lib/kontena/plugin/aws/nodes/restart_command.rb +22 -7
- data/lib/kontena/plugin/aws/nodes/terminate_command.rb +25 -7
- data/lib/kontena/plugin/aws/prompts.rb +148 -0
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
OWYyM2NkMmM4YTdkZGU5ZDAzZWRiMzUyMjYwZDFjMDA0ZmI0ZTRkOA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MWM3MmY3NTgzMzQzZWFkZjQyODA2OTg5Yzk0ZmFkOTZiNTI3OTA0Nw==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
YTBhODExYWY2NzZkZjc0YTgxNTJhNjM5MDFhOGI0NTY0YTMyOTkxMzhmMmJm
|
10
|
+
Y2E1N2Y4NDJkNjc5MGMwZDQzMzY1YWFhMTUzY2VjZDM1ZDM2YTM3N2U0NDAw
|
11
|
+
MGU3MjNiMDBhYzI3YjZmYWMzZGQ5YjA4ODVlNWY1ZTc2OWY5ZjA=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MWUyZDlhY2Y5NzQ5MjQ0NTU0Njc4NTJmMjYxMmE0ZTJlZThkZjhmNzlkZGEw
|
14
|
+
NDE0MDliYWRmYjJkMmRkZmRlOGM3ZDU4YjlkYTNhODhhM2QzOTAyODg2YjFl
|
15
|
+
NGQ5MTczMDY0MjJhY2ZiZTJlNzAyMGZkNDY3YjI0MjczYzkwZjY=
|
@@ -33,7 +33,16 @@ coreos:
|
|
33
33
|
DOMAINS=kontena.local
|
34
34
|
[DHCP]
|
35
35
|
UseDNS=false
|
36
|
-
|
36
|
+
- name: etcd2.service
|
37
|
+
command: start
|
38
|
+
enable: true
|
39
|
+
content: |
|
40
|
+
Description=etcd 2.0
|
41
|
+
After=docker.service
|
42
|
+
[Service]
|
43
|
+
Restart=always
|
44
|
+
RestartSec=5
|
45
|
+
ExecStart=/usr/bin/docker logs --tail=10 -f kontena-etcd
|
37
46
|
- name: 10-weave.network
|
38
47
|
runtime: false
|
39
48
|
content: |
|
@@ -89,11 +89,11 @@ coreos:
|
|
89
89
|
--link kontena-server-mongo:mongodb \
|
90
90
|
-e MONGODB_URI=mongodb://mongodb:27017/kontena_server \
|
91
91
|
<% end -%>
|
92
|
-
<% if server_name
|
93
|
-
-e
|
92
|
+
<% if server_name -%>
|
93
|
+
-e SERVER_NAME=<%= server_name %> \
|
94
94
|
<% end -%>
|
95
|
-
<% if initial_admin_code
|
96
|
-
-e
|
95
|
+
<% if initial_admin_code -%>
|
96
|
+
-e INITIAL_ADMIN_CODE=<%= initial_admin_code %> \
|
97
97
|
<% end -%>
|
98
98
|
-e VAULT_KEY=${KONTENA_VAULT_KEY} -e VAULT_IV=${KONTENA_VAULT_IV} \
|
99
99
|
kontena/server:${KONTENA_VERSION}
|
@@ -2,6 +2,7 @@ require 'fileutils'
|
|
2
2
|
require 'erb'
|
3
3
|
require 'open3'
|
4
4
|
require 'securerandom'
|
5
|
+
require 'json'
|
5
6
|
|
6
7
|
require_relative 'common'
|
7
8
|
|
@@ -10,7 +11,7 @@ module Kontena::Machine::Aws
|
|
10
11
|
include Kontena::Machine::RandomName
|
11
12
|
include Kontena::Machine::CertHelper
|
12
13
|
include Common
|
13
|
-
include Kontena::Cli::
|
14
|
+
include Kontena::Cli::Common
|
14
15
|
|
15
16
|
attr_reader :ec2, :http_client, :region
|
16
17
|
|
@@ -30,7 +31,7 @@ module Kontena::Machine::Aws
|
|
30
31
|
abort('Invalid ssl cert') unless File.exists?(File.expand_path(opts[:ssl_cert]))
|
31
32
|
ssl_cert = File.read(File.expand_path(opts[:ssl_cert]))
|
32
33
|
else
|
33
|
-
spinner "Generating self-signed SSL certificate" do
|
34
|
+
spinner "Generating a self-signed SSL certificate" do
|
34
35
|
ssl_cert = generate_self_signed_cert
|
35
36
|
end
|
36
37
|
end
|
@@ -89,10 +90,11 @@ module Kontena::Machine::Aws
|
|
89
90
|
]
|
90
91
|
})
|
91
92
|
|
92
|
-
spinner "Creating AWS instance #{name.colorize(:cyan)} " do
|
93
|
+
spinner "Creating an AWS instance #{name.colorize(:cyan)} " do
|
93
94
|
sleep 1 until ec2_instance.reload.state.name == 'running'
|
94
95
|
end
|
95
96
|
public_ip = ec2_instance.reload.public_ip_address
|
97
|
+
master_version = nil
|
96
98
|
if public_ip.nil?
|
97
99
|
master_url = "https://#{ec2_instance.private_ip_address}"
|
98
100
|
puts "Could not get public IP for the created master, private connect url is: #{master_url}"
|
@@ -101,16 +103,21 @@ module Kontena::Machine::Aws
|
|
101
103
|
Excon.defaults[:ssl_verify_peer] = false
|
102
104
|
http_client = Excon.new(master_url, :connect_timeout => 10)
|
103
105
|
spinner "Waiting for #{name.colorize(:cyan)} to start " do
|
104
|
-
sleep
|
106
|
+
sleep 0.5 until master_running?(http_client)
|
105
107
|
end
|
108
|
+
|
109
|
+
spinner "Retrieving Kontena Master version" do
|
110
|
+
master_version = JSON.parse(http_client.get(path: '/').body)["version"] rescue nil
|
111
|
+
end
|
112
|
+
|
113
|
+
spinner "Kontena Master #{master_version} is now running at #{master_url}"
|
106
114
|
end
|
107
|
-
puts
|
108
|
-
puts "Kontena Master is now running at #{master_url}".colorize(:green)
|
109
|
-
puts
|
110
115
|
{
|
111
116
|
name: name.sub('kontena-master-', ''),
|
112
117
|
public_ip: public_ip,
|
113
|
-
code: opts[:initial_admin_code]
|
118
|
+
code: opts[:initial_admin_code],
|
119
|
+
provider: 'aws',
|
120
|
+
version: master_version
|
114
121
|
}
|
115
122
|
end
|
116
123
|
|
@@ -33,69 +33,82 @@ module Kontena::Machine::Aws
|
|
33
33
|
resolve_security_groups_to_ids(opts[:security_groups], opts[:vpc]) :
|
34
34
|
ensure_security_group(opts[:grid], opts[:vpc])
|
35
35
|
|
36
|
-
name = opts[:name ] || generate_name
|
37
|
-
|
38
36
|
if opts[:subnet].nil?
|
39
37
|
subnet = default_subnet(opts[:vpc], region+opts[:zone])
|
40
38
|
else
|
41
39
|
subnet = ec2.subnet(opts[:subnet])
|
42
40
|
end
|
43
41
|
dns_server = aws_dns_supported?(opts[:vpc]) ? '169.254.169.253' : '8.8.8.8'
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
image_id: ami,
|
54
|
-
min_count: 1,
|
55
|
-
max_count: 1,
|
56
|
-
instance_type: opts[:type],
|
57
|
-
key_name: opts[:key_pair],
|
58
|
-
user_data: Base64.encode64(user_data(userdata_vars)),
|
59
|
-
block_device_mappings: [
|
60
|
-
{
|
61
|
-
device_name: '/dev/xvda',
|
62
|
-
virtual_name: 'Root',
|
63
|
-
ebs: {
|
64
|
-
volume_size: opts[:storage],
|
65
|
-
volume_type: 'gp2'
|
66
|
-
}
|
67
|
-
}
|
68
|
-
],
|
69
|
-
network_interfaces: [
|
70
|
-
{
|
71
|
-
device_index: 0,
|
72
|
-
subnet_id: subnet.subnet_id,
|
73
|
-
groups: security_groups,
|
74
|
-
associate_public_ip_address: opts[:associate_public_ip],
|
75
|
-
delete_on_termination: true
|
76
|
-
}
|
77
|
-
]
|
78
|
-
}).first
|
79
|
-
ec2_instance.create_tags({
|
80
|
-
tags: [
|
81
|
-
{key: 'Name', value: name},
|
82
|
-
{key: 'kontena_grid', value: opts[:grid]}
|
83
|
-
]
|
84
|
-
})
|
42
|
+
instances = []
|
43
|
+
opts[:count].to_i.times do |i|
|
44
|
+
if opts[:name] && opts[:count].to_i > 1
|
45
|
+
name = "#{opts[:name]}-#{i+1}"
|
46
|
+
elsif opts[:name]
|
47
|
+
name = opts[:name]
|
48
|
+
else
|
49
|
+
name = generate_name
|
50
|
+
end
|
85
51
|
|
86
|
-
|
87
|
-
|
52
|
+
userdata_vars = {
|
53
|
+
name: name,
|
54
|
+
version: opts[:version],
|
55
|
+
master_uri: opts[:master_uri],
|
56
|
+
grid_token: opts[:grid_token],
|
57
|
+
dns_server: dns_server
|
58
|
+
}
|
59
|
+
|
60
|
+
ec2_instance = ec2.create_instances({
|
61
|
+
image_id: ami,
|
62
|
+
min_count: 1,
|
63
|
+
max_count: 1,
|
64
|
+
instance_type: opts[:type],
|
65
|
+
key_name: opts[:key_pair],
|
66
|
+
user_data: Base64.encode64(user_data(userdata_vars)),
|
67
|
+
block_device_mappings: [
|
68
|
+
{
|
69
|
+
device_name: '/dev/xvda',
|
70
|
+
virtual_name: 'Root',
|
71
|
+
ebs: {
|
72
|
+
volume_size: opts[:storage],
|
73
|
+
volume_type: 'gp2'
|
74
|
+
}
|
75
|
+
}
|
76
|
+
],
|
77
|
+
network_interfaces: [
|
78
|
+
{
|
79
|
+
device_index: 0,
|
80
|
+
subnet_id: subnet.subnet_id,
|
81
|
+
groups: security_groups,
|
82
|
+
associate_public_ip_address: opts[:associate_public_ip],
|
83
|
+
delete_on_termination: true
|
84
|
+
}
|
85
|
+
]
|
86
|
+
}).first
|
87
|
+
ec2_instance.create_tags({
|
88
|
+
tags: [
|
89
|
+
{key: 'Name', value: name},
|
90
|
+
{key: 'kontena_grid', value: opts[:grid]}
|
91
|
+
]
|
92
|
+
})
|
93
|
+
|
94
|
+
spinner "Creating AWS instance #{name.colorize(:cyan)} " do
|
95
|
+
sleep 1 until ec2_instance.reload.state.name == 'running'
|
96
|
+
end
|
97
|
+
instances << name
|
88
98
|
end
|
89
|
-
|
90
|
-
|
91
|
-
|
99
|
+
instances.each do |instance_name|
|
100
|
+
node = nil
|
101
|
+
spinner "Waiting for node #{instance_name.colorize(:cyan)} join to grid #{opts[:grid].colorize(:cyan)} " do
|
102
|
+
sleep 1 until node = instance_exists_in_grid?(opts[:grid], instance_name)
|
103
|
+
end
|
104
|
+
labels = [
|
105
|
+
"region=#{region}",
|
106
|
+
"az=#{opts[:zone]}",
|
107
|
+
"provider=aws",
|
108
|
+
"type=#{opts[:type]}"
|
109
|
+
]
|
110
|
+
set_labels(node, labels)
|
92
111
|
end
|
93
|
-
labels = [
|
94
|
-
"region=#{region}",
|
95
|
-
"az=#{opts[:zone]}",
|
96
|
-
"provider=aws"
|
97
|
-
]
|
98
|
-
set_labels(node, labels)
|
99
112
|
end
|
100
113
|
|
101
114
|
##
|
data/lib/kontena/plugin/aws.rb
CHANGED
@@ -1,20 +1,22 @@
|
|
1
1
|
require 'securerandom'
|
2
|
+
require_relative '../prompts'
|
2
3
|
|
3
4
|
module Kontena::Plugin::Aws::Master
|
4
5
|
class CreateCommand < Kontena::Command
|
5
6
|
include Kontena::Cli::Common
|
7
|
+
include Kontena::Plugin::Aws::Prompts
|
6
8
|
|
7
9
|
option "--name", "[NAME]", "Set Master name"
|
8
|
-
option "--access-key", "ACCESS_KEY", "AWS access key ID",
|
9
|
-
option "--secret-key", "SECRET_KEY", "AWS secret key",
|
10
|
-
option "--key-pair", "KEY_PAIR", "EC2 key pair name"
|
10
|
+
option "--access-key", "ACCESS_KEY", "AWS access key ID", environment_variable: "AWS_ACCESS_KEY_ID"
|
11
|
+
option "--secret-key", "SECRET_KEY", "AWS secret access key", environment_variable: "AWS_SECRET_ACCESS_KEY"
|
12
|
+
option "--key-pair", "KEY_PAIR", "EC2 key pair name"
|
11
13
|
option "--ssl-cert", "SSL CERT", "SSL certificate file (default: generate self-signed cert)"
|
12
|
-
option "--region", "REGION", "EC2 Region",
|
13
|
-
option "--zone", "ZONE", "EC2 Availability Zone
|
14
|
-
option "--vpc-id", "VPC ID", "Virtual Private Cloud (VPC) ID
|
15
|
-
option "--subnet-id", "SUBNET ID", "VPC option to specify subnet to launch instance into (default: first subnet
|
16
|
-
option "--type", "SIZE", "Instance type"
|
17
|
-
option "--storage", "STORAGE", "Storage size (GiB)"
|
14
|
+
option "--region", "REGION", "EC2 Region", environment_variable: "AWS_REGION"
|
15
|
+
option "--zone", "ZONE", "EC2 Availability Zone (a,b,c,d,e)"
|
16
|
+
option "--vpc-id", "VPC ID", "Virtual Private Cloud (VPC) ID"
|
17
|
+
option "--subnet-id", "SUBNET ID", "VPC option to specify subnet to launch instance into (default: first subnet in vpc/az)"
|
18
|
+
option "--type", "SIZE", "Instance type"
|
19
|
+
option "--storage", "STORAGE", "Storage size (GiB)"
|
18
20
|
option "--vault-secret", "VAULT_SECRET", "Secret key for Vault (default: generate random secret)"
|
19
21
|
option "--vault-iv", "VAULT_IV", "Initialization vector for Vault (default: generate random iv)"
|
20
22
|
option "--mongodb-uri", "URI", "External MongoDB uri (optional)"
|
@@ -24,18 +26,28 @@ module Kontena::Plugin::Aws::Master
|
|
24
26
|
|
25
27
|
def execute
|
26
28
|
require 'kontena/machine/aws'
|
29
|
+
aws_access_key = ask_aws_access_key
|
30
|
+
aws_secret_key = ask_aws_secret_key
|
31
|
+
aws_region = ask_aws_region(aws_access_key, aws_secret_key)
|
32
|
+
aws_zone = ask_aws_az(aws_access_key, aws_secret_key, aws_region)
|
33
|
+
aws_vpc_id = ask_aws_vpc(aws_access_key, aws_secret_key, aws_region)
|
27
34
|
|
28
|
-
|
35
|
+
exit_with_error("Could not find any Virtual Private Cloud (VPC). Please create one in the AWS console first.") unless aws_vpc_id
|
36
|
+
aws_subnet_id = ask_aws_subnet(aws_access_key, aws_secret_key, aws_region, aws_zone, aws_vpc_id)
|
37
|
+
aws_key_pair = ask_aws_key_pair(aws_access_key, aws_secret_key, aws_region)
|
38
|
+
aws_type = ask_aws_instance_type
|
39
|
+
aws_storage = ask_aws_storage
|
40
|
+
provisioner = provisioner(aws_access_key, aws_secret_key, aws_region)
|
29
41
|
provisioner.run!(
|
30
42
|
name: name,
|
31
|
-
type:
|
32
|
-
vpc:
|
33
|
-
zone:
|
34
|
-
subnet:
|
43
|
+
type: aws_type,
|
44
|
+
vpc: aws_vpc_id,
|
45
|
+
zone: aws_zone,
|
46
|
+
subnet: aws_subnet_id,
|
35
47
|
ssl_cert: ssl_cert,
|
36
|
-
storage:
|
48
|
+
storage: aws_storage,
|
37
49
|
version: version,
|
38
|
-
key_pair:
|
50
|
+
key_pair: aws_key_pair,
|
39
51
|
vault_secret: vault_secret || SecureRandom.hex(24),
|
40
52
|
vault_iv: vault_iv || SecureRandom.hex(24),
|
41
53
|
mongodb_uri: mongodb_uri,
|
@@ -2,17 +2,19 @@ module Kontena::Plugin::Aws::Nodes
|
|
2
2
|
class CreateCommand < Kontena::Command
|
3
3
|
include Kontena::Cli::Common
|
4
4
|
include Kontena::Cli::GridOptions
|
5
|
+
include Kontena::Plugin::Aws::Prompts
|
5
6
|
|
6
7
|
parameter "[NAME]", "Node name"
|
7
|
-
option "--access-key", "ACCESS_KEY", "AWS access key ID",
|
8
|
-
option "--secret-key", "SECRET_KEY", "AWS secret key",
|
9
|
-
option "--key-pair", "KEY_PAIR", "EC2 Key Pair"
|
10
|
-
option "--region", "REGION", "EC2 Region",
|
11
|
-
option "--zone", "ZONE", "EC2 Availability Zone
|
8
|
+
option "--access-key", "ACCESS_KEY", "AWS access key ID", environment_variable: "AWS_ACCESS_KEY_ID"
|
9
|
+
option "--secret-key", "SECRET_KEY", "AWS secret access key", environment_variable: "AWS_SECRET_ACCESS_KEY"
|
10
|
+
option "--key-pair", "KEY_PAIR", "EC2 Key Pair"
|
11
|
+
option "--region", "REGION", "EC2 Region", environment_variable: "AWS_REGION"
|
12
|
+
option "--zone", "ZONE", "EC2 Availability Zone (a,b,c,d,e)"
|
12
13
|
option "--vpc-id", "VPC ID", "Virtual Private Cloud (VPC) ID (default: default vpc)"
|
13
14
|
option "--subnet-id", "SUBNET ID", "VPC option to specify subnet to launch instance into (default: first subnet in vpc/az)"
|
14
|
-
option "--type", "SIZE", "Instance type"
|
15
|
-
option "--storage", "STORAGE", "Storage size (GiB)"
|
15
|
+
option "--type", "SIZE", "Instance type"
|
16
|
+
option "--storage", "STORAGE", "Storage size (GiB)"
|
17
|
+
option "--count", "COUNT", "How many instances to create"
|
16
18
|
option "--version", "VERSION", "Define installed Kontena version", default: 'latest'
|
17
19
|
option "--associate-public-ip-address", :flag, "Whether to associated public IP in case the VPC defaults to not doing it", default: true, attribute_name: :associate_public_ip
|
18
20
|
option "--security-groups", "SECURITY GROUPS", "Comma separated list of security groups (names) where the new instance will be attached (default: create grid specific group if not already existing)"
|
@@ -23,19 +25,31 @@ module Kontena::Plugin::Aws::Nodes
|
|
23
25
|
|
24
26
|
require 'kontena/machine/aws'
|
25
27
|
grid = fetch_grid(current_grid)
|
26
|
-
|
28
|
+
aws_access_key = ask_aws_access_key
|
29
|
+
aws_secret_key = ask_aws_secret_key
|
30
|
+
aws_region = ask_aws_region(aws_access_key, aws_secret_key)
|
31
|
+
aws_zone = ask_aws_az(aws_access_key, aws_secret_key, aws_region)
|
32
|
+
aws_vpc_id = ask_aws_vpc(aws_access_key, aws_secret_key, aws_region)
|
33
|
+
exit_with_error("Could not find any Virtual Private Cloud (VPC). Please create one in the AWS console first.") unless aws_vpc_id
|
34
|
+
aws_subnet_id = ask_aws_subnet(aws_access_key, aws_secret_key, aws_region, aws_zone, aws_vpc_id)
|
35
|
+
aws_key_pair = ask_aws_key_pair(aws_access_key, aws_secret_key, aws_region)
|
36
|
+
aws_type = ask_aws_instance_type
|
37
|
+
aws_storage = ask_aws_storage
|
38
|
+
aws_count = ask_instance_count
|
39
|
+
provisioner = provisioner(client(require_token), aws_access_key, aws_secret_key, aws_region)
|
27
40
|
provisioner.run!(
|
28
41
|
master_uri: api_url,
|
29
42
|
grid_token: grid['token'],
|
30
43
|
grid: current_grid,
|
31
44
|
name: name,
|
32
|
-
type:
|
33
|
-
vpc:
|
34
|
-
zone:
|
35
|
-
subnet:
|
36
|
-
storage:
|
45
|
+
type: aws_type,
|
46
|
+
vpc: aws_vpc_id,
|
47
|
+
zone: aws_zone,
|
48
|
+
subnet: aws_subnet_id,
|
49
|
+
storage: aws_storage,
|
37
50
|
version: version,
|
38
|
-
key_pair:
|
51
|
+
key_pair: aws_key_pair,
|
52
|
+
count: aws_count,
|
39
53
|
associate_public_ip: associate_public_ip?,
|
40
54
|
security_groups: security_groups
|
41
55
|
)
|
@@ -55,5 +69,13 @@ module Kontena::Plugin::Aws::Nodes
|
|
55
69
|
def provisioner(client, access_key, secret_key, region)
|
56
70
|
Kontena::Machine::Aws::NodeProvisioner.new(client, access_key, secret_key, region)
|
57
71
|
end
|
72
|
+
|
73
|
+
def ask_instance_count
|
74
|
+
if self.count.nil?
|
75
|
+
prompt.ask('How many instances?: ', default: 1)
|
76
|
+
else
|
77
|
+
self.count
|
78
|
+
end
|
79
|
+
end
|
58
80
|
end
|
59
81
|
end
|
@@ -1,25 +1,40 @@
|
|
1
1
|
module Kontena::Plugin::Aws::Nodes
|
2
|
-
class RestartCommand <
|
2
|
+
class RestartCommand < Kontena::Command
|
3
3
|
include Kontena::Cli::Common
|
4
4
|
include Kontena::Cli::GridOptions
|
5
|
+
include Kontena::Plugin::Aws::Prompts
|
5
6
|
|
6
|
-
parameter "NAME", "Node name"
|
7
|
-
option "--access-key", "ACCESS_KEY", "AWS access key ID",
|
8
|
-
option "--secret-key", "SECRET_KEY", "AWS secret key",
|
9
|
-
option "--region", "REGION", "EC2 Region",
|
7
|
+
parameter "[NAME]", "Node name"
|
8
|
+
option "--access-key", "ACCESS_KEY", "AWS access key ID", environment_variable: "AWS_ACCESS_KEY_ID"
|
9
|
+
option "--secret-key", "SECRET_KEY", "AWS secret access key", environment_variable: "AWS_SECRET_ACCESS_KEY"
|
10
|
+
option "--region", "REGION", "EC2 Region", environment_variable: "AWS_REGION"
|
10
11
|
|
11
12
|
def execute
|
12
13
|
require_api_url
|
13
14
|
require_current_grid
|
15
|
+
token = require_token
|
16
|
+
node_name = self.name || ask_node(token)
|
17
|
+
node = client(token).get("grids/#{current_grid}/nodes/#{node_name}")
|
14
18
|
|
19
|
+
aws_access_key = ask_aws_access_key
|
20
|
+
aws_secret_key = ask_aws_secret_key
|
21
|
+
aws_region = self.region || resolve_or_ask_region(node, aws_access_key, aws_secret_key)
|
15
22
|
require_relative '../../../machine/aws'
|
16
23
|
|
17
|
-
restarter = restarter(
|
18
|
-
restarter.run!(
|
24
|
+
restarter = restarter(aws_access_key, aws_secret_key, aws_region)
|
25
|
+
restarter.run!(node_name)
|
19
26
|
end
|
20
27
|
|
21
28
|
def restarter(access_key, secret_key, region)
|
22
29
|
Kontena::Machine::Aws::NodeRestarter.new(access_key, secret_key, region)
|
23
30
|
end
|
31
|
+
|
32
|
+
def resolve_or_ask_region(node, access_key, secret_key)
|
33
|
+
if node['labels'] && region_label = node['labels'].find{ |l| l.split('=').first == 'region' }
|
34
|
+
region = region_label.split('=').last
|
35
|
+
end
|
36
|
+
region = ask_aws_region(access_key, secret_key) unless region
|
37
|
+
region
|
38
|
+
end
|
24
39
|
end
|
25
40
|
end
|
@@ -1,25 +1,43 @@
|
|
1
1
|
module Kontena::Plugin::Aws::Nodes
|
2
|
-
class TerminateCommand <
|
2
|
+
class TerminateCommand < Kontena::Command
|
3
3
|
include Kontena::Cli::Common
|
4
4
|
include Kontena::Cli::GridOptions
|
5
|
+
include Kontena::Plugin::Aws::Prompts
|
5
6
|
|
6
|
-
parameter "NAME", "Node name"
|
7
|
-
option "--access-key", "ACCESS_KEY", "AWS access key ID",
|
8
|
-
option "--secret-key", "SECRET_KEY", "AWS secret key",
|
9
|
-
option "--region", "REGION", "EC2 Region",
|
7
|
+
parameter "[NAME]", "Node name"
|
8
|
+
option "--access-key", "ACCESS_KEY", "AWS access key ID", environment_variable: "AWS_ACCESS_KEY_ID"
|
9
|
+
option "--secret-key", "SECRET_KEY", "AWS secret access key", environment_variable: "AWS_SECRET_ACCESS_KEY"
|
10
|
+
option "--region", "REGION", "EC2 Region (default: node's region)", environment_variable: "AWS_REGION"
|
11
|
+
option "--force", :flag, "Force remove", default: false, attribute_name: :forced
|
10
12
|
|
11
13
|
def execute
|
12
14
|
require_api_url
|
13
15
|
require_current_grid
|
14
16
|
|
17
|
+
token = require_token
|
18
|
+
node_name = self.name || ask_node(token)
|
19
|
+
node = client(token).get("grids/#{current_grid}/nodes/#{node_name}")
|
20
|
+
aws_access_key = ask_aws_access_key
|
21
|
+
aws_secret_key = ask_aws_secret_key
|
22
|
+
aws_region = self.region || resolve_or_ask_region(node, aws_access_key, aws_secret_key)
|
23
|
+
|
24
|
+
confirm_command(node_name) unless forced?
|
15
25
|
require 'kontena/machine/aws'
|
16
26
|
grid = client(require_token).get("grids/#{current_grid}")
|
17
|
-
destroyer = destroyer(client(require_token),
|
18
|
-
destroyer.run!(grid,
|
27
|
+
destroyer = destroyer(client(require_token), aws_access_key, aws_secret_key, aws_region)
|
28
|
+
destroyer.run!(grid, node_name)
|
19
29
|
end
|
20
30
|
|
21
31
|
def destroyer(client, access_key, secret_key, region)
|
22
32
|
Kontena::Machine::Aws::NodeDestroyer.new(client, access_key, secret_key, region)
|
23
33
|
end
|
34
|
+
|
35
|
+
def resolve_or_ask_region(node, access_key, secret_key)
|
36
|
+
if node['labels'] && region_label = node['labels'].find{ |l| l.split('=').first == 'region' }
|
37
|
+
region = region_label.split('=').last
|
38
|
+
end
|
39
|
+
region = ask_aws_region(access_key, secret_key) unless region
|
40
|
+
region
|
41
|
+
end
|
24
42
|
end
|
25
43
|
end
|
@@ -0,0 +1,148 @@
|
|
1
|
+
require 'aws-sdk'
|
2
|
+
module Kontena::Plugin::Aws::Prompts
|
3
|
+
|
4
|
+
def ask_aws_access_key
|
5
|
+
if self.access_key.nil?
|
6
|
+
prompt.ask('AWS access key: ', echo: false)
|
7
|
+
else
|
8
|
+
self.access_key
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def ask_aws_secret_key
|
13
|
+
if self.secret_key.nil?
|
14
|
+
prompt.ask('AWS secret key: ', echo: false)
|
15
|
+
else
|
16
|
+
self.secret_key
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def ask_aws_key_pair(access_key, secret_key, region)
|
21
|
+
if self.key_pair.nil?
|
22
|
+
prompt.select("Choose EC2 key pair: ") do |menu|
|
23
|
+
aws_client = ::Aws::EC2::Client.new(access_key_id: access_key, secret_access_key: secret_key, region: region)
|
24
|
+
aws_client.describe_key_pairs.key_pairs.each{ |key_pair|
|
25
|
+
menu.choice key_pair.key_name, key_pair.key_name
|
26
|
+
}
|
27
|
+
end
|
28
|
+
else
|
29
|
+
self.key_pair
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def ask_aws_region(access_key, secret_key, default = 'eu-west-1')
|
34
|
+
if self.region.nil?
|
35
|
+
prompt.select("Choose EC2 region: ") do |menu|
|
36
|
+
aws_client = ::Aws::EC2::Client.new(access_key_id: access_key, secret_access_key: secret_key, region: 'eu-west-1')
|
37
|
+
i = 1
|
38
|
+
aws_client.describe_regions.regions.sort_by{|r| r.region_name }.each{ |region|
|
39
|
+
menu.choice region.region_name, region.region_name
|
40
|
+
if region.region_name == default
|
41
|
+
menu.default i
|
42
|
+
end
|
43
|
+
i += 1
|
44
|
+
}
|
45
|
+
end
|
46
|
+
else
|
47
|
+
self.region
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def ask_aws_az(access_key, secret_key, region)
|
52
|
+
if self.zone.nil?
|
53
|
+
prompt.select("Choose EC2 Availability Zone: ") do |menu|
|
54
|
+
aws_client = ::Aws::EC2::Client.new(access_key_id: access_key, secret_access_key: secret_key, region: region)
|
55
|
+
aws_client.describe_availability_zones.availability_zones.sort_by{|r| r.zone_name }.each{ |zone|
|
56
|
+
if zone.state == 'available'
|
57
|
+
menu.choice zone.zone_name, zone.zone_name.sub(zone.region_name, '')
|
58
|
+
end
|
59
|
+
}
|
60
|
+
end
|
61
|
+
else
|
62
|
+
self.zone
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def ask_aws_vpc(access_key, secret_key, region)
|
67
|
+
if self.vpc_id.nil?
|
68
|
+
aws_client = ::Aws::EC2::Client.new(access_key_id: access_key, secret_access_key: secret_key, region: region)
|
69
|
+
vpcs = aws_client.describe_vpcs.vpcs
|
70
|
+
return nil if vpcs.size == 0
|
71
|
+
if vpcs.size == 1 && vpcs.first.state == "available"
|
72
|
+
vpcs.first.vpc_id
|
73
|
+
else
|
74
|
+
prompt.select("Choose Virtual Private Cloud (VPC) ID: ") do |menu|
|
75
|
+
vpcs.each{ |vpc|
|
76
|
+
if vpc.state == 'available'
|
77
|
+
name = vpc.vpc_id
|
78
|
+
name += ' (default)' if vpc.is_default
|
79
|
+
menu.choice name, vpc.vpc_id
|
80
|
+
end
|
81
|
+
}
|
82
|
+
end
|
83
|
+
end
|
84
|
+
else
|
85
|
+
self.vpc_id
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def ask_aws_subnet(access_key, secret_key, region, zone, vpc)
|
90
|
+
if self.subnet_id.nil?
|
91
|
+
aws_client = ::Aws::EC2::Client.new(access_key_id: access_key, secret_access_key: secret_key, region: region)
|
92
|
+
subnets_result = aws_client.describe_subnets(filters: [
|
93
|
+
{ name: "vpc-id", values: [vpc] },
|
94
|
+
{ name: "availability-zone", values: [zone]}
|
95
|
+
])
|
96
|
+
subnets = subnets_result.subnets.sort_by{|s| s.cidr_block}
|
97
|
+
return nil if subnets.size == 0
|
98
|
+
if subnets.size == 1 && subnets.first.state == "available"
|
99
|
+
puts "Using Subnet (#{subnets.first.subnet_id})"
|
100
|
+
subnets.first.subnet_id
|
101
|
+
else
|
102
|
+
prompt.select("Specify subnet to launch instance into: ") do |menu|
|
103
|
+
subnets.each{ |subnet|
|
104
|
+
if subnet.state == 'available'
|
105
|
+
menu.choice "#{subnet.subnet_id} (#{subnet.cidr_block})", subnet.subnet_id
|
106
|
+
end
|
107
|
+
}
|
108
|
+
end
|
109
|
+
end
|
110
|
+
else
|
111
|
+
self.subnet_id
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def ask_aws_instance_type(default = 't2.small')
|
116
|
+
if self.type.nil?
|
117
|
+
prompt.ask('Instance type: ', default: default)
|
118
|
+
else
|
119
|
+
self.type
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def ask_aws_storage(default = '30')
|
124
|
+
if self.storage.nil?
|
125
|
+
prompt.ask('Storage size (GiB): ', default: default)
|
126
|
+
else
|
127
|
+
self.storage
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def ask_node(token)
|
132
|
+
if self.name.nil?
|
133
|
+
nodes = client(token).get("grids/#{current_grid}/nodes")
|
134
|
+
nodes = nodes['nodes'].select{ |n|
|
135
|
+
n['labels'] && n['labels'].include?('provider=aws'.freeze)
|
136
|
+
}
|
137
|
+
raise "Did not find any nodes with label provider=aws" if nodes.size == 0
|
138
|
+
prompt.select("Select node: ") do |menu|
|
139
|
+
nodes.sort_by{|n| n['node_number'] }.reverse.each do |node|
|
140
|
+
initial = node['initial_member'] ? '(initial) ' : ''
|
141
|
+
menu.choice "#{node['name']} #{initial}", node['name']
|
142
|
+
end
|
143
|
+
end
|
144
|
+
else
|
145
|
+
self.name
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kontena-plugin-aws
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.0
|
4
|
+
version: 0.2.0
|
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-
|
11
|
+
date: 2016-10-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: kontena-cli
|
@@ -102,6 +102,7 @@ files:
|
|
102
102
|
- lib/kontena/plugin/aws/nodes/create_command.rb
|
103
103
|
- lib/kontena/plugin/aws/nodes/restart_command.rb
|
104
104
|
- lib/kontena/plugin/aws/nodes/terminate_command.rb
|
105
|
+
- lib/kontena/plugin/aws/prompts.rb
|
105
106
|
- lib/kontena/plugin/aws_command.rb
|
106
107
|
- lib/kontena_cli_plugin.rb
|
107
108
|
homepage: https://github.com/kontena/kontena-plugin-aws
|
@@ -119,9 +120,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
119
120
|
version: '0'
|
120
121
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
121
122
|
requirements:
|
122
|
-
- - ! '
|
123
|
+
- - ! '>='
|
123
124
|
- !ruby/object:Gem::Version
|
124
|
-
version:
|
125
|
+
version: '0'
|
125
126
|
requirements: []
|
126
127
|
rubyforge_project:
|
127
128
|
rubygems_version: 2.4.5
|