lib/beaker/hypervisor/aws_sdk.rb in beaker-aws-0.5.0 vs lib/beaker/hypervisor/aws_sdk.rb in beaker-aws-0.6.0

- old
+ new

@@ -263,10 +263,12 @@ # @api private def create_instance(host, ami_spec, subnet_id) amitype = host['vmname'] || host['platform'] amisize = host['amisize'] || 'm1.small' vpc_id = host['vpc_id'] || @options['vpc_id'] || nil + host['sg_cidr_ips'] = host['sg_cidr_ips'] || '0.0.0.0/0'; + sg_cidr_ips = host['sg_cidr_ips'].split(',') if vpc_id && !subnet_id raise RuntimeError, "A subnet_id must be provided with a vpc_id" end @@ -322,13 +324,13 @@ } } end end - security_group = ensure_group(vpc || region, Beaker::EC2Helper.amiports(host)) + security_group = ensure_group(vpc || region, Beaker::EC2Helper.amiports(host), sg_cidr_ips) #check if ping is enabled - ping_security_group = ensure_ping_group(vpc || region) + ping_security_group = ensure_ping_group(vpc || region, sg_cidr_ips) msg = "aws-sdk: launching %p on %p using %p/%p%s" % [host.name, amitype, amisize, image_type, subnet_id ? ("in %p" % subnet_id) : ''] @logger.notify(msg) @@ -338,11 +340,11 @@ :image_id => image_id, :monitoring => { :enabled => true, }, :key_name => ensure_key_pair(region).key_pairs.first.key_name, - :security_groups => [security_group.group_name, ping_security_group.group_name], + :security_group_ids => [security_group.group_id, ping_security_group.group_id], :instance_type => amisize, :disable_api_termination => false, :instance_initiated_shutdown_behavior => "terminate", :subnet_id => subnet_id, } @@ -476,11 +478,11 @@ # Here we keep waiting for the machine state to reach 'running' with an # exponential backoff for each poll. # TODO: should probably be a in a shared method somewhere for tries in 1..10 refreshed_instance = instance_by_id(instance.instance_id) - + if refreshed_instance.nil? @logger.debug("Instance #{name} not yet available (#{e})") else if block_given? test_result = yield refreshed_instance @@ -713,11 +715,11 @@ if host['vmname'] =~ /^amazon/ # Amazon Linux requires this to preserve host name changes across reboots. # http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/set-hostname.html # Also note that without an elastic ip set, while this will # preserve the hostname across a full shutdown/startup of the vm - # (as opposed to a reboot) -- the ip address will have changed. + # (as opposed to a reboot) -- the ip address will have changed. host.exec(Command.new("sed -ie '/^HOSTNAME/ s/=.*/=#{host.name}/' /etc/sysconfig/network")) end end end else @@ -906,24 +908,25 @@ # Return an existing group, or create new one # # Accepts a VPC as input for checking & creation. # # @param vpc [Aws::EC2::VPC] the AWS vpc control object + # @param sg_cidr_ips [Array<String>] CIDRs used for outbound security group rule # @return [Aws::EC2::SecurityGroup] created security group # @api private - def ensure_ping_group(vpc) + def ensure_ping_group(vpc, sg_cidr_ips = ['0.0.0.0/0']) @logger.notify("aws-sdk: Ensure security group exists that enables ping, create if not") group = client.describe_security_groups( :filters => [ { :name => 'group-name', :values => [PING_SECURITY_GROUP_NAME] }, { :name => 'vpc-id', :values => [vpc.vpc_id] }, ] ).security_groups.first if group.nil? - group = create_ping_group(vpc) + group = create_ping_group(vpc, sg_cidr_ips) end group end @@ -931,13 +934,14 @@ # # Accepts a VPC as input for checking & creation. # # @param vpc [Aws::EC2::VPC] the AWS vpc control object # @param ports [Array<Number>] an array of port numbers + # @param sg_cidr_ips [Array<String>] CIDRs used for outbound security group rule # @return [Aws::EC2::SecurityGroup] created security group # @api private - def ensure_group(vpc, ports) + def ensure_group(vpc, ports, sg_cidr_ips = ['0.0.0.0/0']) @logger.notify("aws-sdk: Ensure security group exists for ports #{ports.to_s}, create if not") name = group_id(ports) group = client.describe_security_groups( :filters => [ @@ -945,24 +949,25 @@ { :name => 'vpc-id', :values => [vpc.vpc_id] }, ] ).security_groups.first if group.nil? - group = create_group(vpc, ports) + group = create_group(vpc, ports, sg_cidr_ips) end group end # Create a new ping enabled security group # # Accepts a region or VPC for group creation. # - # @param rv [Aws::EC2::Region, Aws::EC2::VPC] the AWS region or vpc control object + # @param region_or_vpc [Aws::EC2::Region, Aws::EC2::VPC] the AWS region or vpc control object + # @param sg_cidr_ips [Array<String>] CIDRs used for outbound security group rule # @return [Aws::EC2::SecurityGroup] created security group # @api private - def create_ping_group(region_or_vpc) + def create_ping_group(region_or_vpc, sg_cidr_ips = ['0.0.0.0/0']) @logger.notify("aws-sdk: Creating group #{PING_SECURITY_GROUP_NAME}") cl = region_or_vpc.is_a?(String) ? client(region_or_vpc) : client params = { :description => 'Custom Beaker security group to enable ping', @@ -970,56 +975,80 @@ } params[:vpc_id] = region_or_vpc.vpc_id if region_or_vpc.is_a?(Aws::EC2::Types::Vpc) group = cl.create_security_group(params) - cl.authorize_security_group_ingress( - :cidr_ip => '0.0.0.0/0', - :ip_protocol => 'icmp', - :from_port => '8', # 8 == ICMPv4 ECHO request - :to_port => '-1', # -1 == All ICMP codes - :group_id => group.group_id, - ) + sg_cidr_ips.each do |cidr_ip| + add_ingress_rule( + cl, + group, + cidr_ip, + '8', # 8 == ICMPv4 ECHO request + '-1', # -1 == All ICMP codes + 'icmp', + ) + end group end # Create a new security group # # Accepts a region or VPC for group creation. # - # @param rv [Aws::EC2::Region, Aws::EC2::VPC] the AWS region or vpc control object + # @param region_or_vpc [Aws::EC2::Region, Aws::EC2::VPC] the AWS region or vpc control object # @param ports [Array<Number>] an array of port numbers + # @param sg_cidr_ips [Array<String>] CIDRs used for outbound security group rule # @return [Aws::EC2::SecurityGroup] created security group # @api private - def create_group(region_or_vpc, ports) + def create_group(region_or_vpc, ports, sg_cidr_ips = ['0.0.0.0/0']) name = group_id(ports) @logger.notify("aws-sdk: Creating group #{name} for ports #{ports.to_s}") + @logger.notify("aws-sdk: Creating group #{name} with CIDR IPs #{sg_cidr_ips.to_s}") cl = region_or_vpc.is_a?(String) ? client(region_or_vpc) : client - group = cl.create_security_group( + params = { + :description => "Custom Beaker security group for #{ports.to_a}", :group_name => name, - :description => "Custom Beaker security group for #{ports.to_a}" - ) + } + params[:vpc_id] = region_or_vpc.vpc_id if region_or_vpc.is_a?(Aws::EC2::Types::Vpc) + + group = cl.create_security_group(params) + unless ports.is_a? Set ports = Set.new(ports) end - ports.each do |port| - cl.authorize_security_group_ingress( - :cidr_ip => '0.0.0.0/0', - :ip_protocol => 'tcp', - :from_port => port, - :to_port => port, - :group_id => group.group_id, - ) + sg_cidr_ips.each do |cidr_ip| + ports.each do |port| + add_ingress_rule(cl, group, cidr_ip, port, port) + end end group end + # Authorizes connections from certain CIDR to a range of ports + # + # @param cl [Aws::EC2::Client] + # @param sg_group [Aws::EC2::SecurityGroup] the AWS security group + # @param cidr_ip [String] CIDR used for outbound security group rule + # @param from_port [String] Starting Port number in the range + # @param to_port [String] Ending Port number in the range + # @return [void] + # @api private + def add_ingress_rule(cl, sg_group, cidr_ip, from_port, to_port, protocol = 'tcp') + cl.authorize_security_group_ingress( + :cidr_ip => cidr_ip, + :ip_protocol => protocol, + :from_port => from_port, + :to_port => to_port, + :group_id => sg_group.group_id, + ) + end + # Return a hash containing AWS credentials # # @return [Hash<Symbol, String>] AWS credentials # @api private def load_credentials @@ -1044,11 +1073,10 @@ # # @param dot_fog [String] dot fog path # @return [Aws::Credentials] ec2 credentials # @api private def load_fog_credentials(dot_fog = '.fog') - fog = YAML.load_file( dot_fog ) - default = fog[:default] + default = get_fog_credentials(dot_fog) raise "You must specify an aws_access_key_id in your .fog file (#{dot_fog}) for ec2 instances!" unless default[:aws_access_key_id] raise "You must specify an aws_secret_access_key in your .fog file (#{dot_fog}) for ec2 instances!" unless default[:aws_secret_access_key] Aws::Credentials.new(