#Cloud Monitoring Pairing
To authenticate with the Rackspace Cloud, execute the following curl command substituting USERNAME and API_KEY with the appropriate values:
curl -s https://identity.api.rackspacecloud.com/v2.0/tokens -X 'POST' \
-d '{"auth":{"RAX-KSKEY:apiKeyCredentials":{"username":"USERNAME", "apiKey":"API_KEY"}}}' \
-H "Content-Type: application/json" | python -m json.tool
This will provide you with your access token and a list of end points for all of our avaliable services.
From the list entities documentation you can see we want to hit the /entities URI using the GET method. Combining this with our service endpoint and access token we get the following curl command:
curl -s https://monitoring.api.rackspacecloud.com/v1.0/TENANT_ID/entities -H "X-Auth-Token:ACCESS_TOKEN" | python -m json.tool
This returns the following:
{
"metadata": {
"count": 75,
"limit": 100,
"marker": null,
"next_href": null,
"next_marker": null
},
"values": [
{
"agent_id": null,
"created_at": 1377640854996,
"id": "en01YHC2X5",
"ip_addresses": {
"private0_v4": "10.208.152.138"
},
"label": "aseb74d9ed-webhead",
"managed": false,
"metadata": null,
"updated_at": 1377640854996,
"uri": "https://ord.servers.api.rackspacecloud.com/TENANT_ID/servers/87ca85b1-e192-4744-9713-ef7922850ccc"
}, ...
Now that we understand the underlying concept, lets see how this is implemented in fog.
Start by firing up irb or pry and create a Rackspace monitoring service as follows:
require 'fog'
service = Fog::Rackspace::Monitoring.new :rackspace_username => RACKSPACE_USER_NAME,
:rackspace_api_key => RACKSPACE_API
We will start off by looking at the low level request layer. To see the avaliable methods for you can execute service.requests.
This returns the following:
:list_agent_tokens, :list_alarms, :list_alarm_examples, :list_checks, :list_entities, :list_metrics, :list_data_points, :list_check_types, :list_overview, :list_notification_plans, :get_agent_token, :get_alarm, :get_alarm_example, :get_check, :get_entity, :create_agent_token, :create_alarm, :create_check, :create_entity, :update_check, :update_entity, :update_alarm, :delete_agent_token, :delete_alarm, :delete_check, :delete_entity, :evaluate_alarm_example]
We are interested in the list_entities method. Executing service.list_entities returns the following:
<Excon::Response:0x007f8fc7461ff0 @data={:body=>{"values"=>[{"id"=>"en01YHC2X5", "label"=>"aseb74d9ed-webhead", "ip_addresses"=>{"private0_v4"=>"10.208.152.138"}, "metadata"=>nil, "managed"=>false, "uri"=>"https://ord.servers.api.rackspacecloud.com/772045/servers/87ca85b1-e192-4744-9713-ef7922850ccc", "agent_id"=>nil, "created_at"=>1377640854996, "updated_at"=>1377640854996}, ..}]}}, :headers=>{"Date"=>"Thu, 29 Aug 2013 15:12:18 GMT", "Content-Type"=>"application/json; charset=UTF-8", "X-RateLimit-Limit"=>"50000", "X-RateLimit-Remaining"=>"49694", "X-RateLimit-Window"=>"24 hours", "X-RateLimit-Type"=>"global", "X-Response-Id"=>".rh-3puT.h-dfw1-maas-prod-api1.r-qQA9Cj1w.c-5580568.ts-1377789138662.v-0b83008", "X-LB"=>"dfw1-maas-prod-api0", "Vary"=>"Accept-Encoding", "Transfer-Encoding"=>"chunked"}, :status=>200, :remote_ip=>"74.205.66.16"}>
This is the implementation of the list_entities method:
module Fog
module Rackspace
class Monitoring
class Real
def list_entities(options={})
request(
:expects => [200, 203],
:method => 'GET',
:path => 'entities',
:query => options
)
end
end
end
end
end
Notice how we are passing our uri and http method to the request method. We also put an expectation that we are expecting to get back an http 200 or http 203 back. Anything other than this will result in an Excon exception being thrown.
The request method is defined on the `Fog::Rackspace::Monitoring' class. This method is show here:
def request(params, parse_json = true, &block)
super(params, parse_json, &block)
rescue Excon::Errors::BadRequest => error
raise BadRequest.slurp(error, self)
rescue Excon::Errors::Conflict => error
raise Conflict.slurp(error, self)
rescue Excon::Errors::NotFound => error
raise NotFound.slurp(error, self)
rescue Excon::Errors::ServiceUnavailable => error
raise ServiceUnavailable.slurp(error, self)
rescue Excon::Errors::InternalServerError => error
raise InternalServerError.slurp(error, self)
rescue Excon::Errors::HTTPStatusError => error
raise ServiceError.slurp(error, self)
end
The request method in the super class more or less handles all the heavy lifting and can be found here. It takes care of setting the X-Auth-Token header, picking the service end point, as well as renewing expired tokens.
The request layer provides a one to one mapping between requests and the remote cloud. The model layer provides a more generalized object based abstraction.
At the center of this abstraction are collections. You can see a list of collections by executing service.collections. The collections for the monitoring servers are show below:
[:entities, :checks, :alarms, :alarm_examples, :agent_tokens, :metrics, :data_points, :check_types]
To access the list of entities from the collection layer we would call service.entities.all or we can lazly retrieve this by executing service.entities.
The model layer will typically have an implementation for both the collection and the associated model.
Shown below is the code for the all method on the Entities collection:
def all(options={})
data = service.list_entities(options).body
marker = data['metadata']['next_marker']
load(data['values'])
end
You can see that under the covers the model layer uses the request layer. In fact, the model layer should never make a direct http call to the underlying cloud. One the request has been made it is pass along to the load method. This will instantiate the underlying model and populate all of the associated model attributes.
Below you can see the attribute declaration of the Entity model:
identity :id
attribute :label
attribute :metadata
attribute :ip_addresses
attribute :agent_id
attribute :managed, :default => false
attribute :uri
Fog automatically assumes that the attribute name maps to the object json. The attributes mechanism can be found here
Fog uses shindo for testing. You can find more information about shindo testing here.
Shindo tests are executed as follows:
bundle exec shindo <testname>
To skip prompts you can optionally use the shindont binary. To execute it with mocks you can preface your command with FOG_MOCK=true.
To see all of fog's HTTP traffic you can set the EXCON_DEBUG variable to true as follows:
EXCON_DEBUG=true <command>