kontena-plugin-aws 0.2.0.pre1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|