summaryrefslogtreecommitdiffstats
path: root/src/config
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2020-11-10 08:18:19 +0100
committerMatthias Beyer <mail@beyermatthias.de>2020-11-10 08:26:33 +0100
commit9d72601e57eeb821314b6188e60817137baf223d (patch)
tree41b1420d61860b4c4bf5946e557e7a25bfa54ab6 /src/config
parent451b417f547c9c58a66847bf472e82664c87460b (diff)
Split configuration module in multiple files
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
Diffstat (limited to 'src/config')
-rw-r--r--src/config/configuration.rs40
-rw-r--r--src/config/container_config.rs11
-rw-r--r--src/config/docker_config.rs42
-rw-r--r--src/config/endpoint_config.rs33
-rw-r--r--src/config/mod.rs233
-rw-r--r--src/config/not_validated.rs79
-rw-r--r--src/config/util.rs17
7 files changed, 250 insertions, 205 deletions
diff --git a/src/config/configuration.rs b/src/config/configuration.rs
new file mode 100644
index 0000000..294c5cb
--- /dev/null
+++ b/src/config/configuration.rs
@@ -0,0 +1,40 @@
+use std::collections::BTreeMap;
+use std::ops::Deref;
+use std::path::PathBuf;
+
+use anyhow::Context;
+use anyhow::Result;
+use handlebars::Handlebars;
+
+use crate::config::NotValidatedConfiguration;
+
+#[derive(Debug)]
+pub struct Configuration<'reg> {
+ pub (in crate::config) inner: NotValidatedConfiguration,
+ pub (in crate::config) hb: Handlebars<'reg>,
+}
+
+impl<'reg> Deref for Configuration<'reg> {
+ type Target = NotValidatedConfiguration;
+
+ fn deref(&self) -> &Self::Target {
+ &self.inner
+ }
+}
+
+impl<'reg> Configuration<'reg> {
+ /// Get the path to the releases directory, interpolate every variable used in the config
+ pub fn releases_directory(&self, hm: &BTreeMap<String, String>) -> Result<PathBuf> {
+ self.hb.render("releases", hm)
+ .map(PathBuf::from)
+ .context("Interpolating variables into 'release' setting from configuration")
+ }
+
+ /// Get the path to the staging directory, interpolate every variable used in the config
+ pub fn staging_directory(&self, hm: &BTreeMap<String, String>) -> Result<PathBuf> {
+ self.hb.render("staging", hm)
+ .map(PathBuf::from)
+ .context("Interpolating variables into 'staging' setting from configuration")
+ }
+}
+
diff --git a/src/config/container_config.rs b/src/config/container_config.rs
new file mode 100644
index 0000000..aad17e8
--- /dev/null
+++ b/src/config/container_config.rs
@@ -0,0 +1,11 @@
+use getset::Getters;
+use serde::Deserialize;
+
+use crate::util::EnvironmentVariableName;
+
+#[derive(Debug, Getters, Deserialize)]
+pub struct ContainerConfig {
+ #[getset(get = "pub")]
+ allowed_env: Vec<EnvironmentVariableName>,
+}
+
diff --git a/src/config/docker_config.rs b/src/config/docker_config.rs
new file mode 100644
index 0000000..fcc605f
--- /dev/null
+++ b/src/config/docker_config.rs
@@ -0,0 +1,42 @@
+use getset::{CopyGetters, Getters};
+use serde::Deserialize;
+
+use crate::config::Endpoint;
+use crate::util::docker::ImageName;
+
+#[derive(Debug, Getters, CopyGetters, Deserialize)]
+pub struct DockerConfig {
+ /// The required docker version
+ ///
+ /// If not set, it will not be checked, which might result in weird things?
+ ///
+ /// # Note
+ ///
+ /// Because the docker API returns strings, not a version object, each compatible version must
+ /// be listed.
+ #[getset(get = "pub")]
+ docker_versions: Option<Vec<String>>,
+
+ /// The required docker api version
+ ///
+ /// If not set, it will not be checked, which might result in weird things?
+ ///
+ /// # Note
+ ///
+ /// Because the docker API returns strings, not a version object, each compatible version must
+ /// be listed.
+ #[getset(get = "pub")]
+ docker_api_versions: Option<Vec<String>>,
+
+ /// Whether the program should verify that the required images are present.
+ /// You want this to be true normally.
+ #[getset(get_copy = "pub")]
+ verify_images_present: bool,
+
+ #[getset(get = "pub")]
+ images: Vec<ImageName>,
+
+ #[getset(get = "pub")]
+ endpoints: Vec<Endpoint>,
+}
+
diff --git a/src/config/endpoint_config.rs b/src/config/endpoint_config.rs
new file mode 100644
index 0000000..2146910
--- /dev/null
+++ b/src/config/endpoint_config.rs
@@ -0,0 +1,33 @@
+use getset::{CopyGetters, Getters};
+use serde::Deserialize;
+
+#[derive(Clone, Debug, Getters, CopyGetters, Deserialize)]
+pub struct Endpoint {
+ #[getset(get = "pub")]
+ name: String,
+
+ #[getset(get = "pub")]
+ uri: String,
+
+ #[getset(get = "pub")]
+ endpoint_type: EndpointType,
+
+ /// Relative speed to other endpoints
+ ///
+ /// So if you have two servers, one with 12 cores and one with 24, you want to set "1" for the
+ /// first and "2" for the second (or "12" for the first and "24" for the second - the ratio is
+ /// the thing here)!
+ #[getset(get_copy = "pub")]
+ speed: usize,
+
+ /// Maximum number of jobs which are allowed on this endpoint
+ #[getset(get_copy = "pub")]
+ maxjobs: usize,
+}
+
+#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
+pub enum EndpointType {
+ Socket,
+ Http,
+}
+
diff --git a/src/config/mod.rs b/src/config/mod.rs
index 4bd0df8..629b274 100644
--- a/src/config/mod.rs
+++ b/src/config/mod.rs
@@ -1,205 +1,28 @@
-use std::collections::BTreeMap;
-use std::fmt::Debug;
-use std::ops::Deref;
-use std::path::PathBuf;
-
-use anyhow::Context;
-use anyhow::Result;
-use getset::CopyGetters;
-use getset::Getters;
-use handlebars::Handlebars;
-use serde::Deserialize;
-
-use crate::phase::PhaseName;
-use crate::util::EnvironmentVariableName;
-use crate::util::docker::ImageName;
-
-#[derive(Debug, Getters, Deserialize)]
-pub struct NotValidatedConfiguration {
- #[getset(get = "pub")]
- repository: PathBuf,
-
- #[serde(default = "default_progress_format")]
- #[getset(get = "pub")]
- progress_format: String,
-
- #[serde(default = "default_package_print_format")]
- #[getset(get = "pub")]
- package_print_format: String,
-
- #[serde(rename = "releases")]
- releases_directory: String,
-
- #[serde(rename = "staging")]
- staging_directory: String,
-
- #[getset(get = "pub")]
- #[serde(rename = "database_host")]
- database_host: String,
-
- #[getset(get = "pub")]
- #[serde(rename = "database_port")]
- database_port: String,
-
- #[getset(get = "pub")]
- #[serde(rename = "database_user")]
- database_user: String,
-
- #[getset(get = "pub")]
- #[serde(rename = "database_password")]
- database_password: String,
-
- #[getset(get = "pub")]
- #[serde(rename = "database_name")]
- database_name: String,
-
- #[getset(get = "pub")]
- docker: DockerConfig,
-
- #[getset(get = "pub")]
- containers: ContainerConfig,
-
- #[getset(get = "pub")]
- available_phases: Vec<PhaseName>,
-}
-
-impl<'reg> NotValidatedConfiguration {
- pub fn validate(self) -> Result<Configuration<'reg>> {
- // TODO: Implement proper validation
-
- let hb = {
- let mut hb = Handlebars::new();
- hb.register_template_string("releases", &self.releases_directory)?;
- hb.register_template_string("staging", &self.staging_directory)?;
- hb
- };
-
- Ok(Configuration {
- inner: self,
- hb,
- })
- }
-}
-
-#[derive(Debug)]
-pub struct Configuration<'reg> {
- inner: NotValidatedConfiguration,
- hb: Handlebars<'reg>,
-}
-
-impl<'reg> Deref for Configuration<'reg> {
- type Target = NotValidatedConfiguration;
-
- fn deref(&self) -> &Self::Target {
- &self.inner
- }
-}
-
-impl<'reg> Configuration<'reg> {
- /// Get the path to the releases directory, interpolate every variable used in the config
- pub fn releases_directory(&self, hm: &BTreeMap<String, String>) -> Result<PathBuf> {
- self.hb.render("releases", hm)
- .map(PathBuf::from)
- .context("Interpolating variables into 'release' setting from configuration")
- }
-
- /// Get the path to the staging directory, interpolate every variable used in the config
- pub fn staging_directory(&self, hm: &BTreeMap<String, String>) -> Result<PathBuf> {
- self.hb.render("staging", hm)
- .map(PathBuf::from)
- .context("Interpolating variables into 'staging' setting from configuration")
- }
-}
-
-
-#[derive(Debug, Getters, CopyGetters, Deserialize)]
-pub struct DockerConfig {
- /// The required docker version
- ///
- /// If not set, it will not be checked, which might result in weird things?
- ///
- /// # Note
- ///
- /// Because the docker API returns strings, not a version object, each compatible version must
- /// be listed.
- #[getset(get = "pub")]
- docker_versions: Option<Vec<String>>,
-
- /// The required docker api version
- ///
- /// If not set, it will not be checked, which might result in weird things?
- ///
- /// # Note
- ///
- /// Because the docker API returns strings, not a version object, each compatible version must
- /// be listed.
- #[getset(get = "pub")]
- docker_api_versions: Option<Vec<String>>,
-
- /// Whether the program should verify that the required images are present.
- /// You want this to be true normally.
- #[getset(get_copy = "pub")]
- verify_images_present: bool,
-
- #[getset(get = "pub")]
- images: Vec<ImageName>,
-
- #[getset(get = "pub")]
- endpoints: Vec<Endpoint>,
-}
-
-#[derive(Debug, Getters, Deserialize)]
-pub struct ContainerConfig {
- #[getset(get = "pub")]
- allowed_env: Vec<EnvironmentVariableName>,
-}
-
-
-#[derive(Clone, Debug, Getters, CopyGetters, Deserialize)]
-pub struct Endpoint {
- #[getset(get = "pub")]
- name: String,
-
- #[getset(get = "pub")]
- uri: String,
-
- #[getset(get = "pub")]
- endpoint_type: EndpointType,
-
- /// Relative speed to other endpoints
- ///
- /// So if you have two servers, one with 12 cores and one with 24, you want to set "1" for the
- /// first and "2" for the second (or "12" for the first and "24" for the second - the ratio is
- /// the thing here)!
- #[getset(get_copy = "pub")]
- speed: usize,
-
- /// Maximum number of jobs which are allowed on this endpoint
- #[getset(get_copy = "pub")]
- maxjobs: usize,
-}
-
-#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
-pub enum EndpointType {
- Socket,
- Http,
-}
-
-
-fn default_progress_format() -> String {
- String::from("[{elapsed_precise}] ({percent:>3}%): {bar:40.cyan/blue} | {msg}")
-}
-
-fn default_package_print_format() -> String {
- String::from(indoc::indoc!(r#"
- {{i}} - {{name}} : {{version}}
- Source: {{source_url}}
- Hash ({{source_hash_type}}): {{source_hash}}"
- {{#if print_system_deps}}System Deps: {{ system_deps }} {{/if}}
- {{#if print_system_runtime_deps}}System runtime Deps: {{ system_runtime_deps }} {{/if}}
- {{#if print_build_deps}}Build Deps: {{ build_deps }} {{/if}}
- {{#if print_runtime_deps}}Runtime Deps: {{ runtime_deps }} {{/if}}
-
- "#))
-}
-
+//! The configuration handling code
+//!
+//! This module contains all code for the configuration of butido itself.
+//!
+//! Please note that the `not_validated` module is the "entry point".
+//! A "NotValidatedConfiguration" is loaded from the filesystem and then transformed into a
+//! `Configuration` object via the `validate()` method.
+//!
+//! This mechanism is chosen because we might want to be able to do validation on the configuration
+//! that is not possible to do with TOML itself.
+//!
+
+mod configuration;
+pub use configuration::*;
+
+mod container_config;
+pub use container_config::*;
+
+mod docker_config;
+pub use docker_config::*;
+
+mod endpoint_config;
+pub use endpoint_config::*;
+
+mod not_validated;
+pub use not_validated::*;
+
+mod util;
diff --git a/src/config/not_validated.rs b/src/config/not_validated.rs
new file mode 100644
index 0000000..6764578
--- /dev/null
+++ b/src/config/not_validated.rs
@@ -0,0 +1,79 @@
+use std::path::PathBuf;
+use anyhow::Result;
+use getset::Getters;
+use handlebars::Handlebars;
+use serde::Deserialize;
+
+use crate::config::Configuration;
+use crate::config::ContainerConfig;
+use crate::config::DockerConfig;
+use crate::config::util::*;
+use crate::phase::PhaseName;
+
+#[derive(Debug, Getters, Deserialize)]
+pub struct NotValidatedConfiguration {
+ #[getset(get = "pub")]
+ repository: PathBuf,
+
+ #[serde(default = "default_progress_format")]
+ #[getset(get = "pub")]
+ progress_format: String,
+
+ #[serde(default = "default_package_print_format")]
+ #[getset(get = "pub")]
+ package_print_format: String,
+
+ #[serde(rename = "releases")]
+ releases_directory: String,
+
+ #[serde(rename = "staging")]
+ staging_directory: String,
+
+ #[getset(get = "pub")]
+ #[serde(rename = "database_host")]
+ database_host: String,
+
+ #[getset(get = "pub")]
+ #[serde(rename = "database_port")]
+ database_port: String,
+
+ #[getset(get = "pub")]
+ #[serde(rename = "database_user")]
+ database_user: String,
+
+ #[getset(get = "pub")]
+ #[serde(rename = "database_password")]
+ database_password: String,
+
+ #[getset(get = "pub")]
+ #[serde(rename = "database_name")]
+ database_name: String,
+
+ #[getset(get = "pub")]
+ docker: DockerConfig,
+
+ #[getset(get = "pub")]
+ containers: ContainerConfig,
+
+ #[getset(get = "pub")]
+ available_phases: Vec<PhaseName>,
+}
+
+impl<'reg> NotValidatedConfiguration {
+ pub fn validate(self) -> Result<Configuration<'reg>> {
+ // TODO: Implement proper validation
+
+ let hb = {
+ let mut hb = Handlebars::new();
+ hb.register_template_string("releases", &self.releases_directory)?;
+ hb.register_template_string("staging", &self.staging_directory)?;
+ hb
+ };
+
+ Ok(Configuration {
+ inner: self,
+ hb,
+ })
+ }
+}
+
diff --git a/src/config/util.rs b/src/config/util.rs
new file mode 100644
index 0000000..8cae2d7
--- /dev/null
+++ b/src/config/util.rs
@@ -0,0 +1,17 @@
+pub fn default_progress_format() -> String {
+ String::from("[{elapsed_precise}] ({percent:>3}%): {bar:40.cyan/blue} | {msg}")
+}
+
+pub fn default_package_print_format() -> String {
+ String::from(indoc::indoc!(r#"
+ {{i}} - {{name}} : {{version}}
+ Source: {{source_url}}
+ Hash ({{source_hash_type}}): {{source_hash}}"
+ {{#if print_system_deps}}System Deps: {{ system_deps }} {{/if}}
+ {{#if print_system_runtime_deps}}System runtime Deps: {{ system_runtime_deps }} {{/if}}
+ {{#if print_build_deps}}Build Deps: {{ build_deps }} {{/if}}
+ {{#if print_runtime_deps}}Runtime Deps: {{ runtime_deps }} {{/if}}
+
+ "#))
+}
+