Skip to content
This repository has been archived by the owner on Jun 5, 2020. It is now read-only.

Commit

Permalink
(MODULES-1702) Working RDS Creation
Browse files Browse the repository at this point in the history
* To get an MVP of RDS working, we also need to create an DB Security Group to access it
  • Loading branch information
petems committed Mar 9, 2015
1 parent 0fc6ec9 commit 7b26866
Show file tree
Hide file tree
Showing 20 changed files with 466 additions and 70 deletions.
53 changes: 53 additions & 0 deletions examples/postgres-rds-example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# RDS

[Amazon Relational Database Service](http://aws.amazon.com/rds/) (Amazon RDS) is a web service that makes it easy to set up, operate, and scale a relational database in the cloud.

## How

This example creates a security group to allow Postgres RDS instance, then creates an RDS instance with that security group assigned.

puppet apply rds_security.pp

Unfortunatly, it's not possible to assign the EC2 group and the allowed IP's to the `db_securitygroup` through the API, so you have to do this manually though the console for now:

## Add the Security Group We Made with Puppet**
![Add EC2 Security Group](./images/add-rds-securitygroup.png?raw=true)

## Add an IP to allow access to the RDS instance
**Note: Enter `0.0.0.0/32` to allow all IPs**
![Add IP to allow](./images/add-ip-to-allow.png?raw=true)

## It should look something like this
![Final Look](./images/final-screen.png?raw=true)

You can now check your security group is correct by using Puppet resource commands:

puppet resource rds_db_securitygroup rds-postgres-db_securitygroup

It should return something like this:

```puppet
rds_db_securitygroup { 'rds-postgres-db_securitygroup':
ensure => 'present',
ec2_security_groups => [{'ec2_security_group_id' => 'sg-83fb3z5', 'ec2_security_group_name' => 'rds-postgres-group', 'ec2_security_group_owner_id' => '4822239859', 'status' => 'authorized'}],
ip_ranges => [{'ip_range' => '0.0.0.0/32', 'status' => 'authorized'}],
owner_id => '239838031',
region => 'us-west-2',
}
```
When this is complete, create the RDS Postgres instance:

puppet apply rds_postgres.pp

This can take a while to setup, but when it's complete, you should be able to access it:

```bash
psql -d postgresql -h puppetlabs-aws-postgres.cwgutxb9fmx.us-west-2.rds.amazonaws.com -U root

Password for user root: pullZstringz345
psql (9.4.0, server 9.3.5)
SSL connection (protocol: TLSv1.2, cipher: DHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

postgresql=> exit
```
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions examples/postgres-rds-example/rds_postgres.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
rds_instance { 'puppetlabs-aws-postgres':
ensure => 'present',
allocated_storage => '5',
db_instance_class => 'db.m3.medium',
db_name => 'postgresql',
engine => 'postgres',
license_model => 'postgresql-license',
db_security_groups => 'rds-postgres-db_securitygroup',
master_username => 'root',
master_user_password=> 'pullZstringz345',
multi_az => 'false',
region => 'us-west-2',
skip_final_snapshot => 'true',
storage_type => 'gp2',
}
18 changes: 18 additions & 0 deletions examples/postgres-rds-example/rds_security.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
ec2_securitygroup { 'rds-postgres-group':
ensure => present,
region => 'us-west-2',
description => 'Group for Allowing access to Postgres (Port 5432)',
ingress => [{
security_group => 'rds-postgres-group',
},{
protocol => 'tcp',
port => 5432,
cidr => '0.0.0.0/0',
}]
}

rds_db_securitygroup { 'rds-postgres-db_securitygroup':
ensure => 'present',
region => 'us-west-2',
db_security_group_description => 'An RDS Security group to allow Postgres',
}
15 changes: 13 additions & 2 deletions lib/puppet/provider/rds_db_securitygroup/v2.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,12 @@ def self.prefetch(resources)
def self.db_security_group_to_hash(region, db_security_group)
{
:ensure => :present,
:region => region,
:name => db_security_group.db_security_group_name,
:db_security_group_description => db_security_group.db_security_group_description,
:owner_id => db_security_group.owner_id,
:ec2_security_groups => ec2_security_group_to_array_of_hashes(db_security_group.ec2_security_groups),
:ip_ranges => ip_ranges_to_array_of_hashes(db_security_group.ip_ranges),
}
end

Expand All @@ -49,7 +51,7 @@ def exists?
def create
Puppet.info("Starting DB instance #{name}")
config = {
:db_security_group_name => resource[:name],
:db_security_group_name => resource[:name],
:db_security_group_description => resource[:db_security_group_description],
}

Expand All @@ -64,7 +66,7 @@ def destroy
config = {
db_security_group_name: name,
}
rds.delete_db_instance(config)
rds.delete_db_security_group(config)
@property_hash[:ensure] = :absent
end

Expand All @@ -79,4 +81,13 @@ def self.ec2_security_group_to_array_of_hashes(ec2_security_groups)
end
end

def self.ip_ranges_to_array_of_hashes(ip_ranges)
ip_ranges.collect do |group|
{
:status => group.status,
:ip_range => group.cidrip,
}
end
end

end
56 changes: 36 additions & 20 deletions lib/puppet/provider/rds_instance/v2.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
require_relative '../../../puppet_x/puppetlabs/aws.rb'
require "base64"

Puppet::Type.type(:rds_instance).provide(:v2, :parent => PuppetX::Puppetlabs::Aws) do
confine feature: :aws
Expand All @@ -11,18 +10,20 @@ def self.instances
instances = []
rds_client(region).describe_db_instances.each do |response|
response.data.db_instances.each do |db|
unless db.db_instance_status =~ /^deleted$|^deleting$/
hash = db_instance_to_hash(region, db)
instances << new(hash) if hash[:name]
end
end
end
instances
end.flatten
end

read_only(:auto_minor_version_upgrade,
:backup_retention_period, :character_set_name, :creation_date_time,
:iops, :master_username,
:multi_az, :backup_window, :vpc_id, :license_model)
:backup_retention_period, :character_set_name, :creation_date_time,
:iops, :master_username,
:multi_az, :backup_window, :vpc_id, :license_model)

def self.prefetch(resources)
instances.each do |prov|
Expand All @@ -33,10 +34,23 @@ def self.prefetch(resources)
end

def self.db_instance_to_hash(region, instance)
tags = rds_client(region).list_tags_for_resource(resource_name: get_arn_for_instance(region,instance.db_instance_identifier))

if instance.respond_to?('skip_final_snapshot')
skip_final_snapshot = instance.skip_final_snapshot
else
skip_final_snapshot = true
end
if instance.respond_to?('final_db_snapshot_identifier')
final_db_snapshot_identifier = instance.final_db_snapshot_identifier
else
final_db_snapshot_identifier = ''
end
if instance.respond_to?('backup_retention_period')
backup_retention_period = instance.backup_retention_period
else
backup_retention_period = 0
end
config = {
ensure: :present,
ensure: :present,
name: instance.db_instance_identifier,
region: region,
engine: instance.engine,
Expand All @@ -48,29 +62,30 @@ def self.db_instance_to_hash(region, instance)
license_model: instance.license_model,
multi_az: instance.multi_az,
iops: instance.iops,
backup_retention_period: backup_retention_period,
skip_final_snapshot: skip_final_snapshot,
final_db_snapshot_identifier: final_db_snapshot_identifier,
db_security_groups: instance.db_security_groups.collect(&:db_security_group_name),
}
if instance.respond_to?('endpoint')
config[:endpoint] = instance.endpoint.address
config[:port] = instance.endpoint.port
end
config
end

def exists?
dest_region = resource[:region] if resource
Puppet.info("Checking if instance #{name} exists in region #{dest_region || region}")
[:present, :creating, :available].include? @property_hash[:ensure]
[:present, :creating, :available, :backing_up].include? @property_hash[:ensure]
end

def create
Puppet.info("Starting DB instance #{name}")
groups = resource[:security_groups]
groups = [groups] unless groups.is_a?(Array)
groups = groups.reject(&:nil?)

config = {
db_instance_identifier: resource[:name],
db_name: resource[:db_name],
db_instance_class: resource[:db_instance_class],
db_instance_identifier: resource[:db_name],
db_instance_class: resource[:db_instance_class],
vpc_security_group_ids: groups,
engine: resource[:engine],
engine_version: resource[:engine_version],
license_model: resource[:license_model],
Expand All @@ -81,21 +96,22 @@ def create
master_username: resource[:master_username],
master_user_password: resource[:master_user_password],
db_subnet_group_name: resource[:db_subnet_group_name],
db_security_groups: resource[:db_security_groups],
}

response = rds_client(resource[:region]).create_db_instance(config)
rds_client(resource[:region]).create_db_instance(config)

@property_hash[:ensure] = :present
end

def destroy
Puppet.info("Deleting instance #{name} in region #{resource[:region]}")
Puppet.info("Deleting database #{name} in region #{resource[:region]}")
rds = rds_client(resource[:region])
Puppet.info("Skip Final Snapshot: #{resource[:skip_final_snapshot]}")
config = {
db_instance_identifier: resource[:name],
skip_final_snapshot: resource[:skip_final_snapshot],
final_db_snapshot_identifier: resource[:final_db_snapshot_identifier],
db_instance_identifier: name,
skip_final_snapshot: skip_final_snapshot,
final_db_snapshot_identifier: final_db_snapshot_identifier,
}
rds.delete_db_instance(config)
@property_hash[:ensure] = :absent
Expand Down
13 changes: 12 additions & 1 deletion lib/puppet/type/rds_db_securitygroup.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
desc 'the name of the DB Security Group (also known as the db_security_group_name)'
end

newproperty(:db_security_group_description) do
newparam(:db_security_group_description) do
desc 'the description of a DB Security group'
validate do |value|
fail 'db_security_group_description should not be blank' if value == ''
Expand All @@ -22,4 +22,15 @@
desc 'the EC2 Security Groups assigned to this RDS DB security group'
end

newproperty(:region) do
desc 'the region in which to create the db_securitygroup'
validate do |value|
fail 'region should not contain spaces' if value =~ /\s/
end
end

newproperty(:ip_ranges, :array_matching => :all) do
desc 'the IP ranges allowed to access the RDS instance'
end

end
Loading

0 comments on commit 7b26866

Please sign in to comment.