class Kontena::Machine::Aws::NodeProvisioner
Attributes
api_client[R]
ec2[R]
Public Class Methods
new(api_client, access_key_id, secret_key, region)
click to toggle source
@param [Kontena::Client] api_client
Kontena
api client @param [String] access_key_id aws_access_key_id @param [String] secret_key aws_secret_access_key @param [String] region
# File lib/kontena/machine/aws/node_provisioner.rb, line 18 def initialize(api_client, access_key_id, secret_key, region) @api_client = api_client @ec2 = ::Aws::EC2::Resource.new( region: region, credentials: ::Aws::Credentials.new(access_key_id, secret_key) ) end
Public Instance Methods
aws_dns_supported?(vpc_id)
click to toggle source
@param [String] vpc_id @return [Boolean]
# File lib/kontena/machine/aws/node_provisioner.rb, line 210 def aws_dns_supported?(vpc_id) vpc = ec2.vpc(vpc_id) response = vpc.describe_attribute({attribute: 'enableDnsSupport'}) response.enable_dns_support end
create_security_group(name, vpc_id)
click to toggle source
creates security_group and authorizes default port ranges
@param [String] name @param [String] vpc_id @return [Aws::EC2::SecurityGroup]
# File lib/kontena/machine/aws/node_provisioner.rb, line 139 def create_security_group(name, vpc_id) sg = ec2.create_security_group({ group_name: name, description: "Kontena Grid", vpc_id: vpc_id }) sg.authorize_ingress({ # SSH ip_protocol: 'tcp', from_port: 22, to_port: 22, cidr_ip: '0.0.0.0/0' }) sg.authorize_ingress({ # HTTP ip_protocol: 'tcp', from_port: 80, to_port: 80, cidr_ip: '0.0.0.0/0' }) sg.authorize_ingress({ # HTTPS ip_protocol: 'tcp', from_port: 443, to_port: 443, cidr_ip: '0.0.0.0/0' }) sg.authorize_ingress({ # OpenVPN ip_protocol: 'udp', from_port: 1194, to_port: 1194, cidr_ip: '0.0.0.0/0' }) sg.authorize_ingress({ # Overlay / Weave network ip_permissions: [ { from_port: 6783, to_port: 6783, ip_protocol: 'tcp', user_id_group_pairs: [ { group_id: sg.group_id, vpc_id: vpc_id } ] }, { from_port: 6783, to_port: 6784, ip_protocol: 'udp', user_id_group_pairs: [ { group_id: sg.group_id, vpc_id: vpc_id } ] } ] }) sg end
ensure_security_group(grid, vpc_id)
click to toggle source
@param [String] grid @return [Array] Security group id in array
# File lib/kontena/machine/aws/node_provisioner.rb, line 120 def ensure_security_group(grid, vpc_id) group_name = "kontena_grid_#{grid}" group_id = resolve_security_groups_to_ids(group_name, vpc_id) if group_id.empty? spinner "Creating AWS security group" do sg = create_security_group(group_name, vpc_id) group_id = [sg.group_id] end end group_id end
erb(template, vars)
click to toggle source
# File lib/kontena/machine/aws/node_provisioner.rb, line 196 def erb(template, vars) ERB.new(template).result(OpenStruct.new(vars).instance_eval { binding }) end
generate_name()
click to toggle source
# File lib/kontena/machine/aws/node_provisioner.rb, line 188 def generate_name "#{super}-#{rand(1..99)}" end
instance_exists_in_grid?(grid, name)
click to toggle source
# File lib/kontena/machine/aws/node_provisioner.rb, line 192 def instance_exists_in_grid?(grid, name) api_client.get("grids/#{grid}/nodes")['nodes'].find{|n| n['name'] == name} end
region()
click to toggle source
@return [String]
# File lib/kontena/machine/aws/node_provisioner.rb, line 179 def region ec2.client.config.region end
run!(opts)
click to toggle source
@param [Hash] opts
# File lib/kontena/machine/aws/node_provisioner.rb, line 26 def run!(opts) if opts[:ami] ami = opts[:ami] else ami = resolve_ami(region) abort('No valid AMI found for region') unless ami end opts[:vpc] = default_vpc.vpc_id unless opts[:vpc] security_groups = opts[:security_groups] ? resolve_security_groups_to_ids(opts[:security_groups], opts[:vpc]) : ensure_security_group(opts[:grid], opts[:vpc]) raise "Missing :subnet option" if opts[:subnet].nil? subnet = ec2.subnet(opts[:subnet]) abort('Failed to find subnet!') unless subnet dns_server = aws_dns_supported?(opts[:vpc]) ? '169.254.169.253' : '8.8.8.8' instances = [] opts[:count].to_i.times do |i| if opts[:name] && opts[:count].to_i > 1 name = "#{opts[:name]}-#{i+1}" elsif opts[:name] name = opts[:name] else name = generate_name end userdata_vars = { name: name, version: opts[:version], master_uri: opts[:master_uri], grid_token: opts[:grid_token], dns_server: dns_server } ec2_instance = ec2.create_instances({ image_id: ami, min_count: 1, max_count: 1, instance_type: opts[:type], key_name: opts[:key_pair], user_data: Base64.encode64(user_data(userdata_vars)), block_device_mappings: [ { device_name: '/dev/xvda', virtual_name: 'Root', ebs: { volume_size: opts[:storage], volume_type: 'gp2' } } ], network_interfaces: [ { device_index: 0, subnet_id: subnet.subnet_id, groups: security_groups, associate_public_ip_address: opts[:associate_public_ip], delete_on_termination: true } ] }).first ec2_instance.create_tags({ tags: [ {key: 'Name', value: name}, {key: 'kontena_grid', value: opts[:grid]} ] }) spinner "Creating AWS instance #{name.colorize(:cyan)} " do sleep 1 until ec2_instance.reload.state.name == 'running' end instances << name end instances.each do |instance_name| node = nil spinner "Waiting for node #{instance_name.colorize(:cyan)} join to grid #{opts[:grid].colorize(:cyan)} " do sleep 1 until node = instance_exists_in_grid?(opts[:grid], instance_name) end labels = [ "region=#{region}", "az=#{opts[:zone]}", "provider=aws", "type=#{opts[:type]}" ] set_labels(node, labels) end end
set_labels(node, labels)
click to toggle source
@param [Hash] node @param [Array<String>] labels
# File lib/kontena/machine/aws/node_provisioner.rb, line 202 def set_labels(node, labels) data = {} data[:labels] = labels api_client.put("nodes/#{node['id']}", data, {}, {'Kontena-Grid-Token' => node['grid']['token']}) end
user_data(vars)
click to toggle source
# File lib/kontena/machine/aws/node_provisioner.rb, line 183 def user_data(vars) cloudinit_template = File.join(__dir__ , '/cloudinit.yml') erb(File.read(cloudinit_template), vars) end