vominator 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|