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};
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<anyhow::Result<(String, String)>> {
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)
.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 {
None
continue;
}
}
_ => None,
_ => continue,
}
}
types
})
{
return Some(Ok((
format!("{}.yaml", self.name().replace("/", "-")),
let mut templates = Vec::new();
for ingress_type in ingress_types {
match ingress_type {
IngressType::External => templates.push(
r#"
apiVersion: v1
kind: ConfigMap
{%- 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) }}
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 }}
data:
DATABASE_URL: postgresql://root@{{environment}}-cluster:26257/{{ vars.cuddle_vars.service | replace("-", "_") }}
"#
.into(),
)));
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

View File

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