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

Commit 0bded84

Browse files
petemsgarethr
authored andcommitted
(CLOUD-295) Adds support for RDS related resources
1 parent f64d467 commit 0bded84

File tree

25 files changed

+1344
-30
lines changed

25 files changed

+1344
-30
lines changed

README.md

Lines changed: 160 additions & 28 deletions
Large diffs are not rendered by default.
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# RDS
2+
3+
[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.
4+
5+
## How
6+
7+
This example creates a security group to allow access to a Postgres RDS instance, then creates that RDS instance with the security group assigned.
8+
9+
puppet apply rds_security.pp
10+
11+
Unfortunately, it's not possible to assign the EC2 group and the allowed IPs to the `db_securitygroup` through the API, so you have to do this manually though the console for now:
12+
13+
## Add the Security Group We Made with Puppet**
14+
![Add EC2 Security Group](./images/add-rds-securitygroup.png?raw=true)
15+
16+
## Add an IP to allow access to the RDS instance
17+
**Note: Enter `0.0.0.0/32` to allow all IPs**
18+
![Add IP to allow](./images/add-ip-to-allow.png?raw=true)
19+
20+
## It should look something like this
21+
![Final Look](./images/final-screen.png?raw=true)
22+
23+
You can now check your security group is correct by using Puppet resource commands:
24+
25+
puppet resource rds_db_securitygroup rds-postgres-db_securitygroup
26+
27+
It should return something like this:
28+
29+
~~~
30+
rds_db_securitygroup { 'rds-postgres-db_securitygroup':
31+
ensure => 'present',
32+
ec2_security_groups => [{'ec2_security_group_id' => 'sg-83fb3z5', 'ec2_security_group_name' => 'rds-postgres-group', 'ec2_security_group_owner_id' => '4822239859', 'status' => 'authorized'}],
33+
ip_ranges => [{'ip_range' => '0.0.0.0/32', 'status' => 'authorized'}],
34+
owner_id => '239838031',
35+
region => 'us-west-2',
36+
}
37+
~~~
38+
39+
When this is complete, create the RDS Postgres instance:
40+
41+
puppet apply rds_postgres.pp
42+
43+
This can take a while to setup, but when it's complete, you should be able to access it:
44+
45+
~~~
46+
psql -d postgresql -h puppetlabs-aws-postgres.cwgutxb9fmx.us-west-2.rds.amazonaws.com -U root
47+
48+
Password for user root: pullZstringz345
49+
psql (9.4.0, server 9.3.5)
50+
SSL connection (protocol: TLSv1.2, cipher: DHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
51+
Type "help" for help.
52+
53+
postgresql=> exit
54+
~~~
51.7 KB
Loading
249 KB
Loading
96 KB
Loading
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
rds_instance { 'puppetlabs-aws-postgres':
2+
ensure => present,
3+
allocated_storage => '5',
4+
db_instance_class => 'db.m3.medium',
5+
db_name => 'postgresql',
6+
engine => 'postgres',
7+
license_model => 'postgresql-license',
8+
db_security_groups => 'rds-postgres-db_securitygroup',
9+
master_username => 'root',
10+
master_user_password=> 'pullZstringz345',
11+
region => 'us-west-2',
12+
skip_final_snapshot => 'true',
13+
storage_type => 'gp2',
14+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
ec2_securitygroup { 'rds-postgres-group':
2+
ensure => present,
3+
region => 'us-west-2',
4+
description => 'Group for Allowing access to Postgres (Port 5432)',
5+
ingress => [{
6+
security_group => 'rds-postgres-group',
7+
},{
8+
protocol => 'tcp',
9+
port => 5432,
10+
cidr => '0.0.0.0/0',
11+
}]
12+
}
13+
14+
rds_db_securitygroup { 'rds-postgres-db_securitygroup':
15+
ensure => present,
16+
region => 'us-west-2',
17+
description => 'An RDS Security group to allow Postgres',
18+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
require_relative '../../../puppet_x/puppetlabs/aws.rb'
2+
3+
Puppet::Type.type(:rds_db_parameter_group).provide(:v2, :parent => PuppetX::Puppetlabs::Aws) do
4+
confine feature: :aws
5+
6+
mk_resource_methods
7+
8+
def self.instances
9+
regions.collect do |region|
10+
instances = []
11+
rds_client(region).describe_db_parameter_groups.each do |response|
12+
response.data.db_parameter_groups.each do |db_parameter_group|
13+
# There's always a default class
14+
hash = db_parameter_group_to_hash(region, db_parameter_group)
15+
instances << new(hash) if hash[:name]
16+
end
17+
end
18+
instances
19+
end.flatten
20+
end
21+
22+
def self.db_parameter_group_to_hash(region, db_parameter_group)
23+
{
24+
:ensure => :present,
25+
:name => db_parameter_group.db_parameter_group_name,
26+
:description => db_parameter_group.description,
27+
:family => db_parameter_group.db_parameter_group_family,
28+
:region => region,
29+
}
30+
end
31+
32+
def exists?
33+
Puppet.info("Checking if DB Parameter Group #{name} exists")
34+
[:present, :creating, :available].include? @property_hash[:ensure]
35+
end
36+
37+
end
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
require_relative '../../../puppet_x/puppetlabs/aws.rb'
2+
3+
Puppet::Type.type(:rds_db_securitygroup).provide(:v2, :parent => PuppetX::Puppetlabs::Aws) do
4+
confine feature: :aws
5+
6+
mk_resource_methods
7+
8+
def self.instances
9+
regions.collect do |region|
10+
instances = []
11+
rds_client(region).describe_db_security_groups.each do |response|
12+
response.data.db_security_groups.each do |db_security_group|
13+
# There's always a default class
14+
unless db_security_group.db_security_group_name =~ /^default$/
15+
hash = db_security_group_to_hash(region, db_security_group)
16+
instances << new(hash) if hash[:name]
17+
end
18+
end
19+
end
20+
instances
21+
end.flatten
22+
end
23+
24+
def self.prefetch(resources)
25+
instances.each do |prov|
26+
if resource = resources[prov.name] # rubocop:disable Lint/AssignmentInCondition
27+
resource.provider = prov if resource[:region] == prov.region
28+
end
29+
end
30+
end
31+
32+
read_only(:region, :description)
33+
34+
def self.db_security_group_to_hash(region, db_security_group)
35+
{
36+
:ensure => :present,
37+
:region => region,
38+
:name => db_security_group.db_security_group_name,
39+
:description => db_security_group.db_security_group_description,
40+
:owner_id => db_security_group.owner_id,
41+
:security_groups => ec2_security_group_to_array_of_hashes(db_security_group.ec2_security_groups),
42+
:ip_ranges => ip_ranges_to_array_of_hashes(db_security_group.ip_ranges),
43+
}
44+
end
45+
46+
def exists?
47+
Puppet.info("Checking if DB Security Group #{name} exists")
48+
[:present, :creating, :available].include? @property_hash[:ensure]
49+
end
50+
51+
def create
52+
Puppet.info("Creating DB Security Group #{name}")
53+
config = {
54+
:db_security_group_name => resource[:name],
55+
:db_security_group_description => resource[:description],
56+
}
57+
58+
rds_client(resource[:region]).create_db_security_group(config)
59+
60+
@property_hash[:ensure] = :present
61+
end
62+
63+
def destroy
64+
Puppet.info("Deleting DB Security Group #{name} in region #{resource[:region]}")
65+
rds = rds_client(resource[:region])
66+
config = {
67+
db_security_group_name: name,
68+
}
69+
rds.delete_db_security_group(config)
70+
@property_hash[:ensure] = :absent
71+
end
72+
73+
def self.ec2_security_group_to_array_of_hashes(ec2_security_groups)
74+
ec2_security_groups.collect do |group|
75+
{
76+
:status => group.status,
77+
:ec2_security_group_name => group.ec2_security_group_name,
78+
:ec2_security_group_owner_id => group.ec2_security_group_owner_id,
79+
:ec2_security_group_id => group.ec2_security_group_id,
80+
}
81+
end
82+
end
83+
84+
def self.ip_ranges_to_array_of_hashes(ip_ranges)
85+
ip_ranges.collect do |group|
86+
{
87+
:status => group.status,
88+
:ip_range => group.cidrip,
89+
}
90+
end
91+
end
92+
93+
end
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
require_relative '../../../puppet_x/puppetlabs/aws.rb'
2+
3+
Puppet::Type.type(:rds_instance).provide(:v2, :parent => PuppetX::Puppetlabs::Aws) do
4+
confine feature: :aws
5+
6+
mk_resource_methods
7+
8+
def self.instances
9+
regions.collect do |region|
10+
instances = []
11+
rds_client(region).describe_db_instances.each do |response|
12+
response.data.db_instances.each do |db|
13+
unless db.db_instance_status =~ /^deleted$|^deleting$/
14+
hash = db_instance_to_hash(region, db)
15+
instances << new(hash) if hash[:name]
16+
end
17+
end
18+
end
19+
instances
20+
end.flatten
21+
end
22+
23+
read_only(:iops, :master_username, :multi_az, :license_model,
24+
:db_name, :region, :db_instance_class, :availability_zone,
25+
:engine, :engine_version, :allocated_storage, :storage_type,
26+
:db_security_groups, :skip_final_snapshot, :final_db_snapshot_identifier,
27+
:db_parameter_group)
28+
29+
def self.prefetch(resources)
30+
instances.each do |prov|
31+
if resource = resources[prov.name] # rubocop:disable Lint/AssignmentInCondition
32+
resource.provider = prov if resource[:region] == prov.region
33+
end
34+
end
35+
end
36+
37+
def self.db_instance_to_hash(region, instance)
38+
config = {
39+
ensure: :present,
40+
name: instance.db_instance_identifier,
41+
region: region,
42+
engine: instance.engine,
43+
engine_version: instance.engine_version,
44+
db_instance_class: instance.db_instance_class,
45+
master_username: instance.master_username,
46+
db_name: instance.db_name,
47+
allocated_storage: instance.allocated_storage,
48+
storage_type: instance.storage_type,
49+
license_model: instance.license_model,
50+
multi_az: instance.multi_az,
51+
iops: instance.iops,
52+
db_parameter_group: instance.db_parameter_groups.collect(&:db_parameter_group_name).first,
53+
db_security_groups: instance.db_security_groups.collect(&:db_security_group_name),
54+
}
55+
if instance.respond_to?('skip_final_snapshot')
56+
config[:skip_final_snapshot] = instance.skip_final_snapshot
57+
end
58+
if instance.respond_to?('final_db_snapshot_identifier')
59+
config[:final_db_snapshot_identifier] = instance.final_db_snapshot_identifier
60+
end
61+
if instance.respond_to?('backup_retention_period')
62+
config[:backup_retention_period] = instance.backup_retention_period
63+
end
64+
if instance.respond_to?('endpoint') && !instance.endpoint.nil?
65+
config[:endpoint] = instance.endpoint.address
66+
config[:port] = instance.endpoint.port
67+
end
68+
config
69+
end
70+
71+
def exists?
72+
dest_region = resource[:region] if resource
73+
Puppet.info("Checking if instance #{name} exists in region #{dest_region || region}")
74+
[:present, :creating, :available, :backing_up].include? @property_hash[:ensure]
75+
end
76+
77+
def create
78+
Puppet.info("Starting DB instance #{name}")
79+
config = {
80+
db_instance_identifier: resource[:name],
81+
db_name: resource[:db_name],
82+
db_instance_class: resource[:db_instance_class],
83+
engine: resource[:engine],
84+
engine_version: resource[:engine_version],
85+
license_model: resource[:license_model],
86+
storage_type: resource[:storage_type],
87+
multi_az: resource[:multi_az].to_s,
88+
allocated_storage: resource[:allocated_storage],
89+
iops: resource[:iops],
90+
master_username: resource[:master_username],
91+
master_user_password: resource[:master_user_password],
92+
subnet_group_name: resource[:db_subnet],
93+
db_security_groups: resource[:db_security_groups],
94+
db_parameter_group_name: resource[:db_parameter_group],
95+
}
96+
97+
rds_client(resource[:region]).create_db_instance(config)
98+
99+
@property_hash[:ensure] = :present
100+
end
101+
102+
def destroy
103+
Puppet.info("Deleting database #{name} in region #{resource[:region]}")
104+
rds = rds_client(resource[:region])
105+
Puppet.info("Skip Final Snapshot: #{resource[:skip_final_snapshot]}")
106+
config = {
107+
db_instance_identifier: name,
108+
skip_final_snapshot: resource[:skip_final_snapshot].to_s,
109+
final_db_snapshot_identifier: resource[:final_db_snapshot_identifier],
110+
}
111+
rds.delete_db_instance(config)
112+
@property_hash[:ensure] = :absent
113+
end
114+
115+
end

0 commit comments

Comments
 (0)