feat: add ingress
Some checks reported errors
continuous-integration/drone/push Build encountered an error

Signed-off-by: kjuulh <contact@kjuulh.io>
This commit is contained in:
Kasper Juul Hermansen 2024-05-27 22:13:18 +02:00
parent 8f806474d1
commit b8fde5644c
Signed by: kjuulh
GPG Key ID: 9AA7BC13CE474394
10 changed files with 350 additions and 36 deletions

View File

@ -4,6 +4,11 @@ use crate::Component;
use super::cuddle_vars::{load_cuddle_file, CuddleVariable, CuddleVariables}; use super::cuddle_vars::{load_cuddle_file, CuddleVariable, CuddleVariables};
pub enum IngressType {
External,
Internal,
}
pub struct Ingress { pub struct Ingress {
variables: CuddleVariables, variables: CuddleVariables,
} }
@ -18,47 +23,120 @@ impl Ingress {
impl Component for Ingress { impl Component for Ingress {
fn name(&self) -> String { fn name(&self) -> String {
format!("cuddle/ingress") "cuddle/ingress".to_string()
} }
fn render( fn render(
&self, &self,
environment: &str, _environment: &str,
value: &serde_yaml::Value, _value: &serde_yaml::Value,
) -> Option<anyhow::Result<(String, String)>> { ) -> Option<anyhow::Result<(String, String)>> {
if let Some(true) = self if let Some(ingress_types) = self
.variables .variables
.0 .0
.get("database") .get("ingress")
.and_then(|v| match v { .and_then(|v| match v {
CuddleVariable::Object(o) => Some(o), CuddleVariable::Array(a) => Some(a),
_ => None, _ => None,
}) })
.and_then(|o| o.0.get("crdb")) .map(|o| {
.and_then(|o| match o { let mut types = Vec::new();
CuddleVariable::String(o) => {
if o == "true" { for value in o {
Some(true) match value {
} else { CuddleVariable::Object(o) => {
None 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(( let mut templates = Vec::new();
format!("{}.yaml", self.name().replace("/", "-")), for ingress_type in ingress_types {
r#" match ingress_type {
apiVersion: v1 IngressType::External => templates.push(
kind: ConfigMap 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: metadata:
name: {{ vars.cuddle_crdb.file_name(vars.cuddle_vars.service) }} annotations:
namespace: {{ vars.cluster_vars.namespace }} cert-manager.io/issuer: kjuulh-app
data: traefik.ingress.kubernetes.io/router.entrypoints: web
DATABASE_URL: postgresql://root@{{environment}}-cluster:26257/{{ vars.cuddle_vars.service | replace("-", "_") }} traefik.ingress.kubernetes.io/router.tls: "true"
"# labels:
.into(), 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 None

View File

@ -6,7 +6,7 @@ mod cuddle_vars;
use cuddle_clusters::{ use cuddle_clusters::{
catalog::{ catalog::{
cluster_vars::ClusterVars, crdb_database::CockroachDB, cuddle_vars::CuddleVars, cluster_vars::ClusterVars, crdb_database::CockroachDB, cuddle_vars::CuddleVars,
vault_secret::VaultSecret, ingress::Ingress, vault_secret::VaultSecret,
}, },
IntoComponent, IntoComponent,
}; };
@ -117,3 +117,20 @@ async fn with_crdb() -> anyhow::Result<()> {
Ok(()) 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(&current_dir).await?.into_component(),
ClusterVars::default().into_component(),
Ingress::new(&current_dir).await?.into_component(),
],
)
.await?;
Ok(())
}

View File

@ -0,0 +1,9 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: service-cuddle-crdb
namespace: dev
data:
DATABASE_URL: postgresql://root@dev-cluster:26257/service

View File

@ -1,9 +0,0 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: service-crdb-config
data:
environment:
DATABASE_URL: postgresql://root@dev-cluster:26257/service

View File

@ -0,0 +1,9 @@
vars:
service: service
ingress:
- external: "true"
- internal: "true"
cuddle/clusters:
dev:
prod:

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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