terrafying 0.0.1 → 1.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: e724b0e9a74aa110c08cf5d626ad5f2b6949756228247e91a0cb95e03d978cf8
4
- data.tar.gz: 2aef909625b0b0deca67334692c92fe09aa390752333a6786f5105fcde16a843
2
+ SHA1:
3
+ metadata.gz: 70869102117177c4b1ae135205c2d3e8125594dc
4
+ data.tar.gz: 68af6eac242cb17475352a4a0892120a5ea9c004
5
5
  SHA512:
6
- metadata.gz: f7fbbbf2099f7aeb7868430f48727f95a1f3c9d4c4a455bb75499a70019222187afc9fca7991a3b0986bc61077730de7eaa35925b4700a93632b37a63cd7d8ed
7
- data.tar.gz: dae8c1681cab403c115f9c272c483a2c02c9a20672bf177ee513ad029061c7894e7c7fa2ede29c166e32295e2a6a07fede984cfb1f7b0972dd11bf0d6a33d4a3
6
+ metadata.gz: ec0f04b65aef668252431358f4faf736d39e5e6f3726175484707b2daecfc58e6d9e5c2e7d42ed09025d39dc80af10910244131c33483373cd1ef0420045186a
7
+ data.tar.gz: 13b42d533f1f85670c09b78eb326d274a9021b1a60521bc566bd051d85da2d56f6692dad0d3b657411994d6d81794b0f209087de3a18ec1f8c3fffa6397c2064
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: terrafying
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 1.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - uSwitch Limited
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-03-16 00:00:00.000000000 Z
11
+ date: 2018-01-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -145,19 +145,6 @@ extensions: []
145
145
  extra_rdoc_files: []
146
146
  files:
147
147
  - bin/terrafying
148
- - lib/hash/deep_merge.rb
149
- - lib/terrafying.rb
150
- - lib/terrafying/aws.rb
151
- - lib/terrafying/cli.rb
152
- - lib/terrafying/dynamodb.rb
153
- - lib/terrafying/dynamodb/config.rb
154
- - lib/terrafying/dynamodb/named_lock.rb
155
- - lib/terrafying/dynamodb/state.rb
156
- - lib/terrafying/generator.rb
157
- - lib/terrafying/lock.rb
158
- - lib/terrafying/state.rb
159
- - lib/terrafying/util.rb
160
- - lib/terrafying/version.rb
161
148
  homepage: https://github.com/uswitch/terrafying
162
149
  licenses:
163
150
  - Apache-2.0
@@ -178,7 +165,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
178
165
  version: '0'
179
166
  requirements: []
180
167
  rubyforge_project:
181
- rubygems_version: 2.7.6
168
+ rubygems_version: 2.4.5
182
169
  signing_key:
183
170
  specification_version: 4
184
171
  summary: No.
@@ -1,6 +0,0 @@
1
- class ::Hash
2
- def deep_merge(second)
3
- merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2 }
4
- self.merge(second, &merger)
5
- end
6
- end
@@ -1,542 +0,0 @@
1
- require 'aws-sdk'
2
-
3
- Aws.use_bundled_cert!
4
-
5
- module Terrafying
6
- module Aws
7
- class Ops
8
-
9
- attr_reader :region
10
-
11
- def initialize(region)
12
- full_jitter = lambda { |c| Kernel.sleep(Kernel.rand(0..[2, (0.3 * 2**c.retries)].min)) }
13
-
14
- ::Aws.config.update({
15
- region: region,
16
- retry_limit: 5,
17
- retry_backoff: full_jitter
18
- })
19
- @autoscaling_client = ::Aws::AutoScaling::Client.new
20
- @ec2_resource = ::Aws::EC2::Resource.new
21
- @ec2_client = ::Aws::EC2::Client.new
22
- @elb_client = ::Aws::ElasticLoadBalancingV2::Client.new
23
- @route53_client = ::Aws::Route53::Client.new
24
- @s3_client = ::Aws::S3::Client.new
25
- @sts_client = ::Aws::STS::Client.new
26
-
27
- @region = region
28
- end
29
-
30
- def account_id
31
- @account_id_cache ||= @sts_client.get_caller_identity.account
32
- end
33
-
34
- def security_group(name)
35
- @security_groups ||= {}
36
- @security_groups[name] ||=
37
- begin
38
- STDERR.puts "Looking up id of security group '#{name}'"
39
- groups = @ec2_resource.security_groups(
40
- {
41
- filters: [
42
- {
43
- name: "group-name",
44
- values: [name],
45
- },
46
- ],
47
- }).limit(2)
48
- case
49
- when groups.count == 1
50
- groups.first.id
51
- when groups.count < 1
52
- raise "No security group with name '#{name}' was found."
53
- when groups.count > 1
54
- raise "More than one security group with name '#{name}' found: " + groups.join(', ')
55
- end
56
- end
57
- end
58
-
59
- def security_group_in_vpc(vpc_id, name)
60
- @security_groups_in_vpc ||= {}
61
- @security_groups_in_vpc[vpc_id + name] ||=
62
- begin
63
- STDERR.puts "Looking up id of security group '#{name}'"
64
- groups = @ec2_resource.security_groups(
65
- {
66
- filters: [
67
- {
68
- name: "group-name",
69
- values: [name],
70
- },
71
- {
72
- name: "vpc-id",
73
- values: [vpc_id],
74
- }
75
- ],
76
- }).limit(2)
77
- case
78
- when groups.count == 1
79
- groups.first.id
80
- when groups.count < 1
81
- raise "No security group with name '#{name}' was found."
82
- when groups.count > 1
83
- raise "More than one security group with name '#{name}' found: " + groups.join(', ')
84
- end
85
- end
86
- end
87
-
88
- def security_group_by_tags(tags)
89
- @security_groups_by_tags ||= {}
90
- @security_groups_by_tags[tags] ||=
91
- begin
92
- groups = @ec2_client.describe_security_groups(
93
- {
94
- filters: [
95
- {
96
- name: "tag-key",
97
- values: tags.keys,
98
- },
99
- {
100
- name: "tag-value",
101
- values: tags.values
102
- }
103
- ]
104
- },
105
- ).security_groups
106
- case
107
- when groups.count == 1
108
- groups.first.id
109
- when groups.count < 1
110
- raise "No security group with tags '#{tags}' was found."
111
- when groups.count > 1
112
- raise "More than one security group with tags '#{tags}' found: " + groups.join(', ')
113
- end
114
- end
115
- end
116
-
117
- def instance_profile(name)
118
- @instance_profiles ||= {}
119
- @instance_profiles[name] ||=
120
- begin
121
- resource = ::Aws::IAM::Resource.new
122
- STDERR.puts "Looking up id of instance profile '#{name}'"
123
- # unfortunately amazon don't let us filter for profiles using
124
- # a name filter, for now we have enumerate and filter manually
125
- coll = resource.instance_profiles
126
- profiles = []
127
- profiles = coll.select {|p| p.instance_profile_name =~ /#{name}/}
128
-
129
- case
130
- when profiles.count == 1
131
- profiles.first.instance_profile_id
132
- when profiles.count < 1
133
- raise "No instance profile with name '#{name}' was found."
134
- when profiles.count > 1
135
- raise "More than one instance profile with name '#{name}' found: " + profiles.join(', ')
136
- end
137
- end
138
- end
139
-
140
- def route_table_for_subnet(subnet_id)
141
- @route_table_for_subnet ||= {}
142
- @route_table_for_subnet[subnet_id] ||=
143
- begin
144
- resp = @ec2_client.describe_route_tables(
145
- {
146
- filters: [
147
- { name: "association.subnet-id", values: [ subnet_id ] },
148
- ],
149
- })
150
-
151
- route_tables = resp.route_tables
152
-
153
- case
154
- when route_tables.count == 1
155
- route_tables.first
156
- when route_tables.count < 1
157
- raise "No route table for subnet '#{subnet_id}' was found."
158
- when profiles.count > 1
159
- raise "More than route table for subnet '#{subnet_id}' found: " + route_tables.join(', ')
160
- end
161
- end
162
- end
163
-
164
- def route_table_for_vpc(vpc_id)
165
- @route_table_for_vpc ||= {}
166
- @route_table_for_vpc[vpc_id] ||=
167
- begin
168
- resp = @ec2_client.describe_route_tables(
169
- {
170
- filters: [
171
- { name: "association.main", values: [ "true" ] },
172
- { name: "vpc-id", values: [ vpc_id ] },
173
- ],
174
- })
175
-
176
- route_tables = resp.route_tables
177
-
178
- case
179
- when route_tables.count == 1
180
- route_tables.first
181
- when route_tables.count < 1
182
- raise "No route table for vpc '#{vpc_id}' was found."
183
- when profiles.count > 1
184
- raise "More than route table for vpc '#{vpc_id}' found: " + route_tables.join(', ')
185
- end
186
- end
187
- end
188
-
189
- def security_groups(*names)
190
- names.map{|n| security_group(n)}
191
- end
192
-
193
- def security_groups_in_vpc(vpc_id, *names)
194
- names.map{|n| security_group_in_vpc(vpc_id, n)}
195
- end
196
-
197
- def subnet(name)
198
- @subnets ||= {}
199
- @subnets[name] ||=
200
- begin
201
- STDERR.puts "Looking up id of subnet '#{name}'"
202
- subnets = @ec2_resource.subnets(
203
- {
204
- filters: [
205
- {
206
- name: "tag:Name",
207
- values: [name],
208
- },
209
- ],
210
- }).limit(2)
211
- case
212
- when subnets.count == 1
213
- subnets.first.id
214
- when subnets.count < 1
215
- raise "No subnet with name '#{name}' was found."
216
- when subnets.count > 1
217
- raise "More than one subnet with this name '#{name}' found : " + subnets.join(', ')
218
- end
219
- end
220
- end
221
-
222
- def subnet_by_id(id)
223
- @subnets_by_id ||= {}
224
- @subnets_by_id[id] ||=
225
- begin
226
- resp = @ec2_client.describe_subnets(
227
- {
228
- subnet_ids: [id],
229
- })
230
- subnets = resp.subnets
231
- case
232
- when subnets.count == 1
233
- subnets.first
234
- when subnets.count < 1
235
- raise "No subnet with id '#{id}' was found."
236
- when subnets.count > 1
237
- raise "More than one subnet with this id '#{id}' found : " + subnets.join(', ')
238
- end
239
- end
240
- end
241
-
242
- def subnets(*names)
243
- names.map{|n| subnet(n)}
244
- end
245
-
246
- def subnets_for_vpc(vpc_id)
247
- @subnets_for_vpc ||= {}
248
- @subnets_for_vpc[vpc_id] ||=
249
- begin
250
- resp = @ec2_client.describe_subnets(
251
- {
252
- filters: [
253
- { name: "vpc-id", values: [ vpc_id ] },
254
- ],
255
- })
256
-
257
- subnets = resp.subnets
258
-
259
- case
260
- when subnets.count >= 1
261
- subnets
262
- when subnets.count < 1
263
- raise "No subnets found for '#{vpc_id}'."
264
- end
265
- end
266
- end
267
-
268
- def ami(name, owners=["self"])
269
- @ami ||= {}
270
- @ami[name] ||=
271
- begin
272
- STDERR.puts "looking for an image with prefix '#{name}'"
273
- resp = @ec2_client.describe_images({owners: owners})
274
- if resp.images.count < 1
275
- raise "no images were found"
276
- end
277
- m = resp.images.select { |a| /^#{name}/.match(a.name) }
278
- if m.count == 0
279
- raise "no image with name '#{name}' was found"
280
- end
281
- m.sort { |x,y| y.creation_date <=> x.creation_date }.shift.image_id
282
- end
283
- end
284
-
285
- def availability_zones
286
- @availability_zones ||=
287
- begin
288
- STDERR.puts "looking for AZs in the current region"
289
- resp = @ec2_client.describe_availability_zones({})
290
- resp.availability_zones.map { |zone|
291
- zone.zone_name
292
- }
293
- end
294
- end
295
-
296
- def vpc(name)
297
- @vpcs ||= {}
298
- @vpcs[name] ||=
299
- begin
300
- STDERR.puts "looking for a VPC with name '#{name}'"
301
- resp = @ec2_client.describe_vpcs({})
302
- matching_vpcs = resp.vpcs.select { |vpc|
303
- name_tag = vpc.tags.select { |tag| tag.key == "Name" }.first
304
- name_tag && name_tag.value == name
305
- }
306
- case
307
- when matching_vpcs.count == 1
308
- matching_vpcs.first
309
- when matching_vpcs.count < 1
310
- raise "No VPC with name '#{name}' was found."
311
- when matching_vpcs.count > 1
312
- raise "More than one VPC with name '#{name}' was found: " + matching_vpcs.join(', ')
313
- end
314
- end
315
- end
316
-
317
- def route_table(name)
318
- @route_tables ||= {}
319
- @route_tables[name] ||=
320
- begin
321
- STDERR.puts "looking for a route table with name '#{name}'"
322
- route_tables = @ec2_client.describe_route_tables(
323
- {
324
- filters: [
325
- {
326
- name: "tag:Name",
327
- values: [name],
328
- },
329
- ],
330
- }
331
- ).route_tables
332
- case
333
- when route_tables.count == 1
334
- route_tables.first.route_table_id
335
- when route_tables.count < 1
336
- raise "No route table with name '#{name}' was found."
337
- when route_tables.count > 1
338
- raise "More than one route table with name '#{name}' was found: " + route_tables.join(', ')
339
- end
340
- end
341
- end
342
-
343
- def elastic_ip(alloc_id)
344
- @ips ||= {}
345
- @ips[alloc_id] ||=
346
- begin
347
- STDERR.puts "looking for an elastic ip with allocation_id '#{alloc_id}'"
348
- ips = @ec2_client.describe_addresses(
349
- {
350
- filters: [
351
- {
352
- name: "allocation-id",
353
- values: [alloc_id],
354
- },
355
- ],
356
- }
357
- ).addresses
358
- case
359
- when ips.count == 1
360
- ips.first
361
- when ips.count < 1
362
- raise "No elastic ip with allocation_id '#{alloc_id}' was found."
363
- when ips.count > 1
364
- raise "More than one elastic ip with allocation_id '#{alloc_id}' was found: " + ips.join(', ')
365
- end
366
- end
367
- end
368
-
369
- def hosted_zone(fqdn)
370
- @hosted_zones ||= {}
371
- @hosted_zones[fqdn] ||=
372
- begin
373
- STDERR.puts "looking for a hosted zone with fqdn '#{fqdn}'"
374
- hosted_zones = @route53_client.list_hosted_zones_by_name({ dns_name: fqdn }).hosted_zones.select { |zone|
375
- zone.name == "#{fqdn}."
376
- }
377
- case
378
- when hosted_zones.count == 1
379
- hosted_zones.first
380
- when hosted_zones.count < 1
381
- raise "No hosted zone with fqdn '#{fqdn}' was found."
382
- when hosted_zones.count > 1
383
- raise "More than one hosted zone with name '#{fqdn}' was found: " + hosted_zones.join(', ')
384
- end
385
- end
386
- end
387
-
388
- def hosted_zone_by_tag(tag)
389
- @hosted_zones ||= {}
390
- @hosted_zones[tag] ||=
391
- begin
392
- STDERR.puts "looking for a hosted zone with tag '#{tag}'"
393
- @aws_hosted_zones ||= @route53_client.list_hosted_zones.hosted_zones.map do |zone|
394
- {
395
- zone: zone,
396
- tags: @route53_client.list_tags_for_resource({resource_type: "hostedzone", resource_id: zone.id.split('/')[2]}).resource_tag_set.tags
397
- }
398
- end
399
-
400
- hosted_zones = @aws_hosted_zones.select do |z|
401
- z[:tags].any? do |aws_tag|
402
- tag.any? { |k, v| aws_tag.key = String(k) && aws_tag.value == v }
403
- end
404
- end
405
-
406
- case
407
- when hosted_zones.count == 1
408
- hosted_zones.first[:zone]
409
- when hosted_zones.count < 1
410
- raise "No hosted zone with tag '#{tag}' was found."
411
- when hosted_zones.count > 1
412
- raise "More than one hosted zone with tag '#{tag}' was found: " + hosted_zones.join(', ')
413
- end
414
- end
415
- end
416
-
417
- def s3_object(bucket, key)
418
- @s3_objects ||= {}
419
- @s3_objects["#{bucket}-#{key}"] ||=
420
- begin
421
- resp = @s3_client.get_object({ bucket: bucket, key: key })
422
- resp.body.read
423
- end
424
- end
425
-
426
- def list_objects(bucket)
427
- @list_objects ||= {}
428
- @list_objects[bucket] ||=
429
- begin
430
- resp = @s3_client.list_objects_v2({ bucket: bucket })
431
- resp.contents
432
- end
433
- end
434
-
435
- def endpoint_service_by_name(service_name)
436
- @endpoint_service ||= {}
437
- @endpoint_service[service_name] ||=
438
- begin
439
- resp = @ec2_client.describe_vpc_endpoint_service_configurations(
440
- {
441
- filters: [
442
- {
443
- name: "service-name",
444
- values: [service_name],
445
- },
446
- ],
447
- }
448
- )
449
-
450
- endpoint_services = resp.service_configurations
451
- case
452
- when endpoint_services.count == 1
453
- endpoint_services.first
454
- when endpoint_services.count < 1
455
- raise "No endpoint service with name '#{service_name}' was found."
456
- when endpoint_services.count > 1
457
- raise "More than one endpoint service with name '#{service_name}' was found: " + endpoint_services.join(', ')
458
- end
459
- end
460
- end
461
-
462
- def endpoint_service_by_lb_arn(arn)
463
- @endpoint_services_by_lb_arn ||= {}
464
- @endpoint_services_by_lb_arn[arn] ||=
465
- begin
466
- resp = @ec2_client.describe_vpc_endpoint_service_configurations
467
-
468
- services = resp.service_configurations.select { |service|
469
- service.network_load_balancer_arns.include?(arn)
470
- }
471
-
472
- case
473
- when services.count == 1
474
- services.first
475
- when services.count < 1
476
- raise "No endpoint service with lb arn '#{arn}' was found."
477
- when services.count > 1
478
- raise "More than one endpoint service with lb arn '#{arn}' was found: " + services.join(', ')
479
- end
480
- end
481
- end
482
-
483
- def lb_by_name(name)
484
- @lbs ||= {}
485
- @lbs[name] ||=
486
- begin
487
- load_balancers = @elb_client.describe_load_balancers({ names: [name] }).load_balancers
488
-
489
- case
490
- when load_balancers.count == 1
491
- load_balancers.first
492
- when load_balancers.count < 1
493
- raise "No load balancer with name '#{name}' was found."
494
- when load_balancers.count > 1
495
- raise "More than one load balancer with name '#{name}' was found: " + load_balancers.join(', ')
496
- end
497
- end
498
- end
499
-
500
- def target_groups_by_lb(arn)
501
- @target_groups ||= {}
502
- @target_groups[arn] ||=
503
- begin
504
- resp = @elb_client.describe_target_groups(
505
- {
506
- load_balancer_arn: arn,
507
- }
508
- )
509
-
510
- resp.target_groups
511
- end
512
- end
513
-
514
- def asgs_by_tags(expectedTags = {})
515
- asgs = []
516
- next_token = nil
517
-
518
- loop do
519
- resp = @autoscaling_client.describe_auto_scaling_groups({ next_token: next_token })
520
-
521
- asgs = asgs + resp.auto_scaling_groups.select { |asg|
522
- matches = asg.tags.select { |tag|
523
- expectedTags[tag.key.to_sym] == tag.value ||
524
- expectedTags[tag.key] == tag.value
525
- }
526
-
527
- matches.count == expectedTags.count
528
- }
529
-
530
- if resp.next_token
531
- next_token = resp.next_token
532
- else
533
- break
534
- end
535
- end
536
-
537
- asgs
538
- end
539
- end
540
-
541
- end
542
- end
@@ -1,73 +0,0 @@
1
- require 'thor'
2
-
3
- module Terrafying
4
- class Cli < Thor
5
- class_option :lock_timeout, :type => :string, :default => nil
6
- class_option :no_lock, :type => :boolean, :default => false
7
- class_option :keep, :type => :boolean, :default => false
8
- class_option :target, :type => :string, :default => nil
9
- class_option :scope, :type => :string, :default => nil
10
- class_option :dynamodb, :type => :boolean, :default => true
11
-
12
- desc "list PATH", "List resources defined"
13
- def list(path)
14
- puts "Defined resources:\n\n"
15
- Config.new(path, options).list.each do |name|
16
- puts "#{name}"
17
- end
18
- end
19
-
20
- desc "plan PATH", "Show execution plan"
21
- def plan(path)
22
- exit Config.new(path, options).plan
23
- end
24
-
25
- desc "graph PATH", "Show execution graph"
26
- def graph(path)
27
- exit Config.new(path, options).graph
28
- end
29
-
30
- desc "validate PATH", "Validate the generated Terraform"
31
- def validate(path)
32
- exit Config.new(path, options).validate
33
- end
34
-
35
- desc "apply PATH", "Apply changes to resources"
36
- option :force, :aliases => ['f'], :type => :boolean, :desc => "Forcefully remove any pending locks"
37
- def apply(path)
38
- exit Config.new(path, options).apply
39
- end
40
-
41
- desc "destroy PATH", "Destroy resources"
42
- option :force, :aliases => ['f'], :type => :boolean, :desc => "Forcefully remove any pending locks"
43
- def destroy(path)
44
- exit Config.new(path, options).destroy
45
- end
46
-
47
- desc "json PATH", "Show terraform JSON"
48
- def json(path)
49
- puts(Config.new(path, options).json)
50
- end
51
-
52
- desc "show-state PATH", "Show state"
53
- def show_state(path)
54
- puts(Config.new(path, options).show_state)
55
- end
56
-
57
- desc "use-remote-state PATH", "Migrate to using remote state storage"
58
- def use_remote_state(path)
59
- puts(Config.new(path, options).use_remote_state)
60
- end
61
-
62
- desc "use-local-state PATH", "Migrate to using local state storage"
63
- def use_local_state(path)
64
- puts(Config.new(path, options).use_local_state)
65
- end
66
-
67
- desc "import PATH ADDR ID", "Import existing infrastructure into your Terraform state"
68
- def import(path, addr, id)
69
- exit Config.new(path, options).import(addr, id)
70
- end
71
-
72
- end
73
- end
@@ -1,17 +0,0 @@
1
- module Terrafying
2
- module DynamoDb
3
- class Config
4
- attr_accessor :state_table, :lock_table
5
-
6
- def initialize
7
- @state_table = "terrafying-state"
8
- @lock_table = "terrafying-state-lock"
9
- end
10
- end
11
-
12
- def config
13
- @config ||= Config.new
14
- end
15
- module_function :config
16
- end
17
- end