Skip to content

Commit

Permalink
feat: Add Sentinel example
Browse files Browse the repository at this point in the history
  • Loading branch information
tim775 committed Dec 18, 2021
1 parent ee936ab commit 8a8ce86
Show file tree
Hide file tree
Showing 6 changed files with 605 additions and 1 deletion.
59 changes: 58 additions & 1 deletion .github/workflows/examples_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,35 @@ jobs:
cp /tmp/infracost_comment.md
./testdata/multi_terraform_workspace_config_file_comment_golden.md
if: env.UPDATE_GOLDEN_FILES == 'true'
open-policy-agent:
name: Open Policy Agent
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Infracost
uses: ./setup
with:
api-key: ${{ secrets.INFRACOST_API_KEY }}
- name: Setup OPA
uses: infracost/setup-opa@v1
- name: Run Infracost
run: >-
infracost breakdown --path=examples/conftest/code/plan.json
--format=json --out-file=/tmp/infracost.json
- name: Run OPA
run: >-
opa eval --input /tmp/infracost.json -d
examples/opa/policy/policy.rego --format pretty "data.infracost.deny"
| tee /tmp/opa.out
- name: Check Policies
run: |
denyReasons=$(</tmp/opa.out)
if [ "$denyReasons" != "[]" ]; then
echo -e "::error::Policy check failed:\n$denyReasons"
exit 1
else
echo "::info::Policy check passed."
fi
private-terraform-module:
name: Private Terraform module
runs-on: ubuntu-latest
Expand Down Expand Up @@ -193,6 +222,34 @@ jobs:
cp /tmp/infracost_comment.md
./testdata/private-terraform-module_comment_golden.md
if: env.UPDATE_GOLDEN_FILES == 'true'
sentinel:
name: Sentinel
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Infracost
uses: ./setup
with:
api-key: ${{ secrets.INFRACOST_API_KEY }}
- name: Setup Sentinel
uses: innovationnorway/setup-sentinel@v1
- name: Run Infracost
run: >-
infracost breakdown --path=examples/sentinel/code/plan.json
--format=json --out-file=/tmp/infracost.json
- name: Run Sentinel
run: >-
sentinel apply -global breakdown="$(cat /tmp/infracost.json)"
examples/sentinel/policy/policy.policy | tee /tmp/sentinel.out
- name: Check Policies
run: |
result=$(</tmp/sentinel.out)
if [ "$result" != "Pass - policy.policy" ]; then
echo -e "::error::Policy check failed:\n$result"
exit 1
else
echo "::info::Policy check passed."
fi
slack:
name: Slack
runs-on: ubuntu-latest
Expand Down Expand Up @@ -398,7 +455,7 @@ jobs:
}
console.log(`percent-change: ${percentChange}`);
console.log(`cost-change: ${costChange}`);
console.log(`cost-change: ${costChange}`);
// Set the calculated diffs as outputs to be used in future steps
core.setOutput('absolute-percent-change', absolutePercentChange);
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ The [examples](examples) directory demonstrates how these actions can be used in
- [Thresholds](examples/thresholds): only post a comment when cost thresholds are exceeded
- [Conftest](examples/conftest): check Infracost cost estimates against policies using Conftest
- [OPA](examples/opa): check Infracost cost estimates against policies using Open Policy Agent
- [Sentinel](examples/sentinel): check Infracost cost estimates against policies using Hashicorp's Sentinel
- [Slack](examples/slack): send cost estimates to Slack

## Actions
Expand Down
1 change: 1 addition & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ All examples post a single comment on pull requests, which gets updated as more
- [Thresholds](thresholds): only post a comment when cost thresholds are exceeded
- [Conftest](conftest): check Infracost cost estimates against policies using Conftest
- [OPA](opa): check Infracost cost estimates against policies using Open Policy Agent
- [Sentinel](sentinel): check Infracost cost estimates against policies using Hashicorp's Sentinel
- [Slack](slack): send cost estimates to Slack

See the [contributing](../CONTRIBUTING.md) guide if you'd like to add an example.
97 changes: 97 additions & 0 deletions examples/sentinel/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Sentinel Example

This example shows how to write cost policies with Hashicorp's [Sentinel](https://www.hashicorp.com/sentinel). For simplicity, this example evaluates policies with the Sentinel CLI (a.k.a. Sentinel Simulator).

When the policy checks pass, the GitHub Action step called "Check Policies" passes and outputs `Policy check passed.` in the action logs. When the policy checks fail, that step fails and the action logs show the Sentinel output indicating failing policies.

Create a policy file (e.g. `policy.policy) that checks a global parameter 'breakdown' containing the Infracost JSON:
```policy
import "strings"
limitTotalDiff = rule {
float(breakdown.totalMonthlyCost) < 1500
}
awsInstances = filter breakdown.projects[0].breakdown.resources as _, resource {
strings.split(resource.name, ".")[0] is "aws_instance"
}
limitInstanceCost = rule {
all awsInstances as _, instance {
float(instance.hourlyCost) <= 2.00
}
}
instanceBaseCost = func(instance) {
cost = 0.0
for instance.costComponents as cc {
cost += float(cc.hourlyCost)
}
return cost
}
instanceIOPSCost = func(instance) {
cost = 0.0
for instance.subresources as sr {
for sr.costComponents as cc {
if cc.name == "Provisioned IOPS" {
cost += float(cc.hourlyCost)
}
}
}
return cost
}
limitInstanceIOPSCost = rule {
all awsInstances as _, instance {
instanceIOPSCost(instance) <= instanceBaseCost(instance)
}
}
main = rule {
limitTotalDiff and
limitInstanceCost and
limitInstanceIOPSCost
}
```

Then use Sentinel to test infrastructure cost changes against the policy.

[//]: <> (BEGIN EXAMPLE)
```yml
name: Sentinel
on: [pull_request]

jobs:
sentinel:
name: Sentinel
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2

- name: Setup Infracost
uses: infracost/actions/setup@v1
with:
api-key: ${{ secrets.INFRACOST_API_KEY }}

- name: Setup Sentinel
uses: innovationnorway/setup-sentinel@v1

- name: Run Infracost
run: infracost breakdown --path=examples/sentinel/code/plan.json --format=json --out-file=/tmp/infracost.json

- name: Run Sentinel
run: sentinel apply -global breakdown="$(cat /tmp/infracost.json)" examples/sentinel/policy/policy.policy | tee /tmp/sentinel.out

- name: Check Policies
run: |
result=$(</tmp/sentinel.out)
if [ "$result" != "Pass - policy.policy" ]; then
echo -e "::error::Policy check failed:\n$result"
exit 1
else
echo "::info::Policy check passed."
fi
```
[//]: <> (END EXAMPLE)
Loading

1 comment on commit 8a8ce86

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💰 Infracost estimate: monthly cost will increase by $110,130 📈

Project Previous New Diff
infracost/infracost/examples/terraform/plan.json $0 $55,065 +$55,065
infracost/infracost/examples/terraform/plan.json $0 $55,065 +$55,065
All projects $0 $110,130 +$110,130
Infracost output
Project: infracost/infracost/examples/terraform/plan.json

+ aws_instance.web_app
  +$55,065

    + Instance usage (Linux/UNIX, on-demand, m5.4xlarge)
      +$41,570

    + root_block_device
    
        + Storage (general purpose SSD, gp2)
          +$371

    + ebs_block_device[0]
    
        + Storage (provisioned IOPS SSD, io1)
          +$9,268
    
        + Provisioned IOPS
          +$3,856

+ aws_lambda_function.hello_world
  Monthly cost depends on usage

    + Requests
      Monthly cost depends on usage
        +$14.83 per 1M requests

    + Duration
      Monthly cost depends on usage
        +$0.0012357988 per GB-seconds

Monthly cost change for infracost/infracost/examples/terraform/plan.json
Amount:  +$55,065 ($0.00 → $55,065)

──────────────────────────────────
Project: infracost/infracost/examples/terraform/plan.json

+ aws_instance.web_app
  +$55,065

    + Instance usage (Linux/UNIX, on-demand, m5.4xlarge)
      +$41,570

    + root_block_device
    
        + Storage (general purpose SSD, gp2)
          +$371

    + ebs_block_device[0]
    
        + Storage (provisioned IOPS SSD, io1)
          +$9,268
    
        + Provisioned IOPS
          +$3,856

+ aws_lambda_function.hello_world
  Monthly cost depends on usage

    + Requests
      Monthly cost depends on usage
        +$14.83 per 1M requests

    + Duration
      Monthly cost depends on usage
        +$0.0012357988 per GB-seconds

Monthly cost change for infracost/infracost/examples/terraform/plan.json
Amount:  +$55,065 ($0.00 → $55,065)

──────────────────────────────────
Key: ~ changed, + added, - removed

4 cloud resources were detected:
∙ 4 were estimated, 4 include usage-based costs, see https://infracost.io/usage-file
Is this comment useful? Yes, No

Please sign in to comment.