Skip to content

Commit 653f9eb

Browse files
author
jtimberman
committed
Add cookbook for managing DNS resource records with dynect
1 parent c8f157e commit 653f9eb

File tree

8 files changed

+388
-0
lines changed

8 files changed

+388
-0
lines changed

‎dynect/README.md‎

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
DESCRIPTION
2+
===========
3+
4+
Automatically configures system DNS using Dyn's API.
5+
6+
REQUIREMENTS
7+
============
8+
9+
Chef 0.8+.
10+
11+
A Dynect account.
12+
13+
The `dynect_rest` gem. The `dynect::default` recipe installs this gem from gemcutter.
14+
15+
Works on any platform Chef runs on that can install gems from Rubygems.org.
16+
17+
ATTRIBUTES
18+
==========
19+
20+
The following attributes need to be set either in a role or on a node directly, they are not set at the cookbook level:
21+
22+
* dynect.customer - Customer ID
23+
* dynect.username - Username
24+
* dynect.password - Password
25+
* dynect.zone - Zone
26+
* dynect.domain - Domain
27+
28+
Example JSON:
29+
30+
{
31+
"dynect":{
32+
"customer": "CUSTOMER",
33+
"username": "USERNAME",
34+
"password": "PASSWORD",
35+
"zone": "ZONE",
36+
"domain": "DOMAIN"
37+
}
38+
}
39+
40+
EC2 specific attributes:
41+
42+
* dynect.ec2.type - type of system, web, db, etc. Default is 'ec2'.
43+
* dynect.ec2.env - logical application environment the system is in. Default is 'prod'.
44+
45+
RESOURCES
46+
=========
47+
48+
rr
49+
--
50+
51+
DNS Resource Record.
52+
53+
Actions:
54+
55+
Applies to the DNS record being managed.
56+
57+
*`:create`
58+
*`:replace`
59+
*`:update`
60+
*`:delete`
61+
62+
Attribute Parameters:
63+
64+
*`record_type` - DNS record type (CNAME, A, etc)
65+
*`rdata` - record data, see the Dyn API documentation.
66+
*`ttl` - time to live in seconds
67+
*`fqdn` - fully qualified domain name
68+
*`username` - dyn username
69+
*`password` - dyn password
70+
*`customer` - dyn customer id
71+
*`zone` - DNS zone
72+
73+
None of the parameters have default values.
74+
75+
Example:
76+
77+
dynect_rr "webprod" do
78+
record_type "A"
79+
rdata({"address" => "10.1.1.10"})
80+
fqdn "webprod.#{node.dynect.domain}"
81+
customer node[:dynect][:customer]
82+
username node[:dynect][:username]
83+
password node[:dynect][:password]
84+
zone node[:dynect][:zone]
85+
end
86+
87+
RECIPES
88+
=======
89+
90+
This cookbook provides the following recipes.
91+
92+
default
93+
-------
94+
95+
The default recipe installs Adam Jacob's `dynect_rest` gem during the Chef run's compile time to ensure it is available in the same run as utilizing the `dynect_rr` resource/provider.
96+
97+
ec2
98+
---
99+
100+
**Only use this recipe on Amazon AWS EC2 hosts!**
101+
102+
The `dynect::ec2` recipe provides an example of working with the Dyn API with EC2 instances. It creates CNAME records based on the EC2 instance ID (`node.ec2.instance_id`), and a constructed hostname from the dynect.ec2 attributes.
103+
104+
The recipe also edits resolv.conf to search compute-1.internal and the dynect.domain and use dynect.domain as the default domain, and it will set the nodes hostname per the DNS settings.
105+
106+
a_record
107+
--------
108+
109+
The `dynect::a_record` recipe will create an `A` record for the node using the detected hostname and IP address from `ohai`.
110+
111+
FURTHER READING
112+
===============
113+
114+
Information on the Dynect API:
115+
116+
*[PDF](http://cdn.dyndns.com/pdf/Dynect-API.pdf)
117+
118+
Dynect REST Ruby Library:
119+
120+
*[Gem](http://rubygems.org/gems/dynect_rest)
121+
*[Code](http://github.com/adamhjk/dynect_rest)
122+
123+
LICENSE AND AUTHOR
124+
==================
125+
126+
- Author: Adam Jacob (<[email protected]>)
127+
- Copyright: 2010, Opscode, Inc.
128+
129+
Licensed under the Apache License, Version 2.0 (the "License");
130+
you may not use this file except in compliance with the License.
131+
You may obtain a copy of the License at
132+
133+
http://www.apache.org/licenses/LICENSE-2.0
134+
135+
Unless required by applicable law or agreed to in writing, software
136+
distributed under the License is distributed on an "AS IS" BASIS,
137+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138+
See the License for the specific language governing permissions and
139+
limitations under the License.

‎dynect/attributes/default.rb‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#
2+
# Cookbook Name:: dynect
3+
# Attribute:: default
4+
#
5+
# Copyright:: 2010, Opscode, Inc <[email protected]>
6+
#
7+
# Licensed under the Apache License, Version 2.0 (the "License");
8+
# you may not use this file except in compliance with the License.
9+
# You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing, software
14+
# distributed under the License is distributed on an "AS IS" BASIS,
15+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
# See the License for the specific language governing permissions and
17+
# limitations under the License.
18+
#
19+
#
20+
21+
# Set these attributes in your role or node.
22+
# set[:dynect][:customer] = ""
23+
# set[:dynect][:username] = ""
24+
# set[:dynect][:password] = ""
25+
# set[:dynect][:zone] = ""
26+
# set[:dynect][:domain] = ""
27+
#
28+
# set[:dynect][:ec2][:type] = "ec2"
29+
# set[:dynect][:ec2][:env] = "prod"

‎dynect/metadata.json‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"maintainer_email": "[email protected]",
3+
"attributes":{
4+
},
5+
"conflicting":{
6+
},
7+
"dependencies":{
8+
},
9+
"providing":{
10+
},
11+
"recipes":{
12+
},
13+
"replacing":{
14+
},
15+
"platforms":{
16+
},
17+
"license": "Apache 2.0",
18+
"version": "0.2.0",
19+
"groupings":{
20+
},
21+
"long_description": "DESCRIPTION\n===========\n\nAutomatically configures system DNS using Dyn's API.\n\nREQUIREMENTS\n============\n\nChef 0.8+.\n\nA Dynect account.\n\nThe `dynect_rest` gem. The `dynect::default` recipe installs this gem from gemcutter.\n\nWorks on any platform Chef runs on that can install gems from Rubygems.org.\n\nATTRIBUTES\n==========\n\nThe following attributes need to be set either in a role or on a node directly, they are not set at the cookbook level:\n\n* dynect.customer - Customer ID\n* dynect.username - Username\n* dynect.password - Password\n* dynect.zone - Zone\n* dynect.domain - Domain\n\nExample JSON:\n\n{\n \"dynect\":{\n \"customer\": \"CUSTOMER\",\n \"username\": \"USERNAME\",\n \"password\": \"PASSWORD\",\n \"zone\": \"ZONE\",\n \"domain\": \"DOMAIN\"\n }\n }\n\nEC2 specific attributes:\n\n* dynect.ec2.type - type of system, web, db, etc. Default is 'ec2'.\n* dynect.ec2.env - logical application environment the system is in. Default is 'prod'.\n\nRESOURCES\n=========\n\nrr\n--\n\nDNS Resource Record.\n\nActions:\n\nApplies to the DNS record being managed.\n\n* `:create`\n* `:replace`\n* `:update`\n* `:delete`\n\nAttribute Parameters:\n\n* `record_type` - DNS record type (CNAME, A, etc)\n* `rdata` - record data, see the Dyn API documentation.\n* `ttl` - time to live in seconds\n* `fqdn` - fully qualified domain name\n* `username` - dyn username\n* `password` - dyn password\n* `customer` - dyn customer id\n* `zone` - DNS zone\n\nNone of the parameters have default values.\n\nExample:\n\n dynect_rr \"webprod\" do\n record_type \"A\"\n rdata({\"address\" => \"10.1.1.10\"})\n fqdn \"webprod.#{node.dynect.domain}\"\n customer node[:dynect][:customer]\n username node[:dynect][:username]\n password node[:dynect][:password]\n zone node[:dynect][:zone]\n end\n\nRECIPES\n=======\n\nThis cookbook provides the following recipes.\n\ndefault\n-------\n\nThe default recipe installs Adam Jacob's `dynect_rest` gem during the Chef run's compile time to ensure it is available in the same run as utilizing the `dynect_rr` resource/provider.\n\nec2\n---\n\n**Only use this recipe on Amazon AWS EC2 hosts!**\n\nThe `dynect::ec2` recipe provides an example of working with the Dyn API with EC2 instances. It creates CNAME records based on the EC2 instance ID (`node.ec2.instance_id`), and a constructed hostname from the dynect.ec2 attributes.\n\nThe recipe also edits resolv.conf to search compute-1.internal and the dynect.domain and use dynect.domain as the default domain, and it will set the nodes hostname per the DNS settings.\n\na_record\n--------\n\nThe `dynect::a_record` recipe will create an `A` record for the node using the detected hostname and IP address from `ohai`.\n\nFURTHER READING\n===============\n\nInformation on the Dynect API:\n\n* [PDF](http://cdn.dyndns.com/pdf/Dynect-API.pdf)\n\nDynect REST Ruby Library:\n\n* [Gem](http://rubygems.org/gems/dynect_rest)\n* [Code](http://github.com/adamhjk/dynect_rest)\n\nLICENSE AND AUTHOR\n==================\n\n- Author: Adam Jacob (<[email protected]>)\n- Copyright: 2010, Opscode, Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
22+
"recommendations":{
23+
},
24+
"name": "dynect",
25+
"maintainer": "Opscode, Inc.",
26+
"description": "Installs/Configures dynect",
27+
"suggestions":{
28+
}
29+
}

‎dynect/metadata.rb‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
maintainer"Opscode, Inc."
2+
maintainer_email"[email protected]"
3+
license"Apache 2.0"
4+
description"Installs/Configures dynect"
5+
long_descriptionIO.read(File.join(File.dirname(__FILE__),'README.md'))
6+
version"0.2"

‎dynect/providers/rr.rb‎

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
#
2+
# Cookbook Name:: dynect
3+
# Provider:: rr
4+
#
5+
# Copyright:: 2010, Opscode, Inc <[email protected]>
6+
#
7+
# Licensed under the Apache License, Version 2.0 (the "License");
8+
# you may not use this file except in compliance with the License.
9+
# You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing, software
14+
# distributed under the License is distributed on an "AS IS" BASIS,
15+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
# See the License for the specific language governing permissions and
17+
# limitations under the License.
18+
#
19+
20+
defload_current_resource
21+
require'dynect_rest'
22+
23+
@dyn=DynectRest.new(@new_resource.customer,@new_resource.username,@new_resource.password,@new_resource.zone)
24+
25+
@current_resource=Chef::Resource::DynectRr.new(@new_resource.name)
26+
@current_resource.record_type(@new_resource.record_type)
27+
@current_resource.customer(@new_resource.customer)
28+
@current_resource.username(@new_resource.username)
29+
@current_resource.password(@new_resource.password)
30+
@current_resource.zone(@new_resource.zone)
31+
32+
@rr=nil
33+
34+
begin
35+
@rr=DynectRest::Resource.new(@dyn,@new_resource.record_type,@new_resource.zone).get(@new_resource.fqdn)
36+
@current_resource.fqdn(@rr.fqdn)
37+
@current_resource.ttl(@rr.ttl)
38+
@current_resource.zone(@rr.zone)
39+
@current_resource.rdata(@rr.rdata)
40+
rescueDynectRest::Exceptions::RequestFailed=>e
41+
Chef::Log.debug("Cannot find resource #{@new_resource} at Dynect")
42+
end
43+
end
44+
45+
defaction_create
46+
unless@rr
47+
rr=DynectRest::Resource.new(@dyn,@new_resource.record_type,@new_resource.zone)
48+
rr.fqdn(@new_resource.fqdn)
49+
rr.ttl(@new_resource.ttl)if@new_resource.ttl
50+
rr.rdata=@new_resource.rdata
51+
rr.save
52+
@dyn.publish
53+
Chef::Log.info("Added #{@new_resource} to dynect")
54+
@updated=true
55+
end
56+
end
57+
58+
defaction_update
59+
if@rr
60+
changed=false
61+
if(@new_resource.ttl && @rr.ttl != @new_resource.ttl)
62+
@rr.ttl(@new_resource.ttl)
63+
Chef::Log.info("Changing #{@new_resource} ttl from #{@rr.ttl} to #{@new_resource.ttl}")
64+
changed=true
65+
end
66+
if@rr.rdata != @new_resource.rdata
67+
Chef::Log.info("Changing #{@new_resource} rdata from #{@rr.rdata.inspect} to #{@new_resource.rdata.inspect}")
68+
@rr.rdata=@new_resource.rdata
69+
changed=true
70+
end
71+
ifchanged
72+
@rr.save
73+
@dyn.publish
74+
Chef::Log.info("Updated #{@new_resource} at dynect")
75+
@updated=true
76+
end
77+
else
78+
action_create
79+
end
80+
end
81+
82+
defaction_replace
83+
rr=DynectRest::Resource.new(@dyn,@new_resource.record_type,@new_resource.zone)
84+
rr.fqdn(@new_resource.fqdn)
85+
rr.ttl(@new_resource.ttl)if@new_resource.ttl
86+
rr.rdata=@new_resource.rdata
87+
rr.save(true)
88+
@dyn.publish
89+
Chef::Log.info("Replaced #{@new_resource} at dynect")
90+
@updated=true
91+
end
92+
93+
defaction_delete
94+
if@rr
95+
@rr.delete
96+
Chef::Log.info("Deleted #{@new_resource} from dynect")
97+
@updated=true
98+
end
99+
end

‎dynect/recipes/a_record.rb‎

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#
2+
# Cookbook Name:: dynect
3+
# Recipe:: a_record
4+
#
5+
# Copyright:: 2010, Opscode, Inc <[email protected]>
6+
#
7+
# Licensed under the Apache License, Version 2.0 (the "License");
8+
# you may not use this file except in compliance with the License.
9+
# You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing, software
14+
# distributed under the License is distributed on an "AS IS" BASIS,
15+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
# See the License for the specific language governing permissions and
17+
# limitations under the License.
18+
#
19+
20+
include_recipe'dynect'
21+
22+
dynect_rrnode[:hostname]do
23+
record_type"A"
24+
rdata({"address"=>node[:ipaddress]})
25+
fqdn"#{node[:hostname]}.#{node[:dynect][:domain]}"
26+
customernode[:dynect][:customer]
27+
usernamenode[:dynect][:username]
28+
passwordnode[:dynect][:password]
29+
zonenode[:dynect][:zone]
30+
action:update
31+
end

‎dynect/recipes/default.rb‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#
2+
# Cookbook Name:: dynect
3+
# Recipe:: default
4+
#
5+
# Copyright:: 2010, Opscode, Inc <[email protected]>
6+
#
7+
# Licensed under the Apache License, Version 2.0 (the "License");
8+
# you may not use this file except in compliance with the License.
9+
# You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing, software
14+
# distributed under the License is distributed on an "AS IS" BASIS,
15+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
# See the License for the specific language governing permissions and
17+
# limitations under the License.
18+
#
19+
20+
# Install dynect in advance
21+
r=gem_package"dynect_rest"do
22+
action:nothing
23+
end
24+
r.run_action(:upgrade)
25+
Gem.clear_paths

‎dynect/resources/rr.rb‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#
2+
# Cookbook Name:: dynect
3+
# Resource:: rr
4+
#
5+
# Author:: Adam Jacob <[email protected]>
6+
# Copyright:: 2010, Opscode, Inc <[email protected]>
7+
#
8+
# Licensed under the Apache License, Version 2.0 (the "License");
9+
# you may not use this file except in compliance with the License.
10+
# You may obtain a copy of the License at
11+
#
12+
# http://www.apache.org/licenses/LICENSE-2.0
13+
#
14+
# Unless required by applicable law or agreed to in writing, software
15+
# distributed under the License is distributed on an "AS IS" BASIS,
16+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17+
# See the License for the specific language governing permissions and
18+
# limitations under the License.
19+
#
20+
21+
actions:delete,:create,:update,:replace
22+
23+
attribute:record_type,:kind_of=>String
24+
attribute:rdata,:kind_of=>Hash
25+
attribute:ttl,:kind_of=>Integer
26+
attribute:fqdn,:kind_of=>String
27+
attribute:username,:kind_of=>String
28+
attribute:password,:kind_of=>String
29+
attribute:customer,:kind_of=>String
30+
attribute:zone,:kind_of=>String

0 commit comments

Comments
(0)