Compare commits
No commits in common. "main" and "v0.1.1" have entirely different histories.
3521
Cargo.lock
generated
3521
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -11,7 +11,5 @@ tracing-subscriber = { version = "0.3.18" }
|
|||||||
clap = { version = "4", features = ["derive", "env"] }
|
clap = { version = "4", features = ["derive", "env"] }
|
||||||
dotenv = { version = "0.15" }
|
dotenv = { version = "0.15" }
|
||||||
|
|
||||||
flux-releaser = { git = "https://git.front.kjuulh.io/kjuulh/flux-releaser", branch = "main" }
|
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
|
@ -17,11 +17,9 @@ uuid = { version = "1.7.0", features = ["v4"] }
|
|||||||
serde_yaml = "0.9.34"
|
serde_yaml = "0.9.34"
|
||||||
tokio-stream = { version = "0.1.15", features = ["full"] }
|
tokio-stream = { version = "0.1.15", features = ["full"] }
|
||||||
walkdir = "2.5.0"
|
walkdir = "2.5.0"
|
||||||
minijinja = { version = "2.0.1", features = ["custom_syntax"] }
|
minijinja = "2.0.1"
|
||||||
futures = "0.3.30"
|
futures = "0.3.30"
|
||||||
|
|
||||||
flux-releaser.workspace = true
|
|
||||||
|
|
||||||
[[test]]
|
[[test]]
|
||||||
name = "integration"
|
name = "integration"
|
||||||
path = "tests/tests.rs"
|
path = "tests/tests.rs"
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
pub mod cluster_vars;
|
pub mod cluster_vars;
|
||||||
pub mod crdb_database;
|
|
||||||
pub mod cuddle_vars;
|
pub mod cuddle_vars;
|
||||||
pub mod ingress;
|
|
||||||
pub mod vault_secret;
|
pub mod vault_secret;
|
||||||
|
@ -1,131 +0,0 @@
|
|||||||
use std::path::Path;
|
|
||||||
|
|
||||||
use minijinja::{value::Object, Value};
|
|
||||||
|
|
||||||
use crate::{catalog::cuddle_vars::CuddleVariable, Component};
|
|
||||||
|
|
||||||
use super::cuddle_vars::{load_cuddle_file, CuddleVariables};
|
|
||||||
|
|
||||||
pub struct CockroachDB {
|
|
||||||
variables: CuddleVariables,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CockroachDB {
|
|
||||||
pub async fn new(path: &Path) -> anyhow::Result<Self> {
|
|
||||||
let variables = load_cuddle_file(path).await?;
|
|
||||||
|
|
||||||
Ok(Self { variables })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Component for CockroachDB {
|
|
||||||
fn name(&self) -> String {
|
|
||||||
"cuddle/crdb".into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render_value(
|
|
||||||
&self,
|
|
||||||
_environment: &str,
|
|
||||||
_value: &serde_yaml::Value,
|
|
||||||
) -> Option<anyhow::Result<minijinja::Value>> {
|
|
||||||
if let Some(true) = self
|
|
||||||
.variables
|
|
||||||
.0
|
|
||||||
.get("database")
|
|
||||||
.and_then(|v| match v {
|
|
||||||
CuddleVariable::Object(o) => Some(o),
|
|
||||||
_ => None,
|
|
||||||
})
|
|
||||||
.and_then(|o| o.0.get("crdb"))
|
|
||||||
.and_then(|o| match o {
|
|
||||||
CuddleVariable::String(o) => {
|
|
||||||
if o == "true" {
|
|
||||||
Some(true)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
})
|
|
||||||
{
|
|
||||||
return Some(Ok(minijinja::Value::from_object(CockroachDBValues {
|
|
||||||
name: self.name(),
|
|
||||||
enabled: true,
|
|
||||||
})));
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(Ok(minijinja::Value::from_object(CockroachDBValues {
|
|
||||||
name: self.name(),
|
|
||||||
enabled: false,
|
|
||||||
})))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render(
|
|
||||||
&self,
|
|
||||||
_environment: &str,
|
|
||||||
_value: &serde_yaml::Value,
|
|
||||||
) -> Option<anyhow::Result<(String, String)>> {
|
|
||||||
if let Some(true) = self
|
|
||||||
.variables
|
|
||||||
.0
|
|
||||||
.get("database")
|
|
||||||
.and_then(|v| match v {
|
|
||||||
CuddleVariable::Object(o) => Some(o),
|
|
||||||
_ => None,
|
|
||||||
})
|
|
||||||
.and_then(|o| o.0.get("crdb"))
|
|
||||||
.and_then(|o| match o {
|
|
||||||
CuddleVariable::String(o) => {
|
|
||||||
if o == "true" {
|
|
||||||
Some(true)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
})
|
|
||||||
{
|
|
||||||
return Some(Ok((
|
|
||||||
format!("{}.yaml", self.name().replace("/", "-")),
|
|
||||||
r#"
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ConfigMap
|
|
||||||
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(),
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct CockroachDBValues {
|
|
||||||
name: String,
|
|
||||||
enabled: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Object for CockroachDBValues {
|
|
||||||
fn get_value(self: &std::sync::Arc<Self>, key: &minijinja::Value) -> Option<minijinja::Value> {
|
|
||||||
let name = self.name.clone();
|
|
||||||
match key.as_str()? {
|
|
||||||
"has_values" => {
|
|
||||||
if self.enabled {
|
|
||||||
Some(minijinja::Value::from_serialize(true))
|
|
||||||
} else {
|
|
||||||
Some(minijinja::Value::from_serialize(false))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"file_name" => Some(Value::from_function(move |file_name: String| {
|
|
||||||
format!("{}-{}", file_name, name.replace("/", "-"))
|
|
||||||
})),
|
|
||||||
"env" => Some(Value::from_serialize("DATABASE_URL")),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -84,7 +84,7 @@ pub struct CuddleVars {
|
|||||||
pub variables: CuddleVariables,
|
pub variables: CuddleVariables,
|
||||||
}
|
}
|
||||||
|
|
||||||
const PARENT_PLAN_PREFIX: &str = ".cuddle/base";
|
const PARENT_PLAN_PREFIX: &str = ".cuddle/plan";
|
||||||
const CUDDLE_FILE: &str = "cuddle.yaml";
|
const CUDDLE_FILE: &str = "cuddle.yaml";
|
||||||
|
|
||||||
impl CuddleVars {
|
impl CuddleVars {
|
||||||
@ -95,7 +95,7 @@ impl CuddleVars {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_cuddle_file(path: &Path) -> BoxFuture<'static, anyhow::Result<CuddleVariables>> {
|
fn load_cuddle_file(path: &Path) -> BoxFuture<'static, anyhow::Result<CuddleVariables>> {
|
||||||
let path = path.to_path_buf();
|
let path = path.to_path_buf();
|
||||||
|
|
||||||
async move {
|
async move {
|
||||||
|
@ -1,172 +0,0 @@
|
|||||||
use std::path::Path;
|
|
||||||
|
|
||||||
use minijinja::{context, syntax::SyntaxConfig};
|
|
||||||
|
|
||||||
use crate::Component;
|
|
||||||
|
|
||||||
use super::cuddle_vars::{load_cuddle_file, CuddleVariable, CuddleVariables};
|
|
||||||
|
|
||||||
pub enum IngressType {
|
|
||||||
External,
|
|
||||||
Internal,
|
|
||||||
ExternalGrpc,
|
|
||||||
InternalGrpc,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Ingress {
|
|
||||||
variables: CuddleVariables,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Ingress {
|
|
||||||
pub async fn new(path: &Path) -> anyhow::Result<Self> {
|
|
||||||
let variables = load_cuddle_file(path).await?;
|
|
||||||
|
|
||||||
Ok(Self { variables })
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render_ingress_types(
|
|
||||||
&self,
|
|
||||||
ingress_types: Vec<IngressType>,
|
|
||||||
) -> anyhow::Result<(String, String)> {
|
|
||||||
let mut templates = Vec::new();
|
|
||||||
|
|
||||||
let internal_template = r#"
|
|
||||||
{%- set service_name = vars.cuddle_vars.service %}
|
|
||||||
{%- set host_name = vars.cuddle_vars.service | replace("_", "-") | replace(".", "-") %}
|
|
||||||
<%- macro host() -%>
|
|
||||||
<% if connection_type is defined %><<connection_type>>.<% endif %>{{ host_name }}.{{ environment }}.<< base_host >>
|
|
||||||
<%- endmacro %>
|
|
||||||
|
|
||||||
<%- macro k8s_service() -%>
|
|
||||||
<%- if connection_type == "grpc" -%>
|
|
||||||
{{ service_name }}-grpc
|
|
||||||
<%- else -%>
|
|
||||||
{{ service_name }}
|
|
||||||
<%- endif -%>
|
|
||||||
<%- endmacro %>
|
|
||||||
|
|
||||||
---
|
|
||||||
apiVersion: networking.k8s.io/v1
|
|
||||||
kind: Ingress
|
|
||||||
metadata:
|
|
||||||
annotations:
|
|
||||||
cert-manager.io/issuer: << issuer >>
|
|
||||||
traefik.ingress.kubernetes.io/router.entrypoints: web
|
|
||||||
traefik.ingress.kubernetes.io/router.tls: "true"
|
|
||||||
labels:
|
|
||||||
app: {{ service_name }}
|
|
||||||
cluster: {{ vars.cluster_vars.name }}
|
|
||||||
name: {{ service_name }}-<< name >>
|
|
||||||
namespace: {{ vars.cluster_vars.namespace }}
|
|
||||||
spec:
|
|
||||||
rules:
|
|
||||||
- host: << host() >>
|
|
||||||
http:
|
|
||||||
paths:
|
|
||||||
- backend:
|
|
||||||
service:
|
|
||||||
name: << k8s_service() >>
|
|
||||||
port:
|
|
||||||
name: << name >>
|
|
||||||
path: /
|
|
||||||
pathType: Prefix
|
|
||||||
tls:
|
|
||||||
- hosts:
|
|
||||||
- << host() >>
|
|
||||||
secretName: tls-{{ service_name }}-<< issuer >>-<< name >>-ingress-dns
|
|
||||||
"#;
|
|
||||||
|
|
||||||
let get_template = |name, base_host, connection_type| {
|
|
||||||
let mut env = minijinja::Environment::new();
|
|
||||||
env.set_syntax(
|
|
||||||
SyntaxConfig::builder()
|
|
||||||
.block_delimiters("<%", "%>")
|
|
||||||
.variable_delimiters("<<", ">>")
|
|
||||||
.comment_delimiters("<#", "#>")
|
|
||||||
.build()
|
|
||||||
.expect("to be able to build minijinja syntax"),
|
|
||||||
);
|
|
||||||
|
|
||||||
env.add_global("name", name);
|
|
||||||
env.add_global("base_host", base_host);
|
|
||||||
if let Some(connection_type) = connection_type {
|
|
||||||
env.add_global("connection_type", connection_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
env.add_global("issuer", "kjuulh-app");
|
|
||||||
|
|
||||||
env.render_named_str("ingress.yaml", internal_template, context! {})
|
|
||||||
};
|
|
||||||
|
|
||||||
for ingress_type in ingress_types {
|
|
||||||
match ingress_type {
|
|
||||||
IngressType::External => {
|
|
||||||
templates.push(get_template("external-http", "kjuulh.app", None)?)
|
|
||||||
}
|
|
||||||
IngressType::Internal => {
|
|
||||||
templates.push(get_template("internal-http", "internal.kjuulh.app", None)?)
|
|
||||||
}
|
|
||||||
IngressType::ExternalGrpc => {
|
|
||||||
templates.push(get_template("external-grpc", "kjuulh.app", Some("grpc"))?)
|
|
||||||
}
|
|
||||||
IngressType::InternalGrpc => templates.push(get_template(
|
|
||||||
"internal-grpc",
|
|
||||||
"internal.kjuulh.app",
|
|
||||||
Some("grpc"),
|
|
||||||
)?),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(("ingress.yaml".into(), templates.join("\n")))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Component for Ingress {
|
|
||||||
fn name(&self) -> String {
|
|
||||||
"cuddle/ingress".to_string()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render(
|
|
||||||
&self,
|
|
||||||
_environment: &str,
|
|
||||||
_value: &serde_yaml::Value,
|
|
||||||
) -> Option<anyhow::Result<(String, String)>> {
|
|
||||||
if let Some(ingress_types) = self
|
|
||||||
.variables
|
|
||||||
.0
|
|
||||||
.get("ingress")
|
|
||||||
.and_then(|v| match v {
|
|
||||||
CuddleVariable::Array(a) => Some(a),
|
|
||||||
_ => 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 if o.0.contains_key("external_grpc") {
|
|
||||||
types.push(IngressType::ExternalGrpc)
|
|
||||||
} else if o.0.contains_key("internal_grpc") {
|
|
||||||
types.push(IngressType::InternalGrpc)
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => continue,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
types
|
|
||||||
})
|
|
||||||
{
|
|
||||||
return Some(self.render_ingress_types(ingress_types));
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
@ -68,40 +68,15 @@ impl Component for VaultSecret {
|
|||||||
return Some(Ok(minijinja::Value::from_object(vault_values)));
|
return Some(Ok(minijinja::Value::from_object(vault_values)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(Ok(minijinja::Value::from_object(VaultSecretValues {
|
None
|
||||||
name: self.name().replace("/", "-"),
|
|
||||||
secrets: VaultSecretsLookup {
|
|
||||||
secrets: Vec::default(),
|
|
||||||
},
|
|
||||||
})))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)>> {
|
||||||
value
|
Some(Ok((
|
||||||
.as_mapping()
|
|
||||||
.and_then(|map| map.get("env"))
|
|
||||||
.and_then(|v| v.as_mapping())
|
|
||||||
.map(|v| {
|
|
||||||
v.iter()
|
|
||||||
.filter_map(|(k, v)| {
|
|
||||||
if v.as_mapping()
|
|
||||||
.map(|m| m.get("vault").filter(|v| v.as_bool() == Some(true)))
|
|
||||||
.is_some()
|
|
||||||
{
|
|
||||||
Some(k)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.filter_map(|k| k.as_str())
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
})
|
|
||||||
.map(|_| {
|
|
||||||
Ok((
|
|
||||||
format!("{}.yaml", self.name().replace("/", "_")),
|
format!("{}.yaml", self.name().replace("/", "_")),
|
||||||
r#"apiVersion: secrets.hashicorp.com/v1beta1
|
r#"apiVersion: secrets.hashicorp.com/v1beta1
|
||||||
kind: VaultStaticSecret
|
kind: VaultStaticSecret
|
||||||
@ -118,8 +93,7 @@ spec:
|
|||||||
type: kv-v2
|
type: kv-v2
|
||||||
"#
|
"#
|
||||||
.into(),
|
.into(),
|
||||||
))
|
)))
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use std::sync::Arc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub trait Component {
|
pub trait Component {
|
||||||
fn name(&self) -> String;
|
fn name(&self) -> String;
|
||||||
@ -27,11 +27,11 @@ pub trait Component {
|
|||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ConcreteComponent {
|
pub struct ConcreteComponent {
|
||||||
inner: Arc<dyn Component + Sync + Send + 'static>,
|
inner: Rc<dyn Component + 'static>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::ops::Deref for ConcreteComponent {
|
impl std::ops::Deref for ConcreteComponent {
|
||||||
type Target = Arc<dyn Component + Sync + Send + 'static>;
|
type Target = Rc<dyn Component + 'static>;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.inner
|
&self.inner
|
||||||
@ -39,8 +39,8 @@ impl std::ops::Deref for ConcreteComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ConcreteComponent {
|
impl ConcreteComponent {
|
||||||
pub fn new<T: Component + Sync + Send + 'static>(t: T) -> Self {
|
pub fn new<T: Component + 'static>(t: T) -> Self {
|
||||||
Self { inner: Arc::new(t) }
|
Self { inner: Rc::new(t) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,7 +54,7 @@ impl IntoComponent for ConcreteComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Component + Sync + Send + 'static> IntoComponent for T {
|
impl<T: Component + 'static> IntoComponent for T {
|
||||||
fn into_component(self) -> ConcreteComponent {
|
fn into_component(self) -> ConcreteComponent {
|
||||||
ConcreteComponent::new(self)
|
ConcreteComponent::new(self)
|
||||||
}
|
}
|
||||||
|
@ -7,5 +7,3 @@ pub mod catalog;
|
|||||||
|
|
||||||
pub mod process;
|
pub mod process;
|
||||||
pub use process::{process, process_opts};
|
pub use process::{process, process_opts};
|
||||||
|
|
||||||
pub mod releaser;
|
|
||||||
|
@ -13,32 +13,12 @@ use tokio_stream::{wrappers::ReadDirStream, StreamExt};
|
|||||||
use crate::components::{ConcreteComponent, IntoComponent};
|
use crate::components::{ConcreteComponent, IntoComponent};
|
||||||
|
|
||||||
pub async fn process() -> anyhow::Result<()> {
|
pub async fn process() -> anyhow::Result<()> {
|
||||||
process_opts(
|
process_opts(Vec::<ConcreteComponent>::new(), ProcessOpts::default()).await
|
||||||
Vec::<ConcreteComponent>::new(),
|
|
||||||
ProcessOpts::default(),
|
|
||||||
None::<NoUploadStrategy>,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait UploadStrategy {
|
|
||||||
fn upload(&self, input_path: &Path) -> BoxFuture<'_, anyhow::Result<()>>;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct NoUploadStrategy {}
|
|
||||||
|
|
||||||
impl UploadStrategy for NoUploadStrategy {
|
|
||||||
fn upload(&self, _input_path: &Path) -> BoxFuture<'_, anyhow::Result<()>> {
|
|
||||||
async move { Ok(()) }.boxed()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ProcessOpts {
|
pub struct ProcessOpts {
|
||||||
pub path: PathBuf,
|
pub path: PathBuf,
|
||||||
pub output: PathBuf,
|
pub output: PathBuf,
|
||||||
|
|
||||||
pub variables: HashMap<String, String>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ProcessOpts {
|
impl Default for ProcessOpts {
|
||||||
@ -49,18 +29,16 @@ impl Default for ProcessOpts {
|
|||||||
.expect("to be able to get current dir")
|
.expect("to be able to get current dir")
|
||||||
.join("cuddle-clusters")
|
.join("cuddle-clusters")
|
||||||
.join("k8s"),
|
.join("k8s"),
|
||||||
variables: HashMap::default(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const TEMPLATES_PATH_PREFIX: &str = "templates/clusters";
|
const TEMPLATES_PATH_PREFIX: &str = "templates/clusters";
|
||||||
const CUDDLE_PLAN_PATH_PREFIX: &str = ".cuddle/base";
|
const CUDDLE_PLAN_PATH_PREFIX: &str = ".cuddle/plan";
|
||||||
|
|
||||||
pub async fn process_opts(
|
pub async fn process_opts(
|
||||||
components: impl IntoIterator<Item = impl IntoComponent>,
|
components: impl IntoIterator<Item = impl IntoComponent>,
|
||||||
opts: ProcessOpts,
|
opts: ProcessOpts,
|
||||||
upload_strategy: Option<impl UploadStrategy>,
|
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let components = components
|
let components = components
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@ -83,21 +61,10 @@ pub async fn process_opts(
|
|||||||
let template_files = load_template_files(&path).await?;
|
let template_files = load_template_files(&path).await?;
|
||||||
tracing::debug!("found files: {:?}", template_files);
|
tracing::debug!("found files: {:?}", template_files);
|
||||||
|
|
||||||
let _ = tokio::fs::remove_dir_all(&opts.output).await;
|
tokio::fs::remove_dir_all(&opts.output).await?;
|
||||||
tokio::fs::create_dir_all(&opts.output).await?;
|
tokio::fs::create_dir_all(&opts.output).await?;
|
||||||
|
|
||||||
process_templates(
|
process_templates(&components, &clusters, &template_files, &opts.output).await?;
|
||||||
&components,
|
|
||||||
&clusters,
|
|
||||||
&template_files,
|
|
||||||
&opts.output,
|
|
||||||
&opts.variables,
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
if let Some(upload_strategy) = upload_strategy {
|
|
||||||
upload_strategy.upload(&opts.output).await?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -217,7 +184,6 @@ async fn process_templates(
|
|||||||
clusters: &CuddleClusters,
|
clusters: &CuddleClusters,
|
||||||
template_files: &TemplateFiles,
|
template_files: &TemplateFiles,
|
||||||
dest: &Path,
|
dest: &Path,
|
||||||
variables: &HashMap<String, String>,
|
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
for (environment, value) in clusters.iter() {
|
for (environment, value) in clusters.iter() {
|
||||||
process_cluster(
|
process_cluster(
|
||||||
@ -226,7 +192,6 @@ async fn process_templates(
|
|||||||
environment,
|
environment,
|
||||||
template_files,
|
template_files,
|
||||||
&dest.join(environment),
|
&dest.join(environment),
|
||||||
variables,
|
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
@ -240,18 +205,9 @@ async fn process_cluster(
|
|||||||
environment: &str,
|
environment: &str,
|
||||||
template_files: &TemplateFiles,
|
template_files: &TemplateFiles,
|
||||||
dest: &Path,
|
dest: &Path,
|
||||||
variables: &HashMap<String, String>,
|
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
for (_, template_file) in &template_files.templates {
|
for (_, template_file) in &template_files.templates {
|
||||||
process_template_file(
|
process_template_file(components, value, environment, template_file, dest).await?;
|
||||||
components,
|
|
||||||
value,
|
|
||||||
environment,
|
|
||||||
template_file,
|
|
||||||
dest,
|
|
||||||
variables,
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (template_file_name, template_content) in components
|
for (template_file_name, template_content) in components
|
||||||
@ -272,7 +228,6 @@ async fn process_cluster(
|
|||||||
&template_file_name,
|
&template_file_name,
|
||||||
&template_content,
|
&template_content,
|
||||||
dest,
|
dest,
|
||||||
variables,
|
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
@ -290,7 +245,6 @@ async fn process_template_file(
|
|||||||
environment: &str,
|
environment: &str,
|
||||||
template_file: &PathBuf,
|
template_file: &PathBuf,
|
||||||
dest: &Path,
|
dest: &Path,
|
||||||
variables: &HashMap<String, String>,
|
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let file = tokio::fs::read_to_string(template_file)
|
let file = tokio::fs::read_to_string(template_file)
|
||||||
.await
|
.await
|
||||||
@ -306,7 +260,6 @@ async fn process_template_file(
|
|||||||
&file_name.to_string_lossy(),
|
&file_name.to_string_lossy(),
|
||||||
&file,
|
&file,
|
||||||
dest,
|
dest,
|
||||||
variables,
|
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@ -320,7 +273,6 @@ async fn process_render_template(
|
|||||||
file_name: &str,
|
file_name: &str,
|
||||||
file_content: &str,
|
file_content: &str,
|
||||||
dest: &Path,
|
dest: &Path,
|
||||||
user_vars: &HashMap<String, String>,
|
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
if !dest.exists() {
|
if !dest.exists() {
|
||||||
tokio::fs::create_dir_all(dest).await?;
|
tokio::fs::create_dir_all(dest).await?;
|
||||||
@ -334,7 +286,6 @@ async fn process_render_template(
|
|||||||
env.add_global("environment", environment);
|
env.add_global("environment", environment);
|
||||||
|
|
||||||
let mut variables = HashMap::new();
|
let mut variables = HashMap::new();
|
||||||
|
|
||||||
for component in components {
|
for component in components {
|
||||||
let name = component.name();
|
let name = component.name();
|
||||||
|
|
||||||
@ -344,10 +295,6 @@ async fn process_render_template(
|
|||||||
variables.insert(name.replace("/", "_"), value);
|
variables.insert(name.replace("/", "_"), value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
variables.insert(
|
|
||||||
"user_vars".into(),
|
|
||||||
minijinja::Value::from_serialize(user_vars),
|
|
||||||
);
|
|
||||||
|
|
||||||
let tmpl = env.get_template(file_name)?;
|
let tmpl = env.get_template(file_name)?;
|
||||||
let rendered = tmpl.render(context! {
|
let rendered = tmpl.render(context! {
|
||||||
|
@ -1,108 +0,0 @@
|
|||||||
use std::{
|
|
||||||
path::{Path, PathBuf},
|
|
||||||
process::Command,
|
|
||||||
};
|
|
||||||
|
|
||||||
use anyhow::Context;
|
|
||||||
use flux_releaser::{
|
|
||||||
app::{LocalApp, SharedLocalApp},
|
|
||||||
services::flux_local_cluster::extensions::FluxLocalClusterManagerExt,
|
|
||||||
};
|
|
||||||
use futures::{future::BoxFuture, FutureExt};
|
|
||||||
|
|
||||||
use crate::process::UploadStrategy;
|
|
||||||
|
|
||||||
#[derive(Default, Clone)]
|
|
||||||
pub struct Releaser {
|
|
||||||
registry: String,
|
|
||||||
service: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Releaser {
|
|
||||||
pub fn with_registry(&mut self, registry: impl Into<String>) -> &mut Self {
|
|
||||||
self.registry = registry.into();
|
|
||||||
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with_service(&mut self, service: impl Into<String>) -> &mut Self {
|
|
||||||
self.service = service.into();
|
|
||||||
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn release(&self, input_path: impl Into<PathBuf>) -> anyhow::Result<()> {
|
|
||||||
let input_path = input_path.into();
|
|
||||||
let branch = self.get_branch()?.ok_or(anyhow::anyhow!(
|
|
||||||
"failed to find branch, required for triggering release"
|
|
||||||
))?;
|
|
||||||
|
|
||||||
tracing::trace!("triggering release for: {}", input_path.display());
|
|
||||||
|
|
||||||
let local_app =
|
|
||||||
SharedLocalApp::new(LocalApp::new(&self.registry).await?).flux_local_cluster_manager();
|
|
||||||
|
|
||||||
let upload_id = local_app
|
|
||||||
.package_clusters(input_path)
|
|
||||||
.await
|
|
||||||
.context("failed to package clusters")?;
|
|
||||||
|
|
||||||
local_app
|
|
||||||
.commit_artifact(&self.service, &branch, upload_id)
|
|
||||||
.await
|
|
||||||
.context("failed to commit artifact")?;
|
|
||||||
|
|
||||||
local_app
|
|
||||||
.trigger_release(&self.service, &branch)
|
|
||||||
.await
|
|
||||||
.context("failed to trigger release")?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_branch(&self) -> anyhow::Result<Option<String>> {
|
|
||||||
let output = Command::new("git")
|
|
||||||
.args(["rev-parse", "--abbrev-ref", "HEAD"])
|
|
||||||
.output()?;
|
|
||||||
|
|
||||||
if output.status.success() {
|
|
||||||
let branch = std::str::from_utf8(&output.stdout)?.trim().to_string();
|
|
||||||
Ok(Some(branch))
|
|
||||||
} else {
|
|
||||||
let err = std::str::from_utf8(&output.stderr)?;
|
|
||||||
anyhow::bail!("Failed to get branch name: {}", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl UploadStrategy for Releaser {
|
|
||||||
fn upload(&self, input_path: &Path) -> BoxFuture<'_, anyhow::Result<()>> {
|
|
||||||
let input_path = input_path.to_path_buf();
|
|
||||||
|
|
||||||
async move {
|
|
||||||
self.release(input_path).await?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
.boxed()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use crate::releaser::Releaser;
|
|
||||||
|
|
||||||
#[tokio::test]
|
|
||||||
async fn can_upload_test() -> anyhow::Result<()> {
|
|
||||||
return Ok(());
|
|
||||||
let releaser = Releaser::default();
|
|
||||||
|
|
||||||
releaser
|
|
||||||
.release(
|
|
||||||
"/home/kjuulh/git/git.front.kjuulh.io/kjuulh/cuddle-rust-service-plan/.cuddle/tmp/cuddle-clusters",
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,9 +1,6 @@
|
|||||||
use std::{cmp::Ordering, collections::HashMap, path::Path};
|
use std::{cmp::Ordering, path::Path};
|
||||||
|
|
||||||
use cuddle_clusters::{
|
use cuddle_clusters::{process::ProcessOpts, ConcreteComponent, IntoComponent};
|
||||||
process::{NoUploadStrategy, ProcessOpts},
|
|
||||||
ConcreteComponent, IntoComponent,
|
|
||||||
};
|
|
||||||
use walkdir::DirEntry;
|
use walkdir::DirEntry;
|
||||||
|
|
||||||
pub(crate) async fn run_test_with_components(
|
pub(crate) async fn run_test_with_components(
|
||||||
@ -30,9 +27,7 @@ pub(crate) async fn run_test_with_components(
|
|||||||
ProcessOpts {
|
ProcessOpts {
|
||||||
path: test_folder.clone(),
|
path: test_folder.clone(),
|
||||||
output: actual.clone(),
|
output: actual.clone(),
|
||||||
variables: HashMap::default(),
|
|
||||||
},
|
},
|
||||||
None::<NoUploadStrategy>,
|
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@ -42,9 +37,7 @@ pub(crate) async fn run_test_with_components(
|
|||||||
ProcessOpts {
|
ProcessOpts {
|
||||||
path: test_folder,
|
path: test_folder,
|
||||||
output: expected.clone(),
|
output: expected.clone(),
|
||||||
variables: HashMap::default(),
|
|
||||||
},
|
},
|
||||||
None::<NoUploadStrategy>,
|
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
|
@ -4,10 +4,7 @@ mod can_run_for_env;
|
|||||||
mod cuddle_vars;
|
mod cuddle_vars;
|
||||||
|
|
||||||
use cuddle_clusters::{
|
use cuddle_clusters::{
|
||||||
catalog::{
|
catalog::{cluster_vars::ClusterVars, cuddle_vars::CuddleVars, vault_secret::VaultSecret},
|
||||||
cluster_vars::ClusterVars, crdb_database::CockroachDB, cuddle_vars::CuddleVars,
|
|
||||||
ingress::Ingress, vault_secret::VaultSecret,
|
|
||||||
},
|
|
||||||
IntoComponent,
|
IntoComponent,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -99,38 +96,3 @@ async fn with_vault_secrets() -> anyhow::Result<()> {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
|
||||||
async fn with_crdb() -> anyhow::Result<()> {
|
|
||||||
let current_dir = std::env::current_dir()?.join("tests/with_crdb");
|
|
||||||
|
|
||||||
run_test_with_components(
|
|
||||||
"with_crdb",
|
|
||||||
vec![
|
|
||||||
CuddleVars::new(¤t_dir).await?.into_component(),
|
|
||||||
ClusterVars::default().into_component(),
|
|
||||||
VaultSecret::default().into_component(),
|
|
||||||
CockroachDB::new(¤t_dir).await?.into_component(),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
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(())
|
|
||||||
}
|
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: {{ vars.cuddle_vars.service }}-config
|
||||||
|
data:
|
||||||
|
{%- if (vars.cluster_vars.env | items | length) > 0 %}
|
||||||
|
environment:
|
||||||
|
{%- for (name, value) in vars.cluster_vars.env | dictsort %}
|
||||||
|
{{name | upper | replace(".", "_") | replace("-", "_") }}: {{value}}
|
||||||
|
{%- endfor %}
|
||||||
|
{%- endif %}
|
@ -1,20 +1,26 @@
|
|||||||
{%- set service_name = vars.cuddle_vars.service -%}
|
{%- set service_name = vars.cuddle_vars.service -%}
|
||||||
|
{%- set cluster_name = vars.cluster_vars.name -%}
|
||||||
|
{%- set cluster_namespace = vars.cluster_vars.namespace -%}
|
||||||
|
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
app: {{ service_name }}
|
app: {{ service_name }}
|
||||||
|
cluster: {{ cluster_name }}
|
||||||
name: {{ service_name }}
|
name: {{ service_name }}
|
||||||
|
namespace: {{ cluster_namespace }}
|
||||||
spec:
|
spec:
|
||||||
replicas: 3
|
replicas: 3
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
app: {{ service_name }}
|
app: {{ service_name }}
|
||||||
|
cluster: {{ cluster_name }}
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
app: {{ service_name }}
|
app: {{ service_name }}
|
||||||
|
cluster: {{ cluster_name }}
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- args:
|
- args:
|
||||||
@ -23,6 +29,9 @@ spec:
|
|||||||
- {{ service_name }}
|
- {{ service_name }}
|
||||||
image: kasperhermansen/{{ service_name }}:main-1715336504
|
image: kasperhermansen/{{ service_name }}:main-1715336504
|
||||||
name: {{ service_name }}
|
name: {{ service_name }}
|
||||||
|
envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: {{service_name}}-config
|
||||||
ports:
|
ports:
|
||||||
- containerPort: 3000
|
- containerPort: 3000
|
||||||
name: external-http
|
name: external-http
|
@ -1,7 +0,0 @@
|
|||||||
vars:
|
|
||||||
service: service
|
|
||||||
database:
|
|
||||||
crdb: "true"
|
|
||||||
|
|
||||||
cuddle/clusters:
|
|
||||||
dev:
|
|
@ -1,9 +0,0 @@
|
|||||||
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ConfigMap
|
|
||||||
metadata:
|
|
||||||
name: service-cuddle-crdb
|
|
||||||
namespace: dev
|
|
||||||
data:
|
|
||||||
DATABASE_URL: postgresql://root@dev-cluster:26257/service
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
|||||||
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
|
|
||||||
envFrom:
|
|
||||||
- configMapRef:
|
|
||||||
name: service-config
|
|
||||||
env:
|
|
||||||
- name: DATABASE_URL
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: service-cuddle-crdb
|
|
||||||
key: DATABASE_URL
|
|
||||||
ports:
|
|
||||||
- containerPort: 3000
|
|
||||||
name: external-http
|
|
||||||
- containerPort: 3001
|
|
||||||
name: internal-http
|
|
||||||
- containerPort: 3002
|
|
||||||
name: internal-grpc
|
|
@ -1,54 +0,0 @@
|
|||||||
{%- 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 }}
|
|
||||||
envFrom:
|
|
||||||
- configMapRef:
|
|
||||||
name: {{service_name}}-config
|
|
||||||
{%- if vars.vault_secret.has_values or vars.cuddle_crdb.has_values %}
|
|
||||||
env:
|
|
||||||
{%- if vars.vault_secret.has_values %}
|
|
||||||
{%- for secret in vars.vault_secret.secrets %}
|
|
||||||
- name: {{secret | upper | replace(".", "_") | replace("-", "_") }}
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: {{ vars.vault_secret.file_name(service_name) }}
|
|
||||||
key: {{ secret }}
|
|
||||||
{%- endfor %}
|
|
||||||
{%- endif %}
|
|
||||||
{%- if vars.cuddle_crdb.has_values %}
|
|
||||||
- name: {{vars.cuddle_crdb.env }}
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: {{ vars.cuddle_crdb.file_name(service_name) }}
|
|
||||||
key: {{ vars.cuddle_crdb.env }}
|
|
||||||
{%- endif %}
|
|
||||||
{%- endif %}
|
|
||||||
ports:
|
|
||||||
- containerPort: 3000
|
|
||||||
name: external-http
|
|
||||||
- containerPort: 3001
|
|
||||||
name: internal-http
|
|
||||||
- containerPort: 3002
|
|
||||||
name: internal-grpc
|
|
@ -1,11 +0,0 @@
|
|||||||
vars:
|
|
||||||
service: service
|
|
||||||
ingress:
|
|
||||||
- external: "true"
|
|
||||||
- internal: "true"
|
|
||||||
- external_grpc: "true"
|
|
||||||
- internal_grpc: "true"
|
|
||||||
|
|
||||||
cuddle/clusters:
|
|
||||||
dev:
|
|
||||||
prod:
|
|
@ -1,121 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
---
|
|
||||||
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-http-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-http-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-external-grpc
|
|
||||||
namespace: dev
|
|
||||||
spec:
|
|
||||||
rules:
|
|
||||||
- host: grpc.service.dev.kjuulh.app
|
|
||||||
http:
|
|
||||||
paths:
|
|
||||||
- backend:
|
|
||||||
service:
|
|
||||||
name: service-grpc
|
|
||||||
port:
|
|
||||||
name: external-grpc
|
|
||||||
path: /
|
|
||||||
pathType: Prefix
|
|
||||||
tls:
|
|
||||||
- hosts:
|
|
||||||
- grpc.service.dev.kjuulh.app
|
|
||||||
secretName: tls-service-kjuulh-app-external-grpc-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-grpc
|
|
||||||
namespace: dev
|
|
||||||
spec:
|
|
||||||
rules:
|
|
||||||
- host: grpc.service.dev.internal.kjuulh.app
|
|
||||||
http:
|
|
||||||
paths:
|
|
||||||
- backend:
|
|
||||||
service:
|
|
||||||
name: service-grpc
|
|
||||||
port:
|
|
||||||
name: internal-grpc
|
|
||||||
path: /
|
|
||||||
pathType: Prefix
|
|
||||||
tls:
|
|
||||||
- hosts:
|
|
||||||
- grpc.service.dev.internal.kjuulh.app
|
|
||||||
secretName: tls-service-kjuulh-app-internal-grpc-ingress-dns
|
|
@ -1,30 +0,0 @@
|
|||||||
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
|
|
@ -1,121 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
---
|
|
||||||
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-http-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-http-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-external-grpc
|
|
||||||
namespace: prod
|
|
||||||
spec:
|
|
||||||
rules:
|
|
||||||
- host: grpc.service.prod.kjuulh.app
|
|
||||||
http:
|
|
||||||
paths:
|
|
||||||
- backend:
|
|
||||||
service:
|
|
||||||
name: service-grpc
|
|
||||||
port:
|
|
||||||
name: external-grpc
|
|
||||||
path: /
|
|
||||||
pathType: Prefix
|
|
||||||
tls:
|
|
||||||
- hosts:
|
|
||||||
- grpc.service.prod.kjuulh.app
|
|
||||||
secretName: tls-service-kjuulh-app-external-grpc-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-grpc
|
|
||||||
namespace: prod
|
|
||||||
spec:
|
|
||||||
rules:
|
|
||||||
- host: grpc.service.prod.internal.kjuulh.app
|
|
||||||
http:
|
|
||||||
paths:
|
|
||||||
- backend:
|
|
||||||
service:
|
|
||||||
name: service-grpc
|
|
||||||
port:
|
|
||||||
name: internal-grpc
|
|
||||||
path: /
|
|
||||||
pathType: Prefix
|
|
||||||
tls:
|
|
||||||
- hosts:
|
|
||||||
- grpc.service.prod.internal.kjuulh.app
|
|
||||||
secretName: tls-service-kjuulh-app-internal-grpc-ingress-dns
|
|
@ -1,30 +0,0 @@
|
|||||||
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
|
|
Loading…
Reference in New Issue
Block a user