vominator 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +25 -0
- data/.rspec +5 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +116 -0
- data/Rakefile +12 -0
- data/bin/vominate +12 -0
- data/circle.yml +5 -0
- data/lib/ec2.rb +12 -0
- data/lib/ec2/instances.rb +362 -0
- data/lib/ec2/security_groups.rb +314 -0
- data/lib/ec2/ssm.rb +81 -0
- data/lib/vominator/aws.rb +15 -0
- data/lib/vominator/constants.rb +53 -0
- data/lib/vominator/ec2.rb +308 -0
- data/lib/vominator/instances.rb +34 -0
- data/lib/vominator/route53.rb +125 -0
- data/lib/vominator/security_groups.rb +26 -0
- data/lib/vominator/ssm.rb +57 -0
- data/lib/vominator/version.rb +3 -0
- data/lib/vominator/vominator.rb +74 -0
- data/lib/vominator/vpc.rb +82 -0
- data/lib/vpc.rb +8 -0
- data/lib/vpc/create.rb +188 -0
- data/spec/lib/instances_spec.rb +2 -0
- data/spec/lib/vominator/aws_spec.rb +6 -0
- data/spec/lib/vominator/ec2_spec.rb +783 -0
- data/spec/lib/vominator/instances_spec.rb +96 -0
- data/spec/lib/vominator/route53_spec.rb +64 -0
- data/spec/lib/vominator/ssm_spec.rb +95 -0
- data/spec/lib/vominator/vominator_spec.rb +209 -0
- data/spec/spec_helper.rb +103 -0
- data/spec/support/matchers/exit_with_code.rb +24 -0
- data/test/puke/cloud-configs/.gitkeep +0 -0
- data/test/puke/cloud-configs/cloud-config-example.erb +63 -0
- data/test/puke/config.yaml +16 -0
- data/test/puke/products/sample-api/instances.yaml +37 -0
- data/test/puke/products/sample-api/security_groups.yaml +19 -0
- data/test/vominator.yaml +7 -0
- data/vominator.gemspec +34 -0
- metadata +259 -0
@@ -0,0 +1,308 @@
|
|
1
|
+
require 'aws-sdk'
|
2
|
+
require 'base64'
|
3
|
+
require_relative 'constants'
|
4
|
+
|
5
|
+
module Vominator
|
6
|
+
class EC2
|
7
|
+
def self.get_virt_type(instance_type)
|
8
|
+
begin
|
9
|
+
return EC2_INSTANCE_METADATA[instance_type.to_sym][:virtualization_type]
|
10
|
+
rescue NoMethodError
|
11
|
+
raise ArgumentError, 'You must specify a valid instance type'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.get_ephemeral_dev_count(instance_type)
|
16
|
+
return EC2_INSTANCE_METADATA[instance_type.to_sym][:ephemeral_devices]
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.get_instances(resource)
|
20
|
+
instances = Hash.new
|
21
|
+
resource.instances.each do |instance|
|
22
|
+
instances[instance.private_ip_address] = {:instance_id => instance.id, :security_groups => instance.security_groups.map { |sg| sg.group_name}}
|
23
|
+
end
|
24
|
+
return instances
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.get_instance(resource, instance_id)
|
28
|
+
return resource.instances(filters: [{name: 'instance-id', values: [instance_id]}]).first
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.get_security_group_name_ids_hash(resource, vpc_id)
|
32
|
+
security_groups = Hash.new
|
33
|
+
resource.vpcs(filters: [{name: 'vpc-id', values: [vpc_id]}]).first.security_groups.each do |security_group|
|
34
|
+
security_groups[security_group.group_name] = security_group.id
|
35
|
+
end
|
36
|
+
return security_groups
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.get_subnets(resource, vpc_id)
|
40
|
+
subnets = Hash.new
|
41
|
+
resource.vpcs(filters: [{name: 'vpc-id', values: [vpc_id]}]).first.subnets.each do |subnet|
|
42
|
+
subnets[subnet.cidr_block] = subnet
|
43
|
+
end
|
44
|
+
return subnets
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.get_ami(puke_config, instance_type, family)
|
48
|
+
if Vominator::EC2.get_virt_type(instance_type) == 'hvm'
|
49
|
+
ami = puke_config['linux_hvm_base_image'] if family == 'linux'
|
50
|
+
ami = puke_config['windows_hvm_base_image'] if family == 'windows'
|
51
|
+
else
|
52
|
+
ami = puke_config['linux_paravirtual_base_image'] if family == 'linux'
|
53
|
+
ami = puke_config['windows_paravirtual_base_image'] if family == 'windows'
|
54
|
+
end
|
55
|
+
return ami
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.create_subnet(resource, subnet, az, vpc_id, route_table_id=nil)
|
59
|
+
subnet = resource.vpcs(filters: [{name: 'vpc-id', values: [vpc_id]}]).first.create_subnet(:cidr_block => subnet, :availability_zone => az)
|
60
|
+
if route_table_id
|
61
|
+
route_table = Vominator::EC2.get_route_table(resource,route_table_id)
|
62
|
+
route_table.associate_with_subnet(subnet_id: subnet.subnet_id)
|
63
|
+
end
|
64
|
+
return subnet
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.get_route_table(resource, route_table_id)
|
68
|
+
return resource.route_tables(filters: [{name: 'route-table-id', values: [route_table_id]}]).first
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.get_termination_protection(client, instance_id)
|
72
|
+
return client.describe_instance_attribute(:instance_id => instance_id, :attribute => 'disableApiTermination').disable_api_termination.value
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.set_termination_protection(client, instance_id, state)
|
76
|
+
client.modify_instance_attribute(:instance_id => instance_id, :disable_api_termination => { :value => state })
|
77
|
+
return client.describe_instance_attribute(:instance_id => instance_id, :attribute => 'disableApiTermination').disable_api_termination.value
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.get_instance_state(resource, instance_id)
|
81
|
+
instance = Vominator::EC2.get_instance(resource,instance_id)
|
82
|
+
|
83
|
+
return instance.state.name
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.set_instance_type(resource, instance_id, type, fqdn)
|
87
|
+
instance = Vominator::EC2.get_instance(resource,instance_id)
|
88
|
+
instance.stop
|
89
|
+
|
90
|
+
# TODO: Add a timed break?
|
91
|
+
sleep 5 until Vominator::EC2.get_instance_state(resource, instance_id) == 'stopped'
|
92
|
+
instance.modify_attribute(:attribute => 'instanceType', :value => type)
|
93
|
+
|
94
|
+
# TODO: We should add in a sleep (with a timed break) and verify the instance goes back to running
|
95
|
+
begin
|
96
|
+
instance.start
|
97
|
+
rescue Aws::EC2::Errors::Unsupported
|
98
|
+
LOGGER.warning("Disabling EBS Optimization for #{fqdn} because #{type} does not support this functionality")
|
99
|
+
instance.ebs_optimized = false
|
100
|
+
instance.start
|
101
|
+
end
|
102
|
+
return Vominator::EC2.get_instance(resource,instance_id).instance_type
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
def self.allocate_public_ip(client, domain='vpc')
|
107
|
+
return client.allocate_address(domain: domain)
|
108
|
+
end
|
109
|
+
|
110
|
+
def self.assign_public_ip(client, instance_id)
|
111
|
+
eip = client.allocate_address(:domain => 'vpc')
|
112
|
+
tries ||= 3
|
113
|
+
begin
|
114
|
+
sleep(0.25)
|
115
|
+
association = client.associate_address(:instance_id => instance_id, :allocation_id => eip.allocation_id)
|
116
|
+
rescue Aws::EC2::Errors::InvalidAllocationIDNotFound
|
117
|
+
retry unless (tries -= 1).zero?
|
118
|
+
end
|
119
|
+
|
120
|
+
if association
|
121
|
+
return eip.public_ip
|
122
|
+
else
|
123
|
+
return nil
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def self.remove_public_ip(client, instance_id)
|
128
|
+
allocation_id = client.describe_addresses(filters: [{name: 'instance-id', values: [instance_id]}]).first['addresses'].first['association_id']
|
129
|
+
if client.disassociate_address(:association_id => allocation_id)
|
130
|
+
return true
|
131
|
+
else
|
132
|
+
return false
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def self.set_ebs_optimized(resource, instance_id, state, fqdn)
|
137
|
+
instance = Vominator::EC2.get_instance(resource,instance_id)
|
138
|
+
instance.stop
|
139
|
+
|
140
|
+
# TODO: Add a timed break?
|
141
|
+
sleep 5 until Vominator::EC2.get_instance_state(resource, instance_id) == 'stopped'
|
142
|
+
|
143
|
+
# TODO: We should add in a sleep (with a timed break) and verify the instance goes back to running
|
144
|
+
begin
|
145
|
+
instance.modify_attribute(:ebs_optimized => {:value => state})
|
146
|
+
instance.start
|
147
|
+
return state
|
148
|
+
rescue Aws::EC2::Errors::Unsupported
|
149
|
+
LOGGER.error("#{fqdn} does not support setting EBS Optimization to #{state} as this is not supported for #{instance.instance_type}")
|
150
|
+
instance.modify_attribute(:ebs_optimized => {:value => false})
|
151
|
+
instance.start
|
152
|
+
return instance.ebs_optimized
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def self.set_source_dest_check(resource, instance_id, state)
|
157
|
+
instance = Vominator::EC2.get_instance(resource,instance_id)
|
158
|
+
if instance.modify_attribute(:source_dest_check => {:value => state})
|
159
|
+
return state
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def self.set_security_groups(resource, instance_id, security_groups, vpc_security_groups, append=true)
|
164
|
+
instance = Vominator::EC2.get_instance(resource,instance_id)
|
165
|
+
if append
|
166
|
+
security_groups = security_groups + instance.security_groups.map {|sg| sg[:group_name]}
|
167
|
+
end
|
168
|
+
group_ids = security_groups.map { |sg| vpc_security_groups[sg] }
|
169
|
+
instance.modify_attribute(:groups => group_ids.compact)
|
170
|
+
return Vominator::EC2.get_instance(resource,instance_id).security_groups.map {|sg| sg[:group_name]}
|
171
|
+
end
|
172
|
+
|
173
|
+
def self.get_ebs_volume(resource, ebs_volume_id)
|
174
|
+
return resource.volumes(filters: [{name: 'volume-id', values: [ebs_volume_id]}]).first
|
175
|
+
end
|
176
|
+
|
177
|
+
def self.get_instance_ebs_volumes(resource, instance_id)
|
178
|
+
instance = Vominator::EC2.get_instance(resource,instance_id)
|
179
|
+
return instance.block_device_mappings.map {|vol| vol[:device_name]}
|
180
|
+
end
|
181
|
+
|
182
|
+
def self.add_ebs_volume(resource, instance_id, volume_type, volume_size, mount_point, iops=false, encrypted=false)
|
183
|
+
instance = Vominator::EC2.get_instance(resource,instance_id)
|
184
|
+
availability_zone = instance.placement[:availability_zone]
|
185
|
+
|
186
|
+
case volume_type
|
187
|
+
when 'magnetic'
|
188
|
+
volume = resource.create_volume(:availability_zone => availability_zone, :volume_type => 'standard', :size => volume_size, :encrypted => encrypted)
|
189
|
+
when 'gp'
|
190
|
+
volume = resource.create_volume(:availability_zone => availability_zone, :volume_type => 'gp2', :size => volume_size, :encrypted => encrypted)
|
191
|
+
when 'piops'
|
192
|
+
iops = volume_size * 15 unless iops
|
193
|
+
volume = resource.create_volume(:availability_zone => availability_zone, :volume_type => 'io1', :size => volume_size, :iops => iops, :encrypted => encrypted)
|
194
|
+
else
|
195
|
+
volume = nil
|
196
|
+
LOGGER.fatal("#{volume_type} is unsupported")
|
197
|
+
end
|
198
|
+
LOGGER.info("Waiting for #{volume.id} to be provisioned and become available")
|
199
|
+
|
200
|
+
sleep 3 until Vominator::EC2.get_ebs_volume(resource, volume.id).state == 'available'
|
201
|
+
|
202
|
+
LOGGER.info("Attaching #{volume.id} to the instance and waiting for it to be attached.")
|
203
|
+
instance.attach_volume(:device => mount_point, :volume_id => volume.id)
|
204
|
+
sleep 3 until Vominator::EC2.get_ebs_volume(resource, volume.id).state == 'in-use'
|
205
|
+
|
206
|
+
return volume
|
207
|
+
end
|
208
|
+
|
209
|
+
def self.get_ephemeral_devices(instance_type)
|
210
|
+
device_count = Vominator::EC2.get_ephemeral_dev_count(instance_type)
|
211
|
+
devices = Hash.new
|
212
|
+
for i in 1..device_count
|
213
|
+
mount_point = (65 + (i)).chr.downcase
|
214
|
+
devices["/dev/sd#{mount_point}"] = "ephemeral#{i-1}"
|
215
|
+
end
|
216
|
+
return devices
|
217
|
+
end
|
218
|
+
|
219
|
+
def self.create_instance(resource, hostname, environment, ami_id, subnet_id, instance_type, key_name, private_ip_address, az, security_group_ids, user_data, ebs_optimized, iam_profile)
|
220
|
+
begin
|
221
|
+
LOGGER.info("Creating instance for #{hostname}.#{environment}")
|
222
|
+
instance = resource.create_instances(:min_count => 1, :max_count => 1, :image_id => ami_id, :subnet_id => subnet_id, :instance_type => instance_type, :key_name => key_name, :private_ip_address => private_ip_address, :placement => {:availability_zone => az}, :security_group_ids => security_group_ids, :user_data => Base64.encode64(user_data), :ebs_optimized => ebs_optimized, :iam_instance_profile => {:name => iam_profile}).first
|
223
|
+
rescue Aws::EC2::Errors::InvalidIPAddressInUse
|
224
|
+
LOGGER.fatal("Unable to create the instance as #{private_ip_address} is in use")
|
225
|
+
rescue Aws::EC2::Errors::InternalError
|
226
|
+
LOGGER.fatal("Unable to create instance due to an AWS internal server error. Try again in a bit")
|
227
|
+
end
|
228
|
+
LOGGER.info('Waiting for the instance to come online.')
|
229
|
+
sleep 10
|
230
|
+
sleep 2 until Vominator::EC2.get_instance_state(resource, instance.id) != 'pending'
|
231
|
+
|
232
|
+
instance.create_tags(:tags => [{:key => 'Name', :value => "#{hostname}.#{environment}"},{:key => 'Environment', :value => environment},{:key => 'Provisioned_By', :value => 'Vominator'}])
|
233
|
+
|
234
|
+
if Vominator::EC2.get_instance_state(resource, instance.id) == 'running'
|
235
|
+
return instance
|
236
|
+
else
|
237
|
+
return nil
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
def self.terminate_instance(resource, instance_id)
|
242
|
+
instance = Vominator::EC2.get_instance(resource,instance_id)
|
243
|
+
instance.terminate
|
244
|
+
sleep 2 until Vominator::EC2.get_instance_state(resource, instance.id) == 'terminated'
|
245
|
+
return true
|
246
|
+
end
|
247
|
+
|
248
|
+
def self.tag_resource(client, resource_id, tags)
|
249
|
+
client.create_tags(resources: [resource_id], tags: tags)
|
250
|
+
end
|
251
|
+
|
252
|
+
def self.get_security_groups(client, vpc_id)
|
253
|
+
return client.describe_security_groups(filters: [{name: 'vpc-id', values: [vpc_id]}]).first.security_groups
|
254
|
+
end
|
255
|
+
|
256
|
+
def self.create_security_group(client, name, vpc_id, description=nil)
|
257
|
+
return client.create_security_group(group_name: name, description: description || name, vpc_id: vpc_id)
|
258
|
+
end
|
259
|
+
|
260
|
+
def self.create_security_group_rule(client,type,group_id,rule)
|
261
|
+
case type
|
262
|
+
when 'ingress'
|
263
|
+
if rule[:source_security_group_id]
|
264
|
+
client.authorize_security_group_ingress({group_id: group_id, ip_permissions: [{ip_protocol: rule[:ip_protocol], from_port: rule[:from_port], to_port: rule[:to_port], user_id_group_pairs: [{group_id: rule[:source_security_group_id]}]}]})
|
265
|
+
end
|
266
|
+
|
267
|
+
if rule[:cidr_ip]
|
268
|
+
client.authorize_security_group_ingress({group_id: group_id, cidr_ip: rule[:cidr_ip], ip_protocol: rule[:ip_protocol], from_port: rule[:from_port], to_port: rule[:to_port]})
|
269
|
+
end
|
270
|
+
|
271
|
+
when 'egress'
|
272
|
+
if rule[:source_security_group_id]
|
273
|
+
client.authorize_security_group_egress({group_id: group_id, ip_permissions: [{ip_protocol: rule[:ip_protocol], from_port: rule[:from_port], to_port: rule[:to_port], user_id_group_pairs: [{group_id: rule[:source_security_group_id]}]}]})
|
274
|
+
end
|
275
|
+
|
276
|
+
if rule[:cidr_ip]
|
277
|
+
client.authorize_security_group_egress({group_id: group_id, cidr_ip: rule[:cidr_ip], ip_protocol: rule[:ip_protocol], from_port: rule[:from_port], to_port: rule[:to_port]})
|
278
|
+
end
|
279
|
+
else
|
280
|
+
return false
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
def self.delete_security_group_rule(client,type,group_id,rule)
|
285
|
+
case type
|
286
|
+
when 'ingress'
|
287
|
+
if rule[:source_security_group_id]
|
288
|
+
client.revoke_security_group_ingress({group_id: group_id, ip_permissions: [{ip_protocol: rule[:ip_protocol], from_port: rule[:from_port], to_port: rule[:to_port], user_id_group_pairs: [{group_id: rule[:source_security_group_id]}]}]})
|
289
|
+
end
|
290
|
+
|
291
|
+
if rule[:cidr_ip]
|
292
|
+
client.revoke_security_group_ingress({group_id: group_id, ip_permissions: [{ip_protocol: rule[:ip_protocol], from_port: rule[:from_port], to_port: rule[:to_port], ip_ranges: [{cidr_ip: rule[:cidr_ip]}]}]})
|
293
|
+
end
|
294
|
+
|
295
|
+
when 'egress'
|
296
|
+
if rule[:source_security_group_id]
|
297
|
+
client.revoke_security_group_egress({group_id: group_id, ip_permissions: [{ip_protocol: rule[:ip_protocol], from_port: rule[:from_port], to_port: rule[:to_port], user_id_group_pairs: [{group_id: rule[:source_security_group_id]}]}]})
|
298
|
+
end
|
299
|
+
|
300
|
+
if rule[:cidr_ip]
|
301
|
+
client.revoke_security_group_egress({group_id: group_id, ip_permissions: [{ip_protocol: rule[:ip_protocol], from_port: rule[:from_port], to_port: rule[:to_port], ip_ranges: [{cidr_ip: rule[:cidr_ip]}]}]})
|
302
|
+
end
|
303
|
+
else
|
304
|
+
return false
|
305
|
+
end
|
306
|
+
end
|
307
|
+
end
|
308
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require_relative 'constants'
|
2
|
+
require 'erubis'
|
3
|
+
|
4
|
+
module Vominator
|
5
|
+
class Instances
|
6
|
+
def self.get_instances(environment, product, filter=false)
|
7
|
+
if PUKE_CONFIG[environment]['products'].include? product
|
8
|
+
config_file = File.expand_path("#{VOMINATOR_CONFIG['configuration_path']}/products/#{product}/instances.yaml")
|
9
|
+
if filter
|
10
|
+
instances = Array.new
|
11
|
+
YAML.load(File.read(config_file)).each do |instance|
|
12
|
+
if filter.include? instance.keys[0]
|
13
|
+
instances.push instance
|
14
|
+
end
|
15
|
+
end
|
16
|
+
else
|
17
|
+
instances = YAML.load(File.read(config_file))
|
18
|
+
end
|
19
|
+
return instances if instances.kind_of?(Array)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.generate_cloud_config(hostname, environment, family, roles, recipes)
|
24
|
+
template = "#{family}_cloud_config_template"
|
25
|
+
begin
|
26
|
+
cloud_config_template = File.read("#{VOMINATOR_CONFIG['configuration_path']}/cloud-configs/#{PUKE_CONFIG[environment][template]}")
|
27
|
+
rescue Errno::EISDIR
|
28
|
+
LOGGER.fatal("Unable to find #{template} in your cloud-config directory. Check that this file exists in #{VOMINATOR_CONFIG['configuration_path']}/cloud-configs/")
|
29
|
+
end
|
30
|
+
cloud_config = Erubis::Eruby.new(cloud_config_template)
|
31
|
+
return cloud_config.result(:hostname => hostname, :env => environment, :roles => roles, :recipes => recipes)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
require 'aws-sdk'
|
2
|
+
require_relative 'constants'
|
3
|
+
|
4
|
+
module Vominator
|
5
|
+
class Route53
|
6
|
+
def self.get_zone_by_id(client, zone_id)
|
7
|
+
return client.get_hosted_zone(id: zone_id).hosted_zone
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.get_zone_by_domain(client, domain_name)
|
11
|
+
zones = client.list_hosted_zones_by_name(dns_name: domain_name).hosted_zones
|
12
|
+
zone = nil
|
13
|
+
zones.each do |z|
|
14
|
+
zone = z if z.name == "#{domain_name}."
|
15
|
+
end
|
16
|
+
|
17
|
+
return zone
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.create_zone(client, domain_name)
|
21
|
+
return client.create_hosted_zone(name: domain_name, caller_reference: "#{domain_name} + #{Time.now.to_i}")
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.get_records(client, zone, max_items=50)
|
25
|
+
resp = client.list_resource_record_sets(:hosted_zone_id => zone, :max_items => max_items)
|
26
|
+
records = resp[:resource_record_sets]
|
27
|
+
while resp[:is_truncated]
|
28
|
+
resp = client.list_resource_record_sets(:hosted_zone_id => zone, :max_items => max_items, :start_record_name => resp[:next_record_name])
|
29
|
+
records += resp[:resource_record_sets]
|
30
|
+
end
|
31
|
+
names = Array.new
|
32
|
+
records.each do |record|
|
33
|
+
names.push record[:name]
|
34
|
+
end
|
35
|
+
return names
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.create_nameserver_records(client, zone, fqdn, nameservers, ttl=172800)
|
39
|
+
resource_records = Array.new
|
40
|
+
nameservers.each do |nameserver|
|
41
|
+
hash = Hash.new
|
42
|
+
hash[:value] = nameserver
|
43
|
+
resource_records.push hash
|
44
|
+
end
|
45
|
+
|
46
|
+
resp = client.change_resource_record_sets(
|
47
|
+
:hosted_zone_id => zone,
|
48
|
+
:change_batch => {
|
49
|
+
:changes => [
|
50
|
+
{
|
51
|
+
:action => "CREATE",
|
52
|
+
:resource_record_set => {
|
53
|
+
:name => fqdn,
|
54
|
+
:type => 'NS',
|
55
|
+
:ttl => ttl,
|
56
|
+
:resource_records => resource_records
|
57
|
+
}
|
58
|
+
}
|
59
|
+
]
|
60
|
+
}
|
61
|
+
)
|
62
|
+
|
63
|
+
if resp.change_info.status == 'PENDING'
|
64
|
+
return true
|
65
|
+
else
|
66
|
+
return false
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.create_record(client, zone, fqdn, ip, type='A', ttl=600)
|
71
|
+
resp = client.change_resource_record_sets(
|
72
|
+
:hosted_zone_id => "/hostedzone/#{zone}",
|
73
|
+
:change_batch => {
|
74
|
+
:changes => [
|
75
|
+
{
|
76
|
+
:action => "CREATE",
|
77
|
+
:resource_record_set => {
|
78
|
+
:name => "#{fqdn}.",
|
79
|
+
:type => type,
|
80
|
+
:ttl => ttl,
|
81
|
+
:resource_records => [{
|
82
|
+
:value => "#{ip}"
|
83
|
+
}]
|
84
|
+
}
|
85
|
+
}
|
86
|
+
]
|
87
|
+
}
|
88
|
+
)
|
89
|
+
|
90
|
+
if resp.change_info.status == 'PENDING'
|
91
|
+
return true
|
92
|
+
else
|
93
|
+
return false
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.delete_record(client, zone, fqdn, ip, type='A', ttl=600)
|
98
|
+
resp = client.change_resource_record_sets(
|
99
|
+
:hosted_zone_id => "/hostedzone/#{zone}",
|
100
|
+
:change_batch => {
|
101
|
+
:changes => [
|
102
|
+
{
|
103
|
+
:action => "DELETE",
|
104
|
+
:resource_record_set => {
|
105
|
+
:name => "#{fqdn}.",
|
106
|
+
:type => type,
|
107
|
+
:ttl => ttl,
|
108
|
+
:resource_records => [{
|
109
|
+
:value => ip
|
110
|
+
}]
|
111
|
+
}
|
112
|
+
|
113
|
+
}
|
114
|
+
]
|
115
|
+
}
|
116
|
+
)
|
117
|
+
if resp.change_info.status == 'PENDING'
|
118
|
+
return true
|
119
|
+
else
|
120
|
+
return false
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
end
|