From 11be84f089c6ab01ec414a376837001f5b43912e Mon Sep 17 00:00:00 2001 From: Andriy Knysh Date: Wed, 14 Oct 2020 15:50:27 -0400 Subject: [PATCH] Add Opsgenie `service`, `service_incident_rule` and `user` modules and tests. Update `team` module (#10) * Add `Opsgenie User` module, example, and test * Update `Opsgenie Team` * Update `Opsgenie Team` * Add `Opsgenie Service` module, example and test * Add `Opsgenie Service` module, example and test * Add `Opsgenie Service` module, example and test * Add `Opsgenie Service` module, example and test * Add `Opsgenie Service Incident Rule` module, example and test * Add `Opsgenie Service Incident Rule` module, example and test * Add `Opsgenie Service Incident Rule` module, example and test * Add `Opsgenie Service Incident Rule` module, example and test * Add `Opsgenie Service Incident Rule` module, example and test * Update tests * Update tests * Update tests * Update tests --- README.md | 25 ++- README.yaml | 5 +- docs/terraform.md | 20 ++- examples/alert_policy/main.tf | 1 + examples/alert_policy/variables.tf | 5 - examples/api_integration/variables.tf | 5 - examples/complete/alert_policy.tf | 1 + examples/complete/outputs.tf | 83 ++++++++- examples/complete/service.tf | 12 ++ examples/complete/service_incident_rule.tf | 38 ++++ examples/complete/team.tf | 2 +- examples/complete/user.tf | 14 ++ examples/complete/variables.tf | 11 -- examples/config/outputs.tf | 32 +++- .../resources/service_incident_rules.yaml | 20 +++ examples/config/resources/services.yaml | 4 + examples/config/resources/teams.yaml | 10 +- examples/config/resources/users.yaml | 6 + examples/escalation/variables.tf | 5 - examples/notification_policy/variables.tf | 5 - examples/team/variables.tf | 5 - examples/user/context.tf | 167 ++++++++++++++++++ examples/user/fixtures.tfvars | 4 + examples/user/main.tf | 15 ++ examples/user/outputs.tf | 14 ++ examples/user/variables.tf | 5 + examples/user/versions.tf | 10 ++ main.tf | 18 ++ modules/alert_policy/main.tf | 2 +- modules/alert_policy/variables.tf | 2 +- modules/api_integration/variables.tf | 2 +- modules/config/README.md | 72 ++++++-- modules/config/main.tf | 15 +- modules/config/outputs.tf | 23 ++- modules/config/service_incident_rules.tf | 33 ++++ modules/config/services.tf | 9 + modules/config/teams.tf | 9 + modules/config/users.tf | 11 ++ modules/config/variables.tf | 2 +- modules/escalation/variables.tf | 2 +- modules/notification_policy/variables.tf | 2 +- modules/service/README.md | 36 ++++ modules/service/context.tf | 167 ++++++++++++++++++ modules/service/main.tf | 7 + modules/service/outputs.tf | 9 + modules/service/variables.tf | 4 + modules/service/versions.tf | 10 ++ modules/service_incident_rule/README.md | 57 ++++++ modules/service_incident_rule/context.tf | 167 ++++++++++++++++++ modules/service_incident_rule/main.tf | 33 ++++ modules/service_incident_rule/outputs.tf | 4 + modules/service_incident_rule/variables.tf | 4 + modules/service_incident_rule/versions.tf | 10 ++ modules/team/README.md | 2 - modules/team/main.tf | 9 + modules/team/variables.tf | 2 +- modules/team_routing_rule/variables.tf | 2 +- modules/user/README.md | 40 +++++ modules/user/context.tf | 167 ++++++++++++++++++ modules/user/main.tf | 9 + modules/user/outputs.tf | 9 + modules/user/variables.tf | 4 + modules/user/versions.tf | 10 ++ outputs.tf | 25 +++ test/Makefile | 1 - test/src/examples_complete_test.go | 31 ++++ test/src/examples_user_test.go | 30 ++++ variables.tf | 27 ++- 68 files changed, 1506 insertions(+), 96 deletions(-) create mode 100644 examples/complete/service.tf create mode 100644 examples/complete/service_incident_rule.tf create mode 100644 examples/complete/user.tf create mode 100644 examples/config/resources/service_incident_rules.yaml create mode 100644 examples/config/resources/services.yaml create mode 100644 examples/config/resources/users.yaml create mode 100644 examples/user/context.tf create mode 100644 examples/user/fixtures.tfvars create mode 100644 examples/user/main.tf create mode 100644 examples/user/outputs.tf create mode 100644 examples/user/variables.tf create mode 100644 examples/user/versions.tf create mode 100644 modules/config/service_incident_rules.tf create mode 100644 modules/config/services.tf create mode 100644 modules/config/users.tf create mode 100644 modules/service/README.md create mode 100644 modules/service/context.tf create mode 100644 modules/service/main.tf create mode 100644 modules/service/outputs.tf create mode 100644 modules/service/variables.tf create mode 100644 modules/service/versions.tf create mode 100644 modules/service_incident_rule/README.md create mode 100644 modules/service_incident_rule/context.tf create mode 100644 modules/service_incident_rule/main.tf create mode 100644 modules/service_incident_rule/outputs.tf create mode 100644 modules/service_incident_rule/variables.tf create mode 100644 modules/service_incident_rule/versions.tf create mode 100644 modules/user/README.md create mode 100644 modules/user/context.tf create mode 100644 modules/user/main.tf create mode 100644 modules/user/outputs.tf create mode 100644 modules/user/variables.tf create mode 100644 modules/user/versions.tf create mode 100644 test/src/examples_user_test.go diff --git a/README.md b/README.md index 9897836..af84113 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,9 @@ Available modules: - [Notification Policy](modules/notification_policy) - [Team](modules/team) - [Team Routing Rule](modules/team_routing_rule) +- [User](modules/user) +- [Service](modules/service) +- [Service Incident Rule](modules/service_incident_rule) **Note:** Root module is just an example that uses all of submodules. @@ -91,7 +94,6 @@ module "team-name" { name = "team-name" description = "team-description" } - } ``` @@ -111,6 +113,7 @@ Submodules examples: - [`notification_policy`](examples/notification_policy) - [`team`](examples/team) - [`team_routing_rule`](examples/team_routing_rule) +- [`user`](examples/user) Here is an example of using the `config` module, which incorporates all resource declarations into a single module: - [`config`](examples/config) @@ -149,25 +152,28 @@ No provider. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | additional\_tag\_map | Additional tags for appending to tags\_as\_list\_of\_maps. Not added to `tags`. | `map(string)` | `{}` | no | -| alert\_policy | This variable is used to configure Opsgenie Alert Policy | `map` | `{}` | no | -| api\_integration | This variable is used to configure Opsgenie API Integration | `map` | `{}` | no | +| alert\_policy | Opsgenie Alert Policy configuration | `map` | `{}` | no | +| api\_integration | Opsgenie API Integration configuration | `map` | `{}` | no | | attributes | Additional attributes (e.g. `1`) | `list(string)` | `[]` | no | | context | Single object for setting entire context at once.
See description of individual variables for details.
Leave string and numeric variables as `null` to use default value.
Individual variable settings (non-null) override settings in context object,
except for attributes, tags, and additional\_tag\_map, which are merged. |
object({
enabled = bool
namespace = string
environment = string
stage = string
name = string
delimiter = string
attributes = list(string)
tags = map(string)
additional_tag_map = map(string)
regex_replace_chars = string
label_order = list(string)
id_length_limit = number
})
|
{
"additional_tag_map": {},
"attributes": [],
"delimiter": null,
"enabled": true,
"environment": null,
"id_length_limit": null,
"label_order": [],
"name": null,
"namespace": null,
"regex_replace_chars": null,
"stage": null,
"tags": {}
}
| no | | delimiter | Delimiter to be used between `namespace`, `environment`, `stage`, `name` and `attributes`.
Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. | `string` | `null` | no | | enabled | Set to false to prevent the module from creating any resources | `bool` | `null` | no | | environment | Environment, e.g. 'uw2', 'us-west-2', OR 'prod', 'staging', 'dev', 'UAT' | `string` | `null` | no | -| escalation | This variable is used to configure Opsgenie Escalation | `map` | `{}` | no | +| escalation | Opsgenie Escalation configuration | `map` | `{}` | no | | id\_length\_limit | Limit `id` to this many characters.
Set to `0` for unlimited length.
Set to `null` for default, which is `0`.
Does not affect `id_full`. | `number` | `null` | no | | label\_order | The naming order of the id output and Name tag.
Defaults to ["namespace", "environment", "stage", "name", "attributes"].
You can omit any of the 5 elements, but at least one must be present. | `list(string)` | `null` | no | | name | Solution name, e.g. 'app' or 'jenkins' | `string` | `null` | no | | namespace | Namespace, which could be your organization name or abbreviation, e.g. 'eg' or 'cp' | `string` | `null` | no | -| notification\_policy | This variable is used to configure Opsgenie Notification Policy | `map` | `{}` | no | +| notification\_policy | Opsgenie Notification Policy configuration | `map` | `{}` | no | | opsgenie\_provider\_api\_key | The API Key for the Opsgenie Integration. If omitted, the OPSGENIE\_API\_KEY environment variable is used | `string` | `""` | no | | regex\_replace\_chars | Regex to replace chars with empty string in `namespace`, `environment`, `stage` and `name`.
If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. | `string` | `null` | no | +| service | Opsgenie Service configuration | `map` | `{}` | no | +| service\_incident\_rule | Opsgenie Service Incident Rule configuration | `map` | `{}` | no | | stage | Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no | | tags | Additional tags (e.g. `map('BusinessUnit','XYZ')` | `map(string)` | `{}` | no | -| team | This variable is used to configure Opsgenie Team | `map` | `{}` | no | -| team\_routing\_rule | This variable is used to configure Opsgenie Team Routing Rule | `map` | `{}` | no | +| team | Opsgenie Team configuration | `map` | `{}` | no | +| team\_routing\_rule | Opsgenie Team Routing Rule configuration | `map` | `{}` | no | +| user | Opsgenie User configuration | `map` | `{}` | no | ## Outputs @@ -186,10 +192,15 @@ No provider. | escalation\_name | Name of the Opsgenie Escalation | | notification\_policy\_id | The ID of the Opsgenie Notification Policy | | notification\_policy\_name | The name of the Opsgenie Notification Policy | +| service\_id | The ID of the Opsgenie Service | +| service\_incident\_rule\_id | The ID of the Opsgenie Service Incident Rule | +| service\_name | The name of the Opsgenie Service | | team\_id | The ID of the Opsgenie Team | | team\_name | The name of the Opsgenie Team | | team\_routing\_rule\_id | The ID of the Opsgenie Team Routing Rule | | team\_routing\_rule\_name | The name of the Opsgenie Team Routing Rule | +| user\_id | The ID of the Opsgenie User | +| user\_name | The name of the Opsgenie User | diff --git a/README.yaml b/README.yaml index 77462fb..018e4c7 100644 --- a/README.yaml +++ b/README.yaml @@ -67,6 +67,9 @@ introduction: |- - [Notification Policy](modules/notification_policy) - [Team](modules/team) - [Team Routing Rule](modules/team_routing_rule) + - [User](modules/user) + - [Service](modules/service) + - [Service Incident Rule](modules/service_incident_rule) **Note:** Root module is just an example that uses all of submodules. @@ -81,7 +84,6 @@ usage: |- name = "team-name" description = "team-description" } - } ``` @@ -98,6 +100,7 @@ examples: |- - [`notification_policy`](examples/notification_policy) - [`team`](examples/team) - [`team_routing_rule`](examples/team_routing_rule) + - [`user`](examples/user) Here is an example of using the `config` module, which incorporates all resource declarations into a single module: - [`config`](examples/config) diff --git a/docs/terraform.md b/docs/terraform.md index 35ef058..af4cd77 100644 --- a/docs/terraform.md +++ b/docs/terraform.md @@ -15,25 +15,28 @@ No provider. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | additional\_tag\_map | Additional tags for appending to tags\_as\_list\_of\_maps. Not added to `tags`. | `map(string)` | `{}` | no | -| alert\_policy | This variable is used to configure Opsgenie Alert Policy | `map` | `{}` | no | -| api\_integration | This variable is used to configure Opsgenie API Integration | `map` | `{}` | no | +| alert\_policy | Opsgenie Alert Policy configuration | `map` | `{}` | no | +| api\_integration | Opsgenie API Integration configuration | `map` | `{}` | no | | attributes | Additional attributes (e.g. `1`) | `list(string)` | `[]` | no | | context | Single object for setting entire context at once.
See description of individual variables for details.
Leave string and numeric variables as `null` to use default value.
Individual variable settings (non-null) override settings in context object,
except for attributes, tags, and additional\_tag\_map, which are merged. |
object({
enabled = bool
namespace = string
environment = string
stage = string
name = string
delimiter = string
attributes = list(string)
tags = map(string)
additional_tag_map = map(string)
regex_replace_chars = string
label_order = list(string)
id_length_limit = number
})
|
{
"additional_tag_map": {},
"attributes": [],
"delimiter": null,
"enabled": true,
"environment": null,
"id_length_limit": null,
"label_order": [],
"name": null,
"namespace": null,
"regex_replace_chars": null,
"stage": null,
"tags": {}
}
| no | | delimiter | Delimiter to be used between `namespace`, `environment`, `stage`, `name` and `attributes`.
Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. | `string` | `null` | no | | enabled | Set to false to prevent the module from creating any resources | `bool` | `null` | no | | environment | Environment, e.g. 'uw2', 'us-west-2', OR 'prod', 'staging', 'dev', 'UAT' | `string` | `null` | no | -| escalation | This variable is used to configure Opsgenie Escalation | `map` | `{}` | no | +| escalation | Opsgenie Escalation configuration | `map` | `{}` | no | | id\_length\_limit | Limit `id` to this many characters.
Set to `0` for unlimited length.
Set to `null` for default, which is `0`.
Does not affect `id_full`. | `number` | `null` | no | | label\_order | The naming order of the id output and Name tag.
Defaults to ["namespace", "environment", "stage", "name", "attributes"].
You can omit any of the 5 elements, but at least one must be present. | `list(string)` | `null` | no | | name | Solution name, e.g. 'app' or 'jenkins' | `string` | `null` | no | | namespace | Namespace, which could be your organization name or abbreviation, e.g. 'eg' or 'cp' | `string` | `null` | no | -| notification\_policy | This variable is used to configure Opsgenie Notification Policy | `map` | `{}` | no | +| notification\_policy | Opsgenie Notification Policy configuration | `map` | `{}` | no | | opsgenie\_provider\_api\_key | The API Key for the Opsgenie Integration. If omitted, the OPSGENIE\_API\_KEY environment variable is used | `string` | `""` | no | | regex\_replace\_chars | Regex to replace chars with empty string in `namespace`, `environment`, `stage` and `name`.
If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. | `string` | `null` | no | +| service | Opsgenie Service configuration | `map` | `{}` | no | +| service\_incident\_rule | Opsgenie Service Incident Rule configuration | `map` | `{}` | no | | stage | Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no | | tags | Additional tags (e.g. `map('BusinessUnit','XYZ')` | `map(string)` | `{}` | no | -| team | This variable is used to configure Opsgenie Team | `map` | `{}` | no | -| team\_routing\_rule | This variable is used to configure Opsgenie Team Routing Rule | `map` | `{}` | no | +| team | Opsgenie Team configuration | `map` | `{}` | no | +| team\_routing\_rule | Opsgenie Team Routing Rule configuration | `map` | `{}` | no | +| user | Opsgenie User configuration | `map` | `{}` | no | ## Outputs @@ -52,9 +55,14 @@ No provider. | escalation\_name | Name of the Opsgenie Escalation | | notification\_policy\_id | The ID of the Opsgenie Notification Policy | | notification\_policy\_name | The name of the Opsgenie Notification Policy | +| service\_id | The ID of the Opsgenie Service | +| service\_incident\_rule\_id | The ID of the Opsgenie Service Incident Rule | +| service\_name | The name of the Opsgenie Service | | team\_id | The ID of the Opsgenie Team | | team\_name | The name of the Opsgenie Team | | team\_routing\_rule\_id | The ID of the Opsgenie Team Routing Rule | | team\_routing\_rule\_name | The name of the Opsgenie Team Routing Rule | +| user\_id | The ID of the Opsgenie User | +| user\_name | The name of the Opsgenie User | diff --git a/examples/alert_policy/main.tf b/examples/alert_policy/main.tf index 29be3e7..1c092fb 100644 --- a/examples/alert_policy/main.tf +++ b/examples/alert_policy/main.tf @@ -22,6 +22,7 @@ module "alert_policy" { type = "match-all-conditions" conditions = [ { + # Possible values are "message", "alias", "description", "source", "entity", "tags", "actions", "details", "extra-properties", "recipients", "teams", "priority" field = "source" operation = "matches" expected_value = ".*prod.*" diff --git a/examples/alert_policy/variables.tf b/examples/alert_policy/variables.tf index e4643cf..841a369 100644 --- a/examples/alert_policy/variables.tf +++ b/examples/alert_policy/variables.tf @@ -3,8 +3,3 @@ variable "opsgenie_provider_api_key" { description = "The API Key for the Opsgenie Integration. If omitted, the OPSGENIE_API_KEY environment variable is used" default = null } - -variable "opsgenie_alert_policy" { - description = "This variable is used to configure opsgenie alert policy" - default = {} -} diff --git a/examples/api_integration/variables.tf b/examples/api_integration/variables.tf index 86aa4c9..841a369 100644 --- a/examples/api_integration/variables.tf +++ b/examples/api_integration/variables.tf @@ -3,8 +3,3 @@ variable "opsgenie_provider_api_key" { description = "The API Key for the Opsgenie Integration. If omitted, the OPSGENIE_API_KEY environment variable is used" default = null } - -variable "opsgenie_integration" { - description = "This variable is used to configure opsgenie integration" - default = {} -} diff --git a/examples/complete/alert_policy.tf b/examples/complete/alert_policy.tf index af91e7f..9aea8c9 100644 --- a/examples/complete/alert_policy.tf +++ b/examples/complete/alert_policy.tf @@ -8,6 +8,7 @@ module "alert_policy" { type = "match-all" conditions = [ { + # Possible values are "message", "alias", "description", "source", "entity", "tags", "actions", "details", "extra-properties", "recipients", "teams", "priority" field = "source" operation = "matches" expected_value = ".*stage.*" diff --git a/examples/complete/outputs.tf b/examples/complete/outputs.tf index e862279..57fd416 100644 --- a/examples/complete/outputs.tf +++ b/examples/complete/outputs.tf @@ -1,9 +1,84 @@ +output "escalation_id" { + description = "The ID of the Opsgenie escalation" + value = module.escalation.escalation_id +} + output "escalation_name" { - description = "The Name of the Opsgenie escalation" + description = "The name of the Opsgenie escalation" value = module.escalation.escalation_name } -output "escalation_id" { - description = "The ID of the Opsgenie escalation" - value = module.escalation.escalation_id +output "api_integration_id" { + description = "The ID of the Opsgenie integration" + value = module.api_integration.api_integration_id +} + +output "api_integration_name" { + description = "The name of the Opsgenie integration" + value = module.api_integration.api_integration_name +} + +output "alert_policy_id" { + description = "The ID of the Opsgenie policy" + value = module.alert_policy.alert_policy_id +} + +output "alert_policy_name" { + description = "The name of the Opsgenie policy" + value = module.alert_policy.alert_policy_name +} + +output "notification_policy_id" { + description = "The ID of the Opsgenie notification policy" + value = module.notification_policy.notification_policy_id +} + +output "notification_policy_name" { + description = "The name of the Opsgenie notification policy" + value = module.notification_policy.notification_policy_name +} + +output "team_routing_rule_id" { + description = "The ID of the Opsgenie team routing rule" + value = module.team_routing_rule.team_routing_rule_id +} + +output "team_routing_rule_name" { + description = "The name of the Opsgenie team routing rule" + value = module.team_routing_rule.team_routing_rule_name +} + +output "team_id" { + description = "The ID of the Opsgenie team" + value = module.team.team_id +} + +output "team_name" { + description = "The name of the Opsgenie team" + value = module.team.team_name +} + +output "user_id" { + description = "The ID of the Opsgenie user" + value = module.user.user_id +} + +output "user_name" { + description = "The name of the Opsgenie user" + value = module.user.user_name +} + +output "service_id" { + description = "The ID of the Opsgenie service" + value = module.service.service_id +} + +output "service_name" { + description = "The name of the Opsgenie service" + value = module.service.service_name +} + +output "service_incident_rule_id" { + description = "The ID of the Opsgenie service incident rule" + value = module.service_incident_rule.service_incident_rule_id } diff --git a/examples/complete/service.tf b/examples/complete/service.tf new file mode 100644 index 0000000..837a4aa --- /dev/null +++ b/examples/complete/service.tf @@ -0,0 +1,12 @@ +module "service" { + source = "../../modules/service" + + # Services are Opsgenie Enterprise feature, disable it for now + enabled = false + + service = { + name = "frontend" + description = "Frontend service" + team_id = module.team.team_id + } +} diff --git a/examples/complete/service_incident_rule.tf b/examples/complete/service_incident_rule.tf new file mode 100644 index 0000000..5ca1dc1 --- /dev/null +++ b/examples/complete/service_incident_rule.tf @@ -0,0 +1,38 @@ +module "service_incident_rule" { + source = "../../modules/service_incident_rule" + + # Services are Opsgenie Enterprise feature, disable it for now + enabled = false + + service_incident_rule = { + service_id = module.service.service_id + + incident_rule = { + condition_match_type = "match-all" + + conditions = [ + { + # Possibke values: message, description, tags, extra-properties, recipients, teams, priority + field = "message" + operation = "matches" + expected_value = ".*stage.*" + }, + { + field = "tags" + operation = "contains" + expected_value = "severity:info" + } + ] + + incident_properties = { + message = "This is a test message" + priority = "P3" + + stakeholder_properties = { + message = "Message for stakeholders" + enable = true + } + } + } + } +} diff --git a/examples/complete/team.tf b/examples/complete/team.tf index 434a4df..7d1377c 100644 --- a/examples/complete/team.tf +++ b/examples/complete/team.tf @@ -4,7 +4,7 @@ module "team" { team = { name = module.this.id description = "team-description" - ignore_members = var.ignore_members + ignore_members = false } } diff --git a/examples/complete/user.tf b/examples/complete/user.tf new file mode 100644 index 0000000..89cbae6 --- /dev/null +++ b/examples/complete/user.tf @@ -0,0 +1,14 @@ +module "user" { + source = "../../modules/user" + + # Users can't be destroyed + enabled = false + + user = { + username = "opsgenie-test@cloudposse.com" + full_name = "Opsgenie Test User" + role = "User" + locale = "en_US" + timezone = "America/New_York" + } +} diff --git a/examples/complete/variables.tf b/examples/complete/variables.tf index 21deac8..841a369 100644 --- a/examples/complete/variables.tf +++ b/examples/complete/variables.tf @@ -3,14 +3,3 @@ variable "opsgenie_provider_api_key" { description = "The API Key for the Opsgenie Integration. If omitted, the OPSGENIE_API_KEY environment variable is used" default = null } - -variable "opsgenie_team" { - description = "This variable is used to configure opsgenie team" - default = {} -} - -variable "ignore_members" { - type = bool - description = "Set to true to ignore any configured member blocks and any team member added/updated/removed via OpsGenie web UI" - default = false -} diff --git a/examples/config/outputs.tf b/examples/config/outputs.tf index b04a924..d34387c 100644 --- a/examples/config/outputs.tf +++ b/examples/config/outputs.tf @@ -1,24 +1,44 @@ output "api_integrations" { - value = module.opsgenie_config.api_integrations + value = module.opsgenie_config.api_integrations + description = "API integrations" } output "alert_policies" { - value = module.opsgenie_config.alert_policies + value = module.opsgenie_config.alert_policies + description = "Alert policies" } output "escalations" { - value = module.opsgenie_config.escalations + value = module.opsgenie_config.escalations + description = "Escalations" } output "notification_policies" { - value = module.opsgenie_config.notification_policies + value = module.opsgenie_config.notification_policies + description = "Notification policies" } output "team_routing_rules" { - value = module.opsgenie_config.team_routing_rules + value = module.opsgenie_config.team_routing_rules + description = "Team routing rules" } output "teams" { - value = module.opsgenie_config.teams + value = module.opsgenie_config.teams + description = "Teams" } +output "users" { + value = module.opsgenie_config.users + description = "Users" +} + +output "services" { + value = module.opsgenie_config.services + description = "Services" +} + +output "service_incident_rule_ids" { + value = module.opsgenie_config.service_incident_rule_ids + description = "Service Incident Rule IDs" +} diff --git a/examples/config/resources/service_incident_rules.yaml b/examples/config/resources/service_incident_rules.yaml new file mode 100644 index 0000000..17193b7 --- /dev/null +++ b/examples/config/resources/service_incident_rules.yaml @@ -0,0 +1,20 @@ +service_incident_rules: + - service_name: frontend + incident_rule: + condition_match_type: match-all + + conditions: + - field: message + operation: matches + expected_value: ".*stage.*" + - field: tags + operation: contains + expected_value: "severity:info" + + incident_properties: + message: This is a test message + priority: P3 + + stakeholder_properties: + message: Message for stakeholders + enable: true diff --git a/examples/config/resources/services.yaml b/examples/config/resources/services.yaml new file mode 100644 index 0000000..befaf93 --- /dev/null +++ b/examples/config/resources/services.yaml @@ -0,0 +1,4 @@ +services: + - name: frontend + description: Frontend service + team_name: acme diff --git a/examples/config/resources/teams.yaml b/examples/config/resources/teams.yaml index 763a023..28043e2 100644 --- a/examples/config/resources/teams.yaml +++ b/examples/config/resources/teams.yaml @@ -1,11 +1,19 @@ teams: - name: acme description: Global Team for Acme Co. + members: + username: opsgenie-test@cloudposse.com + role: admin - name: acme.dev description: Acme Dev Team delete_default_resources: true + members: + username: opsgenie-test@cloudposse.com + role: admin - name: acme.dev.some-service description: "repo: https://github.com/acme/some-service;owner:David Lightman @David Lightman" ignore_members: true delete_default_resources: true - + members: + username: opsgenie-test@cloudposse.com + role: admin diff --git a/examples/config/resources/users.yaml b/examples/config/resources/users.yaml new file mode 100644 index 0000000..2ab33d1 --- /dev/null +++ b/examples/config/resources/users.yaml @@ -0,0 +1,6 @@ +users: + - username: opsgenie-test@cloudposse.com + full_name: Opsgenie Test User + role: User + locale: "en_US" + timezone: "America/New_York" diff --git a/examples/escalation/variables.tf b/examples/escalation/variables.tf index cd60d79..841a369 100644 --- a/examples/escalation/variables.tf +++ b/examples/escalation/variables.tf @@ -3,8 +3,3 @@ variable "opsgenie_provider_api_key" { description = "The API Key for the Opsgenie Integration. If omitted, the OPSGENIE_API_KEY environment variable is used" default = null } - -variable "opsgenie_team" { - description = "This variable is used to configure opsgenie team" - default = {} -} diff --git a/examples/notification_policy/variables.tf b/examples/notification_policy/variables.tf index cd60d79..841a369 100644 --- a/examples/notification_policy/variables.tf +++ b/examples/notification_policy/variables.tf @@ -3,8 +3,3 @@ variable "opsgenie_provider_api_key" { description = "The API Key for the Opsgenie Integration. If omitted, the OPSGENIE_API_KEY environment variable is used" default = null } - -variable "opsgenie_team" { - description = "This variable is used to configure opsgenie team" - default = {} -} diff --git a/examples/team/variables.tf b/examples/team/variables.tf index cd60d79..841a369 100644 --- a/examples/team/variables.tf +++ b/examples/team/variables.tf @@ -3,8 +3,3 @@ variable "opsgenie_provider_api_key" { description = "The API Key for the Opsgenie Integration. If omitted, the OPSGENIE_API_KEY environment variable is used" default = null } - -variable "opsgenie_team" { - description = "This variable is used to configure opsgenie team" - default = {} -} diff --git a/examples/user/context.tf b/examples/user/context.tf new file mode 100644 index 0000000..bae0cf1 --- /dev/null +++ b/examples/user/context.tf @@ -0,0 +1,167 @@ +# +# ONLY EDIT THIS FILE IN github.com/cloudposse/terraform-null-label +# All other instances of this file should be a copy of that one +# +# +# Copy this file from https://github.com/cloudposse/terraform-null-label/blob/master/exports/context.tf +# and then place it in your Terraform module to automatically get +# Cloud Posse's standard configuration inputs suitable for passing +# to Cloud Posse modules. +# +# Modules should access the whole context as `module.this.context` +# to get the input variables with nulls for defaults, +# for example `context = module.this.context`, +# and access individual variables as `module.this.`, +# with final values filled in. +# +# For example, when using defaults, `module.this.context.delimiter` +# will be null, and `module.this.delimiter` will be `-` (hyphen). +# + +module "this" { + source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=tags/0.19.2" + + enabled = var.enabled + namespace = var.namespace + environment = var.environment + stage = var.stage + name = var.name + delimiter = var.delimiter + attributes = var.attributes + tags = var.tags + additional_tag_map = var.additional_tag_map + label_order = var.label_order + regex_replace_chars = var.regex_replace_chars + id_length_limit = var.id_length_limit + + context = var.context +} + +# Copy contents of cloudposse/terraform-null-label/variables.tf here + +variable "context" { + type = object({ + enabled = bool + namespace = string + environment = string + stage = string + name = string + delimiter = string + attributes = list(string) + tags = map(string) + additional_tag_map = map(string) + regex_replace_chars = string + label_order = list(string) + id_length_limit = number + }) + default = { + enabled = true + namespace = null + environment = null + stage = null + name = null + delimiter = null + attributes = [] + tags = {} + additional_tag_map = {} + regex_replace_chars = null + label_order = [] + id_length_limit = null + } + description = <<-EOT + Single object for setting entire context at once. + See description of individual variables for details. + Leave string and numeric variables as `null` to use default value. + Individual variable settings (non-null) override settings in context object, + except for attributes, tags, and additional_tag_map, which are merged. + EOT +} + +variable "enabled" { + type = bool + default = null + description = "Set to false to prevent the module from creating any resources" +} + +variable "namespace" { + type = string + default = null + description = "Namespace, which could be your organization name or abbreviation, e.g. 'eg' or 'cp'" +} + +variable "environment" { + type = string + default = null + description = "Environment, e.g. 'uw2', 'us-west-2', OR 'prod', 'staging', 'dev', 'UAT'" +} + +variable "stage" { + type = string + default = null + description = "Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release'" +} + +variable "name" { + type = string + default = null + description = "Solution name, e.g. 'app' or 'jenkins'" +} + +variable "delimiter" { + type = string + default = null + description = <<-EOT + Delimiter to be used between `namespace`, `environment`, `stage`, `name` and `attributes`. + Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. + EOT +} + +variable "attributes" { + type = list(string) + default = [] + description = "Additional attributes (e.g. `1`)" +} + +variable "tags" { + type = map(string) + default = {} + description = "Additional tags (e.g. `map('BusinessUnit','XYZ')`" +} + +variable "additional_tag_map" { + type = map(string) + default = {} + description = "Additional tags for appending to tags_as_list_of_maps. Not added to `tags`." +} + +variable "label_order" { + type = list(string) + default = null + description = <<-EOT + The naming order of the id output and Name tag. + Defaults to ["namespace", "environment", "stage", "name", "attributes"]. + You can omit any of the 5 elements, but at least one must be present. + EOT +} + +variable "regex_replace_chars" { + type = string + default = null + description = <<-EOT + Regex to replace chars with empty string in `namespace`, `environment`, `stage` and `name`. + If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. + EOT +} + +variable "id_length_limit" { + type = number + default = null + description = <<-EOT + Limit `id` to this many characters. + Set to `0` for unlimited length. + Set to `null` for default, which is `0`. + Does not affect `id_full`. + EOT +} + +#### End of copy of cloudposse/terraform-null-label/variables.tf diff --git a/examples/user/fixtures.tfvars b/examples/user/fixtures.tfvars new file mode 100644 index 0000000..1567b33 --- /dev/null +++ b/examples/user/fixtures.tfvars @@ -0,0 +1,4 @@ +enabled = true +namespace = "eg" +stage = "test" +name = "user" diff --git a/examples/user/main.tf b/examples/user/main.tf new file mode 100644 index 0000000..6e25a59 --- /dev/null +++ b/examples/user/main.tf @@ -0,0 +1,15 @@ +provider "opsgenie" { + api_key = var.opsgenie_provider_api_key +} + +module "user" { + source = "../../modules/user" + + user = { + username = "opsgenie-test@cloudposse.com" + full_name = "Opsgenie Test User" + role = "User" + locale = "en_US" + timezone = "America/New_York" + } +} diff --git a/examples/user/outputs.tf b/examples/user/outputs.tf new file mode 100644 index 0000000..9ec0d07 --- /dev/null +++ b/examples/user/outputs.tf @@ -0,0 +1,14 @@ +output "user" { + description = "Opsgenie User" + value = module.user +} + +output "user_id" { + description = "The ID of the Opsgenie User" + value = module.user.user_id +} + +output "user_name" { + description = "The name of the Opsgenie User" + value = module.user.user_name +} diff --git a/examples/user/variables.tf b/examples/user/variables.tf new file mode 100644 index 0000000..841a369 --- /dev/null +++ b/examples/user/variables.tf @@ -0,0 +1,5 @@ +variable "opsgenie_provider_api_key" { + type = string + description = "The API Key for the Opsgenie Integration. If omitted, the OPSGENIE_API_KEY environment variable is used" + default = null +} diff --git a/examples/user/versions.tf b/examples/user/versions.tf new file mode 100644 index 0000000..600eea7 --- /dev/null +++ b/examples/user/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = ">= 0.12.26" + + required_providers { + opsgenie = { + source = "opsgenie/opsgenie" + version = ">= 0.4" + } + } +} diff --git a/main.tf b/main.tf index f2906f1..030e551 100644 --- a/main.tf +++ b/main.tf @@ -37,3 +37,21 @@ module "team_routing_rule" { team_routing_rule = var.team_routing_rule } + +module "user" { + source = "./modules/user" + + user = var.user +} + +module "service" { + source = "./modules/service" + + service = var.service +} + +module "service_incident_rule" { + source = "./modules/service_incident_rule" + + service_incident_rule = var.service_incident_rule +} diff --git a/modules/alert_policy/main.tf b/modules/alert_policy/main.tf index e55781d..6fcb2fe 100644 --- a/modules/alert_policy/main.tf +++ b/modules/alert_policy/main.tf @@ -22,7 +22,7 @@ resource "opsgenie_alert_policy" "this" { for_each = try(var.alert_policy.responders, []) content { - id = try(responders.value.id, null) + id = responders.value.id name = try(responders.value.name, null) type = responders.value.type username = try(responders.value.username, null) diff --git a/modules/alert_policy/variables.tf b/modules/alert_policy/variables.tf index efe39da..e1c4f1c 100644 --- a/modules/alert_policy/variables.tf +++ b/modules/alert_policy/variables.tf @@ -1,4 +1,4 @@ variable "alert_policy" { default = {} - description = "This variable is used to configure Opsgenie Alert Policy." + description = "Opsgenie Alert Policy configuration" } diff --git a/modules/api_integration/variables.tf b/modules/api_integration/variables.tf index 6c06fc5..f293ca5 100644 --- a/modules/api_integration/variables.tf +++ b/modules/api_integration/variables.tf @@ -1,4 +1,4 @@ variable "api_integration" { default = {} - description = "This variable is used to configure Opsgenie API Integration" + description = "Opsgenie API Integration configuration" } diff --git a/modules/config/README.md b/modules/config/README.md index 58fbc39..715e445 100644 --- a/modules/config/README.md +++ b/modules/config/README.md @@ -1,8 +1,12 @@ ## Config -A Terraform module that configures a multitude of [Opsgenie resources](https://registry.terraform.io/providers/opsgenie/opsgenie/latest/docs). Many resources have cross-resource dependencies, which may be simpler to handle within a single module in certain cases, such as using YAML configurations. +Terraform module that configures a multitude of [Opsgenie resources](https://registry.terraform.io/providers/opsgenie/opsgenie/latest/docs). +Many resources have cross-resource dependencies, which may be simpler to handle within a single module in certain cases, such as using YAML configurations. -This module is designed to accept an input configuration map. One nice way of handling this by passing resource definitions from a YAML configuration file. See below for details & examples. +This module is designed to accept an input configuration map. +One nice way of handling this is by passing resource definitions from a YAML configuration file. + +See below for details & examples. ## YAML Examples @@ -98,6 +102,50 @@ teams: description: "repo: https://github.com/acme/some-service;owner:David Lightman @David Lightman" ``` +### `users.yaml` + +```yaml +users: +- username: opsgenie-test@cloudposse.com + full_name: Opsgenie Test User + role: User + locale: "en_US" + timezone: "America/New_York" +``` + +### `services.yaml` + +```yaml +services: +- name: frontend + team_id: "..." + description: Frontend service +``` + +### `service_incident_rules.yaml` + +```yaml +service_incident_rules: +- service_name: frontend + incident_rule: + condition_match_type: match-all + + conditions: + - field: source + operation: matches + expected_value: ".*stage.*" + - field: tags + operation: contains + expected_value: "severity:info" + + incident_properties: + message: This is a test message + priority: P3 + + stakeholder_properties: + message: Message for stakeholders + enable: true +``` ## Usage @@ -129,11 +177,15 @@ module "opsgenie" { ## Outputs -| Name | Description | -|:------------------------|:--------------------------------------------| -| `alert_policies` | `name` and `id` of each alert policy | -| `api_integrations` | `name` and `id` of each API integration | -| `escalations` | `name` and `id` of each escalation | -| `notification_policies` | `name` and `id` of each notification policy | -| `team_routing_rules` | `name` and `id` of each team routing rule | -| `teams` | `name` and `id` of each team | +| Name | Description | +|:----------------------------|:--------------------------------------------| +| `alert_policies` | `name` and `id` of each alert policy | +| `api_integrations` | `name` and `id` of each API integration | +| `escalations` | `name` and `id` of each escalation | +| `notification_policies` | `name` and `id` of each notification policy | +| `team_routing_rules` | `name` and `id` of each team routing rule | +| `teams` | `name` and `id` of each team | +| `users` | `name` and `id` of each user | +| `services` | `name` and `id` of each service | +| `services` | `name` and `id` of each service | +| `service_incident_rule_ids` | `id` of each service incident rule | diff --git a/modules/config/main.tf b/modules/config/main.tf index 3ad709e..5d3d2b4 100644 --- a/modules/config/main.tf +++ b/modules/config/main.tf @@ -1,8 +1,11 @@ locals { - alert_policies = try(var.opsgenie_resources.alert_policies, []) - api_integrations = try(var.opsgenie_resources.api_integrations, []) - escalations = try(var.opsgenie_resources.escalations, []) - notification_policies = try(var.opsgenie_resources.notification_policies, []) - team_routing_rules = try(var.opsgenie_resources.team_routing_rules, []) - teams = try(var.opsgenie_resources.teams, []) + alert_policies = try(var.opsgenie_resources.alert_policies, []) + api_integrations = try(var.opsgenie_resources.api_integrations, []) + escalations = try(var.opsgenie_resources.escalations, []) + notification_policies = try(var.opsgenie_resources.notification_policies, []) + team_routing_rules = try(var.opsgenie_resources.team_routing_rules, []) + teams = try(var.opsgenie_resources.teams, []) + users = try(var.opsgenie_resources.users, []) + services = try(var.opsgenie_resources.services, []) + service_incident_rules = try(var.opsgenie_resources.service_incident_rules, []) } diff --git a/modules/config/outputs.tf b/modules/config/outputs.tf index 36e6a8a..f13eee2 100644 --- a/modules/config/outputs.tf +++ b/modules/config/outputs.tf @@ -45,5 +45,26 @@ output "teams" { value = { for team in opsgenie_team.this : team.id => team.name } - description = "Team names" + description = "Teams" +} + +output "users" { + value = { + for user in opsgenie_user.this : user.id => user.username + } + description = "Users" +} + +output "services" { + value = { + for service in opsgenie_service.this : service.id => service.name + } + description = "Services" +} + +output "service_incident_rule_ids" { + value = [ + for service_incident_rule in opsgenie_service_incident_rule.this : service_incident_rule.id + ] + description = "Service Incident Rule IDs" } diff --git a/modules/config/service_incident_rules.tf b/modules/config/service_incident_rules.tf new file mode 100644 index 0000000..e0f78bd --- /dev/null +++ b/modules/config/service_incident_rules.tf @@ -0,0 +1,33 @@ +resource "opsgenie_service_incident_rule" "this" { + for_each = local.service_incident_rules + + service_id = opsgenie_service.this[each.value.service_name].id + + incident_rule { + condition_match_type = try(each.value.incident_rule.condition_match_type, "match-all") + + dynamic conditions { + for_each = try(each.value.incident_rule.conditions, []) + + content { + expected_value = try(conditions.value.expected_value, null) + field = conditions.value.field + not = try(conditions.value.not, null) + operation = conditions.value.operation + } + } + + incident_properties { + message = each.value.incident_rule.incident_properties.message + priority = each.value.incident_rule.incident_properties.priority + tags = try(each.value.incident_rule.incident_properties.tags, null) + details = try(each.value.incident_rule.incident_properties.details, null) + + stakeholder_properties { + message = each.value.incident_rule.incident_properties.stakeholder_properties.message + description = try(each.value.incident_rule.incident_properties.stakeholder_properties.description, null) + enable = try(each.value.incident_rule.incident_properties.stakeholder_properties.enable, null) + } + } + } +} diff --git a/modules/config/services.tf b/modules/config/services.tf new file mode 100644 index 0000000..52b8975 --- /dev/null +++ b/modules/config/services.tf @@ -0,0 +1,9 @@ +resource "opsgenie_service" "this" { + for_each = { + for service in local.services : service.name => service + } + + name = each.value.name + team_id = opsgenie_team.this[each.value.team_name].id + description = try(each.value.description, null) +} diff --git a/modules/config/teams.tf b/modules/config/teams.tf index 8d0f688..5bbed53 100644 --- a/modules/config/teams.tf +++ b/modules/config/teams.tf @@ -7,4 +7,13 @@ resource "opsgenie_team" "this" { description = try(each.value.description, each.value.name) ignore_members = try(each.value.ignore_members, false) delete_default_resources = try(each.value.delete_default_resources, false) + + dynamic member { + for_each = try(each.value.members, []) + + content { + id = opsgenie_user.this[member.value.username].id + role = member.value.role + } + } } diff --git a/modules/config/users.tf b/modules/config/users.tf new file mode 100644 index 0000000..77b61ea --- /dev/null +++ b/modules/config/users.tf @@ -0,0 +1,11 @@ +resource "opsgenie_user" "this" { + for_each = { + for user in local.users : user.username => user + } + + username = each.value.username + full_name = each.value.full_name + role = each.value.role + locale = try(each.value.locale, "en_US") + timezone = try(each.value.timezone, "America/New_York") +} diff --git a/modules/config/variables.tf b/modules/config/variables.tf index a11f187..6ee4766 100644 --- a/modules/config/variables.tf +++ b/modules/config/variables.tf @@ -1,4 +1,4 @@ variable "opsgenie_resources" { default = {} - description = "This variable is a map that contains all Opsgenie resource definitions" + description = "Map that contains all Opsgenie resource definitions" } diff --git a/modules/escalation/variables.tf b/modules/escalation/variables.tf index ea06288..38f7c4b 100644 --- a/modules/escalation/variables.tf +++ b/modules/escalation/variables.tf @@ -1,4 +1,4 @@ variable "escalation" { default = {} - description = "This variable is used to configure Opsgenie Escalation" + description = "Opsgenie Escalation configuration" } diff --git a/modules/notification_policy/variables.tf b/modules/notification_policy/variables.tf index b0e9b26..243f2e8 100644 --- a/modules/notification_policy/variables.tf +++ b/modules/notification_policy/variables.tf @@ -1,4 +1,4 @@ variable "notification_policy" { default = {} - description = "This variable is used to configure Opsgenie Notification Policy" + description = "Opsgenie Notification Policy configuration" } diff --git a/modules/service/README.md b/modules/service/README.md new file mode 100644 index 0000000..7392d1e --- /dev/null +++ b/modules/service/README.md @@ -0,0 +1,36 @@ +## Service + +Terraform module to configure [Opsgenie Service](https://registry.terraform.io/providers/opsgenie/opsgenie/latest/docs/resources/service) + + +## Usage + +```hcl +module "service" { + source = "git::https://github.com/cloudposse/terraform-opsgenie-incident-management.git//modules/service?ref=master" + + service = { + name = "frontend" + team_id = "..." + description = "My company frontend service" + } +} +``` + +## Inputs + +**Note:** `service` is a map for two reasons: +- to be able to put whole configuration in yaml file +- variables defined with type set are not robust enough (can't set default values) + +| Name | Default | Description | Required | +|:-------------------------------|:---------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------|:--------:| +| `service` | `{}` | Opsgenie Service configuration | Yes | + + +## Outputs + +| Name | Description | +|:----------------------------|:-----------------------------------------| +| `service_id` | The ID of the Opsgenie Service | +| `service_name` | The name of the Opsgenie Service | diff --git a/modules/service/context.tf b/modules/service/context.tf new file mode 100644 index 0000000..bae0cf1 --- /dev/null +++ b/modules/service/context.tf @@ -0,0 +1,167 @@ +# +# ONLY EDIT THIS FILE IN github.com/cloudposse/terraform-null-label +# All other instances of this file should be a copy of that one +# +# +# Copy this file from https://github.com/cloudposse/terraform-null-label/blob/master/exports/context.tf +# and then place it in your Terraform module to automatically get +# Cloud Posse's standard configuration inputs suitable for passing +# to Cloud Posse modules. +# +# Modules should access the whole context as `module.this.context` +# to get the input variables with nulls for defaults, +# for example `context = module.this.context`, +# and access individual variables as `module.this.`, +# with final values filled in. +# +# For example, when using defaults, `module.this.context.delimiter` +# will be null, and `module.this.delimiter` will be `-` (hyphen). +# + +module "this" { + source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=tags/0.19.2" + + enabled = var.enabled + namespace = var.namespace + environment = var.environment + stage = var.stage + name = var.name + delimiter = var.delimiter + attributes = var.attributes + tags = var.tags + additional_tag_map = var.additional_tag_map + label_order = var.label_order + regex_replace_chars = var.regex_replace_chars + id_length_limit = var.id_length_limit + + context = var.context +} + +# Copy contents of cloudposse/terraform-null-label/variables.tf here + +variable "context" { + type = object({ + enabled = bool + namespace = string + environment = string + stage = string + name = string + delimiter = string + attributes = list(string) + tags = map(string) + additional_tag_map = map(string) + regex_replace_chars = string + label_order = list(string) + id_length_limit = number + }) + default = { + enabled = true + namespace = null + environment = null + stage = null + name = null + delimiter = null + attributes = [] + tags = {} + additional_tag_map = {} + regex_replace_chars = null + label_order = [] + id_length_limit = null + } + description = <<-EOT + Single object for setting entire context at once. + See description of individual variables for details. + Leave string and numeric variables as `null` to use default value. + Individual variable settings (non-null) override settings in context object, + except for attributes, tags, and additional_tag_map, which are merged. + EOT +} + +variable "enabled" { + type = bool + default = null + description = "Set to false to prevent the module from creating any resources" +} + +variable "namespace" { + type = string + default = null + description = "Namespace, which could be your organization name or abbreviation, e.g. 'eg' or 'cp'" +} + +variable "environment" { + type = string + default = null + description = "Environment, e.g. 'uw2', 'us-west-2', OR 'prod', 'staging', 'dev', 'UAT'" +} + +variable "stage" { + type = string + default = null + description = "Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release'" +} + +variable "name" { + type = string + default = null + description = "Solution name, e.g. 'app' or 'jenkins'" +} + +variable "delimiter" { + type = string + default = null + description = <<-EOT + Delimiter to be used between `namespace`, `environment`, `stage`, `name` and `attributes`. + Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. + EOT +} + +variable "attributes" { + type = list(string) + default = [] + description = "Additional attributes (e.g. `1`)" +} + +variable "tags" { + type = map(string) + default = {} + description = "Additional tags (e.g. `map('BusinessUnit','XYZ')`" +} + +variable "additional_tag_map" { + type = map(string) + default = {} + description = "Additional tags for appending to tags_as_list_of_maps. Not added to `tags`." +} + +variable "label_order" { + type = list(string) + default = null + description = <<-EOT + The naming order of the id output and Name tag. + Defaults to ["namespace", "environment", "stage", "name", "attributes"]. + You can omit any of the 5 elements, but at least one must be present. + EOT +} + +variable "regex_replace_chars" { + type = string + default = null + description = <<-EOT + Regex to replace chars with empty string in `namespace`, `environment`, `stage` and `name`. + If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. + EOT +} + +variable "id_length_limit" { + type = number + default = null + description = <<-EOT + Limit `id` to this many characters. + Set to `0` for unlimited length. + Set to `null` for default, which is `0`. + Does not affect `id_full`. + EOT +} + +#### End of copy of cloudposse/terraform-null-label/variables.tf diff --git a/modules/service/main.tf b/modules/service/main.tf new file mode 100644 index 0000000..b00de84 --- /dev/null +++ b/modules/service/main.tf @@ -0,0 +1,7 @@ +resource "opsgenie_service" "this" { + count = module.this.enabled ? 1 : 0 + + name = var.service.name + team_id = var.service.team_id + description = var.service.description +} diff --git a/modules/service/outputs.tf b/modules/service/outputs.tf new file mode 100644 index 0000000..ed13c7f --- /dev/null +++ b/modules/service/outputs.tf @@ -0,0 +1,9 @@ +output "service_id" { + description = "The ID of the Opsgenie Service" + value = join("", opsgenie_service.this.*.id) +} + +output "service_name" { + description = "The name of the Opsgenie Service" + value = join("", opsgenie_service.this.*.name) +} diff --git a/modules/service/variables.tf b/modules/service/variables.tf new file mode 100644 index 0000000..edb62b4 --- /dev/null +++ b/modules/service/variables.tf @@ -0,0 +1,4 @@ +variable "service" { + default = {} + description = "Opsgenie Service configuration" +} diff --git a/modules/service/versions.tf b/modules/service/versions.tf new file mode 100644 index 0000000..600eea7 --- /dev/null +++ b/modules/service/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = ">= 0.12.26" + + required_providers { + opsgenie = { + source = "opsgenie/opsgenie" + version = ">= 0.4" + } + } +} diff --git a/modules/service_incident_rule/README.md b/modules/service_incident_rule/README.md new file mode 100644 index 0000000..261a527 --- /dev/null +++ b/modules/service_incident_rule/README.md @@ -0,0 +1,57 @@ +## Service Incident Rule + +Terraform module to configure [Opsgenie Service Incident Rule](https://registry.terraform.io/providers/opsgenie/opsgenie/latest/docs/resources/service_incident_rule) + + +## Usage + +[Create Opsgenie Team Routing Rule example](../../examples/service_incident_rule) + +```hcl +module "service_incident_rule" { + source = "git::https://github.com/cloudposse/terraform-opsgenie-incident-management.git//modules/service_incident_rule?ref=master" + + service_incident_rule = { + service_id = "..." + + incident_rule = { + condition_match_type = "match-all" + + conditions = [ + { + field = "tags" + operation = "contains" + expected_value = "expected1" + } + ] + + incident_properties = { + message = "This is a test message" + priority = "P3" + + stakeholder_properties = { + message = "Message for stakeholders" + enable = true + } + } + } + } +} +``` + +## Inputs + +**Note:** `service_incident_rule` is a map for two reasons: +- to be able to put whole configuration in yaml file +- variables defined with type set are not robust enough (can't set default values) + +| Name | Default | Description | Required | +|:-------------------------------|:---------------------------------:|:-------------------------------------------------|:--------:| +| `service_incident_rule` | `{}` | Opsgenie Service Incident Rule configuration | Yes | + + +## Outputs + +| Name | Description | +|:------------------------------|:-----------------------------------------------| +| `service_incident_rule_id` | The ID of the Opsgenie Service Incident Rule | diff --git a/modules/service_incident_rule/context.tf b/modules/service_incident_rule/context.tf new file mode 100644 index 0000000..bae0cf1 --- /dev/null +++ b/modules/service_incident_rule/context.tf @@ -0,0 +1,167 @@ +# +# ONLY EDIT THIS FILE IN github.com/cloudposse/terraform-null-label +# All other instances of this file should be a copy of that one +# +# +# Copy this file from https://github.com/cloudposse/terraform-null-label/blob/master/exports/context.tf +# and then place it in your Terraform module to automatically get +# Cloud Posse's standard configuration inputs suitable for passing +# to Cloud Posse modules. +# +# Modules should access the whole context as `module.this.context` +# to get the input variables with nulls for defaults, +# for example `context = module.this.context`, +# and access individual variables as `module.this.`, +# with final values filled in. +# +# For example, when using defaults, `module.this.context.delimiter` +# will be null, and `module.this.delimiter` will be `-` (hyphen). +# + +module "this" { + source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=tags/0.19.2" + + enabled = var.enabled + namespace = var.namespace + environment = var.environment + stage = var.stage + name = var.name + delimiter = var.delimiter + attributes = var.attributes + tags = var.tags + additional_tag_map = var.additional_tag_map + label_order = var.label_order + regex_replace_chars = var.regex_replace_chars + id_length_limit = var.id_length_limit + + context = var.context +} + +# Copy contents of cloudposse/terraform-null-label/variables.tf here + +variable "context" { + type = object({ + enabled = bool + namespace = string + environment = string + stage = string + name = string + delimiter = string + attributes = list(string) + tags = map(string) + additional_tag_map = map(string) + regex_replace_chars = string + label_order = list(string) + id_length_limit = number + }) + default = { + enabled = true + namespace = null + environment = null + stage = null + name = null + delimiter = null + attributes = [] + tags = {} + additional_tag_map = {} + regex_replace_chars = null + label_order = [] + id_length_limit = null + } + description = <<-EOT + Single object for setting entire context at once. + See description of individual variables for details. + Leave string and numeric variables as `null` to use default value. + Individual variable settings (non-null) override settings in context object, + except for attributes, tags, and additional_tag_map, which are merged. + EOT +} + +variable "enabled" { + type = bool + default = null + description = "Set to false to prevent the module from creating any resources" +} + +variable "namespace" { + type = string + default = null + description = "Namespace, which could be your organization name or abbreviation, e.g. 'eg' or 'cp'" +} + +variable "environment" { + type = string + default = null + description = "Environment, e.g. 'uw2', 'us-west-2', OR 'prod', 'staging', 'dev', 'UAT'" +} + +variable "stage" { + type = string + default = null + description = "Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release'" +} + +variable "name" { + type = string + default = null + description = "Solution name, e.g. 'app' or 'jenkins'" +} + +variable "delimiter" { + type = string + default = null + description = <<-EOT + Delimiter to be used between `namespace`, `environment`, `stage`, `name` and `attributes`. + Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. + EOT +} + +variable "attributes" { + type = list(string) + default = [] + description = "Additional attributes (e.g. `1`)" +} + +variable "tags" { + type = map(string) + default = {} + description = "Additional tags (e.g. `map('BusinessUnit','XYZ')`" +} + +variable "additional_tag_map" { + type = map(string) + default = {} + description = "Additional tags for appending to tags_as_list_of_maps. Not added to `tags`." +} + +variable "label_order" { + type = list(string) + default = null + description = <<-EOT + The naming order of the id output and Name tag. + Defaults to ["namespace", "environment", "stage", "name", "attributes"]. + You can omit any of the 5 elements, but at least one must be present. + EOT +} + +variable "regex_replace_chars" { + type = string + default = null + description = <<-EOT + Regex to replace chars with empty string in `namespace`, `environment`, `stage` and `name`. + If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. + EOT +} + +variable "id_length_limit" { + type = number + default = null + description = <<-EOT + Limit `id` to this many characters. + Set to `0` for unlimited length. + Set to `null` for default, which is `0`. + Does not affect `id_full`. + EOT +} + +#### End of copy of cloudposse/terraform-null-label/variables.tf diff --git a/modules/service_incident_rule/main.tf b/modules/service_incident_rule/main.tf new file mode 100644 index 0000000..69401a9 --- /dev/null +++ b/modules/service_incident_rule/main.tf @@ -0,0 +1,33 @@ +resource "opsgenie_service_incident_rule" "this" { + count = module.this.enabled ? 1 : 0 + + service_id = var.service_incident_rule.service_id + + incident_rule { + condition_match_type = try(var.service_incident_rule.incident_rule.condition_match_type, "match-all") + + dynamic conditions { + for_each = try(var.service_incident_rule.incident_rule.conditions, []) + + content { + expected_value = try(conditions.value.expected_value, null) + field = conditions.value.field + not = try(conditions.value.not, null) + operation = conditions.value.operation + } + } + + incident_properties { + message = var.service_incident_rule.incident_rule.incident_properties.message + priority = var.service_incident_rule.incident_rule.incident_properties.priority + tags = try(var.service_incident_rule.incident_rule.incident_properties.tags, null) + details = try(var.service_incident_rule.incident_rule.incident_properties.details, null) + + stakeholder_properties { + message = var.service_incident_rule.incident_rule.incident_properties.stakeholder_properties.message + description = try(var.service_incident_rule.incident_rule.incident_properties.stakeholder_properties.description, null) + enable = try(var.service_incident_rule.incident_rule.incident_properties.stakeholder_properties.enable, null) + } + } + } +} diff --git a/modules/service_incident_rule/outputs.tf b/modules/service_incident_rule/outputs.tf new file mode 100644 index 0000000..daf470b --- /dev/null +++ b/modules/service_incident_rule/outputs.tf @@ -0,0 +1,4 @@ +output "service_incident_rule_id" { + description = "The ID of the Opsgenie Service Incident Rule" + value = join("", opsgenie_service_incident_rule.this.*.id) +} diff --git a/modules/service_incident_rule/variables.tf b/modules/service_incident_rule/variables.tf new file mode 100644 index 0000000..5d56a98 --- /dev/null +++ b/modules/service_incident_rule/variables.tf @@ -0,0 +1,4 @@ +variable "service_incident_rule" { + default = {} + description = "Opsgenie Service Incident Rule configuration" +} diff --git a/modules/service_incident_rule/versions.tf b/modules/service_incident_rule/versions.tf new file mode 100644 index 0000000..600eea7 --- /dev/null +++ b/modules/service_incident_rule/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = ">= 0.12.26" + + required_providers { + opsgenie = { + source = "opsgenie/opsgenie" + version = ">= 0.4" + } + } +} diff --git a/modules/team/README.md b/modules/team/README.md index 2881726..98cb5d8 100644 --- a/modules/team/README.md +++ b/modules/team/README.md @@ -15,7 +15,6 @@ module "team" { name = module.label.id description = "team-description" } - } module "ui_managed_team" { @@ -27,7 +26,6 @@ module "ui_managed_team" { delete_default_resources = true ignore_members = true } - } ``` diff --git a/modules/team/main.tf b/modules/team/main.tf index 2f3506e..79acdd8 100644 --- a/modules/team/main.tf +++ b/modules/team/main.tf @@ -3,4 +3,13 @@ resource "opsgenie_team" "this" { description = try(var.team.description, var.team.name) ignore_members = try(var.team.ignore_members, false) delete_default_resources = try(var.team.delete_default_resources, false) + + dynamic member { + for_each = try(var.team.members, []) + + content { + id = member.value.id + role = member.value.role + } + } } diff --git a/modules/team/variables.tf b/modules/team/variables.tf index 9d9ed4e..0a13925 100644 --- a/modules/team/variables.tf +++ b/modules/team/variables.tf @@ -1,4 +1,4 @@ variable "team" { default = {} - description = "This variable is used to configure Opsgenie Team" + description = "Opsgenie Team configuration" } diff --git a/modules/team_routing_rule/variables.tf b/modules/team_routing_rule/variables.tf index 8b96bb3..58c3c94 100644 --- a/modules/team_routing_rule/variables.tf +++ b/modules/team_routing_rule/variables.tf @@ -1,4 +1,4 @@ variable "team_routing_rule" { default = {} - description = "This variable is used to configure Opsgenie Team Routing Rule" + description = "Opsgenie Team Routing Rule configuration" } diff --git a/modules/user/README.md b/modules/user/README.md new file mode 100644 index 0000000..2ded578 --- /dev/null +++ b/modules/user/README.md @@ -0,0 +1,40 @@ +## User + +Terraform module to configure [Opsgenie User](https://registry.terraform.io/providers/opsgenie/opsgenie/latest/docs/resources/user) + + +## Usage + +[Create Opsgenie User example](../../examples/user) + +```hcl +module "user" { + source = "git::https://github.com/cloudposse/terraform-opsgenie-incident-management.git//modules/user?ref=master" + + user = { + username = "opsgenie-test@cloudposse.com" + full_name = "Opsgenie Test User" + role = "User" + locale = "en_US" + timezone = "America/New_York" + } +} +``` + +## Inputs + +**Note:** `user` is a map for two reasons: +- to be able to put whole configuration in yaml file +- variables defined with type set are not robust enough (can't set default values) + +| Name | Default | Description | Required | +|:-------------------------------|:---------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------|:--------:| +| `user` | `{}` | Opsgenie User configuration | Yes | + + +## Outputs + +| Name | Description | +|:----------------------------|:-----------------------------------------| +| `user_id` | The ID of the Opsgenie User | +| `user_name` | The name of the Opsgenie User | diff --git a/modules/user/context.tf b/modules/user/context.tf new file mode 100644 index 0000000..bae0cf1 --- /dev/null +++ b/modules/user/context.tf @@ -0,0 +1,167 @@ +# +# ONLY EDIT THIS FILE IN github.com/cloudposse/terraform-null-label +# All other instances of this file should be a copy of that one +# +# +# Copy this file from https://github.com/cloudposse/terraform-null-label/blob/master/exports/context.tf +# and then place it in your Terraform module to automatically get +# Cloud Posse's standard configuration inputs suitable for passing +# to Cloud Posse modules. +# +# Modules should access the whole context as `module.this.context` +# to get the input variables with nulls for defaults, +# for example `context = module.this.context`, +# and access individual variables as `module.this.`, +# with final values filled in. +# +# For example, when using defaults, `module.this.context.delimiter` +# will be null, and `module.this.delimiter` will be `-` (hyphen). +# + +module "this" { + source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=tags/0.19.2" + + enabled = var.enabled + namespace = var.namespace + environment = var.environment + stage = var.stage + name = var.name + delimiter = var.delimiter + attributes = var.attributes + tags = var.tags + additional_tag_map = var.additional_tag_map + label_order = var.label_order + regex_replace_chars = var.regex_replace_chars + id_length_limit = var.id_length_limit + + context = var.context +} + +# Copy contents of cloudposse/terraform-null-label/variables.tf here + +variable "context" { + type = object({ + enabled = bool + namespace = string + environment = string + stage = string + name = string + delimiter = string + attributes = list(string) + tags = map(string) + additional_tag_map = map(string) + regex_replace_chars = string + label_order = list(string) + id_length_limit = number + }) + default = { + enabled = true + namespace = null + environment = null + stage = null + name = null + delimiter = null + attributes = [] + tags = {} + additional_tag_map = {} + regex_replace_chars = null + label_order = [] + id_length_limit = null + } + description = <<-EOT + Single object for setting entire context at once. + See description of individual variables for details. + Leave string and numeric variables as `null` to use default value. + Individual variable settings (non-null) override settings in context object, + except for attributes, tags, and additional_tag_map, which are merged. + EOT +} + +variable "enabled" { + type = bool + default = null + description = "Set to false to prevent the module from creating any resources" +} + +variable "namespace" { + type = string + default = null + description = "Namespace, which could be your organization name or abbreviation, e.g. 'eg' or 'cp'" +} + +variable "environment" { + type = string + default = null + description = "Environment, e.g. 'uw2', 'us-west-2', OR 'prod', 'staging', 'dev', 'UAT'" +} + +variable "stage" { + type = string + default = null + description = "Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release'" +} + +variable "name" { + type = string + default = null + description = "Solution name, e.g. 'app' or 'jenkins'" +} + +variable "delimiter" { + type = string + default = null + description = <<-EOT + Delimiter to be used between `namespace`, `environment`, `stage`, `name` and `attributes`. + Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. + EOT +} + +variable "attributes" { + type = list(string) + default = [] + description = "Additional attributes (e.g. `1`)" +} + +variable "tags" { + type = map(string) + default = {} + description = "Additional tags (e.g. `map('BusinessUnit','XYZ')`" +} + +variable "additional_tag_map" { + type = map(string) + default = {} + description = "Additional tags for appending to tags_as_list_of_maps. Not added to `tags`." +} + +variable "label_order" { + type = list(string) + default = null + description = <<-EOT + The naming order of the id output and Name tag. + Defaults to ["namespace", "environment", "stage", "name", "attributes"]. + You can omit any of the 5 elements, but at least one must be present. + EOT +} + +variable "regex_replace_chars" { + type = string + default = null + description = <<-EOT + Regex to replace chars with empty string in `namespace`, `environment`, `stage` and `name`. + If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. + EOT +} + +variable "id_length_limit" { + type = number + default = null + description = <<-EOT + Limit `id` to this many characters. + Set to `0` for unlimited length. + Set to `null` for default, which is `0`. + Does not affect `id_full`. + EOT +} + +#### End of copy of cloudposse/terraform-null-label/variables.tf diff --git a/modules/user/main.tf b/modules/user/main.tf new file mode 100644 index 0000000..88599a9 --- /dev/null +++ b/modules/user/main.tf @@ -0,0 +1,9 @@ +resource "opsgenie_user" "this" { + count = module.this.enabled ? 1 : 0 + + username = var.user.username + full_name = var.user.full_name + role = var.user.role + locale = try(var.user.locale, "en_US") + timezone = try(var.user.timezone, "America/New_York") +} diff --git a/modules/user/outputs.tf b/modules/user/outputs.tf new file mode 100644 index 0000000..190a14d --- /dev/null +++ b/modules/user/outputs.tf @@ -0,0 +1,9 @@ +output "user_id" { + description = "The ID of the Opsgenie User" + value = join("", opsgenie_user.this.*.id) +} + +output "user_name" { + description = "The username of the Opsgenie User" + value = join("", opsgenie_user.this.*.username) +} diff --git a/modules/user/variables.tf b/modules/user/variables.tf new file mode 100644 index 0000000..d759e2e --- /dev/null +++ b/modules/user/variables.tf @@ -0,0 +1,4 @@ +variable "user" { + default = {} + description = "Opsgenie User configuration" +} diff --git a/modules/user/versions.tf b/modules/user/versions.tf new file mode 100644 index 0000000..600eea7 --- /dev/null +++ b/modules/user/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = ">= 0.12.26" + + required_providers { + opsgenie = { + source = "opsgenie/opsgenie" + version = ">= 0.4" + } + } +} diff --git a/outputs.tf b/outputs.tf index d71b6b3..876eeb2 100644 --- a/outputs.tf +++ b/outputs.tf @@ -83,3 +83,28 @@ output "team_routing_rule_name" { description = "The name of the Opsgenie Team Routing Rule" value = module.team_routing_rule.team_routing_rule_name } + +output "user_id" { + description = "The ID of the Opsgenie User" + value = module.user.user_id +} + +output "user_name" { + description = "The name of the Opsgenie User" + value = module.user.user_name +} + +output "service_id" { + description = "The ID of the Opsgenie Service" + value = module.service.service_id +} + +output "service_name" { + description = "The name of the Opsgenie Service" + value = module.service.service_name +} + +output "service_incident_rule_id" { + description = "The ID of the Opsgenie Service Incident Rule" + value = module.service_incident_rule.service_incident_rule_id +} diff --git a/test/Makefile b/test/Makefile index 6c28a55..17b2fe7 100644 --- a/test/Makefile +++ b/test/Makefile @@ -41,4 +41,3 @@ module: deps examples/complete: export TESTS ?= installed lint get-modules get-plugins validate examples/complete: deps $(call RUN_TESTS, ../$@) - diff --git a/test/src/examples_complete_test.go b/test/src/examples_complete_test.go index 74d3ec3..5156bdc 100644 --- a/test/src/examples_complete_test.go +++ b/test/src/examples_complete_test.go @@ -2,6 +2,7 @@ package test import ( "github.com/gruntwork-io/terratest/modules/terraform" + "github.com/stretchr/testify/assert" "testing" ) @@ -20,4 +21,34 @@ func TestExamplesComplete(t *testing.T) { // This will run `terraform init` and `terraform apply` and fail the test if there are any errors terraform.InitAndApply(t, terraformOptions) + + // Run `terraform output` to get the value of an output variable + outputApiIntegrationName := terraform.Output(t, terraformOptions, "api_integration_name") + + // Verify we're getting back the outputs we expect + assert.Regexp(t, "^eg-test-incident-management-workflow$", outputApiIntegrationName) + + // Run `terraform output` to get the value of an output variable + outputEscalationName := terraform.Output(t, terraformOptions, "escalation_name") + + // Verify we're getting back the outputs we expect + assert.Regexp(t, "^eg-test-incident-management-workflow-escalation$", outputEscalationName) + + // Run `terraform output` to get the value of an output variable + outputNotificationPolicyName := terraform.Output(t, terraformOptions, "notification_policy_name") + + // Verify we're getting back the outputs we expect + assert.Regexp(t, "^eg-test-incident-management-workflow$", outputNotificationPolicyName) + + // Run `terraform output` to get the value of an output variable + outputTeamRoutingRuleName := terraform.Output(t, terraformOptions, "team_routing_rule_name") + + // Verify we're getting back the outputs we expect + assert.Regexp(t, "^eg-test-incident-management-workflow$", outputTeamRoutingRuleName) + + // Run `terraform output` to get the value of an output variable + outputTeamName := terraform.Output(t, terraformOptions, "team_name") + + // Verify we're getting back the outputs we expect + assert.Regexp(t, "^eg-test-incident-management-workflow$", outputTeamName) } diff --git a/test/src/examples_user_test.go b/test/src/examples_user_test.go new file mode 100644 index 0000000..becf7a2 --- /dev/null +++ b/test/src/examples_user_test.go @@ -0,0 +1,30 @@ +package test + +import ( + "github.com/gruntwork-io/terratest/modules/terraform" + "github.com/stretchr/testify/assert" + "testing" +) + +// Test the Terraform module in examples/team using Terratest. +func TestExamplesUser(t *testing.T) { + terraformOptions := &terraform.Options{ + // The path to where our Terraform code is located + TerraformDir: "../../examples/user", + Upgrade: true, + // Variables to pass to our Terraform code using -var-file options + VarFiles: []string{"fixtures.tfvars"}, + } + + // At the end of the test, run `terraform destroy` to clean up any resources that were created + defer terraform.Destroy(t, terraformOptions) + + // This will run `terraform init` and `terraform apply` and fail the test if there are any errors + terraform.InitAndApply(t, terraformOptions) + + // Run `terraform output` to get the value of an output variable + userId := terraform.Output(t, terraformOptions, "user_id") + + // Verify we're getting back the outputs we expect + assert.NotEmpty(t, userId) +} diff --git a/variables.tf b/variables.tf index 7e1cfa1..d818dde 100644 --- a/variables.tf +++ b/variables.tf @@ -6,30 +6,45 @@ variable "opsgenie_provider_api_key" { variable "alert_policy" { default = {} - description = "This variable is used to configure Opsgenie Alert Policy" + description = "Opsgenie Alert Policy configuration" } variable "api_integration" { default = {} - description = "This variable is used to configure Opsgenie API Integration" + description = "Opsgenie API Integration configuration" } variable "escalation" { default = {} - description = "This variable is used to configure Opsgenie Escalation" + description = "Opsgenie Escalation configuration" } variable "notification_policy" { default = {} - description = "This variable is used to configure Opsgenie Notification Policy" + description = "Opsgenie Notification Policy configuration" } variable "team" { default = {} - description = "This variable is used to configure Opsgenie Team" + description = "Opsgenie Team configuration" } variable "team_routing_rule" { default = {} - description = "This variable is used to configure Opsgenie Team Routing Rule" + description = "Opsgenie Team Routing Rule configuration" +} + +variable "user" { + default = {} + description = "Opsgenie User configuration" +} + +variable "service" { + default = {} + description = "Opsgenie Service configuration" +} + +variable "service_incident_rule" { + default = {} + description = "Opsgenie Service Incident Rule configuration" }