├── .editorconfig
├── .github
├── CODEOWNERS
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ ├── bug_report.yml
│ ├── config.yml
│ ├── feature_request.md
│ ├── feature_request.yml
│ └── question.md
├── PULL_REQUEST_TEMPLATE.md
├── mergify.yml
├── renovate.json
├── settings.yml
└── workflows
│ ├── branch.yml
│ ├── chatops.yml
│ ├── release.yml
│ └── scheduled.yml
├── .gitignore
├── LICENSE
├── README.md
├── README.yaml
├── atmos.yaml
├── context.tf
├── examples
├── advanced_features
│ ├── api_integration.tf
│ ├── context.tf
│ ├── fixtures.tfvars
│ ├── integration_action.tf
│ ├── main.tf
│ ├── outputs.tf
│ ├── team.tf
│ ├── variables.tf
│ └── versions.tf
├── alert_policy
│ ├── context.tf
│ ├── fixtures.tfvars
│ ├── main.tf
│ ├── outputs.tf
│ ├── variables.tf
│ └── versions.tf
├── api_integration
│ ├── context.tf
│ ├── fixtures.tfvars
│ ├── main.tf
│ ├── outputs.tf
│ ├── variables.tf
│ └── versions.tf
├── complete
│ ├── api_integration.tf
│ ├── context.tf
│ ├── escalation.tf
│ ├── fixtures.tfvars
│ ├── main.tf
│ ├── outputs.tf
│ ├── service.tf
│ ├── service_incident_rule.tf
│ ├── team.tf
│ ├── team_routing_rule.tf
│ ├── user.tf
│ ├── variables.tf
│ └── versions.tf
├── config
│ ├── context.tf
│ ├── fixtures.tfvars
│ ├── main.tf
│ ├── outputs.tf
│ ├── resources
│ │ ├── alert_policies.yaml
│ │ ├── api_integrations.yaml
│ │ ├── escalations.yaml
│ │ ├── integration_actions.yaml
│ │ ├── notification_policies.yaml
│ │ ├── schedule_rotations.yaml
│ │ ├── schedules.yaml
│ │ ├── service_incident_rules.yaml
│ │ ├── services.yaml
│ │ ├── team_routing_rules.yaml
│ │ ├── teams.yaml
│ │ └── users.yaml
│ ├── variables.tf
│ └── versions.tf
├── escalation
│ ├── context.tf
│ ├── fixtures.tfvars
│ ├── main.tf
│ ├── outputs.tf
│ ├── variables.tf
│ └── versions.tf
├── integration_action
│ ├── context.tf
│ ├── fixtures.tfvars
│ ├── main.tf
│ ├── outputs.tf
│ ├── variables.tf
│ └── versions.tf
├── notification_policy
│ ├── context.tf
│ ├── fixtures.de_duplication_action.tfvars
│ ├── fixtures.delay_action.tfvars
│ ├── main.tf
│ ├── outputs.tf
│ ├── variables.tf
│ └── versions.tf
├── schedule
│ ├── context.tf
│ ├── fixtures.tfvars
│ ├── main.tf
│ ├── outputs.tf
│ ├── variables.tf
│ └── versions.tf
├── team
│ ├── context.tf
│ ├── fixtures.tfvars
│ ├── main.tf
│ ├── outputs.tf
│ ├── variables.tf
│ └── versions.tf
├── team_routing_rule
│ ├── context.tf
│ ├── fixtures.tfvars
│ ├── main.tf
│ ├── outputs.tf
│ ├── variables.tf
│ └── versions.tf
└── user
│ ├── context.tf
│ ├── fixtures.tfvars
│ ├── main.tf
│ ├── outputs.tf
│ ├── variables.tf
│ └── versions.tf
├── main.tf
├── modules
├── alert_policy
│ ├── README.md
│ ├── context.tf
│ ├── main.tf
│ ├── outputs.tf
│ ├── variables.tf
│ └── versions.tf
├── api_integration
│ ├── README.md
│ ├── context.tf
│ ├── main.tf
│ ├── outputs.tf
│ ├── variables.tf
│ └── versions.tf
├── config
│ ├── README.md
│ ├── alert_policies.tf
│ ├── api_integrations.tf
│ ├── context.tf
│ ├── escalations.tf
│ ├── existing_resources.tf
│ ├── integration_actions.tf
│ ├── main.tf
│ ├── notification_policies.tf
│ ├── outputs.tf
│ ├── schedule_rotations.tf
│ ├── schedules.tf
│ ├── service_incident_rules.tf
│ ├── services.tf
│ ├── team_routing_rules.tf
│ ├── teams.tf
│ ├── users.tf
│ ├── variables.tf
│ └── versions.tf
├── escalation
│ ├── README.md
│ ├── context.tf
│ ├── main.tf
│ ├── outputs.tf
│ ├── variables.tf
│ └── versions.tf
├── integration_action
│ ├── README.md
│ ├── context.tf
│ ├── main.tf
│ ├── outputs.tf
│ ├── variables.tf
│ └── versions.tf
├── notification_policy
│ ├── README.md
│ ├── context.tf
│ ├── main.tf
│ ├── outputs.tf
│ ├── variables.tf
│ └── versions.tf
├── schedule
│ ├── README.md
│ ├── context.tf
│ ├── main.tf
│ ├── outputs.tf
│ ├── variables.tf
│ └── versions.tf
├── service
│ ├── README.md
│ ├── context.tf
│ ├── main.tf
│ ├── outputs.tf
│ ├── variables.tf
│ └── versions.tf
├── service_incident_rule
│ ├── README.md
│ ├── context.tf
│ ├── main.tf
│ ├── outputs.tf
│ ├── variables.tf
│ └── versions.tf
├── team
│ ├── README.md
│ ├── context.tf
│ ├── main.tf
│ ├── outputs.tf
│ ├── variables.tf
│ └── versions.tf
├── team_routing_rule
│ ├── README.md
│ ├── context.tf
│ ├── main.tf
│ ├── outputs.tf
│ ├── variables.tf
│ └── versions.tf
└── user
│ ├── README.md
│ ├── context.tf
│ ├── main.tf
│ ├── outputs.tf
│ ├── variables.tf
│ └── versions.tf
├── outputs.tf
├── test
├── .gitignore
├── Makefile
├── Makefile.alpine
└── src
│ ├── .gitignore
│ ├── Makefile
│ ├── examples_advanced_features.go
│ ├── examples_alert_policy_test.go
│ ├── examples_api_integration_test.go
│ ├── examples_complete_test.go
│ ├── examples_config_test.go
│ ├── examples_escalation_test.go
│ ├── examples_integration_action.go
│ ├── examples_notification_policy_test.go
│ ├── examples_team_routing_rule_test.go
│ ├── examples_team_test.go
│ ├── examples_user_test.go
│ ├── go.mod
│ ├── go.sum
│ └── utils.go
├── variables.tf
└── versions.tf
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Unix-style newlines with a newline ending every file
2 | [*]
3 | charset = utf-8
4 | end_of_line = lf
5 | indent_size = 2
6 | indent_style = space
7 | insert_final_newline = true
8 | trim_trailing_whitespace = true
9 |
10 | [*.{tf,tfvars}]
11 | indent_size = 2
12 | indent_style = space
13 |
14 | [*.md]
15 | max_line_length = 0
16 | trim_trailing_whitespace = false
17 |
18 | # Override for Makefile
19 | [{Makefile, makefile, GNUmakefile, Makefile.*}]
20 | tab_width = 2
21 | indent_style = tab
22 | indent_size = 4
23 |
24 | [COMMIT_EDITMSG]
25 | max_line_length = 0
26 |
--------------------------------------------------------------------------------
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | # Use this file to define individuals or teams that are responsible for code in a repository.
2 | # Read more:
3 | #
4 | # Order is important: the last matching pattern has the highest precedence
5 |
6 | # These owners will be the default owners for everything
7 | * @cloudposse/engineering @cloudposse/contributors
8 |
9 | # Cloud Posse must review any changes to Makefiles
10 | **/Makefile @cloudposse/engineering
11 | **/Makefile.* @cloudposse/engineering
12 |
13 | # Cloud Posse must review any changes to GitHub actions
14 | .github/* @cloudposse/engineering
15 |
16 | # Cloud Posse must review any changes to standard context definition,
17 | # but some changes can be rubber-stamped.
18 | **/*.tf @cloudposse/engineering @cloudposse/contributors @cloudposse/approvers
19 | README.yaml @cloudposse/engineering @cloudposse/contributors @cloudposse/approvers
20 | README.md @cloudposse/engineering @cloudposse/contributors @cloudposse/approvers
21 | docs/*.md @cloudposse/engineering @cloudposse/contributors @cloudposse/approvers
22 |
23 | # Cloud Posse Admins must review all changes to CODEOWNERS or the mergify configuration
24 | .github/mergify.yml @cloudposse/admins
25 | .github/CODEOWNERS @cloudposse/admins
26 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: 'bug'
6 | assignees: ''
7 |
8 | ---
9 |
10 | Found a bug? Maybe our [Slack Community](https://slack.cloudposse.com) can help.
11 |
12 | [](https://slack.cloudposse.com)
13 |
14 | ## Describe the Bug
15 | A clear and concise description of what the bug is.
16 |
17 | ## Expected Behavior
18 | A clear and concise description of what you expected to happen.
19 |
20 | ## Steps to Reproduce
21 | Steps to reproduce the behavior:
22 | 1. Go to '...'
23 | 2. Run '....'
24 | 3. Enter '....'
25 | 4. See error
26 |
27 | ## Screenshots
28 | If applicable, add screenshots or logs to help explain your problem.
29 |
30 | ## Environment (please complete the following information):
31 |
32 | Anything that will help us triage the bug will help. Here are some ideas:
33 | - OS: [e.g. Linux, OSX, WSL, etc]
34 | - Version [e.g. 10.15]
35 |
36 | ## Additional Context
37 | Add any other context about the problem here.
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | description: Create a report to help us improve
4 | labels: ["bug"]
5 | assignees: [""]
6 | body:
7 | - type: markdown
8 | attributes:
9 | value: |
10 | Found a bug?
11 |
12 | Please checkout our [Slack Community](https://slack.cloudposse.com)
13 | or visit our [Slack Archive](https://archive.sweetops.com/).
14 |
15 | [](https://slack.cloudposse.com)
16 |
17 | - type: textarea
18 | id: concise-description
19 | attributes:
20 | label: Describe the Bug
21 | description: A clear and concise description of what the bug is.
22 | placeholder: What is the bug about?
23 | validations:
24 | required: true
25 |
26 | - type: textarea
27 | id: expected
28 | attributes:
29 | label: Expected Behavior
30 | description: A clear and concise description of what you expected.
31 | placeholder: What happened?
32 | validations:
33 | required: true
34 |
35 | - type: textarea
36 | id: reproduction-steps
37 | attributes:
38 | label: Steps to Reproduce
39 | description: Steps to reproduce the behavior.
40 | placeholder: How do we reproduce it?
41 | validations:
42 | required: true
43 |
44 | - type: textarea
45 | id: screenshots
46 | attributes:
47 | label: Screenshots
48 | description: If applicable, add screenshots or logs to help explain.
49 | validations:
50 | required: false
51 |
52 | - type: textarea
53 | id: environment
54 | attributes:
55 | label: Environment
56 | description: Anything that will help us triage the bug.
57 | placeholder: |
58 | - OS: [e.g. Linux, OSX, WSL, etc]
59 | - Version [e.g. 10.15]
60 | - Module version
61 | - Terraform version
62 | validations:
63 | required: false
64 |
65 | - type: textarea
66 | id: additional
67 | attributes:
68 | label: Additional Context
69 | description: |
70 | Add any other context about the problem here.
71 | validations:
72 | required: false
73 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
2 |
3 | contact_links:
4 |
5 | - name: Community Slack Team
6 | url: https://cloudposse.com/slack/
7 | about: |-
8 | Please ask and answer questions here.
9 |
10 | - name: Office Hours
11 | url: https://cloudposse.com/office-hours/
12 | about: |-
13 | Join us every Wednesday for FREE Office Hours (lunch & learn).
14 |
15 | - name: DevOps Accelerator Program
16 | url: https://cloudposse.com/accelerate/
17 | about: |-
18 | Own your infrastructure in record time. We build it. You drive it.
19 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature Request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: 'feature request'
6 | assignees: ''
7 |
8 | ---
9 |
10 | Have a question? Please checkout our [Slack Community](https://slack.cloudposse.com) or visit our [Slack Archive](https://archive.sweetops.com/).
11 |
12 | [](https://slack.cloudposse.com)
13 |
14 | ## Describe the Feature
15 |
16 | A clear and concise description of what the bug is.
17 |
18 | ## Expected Behavior
19 |
20 | A clear and concise description of what you expected to happen.
21 |
22 | ## Use Case
23 |
24 | Is your feature request related to a problem/challenge you are trying to solve? Please provide some additional context of why this feature or capability will be valuable.
25 |
26 | ## Describe Ideal Solution
27 |
28 | A clear and concise description of what you want to happen. If you don't know, that's okay.
29 |
30 | ## Alternatives Considered
31 |
32 | Explain what alternative solutions or features you've considered.
33 |
34 | ## Additional Context
35 |
36 | Add any other context or screenshots about the feature request here.
37 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature Request
3 | description: Suggest an idea for this project
4 | labels: ["feature request"]
5 | assignees: [""]
6 | body:
7 | - type: markdown
8 | attributes:
9 | value: |
10 | Have a question?
11 |
12 | Please checkout our [Slack Community](https://slack.cloudposse.com)
13 | or visit our [Slack Archive](https://archive.sweetops.com/).
14 |
15 | [](https://slack.cloudposse.com)
16 |
17 | - type: textarea
18 | id: concise-description
19 | attributes:
20 | label: Describe the Feature
21 | description: A clear and concise description of what the feature is.
22 | placeholder: What is the feature about?
23 | validations:
24 | required: true
25 |
26 | - type: textarea
27 | id: expected
28 | attributes:
29 | label: Expected Behavior
30 | description: A clear and concise description of what you expected.
31 | placeholder: What happened?
32 | validations:
33 | required: true
34 |
35 | - type: textarea
36 | id: use-case
37 | attributes:
38 | label: Use Case
39 | description: |
40 | Is your feature request related to a problem/challenge you are trying
41 | to solve?
42 |
43 | Please provide some additional context of why this feature or
44 | capability will be valuable.
45 | validations:
46 | required: true
47 |
48 | - type: textarea
49 | id: ideal-solution
50 | attributes:
51 | label: Describe Ideal Solution
52 | description: A clear and concise description of what you want to happen.
53 | validations:
54 | required: true
55 |
56 | - type: textarea
57 | id: alternatives-considered
58 | attributes:
59 | label: Alternatives Considered
60 | description: Explain alternative solutions or features considered.
61 | validations:
62 | required: false
63 |
64 | - type: textarea
65 | id: additional
66 | attributes:
67 | label: Additional Context
68 | description: |
69 | Add any other context about the problem here.
70 | validations:
71 | required: false
72 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/question.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudposse/terraform-opsgenie-incident-management/cd773cad75c13a8391d3a7a46363add1d2db2902/.github/ISSUE_TEMPLATE/question.md
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ## what
2 |
3 |
7 |
8 | ## why
9 |
10 |
15 |
16 | ## references
17 |
18 |
22 |
--------------------------------------------------------------------------------
/.github/mergify.yml:
--------------------------------------------------------------------------------
1 | extends: .github
2 |
--------------------------------------------------------------------------------
/.github/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "config:base",
4 | ":preserveSemverRanges"
5 | ],
6 | "baseBranches": ["main", "master", "/^release\\/v\\d{1,2}$/"],
7 | "labels": ["auto-update"],
8 | "dependencyDashboardAutoclose": true,
9 | "enabledManagers": ["terraform"],
10 | "terraform": {
11 | "ignorePaths": ["**/context.tf", "examples/**"]
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/.github/settings.yml:
--------------------------------------------------------------------------------
1 | # Upstream changes from _extends are only recognized when modifications are made to this file in the default branch.
2 | _extends: .github
3 | repository:
4 | name: terraform-opsgenie-incident-management
5 | description: Terraform module to provision Opsgenie resources from YAML configurations using the Opsgenie provider,, complete with automated tests
6 | homepage: https://cloudposse.com/accelerate
7 | topics: opsgenie-provider, terraform-modules, terratest, opsgenie, opsgenie-api, escalation, notifications, y, yaml, yaml-configuration
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.github/workflows/branch.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: Branch
3 | on:
4 | pull_request:
5 | branches:
6 | - main
7 | - release/**
8 | types: [opened, synchronize, reopened, labeled, unlabeled]
9 | push:
10 | branches:
11 | - main
12 | - release/v*
13 | paths-ignore:
14 | - '.github/**'
15 | - 'docs/**'
16 | - 'examples/**'
17 | - 'test/**'
18 | - 'README.md'
19 |
20 | permissions: {}
21 |
22 | jobs:
23 | terraform-module:
24 | uses: cloudposse/.github/.github/workflows/shared-terraform-module.yml@main
25 | secrets: inherit
26 |
--------------------------------------------------------------------------------
/.github/workflows/chatops.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: chatops
3 | on:
4 | issue_comment:
5 | types: [created]
6 |
7 | permissions:
8 | pull-requests: write
9 | id-token: write
10 | contents: write
11 | statuses: write
12 |
13 | jobs:
14 | test:
15 | uses: cloudposse/.github/.github/workflows/shared-terraform-chatops.yml@main
16 | if: ${{ github.event.issue.pull_request && contains(github.event.comment.body, '/terratest') }}
17 | secrets: inherit
18 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: release
3 | on:
4 | release:
5 | types:
6 | - published
7 |
8 | permissions:
9 | id-token: write
10 | contents: write
11 | pull-requests: write
12 |
13 | jobs:
14 | terraform-module:
15 | uses: cloudposse/.github/.github/workflows/shared-release-branches.yml@main
16 | secrets: inherit
17 |
--------------------------------------------------------------------------------
/.github/workflows/scheduled.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: scheduled
3 | on:
4 | workflow_dispatch: { } # Allows manually trigger this workflow
5 | schedule:
6 | - cron: "0 3 * * *"
7 |
8 | permissions:
9 | pull-requests: write
10 | id-token: write
11 | contents: write
12 |
13 | jobs:
14 | scheduled:
15 | uses: cloudposse/.github/.github/workflows/shared-terraform-scheduled.yml@main
16 | secrets: inherit
17 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Local .terraform directories
2 | **/.terraform/*
3 |
4 | # .tfstate files
5 | *.tfstate
6 | *.tfstate.*
7 | .terraform
8 | .terraform.tfstate.lock.info
9 |
10 | **/.idea
11 | **/*.iml
12 |
13 | # Cloud Posse Build Harness https://github.com/cloudposse/build-harness
14 | **/.build-harness
15 | **/build-harness
16 |
17 | # Crash log files
18 | crash.log
19 | test.log
20 |
--------------------------------------------------------------------------------
/README.yaml:
--------------------------------------------------------------------------------
1 | #
2 | # This is the canonical configuration for the `README.md`
3 | # Run `make readme` to rebuild the `README.md`
4 | #
5 |
6 | # Name of this project
7 | name: terraform-opsgenie-incident-management
8 |
9 | # Logo for this project
10 | #logo: docs/logo.png
11 |
12 | # License of this project
13 | license: "APACHE2"
14 |
15 | # Copyrights
16 | copyrights:
17 | - name: "Cloud Posse, LLC"
18 | url: "https://cloudposse.com"
19 | year: "2021"
20 |
21 | # Canonical GitHub repo
22 | github_repo: cloudposse/terraform-opsgenie-incident-management
23 |
24 | # Badges to display
25 | badges:
26 | - name: Latest Release
27 | image: https://img.shields.io/github/release/cloudposse/terraform-opsgenie-incident-management.svg?style=for-the-badge
28 | url: https://github.com/cloudposse/terraform-opsgenie-incident-management/releases/latest
29 | - name: Last Updated
30 | image: https://img.shields.io/github/last-commit/cloudposse/terraform-opsgenie-incident-management.svg?style=for-the-badge
31 | url: https://github.com/cloudposse/terraform-opsgenie-incident-management/commits
32 | - name: Slack Community
33 | image: https://slack.cloudposse.com/for-the-badge.svg
34 | url: https://cloudposse.com/slack
35 |
36 | # List any related terraform modules that this module may be used with or that this module depends on.
37 | related:
38 | - name: "terraform-datadog-monitor"
39 | description: "Terraform module to provision Standard System Monitors (cpu, memory, swap, io, etc) in Datadog"
40 | url: "https://github.com/cloudposse/terraform-datadog-monitor"
41 |
42 | # List any resources helpful for someone to get started. For example, link to the hashicorp documentation or AWS documentation.
43 | references:
44 | - name: "Opsgenie API Overview"
45 | description: "Opsgenie APIs give you interconnectivity to process your requests and access data. View our individual documentation for our APIs to see the methods used to process relevant requests. Action-specific instructions are included to help you complete requests, along with sample requests and responses for added guidance. Additionally, view our Rate Limiting section for specific details and configurations."
46 | url: "https://docs.opsgenie.com/docs/api-overview"
47 | - name: "Terraform Registry Opsgenie Provider documentation"
48 | description: "The Opsgenie provider is used to interact with the many resources supported by Opsgenie. The provider needs to be configured with the proper credentials before it can be used."
49 | url: "https://registry.terraform.io/providers/opsgenie/opsgenie/latest/docs"
50 | - name: "Github Terraform OpsGenie provider repository"
51 | description: "The Opsgenie provider is used to interact with the many resources supported by Opsgenie. The provider needs to be configured with the proper credentials before it can be used."
52 | url: "https://github.com/opsgenie/terraform-provider-opsgenie/"
53 |
54 | # Short description of this project
55 | description: |-
56 | Terraform module to provision Opsgenie resources using the Opsgenie provider. The provider needs to be configured with the proper credentials before it can be used.
57 | It consist of root module which is only here as an example but can be used as a combination of all submodules. Submodules can also be combined to abstract away complexity of setting up for example a team escalation.
58 |
59 | # Introduction to the project
60 | introduction: |-
61 | Available modules:
62 | - [Alert Policy](modules/alert_policy)
63 | - [API Integration](modules/api_integration)
64 | - [Config](modules/config)
65 | - [Escalation](modules/escalation)
66 | - [Integration Action](modules/integration_action) (advanced feature — not available to all OpsGenie plans)
67 | - [Notification Policy](modules/notification_policy)
68 | - [Team](modules/team)
69 | - [Team Routing Rule](modules/team_routing_rule)
70 | - [User](modules/user)
71 | - [Service](modules/service)
72 | - [Service Incident Rule](modules/service_incident_rule)
73 |
74 | **Note:** Root module is just an example that uses all of submodules.
75 |
76 | **Note:** See the [Advanced Features Example](examples/advanced_features) for features only available to some OpsGenie plans.
77 |
78 | usage: |-
79 | Here's how to invoke `team` module in your projects
80 |
81 | ```hcl
82 | module "team-name" {
83 | source = "cloudposse/incident-management/opsgenie//modules/team"
84 | # Cloud Posse recommends pinning every module to a specific version
85 | # version = "x.x.x"
86 |
87 | team = {
88 | name = "team-name"
89 | description = "team-description"
90 | }
91 | }
92 | ```
93 |
94 | # Example usage
95 | examples: |-
96 | Here are examples of using the module:
97 |
98 | - [`complete`](examples/complete) - complete example of using this module
99 |
100 | Submodules examples:
101 | - [`alert_policy`](examples/alert_policy)
102 | - [`api_integration`](examples/api_integration)
103 | - [`escalation`](examples/escalation)
104 | - [`integration_action`](examples/integration_action) (advanced feature — not available to all OpsGenie plans)
105 | - [`notification_policy`](examples/notification_policy)
106 | - [`team`](examples/team)
107 | - [`team_routing_rule`](examples/team_routing_rule)
108 | - [`user`](examples/user)
109 |
110 | Here is an example of using the `config` module, which incorporates all resource declarations into a single module:
111 | - [`config`](examples/config)
112 |
113 | Here are automated tests for the examples using [bats](https://github.com/bats-core/bats-core) and [Terratest](https://github.com/gruntwork-io/terratest) (which tests and provisions the examples):
114 | - [test](test)
115 |
116 | # How to get started quickly
117 | #quickstart: |-
118 | # Here's how to get started...
119 |
120 | # Other files to include in this README from the project folder
121 | include: []
122 | contributors: []
123 |
--------------------------------------------------------------------------------
/atmos.yaml:
--------------------------------------------------------------------------------
1 | # Atmos Configuration — powered by https://atmos.tools
2 | #
3 | # This configuration enables centralized, DRY, and consistent project scaffolding using Atmos.
4 | #
5 | # Included features:
6 | # - Organizational custom commands: https://atmos.tools/core-concepts/custom-commands
7 | # - Automated README generation: https://atmos.tools/cli/commands/docs/generate
8 | #
9 |
10 | # Import shared configuration used by all modules
11 | import:
12 | - https://raw.githubusercontent.com/cloudposse/.github/refs/heads/main/.github/atmos/terraform-module.yaml
13 |
--------------------------------------------------------------------------------
/context.tf:
--------------------------------------------------------------------------------
1 | #
2 | # ONLY EDIT THIS FILE IN github.com/cloudposse/terraform-null-label
3 | # All other instances of this file should be a copy of that one
4 | #
5 | #
6 | # Copy this file from https://github.com/cloudposse/terraform-null-label/blob/master/exports/context.tf
7 | # and then place it in your Terraform module to automatically get
8 | # Cloud Posse's standard configuration inputs suitable for passing
9 | # to Cloud Posse modules.
10 | #
11 | # curl -sL https://raw.githubusercontent.com/cloudposse/terraform-null-label/master/exports/context.tf -o context.tf
12 | #
13 | # Modules should access the whole context as `module.this.context`
14 | # to get the input variables with nulls for defaults,
15 | # for example `context = module.this.context`,
16 | # and access individual variables as `module.this.`,
17 | # with final values filled in.
18 | #
19 | # For example, when using defaults, `module.this.context.delimiter`
20 | # will be null, and `module.this.delimiter` will be `-` (hyphen).
21 | #
22 |
23 | module "this" {
24 | source = "cloudposse/label/null"
25 | version = "0.25.0" # requires Terraform >= 0.13.0
26 |
27 | enabled = var.enabled
28 | namespace = var.namespace
29 | tenant = var.tenant
30 | environment = var.environment
31 | stage = var.stage
32 | name = var.name
33 | delimiter = var.delimiter
34 | attributes = var.attributes
35 | tags = var.tags
36 | additional_tag_map = var.additional_tag_map
37 | label_order = var.label_order
38 | regex_replace_chars = var.regex_replace_chars
39 | id_length_limit = var.id_length_limit
40 | label_key_case = var.label_key_case
41 | label_value_case = var.label_value_case
42 | descriptor_formats = var.descriptor_formats
43 | labels_as_tags = var.labels_as_tags
44 |
45 | context = var.context
46 | }
47 |
48 | # Copy contents of cloudposse/terraform-null-label/variables.tf here
49 |
50 | variable "context" {
51 | type = any
52 | default = {
53 | enabled = true
54 | namespace = null
55 | tenant = null
56 | environment = null
57 | stage = null
58 | name = null
59 | delimiter = null
60 | attributes = []
61 | tags = {}
62 | additional_tag_map = {}
63 | regex_replace_chars = null
64 | label_order = []
65 | id_length_limit = null
66 | label_key_case = null
67 | label_value_case = null
68 | descriptor_formats = {}
69 | # Note: we have to use [] instead of null for unset lists due to
70 | # https://github.com/hashicorp/terraform/issues/28137
71 | # which was not fixed until Terraform 1.0.0,
72 | # but we want the default to be all the labels in `label_order`
73 | # and we want users to be able to prevent all tag generation
74 | # by setting `labels_as_tags` to `[]`, so we need
75 | # a different sentinel to indicate "default"
76 | labels_as_tags = ["unset"]
77 | }
78 | description = <<-EOT
79 | Single object for setting entire context at once.
80 | See description of individual variables for details.
81 | Leave string and numeric variables as `null` to use default value.
82 | Individual variable settings (non-null) override settings in context object,
83 | except for attributes, tags, and additional_tag_map, which are merged.
84 | EOT
85 |
86 | validation {
87 | condition = lookup(var.context, "label_key_case", null) == null ? true : contains(["lower", "title", "upper"], var.context["label_key_case"])
88 | error_message = "Allowed values: `lower`, `title`, `upper`."
89 | }
90 |
91 | validation {
92 | condition = lookup(var.context, "label_value_case", null) == null ? true : contains(["lower", "title", "upper", "none"], var.context["label_value_case"])
93 | error_message = "Allowed values: `lower`, `title`, `upper`, `none`."
94 | }
95 | }
96 |
97 | variable "enabled" {
98 | type = bool
99 | default = null
100 | description = "Set to false to prevent the module from creating any resources"
101 | }
102 |
103 | variable "namespace" {
104 | type = string
105 | default = null
106 | description = "ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique"
107 | }
108 |
109 | variable "tenant" {
110 | type = string
111 | default = null
112 | description = "ID element _(Rarely used, not included by default)_. A customer identifier, indicating who this instance of a resource is for"
113 | }
114 |
115 | variable "environment" {
116 | type = string
117 | default = null
118 | description = "ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT'"
119 | }
120 |
121 | variable "stage" {
122 | type = string
123 | default = null
124 | description = "ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release'"
125 | }
126 |
127 | variable "name" {
128 | type = string
129 | default = null
130 | description = <<-EOT
131 | ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'.
132 | This is the only ID element not also included as a `tag`.
133 | The "name" tag is set to the full `id` string. There is no tag with the value of the `name` input.
134 | EOT
135 | }
136 |
137 | variable "delimiter" {
138 | type = string
139 | default = null
140 | description = <<-EOT
141 | Delimiter to be used between ID elements.
142 | Defaults to `-` (hyphen). Set to `""` to use no delimiter at all.
143 | EOT
144 | }
145 |
146 | variable "attributes" {
147 | type = list(string)
148 | default = []
149 | description = <<-EOT
150 | ID element. Additional attributes (e.g. `workers` or `cluster`) to add to `id`,
151 | in the order they appear in the list. New attributes are appended to the
152 | end of the list. The elements of the list are joined by the `delimiter`
153 | and treated as a single ID element.
154 | EOT
155 | }
156 |
157 | variable "labels_as_tags" {
158 | type = set(string)
159 | default = ["default"]
160 | description = <<-EOT
161 | Set of labels (ID elements) to include as tags in the `tags` output.
162 | Default is to include all labels.
163 | Tags with empty values will not be included in the `tags` output.
164 | Set to `[]` to suppress all generated tags.
165 | **Notes:**
166 | The value of the `name` tag, if included, will be the `id`, not the `name`.
167 | Unlike other `null-label` inputs, the initial setting of `labels_as_tags` cannot be
168 | changed in later chained modules. Attempts to change it will be silently ignored.
169 | EOT
170 | }
171 |
172 | variable "tags" {
173 | type = map(string)
174 | default = {}
175 | description = <<-EOT
176 | Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`).
177 | Neither the tag keys nor the tag values will be modified by this module.
178 | EOT
179 | }
180 |
181 | variable "additional_tag_map" {
182 | type = map(string)
183 | default = {}
184 | description = <<-EOT
185 | Additional key-value pairs to add to each map in `tags_as_list_of_maps`. Not added to `tags` or `id`.
186 | This is for some rare cases where resources want additional configuration of tags
187 | and therefore take a list of maps with tag key, value, and additional configuration.
188 | EOT
189 | }
190 |
191 | variable "label_order" {
192 | type = list(string)
193 | default = null
194 | description = <<-EOT
195 | The order in which the labels (ID elements) appear in the `id`.
196 | Defaults to ["namespace", "environment", "stage", "name", "attributes"].
197 | You can omit any of the 6 labels ("tenant" is the 6th), but at least one must be present.
198 | EOT
199 | }
200 |
201 | variable "regex_replace_chars" {
202 | type = string
203 | default = null
204 | description = <<-EOT
205 | Terraform regular expression (regex) string.
206 | Characters matching the regex will be removed from the ID elements.
207 | If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits.
208 | EOT
209 | }
210 |
211 | variable "id_length_limit" {
212 | type = number
213 | default = null
214 | description = <<-EOT
215 | Limit `id` to this many characters (minimum 6).
216 | Set to `0` for unlimited length.
217 | Set to `null` for keep the existing setting, which defaults to `0`.
218 | Does not affect `id_full`.
219 | EOT
220 | validation {
221 | condition = var.id_length_limit == null ? true : var.id_length_limit >= 6 || var.id_length_limit == 0
222 | error_message = "The id_length_limit must be >= 6 if supplied (not null), or 0 for unlimited length."
223 | }
224 | }
225 |
226 | variable "label_key_case" {
227 | type = string
228 | default = null
229 | description = <<-EOT
230 | Controls the letter case of the `tags` keys (label names) for tags generated by this module.
231 | Does not affect keys of tags passed in via the `tags` input.
232 | Possible values: `lower`, `title`, `upper`.
233 | Default value: `title`.
234 | EOT
235 |
236 | validation {
237 | condition = var.label_key_case == null ? true : contains(["lower", "title", "upper"], var.label_key_case)
238 | error_message = "Allowed values: `lower`, `title`, `upper`."
239 | }
240 | }
241 |
242 | variable "label_value_case" {
243 | type = string
244 | default = null
245 | description = <<-EOT
246 | Controls the letter case of ID elements (labels) as included in `id`,
247 | set as tag values, and output by this module individually.
248 | Does not affect values of tags passed in via the `tags` input.
249 | Possible values: `lower`, `title`, `upper` and `none` (no transformation).
250 | Set this to `title` and set `delimiter` to `""` to yield Pascal Case IDs.
251 | Default value: `lower`.
252 | EOT
253 |
254 | validation {
255 | condition = var.label_value_case == null ? true : contains(["lower", "title", "upper", "none"], var.label_value_case)
256 | error_message = "Allowed values: `lower`, `title`, `upper`, `none`."
257 | }
258 | }
259 |
260 | variable "descriptor_formats" {
261 | type = any
262 | default = {}
263 | description = <<-EOT
264 | Describe additional descriptors to be output in the `descriptors` output map.
265 | Map of maps. Keys are names of descriptors. Values are maps of the form
266 | `{
267 | format = string
268 | labels = list(string)
269 | }`
270 | (Type is `any` so the map values can later be enhanced to provide additional options.)
271 | `format` is a Terraform format string to be passed to the `format()` function.
272 | `labels` is a list of labels, in order, to pass to `format()` function.
273 | Label values will be normalized before being passed to `format()` so they will be
274 | identical to how they appear in `id`.
275 | Default is `{}` (`descriptors` output will be empty).
276 | EOT
277 | }
278 |
279 | #### End of copy of cloudposse/terraform-null-label/variables.tf
280 |
--------------------------------------------------------------------------------
/examples/advanced_features/api_integration.tf:
--------------------------------------------------------------------------------
1 | module "api_integration" {
2 | source = "../../modules/api_integration"
3 |
4 | api_integration = {
5 | name = module.this.id
6 | type = "AmazonSns"
7 | owner_team_id = module.team.team_id
8 | }
9 |
10 | context = module.this.context
11 | }
12 |
--------------------------------------------------------------------------------
/examples/advanced_features/fixtures.tfvars:
--------------------------------------------------------------------------------
1 | namespace = "eg"
2 | name = "incident-management-workflow"
3 | stage = "test"
4 |
--------------------------------------------------------------------------------
/examples/advanced_features/integration_action.tf:
--------------------------------------------------------------------------------
1 | module "integration_action" {
2 | source = "../../modules/integration_action"
3 |
4 | integration_action = {
5 | integration_id = module.api_integration.api_integration_id
6 | team_id = module.team.team_id
7 |
8 | create = [
9 | {
10 | name = "Create Non-informational Alerts"
11 | alias = "{{title}}"
12 | filter = {
13 | type = "match-all-conditions"
14 | conditions = [
15 | {
16 | field = "priority"
17 | not = true
18 | operation = "equals"
19 | expected_value = "P5"
20 | }
21 | ]
22 | }
23 | }
24 | ]
25 | }
26 |
27 | context = module.this.context
28 | }
29 |
--------------------------------------------------------------------------------
/examples/advanced_features/main.tf:
--------------------------------------------------------------------------------
1 | provider "opsgenie" {
2 | api_key = var.opsgenie_provider_api_key
3 | }
4 |
--------------------------------------------------------------------------------
/examples/advanced_features/outputs.tf:
--------------------------------------------------------------------------------
1 | output "integration_action_id" {
2 | description = "The ID of the Opsgenie Integration Action"
3 | value = module.integration_action.integration_action_id
4 | }
5 |
6 | output "api_integration_id" {
7 | description = "The ID of the Opsgenie integration"
8 | value = module.api_integration.api_integration_id
9 | }
10 |
11 | output "api_integration_name" {
12 | description = "The name of the Opsgenie integration"
13 | value = module.api_integration.api_integration_name
14 | }
15 |
16 | output "team_id" {
17 | description = "The ID of the Opsgenie team"
18 | value = module.team.team_id
19 | }
20 |
21 | output "team_name" {
22 | description = "The name of the Opsgenie team"
23 | value = module.team.team_name
24 | }
25 |
--------------------------------------------------------------------------------
/examples/advanced_features/team.tf:
--------------------------------------------------------------------------------
1 | module "team" {
2 | source = "../../modules/team"
3 |
4 | team = {
5 | name = "${module.this.id}.security"
6 | description = "${module.this.id} Security Team"
7 | ignore_members = false
8 | }
9 |
10 | context = module.this.context
11 | }
12 |
--------------------------------------------------------------------------------
/examples/advanced_features/variables.tf:
--------------------------------------------------------------------------------
1 | variable "opsgenie_provider_api_key" {
2 | type = string
3 | description = "The API Key for the Opsgenie Integration. If omitted, the OPSGENIE_API_KEY environment variable is used"
4 | default = null
5 | }
6 |
--------------------------------------------------------------------------------
/examples/advanced_features/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 0.13.0"
3 |
4 | required_providers {
5 | opsgenie = {
6 | source = "opsgenie/opsgenie"
7 | version = ">= 0.4"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/examples/alert_policy/fixtures.tfvars:
--------------------------------------------------------------------------------
1 | namespace = "eg"
2 | name = "alert-policy"
3 | stage = "test"
4 |
--------------------------------------------------------------------------------
/examples/alert_policy/main.tf:
--------------------------------------------------------------------------------
1 | provider "opsgenie" {
2 | api_key = var.opsgenie_provider_api_key
3 | }
4 |
5 | module "alert_policy" {
6 | source = "../../modules/alert_policy"
7 |
8 | alert_policy = {
9 | name = module.this.id
10 |
11 | tags = ["test1", "test2"]
12 | priority = "P1"
13 |
14 | responders = [
15 | {
16 | id = module.team.team_id
17 | type = "team"
18 | }
19 | ]
20 |
21 | filter = {
22 | type = "match-all-conditions"
23 | conditions = [
24 | {
25 | # Possible values are "message", "alias", "description", "source", "entity", "tags", "actions", "details", "extra-properties", "recipients", "teams", "priority"
26 | field = "source"
27 | operation = "matches"
28 | expected_value = ".*prod.*"
29 | },
30 | {
31 | field = "tags"
32 | operation = "contains"
33 | expected_value = "severity:critical"
34 | }
35 | ]
36 | }
37 | }
38 |
39 | context = module.this.context
40 | }
41 |
42 | module "team" {
43 | source = "../../modules/team"
44 |
45 | team = {
46 | name = module.this.id
47 | description = "team-description"
48 | }
49 |
50 | context = module.this.context
51 | }
52 |
--------------------------------------------------------------------------------
/examples/alert_policy/outputs.tf:
--------------------------------------------------------------------------------
1 | output "alert_policy" {
2 | description = "Opsgenie Alert Policy"
3 | value = module.alert_policy
4 | }
5 |
6 | output "alert_policy_name" {
7 | description = "Name of the Opsgenie Alert Policy"
8 | value = module.alert_policy.alert_policy_name
9 | }
10 |
11 | output "alert_policy_tags" {
12 | description = "Tags of the Opsgenie Alert Policy"
13 | value = module.alert_policy.alert_policy_tags
14 | }
15 |
16 | output "alert_policy_filter" {
17 | description = "Filter of the Opsgenie Alert Policy"
18 | value = module.alert_policy.alert_policy_filter
19 | }
20 |
21 | output "alert_policy_priority" {
22 | description = "Priority of the Opsgenie Alert Policy"
23 | value = module.alert_policy.alert_policy_priority
24 | }
25 |
26 | output "alert_policy_responders" {
27 | description = "Responders of the Opsgenie Alert Policy"
28 | value = module.alert_policy.alert_policy_responders
29 | }
30 |
--------------------------------------------------------------------------------
/examples/alert_policy/variables.tf:
--------------------------------------------------------------------------------
1 | variable "opsgenie_provider_api_key" {
2 | type = string
3 | description = "The API Key for the Opsgenie Integration. If omitted, the OPSGENIE_API_KEY environment variable is used"
4 | default = null
5 | }
6 |
--------------------------------------------------------------------------------
/examples/alert_policy/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 0.13.0"
3 |
4 | required_providers {
5 | opsgenie = {
6 | source = "opsgenie/opsgenie"
7 | version = ">= 0.4"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/examples/api_integration/fixtures.tfvars:
--------------------------------------------------------------------------------
1 | namespace = "eg"
2 | name = "api-integration"
3 | stage = "test"
4 |
--------------------------------------------------------------------------------
/examples/api_integration/main.tf:
--------------------------------------------------------------------------------
1 | provider "opsgenie" {
2 | api_key = var.opsgenie_provider_api_key
3 | }
4 |
5 | module "team" {
6 | source = "../../modules/team"
7 |
8 | team = {
9 | name = module.this.id
10 | }
11 |
12 | context = module.this.context
13 | }
14 |
15 | module "api_integration" {
16 | source = "../../modules/api_integration"
17 |
18 | api_integration = {
19 | name = module.this.id
20 | type = "AmazonSns"
21 | owner_team_id = module.team.team_id
22 | }
23 |
24 | context = module.this.context
25 | }
26 |
--------------------------------------------------------------------------------
/examples/api_integration/outputs.tf:
--------------------------------------------------------------------------------
1 | output "api_integration_name" {
2 | description = "The name of the Opsgenie API Integration"
3 | value = module.api_integration.api_integration_name
4 | }
5 |
6 | output "api_integration_id" {
7 | description = "The ID of the Opsgenie API Integration"
8 | value = module.api_integration.api_integration_id
9 | }
10 |
11 | output "api_integration_api_key" {
12 | description = "The API key of the Opsgenie API Integration"
13 | value = module.api_integration.api_integration_api_key
14 | sensitive = true
15 | }
16 |
--------------------------------------------------------------------------------
/examples/api_integration/variables.tf:
--------------------------------------------------------------------------------
1 | variable "opsgenie_provider_api_key" {
2 | type = string
3 | description = "The API Key for the Opsgenie Integration. If omitted, the OPSGENIE_API_KEY environment variable is used"
4 | default = null
5 | }
6 |
--------------------------------------------------------------------------------
/examples/api_integration/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 0.13.0"
3 |
4 | required_providers {
5 | opsgenie = {
6 | source = "opsgenie/opsgenie"
7 | version = ">= 0.4"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/examples/complete/api_integration.tf:
--------------------------------------------------------------------------------
1 | module "api_integration" {
2 | source = "../../modules/api_integration"
3 |
4 | api_integration = {
5 | name = module.this.id
6 | type = "AmazonSns"
7 | owner_team_id = module.team.team_id
8 | }
9 | context = module.this.context
10 | }
11 |
--------------------------------------------------------------------------------
/examples/complete/escalation.tf:
--------------------------------------------------------------------------------
1 | module "escalation" {
2 | source = "../../modules/escalation"
3 |
4 | escalation = {
5 | name = "${module.this.id}-escalation"
6 | owner_team_id = module.team.team_id
7 |
8 | rules = [{
9 | recipient = {
10 | type = "team"
11 | id = module.sub_team.team_id
12 | }
13 | }]
14 | }
15 |
16 | context = module.this.context
17 | }
18 |
--------------------------------------------------------------------------------
/examples/complete/fixtures.tfvars:
--------------------------------------------------------------------------------
1 | namespace = "eg"
2 | name = "incident-management-workflow"
3 | stage = "test"
4 |
--------------------------------------------------------------------------------
/examples/complete/main.tf:
--------------------------------------------------------------------------------
1 | provider "opsgenie" {
2 | api_key = var.opsgenie_provider_api_key
3 | }
4 |
--------------------------------------------------------------------------------
/examples/complete/outputs.tf:
--------------------------------------------------------------------------------
1 | output "escalation_id" {
2 | description = "The ID of the Opsgenie escalation"
3 | value = module.escalation.escalation_id
4 | }
5 |
6 | output "escalation_name" {
7 | description = "The name of the Opsgenie escalation"
8 | value = module.escalation.escalation_name
9 | }
10 |
11 | output "api_integration_id" {
12 | description = "The ID of the Opsgenie integration"
13 | value = module.api_integration.api_integration_id
14 | }
15 |
16 | output "api_integration_name" {
17 | description = "The name of the Opsgenie integration"
18 | value = module.api_integration.api_integration_name
19 | }
20 |
21 | output "team_routing_rule_id" {
22 | description = "The ID of the Opsgenie team routing rule"
23 | value = module.team_routing_rule.team_routing_rule_id
24 | }
25 |
26 | output "team_routing_rule_name" {
27 | description = "The name of the Opsgenie team routing rule"
28 | value = module.team_routing_rule.team_routing_rule_name
29 | }
30 |
31 | output "team_id" {
32 | description = "The ID of the Opsgenie team"
33 | value = module.team.team_id
34 | }
35 |
36 | output "team_name" {
37 | description = "The name of the Opsgenie team"
38 | value = module.team.team_name
39 | }
40 |
41 | output "user_id" {
42 | description = "The ID of the Opsgenie user"
43 | value = module.user.user_id
44 | }
45 |
46 | output "user_name" {
47 | description = "The name of the Opsgenie user"
48 | value = module.user.user_name
49 | }
50 |
51 | output "service_id" {
52 | description = "The ID of the Opsgenie service"
53 | value = module.service.service_id
54 | }
55 |
56 | output "service_name" {
57 | description = "The name of the Opsgenie service"
58 | value = module.service.service_name
59 | }
60 |
61 | output "service_incident_rule_id" {
62 | description = "The ID of the Opsgenie service incident rule"
63 | value = module.service_incident_rule.service_incident_rule_id
64 | }
65 |
--------------------------------------------------------------------------------
/examples/complete/service.tf:
--------------------------------------------------------------------------------
1 | module "service" {
2 | source = "../../modules/service"
3 |
4 | # Services are Opsgenie Enterprise feature, disable it for now
5 | enabled = false
6 |
7 | service = {
8 | name = "frontend"
9 | description = "Frontend service"
10 | team_id = module.team.team_id
11 | }
12 |
13 | context = module.this.context
14 | }
15 |
--------------------------------------------------------------------------------
/examples/complete/service_incident_rule.tf:
--------------------------------------------------------------------------------
1 | module "service_incident_rule" {
2 | source = "../../modules/service_incident_rule"
3 |
4 | # Services are Opsgenie Enterprise feature, disable it for now
5 | enabled = false
6 |
7 | service_incident_rule = {
8 | service_id = module.service.service_id
9 |
10 | incident_rule = {
11 | condition_match_type = "match-all"
12 |
13 | conditions = [
14 | {
15 | # Possibke values: message, description, tags, extra-properties, recipients, teams, priority
16 | field = "message"
17 | operation = "matches"
18 | expected_value = ".*stage.*"
19 | },
20 | {
21 | field = "tags"
22 | operation = "contains"
23 | expected_value = "severity:info"
24 | }
25 | ]
26 |
27 | incident_properties = {
28 | message = "This is a test message"
29 | priority = "P3"
30 |
31 | stakeholder_properties = {
32 | message = "Message for stakeholders"
33 | enable = true
34 | }
35 | }
36 | }
37 | }
38 |
39 | context = module.this.context
40 | }
41 |
--------------------------------------------------------------------------------
/examples/complete/team.tf:
--------------------------------------------------------------------------------
1 | module "team" {
2 | source = "../../modules/team"
3 |
4 | team = {
5 | name = module.this.id
6 | description = "team-description"
7 | ignore_members = false
8 | }
9 | context = module.this.context
10 | }
11 |
12 | module "sub_team" {
13 | source = "../../modules/team"
14 |
15 | team = {
16 | name = "${module.this.id}.team"
17 | description = "sub-team-description"
18 | }
19 | context = module.this.context
20 | }
21 |
--------------------------------------------------------------------------------
/examples/complete/team_routing_rule.tf:
--------------------------------------------------------------------------------
1 | module "team_routing_rule" {
2 | source = "../../modules/team_routing_rule"
3 |
4 | team_routing_rule = {
5 | name = module.this.id
6 | team_id = module.team.team_id
7 |
8 | notify = [{
9 | type = "escalation"
10 | id = module.escalation.escalation_id
11 | }]
12 | }
13 |
14 | context = module.this.context
15 | }
16 |
--------------------------------------------------------------------------------
/examples/complete/user.tf:
--------------------------------------------------------------------------------
1 | module "user" {
2 | source = "../../modules/user"
3 |
4 | # Users can't be destroyed
5 | enabled = false
6 |
7 | user = {
8 | username = "opsgenie-test@cloudposse.com"
9 | full_name = "Opsgenie Test User"
10 | role = "User"
11 | locale = "en_US"
12 | timezone = "America/New_York"
13 | }
14 |
15 | context = module.this.context
16 | }
17 |
--------------------------------------------------------------------------------
/examples/complete/variables.tf:
--------------------------------------------------------------------------------
1 | variable "opsgenie_provider_api_key" {
2 | type = string
3 | description = "The API Key for the Opsgenie Integration. If omitted, the OPSGENIE_API_KEY environment variable is used"
4 | default = null
5 | }
6 |
--------------------------------------------------------------------------------
/examples/complete/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 0.13.0"
3 |
4 | required_providers {
5 | opsgenie = {
6 | source = "opsgenie/opsgenie"
7 | version = ">= 0.4"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/examples/config/fixtures.tfvars:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudposse/terraform-opsgenie-incident-management/cd773cad75c13a8391d3a7a46363add1d2db2902/examples/config/fixtures.tfvars
--------------------------------------------------------------------------------
/examples/config/main.tf:
--------------------------------------------------------------------------------
1 | provider "opsgenie" {
2 | api_key = var.opsgenie_provider_api_key
3 | }
4 |
5 | locals {
6 | # Build a map of our various Opsgenie resources that will be used to iterate over each module
7 | opsgenie_resources = merge([
8 | for resource_file in fileset(path.cwd, "resources/*.yaml") : {
9 | for k, v in yamldecode(file(resource_file)) : k => v
10 | }
11 | ]...)
12 | }
13 |
14 | module "opsgenie_config" {
15 | source = "../../modules/config"
16 |
17 | opsgenie_resources = local.opsgenie_resources
18 |
19 | context = module.this.context
20 | }
21 |
--------------------------------------------------------------------------------
/examples/config/outputs.tf:
--------------------------------------------------------------------------------
1 | output "api_integrations" {
2 | value = module.opsgenie_config.api_integrations
3 | description = "API integrations"
4 | }
5 |
6 | output "alert_policies" {
7 | value = module.opsgenie_config.alert_policies
8 | description = "Alert policies"
9 | }
10 |
11 | output "escalations" {
12 | value = module.opsgenie_config.escalations
13 | description = "Escalations"
14 | }
15 |
16 | output "integration_actions" {
17 | value = module.opsgenie_config.integration_actions
18 | description = "Integration Actions"
19 | }
20 |
21 | output "notification_policies" {
22 | value = module.opsgenie_config.notification_policies
23 | description = "Notification policies"
24 | }
25 |
26 | output "team_routing_rules" {
27 | value = module.opsgenie_config.team_routing_rules
28 | description = "Team routing rules"
29 | }
30 |
31 | output "teams" {
32 | value = module.opsgenie_config.teams
33 | description = "Teams"
34 | }
35 |
36 | output "users" {
37 | value = module.opsgenie_config.users
38 | description = "Users"
39 | }
40 |
41 | output "services" {
42 | value = module.opsgenie_config.services
43 | description = "Services"
44 | }
45 |
46 | output "service_incident_rule_ids" {
47 | value = module.opsgenie_config.service_incident_rule_ids
48 | description = "Service Incident Rule IDs"
49 | }
50 |
--------------------------------------------------------------------------------
/examples/config/resources/alert_policies.yaml:
--------------------------------------------------------------------------------
1 | alert_policies:
2 | - name: "prioritize-env-prod-critical-alerts"
3 | owner_team_name: acme.dev
4 | tags:
5 | - "ManagedBy:terraform"
6 | filter:
7 | type: match-all-conditions
8 | conditions:
9 | - field: source
10 | operation: matches
11 | expected_value: ".*prod.acme.*"
12 | - field: tags
13 | operation: contains
14 | expected_value: "severity:critical"
15 | priority: P1
16 |
--------------------------------------------------------------------------------
/examples/config/resources/api_integrations.yaml:
--------------------------------------------------------------------------------
1 | api_integrations:
2 | - name: acme-dev-opsgenie-sns-integration
3 | type: AmazonSns
4 | owner_team_name: acme.dev
5 |
--------------------------------------------------------------------------------
/examples/config/resources/escalations.yaml:
--------------------------------------------------------------------------------
1 | escalations:
2 | - name: acme.dev.some-service-escalation
3 | description: "repo: https://github.com/acme/some-service;owner:David Lightman @David Lightman"
4 | owner_team_name: acme.dev
5 | rules:
6 | - condition: if-not-acked
7 | notify_type: default
8 | delay: 0
9 | recipient:
10 | type: team
11 | team_name: acme.dev.some-service
12 |
--------------------------------------------------------------------------------
/examples/config/resources/integration_actions.yaml:
--------------------------------------------------------------------------------
1 | integration_actions:
2 | - name: acme-dev-opsgenie-sns-close-low-priority
3 | integration_name: acme-dev-opsgenie-sns-integration
4 | create:
5 | - name: Create Non-informational Alerts
6 | alias: "{{title}}"
7 | filter:
8 | type: match-all-conditions
9 | conditions:
10 | - field: priority
11 | not: true
12 | operation: equals
13 | expected_value: P5
14 |
--------------------------------------------------------------------------------
/examples/config/resources/notification_policies.yaml:
--------------------------------------------------------------------------------
1 | notification_policies:
2 | - name: auto-close-based-on-priority
3 | team_name: acme.dev
4 | auto_close_action:
5 | duration:
6 | time_amount: 60
7 | filter:
8 | type: match-all-conditions
9 | conditions:
10 | - field: priority
11 | operation: less-than
12 | expected_value: P3
13 | de_duplication_action:
14 | de_duplication_action_type: frequency-based
15 | count: 2
16 | duration:
17 | time_unit: minutes
18 | time_amount: 5
19 |
20 | - name: delay-action-test
21 | team_name: acme.dev
22 | auto_close_action:
23 | duration:
24 | time_amount: 60
25 | filter:
26 | type: match-all-conditions
27 | conditions:
28 | - field: priority
29 | operation: less-than
30 | expected_value: P3
31 | delay_action:
32 | delay_option: for-duration
33 | duration:
34 | time_unit: minutes
35 | time_amount: 5
36 |
--------------------------------------------------------------------------------
/examples/config/resources/schedule_rotations.yaml:
--------------------------------------------------------------------------------
1 | schedule_rotations:
2 | - name: acme.default.rotation
3 | schedule_name: acme-default
4 | start_date: "1970-01-01T00:00:00Z"
5 | type: weekly
6 | length: 1
7 | participants:
8 | - type: user
9 | username: opsgenie-test@cloudposse.com
10 | - type: user
11 | username: opsgenie-test-2@cloudposse.com
12 | - type: none
13 | time_restriction:
14 | type: time-of-day
15 | restrictions:
16 | - start_hour: 8
17 | start_min: 0
18 | end_hour: 20
19 | end_min: 0
20 |
--------------------------------------------------------------------------------
/examples/config/resources/schedules.yaml:
--------------------------------------------------------------------------------
1 | schedules:
2 | - name: acme-default
3 | description: "Acme Infrastructure Team"
4 | timezone: "America/Los_Angeles"
5 | owner_team_name: acme
6 | enabled: true
7 |
--------------------------------------------------------------------------------
/examples/config/resources/service_incident_rules.yaml:
--------------------------------------------------------------------------------
1 | service_incident_rules:
2 | - name: frontend-service-incident-rule-1
3 | service_name: frontend
4 |
5 | incident_rule:
6 | condition_match_type: match-all
7 |
8 | conditions:
9 | - field: message
10 | operation: matches
11 | expected_value: ".*stage.*"
12 | - field: tags
13 | operation: contains
14 | expected_value: "severity:info"
15 |
16 | incident_properties:
17 | message: This is a test message
18 | priority: P3
19 |
20 | stakeholder_properties:
21 | message: Message for stakeholders
22 | enable: true
23 |
--------------------------------------------------------------------------------
/examples/config/resources/services.yaml:
--------------------------------------------------------------------------------
1 | services:
2 | - name: frontend
3 | description: Frontend service
4 | team_name: acme
5 |
--------------------------------------------------------------------------------
/examples/config/resources/team_routing_rules.yaml:
--------------------------------------------------------------------------------
1 | team_routing_rules:
2 | - name: some-service
3 | owner_team_name: acme.dev
4 | criteria:
5 | type: match-all-conditions
6 | conditions:
7 | - field: tags
8 | operation: contains
9 | expected_value: app:some-service
10 | not: false
11 | notify:
12 | - type: escalation
13 | name: acme.dev.some-service-escalation
14 | order: 0
15 |
--------------------------------------------------------------------------------
/examples/config/resources/teams.yaml:
--------------------------------------------------------------------------------
1 | teams:
2 | - name: acme
3 | description: Global Team for Acme Co.
4 | members:
5 | username: opsgenie-test@cloudposse.com
6 | role: admin
7 | - name: acme.dev
8 | description: Acme Dev Team
9 | delete_default_resources: true
10 | members:
11 | username: opsgenie-test@cloudposse.com
12 | role: admin
13 | - name: acme.dev.some-service
14 | description: "repo: https://github.com/acme/some-service;owner:David Lightman @David Lightman"
15 | ignore_members: true
16 | delete_default_resources: true
17 | members:
18 | username: opsgenie-test@cloudposse.com
19 | role: admin
20 |
--------------------------------------------------------------------------------
/examples/config/resources/users.yaml:
--------------------------------------------------------------------------------
1 | users:
2 | - username: opsgenie-test@cloudposse.com
3 | full_name: Opsgenie Test User
4 | role: User
5 | locale: "en_US"
6 | timezone: "America/New_York"
7 |
8 | - username: opsgenie-test-2@cloudposse.com
9 | full_name: Opsgenie Test User 2
10 | role: User
11 | locale: "en_US"
12 | timezone: "America/New_York"
13 |
--------------------------------------------------------------------------------
/examples/config/variables.tf:
--------------------------------------------------------------------------------
1 | variable "opsgenie_provider_api_key" {
2 | type = string
3 | description = "The API Key for the Opsgenie Integration. If omitted, the OPSGENIE_API_KEY environment variable is used"
4 | default = null
5 | }
6 |
--------------------------------------------------------------------------------
/examples/config/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 0.13.0"
3 |
4 | required_providers {
5 | opsgenie = {
6 | source = "opsgenie/opsgenie"
7 | version = ">= 0.4"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/examples/escalation/fixtures.tfvars:
--------------------------------------------------------------------------------
1 | namespace = "eg"
2 | name = "escalation"
3 | stage = "test"
4 |
--------------------------------------------------------------------------------
/examples/escalation/main.tf:
--------------------------------------------------------------------------------
1 | provider "opsgenie" {
2 | api_key = var.opsgenie_provider_api_key
3 | }
4 |
5 | module "owner_team" {
6 | source = "../../modules/team"
7 |
8 | team = {
9 | name = format("%s-%s", module.this.id, "owner-team")
10 | description = "owner-team-description"
11 | }
12 |
13 | context = module.this.context
14 | }
15 |
16 | module "escalation_team" {
17 | source = "../../modules/team"
18 |
19 | team = {
20 | name = format("%s-%s", module.this.id, "escalation-team")
21 | description = "owner-team-description"
22 | }
23 |
24 | context = module.this.context
25 | }
26 |
27 | module "escalation" {
28 | source = "../../modules/escalation"
29 |
30 | escalation = {
31 | name = module.this.id
32 | owner_team_id = module.owner_team.team_id
33 |
34 | rules = [{
35 | delay = 0
36 | recipient = {
37 | type = "team"
38 | id = module.escalation_team.team_id
39 | }
40 | }]
41 | }
42 |
43 | context = module.this.context
44 | }
45 |
--------------------------------------------------------------------------------
/examples/escalation/outputs.tf:
--------------------------------------------------------------------------------
1 | output "escalation" {
2 | description = "Opsgenie Escalation"
3 | value = module.escalation
4 | }
5 |
6 | output "escalation_name" {
7 | description = "The Name of the Opsgenie Escalation"
8 | value = module.escalation.escalation_name
9 | }
10 |
11 | output "escalation_id" {
12 | description = "The ID of the Opsgenie Escalation"
13 | value = module.escalation.escalation_id
14 | }
15 |
--------------------------------------------------------------------------------
/examples/escalation/variables.tf:
--------------------------------------------------------------------------------
1 | variable "opsgenie_provider_api_key" {
2 | type = string
3 | description = "The API Key for the Opsgenie Integration. If omitted, the OPSGENIE_API_KEY environment variable is used"
4 | default = null
5 | }
6 |
--------------------------------------------------------------------------------
/examples/escalation/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 0.13.0"
3 |
4 | required_providers {
5 | opsgenie = {
6 | source = "opsgenie/opsgenie"
7 | version = ">= 0.4"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/examples/integration_action/fixtures.tfvars:
--------------------------------------------------------------------------------
1 | namespace = "eg"
2 | name = "integration"
3 | stage = "test"
4 |
--------------------------------------------------------------------------------
/examples/integration_action/main.tf:
--------------------------------------------------------------------------------
1 | provider "opsgenie" {
2 | api_key = var.opsgenie_provider_api_key
3 | }
4 |
5 | module "team" {
6 | source = "../../modules/team"
7 |
8 | team = {
9 | name = module.this.id
10 | }
11 |
12 | context = module.this.context
13 | }
14 |
15 | module "api_integration" {
16 | source = "../../modules/api_integration"
17 |
18 | api_integration = {
19 | name = module.this.id
20 | type = "AmazonSns"
21 | owner_team_id = module.team.team_id
22 | }
23 |
24 | context = module.this.context
25 | }
26 |
27 | module "integration_action" {
28 | source = "../../modules/integration_action"
29 |
30 | integration_action = {
31 | integration_id = module.api_integration.api_integration_id
32 | team_id = module.team.team_id
33 |
34 | create = [
35 | {
36 | name = "Create Non-informational Alerts"
37 | alias = "{{title}}"
38 | filter = {
39 | type = "match-all-conditions"
40 | conditions = [
41 | {
42 | field = "priority"
43 | not = true
44 | operation = "equals"
45 | expected_value = "P5"
46 | }
47 | ]
48 | }
49 | }
50 | ]
51 | }
52 |
53 | context = module.this.context
54 | }
55 |
--------------------------------------------------------------------------------
/examples/integration_action/outputs.tf:
--------------------------------------------------------------------------------
1 | output "integration_action" {
2 | description = "Opsgenie Integration Action"
3 | value = module.integration_action
4 | }
5 |
6 | output "integration_action_id" {
7 | description = "The ID of the Opsgenie Integration Action"
8 | value = module.integration_action.integration_action_id
9 | }
10 |
--------------------------------------------------------------------------------
/examples/integration_action/variables.tf:
--------------------------------------------------------------------------------
1 | variable "opsgenie_provider_api_key" {
2 | type = string
3 | description = "The API Key for the Opsgenie Integration. If omitted, the OPSGENIE_API_KEY environment variable is used"
4 | default = null
5 | }
6 |
--------------------------------------------------------------------------------
/examples/integration_action/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 0.13.0"
3 |
4 | required_providers {
5 | opsgenie = {
6 | source = "opsgenie/opsgenie"
7 | version = ">= 0.4"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/examples/notification_policy/fixtures.de_duplication_action.tfvars:
--------------------------------------------------------------------------------
1 | namespace = "eg"
2 | name = "notification-policy"
3 | stage = "test"
4 |
5 | de_duplication_action = {
6 | de_duplication_action_type = "frequency-based"
7 | count = 2
8 | duration = {
9 | time_unit = "minutes"
10 | time_amount = 5
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/examples/notification_policy/fixtures.delay_action.tfvars:
--------------------------------------------------------------------------------
1 | namespace = "eg"
2 | name = "notification-policy"
3 | stage = "test"
4 |
5 | delay_action = {
6 | delay_option = "for-duration"
7 | duration = {
8 | time_unit = "minutes"
9 | time_amount = 10
10 | }
11 | }
12 |
13 |
--------------------------------------------------------------------------------
/examples/notification_policy/main.tf:
--------------------------------------------------------------------------------
1 | provider "opsgenie" {
2 | api_key = var.opsgenie_provider_api_key
3 | }
4 |
5 | module "team" {
6 | source = "../../modules/team"
7 |
8 | team = {
9 | name = module.this.id
10 | description = "owner-team-description"
11 | }
12 |
13 | context = module.this.context
14 | }
15 |
16 | module "notification_policy" {
17 | source = "../../modules/notification_policy"
18 |
19 | notification_policy = {
20 | name = module.this.id
21 | team_id = module.team.team_id
22 |
23 | filter = {
24 | type = "match-all-conditions"
25 | conditions = [
26 | {
27 | field = "tags"
28 | operation = "contains"
29 | expected_value = "recommendation:auto-close"
30 | }
31 | ]
32 | }
33 |
34 | de_duplication_action = var.de_duplication_action
35 | delay_action = var.delay_action
36 |
37 | auto_close_action = {
38 | duration = {
39 | time_unit = "minutes"
40 | time_amount = 5
41 | }
42 | }
43 |
44 | auto_restart_action = {
45 | duration = {
46 | time_unit = "minutes"
47 | time_amount = 5
48 | }
49 | max_repeat_count = 3
50 | }
51 |
52 | suppress = var.suppress
53 | }
54 |
55 | context = module.this.context
56 | }
57 |
--------------------------------------------------------------------------------
/examples/notification_policy/outputs.tf:
--------------------------------------------------------------------------------
1 | output "notification_policy" {
2 | description = "Opsgenie Notification Policy"
3 | value = module.notification_policy
4 | }
5 |
6 | output "notification_policy_id" {
7 | description = "The ID of the Opsgenie Notification Policy"
8 | value = module.notification_policy.notification_policy_id
9 | }
10 |
11 | output "notification_policy_name" {
12 | description = "The name of the Opsgenie Notification Policy"
13 | value = module.notification_policy.notification_policy_name
14 | }
15 |
--------------------------------------------------------------------------------
/examples/notification_policy/variables.tf:
--------------------------------------------------------------------------------
1 | variable "opsgenie_provider_api_key" {
2 | type = string
3 | description = "The API Key for the Opsgenie Integration. If omitted, the OPSGENIE_API_KEY environment variable is used"
4 | default = null
5 | }
6 |
7 | variable "de_duplication_action" {
8 | type = object({
9 | de_duplication_action_type = string
10 | count = number
11 | duration = object({
12 | time_unit = string
13 | time_amount = number
14 | })
15 | })
16 | description = "The de-duplication action for the notification policy"
17 | default = null
18 | }
19 |
20 | variable "delay_action" {
21 | type = object({
22 | delay_option = string
23 | duration = object({
24 | time_unit = string
25 | time_amount = number
26 | })
27 | })
28 | description = "The delay action for the notification policy"
29 | default = null
30 | }
31 |
32 | variable "suppress" {
33 | type = bool
34 | description = "The suppress flag for the notification policy"
35 | default = null
36 | }
37 |
--------------------------------------------------------------------------------
/examples/notification_policy/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 0.13.0"
3 |
4 | required_providers {
5 | opsgenie = {
6 | source = "opsgenie/opsgenie"
7 | version = ">= 0.4"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/examples/schedule/fixtures.tfvars:
--------------------------------------------------------------------------------
1 | namespace = "eg"
2 | name = "schedule"
3 | stage = "test"
4 |
--------------------------------------------------------------------------------
/examples/schedule/main.tf:
--------------------------------------------------------------------------------
1 | provider "opsgenie" {
2 | api_key = var.opsgenie_provider_api_key
3 | }
4 |
5 | module "owner_team" {
6 | source = "../../modules/team"
7 |
8 | team = {
9 | name = format("%s-%s", module.this.id, "owner-team")
10 | description = "owner-team-description"
11 | }
12 |
13 | context = module.this.context
14 | }
15 |
16 | module "team_schedule" {
17 | source = "../../modules/schedule"
18 |
19 | schedule = {
20 | enabled = module.this.enabled
21 | name = module.this.id
22 | description = "team-schedule-description"
23 | owner_team_id = module.owner_team.team_id
24 | }
25 |
26 | context = module.this.context
27 | }
28 |
29 | module "schedule" {
30 | source = "../../modules/schedule"
31 |
32 | schedule = {
33 | enabled = module.this.enabled
34 | name = module.this.id
35 | description = "schedule-description"
36 | }
37 |
38 | context = module.this.context
39 | }
40 |
--------------------------------------------------------------------------------
/examples/schedule/outputs.tf:
--------------------------------------------------------------------------------
1 | output "team" {
2 | description = "Opsgenie Team"
3 | value = module.team
4 | }
5 |
6 | output "team_id" {
7 | description = "The ID of the Opsgenie Team"
8 | value = module.team.team_id
9 | }
10 |
11 | output "team_name" {
12 | description = "The name of the Opsgenie Team"
13 | value = module.team.team_name
14 | }
15 |
--------------------------------------------------------------------------------
/examples/schedule/variables.tf:
--------------------------------------------------------------------------------
1 | variable "opsgenie_provider_api_key" {
2 | type = string
3 | description = "The API Key for the Opsgenie Integration. If omitted, the OPSGENIE_API_KEY environment variable is used"
4 | default = null
5 | }
6 |
--------------------------------------------------------------------------------
/examples/schedule/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 0.13.0"
3 |
4 | required_providers {
5 | opsgenie = {
6 | source = "opsgenie/opsgenie"
7 | version = ">= 0.6.7"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/examples/team/fixtures.tfvars:
--------------------------------------------------------------------------------
1 | namespace = "eg"
2 | name = "team"
3 | stage = "test"
4 |
--------------------------------------------------------------------------------
/examples/team/main.tf:
--------------------------------------------------------------------------------
1 | provider "opsgenie" {
2 | api_key = var.opsgenie_provider_api_key
3 | }
4 |
5 | module "team" {
6 | source = "../../modules/team"
7 |
8 | team = {
9 | name = module.this.id
10 | description = "team-description"
11 | }
12 |
13 | context = module.this.context
14 | }
15 |
--------------------------------------------------------------------------------
/examples/team/outputs.tf:
--------------------------------------------------------------------------------
1 | output "team" {
2 | description = "Opsgenie Team"
3 | value = module.team
4 | }
5 |
6 | output "team_id" {
7 | description = "The ID of the Opsgenie Team"
8 | value = module.team.team_id
9 | }
10 |
11 | output "team_name" {
12 | description = "The name of the Opsgenie Team"
13 | value = module.team.team_name
14 | }
15 |
--------------------------------------------------------------------------------
/examples/team/variables.tf:
--------------------------------------------------------------------------------
1 | variable "opsgenie_provider_api_key" {
2 | type = string
3 | description = "The API Key for the Opsgenie Integration. If omitted, the OPSGENIE_API_KEY environment variable is used"
4 | default = null
5 | }
6 |
--------------------------------------------------------------------------------
/examples/team/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 0.13.0"
3 |
4 | required_providers {
5 | opsgenie = {
6 | source = "opsgenie/opsgenie"
7 | version = ">= 0.4"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/examples/team_routing_rule/fixtures.tfvars:
--------------------------------------------------------------------------------
1 | namespace = "eg"
2 | name = "team-routing-rule"
3 | stage = "test"
4 |
--------------------------------------------------------------------------------
/examples/team_routing_rule/main.tf:
--------------------------------------------------------------------------------
1 | provider "opsgenie" {
2 | api_key = var.opsgenie_provider_api_key
3 | }
4 |
5 | module "escalation_team" {
6 | source = "../../modules/team"
7 |
8 | team = {
9 | name = module.this.id
10 | description = "escalation-team-description"
11 | }
12 |
13 | context = module.this.context
14 | }
15 |
16 | module "escalation" {
17 | source = "../../modules/escalation"
18 |
19 | escalation = {
20 | name = module.this.id
21 | owner_team_id = module.owner_team.team_id
22 |
23 | rules = [{
24 | recipient = {
25 | type = "team"
26 | id = module.escalation_team.team_id
27 | }
28 | }]
29 | }
30 |
31 | context = module.this.context
32 | }
33 |
34 | module "owner_team" {
35 | source = "../../modules/team"
36 |
37 | team = {
38 | name = format("%s-%s", module.this.id, "owner-team")
39 | description = "owner-team-description"
40 | }
41 |
42 | context = module.this.context
43 | }
44 |
45 | module "team_routing_rule" {
46 | source = "../../modules/team_routing_rule"
47 |
48 | team_routing_rule = {
49 | name = module.this.id
50 | team_id = module.owner_team.team_id
51 |
52 | notify = [
53 | {
54 | type = "escalation"
55 | id = module.escalation.escalation_id
56 | }
57 | ]
58 |
59 | time_restriction = {
60 | type = "time-of-day"
61 | restrictions = [
62 | {
63 | end_hour = 17
64 | end_min = 0
65 | start_hour = 9
66 | start_min = 0
67 | }
68 | ]
69 | }
70 | }
71 |
72 | context = module.this.context
73 | }
74 |
--------------------------------------------------------------------------------
/examples/team_routing_rule/outputs.tf:
--------------------------------------------------------------------------------
1 | output "team_routing_rule" {
2 | description = "Opsgenie Team Routing Rule"
3 | value = module.team_routing_rule
4 | }
5 |
6 | output "team_routing_rule_id" {
7 | description = "The ID of the Opsgenie Team Routing Rule"
8 | value = module.team_routing_rule.team_routing_rule_id
9 | }
10 |
11 | output "team_routing_rule_name" {
12 | description = "The name of the Opsgenie Team Routing Rule"
13 | value = module.team_routing_rule.team_routing_rule_name
14 | }
15 |
--------------------------------------------------------------------------------
/examples/team_routing_rule/variables.tf:
--------------------------------------------------------------------------------
1 | variable "opsgenie_provider_api_key" {
2 | type = string
3 | description = "The API Key for the Opsgenie Integration. If omitted, the OPSGENIE_API_KEY environment variable is used"
4 | default = null
5 | }
6 |
--------------------------------------------------------------------------------
/examples/team_routing_rule/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 0.13.0"
3 |
4 | required_providers {
5 | opsgenie = {
6 | source = "opsgenie/opsgenie"
7 | version = ">= 0.4"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/examples/user/fixtures.tfvars:
--------------------------------------------------------------------------------
1 | namespace = "eg"
2 | stage = "test"
3 | name = "user"
4 |
--------------------------------------------------------------------------------
/examples/user/main.tf:
--------------------------------------------------------------------------------
1 | provider "opsgenie" {
2 | api_key = var.opsgenie_provider_api_key
3 | }
4 |
5 | module "user" {
6 | source = "../../modules/user"
7 |
8 | user = {
9 | username = format("opsgenie-test+%s@cloudposse.com", var.random_string)
10 | full_name = "Opsgenie Test User"
11 | role = "User"
12 | locale = "en_US"
13 | timezone = "America/New_York"
14 | }
15 |
16 | context = module.this.context
17 | }
18 |
--------------------------------------------------------------------------------
/examples/user/outputs.tf:
--------------------------------------------------------------------------------
1 | output "user" {
2 | description = "Opsgenie User"
3 | value = module.user
4 | }
5 |
6 | output "user_id" {
7 | description = "The ID of the Opsgenie User"
8 | value = module.user.user_id
9 | }
10 |
11 | output "user_name" {
12 | description = "The name of the Opsgenie User"
13 | value = module.user.user_name
14 | }
15 |
--------------------------------------------------------------------------------
/examples/user/variables.tf:
--------------------------------------------------------------------------------
1 | variable "opsgenie_provider_api_key" {
2 | type = string
3 | description = "The API Key for the Opsgenie Integration. If omitted, the OPSGENIE_API_KEY environment variable is used"
4 | default = null
5 | }
6 |
7 | variable "random_string" {
8 | type = string
9 | description = "A random string to append to the resource names"
10 | default = null
11 | }
12 |
--------------------------------------------------------------------------------
/examples/user/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 0.13.0"
3 |
4 | required_providers {
5 | opsgenie = {
6 | source = "opsgenie/opsgenie"
7 | version = ">= 0.4"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/main.tf:
--------------------------------------------------------------------------------
1 | provider "opsgenie" {
2 | api_key = var.opsgenie_provider_api_key
3 | }
4 |
5 | module "alert_policy" {
6 | source = "./modules/alert_policy"
7 |
8 | alert_policy = var.alert_policy
9 | context = module.this.context
10 | }
11 |
12 | module "api_integration" {
13 | source = "./modules/api_integration"
14 |
15 | api_integration = var.api_integration
16 | context = module.this.context
17 | }
18 |
19 | module "escalation" {
20 | source = "./modules/escalation"
21 |
22 | escalation = var.escalation
23 | context = module.this.context
24 | }
25 |
26 | module "integration_action" {
27 | source = "./modules/integration_action"
28 |
29 | integration_action = var.integration_action
30 | context = module.this.context
31 | }
32 |
33 | module "notification_policy" {
34 | source = "./modules/notification_policy"
35 |
36 | notification_policy = var.notification_policy
37 | context = module.this.context
38 | }
39 |
40 | module "team" {
41 | source = "./modules/team"
42 |
43 | team = var.team
44 | context = module.this.context
45 | }
46 |
47 | module "team_routing_rule" {
48 | source = "./modules/team_routing_rule"
49 |
50 | team_routing_rule = var.team_routing_rule
51 | context = module.this.context
52 | }
53 |
54 | module "user" {
55 | source = "./modules/user"
56 |
57 | user = var.user
58 | context = module.this.context
59 | }
60 |
61 | module "service" {
62 | source = "./modules/service"
63 |
64 | service = var.service
65 | context = module.this.context
66 | }
67 |
68 | module "service_incident_rule" {
69 | source = "./modules/service_incident_rule"
70 |
71 | service_incident_rule = var.service_incident_rule
72 | context = module.this.context
73 | }
74 |
--------------------------------------------------------------------------------
/modules/alert_policy/README.md:
--------------------------------------------------------------------------------
1 | ## Alert Policy
2 |
3 | Terraform module to configure [Opsgenie Alert Policy](https://registry.terraform.io/providers/opsgenie/opsgenie/latest/docs/resources/alert_policy)
4 |
5 |
6 | ## Usage
7 |
8 | [Create Opsgenie Alert Policy example](../../examples/alert_policy)
9 |
10 | ```hcl
11 | module "alert_policy" {
12 | source = "cloudposse/incident-management/opsgenie//modules/alert_policy"
13 | # Cloud Posse recommends pinning every module to a specific version
14 | # version = "x.x.x"
15 |
16 | alert_policy = {
17 | name = "alert-policy"
18 |
19 | tags = ["test1", "test2"]
20 | priority = "P1"
21 |
22 | filter = {
23 | type = "match-all-conditions"
24 | conditions = [
25 | {
26 | field = "source"
27 | operation = "matches"
28 | expected_value = ".*prod.*"
29 | },
30 | {
31 | field = "tags"
32 | operation = "contains"
33 | expected_value = "severity:critical"
34 | }
35 | ]
36 | }
37 | }
38 | }
39 | ```
40 |
41 | ## Inputs
42 |
43 | **Note:** `alert_policy` is a map for two reasons:
44 | - to be able to put whole configuration in yaml file
45 | - variables defined with type set are not robust enough (can't set default values)
46 |
47 | | Name | Default | Description | Required |
48 | |:-------------------------------|:---------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------|:--------:|
49 | | `alert_policy` | `{}` | This variable is used to configure Opsgenie Alert Policy. | Yes |
50 |
51 |
52 | ## Outputs
53 |
54 | | Name | Description |
55 | |:----------------------------|:----------------------------------------|
56 | | `alert_policy_id` | The ID of the Opsgenie Alert Policy. |
57 | | `alert_policy_name` | Name of the Opsgenie Alert Policy. |
58 | | `alert_policy_filter` | Filters of the Opsgenie Alert Policy. |
59 | | `alert_policy_tags` | Tags of the Opsgenie Alert Policy. |
60 | | `alert_policy_priority` | Priority of the Opsgenie Alert Policy. |
61 | | `alert_policy_responders` | Responders of the Opsgenie Alert Policy.|
62 |
--------------------------------------------------------------------------------
/modules/alert_policy/main.tf:
--------------------------------------------------------------------------------
1 | resource "opsgenie_alert_policy" "this" {
2 | count = module.this.enabled ? 1 : 0
3 |
4 | name = var.alert_policy.name
5 | policy_description = try(var.alert_policy.description, var.alert_policy.name)
6 | team_id = try(var.alert_policy.team_id, null)
7 |
8 | enabled = try(var.alert_policy.enabled, true)
9 | continue_policy = try(var.alert_policy.continue, true)
10 |
11 | alias = try(var.alert_policy.alias, null)
12 | entity = try(var.alert_policy.entity, null)
13 | message = try(var.alert_policy.message, "{{ message }}")
14 | priority = try(var.alert_policy.priority, null)
15 | source = try(var.alert_policy.source, null)
16 | tags = try(var.alert_policy.tags, null)
17 |
18 | ignore_original_actions = try(var.alert_policy.ignore_original_actions, false)
19 | ignore_original_details = try(var.alert_policy.ignore_original_details, false)
20 | ignore_original_responders = try(var.alert_policy.ignore_original_responders, false)
21 | ignore_original_tags = try(var.alert_policy.ignore_original_tags, false)
22 |
23 | dynamic "responders" {
24 | for_each = try(var.alert_policy.responders, [])
25 |
26 | content {
27 | id = responders.value.id
28 | name = try(responders.value.name, null)
29 | type = responders.value.type
30 | username = try(responders.value.username, null)
31 | }
32 | }
33 |
34 | filter {
35 | type = try(var.alert_policy.filter.type, "match-all")
36 |
37 | dynamic "conditions" {
38 | for_each = try(var.alert_policy.filter.conditions, [])
39 |
40 | content {
41 | expected_value = try(conditions.value.expected_value, null)
42 | field = try(conditions.value.field, null)
43 | key = try(conditions.value.key, null)
44 | not = try(conditions.value.not, null)
45 | operation = try(conditions.value.operation, null)
46 | }
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/modules/alert_policy/outputs.tf:
--------------------------------------------------------------------------------
1 | output "alert_policy_id" {
2 | description = "The ID of the Opsgenie Alert Policy"
3 | value = try(opsgenie_alert_policy.this[0].id, null)
4 | }
5 |
6 | output "alert_policy_name" {
7 | description = "Name of the Opsgenie Alert Policy"
8 | value = try(opsgenie_alert_policy.this[0].name, null)
9 | }
10 |
11 | output "alert_policy_filter" {
12 | description = "Filters of the Opsgenie Alert Policy"
13 | value = try(opsgenie_alert_policy.this[0].filter, null)
14 | }
15 |
16 | output "alert_policy_tags" {
17 | description = "Tags of the Opsgenie Alert Policy"
18 | value = try(opsgenie_alert_policy.this[0].tags, null)
19 | }
20 |
21 | output "alert_policy_priority" {
22 | description = "Priority of the Opsgenie Alert Policy"
23 | value = try(opsgenie_alert_policy.this[0].priority, null)
24 | }
25 |
26 | output "alert_policy_responders" {
27 | description = "Responders of the Opsgenie Alert Policy"
28 | value = try(opsgenie_alert_policy.this[0].responders, null)
29 | }
30 |
--------------------------------------------------------------------------------
/modules/alert_policy/variables.tf:
--------------------------------------------------------------------------------
1 | variable "alert_policy" {
2 | default = {}
3 | description = "Opsgenie Alert Policy configuration"
4 | }
5 |
--------------------------------------------------------------------------------
/modules/alert_policy/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 0.13.0"
3 |
4 | required_providers {
5 | opsgenie = {
6 | source = "opsgenie/opsgenie"
7 | version = ">= 0.4"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/modules/api_integration/README.md:
--------------------------------------------------------------------------------
1 | ## API Integration
2 |
3 | Terraform module to configure [Opsgenie API Integration](https://registry.terraform.io/providers/opsgenie/opsgenie/latest/docs/resources/api_integration)
4 |
5 |
6 | ## Usage
7 |
8 | [Create Opsgenie API Integration example](../../examples/alert_policy)
9 |
10 | ```hcl
11 | module "api_integration" {
12 | source = "cloudposse/incident-management/opsgenie//modules/api_integration"
13 | # Cloud Posse recommends pinning every module to a specific version
14 | # version = "x.x.x"
15 |
16 | api_integration = {
17 | name = module.label.id
18 | type = "AmazonSns"
19 | owner_team_id = module.team.team_id
20 | }
21 | }
22 | ```
23 |
24 | ## Inputs
25 |
26 | **Note:** `api_integration` is a map for two reasons:
27 | - to be able to put whole configuration in yaml file
28 | - variables defined with type set are not robust enough (can't set default values)
29 |
30 | | Name | Default | Description | Required |
31 | |:-------------------------------|:---------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------|:--------:|
32 | | `api_integration` | `{}` | This variable is used to configure Opsgenie API Integration. | Yes |
33 |
34 |
35 | ## Outputs
36 |
37 | | Name | Description |
38 | |:----------------------------|:-----------------------------------------|
39 | | `api_integration_api_key` | API key of the created integration |
40 | | `api_integration_name` | The name of the Opsgenie API Integration.|
41 | | `api_integration_id` | The ID of the Opsgenie API Integration. |
42 |
--------------------------------------------------------------------------------
/modules/api_integration/main.tf:
--------------------------------------------------------------------------------
1 | resource "opsgenie_api_integration" "this" {
2 | count = module.this.enabled ? 1 : 0
3 |
4 | name = var.api_integration.name
5 | type = var.api_integration.type
6 |
7 | dynamic "responders" {
8 | for_each = try(var.api_integration.responders, [])
9 |
10 | content {
11 | type = responders.value.type
12 | id = responders.value.id
13 | }
14 | }
15 |
16 | enabled = try(var.api_integration.enabled, true)
17 | allow_write_access = try(var.api_integration.allow_write_access, true)
18 | ignore_responders_from_payload = try(var.api_integration.ignore_responders_from_payload, false)
19 | suppress_notifications = try(var.api_integration.suppress_notifications, false)
20 | webhook_url = try(var.api_integration.webhook_url, null)
21 |
22 | owner_team_id = try(var.api_integration.owner_team_id, null)
23 | }
24 |
--------------------------------------------------------------------------------
/modules/api_integration/outputs.tf:
--------------------------------------------------------------------------------
1 | output "api_integration_api_key" {
2 | description = "API key of the created integration"
3 | value = try(opsgenie_api_integration.this[0].api_key, null)
4 | sensitive = true
5 | }
6 |
7 | output "api_integration_name" {
8 | description = "The name of the Opsgenie API Integration"
9 | value = try(opsgenie_api_integration.this[0].name, null)
10 | }
11 |
12 | output "api_integration_id" {
13 | description = "The ID of the Opsgenie API Integration"
14 | value = try(opsgenie_api_integration.this[0].id, null)
15 | }
16 |
--------------------------------------------------------------------------------
/modules/api_integration/variables.tf:
--------------------------------------------------------------------------------
1 | variable "api_integration" {
2 | type = map(any)
3 | default = {}
4 | description = "Opsgenie API Integration configuration"
5 | }
6 |
--------------------------------------------------------------------------------
/modules/api_integration/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 0.13.0"
3 |
4 | required_providers {
5 | opsgenie = {
6 | source = "opsgenie/opsgenie"
7 | version = ">= 0.4"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/modules/config/README.md:
--------------------------------------------------------------------------------
1 | ## Config
2 |
3 | Terraform module that configures a multitude of [Opsgenie resources](https://registry.terraform.io/providers/opsgenie/opsgenie/latest/docs).
4 | Many resources have cross-resource dependencies, which may be simpler to handle within a single module in certain cases, such as using YAML configurations.
5 |
6 | This module is designed to accept an input configuration map.
7 | One nice way of handling this is by passing resource definitions from a YAML configuration file.
8 |
9 | See below for details & examples.
10 |
11 | ## YAML Examples
12 |
13 | ### `alert_policies.yaml`
14 |
15 | ```yaml
16 | alert_policies:
17 | - name: "prioritize-env-prod-critical-alerts"
18 | owner_team_name: acme.dev
19 | tags:
20 | - "ManagedBy:terraform"
21 | filter:
22 | type: match-all-conditions
23 | conditions:
24 | - field: source
25 | operation: matches
26 | expected_value: ".*prod.acme.*"
27 | - field: tags
28 | operation: contains
29 | expected_value: "severity:critical"
30 | priority: P1
31 | ```
32 |
33 | ### `api_integrations.yaml`
34 |
35 | ```yaml
36 | api_integrations:
37 | - name: acme-dev-opsgenie-sns-integration
38 | type: AmazonSns
39 | owner_team_name: acme.dev
40 | ```
41 |
42 | ### `escalations.yaml`
43 |
44 | ```yaml
45 | escalations:
46 | - name: acme.dev.some-service-escalation
47 | description: "repo: https://github.com/acme/some-service;owner:David Lightman @David Lightman"
48 | owner_team_name: acme.dev
49 | rules:
50 | - condition: if-not-acked
51 | notify_type: default
52 | delay: 0
53 | recipient:
54 | type: team
55 | team_name: acme.dev.some-service
56 | ```
57 |
58 | ### `notification_policies.yaml`
59 |
60 | ```yaml
61 | notification_policies:
62 | - name: auto-close-based-on-priority
63 | team_name: acme.dev
64 | auto_close_action:
65 | time_amount: 60
66 | filter:
67 | type: match-all-conditions
68 | conditions:
69 | - field: priority
70 | operation: less-than
71 | expected_value: P3
72 | ```
73 |
74 | ### `schedules.yaml`
75 |
76 | ```yaml
77 | schedules:
78 | - name: acme.default
79 | description: "Acme Infrastructure Team"
80 | timezone: "America/Los_Angeles"
81 | owner_team_name: acme
82 | enabled: true
83 | ```
84 |
85 | ### `schedule_rotations.yaml`
86 |
87 | ```yaml
88 | schedule_rotations:
89 | - name: acme.default.rotation
90 | schedule_name: acme.default
91 | start_date: "1970-01-01T00:00:00Z"
92 | type: weekly
93 | length: 1
94 | participants:
95 | - type: user
96 | username: opsgenie-test@cloudposse.com
97 | - type: none
98 | - type: user
99 | username: opsgenie-test-2@cloudposse.com
100 | time_restriction:
101 | type: time-of-day
102 | restrictions:
103 | - start_hour: 8
104 | start_min: 0
105 | end_hour: 20
106 | end_min: 0
107 | ```
108 |
109 | ### `team_routing_rules.yaml`
110 |
111 | ```yaml
112 | team_routing_rules:
113 | - name: some-service
114 | owner_team_name: acme.dev
115 | criteria:
116 | type: match-all-conditions
117 | conditions:
118 | - field: tags
119 | operation: contains
120 | expected_value: app:some-service
121 | not: false
122 | notify:
123 | - type: escalation
124 | name: acme.dev.some-service-escalation
125 | order: 0
126 | ```
127 |
128 | ### `teams.yaml`
129 |
130 | ```yaml
131 | teams:
132 | - name: acme
133 | description: Global Team for Acme Co.
134 | - name: acme.dev
135 | description: Acme Dev Team
136 | - name: acme.dev.some-service
137 | description: "repo: https://github.com/acme/some-service;owner:David Lightman @David Lightman"
138 | ```
139 |
140 | ### `users.yaml`
141 |
142 | ```yaml
143 | users:
144 | - username: opsgenie-test@cloudposse.com
145 | full_name: Opsgenie Test User
146 | role: User
147 | locale: "en_US"
148 | timezone: "America/New_York"
149 | ```
150 |
151 |
152 | ### `existing_schedules.yaml`
153 |
154 | ```yaml
155 | existing_schedules:
156 | - acme.default
157 | ```
158 |
159 |
160 | ### `existing_teams.yaml`
161 |
162 | ```yaml
163 | existing_teams:
164 | - acme
165 | ```
166 |
167 |
168 | ### `existing_users.yaml`
169 |
170 | ```yaml
171 | existing_users:
172 | - username: opsgenie-test@cloudposse.com
173 | ```
174 |
175 |
176 | ### `services.yaml`
177 |
178 | ```yaml
179 | services:
180 | - name: frontend
181 | team_id: "..."
182 | description: Frontend service
183 | ```
184 |
185 | ### `service_incident_rules.yaml`
186 |
187 | ```yaml
188 | service_incident_rules:
189 | - name: frontend-service-incident-rule-1
190 | service_name: frontend
191 | incident_rule:
192 | condition_match_type: match-all
193 |
194 | conditions:
195 | - field: source
196 | operation: matches
197 | expected_value: ".*stage.*"
198 | - field: tags
199 | operation: contains
200 | expected_value: "severity:info"
201 |
202 | incident_properties:
203 | message: This is a test message
204 | priority: P3
205 |
206 | stakeholder_properties:
207 | message: Message for stakeholders
208 | enable: true
209 | ```
210 |
211 | ## Usage
212 |
213 | [Full Config Example](../../examples/config)
214 |
215 | ```hcl
216 | locals {
217 | # Build a map of our various Opsgenie resources that will be used to iterate over each module
218 | opsgenie_resources = merge([
219 | for resource_file in fileset(path.cwd, "resources/*.yaml") : {
220 | for k, v in yamldecode(file(resource_file)) : k => v
221 | }
222 | ]...)
223 | }
224 |
225 | module "opsgenie" {
226 | source = "cloudposse/incident-management/opsgenie//modules/config"
227 | # Cloud Posse recommends pinning every module to a specific version
228 | # version = "x.x.x"
229 |
230 | opsgenie_resources = local.opsgenie_resources
231 | }
232 | ```
233 |
234 | ## Inputs
235 |
236 | | Name | Default | Description | Required |
237 | |:-------------------------------|:----------------:|:-------------------------------------------------------------------------------|:--------:|
238 | | `opsgenie_resources` | `{}` | A map generated by sourcing YAML resource definitions (see above). | Yes |
239 |
240 |
241 | ## Outputs
242 |
243 | | Name | Description |
244 | |:----------------------------|:--------------------------------------------|
245 | | `alert_policies` | `name` and `id` of each alert policy |
246 | | `api_integrations` | `name` and `id` of each API integration |
247 | | `escalations` | `name` and `id` of each escalation |
248 | | `existing_schedules` | `name` and `id` of each existing schedule |
249 | | `existing_teams` | `name` and `id` of each existing team |
250 | | `existing_users` | `username` and `id` of each existing user |
251 | | `notification_policies` | `name` and `id` of each notification policy |
252 | | `schedules` | `name` and `id` of each schedules |
253 | | `schedule_rotations` | `name` and `id` of each schedule rotations |
254 | | `services` | `name` and `id` of each service |
255 | | `services` | `name` and `id` of each service |
256 | | `service_incident_rule_ids` | `id` of each service incident rule |
257 | | `team_routing_rules` | `name` and `id` of each team routing rule |
258 | | `teams` | `name` and `id` of each team |
259 | | `users` | `username` and `id` of each user |
260 |
--------------------------------------------------------------------------------
/modules/config/alert_policies.tf:
--------------------------------------------------------------------------------
1 | # https://docs.opsgenie.com/docs/alert-api
2 |
3 | resource "opsgenie_alert_policy" "this" {
4 | for_each = module.this.enabled ? { for policy in local.alert_policies : policy.name => policy } : {}
5 |
6 | name = each.value.name
7 | policy_description = try(each.value.policy_description, each.value.name)
8 | alert_description = try(each.value.alert_description, each.value.name)
9 |
10 | # Look up our team id by name
11 | team_id = try(opsgenie_team.this[each.value.owner_team_name].id, data.opsgenie_team.this[each.value.owner_team_name].id, null)
12 |
13 | enabled = try(each.value.enabled, true)
14 | continue_policy = try(each.value.continue, true)
15 |
16 | alias = try(each.value.alias, null)
17 | entity = try(each.value.entity, null)
18 | message = try(each.value.message, "{{message}}")
19 | priority = try(each.value.priority, null)
20 | source = try(each.value.source, null)
21 | tags = try(each.value.tags, null)
22 |
23 | ignore_original_actions = try(each.value.ignore_original_actions, false)
24 | ignore_original_details = try(each.value.ignore_original_details, false)
25 | ignore_original_responders = try(each.value.ignore_original_responders, false)
26 | ignore_original_tags = try(each.value.ignore_original_tags, false)
27 |
28 | dynamic "responders" {
29 | for_each = try(each.value.responders, [])
30 |
31 | content {
32 | type = responders.value.type
33 |
34 | id = lookup(responders.value, "id", null) != null ? responders.value.id : (
35 | responders.value.type == "team" ? try(opsgenie_team.this[responders.value.team_name].id, data.opsgenie_team.this[responders.value.team_name].id) : (
36 | responders.value.type == "user" ? try(opsgenie_user.this[responders.value.user_name].id, data.opsgenie_user.this[responders.value.user_name].id) : (
37 | responders.value.type == "escalation" ? opsgenie_escalation.this[responders.value.escalation_name].id : (
38 | null
39 | )
40 | )
41 | )
42 | )
43 |
44 | name = try(responders.value.name, null)
45 | username = try(responders.value.username, null)
46 | }
47 | }
48 |
49 | filter {
50 | type = try(each.value.filter.type, "match-all")
51 |
52 | dynamic "conditions" {
53 | for_each = try(each.value.filter.conditions, [])
54 |
55 | content {
56 | expected_value = try(conditions.value.expected_value, null)
57 | field = try(conditions.value.field, null)
58 | key = try(conditions.value.key, null)
59 | not = try(conditions.value.not, null)
60 | operation = try(conditions.value.operation, null)
61 | }
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/modules/config/api_integrations.tf:
--------------------------------------------------------------------------------
1 | resource "opsgenie_api_integration" "this" {
2 | for_each = module.this.enabled ? { for integration in local.api_integrations : integration.name => integration } : {}
3 |
4 | name = each.value.name
5 | type = each.value.type
6 |
7 | dynamic "responders" {
8 | for_each = try(each.value.responders, [])
9 |
10 | content {
11 | type = responders.value.type
12 | id = responders.value.id
13 | }
14 | }
15 |
16 | enabled = try(each.value.enabled, true)
17 | allow_write_access = try(each.value.allow_write_access, true)
18 | ignore_responders_from_payload = try(each.value.ignore_responders_from_payload, false)
19 | suppress_notifications = try(each.value.suppress_notifications, false)
20 | webhook_url = try(each.value.webhook_url, null)
21 |
22 | # Look up our team id by name
23 | owner_team_id = try(opsgenie_team.this[each.value.owner_team_name].id, data.opsgenie_team.this[each.value.owner_team_name].id, null)
24 | }
25 |
--------------------------------------------------------------------------------
/modules/config/escalations.tf:
--------------------------------------------------------------------------------
1 | resource "opsgenie_escalation" "this" {
2 | for_each = module.this.enabled ? { for escalation in local.escalations : escalation.name => escalation } : tomap()
3 |
4 | name = each.value.name
5 | description = try(each.value.description, each.value.name)
6 |
7 | # Look up our team id by name
8 | owner_team_id = try(opsgenie_team.this[each.value.owner_team_name].id, data.opsgenie_team.this[each.value.owner_team_name].id, null)
9 |
10 | dynamic "rules" {
11 | for_each = each.value.rules
12 |
13 | content {
14 | condition = try(rules.value.condition, "if-not-acked")
15 | notify_type = try(rules.value.notify_type, "default")
16 | delay = try(rules.value.delay, 0)
17 |
18 | recipient {
19 | type = rules.value.recipient.type
20 | id = try(rules.value.recipient.id, null) != null ? rules.value.recipient.id : (
21 | rules.value.recipient.type == "team" ? try(opsgenie_team.this[rules.value.recipient.team_name].id, data.opsgenie_team.this[rules.value.recipient.team_name].id) : (
22 | rules.value.recipient.type == "user" ? try(opsgenie_user.this[rules.value.recipient.user_name].id, data.opsgenie_user.this[rules.value.recipient.user_name].id) : (
23 | rules.value.recipient.type == "schedule" ? try(opsgenie_schedule.this[rules.value.recipient.schedule_name].id, data.opsgenie_schedule.this[rules.value.recipient.schedule_name].id) : (
24 | null
25 | )
26 | )
27 | )
28 | )
29 | }
30 | }
31 | }
32 |
33 | dynamic "repeat" {
34 | for_each = try(each.value.repeat, {})
35 |
36 | content {
37 | wait_interval = lookup(each.value.repeat, "wait_interval", 5)
38 | count = lookup(each.value.repeat, "count", 0)
39 | reset_recipient_states = lookup(each.value.repeat, "reset_recipient_states", true)
40 | close_alert_after_all = lookup(each.value.repeat, "close_alert_after_all", true)
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/modules/config/existing_resources.tf:
--------------------------------------------------------------------------------
1 | // local.existing users is a list of key pairs, in which all keys are "username".
2 | // Let's remove duplicated items from the list based on the value of each item.
3 | // Existing schedules and teams are just a plain list of their respective
4 | // resource names.
5 | locals {
6 | distinct_existing_users = distinct([for user in local.existing_users : user.username])
7 | unique_existing_users = [for u in local.distinct_existing_users : { "username" = u }]
8 |
9 | unique_existing_schedules = distinct(local.existing_schedules)
10 |
11 | unique_existing_teams = distinct(local.existing_teams)
12 | }
13 |
14 | data "opsgenie_user" "this" {
15 | for_each = module.this.enabled ? { for user in local.unique_existing_users : user.username => user } : tomap()
16 |
17 | username = each.value.username
18 | }
19 |
20 | data "opsgenie_schedule" "this" {
21 | for_each = module.this.enabled ? toset(local.unique_existing_schedules) : toset()
22 |
23 | name = each.key
24 | }
25 |
26 | data "opsgenie_team" "this" {
27 | for_each = module.this.enabled ? toset(local.unique_existing_teams) : toset()
28 |
29 | name = each.key
30 | }
31 |
--------------------------------------------------------------------------------
/modules/config/integration_actions.tf:
--------------------------------------------------------------------------------
1 | resource "opsgenie_integration_action" "this" {
2 | for_each = { for integration_action in local.integration_actions : integration_action.name => integration_action if module.this.enabled }
3 |
4 | # Look up our integration id by name
5 | integration_id = try(opsgenie_api_integration.this[each.value.integration_name].id, null)
6 |
7 | dynamic "create" {
8 | for_each = try(each.value.create, [])
9 |
10 | content {
11 | name = try(create.value.name, null)
12 | order = try(create.value.order, null)
13 | tags = try(create.value.tags, [])
14 | user = try(create.value.user, null)
15 | note = try(create.value.note, null)
16 | alias = try(create.value.alias, null)
17 | source = try(create.value.source, null)
18 | message = try(create.value.message, null)
19 | description = try(create.value.description, null)
20 | entity = try(create.value.entity, null)
21 | alert_actions = try(create.value.alert_actions, [])
22 | extra_properties = try(create.value.extra_properties, {})
23 | custom_priority = try(create.value.custom_priority, null)
24 | ignore_responders_from_payload = try(create.value.ignore_responders_from_payload, false)
25 | ignore_teams_from_payload = try(create.value.ignore_teams_from_payload, false)
26 |
27 | responders {
28 | id = try(opsgenie_api_integration.this[each.value.integration_name].owner_team_id, null)
29 | type = "team"
30 | }
31 |
32 | filter {
33 | type = try(create.value.filter.type, null)
34 |
35 | dynamic "conditions" {
36 | for_each = try(create.value.filter.conditions, [])
37 |
38 | content {
39 | field = try(conditions.value.field, null)
40 | not = try(conditions.value.not, null)
41 | operation = try(conditions.value.operation, null)
42 | expected_value = try(conditions.value.expected_value, null)
43 | }
44 | }
45 | }
46 | }
47 | }
48 |
49 | dynamic "close" {
50 | for_each = try(each.value.close, [])
51 |
52 | content {
53 | name = try(close.value.name, null)
54 | order = try(close.value.order, null)
55 | alias = try(close.value.alias, null)
56 |
57 | filter {
58 | type = try(close.value.filter.type, null)
59 |
60 | dynamic "conditions" {
61 | for_each = try(close.value.filter.conditions, [])
62 |
63 | content {
64 | field = try(conditions.value.field, null)
65 | not = try(conditions.value.not, null)
66 | operation = try(conditions.value.operation, null)
67 | expected_value = try(conditions.value.expected_value, null)
68 | }
69 | }
70 | }
71 | }
72 | }
73 |
74 | dynamic "acknowledge" {
75 | for_each = try(each.value.acknowledge, [])
76 |
77 | content {
78 | name = try(acknowledge.value.name, null)
79 | order = try(acknowledge.value.order, null)
80 | alias = try(acknowledge.value.alias, null)
81 |
82 | filter {
83 | type = try(acknowledge.value.filter.type, null)
84 |
85 | dynamic "conditions" {
86 | for_each = try(acknowledge.value.filter.conditions, [])
87 |
88 | content {
89 | field = try(conditions.value.field, null)
90 | not = try(conditions.value.not, null)
91 | operation = try(conditions.value.operation, null)
92 | expected_value = try(conditions.value.expected_value, null)
93 | }
94 | }
95 | }
96 | }
97 | }
98 |
99 | dynamic "add_note" {
100 | for_each = try(each.value.add_note, [])
101 |
102 | content {
103 | name = try(add_note.value.name, null)
104 | order = try(add_note.value.order, null)
105 | alias = try(add_note.value.alias, null)
106 | note = try(add_note.value.name, null)
107 |
108 | filter {
109 | type = try(add_note.value.filter.type, null)
110 |
111 | dynamic "conditions" {
112 | for_each = try(add_note.value.filter.conditions, [])
113 |
114 | content {
115 | field = try(conditions.value.field, null)
116 | not = try(conditions.value.not, null)
117 | operation = try(conditions.value.operation, null)
118 | expected_value = try(conditions.value.expected_value, null)
119 | }
120 | }
121 | }
122 | }
123 | }
124 |
125 | dynamic "ignore" {
126 | for_each = try(each.value.ignore, [])
127 |
128 | content {
129 | name = try(ignore.value.name, null)
130 | order = try(ignore.value.order, null)
131 |
132 | filter {
133 | type = try(ignore.value.filter.type, null)
134 |
135 | dynamic "conditions" {
136 | for_each = try(ignore.value.filter.conditions, [])
137 |
138 | content {
139 | field = try(conditions.value.field, null)
140 | not = try(conditions.value.not, null)
141 | operation = try(conditions.value.operation, null)
142 | expected_value = try(conditions.value.expected_value, null)
143 | }
144 | }
145 | }
146 | }
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/modules/config/main.tf:
--------------------------------------------------------------------------------
1 | locals {
2 | alert_policies = lookup(var.opsgenie_resources, "alert_policies", [])
3 | api_integrations = lookup(var.opsgenie_resources, "api_integrations", [])
4 | escalations = lookup(var.opsgenie_resources, "escalations", [])
5 | integration_actions = lookup(var.opsgenie_resources, "integration_actions", [])
6 | notification_policies = lookup(var.opsgenie_resources, "notification_policies", [])
7 | schedules = lookup(var.opsgenie_resources, "schedules", [])
8 | existing_schedules = lookup(var.opsgenie_resources, "existing_schedules", [])
9 | schedule_rotations = lookup(var.opsgenie_resources, "schedule_rotations", [])
10 | team_routing_rules = lookup(var.opsgenie_resources, "team_routing_rules", [])
11 | teams = lookup(var.opsgenie_resources, "teams", [])
12 | existing_teams = lookup(var.opsgenie_resources, "existing_teams", [])
13 | users = lookup(var.opsgenie_resources, "users", [])
14 | existing_users = lookup(var.opsgenie_resources, "existing_users", [])
15 | services = lookup(var.opsgenie_resources, "services", [])
16 | service_incident_rules = lookup(var.opsgenie_resources, "service_incident_rules", [])
17 | }
18 |
--------------------------------------------------------------------------------
/modules/config/notification_policies.tf:
--------------------------------------------------------------------------------
1 | resource "opsgenie_notification_policy" "this" {
2 | for_each = module.this.enabled ? { for policy in local.notification_policies : policy.name => policy } : tomap()
3 |
4 | enabled = try(each.value.enabled, true)
5 | name = each.key
6 |
7 | # Look up our team id by name
8 | team_id = try(opsgenie_team.this[each.value.team_name].id, data.opsgenie_team.this[each.value.team_name].id)
9 | policy_description = try(each.value.description, each.value.name)
10 |
11 | filter {
12 | type = try(each.value.filter.type, "match-all")
13 |
14 | dynamic "conditions" {
15 | for_each = try(each.value.filter.conditions, [])
16 |
17 | content {
18 | field = conditions.value.field
19 | operation = conditions.value.operation
20 | expected_value = try(conditions.value.expected_value, "")
21 | key = try(conditions.value.key, null)
22 | not = try(conditions.value.not, false)
23 | order = try(conditions.value.order, null)
24 | }
25 | }
26 | }
27 |
28 | dynamic "time_restriction" {
29 | for_each = try(each.value.time_restriction, null) != null ? [each.value.time_restriction] : []
30 |
31 | content {
32 | type = time_restriction.value.type
33 |
34 | dynamic "restrictions" {
35 | for_each = try(time_restriction.value.restrictions, null) != null ? [time_restriction.value.restrictions] : []
36 |
37 | content {
38 | start_day = restrictions.value.start_day
39 | end_day = restrictions.value.end_day
40 | start_hour = restrictions.value.start_hour
41 | end_hour = restrictions.value.end_hour
42 | start_min = restrictions.value.start_min
43 | end_min = restrictions.value.end_min
44 | }
45 | }
46 |
47 | dynamic "restriction" {
48 | for_each = try(time_restriction.value.restriction, null) != null ? [time_restriction.value.restriction] : []
49 |
50 | content {
51 | start_hour = restriction.value.start_hour
52 | end_hour = restriction.value.end_hour
53 | start_min = restriction.value.start_min
54 | end_min = restriction.value.end_min
55 | }
56 | }
57 | }
58 | }
59 |
60 | dynamic "auto_close_action" {
61 | for_each = try(each.value.auto_close_action, null) != null ? [each.value.auto_close_action] : []
62 |
63 | content {
64 | duration {
65 | time_amount = auto_close_action.value.duration.time_amount
66 | time_unit = try(auto_close_action.value.duration.time_unit, "minutes")
67 | }
68 | }
69 |
70 | }
71 |
72 | dynamic "auto_restart_action" {
73 | for_each = try(each.value.auto_restart_action, null) != null ? [each.value.auto_restart_action] : []
74 |
75 | content {
76 | duration {
77 | time_amount = auto_restart_action.value.duration.time_amount
78 | time_unit = try(auto_restart_action.value.duration.time_unit, "minutes")
79 | }
80 | max_repeat_count = auto_restart_action.value.max_repeat_count
81 | }
82 |
83 | }
84 |
85 | dynamic "de_duplication_action" {
86 | for_each = try(each.value.de_duplication_action, null) != null ? [each.value.de_duplication_action] : []
87 |
88 | content {
89 | de_duplication_action_type = de_duplication_action.value.de_duplication_action_type
90 | count = de_duplication_action.value.count
91 |
92 | dynamic "duration" {
93 | for_each = de_duplication_action.value.de_duplication_action_type == "frequency-based" ? [de_duplication_action.value.duration] : [try(de_duplication_action.value.duration, null)]
94 |
95 | content {
96 | time_amount = duration.value.time_amount
97 | time_unit = try(duration.value.time_unit, "minutes")
98 | }
99 | }
100 | }
101 | }
102 |
103 | dynamic "delay_action" {
104 | for_each = try(each.value.delay_action, null) != null ? [each.value.delay_action] : []
105 |
106 | content {
107 | delay_option = delay_action.value.delay_option
108 |
109 | dynamic "duration" {
110 | for_each = delay_action.value.delay_option == "for-duration" ? [delay_action.value.duration] : []
111 |
112 | content {
113 | time_amount = duration.value.time_amount
114 | time_unit = try(duration.value.time_unit, "minutes")
115 | }
116 | }
117 |
118 | until_hour = delay_action.value.delay_option != "for-duration" ? delay_action.value.until_hour : null
119 | until_minute = delay_action.value.delay_option != "for-duration" ? delay_action.value.until_minute : null
120 | }
121 | }
122 |
123 | suppress = try(each.value.suppress, null)
124 | }
125 |
--------------------------------------------------------------------------------
/modules/config/outputs.tf:
--------------------------------------------------------------------------------
1 | output "alert_policies" {
2 | value = {
3 | for policy in opsgenie_alert_policy.this : policy.id => policy.name
4 | }
5 | description = "Alert policies"
6 | }
7 |
8 | output "api_integrations" {
9 | value = {
10 | for integration in opsgenie_api_integration.this : integration.id => integration.name
11 | }
12 | description = "API integrations"
13 | }
14 |
15 | output "api_integration_keys" {
16 | value = {
17 | for integration in opsgenie_api_integration.this : integration.name => integration.api_key
18 | }
19 | description = "A map of Opsgenie API integration names and generated API keys"
20 | sensitive = true
21 | }
22 |
23 | output "escalations" {
24 | value = {
25 | for escalation in opsgenie_escalation.this : escalation.id => escalation.name
26 | }
27 | description = "Escalations"
28 | }
29 |
30 | output "integration_actions" {
31 | value = [
32 | for integration_action in opsgenie_integration_action.this : integration_action.id
33 | ]
34 | description = "Integration Actions"
35 | }
36 |
37 | output "notification_policies" {
38 | value = {
39 | for policy in opsgenie_notification_policy.this : policy.id => policy.name
40 | }
41 | description = "Notification policies"
42 | }
43 |
44 | output "schedules" {
45 | value = {
46 | for schedule in opsgenie_schedule.this : schedule.id => schedule.name
47 | }
48 | description = "Schedules"
49 | }
50 |
51 | output "schedule_rotations" {
52 | value = {
53 | for rotation in opsgenie_schedule_rotation.this : rotation.id => rotation.name
54 | }
55 | description = "Schedule rotations"
56 | }
57 |
58 | output "team_routing_rules" {
59 | value = {
60 | for rule in opsgenie_team_routing_rule.this : rule.id => rule.name
61 | }
62 | description = "Team routing rules"
63 | }
64 |
65 | output "teams" {
66 | value = {
67 | for team in opsgenie_team.this : team.id => team.name
68 | }
69 | description = "Teams"
70 | }
71 |
72 | output "users" {
73 | value = {
74 | for user in opsgenie_user.this : user.id => user.username
75 | }
76 | description = "Users"
77 | }
78 |
79 | output "existing_users" {
80 | value = {
81 | for user in data.opsgenie_user.this : user.id => user.username
82 | }
83 | description = "Users that already exist in Opsgenie"
84 | }
85 |
86 | output "services" {
87 | value = {
88 | for service in opsgenie_service.this : service.id => service.name
89 | }
90 | description = "Services"
91 | }
92 |
93 | output "service_incident_rule_ids" {
94 | value = [
95 | for service_incident_rule in opsgenie_service_incident_rule.this : service_incident_rule.id
96 | ]
97 | description = "Service Incident Rule IDs"
98 | }
99 |
--------------------------------------------------------------------------------
/modules/config/schedule_rotations.tf:
--------------------------------------------------------------------------------
1 | resource "opsgenie_schedule_rotation" "this" {
2 | for_each = module.this.enabled ? { for schedule_rotation in local.schedule_rotations : schedule_rotation.name => schedule_rotation } : tomap()
3 |
4 | name = each.value.name
5 | type = each.value.type
6 |
7 | start_date = each.value.start_date
8 | end_date = try(each.value.end_date, null)
9 | length = try(each.value.length, null)
10 |
11 | # Look up our schedule id by name
12 | schedule_id = try(opsgenie_schedule.this[each.value.schedule_name].id, data.opsgenie_schedule.this[each.value.schedule_name].id, null)
13 |
14 | dynamic "participant" {
15 | for_each = try(each.value.participants, [])
16 |
17 | content {
18 | type = participant.value.type
19 | id = participant.value.type == "none" ? null : try(opsgenie_user.this[participant.value.username].id, data.opsgenie_user.this[participant.value.username].id)
20 | }
21 | }
22 |
23 | dynamic "time_restriction" {
24 | for_each = try(each.value.time_restriction, null) != null ? ["true"] : []
25 |
26 | content {
27 | type = each.value.time_restriction.type
28 |
29 | dynamic "restriction" {
30 | for_each = each.value.time_restriction.type == "time-of-day" ? each.value.time_restriction.restrictions : []
31 |
32 | content {
33 | start_hour = restriction.value.start_hour
34 | start_min = restriction.value.start_min
35 | end_hour = restriction.value.end_hour
36 | end_min = restriction.value.end_min
37 | }
38 | }
39 |
40 | dynamic "restrictions" {
41 | for_each = each.value.time_restriction.type == "weekday-and-time-of-day" ? each.value.time_restriction.restrictions : []
42 |
43 | content {
44 | start_day = restrictions.value.start_day
45 | end_day = restrictions.value.end_day
46 | start_hour = restrictions.value.start_hour
47 | start_min = restrictions.value.start_min
48 | end_hour = restrictions.value.end_hour
49 | end_min = restrictions.value.end_min
50 | }
51 | }
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/modules/config/schedules.tf:
--------------------------------------------------------------------------------
1 | resource "opsgenie_schedule" "this" {
2 | for_each = module.this.enabled ? { for schedule in local.schedules : schedule.name => schedule } : tomap()
3 |
4 | enabled = try(each.value.enabled, true)
5 |
6 | name = each.value.name
7 | description = try(each.value.description, each.value.name)
8 | timezone = try(each.value.timezone, each.value.name)
9 |
10 | # Look up our team id by name
11 | owner_team_id = try(opsgenie_team.this[each.value.owner_team_name].id, data.opsgenie_team.this[each.value.owner_team_name].id, null)
12 | }
13 |
--------------------------------------------------------------------------------
/modules/config/service_incident_rules.tf:
--------------------------------------------------------------------------------
1 | resource "opsgenie_service_incident_rule" "this" {
2 | for_each = module.this.enabled ? { for service_incident_rule in local.service_incident_rules : service_incident_rule.name => service_incident_rule } : tomap()
3 |
4 | service_id = opsgenie_service.this[each.value.service_name].id
5 |
6 | incident_rule {
7 | condition_match_type = try(each.value.incident_rule.condition_match_type, "match-all")
8 |
9 | dynamic "conditions" {
10 | for_each = try(each.value.incident_rule.conditions, [])
11 |
12 | content {
13 | expected_value = try(conditions.value.expected_value, null)
14 | field = conditions.value.field
15 | not = try(conditions.value.not, null)
16 | operation = conditions.value.operation
17 | }
18 | }
19 |
20 | incident_properties {
21 | message = each.value.incident_rule.incident_properties.message
22 | priority = each.value.incident_rule.incident_properties.priority
23 | tags = try(each.value.incident_rule.incident_properties.tags, null)
24 | details = try(each.value.incident_rule.incident_properties.details, null)
25 |
26 | stakeholder_properties {
27 | message = each.value.incident_rule.incident_properties.stakeholder_properties.message
28 | description = try(each.value.incident_rule.incident_properties.stakeholder_properties.description, null)
29 | enable = try(each.value.incident_rule.incident_properties.stakeholder_properties.enable, null)
30 | }
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/modules/config/services.tf:
--------------------------------------------------------------------------------
1 | resource "opsgenie_service" "this" {
2 | for_each = module.this.enabled ? { for service in local.services : service.name => service } : tomap()
3 |
4 | name = each.value.name
5 | team_id = try(opsgenie_team.this[each.value.team_name].id, data.opsgenie_team.this[each.value.team_name].id)
6 | description = try(each.value.description, null)
7 | }
8 |
--------------------------------------------------------------------------------
/modules/config/team_routing_rules.tf:
--------------------------------------------------------------------------------
1 | resource "opsgenie_team_routing_rule" "this" {
2 | for_each = module.this.enabled ? { for rule in local.team_routing_rules : rule.name => rule } : tomap()
3 |
4 | name = each.value.name
5 |
6 | is_default = try(each.value.is_default, false)
7 |
8 | # Look up Team ID by name
9 | team_id = try(opsgenie_team.this[each.value.owner_team_name].id, data.opsgenie_team.this[each.value.owner_team_name].id)
10 |
11 | order = try(each.value.order, 0)
12 | timezone = try(each.value.timezone, "America/Los_Angeles")
13 |
14 | dynamic "criteria" {
15 | for_each = try(each.value.criteria, null) != null ? ["true"] : []
16 |
17 | content {
18 | type = lookup(each.value.criteria, "type", "match-all")
19 |
20 | dynamic "conditions" {
21 | for_each = lookup(each.value.criteria, "conditions", [])
22 |
23 | content {
24 | expected_value = try(conditions.value.expected_value, null)
25 | field = try(conditions.value.field, null)
26 | key = try(conditions.value.key, null)
27 | not = try(conditions.value.not, null)
28 | operation = try(conditions.value.operation, null)
29 | order = try(conditions.value.order, null)
30 | }
31 | }
32 | }
33 | }
34 |
35 | dynamic "notify" {
36 | for_each = try(each.value.notify, [])
37 |
38 | content {
39 | type = notify.value.type
40 | id = opsgenie_escalation.this[notify.value.name].id
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/modules/config/teams.tf:
--------------------------------------------------------------------------------
1 | resource "opsgenie_team" "this" {
2 | for_each = module.this.enabled ? { for team in local.teams : team.name => team } : tomap()
3 |
4 | name = each.value.name
5 | description = try(each.value.description, each.value.name)
6 | ignore_members = try(each.value.ignore_members, false)
7 | delete_default_resources = try(each.value.delete_default_resources, false)
8 |
9 | dynamic "member" {
10 | for_each = try(tolist(each.value.members), [])
11 |
12 | content {
13 | id = try(opsgenie_user.this[member.value.username].id, data.opsgenie_user.this[member.value.username].id)
14 | role = try(member.value.role, null)
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/modules/config/users.tf:
--------------------------------------------------------------------------------
1 | resource "opsgenie_user" "this" {
2 | for_each = module.this.enabled ? { for user in local.users : user.username => user } : tomap()
3 |
4 | username = each.value.username
5 | full_name = each.value.full_name
6 | role = each.value.role
7 | locale = try(each.value.locale, "en_US")
8 | timezone = try(each.value.timezone, "America/New_York")
9 | }
10 |
--------------------------------------------------------------------------------
/modules/config/variables.tf:
--------------------------------------------------------------------------------
1 | variable "opsgenie_resources" {
2 | default = {}
3 | description = "Map that contains all Opsgenie resource definitions"
4 | }
5 |
--------------------------------------------------------------------------------
/modules/config/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 0.13.0"
3 |
4 | required_providers {
5 | opsgenie = {
6 | source = "opsgenie/opsgenie"
7 | version = ">= 0.4"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/modules/escalation/README.md:
--------------------------------------------------------------------------------
1 | ## Escalation
2 |
3 | Terraform module to configure [Opsgenie Escalation](https://registry.terraform.io/providers/opsgenie/opsgenie/latest/docs/resources/escalation)
4 |
5 |
6 | ## Usage
7 |
8 | [Create Opsgenie Escalation example](../../examples/escalation)
9 |
10 | ```hcl
11 | module "escalation" {
12 | source = "cloudposse/incident-management/opsgenie//modules/escalation"
13 | # Cloud Posse recommends pinning every module to a specific version
14 | # version = "x.x.x"
15 |
16 | escalation = {
17 | name = module.label.id
18 | owner_team_id = module.owner_team.team_id
19 |
20 | rules = [{
21 | recipient = {
22 | type = "team"
23 | id = module.escalation_team.team_id
24 | }
25 | }]
26 | }
27 |
28 | }
29 |
30 | ```
31 |
32 | ## Inputs
33 |
34 | **Note:** `escalation` is a map for two reasons:
35 | - to be able to put whole configuration in yaml file
36 | - variables defined with type set are not robust enough (can't set default values)
37 |
38 | | Name | Default | Description | Required |
39 | |:-------------------------------|:---------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------|:--------:|
40 | | `escalation` | `{}` | This variable is used to configure Opsgenie Escalation. | Yes |
41 |
42 |
43 | ## Outputs
44 |
45 | | Name | Description |
46 | |:----------------------------|:-----------------------------------------|
47 | | `escalation_name` | The name of the Opsgenie Escalation.|
48 | | `escalation_id` | The ID of the Opsgenie Escalation. |
49 |
--------------------------------------------------------------------------------
/modules/escalation/main.tf:
--------------------------------------------------------------------------------
1 | resource "opsgenie_escalation" "this" {
2 | count = module.this.enabled ? 1 : 0
3 |
4 | name = var.escalation.name
5 | description = try(var.escalation.description, var.escalation.name)
6 | owner_team_id = try(var.escalation.owner_team_id, null)
7 |
8 | dynamic "rules" {
9 | for_each = var.escalation.rules
10 |
11 | content {
12 | condition = try(rules.value.condition, "if-not-acked")
13 | notify_type = try(rules.value.notify_type, "default")
14 | delay = try(rules.value.delay, 0)
15 |
16 | recipient {
17 | type = rules.value.recipient.type
18 | id = try(rules.value.recipient.id, null)
19 | }
20 | }
21 | }
22 |
23 | dynamic "repeat" {
24 | for_each = try(var.escalation.repeat, null) != null ? ["true"] : []
25 |
26 | content {
27 | wait_interval = try(var.escalation.repeat.wait_interval, 5)
28 | count = try(var.escalation.repeat.count, 0)
29 | reset_recipient_states = try(var.escalation.repeat.reset_recipient_states, true)
30 | close_alert_after_all = try(var.escalation.repeat.close_alert_after_all, true)
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/modules/escalation/outputs.tf:
--------------------------------------------------------------------------------
1 | output "escalation_id" {
2 | description = "The ID of the Opsgenie Escalation"
3 | value = try(opsgenie_escalation.this[0].id, null)
4 | }
5 |
6 | output "escalation_name" {
7 | description = "Name of the Opsgenie Escalation"
8 | value = try(opsgenie_escalation.this[0].name, null)
9 | }
10 |
--------------------------------------------------------------------------------
/modules/escalation/variables.tf:
--------------------------------------------------------------------------------
1 | variable "escalation" {
2 | default = {}
3 | description = "Opsgenie Escalation configuration"
4 | }
5 |
--------------------------------------------------------------------------------
/modules/escalation/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 0.13.0"
3 |
4 | required_providers {
5 | opsgenie = {
6 | source = "opsgenie/opsgenie"
7 | version = ">= 0.4"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/modules/integration_action/README.md:
--------------------------------------------------------------------------------
1 | ## Integration Action
2 |
3 | Terraform module to configure [Opsgenie Integration Action](https://registry.terraform.io/providers/opsgenie/opsgenie/latest/docs/resources/integration_action)
4 |
5 | NOTE: your OpsGenie plan must support advanced integrations. Otherwise, you will get the following error back from the API: `Your plan does not allow saving advanced integrations.`.
6 |
7 |
8 | ## Usage
9 |
10 | [Create Opsgenie Integration Action example](../../examples/integration_action)
11 |
12 | ```hcl
13 | module "integration_action" {
14 | source = "cloudposse/incident-management/opsgenie//modules/integration_action"
15 | # Cloud Posse recommends pinning every module to a specific version
16 | # version = "x.x.x"
17 |
18 | integration_action = {
19 | integration_id = module.api_integration.api_integration_id
20 |
21 | create = [
22 | {
23 | name = "Create Non-informational Alerts"
24 | alias = "{{title}}"
25 | filter = {
26 | type = "match-all-conditions"
27 | conditions = [
28 | {
29 | field = "priority"
30 | not = true
31 | operation = "equals"
32 | expected_value = "P5"
33 | }
34 | ]
35 | }
36 | }
37 | ]
38 | }
39 | }
40 | ```
41 |
42 | ## Inputs
43 |
44 | **Note:** `integration_action` is a map for two reasons:
45 | - to be able to put whole configuration in yaml file
46 | - variables defined with type set are not robust enough (can't set default values)
47 |
48 | | Name | Default | Description | Required |
49 | |:-------------------------------|:---------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------|:--------:|
50 | | `integration_action` | `{}` | This variable is used to configure Opsgenie Integration Action. | Yes |
51 |
52 |
53 | ## Outputs
54 |
55 | | Name | Description |
56 | |:----------------------------|:---------------------------------------------|
57 | | `integration_action_id` | The ID of the Opsgenie Integration Action. |
58 |
--------------------------------------------------------------------------------
/modules/integration_action/main.tf:
--------------------------------------------------------------------------------
1 | resource "opsgenie_integration_action" "this" {
2 | count = module.this.enabled ? 1 : 0
3 |
4 | integration_id = var.integration_action.integration_id
5 |
6 | dynamic "create" {
7 | for_each = try(var.integration_action.create, [])
8 |
9 | content {
10 | name = try(create.value.name, null)
11 | order = try(create.value.order, null)
12 | tags = try(create.value.tags, [])
13 | user = try(create.value.user, null)
14 | note = try(create.value.note, null)
15 | alias = try(create.value.alias, null)
16 | source = try(create.value.source, null)
17 | message = try(create.value.message, null)
18 | description = try(create.value.description, null)
19 | entity = try(create.value.entity, null)
20 | alert_actions = try(create.value.alert_actions, [])
21 | extra_properties = try(create.value.extra_properties, {})
22 | custom_priority = try(create.value.custom_priority, null)
23 | ignore_responders_from_payload = try(create.value.ignore_responders_from_payload, false)
24 | ignore_teams_from_payload = try(create.value.ignore_teams_from_payload, false)
25 |
26 | responders {
27 | id = var.integration_action.team_id
28 | type = "team"
29 | }
30 |
31 | filter {
32 | type = try(create.value.filter.type, null)
33 |
34 | dynamic "conditions" {
35 | for_each = try(create.value.filter.conditions, [])
36 |
37 | content {
38 | field = try(conditions.value.field, null)
39 | not = try(conditions.value.not, null)
40 | operation = try(conditions.value.operation, null)
41 | expected_value = try(conditions.value.expected_value, null)
42 | }
43 | }
44 | }
45 | }
46 | }
47 |
48 | dynamic "close" {
49 | for_each = try(var.integration_action.close, [])
50 |
51 | content {
52 | name = try(close.value.name, null)
53 | order = try(close.value.order, null)
54 | alias = try(close.value.alias, null)
55 |
56 | filter {
57 | type = try(close.value.filter.type, null)
58 |
59 | dynamic "conditions" {
60 | for_each = try(close.value.filter.conditions, [])
61 |
62 | content {
63 | field = try(conditions.value.field, null)
64 | not = try(conditions.value.not, null)
65 | operation = try(conditions.value.operation, null)
66 | expected_value = try(conditions.value.expected_value, null)
67 | }
68 | }
69 | }
70 | }
71 | }
72 |
73 | dynamic "acknowledge" {
74 | for_each = try(var.integration_action.acknowledge, [])
75 |
76 | content {
77 | name = try(acknowledge.value.name, null)
78 | order = try(acknowledge.value.order, null)
79 | alias = try(acknowledge.value.alias, null)
80 |
81 | filter {
82 | type = try(acknowledge.value.filter.type, null)
83 |
84 | dynamic "conditions" {
85 | for_each = try(acknowledge.value.filter.conditions, [])
86 |
87 | content {
88 | field = try(conditions.value.field, null)
89 | not = try(conditions.value.not, null)
90 | operation = try(conditions.value.operation, null)
91 | expected_value = try(conditions.value.expected_value, null)
92 | }
93 | }
94 | }
95 | }
96 | }
97 |
98 | dynamic "add_note" {
99 | for_each = try(var.integration_action.add_note, [])
100 |
101 | content {
102 | name = try(add_note.value.name, null)
103 | order = try(add_note.value.order, null)
104 | alias = try(add_note.value.alias, null)
105 | note = try(add_note.value.name, null)
106 |
107 | filter {
108 | type = try(add_note.value.filter.type, null)
109 |
110 | dynamic "conditions" {
111 | for_each = try(add_note.value.filter.conditions, [])
112 |
113 | content {
114 | field = try(conditions.value.field, null)
115 | not = try(conditions.value.not, null)
116 | operation = try(conditions.value.operation, null)
117 | expected_value = try(conditions.value.expected_value, null)
118 | }
119 | }
120 | }
121 | }
122 | }
123 |
124 | dynamic "ignore" {
125 | for_each = try(var.integration_action.ignore, [])
126 |
127 | content {
128 | name = try(ignore.value.name, null)
129 | order = try(ignore.value.order, null)
130 |
131 | filter {
132 | type = try(ignore.value.filter.type, null)
133 |
134 | dynamic "conditions" {
135 | for_each = try(ignore.value.filter.conditions, [])
136 |
137 | content {
138 | field = try(conditions.value.field, null)
139 | not = try(conditions.value.not, null)
140 | operation = try(conditions.value.operation, null)
141 | expected_value = try(conditions.value.expected_value, null)
142 | }
143 | }
144 | }
145 | }
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/modules/integration_action/outputs.tf:
--------------------------------------------------------------------------------
1 | output "integration_action_id" {
2 | description = "The ID of the Opsgenie Integration Action"
3 | value = try(opsgenie_integration_action.this[0].id, null)
4 | }
5 |
--------------------------------------------------------------------------------
/modules/integration_action/variables.tf:
--------------------------------------------------------------------------------
1 | variable "integration_action" {
2 | default = {}
3 | description = "Opsgenie Integration Action configuration"
4 | }
5 |
--------------------------------------------------------------------------------
/modules/integration_action/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 0.13.0"
3 |
4 | required_providers {
5 | opsgenie = {
6 | source = "opsgenie/opsgenie"
7 | version = ">= 0.4"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/modules/notification_policy/README.md:
--------------------------------------------------------------------------------
1 | ## Notification Policy
2 |
3 | Terraform module to configure [Opsgenie Notification Policy](https://registry.terraform.io/providers/opsgenie/opsgenie/latest/docs/resources/notification_policy)
4 |
5 |
6 | ## Usage
7 |
8 | [Create Opsgenie Notification Policy example](../../examples/notification_policy)
9 |
10 | ```hcl
11 | module "notification_policy" {
12 | source = "cloudposse/incident-management/opsgenie//modules/notification_policy"
13 | # Cloud Posse recommends pinning every module to a specific version
14 | # version = "x.x.x"
15 |
16 | notification_policy = {
17 | name = module.label.id
18 | team_id = module.team.team_id
19 |
20 | filter = {
21 | type = "match-all-conditions"
22 | conditions = [{
23 | field = "tags"
24 | operation = "contains"
25 | expected_value = "recommendation:auto-close"
26 | }]
27 | }
28 |
29 | de_duplication_action = {
30 | de_duplication_action_type = "frequency-based"
31 | count = 2
32 | duration = {
33 | time_unit = "minutes"
34 | time_amount = 5
35 | }
36 | }
37 |
38 | delay_action = {
39 | delay_option = "for-duration"
40 | duration = {
41 | time_unit = "minutes"
42 | time_amount = 10
43 | }
44 | }
45 |
46 | auto_close_action = {
47 | time_unit = "minutes"
48 | time_amount = 5
49 | }
50 | }
51 | }
52 | ```
53 |
54 | ## Inputs
55 |
56 | **Note:** `notification_policy` is a map for two reasons:
57 | - to be able to put whole configuration in yaml file
58 | - variables defined with type set are not robust enough (can't set default values)
59 |
60 | | Name | Default | Description | Required |
61 | |:-------------------------------|:---------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------|:--------:|
62 | | `notification_policy` | `{}` | This variable is used to configure Opsgenie Notification Policy. | Yes |
63 |
64 |
65 | ## Outputs
66 |
67 | | Name | Description |
68 | |:----------------------------|:---------------------------------------------|
69 | | `notification_policy_name` | The name of the Opsgenie Notification Policy.|
70 | | `notification_policy_id` | The ID of the Opsgenie Notification Policy. |
71 |
--------------------------------------------------------------------------------
/modules/notification_policy/main.tf:
--------------------------------------------------------------------------------
1 | resource "opsgenie_notification_policy" "this" {
2 | count = module.this.enabled ? 1 : 0
3 |
4 | enabled = try(var.notification_policy.enabled, true)
5 | name = var.notification_policy.name
6 |
7 | # Look up our team id by name
8 | team_id = var.notification_policy.team_id
9 | policy_description = try(var.notification_policy.description, var.notification_policy.name)
10 |
11 | filter {
12 | type = try(var.notification_policy.filter.type, "match-all")
13 |
14 | dynamic "conditions" {
15 | for_each = try(var.notification_policy.filter.conditions, [])
16 |
17 | content {
18 | field = conditions.value.field
19 | operation = conditions.value.operation
20 | expected_value = try(conditions.value.expected_value, "")
21 | key = try(conditions.value.key, null)
22 | not = try(conditions.value.not, false)
23 | order = try(conditions.value.order, null)
24 | }
25 | }
26 | }
27 |
28 | dynamic "time_restriction" {
29 | for_each = try(var.notification_policy.time_restriction, null) != null ? [var.notification_policy.time_restriction] : []
30 |
31 | content {
32 | type = time_restriction.value.type
33 |
34 | dynamic "restrictions" {
35 | for_each = try(time_restriction.value.restrictions, null) != null ? [time_restriction.value.restrictions] : []
36 |
37 | content {
38 | start_day = restrictions.value.start_day
39 | end_day = restrictions.value.end_day
40 | start_hour = restrictions.value.start_hour
41 | end_hour = restrictions.value.end_hour
42 | start_min = restrictions.value.start_min
43 | end_min = restrictions.value.end_min
44 | }
45 | }
46 |
47 | dynamic "restriction" {
48 | for_each = try(time_restriction.value.restriction, null) != null ? [time_restriction.value.restriction] : []
49 |
50 | content {
51 | start_hour = restriction.value.start_hour
52 | end_hour = restriction.value.end_hour
53 | start_min = restriction.value.start_min
54 | end_min = restriction.value.end_min
55 | }
56 | }
57 | }
58 | }
59 |
60 | dynamic "auto_close_action" {
61 | for_each = try(var.notification_policy.auto_close_action, null) != null ? [var.notification_policy.auto_close_action] : []
62 |
63 | content {
64 | duration {
65 | time_amount = auto_close_action.value.duration.time_amount
66 | time_unit = try(auto_close_action.value.duration.time_unit, "minutes")
67 | }
68 | }
69 |
70 | }
71 |
72 | dynamic "auto_restart_action" {
73 | for_each = try(var.notification_policy.auto_restart_action, null) != null ? [var.notification_policy.auto_restart_action] : []
74 |
75 | content {
76 | duration {
77 | time_amount = auto_restart_action.value.duration.time_amount
78 | time_unit = try(auto_restart_action.value.duration.time_unit, "minutes")
79 | }
80 | max_repeat_count = auto_restart_action.value.max_repeat_count
81 | }
82 |
83 | }
84 |
85 | dynamic "de_duplication_action" {
86 | for_each = try(var.notification_policy.de_duplication_action, null) != null ? [var.notification_policy.de_duplication_action] : []
87 |
88 | content {
89 | de_duplication_action_type = de_duplication_action.value.de_duplication_action_type
90 | count = de_duplication_action.value.count
91 |
92 | dynamic "duration" {
93 | for_each = de_duplication_action.value.de_duplication_action_type == "frequency-based" ? [de_duplication_action.value.duration] : [try(de_duplication_action.value.duration, null)]
94 |
95 | content {
96 | time_amount = duration.value.time_amount
97 | time_unit = try(duration.value.time_unit, "minutes")
98 | }
99 | }
100 | }
101 | }
102 |
103 | dynamic "delay_action" {
104 | for_each = try(var.notification_policy.delay_action, null) != null ? [var.notification_policy.delay_action] : []
105 |
106 | content {
107 | delay_option = delay_action.value.delay_option
108 |
109 | dynamic "duration" {
110 | for_each = delay_action.value.delay_option == "for-duration" ? [delay_action.value.duration] : []
111 |
112 | content {
113 | time_amount = duration.value.time_amount
114 | time_unit = try(duration.value.time_unit, "minutes")
115 | }
116 | }
117 |
118 | until_hour = delay_action.value.delay_option != "for-duration" ? delay_action.value.until_hour : null
119 | until_minute = delay_action.value.delay_option != "for-duration" ? delay_action.value.until_minute : null
120 | }
121 | }
122 |
123 | suppress = try(var.notification_policy.suppress, null)
124 | }
125 |
--------------------------------------------------------------------------------
/modules/notification_policy/outputs.tf:
--------------------------------------------------------------------------------
1 | output "notification_policy_id" {
2 | description = "The ID of the Opsgenie Notification Policy"
3 | value = try(opsgenie_notification_policy.this[0].id, null)
4 | }
5 |
6 | output "notification_policy_name" {
7 | description = "The name of the Opsgenie Notification Policy"
8 | value = try(opsgenie_notification_policy.this[0].name, null)
9 | }
10 |
--------------------------------------------------------------------------------
/modules/notification_policy/variables.tf:
--------------------------------------------------------------------------------
1 | variable "notification_policy" {
2 | default = {}
3 | description = "Opsgenie Notification Policy configuration"
4 | }
5 |
--------------------------------------------------------------------------------
/modules/notification_policy/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 0.13.0"
3 |
4 | required_providers {
5 | opsgenie = {
6 | source = "opsgenie/opsgenie"
7 | version = ">= 0.4"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/modules/schedule/README.md:
--------------------------------------------------------------------------------
1 | ## schedule
2 |
3 | Terraform module to configure [Opsgenie Schedule](https://registry.terraform.io/providers/opsgenie/opsgenie/latest/docs/resources/schedule)
4 |
5 |
6 | ## Usage
7 |
8 | [Opsgenie Schedule example](../../examples/schedule)
9 |
10 | ```hcl
11 | module "schedule" {
12 | source = "cloudposse/incident-management/opsgenie//modules/schedule"
13 | # Cloud Posse recommends pinning every module to a specific version
14 | # version = "x.x.x"
15 |
16 | schedule = {
17 | name = module.label.id
18 | description = "schedule-description"
19 | }
20 | }
21 |
22 | data "opsgenie_team" "the_team" {
23 | name = var.team_name
24 | }
25 |
26 | module "team_schedule" {
27 |
28 | source = "cloudposse/incident-management/opsgenie//modules/schedule"
29 | # Cloud Posse recommends pinning every module to a specific version
30 | # version = "x.x.x"
31 |
32 | schedule = {
33 | name = module.label.id
34 | description = "team-schedule-description"
35 | owner_team_id = data.opsgenie_team.the_team.id
36 | }
37 | }
38 | ```
39 |
40 | ## Inputs
41 |
42 | **Note:** `schedule` is a map for two reasons:
43 | - to be able to put whole configuration in yaml file
44 | - variables defined with type set are not robust enough (can't set default values)
45 |
46 | | Name | Default | Description | Required |
47 | |:-------------------------------|:---------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------|:--------:|
48 | | `schedule` | `{}` | This variable is used to configure Opsgenie schedule. | Yes |
49 |
50 |
51 | ## Outputs
52 |
53 | | Name | Description |
54 | |:----------------------------|:-----------------------------------------|
55 | | `schedule_name` | The name of the Opsgenie schedule. |
56 | | `schedule_id` | The ID of the Opsgenie schedule. |
57 |
--------------------------------------------------------------------------------
/modules/schedule/main.tf:
--------------------------------------------------------------------------------
1 | resource "opsgenie_schedule" "default" {
2 | count = module.this.enabled ? 1 : 0
3 |
4 | name = var.schedule.name
5 | description = try(var.schedule.description, null)
6 | owner_team_id = try(var.schedule.owner_team_id, null)
7 |
8 | enabled = try(var.schedule.enabled, null) # this is the state of the schedule, NOT module.this.enabled
9 | timezone = try(var.schedule.timezone, null)
10 | }
11 |
--------------------------------------------------------------------------------
/modules/schedule/outputs.tf:
--------------------------------------------------------------------------------
1 | output "schedule_id" {
2 | description = "The ID of the Opsgenie Schedule"
3 | value = try(opsgenie_schedule.default[0].id, null)
4 | }
5 |
--------------------------------------------------------------------------------
/modules/schedule/variables.tf:
--------------------------------------------------------------------------------
1 | variable "schedule" {
2 | type = map(any)
3 | default = {}
4 | description = "Opsgenie Schedule configuration"
5 | }
6 |
--------------------------------------------------------------------------------
/modules/schedule/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 0.13.0"
3 |
4 | required_providers {
5 | opsgenie = {
6 | source = "opsgenie/opsgenie"
7 | version = ">= 0.6.7"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/modules/service/README.md:
--------------------------------------------------------------------------------
1 | ## Service
2 |
3 | Terraform module to configure [Opsgenie Service](https://registry.terraform.io/providers/opsgenie/opsgenie/latest/docs/resources/service)
4 |
5 |
6 | ## Usage
7 |
8 | ```hcl
9 | module "service" {
10 | source = "cloudposse/incident-management/opsgenie//modules/service"
11 | # Cloud Posse recommends pinning every module to a specific version
12 | # version = "x.x.x"
13 |
14 | service = {
15 | name = "frontend"
16 | team_id = "..."
17 | description = "My company frontend service"
18 | }
19 | }
20 | ```
21 |
22 | ## Inputs
23 |
24 | **Note:** `service` is a map for two reasons:
25 | - to be able to put whole configuration in yaml file
26 | - variables defined with type set are not robust enough (can't set default values)
27 |
28 | | Name | Default | Description | Required |
29 | |:-------------------------------|:---------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------|:--------:|
30 | | `service` | `{}` | Opsgenie Service configuration | Yes |
31 |
32 |
33 | ## Outputs
34 |
35 | | Name | Description |
36 | |:----------------------------|:-----------------------------------------|
37 | | `service_id` | The ID of the Opsgenie Service |
38 | | `service_name` | The name of the Opsgenie Service |
39 |
--------------------------------------------------------------------------------
/modules/service/main.tf:
--------------------------------------------------------------------------------
1 | resource "opsgenie_service" "this" {
2 | count = module.this.enabled ? 1 : 0
3 |
4 | name = var.service.name
5 | team_id = var.service.team_id
6 | description = var.service.description
7 | }
8 |
--------------------------------------------------------------------------------
/modules/service/outputs.tf:
--------------------------------------------------------------------------------
1 | output "service_id" {
2 | description = "The ID of the Opsgenie Service"
3 | value = try(opsgenie_service.this[0].id, null)
4 | }
5 |
6 | output "service_name" {
7 | description = "The name of the Opsgenie Service"
8 | value = try(opsgenie_service.this[0].name, null)
9 | }
10 |
--------------------------------------------------------------------------------
/modules/service/variables.tf:
--------------------------------------------------------------------------------
1 | variable "service" {
2 | default = {}
3 | description = "Opsgenie Service configuration"
4 | }
5 |
--------------------------------------------------------------------------------
/modules/service/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 0.13.0"
3 |
4 | required_providers {
5 | opsgenie = {
6 | source = "opsgenie/opsgenie"
7 | version = ">= 0.4"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/modules/service_incident_rule/README.md:
--------------------------------------------------------------------------------
1 | ## Service Incident Rule
2 |
3 | Terraform module to configure [Opsgenie Service Incident Rule](https://registry.terraform.io/providers/opsgenie/opsgenie/latest/docs/resources/service_incident_rule)
4 |
5 |
6 | ## Usage
7 |
8 | [Create Opsgenie Team Routing Rule example](../../examples/service_incident_rule)
9 |
10 | ```hcl
11 | module "service_incident_rule" {
12 | source = "cloudposse/incident-management/opsgenie//modules/service_incident_rule"
13 | # Cloud Posse recommends pinning every module to a specific version
14 | # version = "x.x.x"
15 |
16 | service_incident_rule = {
17 | service_id = "..."
18 |
19 | incident_rule = {
20 | condition_match_type = "match-all"
21 |
22 | conditions = [
23 | {
24 | field = "tags"
25 | operation = "contains"
26 | expected_value = "expected1"
27 | }
28 | ]
29 |
30 | incident_properties = {
31 | message = "This is a test message"
32 | priority = "P3"
33 |
34 | stakeholder_properties = {
35 | message = "Message for stakeholders"
36 | enable = true
37 | }
38 | }
39 | }
40 | }
41 | }
42 | ```
43 |
44 | ## Inputs
45 |
46 | **Note:** `service_incident_rule` is a map for two reasons:
47 | - to be able to put whole configuration in yaml file
48 | - variables defined with type set are not robust enough (can't set default values)
49 |
50 | | Name | Default | Description | Required |
51 | |:-------------------------------|:---------------------------------:|:-------------------------------------------------|:--------:|
52 | | `service_incident_rule` | `{}` | Opsgenie Service Incident Rule configuration | Yes |
53 |
54 |
55 | ## Outputs
56 |
57 | | Name | Description |
58 | |:------------------------------|:-----------------------------------------------|
59 | | `service_incident_rule_id` | The ID of the Opsgenie Service Incident Rule |
60 |
--------------------------------------------------------------------------------
/modules/service_incident_rule/main.tf:
--------------------------------------------------------------------------------
1 | resource "opsgenie_service_incident_rule" "this" {
2 | count = module.this.enabled ? 1 : 0
3 |
4 | service_id = var.service_incident_rule.service_id
5 |
6 | incident_rule {
7 | condition_match_type = try(var.service_incident_rule.incident_rule.condition_match_type, "match-all")
8 |
9 | dynamic "conditions" {
10 | for_each = try(var.service_incident_rule.incident_rule.conditions, [])
11 |
12 | content {
13 | expected_value = try(conditions.value.expected_value, null)
14 | field = conditions.value.field
15 | not = try(conditions.value.not, null)
16 | operation = conditions.value.operation
17 | }
18 | }
19 |
20 | incident_properties {
21 | message = var.service_incident_rule.incident_rule.incident_properties.message
22 | priority = var.service_incident_rule.incident_rule.incident_properties.priority
23 | tags = try(var.service_incident_rule.incident_rule.incident_properties.tags, null)
24 | details = try(var.service_incident_rule.incident_rule.incident_properties.details, null)
25 |
26 | stakeholder_properties {
27 | message = var.service_incident_rule.incident_rule.incident_properties.stakeholder_properties.message
28 | description = try(var.service_incident_rule.incident_rule.incident_properties.stakeholder_properties.description, null)
29 | enable = try(var.service_incident_rule.incident_rule.incident_properties.stakeholder_properties.enable, null)
30 | }
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/modules/service_incident_rule/outputs.tf:
--------------------------------------------------------------------------------
1 | output "service_incident_rule_id" {
2 | description = "The ID of the Opsgenie Service Incident Rule"
3 | value = try(opsgenie_service_incident_rule.this[0].id, null)
4 | }
5 |
--------------------------------------------------------------------------------
/modules/service_incident_rule/variables.tf:
--------------------------------------------------------------------------------
1 | variable "service_incident_rule" {
2 | default = {}
3 | description = "Opsgenie Service Incident Rule configuration"
4 | }
5 |
--------------------------------------------------------------------------------
/modules/service_incident_rule/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 0.13.0"
3 |
4 | required_providers {
5 | opsgenie = {
6 | source = "opsgenie/opsgenie"
7 | version = ">= 0.4"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/modules/team/README.md:
--------------------------------------------------------------------------------
1 | ## Team
2 |
3 | Terraform module to configure [Opsgenie Team](https://registry.terraform.io/providers/opsgenie/opsgenie/latest/docs/resources/team)
4 |
5 |
6 | ## Usage
7 |
8 | [Create Opsgenie Team example](../../examples/team)
9 |
10 | ```hcl
11 | module "team" {
12 | source = "cloudposse/incident-management/opsgenie//modules/team"
13 | # Cloud Posse recommends pinning every module to a specific version
14 | # version = "x.x.x"
15 |
16 | team = {
17 | name = module.label.id
18 | description = "team-description"
19 | }
20 | }
21 |
22 | module "ui_managed_team" {
23 | source = "cloudposse/incident-management/opsgenie//modules/team"
24 | # Cloud Posse recommends pinning every module to a specific version
25 | # version = "x.x.x"
26 |
27 | team = {
28 | name = module.label.id
29 | description = "team-description"
30 | delete_default_resources = true
31 | ignore_members = true
32 | }
33 | }
34 |
35 | ```
36 |
37 | ## Inputs
38 |
39 | **Note:** `team` is a map for two reasons:
40 | - to be able to put whole configuration in yaml file
41 | - variables defined with type set are not robust enough (can't set default values)
42 |
43 | | Name | Default | Description | Required |
44 | |:-------------------------------|:---------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------|:--------:|
45 | | `team` | `{}` | This variable is used to configure Opsgenie Team. | Yes |
46 |
47 |
48 | ## Outputs
49 |
50 | | Name | Description |
51 | |:----------------------------|:-----------------------------------------|
52 | | `team_name` | The name of the Opsgenie Team. |
53 | | `team_id` | The ID of the Opsgenie Team. |
54 |
--------------------------------------------------------------------------------
/modules/team/main.tf:
--------------------------------------------------------------------------------
1 | resource "opsgenie_team" "this" {
2 | count = module.this.enabled ? 1 : 0
3 |
4 | name = var.team.name
5 | description = try(var.team.description, var.team.name)
6 | ignore_members = try(var.team.ignore_members, false)
7 | delete_default_resources = try(var.team.delete_default_resources, false)
8 |
9 | dynamic "member" {
10 | for_each = try(var.team.members, [])
11 |
12 | content {
13 | id = member.value.id
14 | role = member.value.role
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/modules/team/outputs.tf:
--------------------------------------------------------------------------------
1 | output "team_id" {
2 | description = "The ID of the Opsgenie Team"
3 | value = try(opsgenie_team.this[0].id, null)
4 | }
5 |
6 | output "team_name" {
7 | description = "The name of the Opsgenie Team"
8 | value = try(opsgenie_team.this[0].name, null)
9 | }
10 |
--------------------------------------------------------------------------------
/modules/team/variables.tf:
--------------------------------------------------------------------------------
1 | variable "team" {
2 | default = {}
3 | description = "Opsgenie Team configuration"
4 | }
5 |
--------------------------------------------------------------------------------
/modules/team/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 0.13.0"
3 |
4 | required_providers {
5 | opsgenie = {
6 | source = "opsgenie/opsgenie"
7 | version = ">= 0.4"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/modules/team_routing_rule/README.md:
--------------------------------------------------------------------------------
1 | ## Team Routing Rule
2 |
3 | Terraform module to configure [Opsgenie Team Routing Rule](https://registry.terraform.io/providers/opsgenie/opsgenie/latest/docs/resources/team_routing_rule)
4 |
5 |
6 | ## Usage
7 |
8 | [Create Opsgenie Team Routing Rule example](../../examples/team_routing_rule)
9 |
10 | ```hcl
11 | module "team_routing_rule" {
12 | source = "cloudposse/incident-management/opsgenie//modules/team_routing_rule"
13 | # Cloud Posse recommends pinning every module to a specific version
14 | # version = "x.x.x"
15 |
16 | team_routing_rule = {
17 | name = module.label.id
18 | team_id = module.owner_team.team_id
19 |
20 | notify = [{
21 | type = "escalation"
22 | id = module.escalation.escalation_id
23 | }]
24 | }
25 | }
26 | ```
27 |
28 | ## Inputs
29 |
30 | **Note:** `team_routing_rule` is a map for two reasons:
31 | - to be able to put whole configuration in yaml file
32 | - variables defined with type set are not robust enough (can't set default values)
33 |
34 | | Name | Default | Description | Required |
35 | |:-------------------------------|:---------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------|:--------:|
36 | | `team_routing_rule` | `{}` | This variable is used to configure Opsgenie Team Routing Rule. | Yes |
37 |
38 |
39 | ## Outputs
40 |
41 | | Name | Description |
42 | |:----------------------------|:--------------------------------------------|
43 | | `team_routing_rule_name` | The name of the Opsgenie Team Routing Rule.|
44 | | `team_routing_rule_id` | The ID of the Opsgenie Team Routing Rule. |
45 |
46 | ## Important Note
47 |
48 | Due to the Opsgenie terraform provider issue, there is a difference in the configuration of the `time_restriction` blocks based on `type`.
49 |
50 | [Github Issue #282](https://github.com/opsgenie/terraform-provider-opsgenie/issues/282)
51 |
52 | ```hcl
53 | time_restriction {
54 | type = "time-of-day"
55 | restriction {
56 | end_hour = 17
57 | end_min = 0
58 | start_hour = 9
59 | start_min = 0
60 | }
61 | }
62 | ```
63 | vs
64 | ```hcl
65 | time_restriction {
66 | type = "weekday-and-time-of-day"
67 | restriction {
68 | end_day = "friday"
69 | end_hour = 17
70 | end_min = 0
71 | start_day = "monday"
72 | start_hour = 9
73 | start_min = 0
74 | }
75 | }
76 | ```
77 |
--------------------------------------------------------------------------------
/modules/team_routing_rule/main.tf:
--------------------------------------------------------------------------------
1 | resource "opsgenie_team_routing_rule" "this" {
2 | count = module.this.enabled ? 1 : 0
3 |
4 | name = var.team_routing_rule.name
5 | team_id = var.team_routing_rule.team_id
6 | order = try(var.team_routing_rule.order, 5)
7 |
8 | timezone = try(var.team_routing_rule.timezone, "America/Los_Angeles")
9 | dynamic "time_restriction" {
10 | for_each = [for time_restriction in try([var.team_routing_rule.time_restriction], []) : time_restriction if time_restriction != null]
11 |
12 | content {
13 | # NOTE: The Opsgenie terraform provider appears to be inconsistent with how it uses time_restriction:
14 | # `restrictions` for type `weekday-and-time-of-day`
15 | # `restriction` for type `time-of-day`
16 | type = var.team_routing_rule.time_restriction.type
17 | dynamic "restrictions" {
18 | for_each = var.team_routing_rule.time_restriction.type == "weekday-and-time-of-day" ? try(var.team_routing_rule.time_restriction.restrictions, []) : []
19 | content {
20 | start_hour = restrictions.value.start_hour
21 | start_min = restrictions.value.start_min
22 | start_day = restrictions.value.start_day
23 | end_hour = restrictions.value.end_hour
24 | end_min = restrictions.value.end_min
25 | end_day = restrictions.value.end_day
26 | }
27 | }
28 |
29 | dynamic "restriction" {
30 | for_each = var.team_routing_rule.time_restriction.type == "time-of-day" ? try(var.team_routing_rule.time_restriction.restrictions, []) : []
31 | content {
32 | start_hour = restriction.value.start_hour
33 | start_min = restriction.value.start_min
34 | end_hour = restriction.value.end_hour
35 | end_min = restriction.value.end_min
36 | }
37 | }
38 | }
39 | }
40 |
41 | criteria {
42 | type = try(var.team_routing_rule.criteria.type != null ? var.team_routing_rule.criteria.type : "match-all", "match-all")
43 |
44 | dynamic "conditions" {
45 | for_each = try(var.team_routing_rule.criteria.conditions != null ? var.team_routing_rule.criteria.conditions : [], [])
46 |
47 | content {
48 | expected_value = try(conditions.value.expected_value, null)
49 | field = try(conditions.value.field, null)
50 | key = try(conditions.value.key, null)
51 | not = try(conditions.value.not, null)
52 | operation = try(conditions.value.operation, null)
53 | order = try(conditions.value.order, null)
54 | }
55 | }
56 | }
57 |
58 | dynamic "notify" {
59 | for_each = try(var.team_routing_rule.notify, [])
60 |
61 | content {
62 | type = notify.value.type
63 | # name and id parameters are mutually exclusive
64 | id = try(notify.value.id, null)
65 | name = try(notify.value.name, null)
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/modules/team_routing_rule/outputs.tf:
--------------------------------------------------------------------------------
1 | output "team_routing_rule_id" {
2 | description = "The ID of the Opsgenie Team Routing Rule"
3 | value = try(opsgenie_team_routing_rule.this[0].id, null)
4 | }
5 |
6 | output "team_routing_rule_name" {
7 | description = "The name of the Opsgenie Team Routing Rule"
8 | value = try(opsgenie_team_routing_rule.this[0].name, null)
9 | }
10 |
--------------------------------------------------------------------------------
/modules/team_routing_rule/variables.tf:
--------------------------------------------------------------------------------
1 | variable "team_routing_rule" {
2 | default = {}
3 | description = "Opsgenie Team Routing Rule configuration"
4 | }
5 |
--------------------------------------------------------------------------------
/modules/team_routing_rule/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 0.13.0"
3 |
4 | required_providers {
5 | opsgenie = {
6 | source = "opsgenie/opsgenie"
7 | version = ">= 0.6.7"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/modules/user/README.md:
--------------------------------------------------------------------------------
1 | ## User
2 |
3 | Terraform module to configure [Opsgenie User](https://registry.terraform.io/providers/opsgenie/opsgenie/latest/docs/resources/user)
4 |
5 |
6 | ## Usage
7 |
8 | [Create Opsgenie User example](../../examples/user)
9 |
10 | ```hcl
11 | module "user" {
12 | source = "cloudposse/incident-management/opsgenie//modules/user"
13 | # Cloud Posse recommends pinning every module to a specific version
14 | # version = "x.x.x"
15 |
16 | user = {
17 | username = "opsgenie-test@cloudposse.com"
18 | full_name = "Opsgenie Test User"
19 | role = "User"
20 | locale = "en_US"
21 | timezone = "America/New_York"
22 | }
23 | }
24 | ```
25 |
26 | ## Inputs
27 |
28 | **Note:** `user` is a map for two reasons:
29 | - to be able to put whole configuration in yaml file
30 | - variables defined with type set are not robust enough (can't set default values)
31 |
32 | | Name | Default | Description | Required |
33 | |:-------------------------------|:---------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------|:--------:|
34 | | `user` | `{}` | Opsgenie User configuration | Yes |
35 |
36 |
37 | ## Outputs
38 |
39 | | Name | Description |
40 | |:----------------------------|:-----------------------------------------|
41 | | `user_id` | The ID of the Opsgenie User |
42 | | `user_name` | The name of the Opsgenie User |
43 |
--------------------------------------------------------------------------------
/modules/user/main.tf:
--------------------------------------------------------------------------------
1 | resource "opsgenie_user" "this" {
2 | count = module.this.enabled ? 1 : 0
3 |
4 | username = var.user.username
5 | full_name = var.user.full_name
6 | role = var.user.role
7 | locale = try(var.user.locale, "en_US")
8 | timezone = try(var.user.timezone, "America/New_York")
9 | }
10 |
--------------------------------------------------------------------------------
/modules/user/outputs.tf:
--------------------------------------------------------------------------------
1 | output "user_id" {
2 | description = "The ID of the Opsgenie User"
3 | value = try(opsgenie_user.this[0].id, null)
4 | }
5 |
6 | output "user_name" {
7 | description = "The username of the Opsgenie User"
8 | value = try(opsgenie_user.this[0].username, null)
9 | }
10 |
--------------------------------------------------------------------------------
/modules/user/variables.tf:
--------------------------------------------------------------------------------
1 | variable "user" {
2 | default = {}
3 | description = "Opsgenie User configuration"
4 | }
5 |
--------------------------------------------------------------------------------
/modules/user/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 0.13.0"
3 |
4 | required_providers {
5 | opsgenie = {
6 | source = "opsgenie/opsgenie"
7 | version = ">= 0.4"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/outputs.tf:
--------------------------------------------------------------------------------
1 | output "alert_policy_id" {
2 | description = "The ID of the Opsgenie Alert Policy"
3 | value = module.alert_policy.alert_policy_id
4 | }
5 |
6 | output "alert_policy_name" {
7 | description = "Name of the Opsgenie Alert Policy"
8 | value = module.alert_policy.alert_policy_name
9 | }
10 |
11 | output "alert_policy_filter" {
12 | description = "Filters of the Opsgenie Alert Policy"
13 | value = module.alert_policy.alert_policy_filter
14 | }
15 |
16 | output "alert_policy_tags" {
17 | description = "Tags of the Opsgenie Alert Policy"
18 | value = module.alert_policy.alert_policy_tags
19 | }
20 |
21 | output "alert_policy_priority" {
22 | description = "Priority of the Opsgenie Alert Policy"
23 | value = module.alert_policy.alert_policy_priority
24 | }
25 |
26 | output "alert_policy_responders" {
27 | description = "Responders of the Opsgenie Alert Policy."
28 | value = module.alert_policy.alert_policy_responders
29 | }
30 |
31 | output "api_integration_api_key" {
32 | description = "API key of the created integration"
33 | value = module.api_integration.api_integration_api_key
34 | sensitive = true
35 | }
36 |
37 | output "api_integration_name" {
38 | description = "The name of the Opsgenie API Integration"
39 | value = module.api_integration.api_integration_name
40 | }
41 |
42 | output "api_integration_id" {
43 | description = "The ID of the Opsgenie API Integration"
44 | value = module.api_integration.api_integration_id
45 | }
46 |
47 | output "escalation_id" {
48 | description = "The ID of the Opsgenie Escalation"
49 | value = module.escalation.escalation_id
50 | }
51 |
52 | output "escalation_name" {
53 | description = "Name of the Opsgenie Escalation"
54 | value = module.escalation.escalation_name
55 | }
56 |
57 | output "integration_action_id" {
58 | description = "The ID of the Opsgenie Integration Action"
59 | value = module.integration_action.integration_action_id
60 | }
61 |
62 | output "notification_policy_id" {
63 | description = "The ID of the Opsgenie Notification Policy"
64 | value = module.notification_policy.notification_policy_id
65 | }
66 |
67 | output "notification_policy_name" {
68 | description = "The name of the Opsgenie Notification Policy"
69 | value = module.notification_policy.notification_policy_name
70 | }
71 |
72 | output "team_id" {
73 | description = "The ID of the Opsgenie Team"
74 | value = module.team.team_id
75 | }
76 |
77 | output "team_name" {
78 | description = "The name of the Opsgenie Team"
79 | value = module.team.team_name
80 | }
81 |
82 | output "team_routing_rule_id" {
83 | description = "The ID of the Opsgenie Team Routing Rule"
84 | value = module.team_routing_rule.team_routing_rule_id
85 | }
86 |
87 | output "team_routing_rule_name" {
88 | description = "The name of the Opsgenie Team Routing Rule"
89 | value = module.team_routing_rule.team_routing_rule_name
90 | }
91 |
92 | output "user_id" {
93 | description = "The ID of the Opsgenie User"
94 | value = module.user.user_id
95 | }
96 |
97 | output "user_name" {
98 | description = "The name of the Opsgenie User"
99 | value = module.user.user_name
100 | }
101 |
102 | output "service_id" {
103 | description = "The ID of the Opsgenie Service"
104 | value = module.service.service_id
105 | }
106 |
107 | output "service_name" {
108 | description = "The name of the Opsgenie Service"
109 | value = module.service.service_name
110 | }
111 |
112 | output "service_incident_rule_id" {
113 | description = "The ID of the Opsgenie Service Incident Rule"
114 | value = module.service_incident_rule.service_incident_rule_id
115 | }
116 |
--------------------------------------------------------------------------------
/test/.gitignore:
--------------------------------------------------------------------------------
1 | .test-harness
2 | .envrc
3 |
--------------------------------------------------------------------------------
/test/Makefile:
--------------------------------------------------------------------------------
1 | TEST_HARNESS ?= https://github.com/cloudposse/test-harness.git
2 | TEST_HARNESS_BRANCH ?= master
3 | TEST_HARNESS_PATH = $(realpath .test-harness)
4 | BATS_ARGS ?= --tap
5 | BATS_LOG ?= test.log
6 |
7 | # Define a macro to run the tests
8 | define RUN_TESTS
9 | @echo "Running tests in $(1)"
10 | @cd $(1) && bats $(BATS_ARGS) $(addsuffix .bats,$(addprefix $(TEST_HARNESS_PATH)/test/terraform/,$(TESTS)))
11 | endef
12 |
13 | default: all
14 |
15 | -include Makefile.*
16 |
17 | ## Provision the test-harnesss
18 | .test-harness:
19 | [ -d $@ ] || git clone --depth=1 -b $(TEST_HARNESS_BRANCH) $(TEST_HARNESS) $@
20 |
21 | ## Initialize the tests
22 | init: .test-harness
23 |
24 | ## Install all dependencies (OS specific)
25 | deps::
26 | @exit 0
27 |
28 | ## Clean up the test harness
29 | clean:
30 | [ "$(TEST_HARNESS_PATH)" == "/" ] || rm -rf $(TEST_HARNESS_PATH)
31 |
32 | ## Run all tests
33 | all: module pre-test examples/complete examples/advanced_features examples/alert_policy examples/api_integration examples/complete examples/config examples/escalation examples/integration_action examples/notification_policy examples/schedule examples/team examples/team_routing_rule examples/user
34 |
35 | ## Run basic sanity checks against the module itself
36 | module: export TESTS ?= installed lint get-modules module-pinning get-plugins provider-pinning validate terraform-docs input-descriptions output-descriptions
37 | module: deps
38 | $(call RUN_TESTS, ../)
39 |
40 | pre-test:
41 | export TESTS ?= installed lint get-modules get-plugins validate
42 |
43 | ## Run tests against example
44 | examples/complete: deps
45 | $(call RUN_TESTS, ../$@)
46 | examples/advanced_features: deps
47 | $(call RUN_TESTS, ../$@)
48 | examples/alert_policy: deps
49 | $(call RUN_TESTS, ../$@)
50 | examples/api_integration: deps
51 | $(call RUN_TESTS, ../$@)
52 | examples/complete: deps
53 | $(call RUN_TESTS, ../$@)
54 | examples/config: deps
55 | $(call RUN_TESTS, ../$@)
56 | examples/escalation: deps
57 | $(call RUN_TESTS, ../$@)
58 | examples/integration_action: deps
59 | $(call RUN_TESTS, ../$@)
60 | examples/notification_policy: deps
61 | $(call RUN_TESTS, ../$@)
62 | examples/schedule: deps
63 | $(call RUN_TESTS, ../$@)
64 | examples/team: deps
65 | $(call RUN_TESTS, ../$@)
66 | examples/team_routing_rule: deps
67 | $(call RUN_TESTS, ../$@)
68 | examples/user: deps
69 | $(call RUN_TESTS, ../$@)
70 |
--------------------------------------------------------------------------------
/test/Makefile.alpine:
--------------------------------------------------------------------------------
1 | ifneq (,$(wildcard /sbin/apk))
2 | ## Install all dependencies for alpine
3 | deps:: init
4 | @apk add --update terraform-docs@cloudposse json2hcl@cloudposse
5 | endif
6 |
--------------------------------------------------------------------------------
/test/src/.gitignore:
--------------------------------------------------------------------------------
1 | .gopath
2 | vendor/
3 |
--------------------------------------------------------------------------------
/test/src/Makefile:
--------------------------------------------------------------------------------
1 | export TF_CLI_ARGS_init ?= -get-plugins=true
2 | export TERRAFORM_VERSION ?= $(shell curl -s https://checkpoint-api.hashicorp.com/v1/check/terraform | jq -r -M '.current_version' | cut -d. -f1-2)
3 |
4 | .DEFAULT_GOAL : all
5 |
6 | .PHONY: all
7 | ## Default target
8 | all: test
9 |
10 | .PHONY : init
11 | ## Initialize tests
12 | init:
13 | @exit 0
14 |
15 | .PHONY : test
16 | ## Run tests
17 | test: init
18 | go mod download
19 | go test -v -timeout 60m -parallel 8
20 |
21 | ## Run tests in docker container
22 | docker/test:
23 | docker run --name terratest --rm -it -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e AWS_SESSION_TOKEN -e GITHUB_TOKEN \
24 | -e PATH="/usr/local/terraform/$(TERRAFORM_VERSION)/bin:/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" \
25 | -v $(CURDIR)/../../:/module/ cloudposse/test-harness:latest -C /module/test/src test
26 |
27 | .PHONY : clean
28 | ## Clean up files
29 | clean:
30 | rm -rf ../../examples/complete/*.tfstate*
31 |
--------------------------------------------------------------------------------
/test/src/examples_advanced_features.go:
--------------------------------------------------------------------------------
1 | package test
2 |
3 | import (
4 | "github.com/gruntwork-io/terratest/modules/random"
5 | "github.com/gruntwork-io/terratest/modules/terraform"
6 | testStructure "github.com/gruntwork-io/terratest/modules/test-structure"
7 | "strings"
8 | "testing"
9 | )
10 |
11 | // Test the Terraform module in examples/advanced_features using Terratest.
12 | func TestExamplesAdvancedFeatures(t *testing.T) {
13 | t.Parallel()
14 | randID := strings.ToLower(random.UniqueId())
15 | attributes := []string{randID}
16 |
17 | rootFolder := "../../"
18 | terraformFolderRelativeToRoot := "examples/advanced_features"
19 | varFiles := []string{"fixtures.tfvars"}
20 |
21 | tempTestFolder := testStructure.CopyTerraformFolderToTemp(t, rootFolder, terraformFolderRelativeToRoot)
22 |
23 | terraformOptions := &terraform.Options{
24 | // The path to where our Terraform code is located
25 | TerraformDir: tempTestFolder,
26 | Upgrade: true,
27 | // Variables to pass to our Terraform code using -var-file options
28 | VarFiles: varFiles,
29 | Vars: map[string]interface{}{
30 | "attributes": attributes,
31 | },
32 | }
33 |
34 | // At the end of the test, run `terraform destroy` to clean up any resources that were created
35 | defer cleanup(t, terraformOptions, tempTestFolder)
36 |
37 | // This will run `terraform init` and `terraform apply` and fail the test if there are any errors
38 | terraform.InitAndApply(t, terraformOptions)
39 | }
40 |
--------------------------------------------------------------------------------
/test/src/examples_alert_policy_test.go:
--------------------------------------------------------------------------------
1 | package test
2 |
3 | import (
4 | "github.com/gruntwork-io/terratest/modules/random"
5 | "github.com/gruntwork-io/terratest/modules/terraform"
6 | testStructure "github.com/gruntwork-io/terratest/modules/test-structure"
7 | "github.com/stretchr/testify/assert"
8 | "strings"
9 | "testing"
10 | )
11 |
12 | // Test the Terraform module in examples/alert_policy using Terratest.
13 | func TestExamplesAlertPolicy(t *testing.T) {
14 | t.SkipNow()
15 | // We are skipping this test because of the following error:
16 | // Error: Error occurred with Status code: 403, Message: You are not authorized to use policies!, Took: 0.001000, RequestId: 66e46694-8e4c-4e20-9644-178db4b2f4c1
17 |
18 | t.Parallel()
19 | randID := strings.ToLower(random.UniqueId())
20 | attributes := []string{randID}
21 |
22 | rootFolder := "../../"
23 | terraformFolderRelativeToRoot := "examples/alert_policy"
24 | varFiles := []string{"fixtures.tfvars"}
25 |
26 | tempTestFolder := testStructure.CopyTerraformFolderToTemp(t, rootFolder, terraformFolderRelativeToRoot)
27 |
28 | terraformOptions := &terraform.Options{
29 | // The path to where our Terraform code is located
30 | TerraformDir: tempTestFolder,
31 | Upgrade: true,
32 | // Variables to pass to our Terraform code using -var-file options
33 | VarFiles: varFiles,
34 | Vars: map[string]interface{}{
35 | "attributes": attributes,
36 | },
37 | }
38 |
39 | // At the end of the test, run `terraform destroy` to clean up any resources that were created
40 | defer cleanup(t, terraformOptions, tempTestFolder)
41 |
42 | // This will run `terraform init` and `terraform apply` and fail the test if there are any errors
43 | terraform.InitAndApply(t, terraformOptions)
44 |
45 | // Run `terraform output` to get the value of an output variable and test it
46 | outputAlertPolicyName := terraform.Output(t, terraformOptions, "alert_policy_name")
47 | assert.Equal(t, "eg-test-alert-policy", outputAlertPolicyName)
48 |
49 | outputAlertPolicyPriority := terraform.Output(t, terraformOptions, "alert_policy_priority")
50 | assert.Equal(t, "P1", outputAlertPolicyPriority)
51 |
52 | expectedAlertPolicyTags := `[
53 | "test1",
54 | "test2",
55 | ]`
56 | outputAlertPolicyTags := terraform.Output(t, terraformOptions, "alert_policy_tags")
57 | assert.Equal(t, expectedAlertPolicyTags, outputAlertPolicyTags)
58 |
59 | expectedAlertPolicyFilter := `[
60 | {
61 | "conditions" = [
62 | {
63 | "expected_value" = ".*prod.*"
64 | "field" = "source"
65 | "key" = ""
66 | "not" = false
67 | "operation" = "matches"
68 | "order" = 0
69 | },
70 | {
71 | "expected_value" = "severity:critical"
72 | "field" = "tags"
73 | "key" = ""
74 | "not" = false
75 | "operation" = "contains"
76 | "order" = 0
77 | },
78 | ]
79 | "type" = "match-all-conditions"
80 | },
81 | ]`
82 | outputAlertPolicyFilter := terraform.Output(t, terraformOptions, "alert_policy_filter")
83 | assert.Equal(t, expectedAlertPolicyFilter, outputAlertPolicyFilter)
84 |
85 | expectedAlertPolicyResponders := `[
86 | {
87 | "id" = .*
88 | "name" = ""
89 | "type" = "team"
90 | "username" = ""
91 | },
92 | ]`
93 | outputAlertPolicyResponders := terraform.Output(t, terraformOptions, "alert_policy_responders")
94 | assert.Regexp(t, expectedAlertPolicyResponders, outputAlertPolicyResponders)
95 | }
96 |
--------------------------------------------------------------------------------
/test/src/examples_api_integration_test.go:
--------------------------------------------------------------------------------
1 | package test
2 |
3 | import (
4 | "github.com/gruntwork-io/terratest/modules/random"
5 | "github.com/gruntwork-io/terratest/modules/terraform"
6 | testStructure "github.com/gruntwork-io/terratest/modules/test-structure"
7 | "github.com/stretchr/testify/assert"
8 | "strings"
9 | "testing"
10 | )
11 |
12 | // Test the Terraform module in examples/api_integration using Terratest.
13 | func TestExamplesApiIntegration(t *testing.T) {
14 | t.Parallel()
15 | randID := strings.ToLower(random.UniqueId())
16 | attributes := []string{randID}
17 |
18 | rootFolder := "../../"
19 | terraformFolderRelativeToRoot := "examples/api_integration"
20 | varFiles := []string{"fixtures.tfvars"}
21 |
22 | tempTestFolder := testStructure.CopyTerraformFolderToTemp(t, rootFolder, terraformFolderRelativeToRoot)
23 |
24 | terraformOptions := &terraform.Options{
25 | // The path to where our Terraform code is located
26 | TerraformDir: tempTestFolder,
27 | Upgrade: true,
28 | // Variables to pass to our Terraform code using -var-file options
29 | VarFiles: varFiles,
30 | Vars: map[string]interface{}{
31 | "attributes": attributes,
32 | },
33 | }
34 |
35 | // At the end of the test, run `terraform destroy` to clean up any resources that were created
36 | defer cleanup(t, terraformOptions, tempTestFolder)
37 |
38 | // This will run `terraform init` and `terraform apply` and fail the test if there are any errors
39 | terraform.InitAndApply(t, terraformOptions)
40 |
41 | // Run `terraform output` to get the value of an output variable
42 | outputApiIntegrationName := terraform.Output(t, terraformOptions, "api_integration_name")
43 | expectedApiIntegrationName := "eg-test-api-integration-" + randID
44 |
45 | // Verify we're getting back the outputs we expect
46 | assert.Equal(t, expectedApiIntegrationName, outputApiIntegrationName)
47 | }
48 |
--------------------------------------------------------------------------------
/test/src/examples_complete_test.go:
--------------------------------------------------------------------------------
1 | package test
2 |
3 | import (
4 | "regexp"
5 | "strings"
6 | "testing"
7 |
8 | "github.com/gruntwork-io/terratest/modules/random"
9 | "github.com/gruntwork-io/terratest/modules/terraform"
10 | testStructure "github.com/gruntwork-io/terratest/modules/test-structure"
11 | "github.com/stretchr/testify/assert"
12 | )
13 |
14 | // Test the Terraform module in examples/complete using Terratest.
15 | func TestExamplesComplete(t *testing.T) {
16 | t.Parallel()
17 | randID := strings.ToLower(random.UniqueId())
18 | attributes := []string{randID}
19 |
20 | rootFolder := "../../"
21 | terraformFolderRelativeToRoot := "examples/complete"
22 | varFiles := []string{"fixtures.tfvars"}
23 |
24 | tempTestFolder := testStructure.CopyTerraformFolderToTemp(t, rootFolder, terraformFolderRelativeToRoot)
25 |
26 | terraformOptions := &terraform.Options{
27 | // The path to where our Terraform code is located
28 | TerraformDir: tempTestFolder,
29 | Upgrade: true,
30 | // Variables to pass to our Terraform code using -var-file options
31 | VarFiles: varFiles,
32 | Vars: map[string]interface{}{
33 | "attributes": attributes,
34 | },
35 | }
36 |
37 | // At the end of the test, run `terraform destroy` to clean up any resources that were created
38 | defer cleanup(t, terraformOptions, tempTestFolder)
39 |
40 | // This will run `terraform init` and `terraform apply` and fail the test if there are any errors
41 | terraform.InitAndApply(t, terraformOptions)
42 |
43 | // Run `terraform output` to get the value of an output variable
44 | outputApiIntegrationName := terraform.Output(t, terraformOptions, "api_integration_name")
45 |
46 | // Verify we're getting back the outputs we expect
47 | expectedWorkflowName := "eg-test-incident-management-workflow-" + randID
48 | assert.Equal(t, expectedWorkflowName, outputApiIntegrationName)
49 |
50 | // Run `terraform output` to get the value of an output variable
51 |
52 | outputEscalationName := terraform.Output(t, terraformOptions, "escalation_name")
53 | expectedEscalationName := "eg-test-incident-management-workflow-" + randID + "-escalation"
54 |
55 | // Verify we're getting back the outputs we expect
56 | assert.Equal(t, expectedEscalationName, outputEscalationName)
57 |
58 | // Run `terraform output` to get the value of an output variable
59 | outputTeamRoutingRuleName := terraform.Output(t, terraformOptions, "team_routing_rule_name")
60 | expectedTeamRoutingRuleName := "eg-test-incident-management-workflow-" + randID
61 |
62 | // Verify we're getting back the outputs we expect
63 | assert.Equal(t, expectedTeamRoutingRuleName, outputTeamRoutingRuleName)
64 |
65 | // Run `terraform output` to get the value of an output variable
66 | outputTeamName := terraform.Output(t, terraformOptions, "team_name")
67 | expectedTeamName := "eg-test-incident-management-workflow-" + randID
68 | // Verify we're getting back the outputs we expect
69 | assert.Equal(t, expectedTeamName, outputTeamName)
70 | }
71 |
72 | func TestExamplesCompleteDisabled(t *testing.T) {
73 | t.Parallel()
74 | randID := strings.ToLower(random.UniqueId())
75 | attributes := []string{randID}
76 |
77 | rootFolder := "../../"
78 | terraformFolderRelativeToRoot := "examples/complete"
79 | varFiles := []string{"fixtures.tfvars"}
80 |
81 | tempTestFolder := testStructure.CopyTerraformFolderToTemp(t, rootFolder, terraformFolderRelativeToRoot)
82 |
83 | terraformOptions := &terraform.Options{
84 | // The path to where our Terraform code is located
85 | TerraformDir: tempTestFolder,
86 | Upgrade: true,
87 | // Variables to pass to our Terraform code using -var-file options
88 | VarFiles: varFiles,
89 | Vars: map[string]interface{}{
90 | "attributes": attributes,
91 | "enabled": false,
92 | },
93 | }
94 |
95 | // At the end of the test, run `terraform destroy` to clean up any resources that were created
96 | defer cleanup(t, terraformOptions, tempTestFolder)
97 |
98 | // This will run `terraform init` and `terraform apply` and fail the test if there are any errors
99 | results := terraform.InitAndApply(t, terraformOptions)
100 |
101 | // Should complete successfully without creating or changing any resources.
102 | // Extract the "Resources:" section of the output to make the error message more readable.
103 | re := regexp.MustCompile(`Resources: [^.]+\.`)
104 | match := re.FindString(results)
105 | assert.Equal(t, "Resources: 0 added, 0 changed, 0 destroyed.", match, "Re-applying the same configuration should not change any resources")
106 | }
107 |
--------------------------------------------------------------------------------
/test/src/examples_config_test.go:
--------------------------------------------------------------------------------
1 | package test
2 |
3 | import (
4 | "github.com/gruntwork-io/terratest/modules/random"
5 | "github.com/gruntwork-io/terratest/modules/terraform"
6 | testStructure "github.com/gruntwork-io/terratest/modules/test-structure"
7 | "strings"
8 | "testing"
9 | )
10 |
11 | // Test the Terraform module in examples/config using Terratest.
12 | func TestExamplesConfig(t *testing.T) {
13 | // We skip the ExamplesConfig Test because our API key doesn't allow full testing of the modules used in the example.
14 | t.SkipNow()
15 |
16 | t.Parallel()
17 | randID := strings.ToLower(random.UniqueId())
18 | attributes := []string{randID}
19 |
20 | rootFolder := "../../"
21 | terraformFolderRelativeToRoot := "examples/config"
22 | varFiles := []string{"fixtures.tfvars"}
23 |
24 | tempTestFolder := testStructure.CopyTerraformFolderToTemp(t, rootFolder, terraformFolderRelativeToRoot)
25 |
26 | terraformOptions := &terraform.Options{
27 | // The path to where our Terraform code is located
28 | TerraformDir: tempTestFolder,
29 | Upgrade: true,
30 | // Variables to pass to our Terraform code using -var-file options
31 | VarFiles: varFiles,
32 | Vars: map[string]interface{}{
33 | "attributes": attributes,
34 | },
35 | }
36 |
37 | // At the end of the test, run `terraform destroy` to clean up any resources that were created
38 | defer cleanup(t, terraformOptions, tempTestFolder)
39 |
40 | // This will run `terraform init` and `terraform apply` and fail the test if there are any errors
41 | terraform.InitAndApply(t, terraformOptions)
42 | }
43 |
--------------------------------------------------------------------------------
/test/src/examples_escalation_test.go:
--------------------------------------------------------------------------------
1 | package test
2 |
3 | import (
4 | "github.com/gruntwork-io/terratest/modules/random"
5 | "github.com/gruntwork-io/terratest/modules/terraform"
6 | testStructure "github.com/gruntwork-io/terratest/modules/test-structure"
7 | "github.com/stretchr/testify/assert"
8 | "strings"
9 | "testing"
10 | )
11 |
12 | // Test the Terraform module in examples/escalation using Terratest.
13 | func TestExamplesEscalation(t *testing.T) {
14 | t.Parallel()
15 | randID := strings.ToLower(random.UniqueId())
16 | attributes := []string{randID}
17 |
18 | rootFolder := "../../"
19 | terraformFolderRelativeToRoot := "examples/escalation"
20 | varFiles := []string{"fixtures.tfvars"}
21 |
22 | tempTestFolder := testStructure.CopyTerraformFolderToTemp(t, rootFolder, terraformFolderRelativeToRoot)
23 |
24 | terraformOptions := &terraform.Options{
25 | // The path to where our Terraform code is located
26 | TerraformDir: tempTestFolder,
27 | Upgrade: true,
28 | // Variables to pass to our Terraform code using -var-file options
29 | VarFiles: varFiles,
30 | Vars: map[string]interface{}{
31 | "attributes": attributes,
32 | },
33 | }
34 |
35 | // At the end of the test, run `terraform destroy` to clean up any resources that were created
36 | defer cleanup(t, terraformOptions, tempTestFolder)
37 |
38 | // This will run `terraform init` and `terraform apply` and fail the test if there are any errors
39 | terraform.InitAndApply(t, terraformOptions)
40 |
41 | // Run `terraform output` to get the value of an output variable
42 | outputEscalationName := terraform.Output(t, terraformOptions, "escalation_name")
43 | expectedEscalationName := "eg-test-escalation-" + randID
44 | // Verify we're getting back the outputs we expect
45 | assert.Equal(t, expectedEscalationName, outputEscalationName)
46 | }
47 |
--------------------------------------------------------------------------------
/test/src/examples_integration_action.go:
--------------------------------------------------------------------------------
1 | package test
2 |
3 | import (
4 | "github.com/gruntwork-io/terratest/modules/random"
5 | "github.com/gruntwork-io/terratest/modules/terraform"
6 | testStructure "github.com/gruntwork-io/terratest/modules/test-structure"
7 | "strings"
8 | "testing"
9 | )
10 |
11 | // Test the Terraform module in examples/integration_action using Terratest.
12 | func TestExamplesIntegrationAction(t *testing.T) {
13 | t.Parallel()
14 | randID := strings.ToLower(random.UniqueId())
15 | attributes := []string{randID}
16 |
17 | rootFolder := "../../"
18 | terraformFolderRelativeToRoot := "examples/integration_action"
19 | varFiles := []string{"fixtures.tfvars"}
20 |
21 | tempTestFolder := testStructure.CopyTerraformFolderToTemp(t, rootFolder, terraformFolderRelativeToRoot)
22 |
23 | terraformOptions := &terraform.Options{
24 | // The path to where our Terraform code is located
25 | TerraformDir: tempTestFolder,
26 | Upgrade: true,
27 | // Variables to pass to our Terraform code using -var-file options
28 | VarFiles: varFiles,
29 | Vars: map[string]interface{}{
30 | "attributes": attributes,
31 | },
32 | }
33 |
34 | // At the end of the test, run `terraform destroy` to clean up any resources that were created
35 | defer cleanup(t, terraformOptions, tempTestFolder)
36 |
37 | // This will run `terraform init` and `terraform apply` and fail the test if there are any errors
38 | terraform.InitAndApply(t, terraformOptions)
39 | }
40 |
--------------------------------------------------------------------------------
/test/src/examples_notification_policy_test.go:
--------------------------------------------------------------------------------
1 | package test
2 |
3 | import (
4 | "github.com/gruntwork-io/terratest/modules/random"
5 | "github.com/gruntwork-io/terratest/modules/terraform"
6 | testStructure "github.com/gruntwork-io/terratest/modules/test-structure"
7 | "github.com/stretchr/testify/assert"
8 | "strings"
9 | "testing"
10 | )
11 |
12 | // Test the Terraform module in examples/notification_policy using Terratest.
13 | func TestExamplesNotificationPolicyDeDuplicationAction(t *testing.T) {
14 | // We are skipping this test because of the following error:
15 | // Error: Error occurred with Status code: 403, Message: You are not authorized to use policies!, Took: 0.001000, RequestId: 66e46694-8e4c-4e20-9644-178db4b2f4c1
16 | t.SkipNow()
17 |
18 | t.Parallel()
19 | randID := strings.ToLower(random.UniqueId())
20 | attributes := []string{randID}
21 |
22 | rootFolder := "../../"
23 | terraformFolderRelativeToRoot := "examples/notification_policy"
24 | varFiles := []string{"fixtures.de_duplication_action.tfvars"}
25 |
26 | tempTestFolder := testStructure.CopyTerraformFolderToTemp(t, rootFolder, terraformFolderRelativeToRoot)
27 |
28 | terraformOptions := &terraform.Options{
29 | // The path to where our Terraform code is located
30 | TerraformDir: tempTestFolder,
31 | Upgrade: true,
32 | // Variables to pass to our Terraform code using -var-file options
33 | VarFiles: varFiles,
34 | Vars: map[string]interface{}{
35 | "attributes": attributes,
36 | },
37 | }
38 |
39 | // At the end of the test, run `terraform destroy` to clean up any resources that were created
40 | defer cleanup(t, terraformOptions, tempTestFolder)
41 |
42 | // This will run `terraform init` and `terraform apply` and fail the test if there are any errors
43 | terraform.InitAndApply(t, terraformOptions)
44 |
45 | // Run `terraform output` to get the value of an output variable
46 | outputNotificationPolicyName := terraform.Output(t, terraformOptions, "notification_policy_name")
47 |
48 | // Verify we're getting back the outputs we expect
49 | assert.Regexp(t, "^eg-test-notification-policy$", outputNotificationPolicyName)
50 | }
51 |
52 | func TestExamplesNotificationPolicyDelayAction(t *testing.T) {
53 | // We are skipping this test because of the following error:
54 | // Error: Error occurred with Status code: 403, Message: You are not authorized to use policies!, Took: 0.001000, RequestId: 66e46694-8e4c-4e20-9644-178db4b2f4c1
55 | t.SkipNow()
56 |
57 | t.Parallel()
58 | randID := strings.ToLower(random.UniqueId())
59 | attributes := []string{randID}
60 |
61 | rootFolder := "../../"
62 | terraformFolderRelativeToRoot := "examples/notification_policy"
63 | varFiles := []string{"fixtures.delay_action.tfvars"}
64 |
65 | tempTestFolder := testStructure.CopyTerraformFolderToTemp(t, rootFolder, terraformFolderRelativeToRoot)
66 |
67 | terraformOptions := &terraform.Options{
68 | // The path to where our Terraform code is located
69 | TerraformDir: tempTestFolder,
70 | Upgrade: true,
71 | // Variables to pass to our Terraform code using -var-file options
72 | VarFiles: varFiles,
73 | Vars: map[string]interface{}{
74 | "attributes": attributes,
75 | },
76 | }
77 |
78 | // At the end of the test, run `terraform destroy` to clean up any resources that were created
79 | defer cleanup(t, terraformOptions, tempTestFolder)
80 |
81 | // This will run `terraform init` and `terraform apply` and fail the test if there are any errors
82 | terraform.InitAndApply(t, terraformOptions)
83 |
84 | // Run `terraform output` to get the value of an output variable
85 | outputNotificationPolicyName := terraform.Output(t, terraformOptions, "notification_policy_name")
86 |
87 | // Verify we're getting back the outputs we expect
88 | assert.Regexp(t, "^eg-test-notification-policy$", outputNotificationPolicyName)
89 | }
90 |
--------------------------------------------------------------------------------
/test/src/examples_team_routing_rule_test.go:
--------------------------------------------------------------------------------
1 | package test
2 |
3 | import (
4 | "github.com/gruntwork-io/terratest/modules/random"
5 | "github.com/gruntwork-io/terratest/modules/terraform"
6 | testStructure "github.com/gruntwork-io/terratest/modules/test-structure"
7 | "github.com/stretchr/testify/assert"
8 | "strings"
9 | "testing"
10 | )
11 |
12 | // Test the Terraform module in examples/team_routing_rule using Terratest.
13 | func TestExamplesTeamRoutingRule(t *testing.T) {
14 | t.Parallel()
15 | randID := strings.ToLower(random.UniqueId())
16 | attributes := []string{randID}
17 |
18 | rootFolder := "../../"
19 | terraformFolderRelativeToRoot := "examples/team_routing_rule"
20 | varFiles := []string{"fixtures.tfvars"}
21 |
22 | tempTestFolder := testStructure.CopyTerraformFolderToTemp(t, rootFolder, terraformFolderRelativeToRoot)
23 |
24 | terraformOptions := &terraform.Options{
25 | // The path to where our Terraform code is located
26 | TerraformDir: tempTestFolder,
27 | Upgrade: true,
28 | // Variables to pass to our Terraform code using -var-file options
29 | VarFiles: varFiles,
30 | Vars: map[string]interface{}{
31 | "attributes": attributes,
32 | },
33 | }
34 |
35 | // At the end of the test, run `terraform destroy` to clean up any resources that were created
36 | defer cleanup(t, terraformOptions, tempTestFolder)
37 |
38 | // This will run `terraform init` and `terraform apply` and fail the test if there are any errors
39 | terraform.InitAndApply(t, terraformOptions)
40 |
41 | // Run `terraform output` to get the value of an output variable
42 | outputTeamRoutingRuleName := terraform.Output(t, terraformOptions, "team_routing_rule_name")
43 | expectedTeamRoutingRuleName := "eg-test-team-routing-rule-" + randID
44 | // Verify we're getting back the outputs we expect
45 | assert.Equal(t, expectedTeamRoutingRuleName, outputTeamRoutingRuleName)
46 | }
47 |
--------------------------------------------------------------------------------
/test/src/examples_team_test.go:
--------------------------------------------------------------------------------
1 | package test
2 |
3 | import (
4 | "github.com/gruntwork-io/terratest/modules/random"
5 | "github.com/gruntwork-io/terratest/modules/terraform"
6 | testStructure "github.com/gruntwork-io/terratest/modules/test-structure"
7 | "github.com/stretchr/testify/assert"
8 | "strings"
9 | "testing"
10 | )
11 |
12 | // Test the Terraform module in examples/team using Terratest.
13 | func TestExamplesTeam(t *testing.T) {
14 | t.Parallel()
15 | randID := strings.ToLower(random.UniqueId())
16 | attributes := []string{randID}
17 |
18 | rootFolder := "../../"
19 | terraformFolderRelativeToRoot := "examples/team"
20 | varFiles := []string{"fixtures.tfvars"}
21 |
22 | tempTestFolder := testStructure.CopyTerraformFolderToTemp(t, rootFolder, terraformFolderRelativeToRoot)
23 |
24 | terraformOptions := &terraform.Options{
25 | // The path to where our Terraform code is located
26 | TerraformDir: tempTestFolder,
27 | Upgrade: true,
28 | // Variables to pass to our Terraform code using -var-file options
29 | VarFiles: varFiles,
30 | Vars: map[string]interface{}{
31 | "attributes": attributes,
32 | },
33 | }
34 |
35 | // At the end of the test, run `terraform destroy` to clean up any resources that were created
36 | defer cleanup(t, terraformOptions, tempTestFolder)
37 |
38 | // This will run `terraform init` and `terraform apply` and fail the test if there are any errors
39 | terraform.InitAndApply(t, terraformOptions)
40 |
41 | // Run `terraform output` to get the value of an output variable
42 | outputTeamName := terraform.Output(t, terraformOptions, "team_name")
43 | expectedTeamName := "eg-test-team-" + randID
44 | // Verify we're getting back the outputs we expect
45 |
46 | assert.Equal(t, expectedTeamName, outputTeamName)
47 | }
48 |
--------------------------------------------------------------------------------
/test/src/examples_user_test.go:
--------------------------------------------------------------------------------
1 | package test
2 |
3 | import (
4 | "github.com/gruntwork-io/terratest/modules/random"
5 | "github.com/gruntwork-io/terratest/modules/terraform"
6 | testStructure "github.com/gruntwork-io/terratest/modules/test-structure"
7 | "github.com/stretchr/testify/assert"
8 | "strings"
9 | "testing"
10 | )
11 |
12 | // Test the Terraform module in examples/user using Terratest.
13 | func TestExamplesUser(t *testing.T) {
14 | t.Parallel()
15 | randID := strings.ToLower(random.UniqueId())
16 | attributes := []string{randID}
17 |
18 | rootFolder := "../../"
19 | terraformFolderRelativeToRoot := "examples/user"
20 | varFiles := []string{"fixtures.tfvars"}
21 |
22 | tempTestFolder := testStructure.CopyTerraformFolderToTemp(t, rootFolder, terraformFolderRelativeToRoot)
23 |
24 | terraformOptions := &terraform.Options{
25 | // The path to where our Terraform code is located
26 | TerraformDir: tempTestFolder,
27 | Upgrade: true,
28 | // Variables to pass to our Terraform code using -var-file options
29 | VarFiles: varFiles,
30 | Vars: map[string]interface{}{
31 | "attributes": attributes,
32 | "random_string": randID,
33 | },
34 | }
35 |
36 | // At the end of the test, run `terraform destroy` to clean up any resources that were created
37 | defer cleanup(t, terraformOptions, tempTestFolder)
38 |
39 | // This will run `terraform init` and `terraform apply` and fail the test if there are any errors
40 | terraform.InitAndApply(t, terraformOptions)
41 |
42 | // Run `terraform output` to get the value of an output variable
43 | userId := terraform.Output(t, terraformOptions, "user_id")
44 |
45 | // Verify we're getting back the outputs we expect
46 | assert.NotEmpty(t, userId)
47 | }
48 |
--------------------------------------------------------------------------------
/test/src/utils.go:
--------------------------------------------------------------------------------
1 | package test
2 |
3 | import (
4 | "os"
5 | "testing"
6 |
7 | "github.com/gruntwork-io/terratest/modules/terraform"
8 | )
9 |
10 | func cleanup(t *testing.T, terraformOptions *terraform.Options, tempTestFolder string) {
11 | terraform.Destroy(t, terraformOptions)
12 | _ = os.RemoveAll(tempTestFolder)
13 | }
14 |
--------------------------------------------------------------------------------
/variables.tf:
--------------------------------------------------------------------------------
1 | variable "opsgenie_provider_api_key" {
2 | type = string
3 | description = "The API Key for the Opsgenie Integration. If omitted, the OPSGENIE_API_KEY environment variable is used"
4 | default = ""
5 | }
6 |
7 | variable "alert_policy" {
8 | default = {}
9 | description = "Opsgenie Alert Policy configuration"
10 | }
11 |
12 | variable "api_integration" {
13 | type = map(any)
14 | default = {}
15 | description = "Opsgenie API Integration configuration"
16 | }
17 |
18 | variable "escalation" {
19 | default = {}
20 | description = "Opsgenie Escalation configuration"
21 | }
22 |
23 | variable "integration_action" {
24 | default = {}
25 | description = "Opsgenie Integration Action configuration"
26 | }
27 |
28 | variable "notification_policy" {
29 | default = {}
30 | description = "Opsgenie Notification Policy configuration"
31 | }
32 |
33 | variable "team" {
34 | default = {}
35 | description = "Opsgenie Team configuration"
36 | }
37 |
38 | variable "team_routing_rule" {
39 | default = {}
40 | description = "Opsgenie Team Routing Rule configuration"
41 | }
42 |
43 | variable "user" {
44 | default = {}
45 | description = "Opsgenie User configuration"
46 | }
47 |
48 | variable "service" {
49 | default = {}
50 | description = "Opsgenie Service configuration"
51 | }
52 |
53 | variable "service_incident_rule" {
54 | default = {}
55 | description = "Opsgenie Service Incident Rule configuration"
56 | }
57 |
--------------------------------------------------------------------------------
/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 0.13.0"
3 |
4 | required_providers {
5 | opsgenie = {
6 | source = "opsgenie/opsgenie"
7 | version = ">= 0.4"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------