From b8fde5644c92607c178eb4cb4825df6f7aa24007 Mon Sep 17 00:00:00 2001 From: kjuulh Date: Mon, 27 May 2024 22:13:18 +0200 Subject: [PATCH] feat: add ingress Signed-off-by: kjuulh --- crates/cuddle-clusters/src/catalog/ingress.rs | 130 ++++++++++++++---- crates/cuddle-clusters/tests/tests.rs | 19 ++- .../with_crdb/expected/dev/cuddle-crdb.yaml | 9 ++ .../with_crdb/expected/dev/cuddle_crdb.yaml | 9 -- .../tests/with_ingress/cuddle.yaml | 9 ++ .../expected/dev/ingress.yaml.jinja2 | 59 ++++++++ .../tests/with_ingress/expected/dev/some.yaml | 30 ++++ .../expected/prod/ingress.yaml.jinja2 | 59 ++++++++ .../with_ingress/expected/prod/some.yaml | 30 ++++ .../templates/clusters/some.yaml.jinja2 | 32 +++++ 10 files changed, 350 insertions(+), 36 deletions(-) create mode 100644 crates/cuddle-clusters/tests/with_crdb/expected/dev/cuddle-crdb.yaml delete mode 100644 crates/cuddle-clusters/tests/with_crdb/expected/dev/cuddle_crdb.yaml create mode 100644 crates/cuddle-clusters/tests/with_ingress/cuddle.yaml create mode 100644 crates/cuddle-clusters/tests/with_ingress/expected/dev/ingress.yaml.jinja2 create mode 100644 crates/cuddle-clusters/tests/with_ingress/expected/dev/some.yaml create mode 100644 crates/cuddle-clusters/tests/with_ingress/expected/prod/ingress.yaml.jinja2 create mode 100644 crates/cuddle-clusters/tests/with_ingress/expected/prod/some.yaml create mode 100644 crates/cuddle-clusters/tests/with_ingress/templates/clusters/some.yaml.jinja2 diff --git a/crates/cuddle-clusters/src/catalog/ingress.rs b/crates/cuddle-clusters/src/catalog/ingress.rs index 09aada5..d38e2da 100644 --- a/crates/cuddle-clusters/src/catalog/ingress.rs +++ b/crates/cuddle-clusters/src/catalog/ingress.rs @@ -4,6 +4,11 @@ use crate::Component; use super::cuddle_vars::{load_cuddle_file, CuddleVariable, CuddleVariables}; +pub enum IngressType { + External, + Internal, +} + pub struct Ingress { variables: CuddleVariables, } @@ -18,47 +23,120 @@ impl Ingress { impl Component for Ingress { fn name(&self) -> String { - format!("cuddle/ingress") + "cuddle/ingress".to_string() } fn render( &self, - environment: &str, - value: &serde_yaml::Value, + _environment: &str, + _value: &serde_yaml::Value, ) -> Option> { - if let Some(true) = self + if let Some(ingress_types) = self .variables .0 - .get("database") + .get("ingress") .and_then(|v| match v { - CuddleVariable::Object(o) => Some(o), + CuddleVariable::Array(a) => Some(a), _ => None, }) - .and_then(|o| o.0.get("crdb")) - .and_then(|o| match o { - CuddleVariable::String(o) => { - if o == "true" { - Some(true) - } else { - None + .map(|o| { + let mut types = Vec::new(); + + for value in o { + match value { + CuddleVariable::Object(o) => { + if o.0.contains_key("external") { + types.push(IngressType::External) + } else if o.0.contains_key("internal") { + types.push(IngressType::Internal) + } else { + continue; + } + } + _ => continue, } } - _ => None, + + types }) { - return Some(Ok(( - format!("{}.yaml", self.name().replace("/", "-")), - r#" -apiVersion: v1 -kind: ConfigMap + let mut templates = Vec::new(); + for ingress_type in ingress_types { + match ingress_type { + IngressType::External => templates.push( + r#" +{%- set service_name = vars.cuddle_vars.service | replace("-", "_") %} +{%- set host_name = vars.cuddle_vars.service | replace("_", "-") | replace(".", "-") %} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress metadata: - name: {{ vars.cuddle_crdb.file_name(vars.cuddle_vars.service) }} - namespace: {{ vars.cluster_vars.namespace }} -data: - DATABASE_URL: postgresql://root@{{environment}}-cluster:26257/{{ vars.cuddle_vars.service | replace("-", "_") }} - "# - .into(), - ))); + annotations: + cert-manager.io/issuer: kjuulh-app + traefik.ingress.kubernetes.io/router.entrypoints: web + traefik.ingress.kubernetes.io/router.tls: "true" + labels: + app: {{ service_name }} + cluster: {{ vars.cluster_vars.namespace }} + name: {{ service_name }}-external-http + namespace: {{ vars.cluster_vars.namespace }} +spec: + rules: + - host: {{ host_name }}.{{ environment }}.kjuulh.app + http: + paths: + - backend: + service: + name: {{ service_name }} + port: + name: external-http + path: / + pathType: Prefix + tls: + - hosts: + - {{ host_name }}.{{ environment }}.kjuulh.app + secretName: tls-{{ service_name }}-kjuulh-app-external-ingress-dns +"#, + ), + IngressType::Internal => templates.push( + r#" +{%- set service_name = vars.cuddle_vars.service | replace("-", "_") %} +{%- set host_name = vars.cuddle_vars.service | replace("_", "-") | replace(".", "-") %} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + cert-manager.io/issuer: kjuulh-app + traefik.ingress.kubernetes.io/router.entrypoints: web + traefik.ingress.kubernetes.io/router.tls: "true" + labels: + app: {{ service_name }} + cluster: {{ vars.cluster_vars.namespace }} + name: {{ service_name }}-internal-http + namespace: {{ vars.cluster_vars.namespace }} +spec: + rules: + - host: {{ host_name }}.{{ environment }}.internal.kjuulh.app + http: + paths: + - backend: + service: + name: {{ service_name }} + port: + name: internal-http + path: / + pathType: Prefix + tls: + - hosts: + - {{ host_name }}.{{ environment }}.internal.kjuulh.app + secretName: tls-{{ service_name }}-kjuulh-app-internal-ingress-dns +"#, + ), + } + } + + return Some(Ok(("ingress.yaml.jinja2".into(), templates.join("\n")))); } None diff --git a/crates/cuddle-clusters/tests/tests.rs b/crates/cuddle-clusters/tests/tests.rs index a99f243..8fa96bf 100644 --- a/crates/cuddle-clusters/tests/tests.rs +++ b/crates/cuddle-clusters/tests/tests.rs @@ -6,7 +6,7 @@ mod cuddle_vars; use cuddle_clusters::{ catalog::{ cluster_vars::ClusterVars, crdb_database::CockroachDB, cuddle_vars::CuddleVars, - vault_secret::VaultSecret, + ingress::Ingress, vault_secret::VaultSecret, }, IntoComponent, }; @@ -117,3 +117,20 @@ async fn with_crdb() -> anyhow::Result<()> { Ok(()) } + +#[tokio::test] +async fn with_ingress() -> anyhow::Result<()> { + let current_dir = std::env::current_dir()?.join("tests/with_ingress"); + + run_test_with_components( + "with_ingress", + vec![ + CuddleVars::new(¤t_dir).await?.into_component(), + ClusterVars::default().into_component(), + Ingress::new(¤t_dir).await?.into_component(), + ], + ) + .await?; + + Ok(()) +} diff --git a/crates/cuddle-clusters/tests/with_crdb/expected/dev/cuddle-crdb.yaml b/crates/cuddle-clusters/tests/with_crdb/expected/dev/cuddle-crdb.yaml new file mode 100644 index 0000000..8a380ff --- /dev/null +++ b/crates/cuddle-clusters/tests/with_crdb/expected/dev/cuddle-crdb.yaml @@ -0,0 +1,9 @@ + +apiVersion: v1 +kind: ConfigMap +metadata: + name: service-cuddle-crdb + namespace: dev +data: + DATABASE_URL: postgresql://root@dev-cluster:26257/service + \ No newline at end of file diff --git a/crates/cuddle-clusters/tests/with_crdb/expected/dev/cuddle_crdb.yaml b/crates/cuddle-clusters/tests/with_crdb/expected/dev/cuddle_crdb.yaml deleted file mode 100644 index 8d595b5..0000000 --- a/crates/cuddle-clusters/tests/with_crdb/expected/dev/cuddle_crdb.yaml +++ /dev/null @@ -1,9 +0,0 @@ - -apiVersion: v1 -kind: ConfigMap -metadata: - name: service-crdb-config -data: - environment: - DATABASE_URL: postgresql://root@dev-cluster:26257/service - \ No newline at end of file diff --git a/crates/cuddle-clusters/tests/with_ingress/cuddle.yaml b/crates/cuddle-clusters/tests/with_ingress/cuddle.yaml new file mode 100644 index 0000000..295ffef --- /dev/null +++ b/crates/cuddle-clusters/tests/with_ingress/cuddle.yaml @@ -0,0 +1,9 @@ +vars: + service: service + ingress: + - external: "true" + - internal: "true" + +cuddle/clusters: + dev: + prod: diff --git a/crates/cuddle-clusters/tests/with_ingress/expected/dev/ingress.yaml.jinja2 b/crates/cuddle-clusters/tests/with_ingress/expected/dev/ingress.yaml.jinja2 new file mode 100644 index 0000000..fdecd1f --- /dev/null +++ b/crates/cuddle-clusters/tests/with_ingress/expected/dev/ingress.yaml.jinja2 @@ -0,0 +1,59 @@ + +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + cert-manager.io/issuer: kjuulh-app + traefik.ingress.kubernetes.io/router.entrypoints: web + traefik.ingress.kubernetes.io/router.tls: "true" + labels: + app: service + cluster: dev + name: service-external-http + namespace: dev +spec: + rules: + - host: service.dev.kjuulh.app + http: + paths: + - backend: + service: + name: service + port: + name: external-http + path: / + pathType: Prefix + tls: + - hosts: + - service.dev.kjuulh.app + secretName: tls-service-kjuulh-app-external-ingress-dns +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + cert-manager.io/issuer: kjuulh-app + traefik.ingress.kubernetes.io/router.entrypoints: web + traefik.ingress.kubernetes.io/router.tls: "true" + labels: + app: service + cluster: dev + name: service-internal-http + namespace: dev +spec: + rules: + - host: service.dev.internal.kjuulh.app + http: + paths: + - backend: + service: + name: service + port: + name: internal-http + path: / + pathType: Prefix + tls: + - hosts: + - service.dev.internal.kjuulh.app + secretName: tls-service-kjuulh-app-internal-ingress-dns \ No newline at end of file diff --git a/crates/cuddle-clusters/tests/with_ingress/expected/dev/some.yaml b/crates/cuddle-clusters/tests/with_ingress/expected/dev/some.yaml new file mode 100644 index 0000000..43c5173 --- /dev/null +++ b/crates/cuddle-clusters/tests/with_ingress/expected/dev/some.yaml @@ -0,0 +1,30 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: service + name: service +spec: + replicas: 3 + selector: + matchLabels: + app: service + template: + metadata: + labels: + app: service + spec: + containers: + - args: + - serve + command: + - service + image: kasperhermansen/service:main-1715336504 + name: service + ports: + - containerPort: 3000 + name: external-http + - containerPort: 3001 + name: internal-http + - containerPort: 3002 + name: internal-grpc \ No newline at end of file diff --git a/crates/cuddle-clusters/tests/with_ingress/expected/prod/ingress.yaml.jinja2 b/crates/cuddle-clusters/tests/with_ingress/expected/prod/ingress.yaml.jinja2 new file mode 100644 index 0000000..573cbce --- /dev/null +++ b/crates/cuddle-clusters/tests/with_ingress/expected/prod/ingress.yaml.jinja2 @@ -0,0 +1,59 @@ + +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + cert-manager.io/issuer: kjuulh-app + traefik.ingress.kubernetes.io/router.entrypoints: web + traefik.ingress.kubernetes.io/router.tls: "true" + labels: + app: service + cluster: prod + name: service-external-http + namespace: prod +spec: + rules: + - host: service.prod.kjuulh.app + http: + paths: + - backend: + service: + name: service + port: + name: external-http + path: / + pathType: Prefix + tls: + - hosts: + - service.prod.kjuulh.app + secretName: tls-service-kjuulh-app-external-ingress-dns +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + cert-manager.io/issuer: kjuulh-app + traefik.ingress.kubernetes.io/router.entrypoints: web + traefik.ingress.kubernetes.io/router.tls: "true" + labels: + app: service + cluster: prod + name: service-internal-http + namespace: prod +spec: + rules: + - host: service.prod.internal.kjuulh.app + http: + paths: + - backend: + service: + name: service + port: + name: internal-http + path: / + pathType: Prefix + tls: + - hosts: + - service.prod.internal.kjuulh.app + secretName: tls-service-kjuulh-app-internal-ingress-dns \ No newline at end of file diff --git a/crates/cuddle-clusters/tests/with_ingress/expected/prod/some.yaml b/crates/cuddle-clusters/tests/with_ingress/expected/prod/some.yaml new file mode 100644 index 0000000..43c5173 --- /dev/null +++ b/crates/cuddle-clusters/tests/with_ingress/expected/prod/some.yaml @@ -0,0 +1,30 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: service + name: service +spec: + replicas: 3 + selector: + matchLabels: + app: service + template: + metadata: + labels: + app: service + spec: + containers: + - args: + - serve + command: + - service + image: kasperhermansen/service:main-1715336504 + name: service + ports: + - containerPort: 3000 + name: external-http + - containerPort: 3001 + name: internal-http + - containerPort: 3002 + name: internal-grpc \ No newline at end of file diff --git a/crates/cuddle-clusters/tests/with_ingress/templates/clusters/some.yaml.jinja2 b/crates/cuddle-clusters/tests/with_ingress/templates/clusters/some.yaml.jinja2 new file mode 100644 index 0000000..6601c7e --- /dev/null +++ b/crates/cuddle-clusters/tests/with_ingress/templates/clusters/some.yaml.jinja2 @@ -0,0 +1,32 @@ +{%- set service_name = vars.cuddle_vars.service -%} + +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: {{ service_name }} + name: {{ service_name }} +spec: + replicas: 3 + selector: + matchLabels: + app: {{ service_name }} + template: + metadata: + labels: + app: {{ service_name }} + spec: + containers: + - args: + - serve + command: + - {{ service_name }} + image: kasperhermansen/{{ service_name }}:main-1715336504 + name: {{ service_name }} + ports: + - containerPort: 3000 + name: external-http + - containerPort: 3001 + name: internal-http + - containerPort: 3002 + name: internal-grpc