Skip to content

Commit

Permalink
feat: add automatic log drains for addons (#10)
Browse files Browse the repository at this point in the history
  • Loading branch information
josephpage authored Sep 26, 2023
1 parent eda67ef commit cff3966
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 7 deletions.
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ Used in production by :
| [scalingo_container_type.containers](https://registry.terraform.io/providers/scalingo/scalingo/latest/docs/resources/container_type) | resource |
| [scalingo_domain.canonical_domain](https://registry.terraform.io/providers/scalingo/scalingo/latest/docs/resources/domain) | resource |
| [scalingo_domain.domain_aliases](https://registry.terraform.io/providers/scalingo/scalingo/latest/docs/resources/domain) | resource |
| [scalingo_log_drain.log_drain](https://registry.terraform.io/providers/scalingo/scalingo/latest/docs/resources/log_drain) | resource |
| [scalingo_log_drain.addons](https://registry.terraform.io/providers/scalingo/scalingo/latest/docs/resources/log_drain) | resource |
| [scalingo_log_drain.app](https://registry.terraform.io/providers/scalingo/scalingo/latest/docs/resources/log_drain) | resource |
| [scalingo_scm_repo_link.scm_repo_link](https://registry.terraform.io/providers/scalingo/scalingo/latest/docs/resources/scm_repo_link) | resource |

## Inputs
Expand All @@ -74,8 +75,8 @@ Used in production by :
| <a name="input_environment"></a> [environment](#input\_environment) | Map of environment variables to set on the application. Note that value of environment variables can be null or empty. | `map(string)` | `null` | no |
| <a name="input_github_integration"></a> [github\_integration](#input\_github\_integration) | Configuration of the GitHub integration of the application. Only one of github\_integration or gitlab\_integration can be set. | <pre>object({<br> repo_url = string<br> integration_uuid = optional(string)<br> branch = optional(string, "main")<br> auto_deploy_enabled = optional(bool, true)<br> })</pre> | `null` | no |
| <a name="input_gitlab_integration"></a> [gitlab\_integration](#input\_gitlab\_integration) | Configuration of the GitLab integration of the application. Only one of github\_integration or gitlab\_integration can be set. | <pre>object({<br> repo_url = string<br> integration_uuid = optional(string)<br> branch = optional(string, "main")<br> auto_deploy_enabled = optional(bool, true)<br> })</pre> | `null` | no |
| <a name="input_log_drains"></a> [log\_drains](#input\_log\_drains) | n/a | <pre>list(object({<br> type = string<br> url = optional(string, "")<br> drain_region = optional(string, "")<br> addon = optional(string, "")<br> host = optional(string, "")<br> port = optional(string, "")<br> token = optional(string, "")<br> }))</pre> | `[]` | no |
| <a name="input_name"></a> [name](#input\_name) | n/a | `string` | n/a | yes |
| <a name="input_log_drains"></a> [log\_drains](#input\_log\_drains) | List of log\_drain configuration to redirect logs from the application and addons to a log management service. Each configuration is automatically associated to the application and to every eligible addons. | <pre>list(object({<br> type = string<br> url = optional(string, "")<br> drain_region = optional(string, "")<br> host = optional(string, "")<br> port = optional(string, "")<br> token = optional(string, "")<br> }))</pre> | `[]` | no |
| <a name="input_name"></a> [name](#input\_name) | Name of the application. Must be unique on Scalingo. | `string` | n/a | yes |
| <a name="input_review_apps"></a> [review\_apps](#input\_review\_apps) | Configuration of the review apps of the application. | <pre>object({<br> enabled = optional(bool, false)<br><br> # By default: delete review apps 0 hours after closing the PR<br> delete_on_close_enabled = optional(bool, true)<br> hours_before_delete_on_close = optional(string, "0")<br><br> # By default: delete review apps after 5 days of inactivity (= no new deployment)<br> delete_stale_enabled = optional(bool, true)<br> hours_before_delete_stale = optional(string, "168")<br><br> # By default: do not create review apps for PRs from forks<br> automatic_creation_from_forks_allowed = optional(bool, false)<br> })</pre> | `{}` | no |
| <a name="input_router_logs"></a> [router\_logs](#input\_router\_logs) | When true, the router logs are included in the application logs. (default: `false`) | `bool` | `false` | no |
| <a name="input_stack"></a> [stack](#input\_stack) | The stack to use for the app (default: "scalingo-22"). | `string` | `"scalingo-22"` | no |
Expand Down
28 changes: 26 additions & 2 deletions log_drains.tf
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# Log drains
# How it works :https://doc.scalingo.com/platform/app/log-drain
# API Docs : https://developers.scalingo.com/log_drains
resource "scalingo_log_drain" "log_drain" {

# Log drains for applications
resource "scalingo_log_drain" "app" {
for_each = { for log_drain in var.log_drains : log_drain.type => log_drain }

app = scalingo_app.app.id
Expand All @@ -11,7 +13,29 @@ resource "scalingo_log_drain" "log_drain" {
# Log drain parameters are different depending on the type
url = sensitive(each.value.url)
drain_region = each.value.drain_region
addon = each.value.addon
host = each.value.host
port = each.value.port
token = sensitive(each.value.token)
}

# Log drains for addons
resource "scalingo_log_drain" "addons" {
# Create a map of log_drain for each addon and log_drain combination :
# e.g. { "redis-elk" = { addon_id = "xxxx", type = "elk", url = "https://elk.example.com/xxxx" } }
for_each = { for log_drain in setproduct(var.log_drains, values(scalingo_addon.addons)) :
"${log_drain[1].provider_id}-${log_drain[0].type}"
=> merge(log_drain[0], { addon_id = log_drain[1].id })
}

# Associate the log drain to app AND addon
app = scalingo_app.app.id
addon = each.value.addon_id

type = each.value.type

# Log drain parameters are different depending on the type
url = sensitive(each.value.url)
drain_region = each.value.drain_region
host = each.value.host
port = each.value.port
token = sensitive(each.value.token)
Expand Down
35 changes: 35 additions & 0 deletions upgrade_to_v0.3.0.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
### Migration from v0.2.0 of the module
### REMOVE when releasing v1.0.0

moved {
from = scalingo_log_drain.log_drain["elk"]
to = scalingo_log_drain.app["elk"]
}
moved {
from = scalingo_log_drain.log_drain["appsignal"]
to = scalingo_log_drain.app["appsignal"]
}
moved {
from = scalingo_log_drain.log_drain["logtail"]
to = scalingo_log_drain.app["logtail"]
}
moved {
from = scalingo_log_drain.log_drain["datadog"]
to = scalingo_log_drain.app["datadog"]
}
moved {
from = scalingo_log_drain.log_drain["ovh-graylog"]
to = scalingo_log_drain.app["ovh-graylog"]
}
moved {
from = scalingo_log_drain.log_drain["papertrail"]
to = scalingo_log_drain.app["papertrail"]
}
moved {
from = scalingo_log_drain.log_drain["logtail"]
to = scalingo_log_drain.app["logtail"]
}
moved {
from = scalingo_log_drain.log_drain["syslog"]
to = scalingo_log_drain.app["syslog"]
}
13 changes: 11 additions & 2 deletions variables.tf
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
variable "name" {
type = string
description = "Name of the application. Must be unique on Scalingo."
type = string
}

variable "stack" {
Expand Down Expand Up @@ -183,11 +184,11 @@ variable "domain_aliases" {
}

variable "log_drains" {
description = "List of log_drain configuration to redirect logs from the application and addons to a log management service. Each configuration is automatically associated to the application and to every eligible addons."
type = list(object({
type = string
url = optional(string, "")
drain_region = optional(string, "")
addon = optional(string, "")
host = optional(string, "")
port = optional(string, "")
token = optional(string, "")
Expand All @@ -202,4 +203,12 @@ variable "log_drains" {
]) == 0
error_message = "The list of log drains must contain only valid log drains type (elk/appsignal/logtail/datadog/ovh-graylog/papertrail/logtail/syslog)."
}

validation {
condition = length([
for drain in var.log_drains :
drain if drain.type == "elk" && can(length(regex("^https?://([a-zA-Z0-9_\\-\\.]+)\\.([a-zA-Z]{2,5})$", drain.url)) == 0)
]) == 0
error_message = "Log drains of type \"elk\" must have a valid url."
}
}

0 comments on commit cff3966

Please sign in to comment.