Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ArgoCD Slack Notifications #905

Merged
merged 15 commits into from
Dec 6, 2023
3 changes: 3 additions & 0 deletions modules/argocd-repo/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,11 @@ $ terraform import -var "import_profile_name=eg-mgmt-gbl-corp-admin" -var-file="
| <a name="input_name"></a> [name](#input\_name) | ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'.<br>This is the only ID element not also included as a `tag`.<br>The "name" tag is set to the full `id` string. There is no tag with the value of the `name` input. | `string` | `null` | no |
| <a name="input_namespace"></a> [namespace](#input\_namespace) | ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique | `string` | `null` | no |
| <a name="input_permissions"></a> [permissions](#input\_permissions) | A list of Repository Permission objects used to configure the team permissions of the repository<br><br>`team_slug` should be the name of the team without the `@{org}` e.g. `@cloudposse/team` => `team`<br>`permission` is just one of the available values listed below | <pre>list(object({<br> team_slug = string,<br> permission = string<br> }))</pre> | `[]` | no |
| <a name="input_push_restrictions_enabled"></a> [push\_restrictions\_enabled](#input\_push\_restrictions\_enabled) | Enforce who can push to the main branch | `bool` | `true` | no |
| <a name="input_regex_replace_chars"></a> [regex\_replace\_chars](#input\_regex\_replace\_chars) | Terraform regular expression (regex) string.<br>Characters matching the regex will be removed from the ID elements.<br>If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. | `string` | `null` | no |
| <a name="input_region"></a> [region](#input\_region) | AWS Region | `string` | n/a | yes |
| <a name="input_required_pull_request_reviews"></a> [required\_pull\_request\_reviews](#input\_required\_pull\_request\_reviews) | Enforce restrictions for pull request reviews | `bool` | `true` | no |
| <a name="input_slack_notifications_channel"></a> [slack\_notifications\_channel](#input\_slack\_notifications\_channel) | If given, the Slack channel to for deployment notifications. | `string` | `""` | no |
| <a name="input_ssm_github_api_key"></a> [ssm\_github\_api\_key](#input\_ssm\_github\_api\_key) | SSM path to the GitHub API key | `string` | `"/argocd/github/api_key"` | no |
| <a name="input_ssm_github_deploy_key_format"></a> [ssm\_github\_deploy\_key\_format](#input\_ssm\_github\_deploy\_key\_format) | Format string of the SSM parameter path to which the deploy keys will be written to (%s will be replaced with the environment name) | `string` | `"/argocd/deploy_keys/%s"` | no |
| <a name="input_stage"></a> [stage](#input\_stage) | ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no |
Expand Down
15 changes: 8 additions & 7 deletions modules/argocd-repo/applicationset.tf
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ resource "github_repository_file" "application_set" {
branch = local.github_repository.default_branch
file = "${each.value.tenant != null ? format("%s/", each.value.tenant) : ""}${each.value.environment}-${each.value.stage}${length(each.value.attributes) > 0 ? format("-%s", join("-", each.value.attributes)) : ""}/${local.manifest_kubernetes_namespace}/applicationset.yaml"
content = templatefile("${path.module}/templates/applicationset.yaml.tpl", {
environment = each.key
auto-sync = each.value.auto-sync
ignore-differences = each.value.ignore-differences
name = module.this.namespace
namespace = local.manifest_kubernetes_namespace
ssh_url = local.github_repository.ssh_clone_url
notifications = var.github_default_notifications_enabled
environment = each.key
auto-sync = each.value.auto-sync
ignore-differences = each.value.ignore-differences
name = module.this.namespace
namespace = local.manifest_kubernetes_namespace
ssh_url = local.github_repository.ssh_clone_url
notifications = var.github_default_notifications_enabled
slack_notifications_channel = var.slack_notifications_channel
})
commit_message = "Initialize environment: `${each.key}`."
commit_author = var.github_user
Expand Down
23 changes: 13 additions & 10 deletions modules/argocd-repo/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ locals {
env.tenant,
env.environment,
env.stage,
"${join("-", env.attributes)}"
join("-", env.attributes)
)) => env
} : {}

Expand Down Expand Up @@ -72,19 +72,22 @@ resource "github_branch_protection" "default" {

repository_id = local.github_repository.name

pattern = join("", github_branch_default.default.*.branch)
pattern = join("", github_branch_default.default[*].branch)
milldr marked this conversation as resolved.
Show resolved Hide resolved
milldr marked this conversation as resolved.
Show resolved Hide resolved
enforce_admins = false # needs to be false in order to allow automation user to push
allows_deletions = true

required_pull_request_reviews {
dismiss_stale_reviews = true
restrict_dismissals = true
require_code_owner_reviews = true
dynamic "required_pull_request_reviews" {
for_each = var.required_pull_request_reviews ? [0] : []
content {
dismiss_stale_reviews = true
restrict_dismissals = true
require_code_owner_reviews = true
}
}

push_restrictions = [
join("", data.github_user.automation_user.*.node_id),
]
push_restrictions = var.push_restrictions_enabled ? [
join("", data.github_user.automation_user[*].node_id),
] : []
}

data "github_team" "default" {
Expand Down Expand Up @@ -112,7 +115,7 @@ resource "github_repository_deploy_key" "default" {
for_each = local.environments

title = "Deploy key for ArgoCD environment: ${each.key} (${local.github_repository.default_branch} branch)"
repository = join("", github_repository.default.*.name)
repository = join("", github_repository.default[*].name)
key = tls_private_key.default[each.key].public_key_openssh
read_only = true
}
8 changes: 8 additions & 0 deletions modules/argocd-repo/templates/applicationset.yaml.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@ spec:
notifications.argoproj.io/subscribe.on-deploy-succeded.argocd-repo-github-commit-status: ""
notifications.argoproj.io/subscribe.on-deploy-failed.app-repo-github-commit-status: ""
notifications.argoproj.io/subscribe.on-deploy-failed.argocd-repo-github-commit-status: ""
%{ endif ~}
%{if length(slack_notifications_channel) > 0 ~}
notifications.argoproj.io/subscribe.on-created.slack: ${slack_notifications_channel}
notifications.argoproj.io/subscribe.on-deleted.slack: ${slack_notifications_channel}
notifications.argoproj.io/subscribe.on-success.slack: ${slack_notifications_channel}
notifications.argoproj.io/subscribe.on-health-degraded.slack: ${slack_notifications_channel}
notifications.argoproj.io/subscribe.on-failure.slack: ${slack_notifications_channel}
notifications.argoproj.io/subscribe.on-started.slack: ${slack_notifications_channel}
%{ endif ~}
name: '{{name}}'
spec:
Expand Down
18 changes: 18 additions & 0 deletions modules/argocd-repo/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,21 @@ variable "create_repo" {
description = "Whether or not to create the repository or use an existing one"
default = true
}

variable "required_pull_request_reviews" {
type = bool
description = "Enforce restrictions for pull request reviews"
default = true
}

variable "push_restrictions_enabled" {
type = bool
description = "Enforce who can push to the main branch"
default = true
}

variable "slack_notifications_channel" {
type = string
default = ""
description = "If given, the Slack channel to for deployment notifications."
}
4 changes: 4 additions & 0 deletions modules/eks/argocd/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## Components PR [#905](https://github.com/cloudposse/terraform-aws-components/pull/905)

The `notifictations.tf` file has been renamed to `notifications.tf`. Delete `notifictations.tf` after vendoring these changes.

## Components PR [#851](https://github.com/cloudposse/terraform-aws-components/pull/851)

This is a bug fix and feature enhancement update.
Expand Down
26 changes: 23 additions & 3 deletions modules/eks/argocd/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,24 @@ components:
github_webhook_enabled: true
```

### Slack Notifications

ArgoCD supports Slack notifications on application deployments.

1. In order to enable Slack notifications, first create a Slack Application following the [ArgoCD documentation](https://argocd-notifications.readthedocs.io/en/stable/services/slack/).
1. Create an OAuth token for the new Slack App
1. Save the OAuth token to AWS SSM Parameter Store in the same account and region as Github tokens. For example, `core-use2-auto`
1. Add the app to the chosen Slack channel. _If not added, notifications will not work_
1. For this component, enable Slack integrations for each Application with `var.slack_notifications_enabled` and `var.slack_notifications`:

```yaml
slack_notifications_enabled: true
slack_notifications:
channel: argocd-updates
```

6. In the `argocd-repo` component, set `var.slack_notifications_channel` to the name of the Slack notification channel to add the relevant ApplicationSet annotations

## Troubleshooting

## Login to ArgoCD admin UI
Expand Down Expand Up @@ -404,8 +422,8 @@ Reference: https://stackoverflow.com/questions/75046330/argo-cd-error-server-sec

| Name | Source | Version |
|------|--------|---------|
| <a name="module_argocd"></a> [argocd](#module\_argocd) | cloudposse/helm-release/aws | 0.10.0 |
| <a name="module_argocd_apps"></a> [argocd\_apps](#module\_argocd\_apps) | cloudposse/helm-release/aws | 0.10.0 |
| <a name="module_argocd"></a> [argocd](#module\_argocd) | cloudposse/helm-release/aws | 0.10.1 |
| <a name="module_argocd_apps"></a> [argocd\_apps](#module\_argocd\_apps) | cloudposse/helm-release/aws | 0.10.1 |
| <a name="module_argocd_repo"></a> [argocd\_repo](#module\_argocd\_repo) | cloudposse/stack-config/yaml//modules/remote-state | 1.5.0 |
| <a name="module_dns_gbl_delegated"></a> [dns\_gbl\_delegated](#module\_dns\_gbl\_delegated) | cloudposse/stack-config/yaml//modules/remote-state | 1.5.0 |
| <a name="module_eks"></a> [eks](#module\_eks) | cloudposse/stack-config/yaml//modules/remote-state | 1.5.0 |
Expand All @@ -425,6 +443,7 @@ Reference: https://stackoverflow.com/questions/75046330/argo-cd-error-server-sec
| [aws_ssm_parameter.github_deploy_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameter) | data source |
| [aws_ssm_parameter.oidc_client_id](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameter) | data source |
| [aws_ssm_parameter.oidc_client_secret](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameter) | data source |
| [aws_ssm_parameter.slack_notifications](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameter) | data source |
| [aws_ssm_parameters_by_path.argocd_notifications](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameters_by_path) | data source |
| [kubernetes_resources.crd](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/data-sources/resources) | data source |

Expand All @@ -438,7 +457,6 @@ Reference: https://stackoverflow.com/questions/75046330/argo-cd-error-server-sec
| <a name="input_alb_logs_bucket"></a> [alb\_logs\_bucket](#input\_alb\_logs\_bucket) | The name of the bucket for ALB access logs. The bucket must have policy allowing the ELB logging principal | `string` | `""` | no |
| <a name="input_alb_logs_prefix"></a> [alb\_logs\_prefix](#input\_alb\_logs\_prefix) | `alb_logs_bucket` s3 bucket prefix | `string` | `""` | no |
| <a name="input_alb_name"></a> [alb\_name](#input\_alb\_name) | The name of the ALB (e.g. `argocd`) provisioned by `alb-controller`. Works together with `var.alb_group_name` | `string` | `null` | no |
| <a name="input_argo_enable_workflows_auth"></a> [argo\_enable\_workflows\_auth](#input\_argo\_enable\_workflows\_auth) | Allow argo-workflows to use Dex instance for SAML auth | `bool` | `false` | no |
| <a name="input_argocd_apps_chart"></a> [argocd\_apps\_chart](#input\_argocd\_apps\_chart) | Chart name to be installed. The chart name can be local path, a URL to a chart, or the name of the chart if `repository` is specified. It is also possible to use the `<repository>/<chart>` format here if you are running Terraform on a system that the repository has been added to with `helm repo add` but this is not recommended. | `string` | `"argocd-apps"` | no |
| <a name="input_argocd_apps_chart_description"></a> [argocd\_apps\_chart\_description](#input\_argocd\_apps\_chart\_description) | Set release description attribute (visible in the history). | `string` | `"A Helm chart for managing additional Argo CD Applications and Projects"` | no |
| <a name="input_argocd_apps_chart_repository"></a> [argocd\_apps\_chart\_repository](#input\_argocd\_apps\_chart\_repository) | Repository URL where to locate the requested chart. | `string` | `"https://argoproj.github.io/argo-helm"` | no |
Expand Down Expand Up @@ -506,6 +524,8 @@ Reference: https://stackoverflow.com/questions/75046330/argo-cd-error-server-sec
| <a name="input_saml_enabled"></a> [saml\_enabled](#input\_saml\_enabled) | Toggles SAML integration in the deployed chart | `bool` | `false` | no |
| <a name="input_saml_rbac_scopes"></a> [saml\_rbac\_scopes](#input\_saml\_rbac\_scopes) | SAML RBAC scopes to request | `string` | `"[email,groups]"` | no |
| <a name="input_saml_sso_providers"></a> [saml\_sso\_providers](#input\_saml\_sso\_providers) | SAML SSO providers components | <pre>map(object({<br> component = string<br> environment = optional(string, null)<br> }))</pre> | `{}` | no |
| <a name="input_slack_notifications"></a> [slack\_notifications](#input\_slack\_notifications) | ArgoCD Slack notification configuration. Requires Slack Bot created with token stored at the given SSM Parameter path.<br><br>See: https://argocd-notifications.readthedocs.io/en/stable/services/slack/ | <pre>object({<br> token_ssm_path = optional(string, "/argocd/notifications/notifiers/slack/token")<br> api_url = optional(string, null)<br> username = optional(string, "ArgoCD")<br> icon = optional(string, null)<br> })</pre> | `{}` | no |
| <a name="input_slack_notifications_enabled"></a> [slack\_notifications\_enabled](#input\_slack\_notifications\_enabled) | Whether or not to enable Slack notifications. See `var.slack_notifications.` | `bool` | `false` | no |
| <a name="input_ssm_github_api_key"></a> [ssm\_github\_api\_key](#input\_ssm\_github\_api\_key) | SSM path to the GitHub API key | `string` | `"/argocd/github/api_key"` | no |
| <a name="input_ssm_oidc_client_id"></a> [ssm\_oidc\_client\_id](#input\_ssm\_oidc\_client\_id) | The SSM Parameter Store path for the ID of the IdP client | `string` | `"/argocd/oidc/client_id"` | no |
| <a name="input_ssm_oidc_client_secret"></a> [ssm\_oidc\_client\_secret](#input\_ssm\_oidc\_client\_secret) | The SSM Parameter Store path for the secret of the IdP client | `string` | `"/argocd/oidc/client_secret"` | no |
Expand Down
2 changes: 1 addition & 1 deletion modules/eks/argocd/data.tf
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ data "aws_ssm_parameter" "github_deploy_key" {
module.this.tenant,
module.this.environment,
module.this.stage,
"${join("-", module.this.attributes)}"
join("-", module.this.attributes)
)
) : null

Expand Down
13 changes: 10 additions & 3 deletions modules/eks/argocd/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ locals {
value = nonsensitive(local.webhook_github_secret)
type = "string"
}
] : [],
local.slack_notifications_enabled ? [
{
name = "notifications.secret.items.slack-token"
value = data.aws_ssm_parameter.slack_notifications[0].value
type = "string"
}
] : []
))
regional_service_discovery_domain = "${module.this.environment}.${module.dns_gbl_delegated.outputs.default_domain_name}"
Expand Down Expand Up @@ -102,7 +109,7 @@ locals {

module "argocd" {
source = "cloudposse/helm-release/aws"
version = "0.10.0"
version = "0.10.1"

name = "argocd" # avoids hitting length restrictions on IAM Role names
chart = var.chart
Expand Down Expand Up @@ -188,7 +195,7 @@ data "kubernetes_resources" "crd" {

module "argocd_apps" {
source = "cloudposse/helm-release/aws"
version = "0.10.0"
version = "0.10.1"

name = "" # avoids hitting length restrictions on IAM Role names
chart = var.argocd_apps_chart
Expand All @@ -215,7 +222,7 @@ module "argocd_apps" {
stage = var.stage
attributes = var.attributes
}
),
)
])

depends_on = [
Expand Down