infra: travel-agent stack (namespace + ExternalSecret + 2 CronJobs)
This commit is contained in:
parent
e1ab23193d
commit
46f63bb70e
3 changed files with 180 additions and 0 deletions
157
stacks/travel-agent/main.tf
Normal file
157
stacks/travel-agent/main.tf
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
locals {
|
||||
namespace = "travel-agent"
|
||||
image = "forgejo.viktorbarzin.me/viktor/travel-agent:${var.image_tag}"
|
||||
labels = {
|
||||
app = "travel-agent"
|
||||
}
|
||||
|
||||
# Two workflows, both scheduled in Europe/London (K8s 1.27+ honours timeZone).
|
||||
workflows = {
|
||||
"flight-train-check" = {
|
||||
schedule = "0 8 * * *"
|
||||
arg = "flight_train_check"
|
||||
}
|
||||
"trip-weather-brief" = {
|
||||
schedule = "0 21 * * *"
|
||||
arg = "trip_weather_brief"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_namespace" "travel_agent" {
|
||||
metadata {
|
||||
name = local.namespace
|
||||
labels = {
|
||||
tier = local.tiers.aux
|
||||
"istio-injection" = "disabled"
|
||||
# Opt into Keel auto-update (inject-keel-annotations ClusterPolicy).
|
||||
"keel.sh/enrolled" = "true"
|
||||
}
|
||||
}
|
||||
lifecycle {
|
||||
# KYVERNO_LIFECYCLE_V1: goldilocks-vpa-auto-mode ClusterPolicy stamps this label on every namespace
|
||||
ignore_changes = [metadata[0].labels["goldilocks.fairwinds.com/vpa-update-mode"]]
|
||||
}
|
||||
}
|
||||
|
||||
# App secrets — seed these in Vault before applying:
|
||||
# secret/travel-agent
|
||||
# nextcloud_caldav_url — CalDAV collection URL (Nextcloud)
|
||||
# nextcloud_caldav_user — CalDAV username
|
||||
# nextcloud_caldav_pass — CalDAV app password
|
||||
# slack_webhook_url — incoming-webhook URL for the target channel
|
||||
resource "kubernetes_manifest" "external_secret" {
|
||||
manifest = {
|
||||
apiVersion = "external-secrets.io/v1beta1"
|
||||
kind = "ExternalSecret"
|
||||
metadata = {
|
||||
name = "travel-agent-secrets"
|
||||
namespace = local.namespace
|
||||
}
|
||||
spec = {
|
||||
refreshInterval = "1h"
|
||||
secretStoreRef = {
|
||||
name = "vault-kv"
|
||||
kind = "ClusterSecretStore"
|
||||
}
|
||||
target = {
|
||||
name = "travel-agent-secrets"
|
||||
creationPolicy = "Owner"
|
||||
template = {
|
||||
metadata = {
|
||||
annotations = {
|
||||
"reloader.stakater.com/match" = "true"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
data = [
|
||||
{
|
||||
secretKey = "NEXTCLOUD_CALDAV_URL"
|
||||
remoteRef = { key = "travel-agent", property = "nextcloud_caldav_url" }
|
||||
},
|
||||
{
|
||||
secretKey = "NEXTCLOUD_CALDAV_USER"
|
||||
remoteRef = { key = "travel-agent", property = "nextcloud_caldav_user" }
|
||||
},
|
||||
{
|
||||
secretKey = "NEXTCLOUD_CALDAV_PASS"
|
||||
remoteRef = { key = "travel-agent", property = "nextcloud_caldav_pass" }
|
||||
},
|
||||
{
|
||||
secretKey = "SLACK_WEBHOOK_URL"
|
||||
remoteRef = { key = "travel-agent", property = "slack_webhook_url" }
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
depends_on = [kubernetes_namespace.travel_agent]
|
||||
}
|
||||
|
||||
resource "kubernetes_cron_job_v1" "workflow" {
|
||||
for_each = local.workflows
|
||||
|
||||
metadata {
|
||||
name = "travel-agent-${each.key}"
|
||||
namespace = kubernetes_namespace.travel_agent.metadata[0].name
|
||||
labels = merge(local.labels, {
|
||||
component = each.key
|
||||
})
|
||||
}
|
||||
|
||||
spec {
|
||||
schedule = each.value.schedule
|
||||
timezone = "Europe/London"
|
||||
concurrency_policy = "Forbid"
|
||||
starting_deadline_seconds = 300
|
||||
successful_jobs_history_limit = 3
|
||||
failed_jobs_history_limit = 5
|
||||
|
||||
job_template {
|
||||
metadata {
|
||||
labels = merge(local.labels, {
|
||||
component = each.key
|
||||
})
|
||||
}
|
||||
spec {
|
||||
backoff_limit = 1
|
||||
ttl_seconds_after_finished = 86400
|
||||
template {
|
||||
metadata {
|
||||
labels = merge(local.labels, {
|
||||
component = each.key
|
||||
})
|
||||
}
|
||||
spec {
|
||||
restart_policy = "OnFailure"
|
||||
image_pull_secrets {
|
||||
name = "registry-credentials"
|
||||
}
|
||||
container {
|
||||
name = "runner"
|
||||
image = local.image
|
||||
args = [each.value.arg]
|
||||
env_from {
|
||||
secret_ref { name = "travel-agent-secrets" }
|
||||
}
|
||||
resources {
|
||||
requests = { cpu = "100m", memory = "128Mi" }
|
||||
limits = { memory = "256Mi" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lifecycle {
|
||||
ignore_changes = [
|
||||
spec[0].job_template[0].spec[0].template[0].spec[0].dns_config, # KYVERNO_LIFECYCLE_V1
|
||||
# Keel manages tag updates on enrolled namespaces.
|
||||
spec[0].job_template[0].spec[0].template[0].spec[0].container[0].image, # KEEL_IGNORE_IMAGE
|
||||
]
|
||||
}
|
||||
|
||||
depends_on = [kubernetes_manifest.external_secret]
|
||||
}
|
||||
18
stacks/travel-agent/terragrunt.hcl
Normal file
18
stacks/travel-agent/terragrunt.hcl
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
include "root" {
|
||||
path = find_in_parent_folders()
|
||||
}
|
||||
|
||||
dependency "platform" {
|
||||
config_path = "../platform"
|
||||
skip_outputs = true
|
||||
}
|
||||
|
||||
dependency "vault" {
|
||||
config_path = "../vault"
|
||||
skip_outputs = true
|
||||
}
|
||||
|
||||
dependency "external-secrets" {
|
||||
config_path = "../external-secrets"
|
||||
skip_outputs = true
|
||||
}
|
||||
5
stacks/travel-agent/variables.tf
Normal file
5
stacks/travel-agent/variables.tf
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
variable "image_tag" {
|
||||
type = string
|
||||
default = "latest"
|
||||
description = "travel-agent image tag. Use 8-char git SHA in CI; :latest only for local trials."
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue