Class: Qurd::Message

Inherits:
Object
  • Object
show all
Extended by:
Qurd::Mixins::Configuration
Includes:
Qurd::Mixins::AwsClients, Qurd::Mixins::Configuration
Defined in:
lib/qurd/message.rb

Overview

Convert an SQS auto scaling message to a more usable object

Examples:

SQS auto scaling message

{
  "Type" : "Notification",
  "MessageId" : "e4379a5a-e119-53f7-b6ef-d7dbd32d31fe",
  "TopicArn" : "arn:aws:sns:us-east-1:123456890:test-ScalingNotificationsTopic-HPPYDAYSAGAIN",
  "Subject" : "Auto Scaling: termination for group \"test2-AutoScalingGroup-1QDX3CNO5SU3D\"",
  "Message" : "{\"StatusCode\":\"InProgress\",\"Service\":\"AWS Auto Scaling\",\"AutoScalingGroupName\":\"test2-AutoScalingGroup-1QDX3CNO5SU3D\",\"Description\":\"Terminating EC2 instance: i-08e58cf8\",\"ActivityId\":\"93faaf3a-28cb-4982-a690-0a73c989ab1f\",\"Event\":\"autoscaling:EC2_INSTANCE_TERMINATE\",\"Details\":{\"Availability Zone\":\"us-east-1a\",\"Subnet ID\":\"subnet-3c3e0e14\"},\"AutoScalingGroupARN\":\"arn:aws:autoscaling:us-east-1:123456890:autoScalingGroup:4edb2535-5015-4b81-b668-88ecb0effcb7:autoScalingGroupName/test2-AutoScalingGroup-1QDX3CNO5SU3D\",\"Progress\":50,\"Time\":\"2015-03-16T19:33:08.181Z\",\"AccountId\":\"123456890\",\"RequestId\":\"93faaf3a-28cb-4982-a690-0a73c989ab1f\",\"StatusMessage\":\"\",\"EndTime\":\"2015-03-16T19:33:08.181Z\",\"EC2InstanceId\":\"i-08e58cf8\",\"StartTime\":\"2015-03-16T19:29:14.911Z\",\"Cause\":\"At 2015-03-16T19:29:14Z an instance was taken out of service in response to a ELB system health check failure.\"}",
  "Timestamp" : "2015-03-16T19:33:08.242Z",
  "SignatureVersion" : "1",
  "Signature" : "I+SE8tMiq13/wDTPTJnJvHYi3jSjChhYByJAsnhY0wGa+0lxXc18vPIn9hIT0tYRNWMcR/Xn1AUNsgHrLjzB93xukyKA2CDff08zIuP0l4Xle/FSEJzfkJ0FDqZnzelFuZ2PMtO3lf5UY7CWZg/wKJv6I9CNJF4Ll9YgvC8Moe/31VwJwNy4TRAWdBhDuRXLjbEHoFNGjaGquiduOGySrgRmm74d0P0zWj7IfWbqO6ReNG2ADrqw+Bhn6dAkkeFH+9vJZeKdUCgsXX8XCBHcWX+yAb4WJH90hdosLN12DCdn2AvNgQfoTdpDPkTHC+QcwfRs52d3MD2WLrUfBMBy0A==",
  "SigningCertURL" : "https://sns.us-east-1.amazonaws.com/SimpleNotificationService-d6d679a1d18e95c2f9ffcf11f4f9e198.pem",
  "UnsubscribeURL" : "https://sns.us-east-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-1:123456890:test-ScalingNotificationsTopic-HPPYDAYSAGAIN:bd850bb2-1a69-4456-a517-c645a26f54b2"
}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Qurd::Mixins::Configuration

qurd_config, qurd_configuration, qurd_logger, qurd_logger!

Methods included from Qurd::Mixins::AwsClients

#aws_client, #aws_retryable

Constructor Details

#initialize(attrs) ⇒ Message

Returns a new instance of Message.

Parameters:

Options Hash (attrs):

  • :aws_credentials (Aws::Credentials)
  • :name (String)
  • :queue_url (String)
  • :region (String)

    msg AWS SQS message

  • :message (Struct)

    AWS SQS message



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/qurd/message.rb', line 65

def initialize(attrs)
  @aws_credentials = attrs[:aws_credentials]
  @name = attrs[:name]
  @queue_url = attrs[:queue_url]
  @region = attrs[:region]
  @sqs_message = attrs[:message]

  @exceptions = []
  @failed = false
  @context = qurd_config.get_context(name: @name,
                                     queue_name: (@queue_url[/[^\/]+$/] rescue nil),
                                     instance_id: instance_id,
                                     message_id: message_id,
                                     action: action)

  qurd_logger.info "Received #{body.Subject} Cause #{message.Cause} Event #{message.Event}"
end

Instance Attribute Details

#aws_credentialsAws::Credentials (readonly)

Returns:

  • (Aws::Credentials)


51
52
53
# File 'lib/qurd/message.rb', line 51

def aws_credentials
  @aws_credentials
end

#contextCabin::Context (readonly)

Cabin::Channel logs messages as well as context. Context is retained until it is cleared.

Returns:

  • (Cabin::Context)

    Context data



51
52
53
54
55
56
# File 'lib/qurd/message.rb', line 51

attr_reader :aws_credentials,
:context,
:exceptions,
:name,
:queue_url,
:region

#exceptionsArray<Exception> (readonly)

Action exceptions

Returns:

  • (Array<Exception>)


51
52
53
54
55
56
# File 'lib/qurd/message.rb', line 51

attr_reader :aws_credentials,
:context,
:exceptions,
:name,
:queue_url,
:region

#nameString (readonly)

The Listener name

Returns:



51
52
53
54
55
56
# File 'lib/qurd/message.rb', line 51

attr_reader :aws_credentials,
:context,
:exceptions,
:name,
:queue_url,
:region

#queue_urlString (readonly)

The SQS url the message came from

Returns:



51
52
53
54
55
56
# File 'lib/qurd/message.rb', line 51

attr_reader :aws_credentials,
:context,
:exceptions,
:name,
:queue_url,
:region

#regionObject (readonly)

Returns the value of attribute region.



51
52
53
54
55
56
# File 'lib/qurd/message.rb', line 51

attr_reader :aws_credentials,
:context,
:exceptions,
:name,
:queue_url,
:region

Class Method Details

.add_accessor(name) ⇒ Object

Add setter and getter instances methods. If the get or set method is already defined, an exception will be raised.

Parameters:

  • name (Symbol)

    the name of the method to add



23
24
25
26
27
28
29
# File 'lib/qurd/message.rb', line 23

def self.add_accessor(name)
  if instance_methods.include?(name) ||
     instance_methods.include?("#{name}=")
    qurd_logger.warn "Can not replace a method! (#{name})"
  end
  attr_accessor name
end

Instance Method Details

#actionString

Convert the message.Event to an action

Returns:

  • (String)

    launch, launch_error, terminate, terminate_error, or test



163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/qurd/message.rb', line 163

def action
  case message.Event
  when 'autoscaling:EC2_INSTANCE_LAUNCH' then 'launch'
  when 'autoscaling:EC2_INSTANCE_LAUNCH_ERROR' then 'launch_error'
  when 'autoscaling:EC2_INSTANCE_TERMINATE' then 'terminate'
  when 'autoscaling:EC2_INSTANCE_TERMINATE_ERROR' then 'terminate_error'
  when 'autoscaling:TEST_NOTIFICATION' then 'test'
  else
    qurd_logger.info "Ignoring #{message.Event}"
    failed!
  end
end

#bodyHashie::Mash

Convert the SQS message body to a mash, keys include Type, MessageId, TopicArn, Subject, Message, Timestamp, SignatureVersion, Signature, SigningCertURL, UnsubscribeURL

Returns:

  • (Hashie::Mash)


87
88
89
90
91
# File 'lib/qurd/message.rb', line 87

def body
  @body ||= Hashie::Mash.new JSON.load(@sqs_message.body)
rescue JSON::ParserError
  @body = Hashie::Mash.new {}
end

#deleteObject

Delete an AWS SQS message



177
178
179
180
181
182
183
184
185
186
187
# File 'lib/qurd/message.rb', line 177

def delete
  qurd_logger.debug('Preparing to delete message')
  if failed? && qurd_configuration.save_failures
    qurd_logger.error 'Message failed processing, not deleting'
  elsif qurd_configuration.dry_run
    qurd_logger.info 'Dry run'
  else
    delete_message
  end
  context.clear
end

#failed!(e = nil) ⇒ Object

Record an action failure

Parameters:

  • e (Exception) (defaults to: nil)

    The exception



125
126
127
128
129
130
# File 'lib/qurd/message.rb', line 125

def failed!(e = nil)
  qurd_logger.debug 'Failed'
  @exceptions << e if e
  @failed = true
  nil
end

#failed?Boolean

Has processing the message failed

Returns:

  • (Boolean)


134
135
136
# File 'lib/qurd/message.rb', line 134

def failed?
  @failed == true
end

#inspectObject



190
191
192
193
194
195
196
197
198
# File 'lib/qurd/message.rb', line 190

def inspect
  format('#<Qurd::Message message_id:%s subject:%s cause:%s ' \
         'instance_id:%s instance:%s>',
         message_id,
         body.Subject,
         message.Cause,
         instance_id,
         instance)
end

#instance(tries = nil) ⇒ Struct|nil

Memozied EC2 instance. Caller must anticipate nil results, as instances may terminate before the message is received.

Parameters:

  • tries (Fixnum) (defaults to: nil)

    The number of times to retry the Aws API

Returns:

  • (Struct|nil)


142
143
144
145
# File 'lib/qurd/message.rb', line 142

def instance(tries = nil)
  return @instance if @instance
  @instance = aws_instance(tries)
end

#instance_idString

The SQS message’s EC2InstanceId

Returns:



107
108
109
# File 'lib/qurd/message.rb', line 107

def instance_id
  @instance_id ||= message.EC2InstanceId
end

#instance_nameObject

Memoize the instance’s Name tag



148
149
150
151
152
153
154
155
156
157
158
# File 'lib/qurd/message.rb', line 148

def instance_name
  return @instance_name if @instance_name
  @instance_name = instance.tags.find do |t|
    t.key == 'Name'
  end.value
  qurd_logger.debug("Found instance name '#{@instance_name}'")
  @instance_name
rescue NoMethodError
  qurd_logger.debug('No instance found')
  @instance_name = nil
end

#messageHashie::Mash

Convert body.Message to a mash, keys include StatusCode, Service, AutoScalingGroupName, Description, ActivityId, Event, Details AutoScalingGroupARN Progress Time AccountId RequestId, StatusMessage EndTime EC2InstanceId StartTime Cause

Returns:

  • (Hashie::Mash)


99
100
101
102
103
# File 'lib/qurd/message.rb', line 99

def message
  @message ||= Hashie::Mash.new JSON.load(body.Message)
rescue JSON::ParserError
  @message = Hashie::Mash.new {}
end

#message_idString

The body.MessageId

Returns:



113
114
115
# File 'lib/qurd/message.rb', line 113

def message_id
  @message_id ||= body.MessageId
end

#receipt_handleString

The SQS receipt_handle, used to delete a message

Returns:



119
120
121
# File 'lib/qurd/message.rb', line 119

def receipt_handle
  @sqs_message.receipt_handle
end