Skip to content

Commit 173a685

Browse files
committed
feat: Add basic user config reading mechanism
1 parent 545748b commit 173a685

File tree

7 files changed

+222
-15
lines changed

7 files changed

+222
-15
lines changed

Cargo.lock

Lines changed: 31 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.nix

Lines changed: 102 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ stackable-operator = { git = "https://github.com/stackabletech/operator-rs.git",
5353
tera = "1.20"
5454
termion = "4.0"
5555
tokio = { version = "1.38", features = ["rt-multi-thread", "macros", "fs", "process", "io-std"] }
56+
toml = { version = "0.9.8", features = ["serde"] }
5657
tower-http = { version = "0.5", features = ["validate-request"] }
5758
tracing = "0.1"
5859
tracing-indicatif = "0.3.9"

rust/stackablectl/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ serde.workspace = true
3030
snafu.workspace = true
3131
tera.workspace = true
3232
tokio.workspace = true
33+
toml.workspace = true
3334
tracing-subscriber.workspace = true
3435
tracing.workspace = true
3536
tracing-indicatif.workspace = true

rust/stackablectl/src/cli/mod.rs

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
use std::env;
1+
use std::{env, path::Path};
22

33
use clap::{Parser, Subcommand, ValueEnum};
44
use directories::ProjectDirs;
5-
use snafu::{ResultExt, Snafu};
5+
use snafu::{OptionExt, ResultExt, Snafu};
66
use stackable_cockpit::{
77
constants::{HELM_REPO_NAME_DEV, HELM_REPO_NAME_STABLE, HELM_REPO_NAME_TEST},
88
helm,
@@ -19,6 +19,7 @@ use tracing::{Level, instrument};
1919
use crate::{
2020
args::{CommonFileArgs, CommonOperatorConfigsArgs, CommonRepoArgs},
2121
cmds::{cache, completions, debug, demo, operator, release, stack, stacklet},
22+
config::UserConfig,
2223
constants::{
2324
DEMOS_REPOSITORY_DEMOS_SUBPATH, DEMOS_REPOSITORY_STACKS_SUBPATH, DEMOS_REPOSITORY_URL_BASE,
2425
ENV_KEY_DEMO_FILES, ENV_KEY_RELEASE_FILES, ENV_KEY_STACK_FILES, REMOTE_RELEASE_FILE,
@@ -55,6 +56,9 @@ pub enum Error {
5556

5657
#[snafu(display("helm error"))]
5758
Helm { source: helm::Error },
59+
60+
#[snafu(display("failed to retrieve XDG directories"))]
61+
RetrieveXdgDirectories,
5862
}
5963

6064
#[derive(Debug, Parser)]
@@ -148,27 +152,29 @@ impl Cli {
148152
Ok(())
149153
}
150154

151-
pub fn cache_settings(&self) -> Result<Settings, CacheSettingsError> {
155+
fn cache_settings(&self, cache_directory: &Path) -> Result<Settings, CacheSettingsError> {
152156
if self.no_cache {
153157
tracing::debug!("Cache disabled");
154158
Ok(Settings::disabled())
155159
} else {
156-
let project_dir = ProjectDirs::from(
157-
USER_DIR_QUALIFIER,
158-
USER_DIR_ORGANIZATION_NAME,
159-
USER_DIR_APPLICATION_NAME,
160-
)
161-
.ok_or(CacheSettingsError::UserDir)?;
162-
163-
let cache_dir = project_dir.cache_dir();
164160
tracing::debug!(
165-
cache_dir = %cache_dir.to_string_lossy(),
161+
cache_directory = %cache_directory.to_string_lossy(),
166162
"Setting cache directory"
167163
);
168-
Ok(Settings::disk(cache_dir))
164+
Ok(Settings::disk(cache_directory))
169165
}
170166
}
171167

168+
#[allow(clippy::result_large_err)]
169+
fn xdg_directories() -> Result<ProjectDirs, Error> {
170+
ProjectDirs::from(
171+
USER_DIR_QUALIFIER,
172+
USER_DIR_ORGANIZATION_NAME,
173+
USER_DIR_APPLICATION_NAME,
174+
)
175+
.context(RetrieveXdgDirectoriesSnafu)
176+
}
177+
172178
#[instrument(skip_all)]
173179
pub async fn run(&self) -> Result<String, Error> {
174180
// FIXME (Techassi): There might be a better way to handle this with
@@ -181,8 +187,16 @@ impl Cli {
181187
_ => self.add_helm_repos().context(HelmSnafu)?,
182188
}
183189

190+
let xdg_directories = Cli::xdg_directories()?;
191+
let user_config_path = xdg_directories.config_dir().join("config.toml");
192+
193+
let _user_config = UserConfig::from_file(user_config_path)
194+
.unwrap()
195+
.unwrap_or_default();
196+
dbg!(_user_config);
197+
184198
let cache = self
185-
.cache_settings()
199+
.cache_settings(xdg_directories.cache_dir())
186200
.unwrap()
187201
.try_into_cache()
188202
.await

rust/stackablectl/src/config.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
use std::path::{Path, PathBuf};
2+
3+
use serde::Deserialize;
4+
use snafu::{ResultExt, Snafu};
5+
6+
#[derive(Debug, Default, Deserialize)]
7+
pub struct UserConfig {
8+
pub version: VersionOptions,
9+
}
10+
11+
#[derive(Debug, Deserialize)]
12+
pub struct VersionOptions {
13+
pub check_enabled: bool,
14+
}
15+
16+
#[derive(Debug, Snafu)]
17+
pub enum Error {
18+
#[snafu(display("failed to read config file from {path}", path = path.display()))]
19+
Read {
20+
source: std::io::Error,
21+
path: PathBuf,
22+
},
23+
24+
#[snafu(display("failed to deserialize config file located at {path} as TOML", path = path.display()))]
25+
Deserialize {
26+
source: toml::de::Error,
27+
path: PathBuf,
28+
},
29+
}
30+
31+
impl UserConfig {
32+
pub fn from_file<P>(path: P) -> Result<Option<Self>, Error>
33+
where
34+
P: AsRef<Path>,
35+
{
36+
let path = path.as_ref();
37+
38+
match std::fs::read_to_string(path) {
39+
Ok(contents) => {
40+
let config = toml::from_str(&contents).context(DeserializeSnafu { path })?;
41+
Ok(Some(config))
42+
}
43+
Err(err) if err.kind() == std::io::ErrorKind::NotFound => Ok(None),
44+
Err(err) => Err(Error::Read {
45+
path: path.to_path_buf(),
46+
source: err,
47+
}),
48+
}
49+
}
50+
}
51+
52+
impl Default for VersionOptions {
53+
fn default() -> Self {
54+
Self {
55+
check_enabled: true,
56+
}
57+
}
58+
}

rust/stackablectl/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
pub mod args;
22
pub mod cli;
33
pub mod cmds;
4+
pub mod config;
45
pub mod constants;
56
pub mod output;
67
pub mod utils;

0 commit comments

Comments
 (0)