Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added enable flag for chef and set it to true by default #20

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
31 changes: 29 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ You will need to create a CloudWatch Events rule that's configured to send termi
1. Goto CloudWatch Events in the AWS Console
1. Click *Create rule*
1. Select event source of *EC2 instance state change notification*
1. Select specific state of *Terminated*
1. Select specific state of *Terminated* (optional will ignore events that are not *Terminated*)
1. Add a target of *SQS Queue* and set queue to the cloudwatch-events queue created in step one
1. Give the rule a name/description and click *Create rule*

Expand Down Expand Up @@ -87,9 +87,36 @@ To enable webhooks, add a `:webhooks:` section to the config:
Chat notifications can be sent when the webhook successfully executes. See
config.yml.sample for an example of the config.

### Node name provider lookup

By default aws-cleaner assumes that the lookup will be done against chef as this was one of its core intentions. This can be configured for sensu via config:
```
:general:
:node_name_provider: 'sensu'
```

### Chef

If switching the client lookup to sensu you will probably want to disable chef removal via the following config:
```
:chef:
:enable: false
```

When using chef you will want the following config:
```
:chef:
:url: 'https://chef.example.com/organizations/example'
:client: 'somebody'
:key: '/path/to/client.pem'
:enable: true
```

While we currently assume chef removal being desired is considered the default it may not always be so you should set `enable` to true to avoid a breaking change later.

### Sensu

By default aws-cleaner assumes that removing from sensu is desired as this was one of its core intentions. To allow people to leverage this without sensu you can disable it via config:
You can disable sensu via config as well to skip removing the client from sensu:
```
:sensu:
:enable: false
Expand Down
72 changes: 47 additions & 25 deletions bin/aws_cleaner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def logger(config)
logger
end

def webhook(id, instance_id)
def webhook(instance_id)
if @config[:webhooks]
@config[:webhooks].each do |hook, hook_config|
if AwsCleaner::Webhooks.fire_webhook(hook_config, @config, instance_id)
Expand All @@ -72,31 +72,26 @@ def webhook(id, instance_id)
@logger.info("Failed to run webhook #{hook}")
end
end
AwsCleaner.new.delete_message(id, @config)
end
end

def chef(id, instance_id, chef_node)
if chef_node
if AwsCleaner::Chef.remove_from_chef(chef_node, @chef_client, @config)
@logger.info("Removed #{chef_node} from Chef")
AwsCleaner.new.delete_message(id, @config)
end
def chef(instance_id, chef_node)
return unless @config[:chef][:enable]

if AwsCleaner::Chef.remove_from_chef(chef_node, @chef_client, @config)
@logger.info("Removed #{chef_node} from Chef")
else
@logger.info("Instance #{instance_id} does not exist in Chef, deleting message")
AwsCleaner.new.delete_message(id, @config)
@logger.info("Instance #{instance_id} does not exist in Chef")
end
end

def sensu(id, instance_id, chef_node)
def sensu(instance_id, sensu_node)
return unless @config[:sensu][:enable]
if AwsCleaner::Sensu.in_sensu?(chef_node, @config)
if AwsCleaner::Sensu.remove_from_sensu(chef_node, @config)
@logger.info("Removed #{chef_node} from Sensu")
else
@logger.info("Instance #{instance_id} does not exist in Sensu, deleting message")
end
AwsCleaner.new.delete_message(id, @config)

if AwsCleaner::Sensu.remove_from_sensu(sensu_node, @config)
@logger.info("Removed #{sensu_node} from Sensu")
else
@logger.info("Instance #{instance_id} does not exist in Sensu")
end
end

Expand All @@ -115,12 +110,25 @@ def closelog(message)
@sqs_client = AwsCleaner::SQS.client(@config)
@chef_client = AwsCleaner::Chef.client(@config)

# to provide backwards compatibility as this key did not exist previously
# to provide backwards compatibility as these keys did not exist previously
@config[:chef][:enable] = if @config[:chef][:enable].nil?
true
else
@config[:chef][:enable]
end
@config[:sensu][:enable] = if @config[:sensu][:enable].nil?
true
else
@config[:sensu][:enable]
end
@config[:general] = if @config[:general].nil?
''
end
@config[:general][:node_name_provider] = if @config[:general][:node_name_provider].nil?
'chef'
else
@config[:general][:node_name_provider]
end

# main loop
loop do
Expand All @@ -144,17 +152,31 @@ def closelog(message)
next
end

instance_id = AwsCleaner.new.process_message(body)
instance_id = AwsCleaner.new.process_message(body, @config)

if instance_id
chef_node = AwsCleaner::Chef.get_chef_node_name(instance_id, @config)
webhook(id, instance_id)
chef(id, instance_id, chef_node)
sensu(id, instance_id, chef_node)
node = case @config[:general][:node_name_provider]
when 'sensu'
AwsCleaner::Sensu.get_sensu_node_name(instance_id, @config)
else
AwsCleaner::Chef.get_chef_node_name(instance_id, @config)
end

if node
@logger.info("Instance #{instance_id} found, node name is #{node}.")

webhook(instance_id)
chef(instance_id, node)
sensu(instance_id, node)

@logger.info("All done with #{node}, deleting message.")
else
@logger.info("Instance #{instance_id} not found, deleting message.")
end
else
@logger.info('Message not relevant, deleting')
AwsCleaner.new.delete_message(id, @config)
end
AwsCleaner.new.delete_message(id, @config)
end

sleep(5)
Expand Down
3 changes: 3 additions & 0 deletions config.yml.sample
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
:general:
:node_name_provider: 'chef'
:aws:
# only region is required when using iam which is recommended
:access_key_id: 'AWS Access Key'
Expand All @@ -12,6 +14,7 @@
:url: 'https://chef.example.com/organizations/example'
:client: 'somebody'
:key: '/path/to/client.pem'
:enable: true
:hipchat:
:api_token: 'Hipchat API token'
:room: 'Notifications'
Expand Down
31 changes: 31 additions & 0 deletions lib/aws-cleaner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,37 @@ def self.remove_from_chef(node_name, chef, config)
end

module Sensu
# call the Sensu API to get the node name of the instance
def self.get_sensu_node_name(instance_id, config)
offset = 0
returned_clients = 100

while returned_clients == 100
response = RestClient::Request.execute(
url: "#{config[:sensu][:url]}/clients?limit=100&offset=#{offset}",
method: :get,
timeout: 5,
open_timeout: 5
)

clients = JSON.parse(response.body)
client = clients.find { |child| child['name'].include?(instance_id[2..-1]) }
client_name = if client.nil?
false
else
client['name']
end

break if client_name

returned_clients = clients.count
offset += 100
end

return false unless client_name
client_name
end

# check if the node exists in Sensu
def self.in_sensu?(node_name, config)
RestClient::Request.execute(
Expand Down