aws-watcher 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +7 -0
  2. data/bin/aws_watcher.rb +106 -0
  3. data/lib/aws-watcher.rb +35 -0
  4. metadata +216 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f28f50f0ca7431183991d62d6ace837e3cc4c99b
4
+ data.tar.gz: 06704407b72737f799420afd04406926fa945052
5
+ SHA512:
6
+ metadata.gz: 4aa9aae62d9199e876121220d4321aaa17c13d87986c26ae24fa167388e620f8587eb1054855b8eccc24cee8e3bf0a431d2817438ee55abaf87fa807d899ef2b
7
+ data.tar.gz: beb7e55a6c11aa2c6a09a48ea3f83b07b7d0519ce05ebbf55620c5ebfaf0b21b28d3c1215961b799905a4c9742b5a703489db434900fcbfad8c25e5ba0ae1d23
@@ -0,0 +1,106 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Listen for AWS CloudWatch Events EC2 running events delivered via SQS
4
+ # and removes events after nodes have sucessfully bootstrapped to Chef.
5
+ # Copyright (c) 2017 Ben Abrams
6
+ # Licensed under The MIT License
7
+ #
8
+
9
+ # ensure gems are present
10
+ begin
11
+ # aws-cleaner deps
12
+ require 'json'
13
+ require 'yaml'
14
+ require 'aws-sdk-core'
15
+ require 'chef-api'
16
+ require 'chronic'
17
+ require 'hipchat'
18
+ require 'rest-client'
19
+ require 'time'
20
+ require 'trollop'
21
+ require 'slack/poster'
22
+ require 'aws_cleaner/aws_cleaner.rb'
23
+ # aws_watcher deps
24
+ rescue LoadError => e
25
+ raise "Missing Gems: #{e}"
26
+ end
27
+
28
+ require_relative '../lib/aws-watcher.rb'
29
+
30
+ # config file
31
+ def config(file)
32
+ YAML.safe_load(File.read(file), [Symbol])
33
+ rescue StandardError => e
34
+ raise "Failed to open config file: #{e}"
35
+ end
36
+
37
+ # get options
38
+ opts = Trollop.options do
39
+ opt :config, 'Path to config file', type: :string, default: 'config.yml'
40
+ end
41
+
42
+ @config = config(opts[:config])
43
+
44
+ # initialize clients
45
+ @sqs_client = AwsCleaner::SQS.client(@config)
46
+ @chef_client = AwsCleaner::Chef.client(@config)
47
+
48
+ # start program in infinate loop
49
+ loop do
50
+ messages = @sqs_client.receive_message(
51
+ queue_url: @config[:sqs][:queue],
52
+ max_number_of_messages: 10,
53
+ visibility_timeout: 3
54
+ ).messages
55
+
56
+ puts "Got #{messages.size} messages"
57
+ messages.each_with_index do |message, index|
58
+ puts "Looking at message number #{index}"
59
+ body = AwsCleaner.new.parse(message.body)
60
+ id = message.receipt_handle
61
+ now = Time.now.utc
62
+ launch_time = Chronic.parse(body['time'])
63
+
64
+ unless body
65
+ AwsCleaner.new.delete_message(id, @config)
66
+ next
67
+ end
68
+
69
+ @instance_id = AwsCleaner.new.process_message(body)
70
+ chef_node = AwsCleaner::Chef.get_chef_node_name(@instance_id, @config)
71
+ elapsed_time = now - launch_time
72
+ p "launch_time: #{launch_time}"
73
+ p "now: #{now}"
74
+ # if the node exists in chef it hass bootstrapped
75
+ # so we can delete the message
76
+ if chef_node || !AwsWatcher::EC2.instance_alive?(@instance_id, @config)
77
+ p "instance: #{@instance_id} has bootstrapped, removing message from queue"
78
+ AwsCleaner.new.delete_message(id, @config)
79
+
80
+ end
81
+ p "instance: #{@instance_id}, launched: #{launch_time}, elapsed: #{elapsed_time}"
82
+ # if the elapsed time is less than how long we consider
83
+ # a 'normal' converge time that's ok we just move on and
84
+ # wait for another pass
85
+ if elapsed_time < @config[:bootstrap][:converged_by]
86
+ if ENV['LOG_LEVEL'] == 'DEBUG'
87
+ 'node elaspsed time is normal'
88
+ end
89
+ next
90
+ # if the elapsed time is greater than or equal then we need
91
+ # to do something although I am not sure what yet.
92
+ elsif elapsed_time >= @config[:bootstrap][:converged_by]
93
+ # we want to validate that the machine is still in aws
94
+ # and did not get terminated by something like an auto scale
95
+ # group or someone messing around in console
96
+ p 'node elaspsed time is too high'
97
+ notification = "node: #{@instance_id} has not checked in, "
98
+ notification += 'it should have converged by: '
99
+ notification += "#{@config[:bootstrap][:converged_by]} "
100
+ notification += 'and has been running since:and has been '
101
+ notification += "running since: #{elapsed_time}"
102
+ AwsCleaner::Notify.notify_chat(notification, @config)
103
+ end
104
+ end
105
+ sleep @config[:poll_time]
106
+ end
@@ -0,0 +1,35 @@
1
+ # main aws_watcher lib
2
+ class AwsWatcher
3
+ require 'aws_cleaner/aws_cleaner.rb'
4
+ module Chef
5
+ include AwsCleaner::Chef
6
+ end
7
+
8
+ module SQS
9
+ include AwsCleaner::SQS
10
+ end
11
+
12
+ module EC2
13
+ def self.client(config)
14
+ Aws::EC2::Client.new(config[:aws])
15
+ end
16
+
17
+ def self.instance_alive?(id, config)
18
+ AwsWatcher::EC2.client(config).describe_instance_attribute(
19
+ attribute: 'instanceType',
20
+ instance_id: id.to_s
21
+ )
22
+ true
23
+ rescue Aws::EC2::Errors::InvalidInstanceIDNotFound => e
24
+ p "instance: #{id} was not found."
25
+ if ENV['LOG_LEVEL'] == 'DEBUG'
26
+ p e
27
+ end
28
+ false
29
+ end
30
+ end
31
+
32
+ module Notify
33
+ include AwsCleaner::Notify
34
+ end
35
+ end
metadata ADDED
@@ -0,0 +1,216 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: aws-watcher
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ben Abrams
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-04-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.12'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.12'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '12.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '12.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.5'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.5'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubocop
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.46.0
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.46.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: aws-sdk-core
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '2.0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '2.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: chef-api
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.5'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.5'
97
+ - !ruby/object:Gem::Dependency
98
+ name: chronic
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '0.10'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '0.10'
111
+ - !ruby/object:Gem::Dependency
112
+ name: hipchat
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '1.5'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '1.5'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rest-client
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '2'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '2'
139
+ - !ruby/object:Gem::Dependency
140
+ name: slack-poster
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '2.2'
146
+ type: :runtime
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '2.2'
153
+ - !ruby/object:Gem::Dependency
154
+ name: trollop
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '2.1'
160
+ type: :runtime
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: '2.1'
167
+ - !ruby/object:Gem::Dependency
168
+ name: aws-cleaner
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: '2'
174
+ type: :runtime
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - "~>"
179
+ - !ruby/object:Gem::Version
180
+ version: '2'
181
+ description: AWS Watcher tracks EC2 instances being started to ensure they bootstrap
182
+ to chef
183
+ email: me@benabrams.it
184
+ executables:
185
+ - aws_watcher.rb
186
+ extensions: []
187
+ extra_rdoc_files: []
188
+ files:
189
+ - bin/aws_watcher.rb
190
+ - lib/aws-watcher.rb
191
+ homepage: https://github.com/majormoses/aws-watcher
192
+ licenses:
193
+ - MIT
194
+ metadata: {}
195
+ post_install_message:
196
+ rdoc_options: []
197
+ require_paths:
198
+ - lib
199
+ required_ruby_version: !ruby/object:Gem::Requirement
200
+ requirements:
201
+ - - ">="
202
+ - !ruby/object:Gem::Version
203
+ version: '0'
204
+ required_rubygems_version: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - ">="
207
+ - !ruby/object:Gem::Version
208
+ version: '0'
209
+ requirements: []
210
+ rubyforge_project:
211
+ rubygems_version: 2.4.5.1
212
+ signing_key:
213
+ specification_version: 4
214
+ summary: AWS Watcher tracks EC2 instances being started to ensure they bootstrap to
215
+ chef
216
+ test_files: []