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