From 5125b34878ef2cbf415655e52b43eedaa223e354 Mon Sep 17 00:00:00 2001 From: benpillet Date: Sat, 28 May 2016 13:09:31 -0700 Subject: [PATCH 1/6] Draft of associate_public_ip_address --- .../provider/ec2_launchconfiguration/v2.rb | 14 +++++- lib/puppet/type/ec2_launchconfiguration.rb | 45 +++++++++++++++++++ 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/lib/puppet/provider/ec2_launchconfiguration/v2.rb b/lib/puppet/provider/ec2_launchconfiguration/v2.rb index 94023979..61240c02 100644 --- a/lib/puppet/provider/ec2_launchconfiguration/v2.rb +++ b/lib/puppet/provider/ec2_launchconfiguration/v2.rb @@ -16,6 +16,7 @@ def self.instances launch_configs << new(hash) end end +puts "launch_configs: #{launch_configs}" launch_configs rescue Timeout::Error, StandardError => e raise PuppetX::Puppetlabs::FetchingAWSDataError.new(region, self.resource_type.name.to_s, e.message) @@ -36,6 +37,7 @@ def self.prefetch(resources) def self.config_to_hash(region, config) # It appears possible to get launch configurations manually to a state where # they return the identifier of an invalid or a non-existent security groups +# puts "config_to_hash(#{config})" security_group_names = begin group_response = ec2_client(region).describe_security_groups(group_ids: config.security_groups) group_response.data.security_groups.collect(&:group_name) @@ -49,7 +51,11 @@ def self.config_to_hash(region, config) image_id: config.image_id, key_name: config.key_name, ensure: :present, - region: region + region: region, + block_device_mappings: config.block_device_mappings, + spot_price: config.spot_price, + ebs_optimized: config.ebs_optimized, + associate_public_ip_address: config.associate_public_ip_address || true, } end @@ -82,13 +88,17 @@ def create end data = resource[:user_data].nil? ? nil : Base64.encode64(resource[:user_data]) - +assoc = resource[:associate_public_ip_address] +puts "create associate: #{assoc.class} #{assoc}" config = { launch_configuration_name: name, image_id: resource[:image_id], security_groups: group_ids, instance_type: resource[:instance_type], user_data: data, + associate_public_ip_address: resource[:associate_public_ip_address], + # block_device_mappings: resource[:block_device_mappings], + } key = resource[:key_name] ? resource[:key_name] : false diff --git a/lib/puppet/type/ec2_launchconfiguration.rb b/lib/puppet/type/ec2_launchconfiguration.rb index 1133ae9c..ccaa4e9d 100644 --- a/lib/puppet/type/ec2_launchconfiguration.rb +++ b/lib/puppet/type/ec2_launchconfiguration.rb @@ -67,6 +67,45 @@ def insync?(is) end end + newproperty(:block_device_mappings, :array_matching => :all) do + desc "One or more mappings that specify how block devices are exposed to the instance." + validate do |value| + Puppet.warning "validate(#{value})" + devices = value.is_a?(Array) ? value : [value] + devices.each do |device| + fail "block device must be named" unless value.keys.include?('device_name') + choices = ['volume_size', 'snapshot_id'] + fail "block device must include at least one of: " + choices.join(' ') if (value.keys & choices).empty? + if value['volume_type'] == 'io1' + fail 'must specify iops if using provisioned iops volumes' unless value.keys.include?('iops') + end + end + end + + def insync?(is) + existing_devices = is.collect { |device| device[:device_name] } + specified_devices = should.collect { |device| device['device_name'] } + existing_devices.to_set == specified_devices.to_set + end + + def set(value) + read_only_warning(value, self, should) + end + end + + newproperty(:associate_public_ip_address, :boolean => true, :parent => Puppet::Parameter::Boolean) do + desc 'Specifies whether to assign a public IP address to each instance launched in a Amazon VPC. If the instance is launched into a default subnet, the default is true.' + defaultto :true + newvalues(:true, :false) + def insync?(is) + is.to_s == should.to_s + end + + def set(value) + read_only_warning(value, self, should) + end + end + autorequire(:ec2_securitygroup) do groups = self[:security_groups] groups.is_a?(Array) ? groups : [groups] @@ -77,3 +116,9 @@ def insync?(is) end end +def read_only_warning(value, property, should) + msg = "#{property.name} is read-only. Cannot set to: #{should}" + Puppet.warning msg + #raise Puppet::Error, msg + false +end From 2edf3a1f1911955d7176d79d8aed93754f917a87 Mon Sep 17 00:00:00 2001 From: benpillet Date: Sat, 28 May 2016 13:42:56 -0700 Subject: [PATCH 2/6] Add unit test of type launchconfig associate_public_ip_address --- lib/puppet/type/ec2_launchconfiguration.rb | 2 ++ spec/unit/type/ec2_launchconfiguration_spec.rb | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/lib/puppet/type/ec2_launchconfiguration.rb b/lib/puppet/type/ec2_launchconfiguration.rb index ccaa4e9d..26a79ddb 100644 --- a/lib/puppet/type/ec2_launchconfiguration.rb +++ b/lib/puppet/type/ec2_launchconfiguration.rb @@ -1,3 +1,5 @@ +require 'puppet/parameter/boolean' + Puppet::Type.newtype(:ec2_launchconfiguration) do @doc = 'Type representing an EC2 launch configuration.' diff --git a/spec/unit/type/ec2_launchconfiguration_spec.rb b/spec/unit/type/ec2_launchconfiguration_spec.rb index 3517508f..c95f44be 100644 --- a/spec/unit/type/ec2_launchconfiguration_spec.rb +++ b/spec/unit/type/ec2_launchconfiguration_spec.rb @@ -7,6 +7,7 @@ def launchconfig_config instance_type: 't1.micro', region: 'sa-east-1', security_groups: ['test-sg'], + associate_public_ip_address: false, } end @@ -30,6 +31,7 @@ def launchconfig_config :instance_type, :image_id, :key_name, + :associate_public_ip_address, ] end @@ -81,4 +83,13 @@ def launchconfig_config end end + context 'with a full set of properties' do + before :all do + @instance = type_class.new(launchconfig_config) + end + + it "should convert associate_public_ip_address to a boolean" do + expect(@instance[:associate_public_ip_address].kind_of?(TrueClass) || @instance[:associate_public_ip_address].kind_of?(FalseClass)).to be true + end + end end From 3355ad9544a65a627ed46f3d3a968156b6a19af3 Mon Sep 17 00:00:00 2001 From: benpillet Date: Sat, 28 May 2016 13:45:57 -0700 Subject: [PATCH 3/6] Add provider test for associate_public_ip_address --- spec/unit/provider/ec2_launchconfig/v2_spec.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/unit/provider/ec2_launchconfig/v2_spec.rb b/spec/unit/provider/ec2_launchconfig/v2_spec.rb index b85ac631..7b2f8ae9 100644 --- a/spec/unit/provider/ec2_launchconfig/v2_spec.rb +++ b/spec/unit/provider/ec2_launchconfig/v2_spec.rb @@ -15,6 +15,7 @@ instance_type: 't1.micro', region: 'sa-east-1', security_groups: ['test-sg'], + associate_public_ip_address: false, ) } From 69ed8aa40a850f8b3d56597a3ec4bfce61ac2944 Mon Sep 17 00:00:00 2001 From: benpillet Date: Sat, 28 May 2016 13:48:27 -0700 Subject: [PATCH 4/6] Cleanup extra cruft --- .../provider/ec2_launchconfiguration/v2.rb | 11 ++------ lib/puppet/type/ec2_launchconfiguration.rb | 26 ------------------- 2 files changed, 2 insertions(+), 35 deletions(-) diff --git a/lib/puppet/provider/ec2_launchconfiguration/v2.rb b/lib/puppet/provider/ec2_launchconfiguration/v2.rb index 61240c02..6176d6f1 100644 --- a/lib/puppet/provider/ec2_launchconfiguration/v2.rb +++ b/lib/puppet/provider/ec2_launchconfiguration/v2.rb @@ -16,7 +16,6 @@ def self.instances launch_configs << new(hash) end end -puts "launch_configs: #{launch_configs}" launch_configs rescue Timeout::Error, StandardError => e raise PuppetX::Puppetlabs::FetchingAWSDataError.new(region, self.resource_type.name.to_s, e.message) @@ -52,10 +51,7 @@ def self.config_to_hash(region, config) key_name: config.key_name, ensure: :present, region: region, - block_device_mappings: config.block_device_mappings, - spot_price: config.spot_price, - ebs_optimized: config.ebs_optimized, - associate_public_ip_address: config.associate_public_ip_address || true, + associate_public_ip_address: config.associate_public_ip_address, } end @@ -88,8 +84,7 @@ def create end data = resource[:user_data].nil? ? nil : Base64.encode64(resource[:user_data]) -assoc = resource[:associate_public_ip_address] -puts "create associate: #{assoc.class} #{assoc}" + config = { launch_configuration_name: name, image_id: resource[:image_id], @@ -97,8 +92,6 @@ def create instance_type: resource[:instance_type], user_data: data, associate_public_ip_address: resource[:associate_public_ip_address], - # block_device_mappings: resource[:block_device_mappings], - } key = resource[:key_name] ? resource[:key_name] : false diff --git a/lib/puppet/type/ec2_launchconfiguration.rb b/lib/puppet/type/ec2_launchconfiguration.rb index 26a79ddb..8585e05e 100644 --- a/lib/puppet/type/ec2_launchconfiguration.rb +++ b/lib/puppet/type/ec2_launchconfiguration.rb @@ -69,32 +69,6 @@ def insync?(is) end end - newproperty(:block_device_mappings, :array_matching => :all) do - desc "One or more mappings that specify how block devices are exposed to the instance." - validate do |value| - Puppet.warning "validate(#{value})" - devices = value.is_a?(Array) ? value : [value] - devices.each do |device| - fail "block device must be named" unless value.keys.include?('device_name') - choices = ['volume_size', 'snapshot_id'] - fail "block device must include at least one of: " + choices.join(' ') if (value.keys & choices).empty? - if value['volume_type'] == 'io1' - fail 'must specify iops if using provisioned iops volumes' unless value.keys.include?('iops') - end - end - end - - def insync?(is) - existing_devices = is.collect { |device| device[:device_name] } - specified_devices = should.collect { |device| device['device_name'] } - existing_devices.to_set == specified_devices.to_set - end - - def set(value) - read_only_warning(value, self, should) - end - end - newproperty(:associate_public_ip_address, :boolean => true, :parent => Puppet::Parameter::Boolean) do desc 'Specifies whether to assign a public IP address to each instance launched in a Amazon VPC. If the instance is launched into a default subnet, the default is true.' defaultto :true From d05293b715cb73a9df6e38c30da9b3116a7ea0ef Mon Sep 17 00:00:00 2001 From: benpillet Date: Sat, 28 May 2016 13:50:45 -0700 Subject: [PATCH 5/6] Add README doc --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index e17b20c4..2862df95 100644 --- a/README.md +++ b/README.md @@ -614,6 +614,9 @@ Specifies that basic state of the resource. Valid values are 'attached', 'detach #####`vpc` *Optional* A hint to specify the VPC. This is useful when detecting ambiguously named security groups that might exist in different VPCs, such as 'default'. This parameter is set at creation only; it is not affected by updates. +#####`associate_public_ip_address` +*Optional* One or more mappings that specify how block devices are exposed to the instance. For more information, see [Block Device Mapping](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/block-device-mapping-concepts.html) in the Amazon Elastic Compute Cloud User Guide. This parameter is set at creation only; it is not affected by updates. + #### Type: ec2_scalingpolicy #####`name` From 4064e00df08f5b834d1785d37db8a0c56962849b Mon Sep 17 00:00:00 2001 From: Ben Pillet Date: Sat, 28 May 2016 17:28:32 -0700 Subject: [PATCH 6/6] Make associate_public_ip_address a property boolean --- lib/puppet/type/ec2_launchconfiguration.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/puppet/type/ec2_launchconfiguration.rb b/lib/puppet/type/ec2_launchconfiguration.rb index 8585e05e..d044f4fd 100644 --- a/lib/puppet/type/ec2_launchconfiguration.rb +++ b/lib/puppet/type/ec2_launchconfiguration.rb @@ -1,4 +1,4 @@ -require 'puppet/parameter/boolean' +require 'puppet/property/boolean' Puppet::Type.newtype(:ec2_launchconfiguration) do @doc = 'Type representing an EC2 launch configuration.' @@ -69,7 +69,7 @@ def insync?(is) end end - newproperty(:associate_public_ip_address, :boolean => true, :parent => Puppet::Parameter::Boolean) do + newproperty(:associate_public_ip_address, :boolean => true, :parent => Puppet::Property::Boolean) do desc 'Specifies whether to assign a public IP address to each instance launched in a Amazon VPC. If the instance is launched into a default subnet, the default is true.' defaultto :true newvalues(:true, :false)