sortinghat 0.3.3 → 0.3.4.develop

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 8781c38bf0c7c5db4a3ca524b653fc6dd43bf457
4
- data.tar.gz: 70f1c58afeadd42a06e63d02b95f87cdb5237be7
2
+ SHA256:
3
+ metadata.gz: 9a0bb1fc284e16b20cff54621a6608e51c1b233fcfe6877012c9f9f2560a0453
4
+ data.tar.gz: 4fb17c7cccf23ed6e006e90d171d0ef339a2516664907d1fb166d9c3b9e05d29
5
5
  SHA512:
6
- metadata.gz: c9a2813b2ff10016d9dfbed256170a088104c1ae986c23d39e6ea0584fffdb59349d84ad01bec7be403aecdba4aa7c00215894a79cef5f377e2af89a83bb8d0d
7
- data.tar.gz: 5715916fce1f304cc93b7140389ab1af2f12b6a005ad89ad7e5bc7aed9be456f5c590a1964040e4c1f64a35dae33fddbe37921ba444bcd718aa5ddb557fb7444
6
+ metadata.gz: '07584c6af915ac9aea638cd9e24592b4fa8576545285298ece0ec4bfd5deff9bee34ae9db876dffc63d610103e44edc1eefc26ba90313819802d5b66bd7284a3'
7
+ data.tar.gz: 83fed95b1925f27736a4f4fd9b20807a6bf2ddf2a0b0ca6beb61ccb244d1bc3c126bd4835f3a6339bc26c3ebf19afc4cc8bc33f4c3c4c415584da97fc113666c
data/.gitignore CHANGED
@@ -1,4 +1,5 @@
1
1
  /.bundle/
2
+ /.idea/
2
3
  /.yardoc
3
4
  /Gemfile.lock
4
5
  /_yardoc/
@@ -7,3 +8,5 @@
7
8
  /pkg/
8
9
  /spec/reports/
9
10
  /tmp/
11
+ /*.gem
12
+ /*.sublime*
data/README.md CHANGED
@@ -1,4 +1,8 @@
1
1
  # Sortinghat
2
+ [![Gem Version](https://badge.fury.io/rb/sortinghat.svg)](https://badge.fury.io/rb/sortinghat)
3
+ [![Total Gem Downloads](https://ruby-gem-downloads-badge.herokuapp.com/sortinghat?type=total)](https://rubygems.org/gems/sortinghat)
4
+ [![Build Status](https://travis-ci.org/praymann/sortinghat.svg?branch=master)](https://travis-ci.org/praymann/sortinghat?branch=master)
5
+ [![Build Status](https://travis-ci.org/praymann/sortinghat.svg?branch=develop)](https://travis-ci.org/praymann/sortinghat?branch=develop)
2
6
 
3
7
  Sortinghat is a unqiue Ruby gem that allows AWS AutoScaling instances to name themselves.
4
8
 
@@ -9,12 +13,12 @@ When the Sorting Hat is given specific arguments, it can find the gaps in curren
9
13
  It follows a specific pattern for hostnames/fqdn:
10
14
 
11
15
  ```
12
- [client]-[environment]-[type][prefix].[domain].com.
16
+ [client]-[environment]-[type][suffix]-[region].[domain].com.
13
17
  ```
14
18
  For example:
15
19
 
16
20
  ```
17
- nike-prod-nginx09.prod-nike.com
21
+ nike-prod-nginx09-us-west-2.prod-nike.com
18
22
  ```
19
23
 
20
24
  ## Installation:
@@ -31,8 +35,6 @@ It requires the following gems:
31
35
  * aws-sdk 2.1.2
32
36
  * pure_json
33
37
 
34
- The v2.1.2 dependency comes from the fact that as of this writting the latest codedeploy-agent (installed via .rpm) breaks if it does not have v2.1.2.
35
-
36
38
  During actually usage, the gem requires that the instance have the following IAM actions allowed via policy:
37
39
  * autoscaling:DescribeAutoScalingInstances
38
40
  * autoscaling:DescribeAutoScalingGroups
@@ -71,6 +73,11 @@ Run:
71
73
 
72
74
  $ bundle exec bin/sortinghat -h
73
75
 
76
+ ## Credits
77
+
78
+ Kudos to [nerk01](https://github.com/nerk01) for help and guidance with anything Ruby! He is also a contributor to this project.
79
+
80
+ Kudos to [jrbeilke](https://github.com/jrbeilke) for help and guidance with Ruby and the "[rubber duck debugging](https://en.wikipedia.org/wiki/Rubber_duck_debugging)" support.
74
81
 
75
82
  ## Contributing
76
83
 
data/bin/sortinghat CHANGED
@@ -5,13 +5,17 @@ require 'optparse'
5
5
 
6
6
  options = {}
7
7
 
8
+ # Default to being numbered instances
9
+ options[:numbered] = true
10
+
8
11
  parser = OptionParser.new do |opt|
9
- opt.banner = "Usage: sortinghat [OPTIONS]"
10
- opt.separator ""
11
- opt.separator "All options are required for the Sorting Hat to function."
12
- opt.separator "A trailing dot will be added to the zone should you forget it."
13
- opt.separator ""
14
- opt.separator "Options:"
12
+ opt.banner = 'Usage: sortinghat [OPTIONS]'
13
+ opt.separator ''
14
+ opt.separator 'All options except --numbered are required for the Sorting Hat to function.'
15
+ opt.separator 'The option --numbered is by default \'true\''
16
+ opt.separator 'A trailing dot will be added to the zone should you forget it.'
17
+ opt.separator ''
18
+ opt.separator 'Options:'
15
19
 
16
20
  opt.on("-c", "--client CLIENT", "Client name") do |client|
17
21
  options[:client] = client
@@ -26,13 +30,17 @@ parser = OptionParser.new do |opt|
26
30
  end
27
31
 
28
32
  opt.on("-r", "--region REGION", "Region name") do |region|
29
- options[:region] = region
33
+ options[:region] = region
30
34
  end
31
35
 
32
36
  opt.on("-z", "--zone DOMAIN", "Hosted Zone") do |zone|
33
37
  options[:zone] = zone
34
38
  end
35
39
 
40
+ opt.on('-n', '--[not-]numbered', 'Number suffix?') do |numbered|
41
+ options[:numbered] = numbered
42
+ end
43
+
36
44
  opt.on("-h", "--help", "Help menu") do
37
45
  puts parser
38
46
  exit 0
@@ -41,12 +49,6 @@ end
41
49
 
42
50
  parser.parse!
43
51
 
44
- if options.length < 5
45
- abort "All options are required."
46
- end
47
-
48
- this = Sortinghat::Banquet.new(options)
49
-
50
- this.dejavu?
52
+ abort 'All options are required.' if options.length < 5
51
53
 
52
- this.start!
54
+ Sortinghat::Banquet.assign_house(options)
@@ -5,12 +5,13 @@ require 'date'
5
5
 
6
6
  module Sortinghat
7
7
  class AWS
8
- def initialize( region = 'us-east-1' )
8
+ def initialize(region = 'us-east-1')
9
9
  # Be using this lots, make it an instance variable
10
10
  @region = region
11
11
 
12
12
  # Set a generic client for use
13
- @client = Aws::EC2::Client.new(region: @region)
13
+ @ec2_client = Aws::EC2::Client.new(region: @region)
14
+ @autoscale_client = Aws::AutoScaling::Client.new(region: @region)
14
15
 
15
16
  # Create a syslog for us to use as an instance variable
16
17
  @log = Syslog::Logger.new 'sortinghat'
@@ -18,35 +19,28 @@ module Sortinghat
18
19
 
19
20
  # Method to discover what auto-scaling group the current instance is in, then the instances in that group
20
21
  # Returns array of the Name tag values of the instances
21
- def discover()
22
- # Temporay array for use
23
- ids = Array.new
24
-
25
- # Start a new client
26
- autoscale = Aws::AutoScaling::Client.new( region: @region )
27
-
28
- # Use the client to describe this instance
29
- current = autoscale.describe_auto_scaling_instances({
30
- instance_ids: [grabinstanceid()],
31
- max_records: 1
32
- })
33
- @log.info("Grabbed current AutoScaling instance via aws-sdk")
34
-
22
+ def discover
35
23
  # Use the client to grab all instances in this auto-scaling group
36
- all = autoscale.describe_auto_scaling_groups({
37
- auto_scaling_group_names: [current.auto_scaling_instances[0].auto_scaling_group_name],
24
+ all = @autoscale_client.describe_auto_scaling_groups(
25
+ auto_scaling_group_names: [find_own_autoscale_name],
38
26
  max_records: 1
39
- })
40
- @log.info("Grabbed the instances of our AutoScaling group via aws-sdk")
27
+ )
28
+ @log.info('Grabbed the instances of our AutoScaling group via aws-sdk')
29
+
30
+ # Grab their hostname(s)
31
+ names = all.auto_scaling_groups[0].instances.map { |instance| idtoname(instance.instance_id) }
32
+ @log.info("Returning instances '#{names.join("','")}'")
41
33
 
42
- # Grab their instanceId(s)
43
- all.auto_scaling_groups[0].instances.each do |instance|
44
- ids << idtoname(instance.instance_id)
45
- end
46
- @log.info("Returning instances '#{ids.join("','")}'")
47
-
48
34
  # Return the ids
49
- ids
35
+ names
36
+ end
37
+
38
+ # Method to search for instances matching a hostname
39
+ # Returns array of instances
40
+ def search_hosts(hostname)
41
+ resp = @client.describe_instances(filters: [{ name: 'tag:Name', value: [hostname] }])
42
+ return resp.reservations unless resp.reservations.empty?
43
+ []
50
44
  end
51
45
 
52
46
  # Method to set the Name tag on the current instance
@@ -56,32 +50,21 @@ module Sortinghat
56
50
  resource = Aws::EC2::Resource.new(client: @client)
57
51
 
58
52
  # Use the resource, to find current instance, and set the Name tag
59
- resource.instance(grabinstanceid()).create_tags({
60
- tags: [
61
- {
62
- key: 'Name',
63
- value: hostname,
64
- },
65
- ]
66
- })
53
+ resource.instance(grabinstanceid)
54
+ .create_tags(tags: [{ key: 'Name', value: hostname }])
67
55
  @log.info("Set Name tag to #{hostname} via aws-sdk")
68
56
  end
69
57
 
70
58
  # Method to remove the Name tag, and set a temporary one
71
59
  # Returns nothing
72
- def removetag!()
60
+ def removetag!
73
61
  # Use the instance varible client to create a new Resource
74
62
  resource = Aws::EC2::Resource.new(client: @client)
75
63
 
76
64
  # Use the resource, to find current instance, and set the Name tag
77
- resource.instance(grabinstanceid()).create_tags({
78
- tags: [
79
- {
80
- key: 'Name',
81
- value: "sortinghat-#{rand(100)}",
82
- },
83
- ]
84
- })
65
+ hostname = "sortinghat-#{rand(100)}"
66
+ resource.instance(grabinstanceid)
67
+ .create_tags(tags: [{ key: 'Name', value: hostname }])
85
68
  @log.info("Set Name tag to temporary #{hostname} via aws-sdk")
86
69
  end
87
70
 
@@ -89,10 +72,10 @@ module Sortinghat
89
72
  # Returns nothing
90
73
  def setroute53(zone, fqdn)
91
74
  # Create a new client, and use it to update/insert our A record
92
- Aws::Route53::Client.new(region: @region).change_resource_record_sets({
75
+ Aws::Route53::Client.new(region: @region).change_resource_record_sets(
93
76
  hosted_zone_id: zonetoid(zone),
94
77
  change_batch: {
95
- comment: "Sorting Hat #{Date.today.to_s}",
78
+ comment: "Sorting Hat #{Date.today}",
96
79
  changes: [
97
80
  {
98
81
  action: 'UPSERT',
@@ -100,22 +83,18 @@ module Sortinghat
100
83
  name: fqdn,
101
84
  type: 'A',
102
85
  ttl: '30',
103
- resource_records: [
104
- {
105
- value: grabinstanceprivateip()
106
- },
107
- ],
108
- },
109
- },
110
- ],
111
- },
112
- })
86
+ resource_records: [{ value: grabinstanceprivateip }]
87
+ }
88
+ }
89
+ ]
90
+ }
91
+ )
113
92
  @log.info("Issued UPSERT to Route53 for #{fqdn}")
114
93
  end
115
94
 
116
- def privateip()
117
- return grabinstanceprivateip()
118
- end
95
+ def privateip
96
+ grabinstanceprivateip
97
+ end
119
98
 
120
99
  private
121
100
 
@@ -126,20 +105,30 @@ module Sortinghat
126
105
  end
127
106
 
128
107
  def zonetoid(hostedzone)
129
- resp = Aws::Route53::Client.new(region: @region).list_hosted_zones()
108
+ resp = Aws::Route53::Client.new(region: @region).list_hosted_zones
130
109
  resp.hosted_zones.each do |zone|
131
- if zone.name == hostedzone
132
- return zone.id
133
- end
110
+ return zone.id if zone.name == hostedzone
134
111
  end
135
112
  end
136
113
 
137
- def grabinstanceid()
138
- return Net::HTTP.get_response(URI.parse("http://169.254.169.254/latest/meta-data/instance-id")).body
114
+ def grabinstanceid
115
+ Net::HTTP.get_response(URI.parse('http://169.254.169.254/latest/meta-data/instance-id')).body
116
+ end
117
+
118
+ def grabinstanceprivateip
119
+ Net::HTTP.get_response(URI.parse('http://169.254.169.254/latest/meta-data/local-ipv4')).body
139
120
  end
140
121
 
141
- def grabinstanceprivateip()
142
- return Net::HTTP.get_response(URI.parse("http://169.254.169.254/latest/meta-data/local-ipv4")).body
122
+ def find_own_autoscale_name
123
+ # Use the client to describe this instances autoscale
124
+ current_as = @autoscale_client.describe_auto_scaling_instances(
125
+ instance_ids: [grabinstanceid],
126
+ max_records: 1
127
+ )
128
+ @log.info('Grabbed current AutoScaling instance via aws-sdk')
129
+
130
+ # Return current autoscale name
131
+ current_as.auto_scaling_instances[0].auto_scaling_group_name
143
132
  end
144
133
  end
145
134
  end
@@ -3,19 +3,22 @@ require 'fileutils'
3
3
 
4
4
  module Sortinghat
5
5
  class Banquet
6
+ def self.assign_house(options = {})
7
+ this = new(options)
8
+ this.dejavu?
9
+ this.start!
10
+ end
6
11
 
7
12
  # Creation method
8
13
  def initialize(options = {})
9
14
  # Check that we have write premissions
10
- checkpermissions()
15
+ checkpermissions
11
16
 
12
17
  # Create a syslog for us to use as an instance variable
13
18
  @log = Syslog::Logger.new 'sortinghat'
14
19
 
15
20
  # Append a trailing dot to the zone, if there isn't one
16
- if options[:zone][-1, 1] != '.'
17
- options[:zone] << '.'
18
- end
21
+ options[:zone] << '.' if options[:zone][-1, 1] != '.'
19
22
 
20
23
  # Save the options as instance variable
21
24
  @options = options
@@ -27,7 +30,7 @@ module Sortinghat
27
30
  # Method to figure out if we've been here before
28
31
  def dejavu?
29
32
  # Check for sentinel file
30
- if File.exists?('/etc/.sorted')
33
+ if File.exist?('/etc/.sorted')
31
34
  # We found it, log error and exit successfully
32
35
  @log.info('Found /etc/.sorted, refusing to sort.')
33
36
  exit 0
@@ -36,51 +39,25 @@ module Sortinghat
36
39
 
37
40
  # Main method of Sortinghat
38
41
  def start!
39
-
40
- # Best thing to avoid run conditions are to wait
41
- sleep rand(10)
42
-
43
- # Find out who is who, instances alive
44
- # If discover() returns an Array full of nil(s), alive will become an empty Array
45
- alive = cleanup(@aws.discover())
46
-
47
- # Given the alive instances, find our prefix
48
- # If alive an empty array, selection will return the number '1'
49
- @prefix = ensurezero(selection(alive))
50
-
51
- # Put together hostname/fqdn
52
- construction()
42
+ construct_hostname
53
43
 
54
44
  # Set the Name tag on this instance
55
45
  @aws.settag!(@hostname)
56
46
 
57
- # Find out who is who, instances alive
58
- # If discover() returns an Array full of nil(s), alive will become an empty Array
59
- alive = cleanup(@aws.discover())
60
-
61
- # Only enter recursion if the uniq() length of the alive array does not equal the actual length
62
- # On AutoScalingGroup initalization, the cleanup() should ensure the alive array is empty not nil so uniq() works
63
- unless alive.uniq.length == alive.length
64
- # There are duplicates, remove tag, wait, restart
65
- @aws.removetag!()
66
- sleep rand(10)
67
- start!()
68
- end
69
-
70
47
  # Register in DNS
71
48
  @aws.setroute53(@options[:zone], @fqdn)
72
49
 
73
50
  # Set the localhost hostname
74
- setlocal()
51
+ setlocal
75
52
 
76
53
  # Set /etc/hosts
77
- sethostsfile()
54
+ sethostsfile
78
55
 
79
56
  # Throw the hostname in /etc/sysconfig/httpd (if exists)
80
- givetohttpd()
57
+ givetohttpd
81
58
 
82
59
  # All done
83
- finish!()
60
+ finish!
84
61
  end
85
62
 
86
63
  # Last method of Sortinghat
@@ -92,7 +69,7 @@ module Sortinghat
92
69
  private
93
70
 
94
71
  # Method to check that we have write permissions to /etc/*
95
- def checkpermissions()
72
+ def checkpermissions
96
73
  unless File.stat('/etc/hosts').writable?
97
74
  # We found it, log error and exit successfully
98
75
  @log.error('Can not write to /etc, missing required permissions.')
@@ -103,71 +80,87 @@ module Sortinghat
103
80
  # Method to cleanup the array returned by aws.discover()
104
81
  # Remove nil values basically
105
82
  def cleanup(array)
106
- clean = array.reject { |item| item.nil? }
83
+ clean = array.reject(&:nil?)
107
84
  return [] if clean.empty?
108
85
  clean
109
86
  end
110
87
 
111
- # Method to consume the alive array and figure out what this instance's prefix should be
88
+ # Cconsume the alive array and return array of available suffix
112
89
  def selection(array)
113
- # If array is empty, just return 01
114
- return 1 if array.empty?
90
+ array = cleanup(array)
115
91
 
116
- # Array to store the numbers already taken
117
- taken = Array.new
92
+ # If array is empty, just return 01
93
+ return [1] if array.empty?
118
94
 
119
95
  # Filter the incoming array, find the numbers and store them in the taken Array
120
- array.each { |string| taken << string.scan(/\d./).join('').sub(/^0+/, '').to_i }
96
+ taken = array.map { |str| str[/^.*\D(\d{2,}).*/, 1].sub(/^0+/, '').to_i }
121
97
 
122
98
  # We have two digits, define our range of numbers
123
99
  limits = (1..99).to_a
124
100
 
125
- # Return the first value once we find what isn't taken in our range of numbers
126
- (limits - taken)[0]
101
+ # Return the avilable values once we find what isn't taken in our range of numbers
102
+ limits - taken
103
+ end
104
+
105
+ def construct_hostname
106
+ # Get array of hostnames in our scale group
107
+ scalegroup_hosts = @aws.discover
108
+
109
+ # determine the next available suffix
110
+ selection(scalegroup_hosts).find(method(:assignment_unclear)) do |candidate|
111
+ @suffix = ''
112
+ @suffix = ensurezero(candidate) if @options[:numbered]
113
+ construction
114
+ matches = @aws.search_hosts(@hostname)
115
+ matches.empty?
116
+ end
127
117
  end
128
118
 
129
- # Method to ensure our prefix always has a leading 0 if < 10
130
- def ensurezero(prefix)
131
- prefix < 10 ? prefix.to_s.rjust(2, "0") : prefix
119
+ # Method to ensure our suffix always has a leading 0 if < 10
120
+ def ensurezero(suffix)
121
+ return suffix.to_s.rjust(2, '0') if suffix < 10
122
+ suffix
132
123
  end
133
124
 
134
125
  # Method to construct our instance variables @hostname and @fqdn
135
- def construction()
136
- @hostname = "#{@options[:client]}-#{@options[:env]}-#{@options[:type]}#{@prefix.to_s}-#{@options[:region]}"
137
- @fqdn = "#{@options[:client]}-#{@options[:env]}-#{@options[:type]}#{@prefix.to_s}-#{@options[:region]}.#{@options[:zone]}"
126
+ def construction
127
+ @hostname = "#{@options[:client]}-#{@options[:env]}-#{@options[:type]}#{@suffix}-#{@options[:region]}"
128
+ @fqdn = "#{@options[:client]}-#{@options[:env]}-#{@options[:type]}#{@suffix}-#{@options[:region]}.#{@options[:zone]}"
129
+ end
130
+
131
+ def assignment_unclear
132
+ @suffix = ensurezero("#{rand(100)}")
133
+ construction
138
134
  end
139
135
 
140
136
  # Method to set the local hostname on this instance
141
- def setlocal()
137
+ def setlocal
142
138
  if system("hostnamectl set-hostname #{@fqdn}")
143
139
  @log.info("Set the localhost hostname to #{@fqdn}.")
144
140
  end
145
141
  end
146
142
 
147
- def sethostsfile()
143
+ def sethostsfile
148
144
  # Store the ip address so we only make one metadata call here
149
145
  privateip = @aws.privateip()
150
- if File.readlines('/etc/hosts').grep(/#{@hostname}|#{privateip}/).size < 1
146
+ if File.readlines('/etc/hosts').grep(/#{@hostname}|#{privateip}/).empty?
151
147
  File.open('/etc/hosts', 'a') do |file|
152
148
  file.puts "#{privateip} \t #{@hostname} #{@fqdn}"
153
149
  end
154
- @log.info("Added hostname(s) to /etc/hosts.")
150
+ @log.info('Added hostname(s) to /etc/hosts.')
155
151
  else
156
- @log.warn("The hostname(s) were already in /etc/hosts.")
152
+ @log.warn('The hostname(s) were already in /etc/hosts.')
157
153
  end
158
154
  end
159
155
 
160
- def givetohttpd()
156
+ def givetohttpd
161
157
  file = '/etc/sysconfig/httpd'
162
- if File.exists?(file)
163
- if File.readlines(file).grep(/HOSTNAME/).size < 1
164
- @log.info("Found #{file}, appending HOSTNAME=#{@hostname}.")
165
- File.open(file, 'a') do |file|
166
- file.puts "HOSTNAME=#{@hostname}"
167
- end
168
- else
169
- @log.warn("Found HOSTNAME already in #{file}")
170
- end
158
+ return unless File.exist?(file)
159
+ if File.readlines(file).grep(/HOSTNAME/).empty?
160
+ @log.info("Found #{file}, appending HOSTNAME=#{@hostname}.")
161
+ File.open(file, 'a') { |sysconfig| sysconfig.puts "HOSTNAME=#{@hostname}" }
162
+ else
163
+ @log.warn("Found HOSTNAME already in #{file}")
171
164
  end
172
165
  end
173
166
  end
@@ -1,3 +1,3 @@
1
1
  module Sortinghat
2
- VERSION = "0.3.3"
2
+ VERSION = '0.3.4.develop'.freeze
3
3
  end
data/sortinghat.gemspec CHANGED
@@ -31,6 +31,6 @@ Gem::Specification.new do |spec|
31
31
  spec.add_development_dependency "rake", "~> 10.0"
32
32
  spec.add_development_dependency "rspec"
33
33
 
34
- spec.add_runtime_dependency "aws-sdk", '2.1.2'
34
+ spec.add_runtime_dependency "aws-sdk", "~> 2.1.2"
35
35
  spec.add_runtime_dependency "json_pure"
36
36
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sortinghat
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3
4
+ version: 0.3.4.develop
5
5
  platform: ruby
6
6
  authors:
7
7
  - D. Pramann
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-01-21 00:00:00.000000000 Z
11
+ date: 2019-05-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -56,14 +56,14 @@ dependencies:
56
56
  name: aws-sdk
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - '='
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
61
  version: 2.1.2
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - '='
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: 2.1.2
69
69
  - !ruby/object:Gem::Dependency
@@ -118,12 +118,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
118
118
  version: '0'
119
119
  required_rubygems_version: !ruby/object:Gem::Requirement
120
120
  requirements:
121
- - - ">="
121
+ - - ">"
122
122
  - !ruby/object:Gem::Version
123
- version: '0'
123
+ version: 1.3.1
124
124
  requirements: []
125
125
  rubyforge_project:
126
- rubygems_version: 2.4.8
126
+ rubygems_version: 2.7.7
127
127
  signing_key:
128
128
  specification_version: 4
129
129
  summary: Have auto-scaling instances name themselves!