summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2021-03-11 11:47:56 +0100
committerMatthias Beyer <mail@beyermatthias.de>2021-03-11 11:47:56 +0100
commit5ca0dbdf1b13eda96a074d0a2d29dffcb5e60b25 (patch)
treedc2b47b17560d1d87c0300e62ff0331dbbdc54e7
parentb95c3f21a2a9406d45a0e421a11f6425291f1182 (diff)
parent540647ef5e911dc931092ecc420de6db1019707f (diff)
Merge branch 'xdg-config'
-rw-r--r--Cargo.toml1
-rw-r--r--config.toml3
-rw-r--r--examples/packages/repo/config.toml6
-rw-r--r--src/commands/build.rs6
-rw-r--r--src/commands/endpoint.rs28
-rw-r--r--src/commands/endpoint_container.rs3
-rw-r--r--src/config/docker_config.rs5
-rw-r--r--src/config/endpoint_config.rs27
-rw-r--r--src/db/models/endpoint.rs7
-rw-r--r--src/endpoint/configuration.rs3
-rw-r--r--src/endpoint/configured.rs19
-rw-r--r--src/main.rs24
12 files changed, 88 insertions, 44 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 58da28f..0f36ca3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -61,6 +61,7 @@ url = { version = "2", features = ["serde"] }
uuid = { version = "0.6", features = ["serde", "v4"] }
walkdir = "2"
which = "4"
+xdg = "2"
# Hard-code rand to 0.4.4
#
diff --git a/config.toml b/config.toml
index 15843de..46fc7cc 100644
--- a/config.toml
+++ b/config.toml
@@ -170,8 +170,7 @@ verify_images_present = true
# List of docker endpoints
#
-[[docker.endpoints]]
-name = "testhostname"
+[docker.endpoints.testhostname]
uri = "http://0.0.0.0:8095" # the URI of the endpoint. Either http or socket path
endpoint_type = "http" # either "http" or "socket"
diff --git a/examples/packages/repo/config.toml b/examples/packages/repo/config.toml
index 34fb996..5701f5c 100644
--- a/examples/packages/repo/config.toml
+++ b/examples/packages/repo/config.toml
@@ -40,11 +40,9 @@ images = [ "debian:bullseye" ]
verify_images_present = true
#
-# List of docker endpoints
+# Docker endpoints
#
-
-[[docker.endpoints]]
-name = "testhostname"
+[docker.endpoints.testhostname]
uri = "http://0.0.0.0:8095" # the URI of the endpoint. Either http or socket path
endpoint_type = "http" # either "http" or "socket"
speed = 1 # currently ignored, but required to be present
diff --git a/src/commands/build.rs b/src/commands/build.rs
index 9880552..81077d4 100644
--- a/src/commands/build.rs
+++ b/src/commands/build.rs
@@ -102,10 +102,10 @@ pub async fn build(
.docker()
.endpoints()
.iter()
- .cloned()
- .map(|ep_cfg| {
+ .map(|(ep_name, ep_cfg)| {
crate::endpoint::EndpointConfiguration::builder()
- .endpoint(ep_cfg)
+ .endpoint_name(ep_name.clone())
+ .endpoint(ep_cfg.clone())
.required_images(config.docker().images().clone())
.required_docker_versions(config.docker().docker_versions().clone())
.required_docker_api_versions(config.docker().docker_api_versions().clone())
diff --git a/src/commands/endpoint.rs b/src/commands/endpoint.rs
index c1632e6..5338978 100644
--- a/src/commands/endpoint.rs
+++ b/src/commands/endpoint.rs
@@ -20,6 +20,7 @@ use itertools::Itertools;
use tokio_stream::StreamExt;
use crate::config::Configuration;
+use crate::config::EndpointName;
use crate::util::progress::ProgressBars;
use crate::endpoint::Endpoint;
@@ -27,12 +28,13 @@ pub async fn endpoint(matches: &ArgMatches, config: &Configuration, progress_gen
let endpoint_names = matches
.value_of("endpoint_name")
.map(String::from)
+ .map(EndpointName::from)
.map(|ep| vec![ep])
.unwrap_or_else(|| {
config.docker()
.endpoints()
.iter()
- .map(|ep| ep.name())
+ .map(|(ep_name, _)| ep_name)
.cloned()
.collect()
});
@@ -47,7 +49,7 @@ pub async fn endpoint(matches: &ArgMatches, config: &Configuration, progress_gen
}
}
-async fn ping(endpoint_names: Vec<String>,
+async fn ping(endpoint_names: Vec<EndpointName>,
matches: &ArgMatches,
config: &Configuration,
progress_generator: ProgressBars
@@ -94,7 +96,7 @@ async fn ping(endpoint_names: Vec<String>,
tokio::join!(ping_process, multibar_block).0
}
-async fn stats(endpoint_names: Vec<String>,
+async fn stats(endpoint_names: Vec<EndpointName>,
matches: &ArgMatches,
config: &Configuration,
progress_generator: ProgressBars
@@ -155,7 +157,7 @@ async fn stats(endpoint_names: Vec<String>,
}
-async fn containers(endpoint_names: Vec<String>,
+async fn containers(endpoint_names: Vec<EndpointName>,
matches: &ArgMatches,
config: &Configuration,
) -> Result<()> {
@@ -167,7 +169,7 @@ async fn containers(endpoint_names: Vec<String>,
}
}
-async fn containers_list(endpoint_names: Vec<String>,
+async fn containers_list(endpoint_names: Vec<EndpointName>,
matches: &ArgMatches,
config: &Configuration,
) -> Result<()> {
@@ -204,7 +206,7 @@ async fn containers_list(endpoint_names: Vec<String>,
.filter(|stat| newer_than_filter.as_ref().map(|time| time < &stat.created).unwrap_or(true))
.map(|stat| {
vec![
- endpoint_name.clone(),
+ endpoint_name.as_ref().to_owned(),
stat.id,
stat.image,
stat.created.to_string(),
@@ -219,7 +221,7 @@ async fn containers_list(endpoint_names: Vec<String>,
crate::commands::util::display_data(hdr, data, csv)
}
-async fn containers_prune(endpoint_names: Vec<String>,
+async fn containers_prune(endpoint_names: Vec<EndpointName>,
matches: &ArgMatches,
config: &Configuration,
) -> Result<()> {
@@ -274,16 +276,16 @@ fn get_date_filter(name: &str, matches: &ArgMatches) -> Result<Option<chrono::Da
/// Helper function to connect to all endpoints from the configuration, that appear (by name) in
/// the `endpoint_names` list
-pub(super) async fn connect_to_endpoints(config: &Configuration, endpoint_names: &[String]) -> Result<Vec<Arc<Endpoint>>> {
+pub(super) async fn connect_to_endpoints(config: &Configuration, endpoint_names: &[EndpointName]) -> Result<Vec<Arc<Endpoint>>> {
let endpoint_configurations = config
.docker()
.endpoints()
.iter()
- .filter(|ep| endpoint_names.contains(ep.name()))
- .cloned()
- .map(|ep_cfg| {
+ .filter(|(ep_name, _)| endpoint_names.contains(ep_name))
+ .map(|(ep_name, ep_cfg)| {
crate::endpoint::EndpointConfiguration::builder()
- .endpoint(ep_cfg)
+ .endpoint_name(ep_name.clone())
+ .endpoint(ep_cfg.clone())
.required_images(config.docker().images().clone())
.required_docker_versions(config.docker().docker_versions().clone())
.required_docker_api_versions(config.docker().docker_api_versions().clone())
@@ -294,7 +296,7 @@ pub(super) async fn connect_to_endpoints(config: &Configuration, endpoint_names:
info!("Endpoint config build");
info!("Connecting to {n} endpoints: {eps}",
n = endpoint_configurations.len(),
- eps = endpoint_configurations.iter().map(|epc| epc.endpoint().name()).join(", "));
+ eps = endpoint_configurations.iter().map(|epc| epc.endpoint_name()).join(", "));
crate::endpoint::util::setup_endpoints(endpoint_configurations).await
}
diff --git a/src/commands/endpoint_container.rs b/src/commands/endpoint_container.rs
index 1861cc7..962b62c 100644
--- a/src/commands/endpoint_container.rs
+++ b/src/commands/endpoint_container.rs
@@ -18,8 +18,9 @@ use tokio_stream::StreamExt;
use shiplift::Container;
use crate::config::Configuration;
+use crate::config::EndpointName;
-pub async fn container(endpoint_names: Vec<String>,
+pub async fn container(endpoint_names: Vec<EndpointName>,
matches: &ArgMatches,
config: &Configuration,
) -> Result<()> {
diff --git a/src/config/docker_config.rs b/src/config/docker_config.rs
index 1cef561..f7cd1db 100644
--- a/src/config/docker_config.rs
+++ b/src/config/docker_config.rs
@@ -8,10 +8,13 @@
// SPDX-License-Identifier: EPL-2.0
//
+use std::collections::HashMap;
+
use getset::{CopyGetters, Getters};
use serde::Deserialize;
use crate::config::Endpoint;
+use crate::config::EndpointName;
use crate::util::docker::ImageName;
/// Configuration of the docker daemon interfacing functionality
@@ -48,5 +51,5 @@ pub struct DockerConfig {
images: Vec<ImageName>,
#[getset(get = "pub")]
- endpoints: Vec<Endpoint>,
+ endpoints: HashMap<EndpointName, Endpoint>,
}
diff --git a/src/config/endpoint_config.rs b/src/config/endpoint_config.rs
index 13db137..69405dc 100644
--- a/src/config/endpoint_config.rs
+++ b/src/config/endpoint_config.rs
@@ -11,13 +11,31 @@
use getset::{CopyGetters, Getters};
use serde::Deserialize;
+#[derive(Debug, Clone, Deserialize, Eq, PartialEq, Ord, PartialOrd, Hash)]
+#[serde(transparent)]
+pub struct EndpointName(String);
+
+impl From<String> for EndpointName {
+ fn from(s: String) -> Self {
+ EndpointName(s)
+ }
+}
+
+impl std::fmt::Display for EndpointName {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
+ self.0.fmt(f)
+ }
+}
+
+impl AsRef<str> for EndpointName {
+ fn as_ref(&self) -> &str {
+ self.0.as_ref()
+ }
+}
+
/// Configuration of a single endpoint
#[derive(Clone, Debug, Getters, CopyGetters, Deserialize)]
pub struct Endpoint {
- /// A human-readable name of the endpoint
- #[getset(get = "pub")]
- name: String,
-
/// The URI where the endpoint is reachable
#[getset(get = "pub")]
uri: String,
@@ -42,3 +60,4 @@ pub enum EndpointType {
#[serde(rename = "http")]
Http,
}
+
diff --git a/src/db/models/endpoint.rs b/src/db/models/endpoint.rs
index 73009f6..d7a7986 100644
--- a/src/db/models/endpoint.rs
+++ b/src/db/models/endpoint.rs
@@ -13,6 +13,7 @@ use anyhow::Result;
use diesel::prelude::*;
use diesel::PgConnection;
+use crate::config::EndpointName;
use crate::schema::endpoints;
use crate::schema::endpoints::*;
@@ -29,8 +30,8 @@ struct NewEndpoint<'a> {
}
impl Endpoint {
- pub fn create_or_fetch(database_connection: &PgConnection, ep_name: &str) -> Result<Endpoint> {
- let new_ep = NewEndpoint { name: ep_name };
+ pub fn create_or_fetch(database_connection: &PgConnection, ep_name: &EndpointName) -> Result<Endpoint> {
+ let new_ep = NewEndpoint { name: ep_name.as_ref() };
diesel::insert_into(endpoints::table)
.values(&new_ep)
@@ -38,7 +39,7 @@ impl Endpoint {
.execute(database_connection)?;
dsl::endpoints
- .filter(name.eq(ep_name))
+ .filter(name.eq(ep_name.as_ref()))
.first::<Endpoint>(database_connection)
.map_err(Error::from)
}
diff --git a/src/endpoint/configuration.rs b/src/endpoint/configuration.rs
index a9b4688..bdabd08 100644
--- a/src/endpoint/configuration.rs
+++ b/src/endpoint/configuration.rs
@@ -16,6 +16,9 @@ use crate::util::docker::ImageName;
#[derive(Getters, TypedBuilder)]
pub struct EndpointConfiguration {
#[getset(get = "pub")]
+ endpoint_name: crate::config::EndpointName,
+
+ #[getset(get = "pub")]
endpoint: crate::config::Endpoint,
#[getset(get = "pub")]
diff --git a/src/endpoint/configured.rs b/src/endpoint/configured.rs
index 7265dd6..f850ff6 100644
--- a/src/endpoint/configured.rs
+++ b/src/endpoint/configured.rs
@@ -28,6 +28,7 @@ use tokio::sync::RwLock;
use tokio_stream::StreamExt;
use typed_builder::TypedBuilder;
+use crate::config::EndpointName;
use crate::endpoint::EndpointConfiguration;
use crate::filestore::ReleaseStore;
use crate::filestore::StagingStore;
@@ -43,7 +44,7 @@ use crate::util::docker::ImageName;
#[derive(Getters, CopyGetters, TypedBuilder)]
pub struct Endpoint {
#[getset(get = "pub")]
- name: String,
+ name: EndpointName,
#[getset(get = "pub")]
docker: Docker,
@@ -69,10 +70,10 @@ impl Debug for Endpoint {
impl Endpoint {
pub(super) async fn setup(epc: EndpointConfiguration) -> Result<Self> {
- let ep = Endpoint::setup_endpoint(epc.endpoint()).with_context(|| {
+ let ep = Endpoint::setup_endpoint(epc.endpoint_name(), epc.endpoint()).with_context(|| {
anyhow!(
"Setting up endpoint: {} -> {}",
- epc.endpoint().name(),
+ epc.endpoint_name(),
epc.endpoint().uri()
)
})?;
@@ -89,21 +90,21 @@ impl Endpoint {
let _ = versions_compat.with_context(|| {
anyhow!(
"Checking version compatibility for {} -> {}",
- epc.endpoint().name(),
+ epc.endpoint_name(),
epc.endpoint().uri()
)
})?;
let _ = api_versions_compat.with_context(|| {
anyhow!(
"Checking API version compatibility for {} -> {}",
- epc.endpoint().name(),
+ epc.endpoint_name(),
epc.endpoint().uri()
)
})?;
let _ = imgs_avail.with_context(|| {
anyhow!(
"Checking for available images on {} -> {}",
- epc.endpoint().name(),
+ epc.endpoint_name(),
epc.endpoint().uri()
)
})?;
@@ -111,7 +112,7 @@ impl Endpoint {
Ok(ep)
}
- fn setup_endpoint(ep: &crate::config::Endpoint) -> Result<Endpoint> {
+ fn setup_endpoint(ep_name: &EndpointName, ep: &crate::config::Endpoint) -> Result<Endpoint> {
match ep.endpoint_type() {
crate::config::EndpointType::Http => shiplift::Uri::from_str(ep.uri())
.map(shiplift::Docker::host)
@@ -119,7 +120,7 @@ impl Endpoint {
.map_err(Error::from)
.map(|docker| {
Endpoint::builder()
- .name(ep.name().clone())
+ .name(ep_name.clone())
.uri(ep.uri().clone())
.docker(docker)
.num_max_jobs(ep.maxjobs())
@@ -129,7 +130,7 @@ impl Endpoint {
crate::config::EndpointType::Socket => Ok({
Endpoint::builder()
- .name(ep.name().clone())
+ .name(ep_name.clone())
.uri(ep.uri().clone())
.num_max_jobs(ep.maxjobs())
.network_mode(ep.network_mode().clone())
diff --git a/src/main.rs b/src/main.rs
index 9cfdfe2..1aaaefb 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -51,6 +51,7 @@ extern crate diesel;
use std::path::PathBuf;
use anyhow::anyhow;
+use anyhow::Context;
use anyhow::Result;
use clap::ArgMatches;
use logcrate::debug;
@@ -93,12 +94,27 @@ async fn main() -> Result<()> {
.ok_or_else(|| anyhow!("Not a repository with working directory. Cannot do my job!"))?;
let mut config = ::config::Config::default();
+ config.merge(::config::File::from(repo_path.join("config.toml")))
+ .context("Failed to load config.toml from repository")?;
+
+ {
+ let xdg = xdg::BaseDirectories::with_prefix("butido")?;
+ let xdg_config_file = xdg.find_config_file("config.toml");
+ if let Some(xdg_config) = xdg_config_file {
+ debug!("Configuration file found with XDG: {}", xdg_config.display());
+ config.merge(::config::File::from(xdg_config))
+ .context("Failed to load config.toml from XDG configuration directory")?;
+ } else {
+ debug!("No configuration file found with XDG: {}", xdg.get_config_home().display());
+ }
+ }
- config
- .merge(::config::File::from(repo_path.join("config.toml")))?
- .merge(::config::Environment::with_prefix("BUTIDO"))?;
+ config.merge(::config::Environment::with_prefix("BUTIDO"))?;
- let config = config.try_into::<NotValidatedConfiguration>()?.validate()?;
+ let config = config.try_into::<NotValidatedConfiguration>()
+ .context("Failed to load Configuration object")?
+ .validate()
+ .context("Failed to validate configuration")?;
let hide_bars = cli.is_present("hide_bars") || crate::util::stdout_is_pipe();
let progressbars = ProgressBars::setup(