Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions api/src/apps/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,7 @@ use crate::config::{Config, ConfigError};
use crate::deployment::deployment_unit::DeploymentTemplatingError;
use crate::deployment::deployment_unit::DeploymentUnitBuilder;
use crate::deployment::hooks::HooksError;
use crate::infrastructure::HttpForwarder;
use crate::infrastructure::Infrastructure;
use crate::infrastructure::TraefikIngressRoute;
use crate::infrastructure::{HttpForwarder, Infrastructure, TraefikIngressRoute};
use crate::models::user_defined_parameters::UserDefinedParameters;
use crate::models::Owner;
use crate::models::{App, AppName, ContainerType, LogChunk, Service, ServiceConfig, ServiceStatus};
Expand Down Expand Up @@ -363,6 +361,9 @@ impl Apps {
);
deployment_unit_builder
.apply_base_traefik_ingress_route(base_traefik_ingress_route.clone())
.map_err(|e| AppsError::BaseRouteNotMergeable {
error: e.to_string(),
})?
.build()
} else {
deployment_unit_builder.build()
Expand Down Expand Up @@ -472,6 +473,8 @@ pub enum AppsError {
AppNotFound { app_name: AppName },
#[error("Cannot create more than {limit} apps")]
AppLimitExceeded { limit: usize },
#[error("Cannot merge the base route: {error}")]
BaseRouteNotMergeable { error: String },
/// Will be used when the service cannot interact correctly with the infrastructure.
#[error("Cannot interact with infrastructure: {error}")]
InfrastructureError { error: String },
Expand Down
1 change: 1 addition & 0 deletions api/src/apps/routes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,7 @@ impl From<AppsError> for HttpApiError {
},
AppsError::AppNotFound { .. } => StatusCode::NOT_FOUND,
AppsError::InfrastructureError { .. }
| AppsError::BaseRouteNotMergeable { .. }
| AppsError::InvalidServerConfiguration { .. }
| AppsError::TemplatingIssue { .. }
| AppsError::UnapplicableHook { .. } => {
Expand Down
36 changes: 19 additions & 17 deletions api/src/deployment/deployment_unit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ use url::Url;
use super::hooks::HooksError;
use crate::config::{Config, StorageStrategy};
use crate::deployment::hooks::Hooks;
use crate::infrastructure::{TraefikIngressRoute, TraefikMiddleware, TraefikRouterRule};
use crate::infrastructure::{
TraefikIngressRoute, TraefikIngressRouteMergeError, TraefikMiddleware, TraefikRouterRule,
};
use crate::models::user_defined_parameters::UserDefinedParameters;
use crate::models::{AppName, ContainerType, Image, Owner, ServiceConfig};
use crate::registry::ImageInfo;
Expand Down Expand Up @@ -567,12 +569,12 @@ impl DeploymentUnitBuilder<WithUserInformation> {
storage_strategy: &StorageStrategy,
image_infos: &HashMap<Image, ImageInfo>,
) -> Result<DeployableService, DeploymentTemplatingError> {
let service_name = raw_service_config.service_name();
let app_name = &self.stage.app_name;

let ingress_route =
match raw_service_config.routing() {
None => TraefikIngressRoute::with_defaults(
&self.stage.app_name,
raw_service_config.service_name(),
),
None => TraefikIngressRoute::with_defaults(&self.stage.app_name, service_name),
Some(routing) => match &routing.rule {
Some(rule) => TraefikIngressRoute::with_rule_and_middlewares(
TraefikRouterRule::from_str(rule).map_err(|err| {
Expand All @@ -586,7 +588,7 @@ impl DeploymentUnitBuilder<WithUserInformation> {
.iter()
.enumerate()
.map(|(i, (name, spec))| TraefikMiddleware {
name: format!("custom-middleware-{i}"),
name: format!("{app_name}-{service_name}-custom-middleware-{i}"),
spec: serde_value::to_value(serde_json::json!({
name: spec.clone()
}))
Expand All @@ -596,10 +598,10 @@ impl DeploymentUnitBuilder<WithUserInformation> {
),
None => TraefikIngressRoute::with_defaults_and_additional_middleware(
&self.stage.app_name,
raw_service_config.service_name(),
service_name,
routing.additional_middlewares.iter().enumerate().map(
|(i, (name, spec))| TraefikMiddleware {
name: format!("custom-middleware-{i}"),
name: format!("{app_name}-{service_name}-custom-middleware-{i}"),
spec: serde_value::to_value(serde_json::json!({
name: spec.clone()
}))
Expand Down Expand Up @@ -692,26 +694,26 @@ impl DeploymentUnitBuilder<WithAppliedHooks> {
pub fn apply_base_traefik_ingress_route(
mut self,
route: TraefikIngressRoute,
) -> DeploymentUnitBuilder<WithAppliedIngressRoute> {
) -> Result<DeploymentUnitBuilder<WithAppliedIngressRoute>, TraefikIngressRouteMergeError> {
for service in &mut self.stage.services {
let service_route = std::mem::replace(&mut service.ingress_route, route.clone());
service.ingress_route.merge_with(service_route);
service.ingress_route.merge_with(service_route)?;
}

let mut route = route;
route.merge_with(TraefikIngressRoute::with_app_only_defaults(
&self.stage.app_name,
));
))?;

DeploymentUnitBuilder {
Ok(DeploymentUnitBuilder {
stage: WithAppliedIngressRoute {
app_name: self.stage.app_name,
services: self.stage.services,
route,
owners: self.stage.owners,
user_defined_parameters: self.stage.user_defined_parameters,
},
}
})
}

pub fn build(self) -> DeploymentUnit {
Expand Down Expand Up @@ -1339,7 +1341,7 @@ mod tests {
.await?
.apply_base_traefik_ingress_route(TraefikIngressRoute::with_rule(
TraefikRouterRule::path_prefix_rule(vec![String::from("my-path-prefix")]),
))
))?
.build();

let service = unit.services.into_iter().next().unwrap();
Expand Down Expand Up @@ -1407,7 +1409,7 @@ mod tests {
configs[0].ingress_route().routes()[0].middlewares(),
&vec![
crate::infrastructure::TraefikMiddleware {
name: String::from("custom-middleware-0"),
name: String::from("master-adminer-custom-middleware-0"),
spec: serde_value::to_value(serde_json::json!({
"headers": {
"customRequestHeaders": {
Expand All @@ -1418,7 +1420,7 @@ mod tests {
.unwrap()
},
crate::infrastructure::TraefikMiddleware {
name: String::from("custom-middleware-1"),
name: String::from("master-adminer-custom-middleware-1"),
spec: serde_value::to_value(serde_json::json!({
"stripPrefix": {
"prefixes": [
Expand Down Expand Up @@ -1482,7 +1484,7 @@ mod tests {
.unwrap()
},
crate::infrastructure::TraefikMiddleware {
name: String::from("custom-middleware-0"),
name: String::from("master-adminer-custom-middleware-0"),
spec: serde_value::to_value(serde_json::json!({
"headers": {
"customRequestHeaders": {
Expand Down
10 changes: 5 additions & 5 deletions api/src/infrastructure/docker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -460,14 +460,14 @@ impl DockerInfrastructure {
let mut applied_middle_wares = String::new();
for middleware in route.middlewares() {
for (key, value) in middleware.to_key_value_spec() {
let middleware_name = &middleware.name;
if !applied_middle_wares.is_empty() {
applied_middle_wares += ",";
applied_middle_wares += ", ";
}
applied_middle_wares += &format!("{}@docker", middleware.name);
applied_middle_wares += &middleware_name;
labels.insert(
format!(
"traefik.http.middlewares.{}.{}",
middleware.name,
"traefik.http.middlewares.{middleware_name}.{}",
key.to_lowercase()
),
value,
Expand Down Expand Up @@ -1779,7 +1779,7 @@ mod tests {
expected: serde_json::json!({
"Labels": {
"traefik.http.routers.master-db.rule": "PathPrefix(`/master/db/`)",
"traefik.http.routers.master-db.middlewares": "master-db-middleware@docker",
"traefik.http.routers.master-db.middlewares": "master-db-middleware",
"traefik.http.middlewares.master-db-middleware.stripprefix.prefixes": "/master/db/",
"traefik.docker.network": "master-net",
}
Expand Down
1 change: 1 addition & 0 deletions api/src/infrastructure/kubernetes/deployment_unit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1442,6 +1442,7 @@ mod tests {
&AppName::master(),
),
)
.unwrap()
.build();

K8sDeploymentUnit::parse_from_log_streams(&deployment_unit, log_streams)
Expand Down
36 changes: 24 additions & 12 deletions api/src/infrastructure/kubernetes/payloads.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,15 +148,21 @@ pub fn convert_k8s_ingress_to_traefik_ingress(
ingress: Ingress,
base_route: TraefikIngressRoute,
services: &[V1Service],
) -> Result<(IngressRoute, Vec<Middleware>), (Ingress, &'static str)> {
) -> Result<(IngressRoute, Vec<Middleware>), (Ingress, String)> {
let Some(name) = ingress.metadata.name.as_ref() else {
return Err((ingress, "Ingress object does not provide a name"));
return Err((
ingress,
String::from("Ingress object does not provide a name"),
));
};
let Some(spec) = ingress.spec.as_ref() else {
return Err((ingress, "Ingress does not provide spec"));
return Err((ingress, String::from("Ingress does not provide spec")));
};
let Some(rules) = spec.rules.as_ref() else {
return Err((ingress, "Ingress' spec does not provide rules"));
return Err((
ingress,
String::from("Ingress' spec does not provide rules"),
));
};

let Some(path) = rules
Expand All @@ -166,12 +172,15 @@ pub fn convert_k8s_ingress_to_traefik_ingress(
else {
return Err((
ingress,
"Ingress' rule does not a provide http paths object",
String::from("Ingress' rule does not a provide http paths object"),
));
};

let Some(path_value) = path.path.as_ref() else {
return Err((ingress, "Ingress' path does not provide a HTTP path value"));
return Err((
ingress,
String::from("Ingress' path does not provide a HTTP path value"),
));
};

let (rule, middleware) = match &spec.ingress_class_name {
Expand Down Expand Up @@ -246,7 +255,9 @@ pub fn convert_k8s_ingress_to_traefik_ingress(

let mut route = base_route;
if let Some(rule) = rule {
route.merge_with(rule);
if let Err(e) = route.merge_with(rule) {
return Err((ingress, e.to_string()));
}
}

let mut middlewares_refs = route
Expand All @@ -270,7 +281,10 @@ pub fn convert_k8s_ingress_to_traefik_ingress(
}));

let Some(service) = path.backend.service.as_ref() else {
return Err((ingress, "Expecting a service name for the path"));
return Err((
ingress,
String::from("Expecting a service name for the path"),
));
};

let port = if let Some(port) = service
Expand All @@ -289,7 +303,7 @@ pub fn convert_k8s_ingress_to_traefik_ingress(
else {
return Err((
ingress,
"There is no service matching to the ingress' service.",
String::from("There is no service matching to the ingress' service."),
));
};

Expand All @@ -307,7 +321,7 @@ pub fn convert_k8s_ingress_to_traefik_ingress(
else {
return Err((
ingress,
"There is no service matching to the ingress' service and port name.",
String::from("There is no service matching to the ingress' service and port name."),
));
};
port as u16
Expand Down Expand Up @@ -1894,7 +1908,6 @@ mod tests {
}),
..Default::default()
},
..Default::default()
}],
}),
..Default::default()
Expand Down Expand Up @@ -1992,7 +2005,6 @@ mod tests {
}),
..Default::default()
},
..Default::default()
}],
}),
..Default::default()
Expand Down
4 changes: 3 additions & 1 deletion api/src/infrastructure/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ pub use dummy_infrastructure::DummyInfrastructure as Dummy;
pub use infrastructure::{HttpForwarder, Infrastructure};
pub use kubernetes::KubernetesInfrastructure as Kubernetes;
use serde_json::{map::Map, Value};
pub use traefik::{TraefikIngressRoute, TraefikMiddleware, TraefikRouterRule};
pub use traefik::{
TraefikIngressRoute, TraefikIngressRouteMergeError, TraefikMiddleware, TraefikRouterRule,
};

mod docker;
#[cfg(test)]
Expand Down
Loading
Loading