Validations¶
A validation performs some action and then checks the results of that action against a set of expectations. Alarmageddon comes with validations for checking the results of HTTP calls, checking the output of SSH commands, and checking the length of RabbitMQ queues.
All validations accept a priority
argument. This should be one of Priority.LOW
, Priority.NORMAL
, or Priority.CRITICAL
. This priority level is used to determine whether or not a publisher should publish the results of the validation.
HTTP¶
You can create HttpValidations for various HTTP methods:
HttpValidation.get("http://www.google.com")
HttpValidation.post("http://www.google.com",data={key:value})
HttpValidation.put("http://www.google.com"data={key:value})
HttpValidation.options("http://www.google.com")
HttpValidation.head("http://www.google.com")
You can change the timeout length:
HttpValidation.get("http://www.google.com", timeout=10)
Or designate a number of retry attempts:
HttpValidation.get("http://www.google.com", retries=10)
You can supply custom headers:
header = {"Authorization":"value"}
HttpValidation.get("http://www.google.com", headers=header)
If you’ve created a validation that you would like to apply to multiple hosts:
validation = HttpValidation.get("http://www.google.com")
hosts = ["http://www.bing.com","http://www.yahoo.com"]
new_validations = validation.duplicate_with_hosts(hosts)
An example of expectations on HttpValidations, where we expect to get either a 200 or 404 status code, and expect the result to contain JSON with the designated value:
validation = HttpValidation.get("url")
validation.expect_status_codes([200,404])
validation.expect_json_property_value("json.path.to.value","expected")
expect_json_property_value
accepts query string that allows you to pluck values from json. Consider the following json document
{“abc”: “123”, “another”: {“nested”: “entry”}, “alpha”: {“array”: [1, 2, 3, 4]}}
abc
will reference "123"
another.nested
will reference "entry"
array[4]
will reference 4
array[*]
will reference [1, 2, 3, 4]
SSH¶
To perform validations over SSH, you’ll need to supply the appropriate credentials:
ctx = SshContext("username","keyfile_path")
You can check the average load:
LoadAverageValidation(ctx).expect_max_1_minute_load(5, hosts=['127.0.0.1'])
You can verify that an upstart service is running:
UpstartServiceValidation(ctx, "service_name", hosts=['127.0.0.1'])
But ultimately, the above are just convenience classes for common use cases - you can perform arbitrary commands and check the output:
validation = SshCommandValidation(ctx, "validation name", "ps -ef | grep python", hosts=['127.0.0.1'])
validation.expect_output_contains("python")
Cassandra¶
Cassandra validations are a special case of SSH validations:
CassandraStatusValidation(ssh_ctx, hosts=['127.0.0.1'])
Kafka¶
Kafka validations will inspect your kafka partitions and leader elections. If a single partition has multiple leaders the validation will fail:
KafkaStatusValidation(ssh_ctx, zookeeper_nodes='127.0.0.1:2181,127.0.0.2:2181,127.0.0.3:2181',hosts=['127.0.0.1'])
RabbitMQ¶
As with SSH, you have to supply credentials for RabbitMQ Validations:
ctx = RabbitMqContext("127.0.0.1",80,"username","password")
Once you have the context, you can construct validations that check that the number of messages in a queue is less than some value. For example, the following will fail if the queue “queue_name” has more than 1000 messages in it:
RabbitMqValidation(ctx, "validation name", "queue_name", 1000)
Graphite¶
You also need a context for Graphite:
ctx = GraphiteContext("127.0.0.1")
Given the context, you can check statistics on various Graphite readings:
validation = GraphiteValidation(ctx, "validation name", "Errors")
validation.expect_average_in_range(1,10)
Validation Groups and GroupValidations¶
You may have a set of tests where individual failures are minor but multiple failures indicate a problem (eg, machines behind an HAProxy). Alarmageddon Validations include the notion of a validation group, which indicate that a set of validations belong together:
validations = []
validations.append(HttpValidation.get("http://www.google.com",group="a").expect_status_codes([200]))
validations.append(HttpValidation.get("http://www.yahoo.com",group="a").expect_status_codes([200]))
validations.append(HttpValidation.get("http://www.bing.com",group="a").expect_status_codes([200]))
In this case, we have three validations that belong to the validation group “a”. Now that we have a group, we can create a GroupValidation that contains expectations about the results of other validations:
validations.append(GroupValidation("Group a Validation", "a", normal_threshold=1, critical_threshold=2))
This new validation does not have an explicit priority level. Rather, it defaults to LOW priority. If the number of failures in group “a” reaches the normal_threshold, the validation will be considered a failure and the priority will become NORMAL. If it reaches the critical_threshold, the priority will become CRITICAL (and the validation will still be a failure).
You can create GroupValidations on groups of GroupValidations. The only difference is that an order
parameter must be passed, to ensure that the tests are run in the correct order:
validations.append(GroupValidation("Group a Validation", "a", normal_threshold=1, critical_threshold=2, group="c"))
validations.append(GroupValidation("Group b Validation", "b", normal_threshold=1, critical_threshold=2, group="c"))
validations.append(alarmageddon.validation.GroupValidation("Group c Validation", "c", normal_threshold=2, order=2))