chef-provisioning-aws 0.3 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5ec492afa3798bae513c3b61ea626958a6b7e954
4
- data.tar.gz: 1b8ecf59b63a169aaa7d744efe491f3f1627065c
3
+ metadata.gz: 3e941203fbc66689312f07ace28e6ea90413c25b
4
+ data.tar.gz: fd09857eee368a41188c6c36084aacf061b31eef
5
5
  SHA512:
6
- metadata.gz: bcbdddb1f0cc451ecd9b345e62fc95d6049e5e1d9c715dff1b000f859a80728d1670fb42064e65b4ca1b2e93d26e9c036177b36d40a3a5802ad67a1e14a344d4
7
- data.tar.gz: 8e17c7774db57b2e9774d366ffbe04f301c8bb5d09761a7a9f6fb1892567cd2163a6197a31591ca7a249f8f4216c1f65790a3c91f6e074c45b1a7ad197ab448f
6
+ metadata.gz: 8421e20240201c3c8e66a03017d700dbdb91c669a092793b003ba5ea24234449ebe8c5c4f9517c6c943ecfd1eb5ad138279fc5548045babb004fbf2455c2ca02
7
+ data.tar.gz: 08802b5ba314ce4840c4ef883164877c57291a98ae1d76720fff5c58d8e4308adfbb5bb1479d77bc46a3525fd9a5ccad99fc643db317a9b92c71806550cb889f
@@ -9,12 +9,12 @@ class Chef::Provider::AwsAutoScalingGroup < Chef::Provider::AwsProvider
9
9
  :max_size => new_resource.max_size,
10
10
  :availability_zones => availability_zones
11
11
  }
12
-
12
+
13
13
  auto_scaling_opts[:desired_capacity] = new_resource.desired_capacity if new_resource.desired_capacity
14
14
  auto_scaling_opts[:load_balancers] = new_resource.load_balancers if new_resource.load_balancers
15
-
16
- converge_by "Creating new Auto Scaling group #{new_resource.name} in #{new_resource.region_name}" do
17
- @existing_group = auto_scaling.groups.create(
15
+
16
+ converge_by "Creating new Auto Scaling group #{new_resource.name} in #{new_driver.aws_config.region}" do
17
+ @existing_group = new_driver.auto_scaling.groups.create(
18
18
  new_resource.name,
19
19
  auto_scaling_opts
20
20
  )
@@ -26,7 +26,7 @@ class Chef::Provider::AwsAutoScalingGroup < Chef::Provider::AwsProvider
26
26
 
27
27
  action :delete do
28
28
  if existing_group
29
- converge_by "Deleting Auto Scaling group #{new_resource.name} in #{new_resource.region_name}" do
29
+ converge_by "Deleting Auto Scaling group #{new_resource.name} in #{new_driver.aws_config.region}" do
30
30
  existing_group.delete!
31
31
  end
32
32
  end
@@ -35,12 +35,12 @@ class Chef::Provider::AwsAutoScalingGroup < Chef::Provider::AwsProvider
35
35
  end
36
36
 
37
37
  def availability_zones
38
- @availability_zones ||= ec2.availability_zones.reduce([]) { |result, az| result << az }
38
+ @availability_zones ||= new_driver.ec2.availability_zones.reduce([]) { |result, az| result << az }
39
39
  end
40
40
 
41
41
  def existing_group
42
42
  @existing_group ||= begin
43
- eg = auto_scaling.groups[new_resource.name]
43
+ eg = new_driver.auto_scaling.groups[new_resource.name]
44
44
  eg.exists? ? eg : nil
45
45
  end
46
46
  end
@@ -6,9 +6,9 @@ class Chef::Provider::AwsEbsVolume < Chef::Provider::AwsProvider
6
6
 
7
7
  action :create do
8
8
  if existing_volume == nil
9
- converge_by "Creating new EBS volume #{fqn} in #{new_resource.region_name}" do
9
+ converge_by "Creating new EBS volume #{fqn} in #{new_driver.aws_config.region}" do
10
10
 
11
- ebs = ec2.volumes.create(
11
+ ebs = new_driver.ec2.volumes.create(
12
12
  :availability_zone => new_resource.availability_zone,
13
13
  :size => new_resource.size.to_i
14
14
  )
@@ -27,7 +27,7 @@ class Chef::Provider::AwsEbsVolume < Chef::Provider::AwsProvider
27
27
 
28
28
  action :delete do
29
29
  if existing_volume
30
- converge_by "Deleting EBS volume #{fqn} in #{new_resource.region_name}" do
30
+ converge_by "Deleting EBS volume #{fqn} in #{new_driver.aws_config.region}" do
31
31
  existing_volume.delete
32
32
  end
33
33
  end
@@ -39,7 +39,7 @@ class Chef::Provider::AwsEbsVolume < Chef::Provider::AwsProvider
39
39
  def existing_volume
40
40
  @existing_volume ||= new_resource.volume_id == nil ? nil : begin
41
41
  Chef::Log.debug("Loading volume #{new_resource.volume_id}")
42
- volume = ec2.volumes[new_resource.volume_id]
42
+ volume = new_driver.ec2.volumes[new_resource.volume_id]
43
43
  if [:deleted, :deleting, :error].include? volume.status
44
44
  nil
45
45
  else
@@ -6,8 +6,8 @@ class Chef::Provider::AwsEipAddress < Chef::Provider::AwsProvider
6
6
 
7
7
  action :create do
8
8
  if existing_ip == nil
9
- converge_by "Creating new EIP address in #{new_resource.region_name}" do
10
- eip = ec2.elastic_ips.create :vpc => new_resource.associate_to_vpc
9
+ converge_by "Creating new EIP address in #{new_driver.aws_config.region}" do
10
+ eip = new_driver.ec2.elastic_ips.create :vpc => new_resource.associate_to_vpc
11
11
  new_resource.public_ip eip.public_ip
12
12
  new_resource.domain eip.domain
13
13
  new_resource.instance_id eip.instance_id
@@ -22,7 +22,7 @@ class Chef::Provider::AwsEipAddress < Chef::Provider::AwsProvider
22
22
 
23
23
  action :delete do
24
24
  if existing_ip
25
- converge_by "Deleting EIP Address #{new_resource.name} in #{new_resource.region_name}" do
25
+ converge_by "Deleting EIP Address #{new_resource.name} in #{new_driver.aws_config.region}" do
26
26
  #if it's attached to something in a vpc, disassociate first
27
27
  if existing_ip.instance_id != nil && existing_ip.domain == 'vpc'
28
28
  existing_ip.disassociate
@@ -34,11 +34,11 @@ class Chef::Provider::AwsEipAddress < Chef::Provider::AwsProvider
34
34
  end
35
35
 
36
36
  action :associate do
37
- converge_by "Associating EIP Address #{new_resource.name} in #{new_resource.region_name}" do
37
+ converge_by "Associating EIP Address #{new_resource.name} in #{new_driver.aws_config.region}" do
38
38
  if existing_ip == nil
39
39
  action_create
40
40
  end
41
- eip = ec2.elastic_ips[new_resource.public_ip]
41
+ eip = new_driver.ec2.elastic_ips[new_resource.public_ip]
42
42
  begin
43
43
  spec = Chef::Provisioning::ChefMachineSpec.get(new_resource.machine)
44
44
  if spec == nil
@@ -55,7 +55,7 @@ class Chef::Provider::AwsEipAddress < Chef::Provider::AwsProvider
55
55
  end
56
56
 
57
57
  action :disassociate do
58
- converge_by "Disassociating EIP Address #{new_resource.name} in #{new_resource.region_name}" do
58
+ converge_by "Disassociating EIP Address #{new_resource.name} in #{new_driver.aws_config.region}" do
59
59
  begin
60
60
  if existing_ip != nil
61
61
  existing_ip.disassociate
@@ -73,7 +73,7 @@ class Chef::Provider::AwsEipAddress < Chef::Provider::AwsProvider
73
73
  def existing_ip
74
74
  new_resource.hydrate
75
75
  @existing_ip ||= new_resource.public_ip == nil ? nil : begin
76
- eip = ec2.elastic_ips[new_resource.public_ip]
76
+ eip = new_driver.ec2.elastic_ips[new_resource.public_ip]
77
77
  eip
78
78
  rescue => e
79
79
  Chef::Application.fatal!("Error looking for EIP Address: #{e}")
@@ -18,7 +18,7 @@ class Chef::Provider::AwsKeyPair < Chef::Provider::AwsProvider
18
18
 
19
19
  action :delete do
20
20
  if current_resource_exists?
21
- ec2.key_pairs[new_resource.name].delete
21
+ new_driver.ec2.key_pairs[new_resource.name].delete
22
22
  end
23
23
  end
24
24
 
@@ -79,8 +79,8 @@ class Chef::Provider::AwsKeyPair < Chef::Provider::AwsProvider
79
79
  if !new_fingerprints.any? { |f| compare_public_key f }
80
80
  if new_resource.allow_overwrite
81
81
  converge_by "update #{key_description} to match local key at #{new_resource.private_key_path}" do
82
- ec2.key_pairs[new_resource.name].delete
83
- ec2.key_pairs.import(new_resource.name, Cheffish::KeyFormatter.encode(desired_key, :format => :openssh))
82
+ new_driver.ec2.key_pairs[new_resource.name].delete
83
+ new_driver.ec2.key_pairs.import(new_resource.name, Cheffish::KeyFormatter.encode(desired_key, :format => :openssh))
84
84
  end
85
85
  else
86
86
  raise "#{key_description} with fingerprint #{@current_fingerprint} does not match local key fingerprint(s) #{new_fingerprints}, and allow_overwrite is false!"
@@ -92,7 +92,7 @@ class Chef::Provider::AwsKeyPair < Chef::Provider::AwsProvider
92
92
 
93
93
  # Create key
94
94
  converge_by "create #{key_description} from local key at #{new_resource.private_key_path}" do
95
- ec2.key_pairs.import(new_resource.name, Cheffish::KeyFormatter.encode(desired_key, :format => :openssh))
95
+ new_driver.ec2.key_pairs.import(new_resource.name, Cheffish::KeyFormatter.encode(desired_key, :format => :openssh))
96
96
  end
97
97
  end
98
98
  end
@@ -136,7 +136,7 @@ class Chef::Provider::AwsKeyPair < Chef::Provider::AwsProvider
136
136
 
137
137
  def existing_keypair
138
138
  @existing_keypair ||= begin
139
- ec2.key_pairs[fqn]
139
+ new_driver.ec2.key_pairs[fqn]
140
140
  rescue
141
141
  nil
142
142
  end
@@ -175,7 +175,7 @@ class Chef::Provider::AwsKeyPair < Chef::Provider::AwsProvider
175
175
  def load_current_resource
176
176
  @current_resource = Chef::Resource::AwsKeyPair.new(new_resource.name, run_context)
177
177
 
178
- current_key_pair = ec2.key_pairs[new_resource.name]
178
+ current_key_pair = new_driver.ec2.key_pairs[new_resource.name]
179
179
  if current_key_pair && current_key_pair.exists?
180
180
  @current_fingerprint = current_key_pair ? current_key_pair.fingerprint : nil
181
181
  else
@@ -3,8 +3,8 @@ require 'chef/provider/aws_provider'
3
3
  class Chef::Provider::AwsLaunchConfig < Chef::Provider::AwsProvider
4
4
  action :create do
5
5
  if existing_launch_config.nil?
6
- converge_by "Creating new Launch Config #{id} in #{new_resource.region_name}" do
7
- @existing_launch_config = auto_scaling.launch_configurations.create(
6
+ converge_by "Creating new Launch Config #{id} in #{new_driver.aws_config.region}" do
7
+ @existing_launch_config = new_driver.auto_scaling.launch_configurations.create(
8
8
  new_resource.name,
9
9
  new_resource.image,
10
10
  new_resource.instance_type
@@ -17,7 +17,7 @@ class Chef::Provider::AwsLaunchConfig < Chef::Provider::AwsProvider
17
17
 
18
18
  action :delete do
19
19
  if existing_launch_config
20
- converge_by "Deleting Launch Config #{id} in #{new_resource.region_name}" do
20
+ converge_by "Deleting Launch Config #{id} in #{new_driver.aws_config.region}" do
21
21
  begin
22
22
  existing_launch_config.delete
23
23
  rescue AWS::AutoScaling::Errors::ResourceInUse
@@ -32,7 +32,7 @@ class Chef::Provider::AwsLaunchConfig < Chef::Provider::AwsProvider
32
32
 
33
33
  def existing_launch_config
34
34
  @existing_launch_config ||= begin
35
- elc = auto_scaling.launch_configurations[new_resource.name]
35
+ elc = new_driver.auto_scaling.launch_configurations[new_resource.name]
36
36
  elc.exists? ? elc : nil
37
37
  end
38
38
  end
@@ -1,89 +1,22 @@
1
1
  require 'chef/provider/lwrp_base'
2
- require 'chef/provisioning/aws_driver/credentials'
3
2
 
4
3
  class Chef::Provider::AwsProvider < Chef::Provider::LWRPBase
5
4
  use_inline_resources
6
5
 
7
- attr_reader :credentials
8
-
9
6
  # All these need to implement whyrun
10
7
  def whyrun_supported?
11
8
  true
12
9
  end
13
10
 
14
- def from_hash hash
15
- hash.each do |k,v|
16
- begin
17
- self.instance_variable_set("@#{k}", v)
18
- rescue NameError => ne
19
- # nothing...
20
- end
21
- end
22
- self
23
- end
24
-
25
- def resource_from_databag(fqn, chef_server = Cheffish.default_chef_server)
26
- chef_api = Cheffish.chef_server_api(chef_server)
27
- begin
28
- data = chef_api.get("/data/#{databag_name}/#{fqn}")
29
- rescue Net::HTTPServerException => e
30
- if e.response.code == '404'
31
- nil
32
- else
33
- raise
34
- end
35
- end
36
- end
37
-
38
- def initialize(*args)
39
- super
40
- # TODO - temporary, needs to be better
41
- @credentials = Chef::Provisioning::AWSDriver::Credentials.new
42
- @credentials.load_default
43
- credentials = @credentials.default
44
- AWS.config(:access_key_id => credentials[:aws_access_key_id],
45
- :secret_access_key => credentials[:aws_secret_access_key])
46
- end
47
-
48
- def self.databag_name
49
- raise 'Class does not implement databag name'
50
- end
51
-
52
11
  def fqn
53
12
  if id
54
13
  id
55
14
  else
56
- "#{new_resource.name}_#{new_resource.region_name}"
15
+ "#{new_resource.name}_#{new_driver.aws_config.region}"
57
16
  end
58
17
  end
59
18
 
60
- # AWS objects we might need
61
- def ec2
62
- @ec2 ||= aws_init { AWS::EC2.new }
63
- end
64
-
65
- def sns
66
- @sns ||= aws_init { AWS::SNS.new }
67
- end
68
-
69
- def sqs
70
- @sqs ||= aws_init { AWS::SQS.new }
71
- end
72
-
73
- def s3
74
- @s3 ||= aws_init { AWS::S3.new }
75
- end
76
-
77
- def auto_scaling
78
- @auto_scaling ||= aws_init { AWS::AutoScaling.new }
79
- end
80
-
81
- private
82
- def aws_init
83
- credentials = @credentials.default
84
- region = new_resource.region_name || credentials[:region]
85
- # Pivot region
86
- AWS.config(:region => region)
87
- yield
19
+ def new_driver
20
+ run_context.chef_provisioning.driver_for(new_resource.driver)
88
21
  end
89
22
  end
@@ -5,7 +5,7 @@ class Chef::Provider::AwsS3Bucket < Chef::Provider::AwsProvider
5
5
  action :create do
6
6
  if existing_bucket == nil
7
7
  converge_by "Creating new S3 bucket #{fqn}" do
8
- bucket = s3.buckets.create(fqn)
8
+ bucket = new_driver.s3.buckets.create(fqn)
9
9
  bucket.tags['Name'] = new_resource.name
10
10
  end
11
11
  end
@@ -38,7 +38,7 @@ class Chef::Provider::AwsS3Bucket < Chef::Provider::AwsProvider
38
38
 
39
39
  def existing_bucket
40
40
  Chef::Log.debug("Checking for S3 bucket #{fqn}")
41
- @existing_bucket ||= s3.buckets[fqn] if s3.buckets[fqn].exists?
41
+ @existing_bucket ||= new_driver.s3.buckets[fqn] if new_driver.s3.buckets[fqn].exists?
42
42
  end
43
43
 
44
44
  def modifies_website_configuration?
@@ -5,7 +5,7 @@ class Chef::Provider::AwsSecurityGroup < Chef::Provider::AwsProvider
5
5
 
6
6
  action :create do
7
7
  if existing_sg == nil
8
- converge_by "Creating new SG #{new_resource.name} in #{new_resource.region_name}" do
8
+ converge_by "Creating new SG #{new_resource.name} in #{new_driver.aws_config.region}" do
9
9
  opts = {
10
10
  :description => new_resource.description,
11
11
  :vpc => nil
@@ -14,14 +14,14 @@ class Chef::Provider::AwsSecurityGroup < Chef::Provider::AwsProvider
14
14
  if new_resource.vpc_id
15
15
  opts[:vpc] = new_resource.vpc_id
16
16
  elsif new_resource.vpc_name
17
- existing_vpc = ec2.vpcs.with_tag('Name', new_resource.vpc_name).first
17
+ existing_vpc = new_driver.ec2.vpcs.with_tag('Name', new_resource.vpc_name).first
18
18
  Chef::Log.debug("Existing VPC: #{existing_vpc.inspect}")
19
19
  if existing_vpc
20
20
  opts[:vpc] = existing_vpc
21
21
  end
22
22
  end
23
23
 
24
- sg = ec2.security_groups.create(new_resource.name, opts)
24
+ sg = new_driver.ec2.security_groups.create(new_resource.name, opts)
25
25
  new_resource.security_group_id sg.group_id
26
26
  new_resource.save
27
27
  end
@@ -33,7 +33,7 @@ class Chef::Provider::AwsSecurityGroup < Chef::Provider::AwsProvider
33
33
 
34
34
  action :delete do
35
35
  if existing_sg
36
- converge_by "Deleting SG #{new_resource.name} in #{new_resource.region_name}" do
36
+ converge_by "Deleting SG #{new_resource.name} in #{new_driver.aws_config.region}" do
37
37
  existing_sg.delete
38
38
  end
39
39
  end
@@ -47,7 +47,7 @@ class Chef::Provider::AwsSecurityGroup < Chef::Provider::AwsProvider
47
47
  if new_resource.inbound_rules
48
48
  new_resource.inbound_rules.each do |rule|
49
49
  begin
50
- converge_by "Updating SG #{new_resource.name} in #{new_resource.region_name} to allow inbound #{rule[:protocol]}/#{rule[:ports]} from #{rule[:sources]}" do
50
+ converge_by "Updating SG #{new_resource.name} in #{new_driver.aws_config.region} to allow inbound #{rule[:protocol]}/#{rule[:ports]} from #{rule[:sources]}" do
51
51
  security_group.authorize_ingress(rule[:protocol], rule[:ports], *rule[:sources])
52
52
  end
53
53
  rescue AWS::EC2::Errors::InvalidPermission::Duplicate
@@ -60,7 +60,7 @@ class Chef::Provider::AwsSecurityGroup < Chef::Provider::AwsProvider
60
60
  if new_resource.outbound_rules
61
61
  new_resource.outbound_rules.each do |rule|
62
62
  begin
63
- converge_by "Updating SG #{new_resource.name} in #{new_resource.region_name} to allow outbound #{rule[:protocol]}/#{rule[:ports]} to #{rule[:destinations]}" do
63
+ converge_by "Updating SG #{new_resource.name} in #{new_driver.aws_config.region} to allow outbound #{rule[:protocol]}/#{rule[:ports]} to #{rule[:destinations]}" do
64
64
  security_group.authorize_egress( *rule[:destinations], :protocol => rule[:protocol], :ports => rule[:ports])
65
65
  end
66
66
  rescue AWS::EC2::Errors::InvalidPermission::Duplicate
@@ -73,7 +73,7 @@ class Chef::Provider::AwsSecurityGroup < Chef::Provider::AwsProvider
73
73
  def existing_sg
74
74
  @existing_sg ||= begin
75
75
  if id != nil
76
- ec2.security_groups[id]
76
+ new_driver.ec2.security_groups[id]
77
77
  else
78
78
  nil
79
79
  end
@@ -5,8 +5,8 @@ class Chef::Provider::AwsSnsTopic < Chef::Provider::AwsProvider
5
5
 
6
6
  action :create do
7
7
  if existing_topic == nil
8
- converge_by "Creating new SNS topic #{fqn} in #{new_resource.region_name}" do
9
- sns.topics.create(fqn)
8
+ converge_by "Creating new SNS topic #{fqn} in #{new_driver.aws_config.region}" do
9
+ new_driver.sns.topics.create(fqn)
10
10
 
11
11
  new_resource.created_at DateTime.now.to_s
12
12
  new_resource.save
@@ -16,7 +16,7 @@ class Chef::Provider::AwsSnsTopic < Chef::Provider::AwsProvider
16
16
 
17
17
  action :delete do
18
18
  if existing_topic
19
- converge_by "Deleting SNS topic #{fqn} in #{new_resource.region_name}" do
19
+ converge_by "Deleting SNS topic #{fqn} in #{new_driver.aws_config.region}" do
20
20
  existing_topic.delete
21
21
  end
22
22
  end
@@ -26,7 +26,7 @@ class Chef::Provider::AwsSnsTopic < Chef::Provider::AwsProvider
26
26
 
27
27
  def existing_topic
28
28
  @existing_topic ||= begin
29
- sns.topics.named(fqn)
29
+ new_driver.sns.topics.named(fqn)
30
30
  rescue
31
31
  nil
32
32
  end
@@ -5,10 +5,10 @@ class Chef::Provider::AwsSqsQueue < Chef::Provider::AwsProvider
5
5
 
6
6
  action :create do
7
7
  if existing_queue == nil
8
- converge_by "Creating new SQS queue #{fqn} in #{new_resource.region_name}" do
8
+ converge_by "Creating new SQS queue #{fqn} in #{new_driver.aws_config.region}" do
9
9
  loop do
10
10
  begin
11
- sqs.queues.create(fqn)
11
+ new_driver.sqs.queues.create(fqn)
12
12
  break
13
13
  rescue AWS::SQS::Errors::QueueDeletedRecently
14
14
  sleep 5
@@ -23,7 +23,7 @@ class Chef::Provider::AwsSqsQueue < Chef::Provider::AwsProvider
23
23
 
24
24
  action :delete do
25
25
  if existing_queue
26
- converge_by "Deleting SQS queue #{fqn} in #{new_resource.region_name}" do
26
+ converge_by "Deleting SQS queue #{fqn} in #{new_driver.aws_config.region}" do
27
27
  existing_queue.delete
28
28
  end
29
29
  end
@@ -33,7 +33,7 @@ class Chef::Provider::AwsSqsQueue < Chef::Provider::AwsProvider
33
33
 
34
34
  def existing_queue
35
35
  @existing_queue ||= begin
36
- sqs.queues.named(fqn)
36
+ new_driver.sqs.queues.named(fqn)
37
37
  rescue
38
38
  nil
39
39
  end
@@ -7,10 +7,10 @@ class Chef::Provider::AwsSubnet < Chef::Provider::AwsProvider
7
7
  fail "Can't create a Subnet without a CIDR block" if new_resource.cidr_block.nil?
8
8
 
9
9
  if existing_subnet == nil
10
- converge_by "Creating new Subnet #{fqn} in VPC #{new_resource.vpc} in #{new_resource.region_name}" do
10
+ converge_by "Creating new Subnet #{fqn} in VPC #{new_resource.vpc} in #{new_driver.aws_config.region}" do
11
11
  opts = { :vpc => vpc_id }
12
12
  opts[:availability_zone] = new_resource.availability_zone if new_resource.availability_zone
13
- subnet = ec2.subnets.create(new_resource.cidr_block, opts)
13
+ subnet = new_driver.ec2.subnets.create(new_resource.cidr_block, opts)
14
14
  subnet.tags['Name'] = new_resource.name
15
15
  subnet.tags['VPC'] = new_resource.vpc
16
16
  new_resource.subnet_id subnet.id
@@ -21,7 +21,7 @@ class Chef::Provider::AwsSubnet < Chef::Provider::AwsProvider
21
21
 
22
22
  action :delete do
23
23
  if existing_subnet
24
- converge_by "Deleting subnet #{fqn} in VPC #{new_resource.vpc} in #{new_resource.region_name}" do
24
+ converge_by "Deleting subnet #{fqn} in VPC #{new_resource.vpc} in #{new_driver.aws_config.region}" do
25
25
  existing_subnet.delete
26
26
  end
27
27
  end
@@ -31,7 +31,7 @@ class Chef::Provider::AwsSubnet < Chef::Provider::AwsProvider
31
31
 
32
32
  def vpc_id
33
33
  @vpc_id ||= begin
34
- ec2.vpcs.with_tag('Name', new_resource.vpc).first
34
+ new_driver.ec2.vpcs.with_tag('Name', new_resource.vpc).first
35
35
  rescue
36
36
  nil
37
37
  end
@@ -39,7 +39,7 @@ class Chef::Provider::AwsSubnet < Chef::Provider::AwsProvider
39
39
 
40
40
  def existing_subnet
41
41
  @subnet_id ||= begin
42
- ec2.subnets.with_tag('Name', new_resource.name).first
42
+ new_driver.ec2.subnets.with_tag('Name', new_resource.name).first
43
43
  rescue
44
44
  nil
45
45
  end
@@ -7,9 +7,9 @@ class Chef::Provider::AwsVpc < Chef::Provider::AwsProvider
7
7
  fail "Can't create a VPC without a CIDR block" if new_resource.cidr_block.nil?
8
8
 
9
9
  if existing_vpc == nil
10
- converge_by "Creating new VPC #{fqn} in #{new_resource.region_name}" do
10
+ converge_by "Creating new VPC #{fqn} in #{new_driver.aws_config.region}" do
11
11
  opts = { :instance_tenancy => :default}
12
- vpc = ec2.vpcs.create(new_resource.cidr_block, opts)
12
+ vpc = new_driver.ec2.vpcs.create(new_resource.cidr_block, opts)
13
13
  vpc.tags['Name'] = new_resource.name
14
14
  new_resource.vpc_id vpc.id
15
15
  new_resource.save
@@ -19,7 +19,7 @@ class Chef::Provider::AwsVpc < Chef::Provider::AwsProvider
19
19
 
20
20
  action :delete do
21
21
  if existing_vpc
22
- converge_by "Deleting VPC #{fqn} in #{new_resource.region_name}" do
22
+ converge_by "Deleting VPC #{fqn} in #{new_driver.aws_config.region}" do
23
23
  existing_vpc.delete
24
24
  end
25
25
  end
@@ -29,7 +29,7 @@ class Chef::Provider::AwsVpc < Chef::Provider::AwsProvider
29
29
 
30
30
  def existing_vpc
31
31
  @existing_vpc ||= begin
32
- ec2.vpcs.with_tag('Name', new_resource.name).first
32
+ new_driver.ec2.vpcs.with_tag('Name', new_resource.name).first
33
33
  rescue
34
34
  nil
35
35
  end
@@ -29,7 +29,7 @@ module AWSDriver
29
29
 
30
30
  include Chef::Mixin::ShellOut
31
31
 
32
- attr_reader :region
32
+ attr_reader :aws_config
33
33
 
34
34
  # URL scheme:
35
35
  # aws:profilename:region
@@ -47,45 +47,58 @@ module AWSDriver
47
47
  region = nil if region && region.empty?
48
48
 
49
49
  credentials = profile_name ? aws_credentials[profile_name] : aws_credentials.default
50
- @region = region || credentials[:region]
51
- # TODO: fix credentials here
52
- AWS.config(:access_key_id => credentials[:aws_access_key_id],
53
- :secret_access_key => credentials[:aws_secret_access_key],
54
- :region => @region)
50
+ @aws_config = AWS::Core::Configuration.new(
51
+ access_key_id: credentials[:aws_access_key_id],
52
+ secret_access_key: credentials[:aws_secret_access_key],
53
+ region: region || credentials[:region]
54
+ )
55
55
  end
56
56
 
57
57
  def self.canonicalize_url(driver_url, config)
58
58
  [ driver_url, config ]
59
59
  end
60
60
 
61
-
62
61
  # Load balancer methods
63
62
  def allocate_load_balancer(action_handler, lb_spec, lb_options, machine_specs)
64
63
  lb_options ||= {}
65
- if lb_options[:security_group_id]
66
- security_group = ec2.security_groups[:security_group_id]
67
- elsif lb_options[:security_group_name]
68
- security_group = ec2.security_groups.filter('group-name', lb_options[:security_group_name])
64
+ if lb_options[:security_group_ids]
65
+ security_groups = ec2.security_groups.filter('group-id', lb_options[:security_group_ids]).to_a
66
+ elsif lb_options[:security_group_names]
67
+ security_groups = ec2.security_groups.filter('group-name', lb_options[:security_group_names]).to_a
68
+ else
69
+ security_groups = []
69
70
  end
71
+ security_group_ids = security_groups.map { |sg| sg.id }
70
72
 
71
- availability_zones = lb_options[:availability_zones]
73
+ availability_zones = lb_options[:availability_zones] || []
74
+ subnets = lb_options[:subnets] || []
72
75
  listeners = lb_options[:listeners]
76
+ scheme = lb_options[:scheme]
73
77
 
74
78
  validate_listeners(listeners)
79
+ if !availability_zones.empty? && !subnets.empty?
80
+ raise "You cannot specify both `availability_zones` and `subnets`"
81
+ end
75
82
 
76
83
  lb_optionals = {}
77
- lb_optionals[:security_groups] = [security_group] if security_group
78
- lb_optionals[:availability_zones] = availability_zones if availability_zones
84
+ lb_optionals[:security_groups] = security_group_ids unless security_group_ids.empty?
85
+ lb_optionals[:availability_zones] = availability_zones unless availability_zones.empty?
86
+ lb_optionals[:subnets] = subnets unless subnets.empty?
79
87
  lb_optionals[:listeners] = listeners if listeners
88
+ lb_optionals[:scheme] = scheme if scheme
80
89
 
90
+ old_elb = nil
81
91
  actual_elb = load_balancer_for(lb_spec)
82
92
  if !actual_elb.exists?
83
93
  perform_action = proc { |desc, &block| action_handler.perform_action(desc, &block) }
84
94
 
85
- updates = [ "Create load balancer #{lb_spec.name} in #{@region}" ]
86
- updates << " enable availability zones #{availability_zones.join(', ')}" if availability_zones && availability_zones.size > 0
95
+ security_group_names = security_groups.map { |sg| sg.name }.join(",")
96
+
97
+ updates = [ "Create load balancer #{lb_spec.name} in #{aws_config.region}" ]
98
+ updates << " enable availability zones #{availability_zones.join(', ')}" if availability_zones.size > 0
99
+ updates << " attach subnets #{subnets.join(', ')}" if subnets.size > 0
87
100
  updates << " with listeners #{listeners.join(', ')}" if listeners && listeners.size > 0
88
- updates << " with security group #{security_group.name}" if security_group
101
+ updates << " with security groups #{security_group_names}" if security_group_names
89
102
 
90
103
  action_handler.perform_action updates do
91
104
  actual_elb = elb.load_balancers.create(lb_spec.name, lb_optionals)
@@ -100,25 +113,113 @@ module AWSDriver
100
113
  # Header gets printed the first time we make an update
101
114
  perform_action = proc do |desc, &block|
102
115
  perform_action = proc { |desc, &block| action_handler.perform_action(desc, &block) }
103
- action_handler.perform_action [ "Update load balancer #{lb_spec.name} in #{@region}", desc ].flatten, &block
116
+ action_handler.perform_action [ "Update load balancer #{lb_spec.name} in #{aws_config.region}", desc ].flatten, &block
104
117
  end
105
118
 
106
- # Update availability zones
107
- enable_zones = (availability_zones || []).dup
108
- disable_zones = []
109
- actual_elb.availability_zones.each do |availability_zone|
110
- if !enable_zones.delete(availability_zone.name)
111
- disable_zones << availability_zone.name
119
+ # TODO: refactor this whole giant method into many smaller method calls
120
+ # Update scheme - scheme is immutable once set, so if it is changing we need to delete the old
121
+ # ELB and create a new one
122
+ if scheme && scheme.downcase != actual_elb.scheme
123
+ desc = [" updating scheme to #{scheme}"]
124
+ desc << " WARN: scheme is immutable, so deleting and re-creating the ELB"
125
+ perform_action.call(desc) do
126
+ old_elb = actual_elb
127
+ actual_elb = elb.load_balancers.create(lb_spec.name, lb_optionals)
112
128
  end
113
129
  end
114
- if enable_zones.size > 0
115
- perform_action.call(" enable availability zones #{enable_zones.join(', ')}") do
116
- actual_elb.availability_zones.enable(*enable_zones)
130
+
131
+ # Update security groups
132
+ if security_group_ids.empty?
133
+ Chef::Log.debug("No Security Groups specified. Load_balancer[#{actual_elb.name}] cannot have " +
134
+ "empty Security Groups, so assuming it only currently has the default Security Group. No action taken.")
135
+ else
136
+ current = actual_elb.security_group_ids
137
+ desired = security_group_ids
138
+ if current != desired
139
+ perform_action.call(" updating security groups to #{desired.to_a}") do
140
+ elb.client.apply_security_groups_to_load_balancer(
141
+ load_balancer_name: actual_elb.name,
142
+ security_groups: desired.to_a
143
+ )
144
+ end
117
145
  end
118
146
  end
119
- if disable_zones.size > 0
120
- perform_action.call(" disable availability zones #{disable_zones.join(', ')}") do
121
- actual_elb.availability_zones.disable(*disable_zones)
147
+
148
+ # A subnet always belongs to an availability zone. When specifying a ELB spec, you can either
149
+ # specify subnets OR AZs but not both. You cannot specify multiple subnets in the same AZ.
150
+ # You must specify at least 1 subnet or AZ. On an update you cannot remove all subnets
151
+ # or AZs - it must belong to one.
152
+ if !availability_zones.empty? && !subnets.empty?
153
+ # We do this check here because there is no atomic call we can make to specify both
154
+ # subnets and AZs at the same time
155
+ raise "You cannot specify both `availability_zones` and `subnets`"
156
+ end
157
+ # Users can switch from availability zones to subnets or vice versa. To ensure we do not
158
+ # unassign all (which causes an AWS error) we first add all available ones, then remove
159
+ # an unecessary ones
160
+ actual_zones_subnets = {}
161
+ actual_elb.subnets.each do |subnet|
162
+ actual_zones_subnets[subnet.id] = subnet.availability_zone.name
163
+ end
164
+
165
+ # Only 1 of subnet or AZ will be populated b/c of our check earlier
166
+ desired_subnets_zones = {}
167
+ availability_zones.each do |zone|
168
+ # If the user specifies availability zone, we find the default subnet for that
169
+ # AZ because this duplicates the create logic
170
+ zone = zone.downcase
171
+ filters = [
172
+ {:name => 'availabilityZone', :values => [zone]},
173
+ {:name => 'defaultForAz', :values => ['true']}
174
+ ]
175
+ default_subnet = ec2.client.describe_subnets(:filters => filters)[:subnet_set]
176
+ if default_subnet.size != 1
177
+ raise "Could not find default subnet in availability zone #{zone}"
178
+ end
179
+ default_subnet = default_subnet[0]
180
+ desired_subnets_zones[default_subnet[:subnet_id]] = zone
181
+ end
182
+ unless subnets.empty?
183
+ subnet_query = ec2.client.describe_subnets(:subnet_ids => subnets)[:subnet_set]
184
+ # AWS raises an error on an unknown subnet, but not an unknown AZ
185
+ subnet_query.each do |subnet|
186
+ zone = subnet[:availability_zone].downcase
187
+ desired_subnets_zones[subnet[:subnet_id]] = zone
188
+ end
189
+ end
190
+
191
+ # We only bother attaching subnets, because doing this automatically attaches the AZ
192
+ attach_subnets = desired_subnets_zones.keys - actual_zones_subnets.keys
193
+ unless attach_subnets.empty?
194
+ action = " attach subnets #{attach_subnets.join(', ')}"
195
+ enable_zones = (desired_subnets_zones.map {|s,z| z if attach_subnets.include?(s)}).compact
196
+ action += " (availability zones #{enable_zones.join(', ')})"
197
+ perform_action.call(action) do
198
+ begin
199
+ elb.client.attach_load_balancer_to_subnets(
200
+ load_balancer_name: actual_elb.name,
201
+ subnets: attach_subnets
202
+ )
203
+ rescue AWS::ELB::Errors::InvalidConfigurationRequest
204
+ raise "You cannot currently move from 1 subnet to another in the same availability zone. " +
205
+ "Amazon does not have an atomic operation which allows this. You must create a new " +
206
+ "ELB with the correct subnets and move instances into it. Tried to attach subets " +
207
+ "#{attach_subnets.join(', ')} (availability zones #{enable_zones.join(', ')}) to " +
208
+ "existing ELB named #{actual_elb.name}"
209
+ end
210
+ end
211
+ end
212
+
213
+ detach_subnets = actual_zones_subnets.keys - desired_subnets_zones.keys
214
+ unless detach_subnets.empty?
215
+ action = " detach subnets #{detach_subnets.join(', ')}"
216
+ disable_zones = (actual_zones_subnets.map {|s,z| z if detach_subnets.include?(s)}).compact
217
+ action += " (availability zones #{disable_zones.join(', ')})"
218
+ perform_action.call(action) do
219
+ elb.client.detach_load_balancer_from_subnets(
220
+ load_balancer_name: actual_elb.name,
221
+ subnets: detach_subnets
222
+ )
122
223
  end
123
224
  end
124
225
 
@@ -171,24 +272,39 @@ module AWSDriver
171
272
  end
172
273
  end
173
274
 
174
- # Update instance list
175
- actual_instance_ids = Set.new(actual_elb.instances.map { |i| i.instance_id })
176
-
177
- instances_to_add = machine_specs.select { |s| !actual_instance_ids.include?(s.location['instance_id']) }
178
- instance_ids_to_remove = actual_instance_ids - machine_specs.map { |s| s.location['instance_id'] }
275
+ # Update instance list, but only if there are machines specified
276
+ actual_instance_ids = actual_elb.instances.map { |i| i.instance_id }
179
277
 
180
- if instances_to_add.size > 0
181
- perform_action.call(" add machines #{instances_to_add.map { |s| s.name }.join(', ')}") do
182
- instance_ids_to_add = instances_to_add.map { |s| s.location['instance_id'] }
183
- Chef::Log.debug("Adding instances #{instance_ids_to_add.join(', ')} to load balancer #{actual_elb.name} in region #{@region}")
184
- actual_elb.instances.add(instance_ids_to_add)
278
+ if machine_specs
279
+ instances_to_add = machine_specs.select { |s| !actual_instance_ids.include?(s.location['instance_id']) }
280
+ instance_ids_to_remove = actual_instance_ids - machine_specs.map { |s| s.location['instance_id'] }
281
+
282
+ if instances_to_add.size > 0
283
+ perform_action.call(" add machines #{instances_to_add.map { |s| s.name }.join(', ')}") do
284
+ instance_ids_to_add = instances_to_add.map { |s| s.location['instance_id'] }
285
+ Chef::Log.debug("Adding instances #{instance_ids_to_add.join(', ')} to load balancer #{actual_elb.name} in region #{aws_config.region}")
286
+ actual_elb.instances.add(instance_ids_to_add)
287
+ end
288
+ end
289
+
290
+ if instance_ids_to_remove.size > 0
291
+ perform_action.call(" remove instances #{instance_ids_to_remove}") do
292
+ actual_elb.instances.remove(instance_ids_to_remove)
293
+ end
185
294
  end
186
295
  end
187
296
 
188
- if instance_ids_to_remove.size > 0
189
- perform_action.call(" remove instances #{instance_ids_to_remove}") do
190
- actual_elb.instances.remove(instance_ids_to_remove)
191
- end
297
+ # We have successfully switched all our instances to the (possibly) new LB
298
+ # so it is safe to delete the old one.
299
+ unless old_elb.nil?
300
+ old_elb.delete
301
+ end
302
+ ensure
303
+ # Something went wrong before we could moved instances from the old ELB to the new one
304
+ # Don't delete the old ELB, but warn users there could now be 2 ELBs with the same name
305
+ unless old_elb.nil?
306
+ Chef::Log.warn("It is possible there are now 2 ELB instances - #{old_elb.id} and #{actual_elb.id}. " +
307
+ "Determine which is correct and manually clean up the other.")
192
308
  end
193
309
  end
194
310
 
@@ -295,7 +411,7 @@ EOD
295
411
  if actual_instance == nil || !actual_instance.exists? || actual_instance.status == :terminated
296
412
  bootstrap_options = bootstrap_options_for(action_handler, machine_spec, machine_options)
297
413
 
298
- action_handler.perform_action "Create #{machine_spec.name} with AMI #{bootstrap_options[:image_id]} in #{@region}" do
414
+ action_handler.perform_action "Create #{machine_spec.name} with AMI #{bootstrap_options[:image_id]} in #{aws_config.region}" do
299
415
  Chef::Log.debug "Creating instance with bootstrap options #{bootstrap_options}"
300
416
 
301
417
  instance = ec2.instances.create(bootstrap_options.to_hash)
@@ -339,7 +455,7 @@ EOD
339
455
  if instance.status != :running
340
456
  wait_until_machine(action_handler, machine_spec, instance) { instance.status != :stopping }
341
457
  if instance.status == :stopped
342
- action_handler.perform_action "Start #{machine_spec.name} (#{machine_spec.location['instance_id']}) in #{@region} ..." do
458
+ action_handler.perform_action "Start #{machine_spec.name} (#{machine_spec.location['instance_id']}) in #{aws_config.region} ..." do
343
459
  instance.start
344
460
  end
345
461
  end
@@ -364,7 +480,7 @@ EOD
364
480
  instance = instance_for(machine_spec)
365
481
  if instance && instance.exists?
366
482
  # TODO do we need to wait_until(action_handler, machine_spec, instance) { instance.status != :shutting_down } ?
367
- action_handler.perform_action "Terminate #{machine_spec.name} (#{machine_spec.location['instance_id']}) in #{@region} ..." do
483
+ action_handler.perform_action "Terminate #{machine_spec.name} (#{machine_spec.location['instance_id']}) in #{aws_config.region} ..." do
368
484
  instance.terminate
369
485
  machine_spec.location = nil
370
486
  end
@@ -376,6 +492,30 @@ EOD
376
492
  strategy.cleanup_convergence(action_handler, machine_spec)
377
493
  end
378
494
 
495
+ def ec2
496
+ @ec2 ||= AWS::EC2.new(config: aws_config)
497
+ end
498
+
499
+ def elb
500
+ @elb ||= AWS::ELB.new(config: aws_config)
501
+ end
502
+
503
+ def sns
504
+ @sns ||= AWS::SNS.new(config: aws_config)
505
+ end
506
+
507
+ def sqs
508
+ @sqs ||= AWS::SQS.new(config: aws_config)
509
+ end
510
+
511
+ def s3
512
+ @s3 ||= AWS::S3.new(config: aws_config)
513
+ end
514
+
515
+ def auto_scaling
516
+ @auto_scaling ||= AWS::AutoScaling.new(config: aws_config)
517
+ end
518
+
379
519
  private
380
520
 
381
521
  # For creating things like AWS keypairs exclusively
@@ -397,7 +537,7 @@ EOD
397
537
 
398
538
  def bootstrap_options_for(action_handler, machine_spec, machine_options)
399
539
  bootstrap_options = (machine_options[:bootstrap_options] || {}).to_h.dup
400
- image_id = bootstrap_options[:image_id] || machine_options[:image_id] || default_ami_for_region(@region)
540
+ image_id = bootstrap_options[:image_id] || machine_options[:image_id] || default_ami_for_region(aws_config.region)
401
541
  bootstrap_options[:image_id] = image_id
402
542
  if !bootstrap_options[:key_name]
403
543
  Chef::Log.debug('No key specified, generating a default one...')
@@ -415,14 +555,6 @@ EOD
415
555
  bootstrap_options
416
556
  end
417
557
 
418
- def ec2
419
- @ec2 ||= AWS.ec2
420
- end
421
-
422
- def elb
423
- @elb ||= AWS::ELB.new
424
- end
425
-
426
558
  def default_ssh_username
427
559
  'ubuntu'
428
560
  end
@@ -747,13 +879,11 @@ EOD
747
879
  def default_aws_keypair(action_handler, machine_spec)
748
880
  driver = self
749
881
  default_key_name = default_aws_keypair_name(machine_spec)
750
- _region = region
751
882
  updated = @@chef_default_lock.synchronize do
752
883
  Provisioning.inline_resource(action_handler) do
753
884
  aws_key_pair default_key_name do
754
885
  driver driver
755
886
  allow_overwrite true
756
- region_name _region
757
887
  end
758
888
  end
759
889
  end
@@ -1,7 +1,7 @@
1
1
  class Chef
2
2
  module Provisioning
3
3
  module AWSDriver
4
- VERSION = '0.3'
4
+ VERSION = '0.4.0'
5
5
  end
6
6
  end
7
7
  end
@@ -4,15 +4,9 @@ require 'chef/resource/aws_resource'
4
4
  class Chef::Resource::AwsKeyPair < Chef::Resource::AwsResource
5
5
  self.resource_name = 'aws_key_pair'
6
6
 
7
- def initialize(*args)
8
- super
9
- @driver = run_context.chef_provisioning.current_driver
10
- end
11
-
12
7
  actions :create, :delete, :nothing
13
8
  default_action :create
14
9
 
15
- attribute :driver
16
10
  # Private key to use as input (will be generated if it does not exist)
17
11
  attribute :private_key_path, :kind_of => String
18
12
  # Public key to use as input (will be generated if it does not exist)
@@ -1,10 +1,10 @@
1
1
  # Common AWS resource - contains metadata that all AWS resources will need
2
2
  class Chef::Resource::AwsResource < Chef::Resource::ChefDataBagResource
3
- stored_attribute :region_name
3
+ stored_attribute :driver
4
4
 
5
5
  def initialize(*args)
6
6
  super
7
- @region_name = run_context.chef_provisioning.current_data_center
7
+ @driver = run_context.chef_provisioning.current_driver
8
8
  end
9
9
 
10
10
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chef-provisioning-aws
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.3'
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Ewart
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-26 00:00:00.000000000 Z
11
+ date: 2015-03-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chef
@@ -136,7 +136,6 @@ files:
136
136
  - lib/chef/resource/aws_sqs_queue.rb
137
137
  - lib/chef/resource/aws_subnet.rb
138
138
  - lib/chef/resource/aws_vpc.rb
139
- - spec/acceptance/aws_ebs_volume/nodes/ettores-mbp.lan.json
140
139
  - spec/chef_zero_rspec_helper.rb
141
140
  - spec/spec_helper.rb
142
141
  - spec/unit/aws_driver/credentials_spec.rb
@@ -161,9 +160,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
161
160
  version: '0'
162
161
  requirements: []
163
162
  rubyforge_project:
164
- rubygems_version: 2.2.2
163
+ rubygems_version: 2.4.2
165
164
  signing_key:
166
165
  specification_version: 4
167
166
  summary: Provisioner for creating aws containers in Chef Provisioning.
168
167
  test_files: []
169
- has_rdoc:
@@ -1,3 +0,0 @@
1
- {
2
- "name": "ettores-mbp.lan"
3
- }