Overview

In addition to built-in Cost, Security, Operational, and Compliance policies (See RightScale Policies), RightScale supports for creating custom policies using the new and purpose built Policy Template Language. These policies can then be uploaded and applied in RightScale just like the pre-built ones.

Check out a couple sample policies below and learn more about the Policy Template Language.

Sample Policy: Reserved Instance Expiration

This sample code shows a policy around Reserved Instance expiration. It outlines key constructs needed to write a policy.

Input Parameters:

  • Number of days before the RI expires that you want to trigger an incident
  • Email address to alert when the policy triggers an incident
  • Email address to alert when the incident is resolved (eg: RI is re-purchased)

Actions:

  • Email alert

Policy Template Code

name "Expired Reserved Instances"
rs_pt_ver 20180301
type "policy"
short_description "A policy that sends email notifications before reserved instances expire. See the [README](https://github.com/rightscale/policy_templates/tree/master/cost/aws/reserved_instances/expiration) and [docs.rightscale.com/policies](https://docs.rightscale.com/policies/) to learn more."
long_description "Version: 1.2"
severity "medium"
category "Cost"

permission "optima" do
  label "Access Optima Resources"
  resources "rs_optima.aws_reserved_instances"
  actions "rs_optima.index"
end

parameter "param_heads_up_days" do
  type "number"
  label "Number of days to prior to expiration date to trigger incident"
end

parameter "param_escalate_to" do
  type "list"
  label "Email addresses of the recipients you wish to notify"
end

auth "auth_rs", type: "rightscale"

datasource "ds_reservations" do
  request do
    auth $auth_rs
    host "optima.rightscale.com"
    path join(["/api/reco/orgs/",rs_org_id,"/aws_reserved_instances"])
  end
  result do
    encoding "json"
    collect jmes_path(response,"[*]") do
      field "end_datetime", jmes_path(col_item,"end_datetime")
      field "account_name", jmes_path(col_item,"account_name")
      field "account_id", jmes_path(col_item,"account_id")
      field "region", jmes_path(col_item,"region")
      field "instance_type", jmes_path(col_item,"instance_type")
      field "instance_count", jmes_path(col_item,"number_of_instances")
    end
  end
end

escalation "alert" do
  email $param_escalate_to
end

policy "ri_expiration" do
  validate_each $ds_reservations do
    summary_template "Reserved instances are nearing expiration."
    detail_template <<-EOS
# Reserved Instance Expiration

| Account | Region | Instance Type | Instance Count | End Time |
| ------- | ------ | ------------- | -------------- | -------- |
{{ range data -}}
| {{ .account_name }}({{ .account_id }}) | {{.region}} | {{.instance_type}} | {{.instance_count}} | {{.end_datetime}} |
{{ end -}}

EOS

    escalate $alert
    check gt(dec(to_d(val(item, "end_datetime")), now), prod($param_heads_up_days, 24*3600))
  end
end

Sample Policy: Instance Quota under 1000

Following policy enforces that no more than 1,000 instances are running in the project:

Input Parameters:

  • Email address to alert when the policy triggers an incident

Actions:

  • Email alert

Policy Template Code

It's not a mandatory requirement but we recommend using .pt as the file extension for policy templates.

name "Instance Quota"
rs_pt_ver 20180301
type "policy"
short_description "Limit the total number of VMs running in a project."
severity "low"
category "Custom"

parameter "param_escalate_to" do
  type "list"
  label "Email addresses of the recipients you wish to notify"
end

# Permissions required to apply the policy
permission "access_cm" do
  label "List Instances"
  resources "rs_cm.instances"
  actions "rs_cm.index"
end

# Retrieve all the clouds registered in the project.
resources "clouds", type: "rs_cm.clouds"

# Retrieve all operational instances across all clouds.
resources "instances", type: "rs_cm.instances" do
   iterate @clouds
   cloud_href href(iter_item)
   filter do
      state "operational"
   end
end

# Send an email when a validation fails
escalation "email" do
  email $param_escalate_to
end

# The actual policy definition
policy "instance_quota" do
   # The policy validates the "instances" resources
   validate @instances do
      # Define the templates used to render the incident text details
      summary_template "Instance Quota Exceeded"
      detail_template "There are {{len data}} instances which is more than 1,000."
      # Use the "email" escalation on validation failure
      escalate $email
      # The check being performed by this validation (there can be more than one)
      check lt(size(data), 1000)
   end
end

Testing and Debugging

Following are a few ways to quickly test and debug your custom policies.

Policy debug log

Whenever a policy is applied it automatically creates a debug log that can be viewed by users with the policy designer role in the given account. The debug log displays the following information as the policy is evaluated:

  • Outgoing http requests including headers, body, and query parameters.
  • Resources, Datasource, and JavaScript data as its evaluated.
  • console.log and console.dir statements from JavaScript.
  • Info about failed validation/check statements.

Resources

  • Test against RightScale API directly using your favorite mechanism.
  • Postman or rsc tool or Self-Service CWF Console.

“DataSources” - API based

  • Test against the given API directly

“DataSources” - JavaScript based

  • Policy JavaScript can be tested against “Otto” - a Golang JavaScript interpretor
go get -v github.com/robertkrimen/otto/otto

Escalation and Resolution Actions

  • Test RCL in Self-Service CWF Console
  • Create logging calls to Audit Entries. These entries can be found in Cloud Management > Reports > Audit entries
define myaction($data) do
  $$debug = true
  call sys_log('data',$data)
end

define sys_log($subject, $detail) do
  if $$debug
    rs_cm.audit_entries.create(
      notify: "None",
      audit_entry: {
        auditee_href: @@account,
        summary: $subject,
        detail: $detail
      }
    )
  end
end

Force policy to create an Incident to dump data

  • Use following validation check in your policy
check eq(0,1)