Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Minor updates to match CLI #406

Merged
merged 4 commits into from
Mar 12, 2025
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
2 changes: 1 addition & 1 deletion gel-dsn/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "gel-dsn"
license = "MIT/Apache-2.0"
version = "0.1.0"
version = "0.1.1"
authors = ["MagicStack Inc. <[email protected]>"]
edition = "2021"
description = "Data-source name (DSN) parser for Gel and PostgreSQL databases."
Expand Down
10 changes: 8 additions & 2 deletions gel-dsn/src/gel/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -658,11 +658,17 @@ impl TryInto<Params> for ConnectionOptions {
}

if self.tls_ca.is_some() && self.tls_ca_file.is_some() {
return Err(ParseError::ExclusiveOptions);
return Err(ParseError::ExclusiveOptions(
"tls_ca".to_string(),
"tls_ca_file".to_string(),
));
}

if self.branch.is_some() && self.database.is_some() {
return Err(ParseError::ExclusiveOptions);
return Err(ParseError::ExclusiveOptions(
"branch".to_string(),
"database".to_string(),
));
}

let mut credentials = Param::from_file(self.credentials_file.clone());
Expand Down
5 changes: 3 additions & 2 deletions gel-dsn/src/gel/env.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use super::{
error::*, BuildContext, ClientSecurity, CloudCerts, FromParamStr, InstanceName, TlsSecurity,
error::*, BuildContext, ClientSecurity, CloudCerts, FromParamStr, InstanceName, ParamSource,
TlsSecurity,
};
use crate::host::HostType;
use crate::EnvVar;
Expand Down Expand Up @@ -186,7 +187,7 @@ pub fn get_envs(
Err(std::env::VarError::NotPresent) => continue,
Err(err @ std::env::VarError::NotUnicode(_)) => {
return Err(ParseError::EnvNotFound(
EnvironmentSource::Explicit,
ParamSource::Explicit,
err.to_string(),
));
}
Expand Down
44 changes: 23 additions & 21 deletions gel-dsn/src/gel/error.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use crate::host::HostParseError;
use std::{convert::Infallible, num::ParseIntError};

use super::ParamSource;

#[derive(Debug, Clone, PartialEq, Eq, derive_more::Display, PartialOrd, Ord)]
pub enum CompoundSource {
Dsn,
Expand Down Expand Up @@ -46,22 +48,14 @@ pub enum InvalidDsnError {
BranchAndDatabase,
}

#[derive(Debug, Clone, PartialEq, Eq, derive_more::Display, PartialOrd, Ord)]
pub enum EnvironmentSource {
#[display("Explicit")]
Explicit,
#[display("Param::Env")]
Param,
}

#[derive(Debug, derive_more::Error, derive_more::Display, PartialEq, Eq, PartialOrd, Ord)]
pub enum ParseError {
#[display("Credentials file not found")]
CredentialsFileNotFound,
#[display("Environment variable not found: {_1} ({_0})")]
EnvNotFound(EnvironmentSource, #[error(not(source))] String),
#[display("Exclusive options")]
ExclusiveOptions,
#[display("Environment variable was not set: {_1} (from {_0})")]
EnvNotFound(ParamSource, #[error(not(source))] String),
#[display("{_0} and {_1} are mutually exclusive and cannot be used together")]
ExclusiveOptions(String, String),
#[display("File not found")]
FileNotFound,
#[display("Invalid credentials file: {_0}")]
Expand Down Expand Up @@ -94,7 +88,7 @@ pub enum ParseError {
MultipleCompoundOpts(#[error(not(source))] Vec<CompoundSource>),
#[display("No options or .toml file")]
NoOptionsOrToml,
#[display("Project not initialised")]
#[display("Project not initialized")]
ProjectNotInitialised,
#[display("Secret key not found")]
SecretKeyNotFound,
Expand All @@ -107,7 +101,7 @@ impl ParseError {
match self {
Self::EnvNotFound(..) => "env_not_found",
Self::CredentialsFileNotFound => "credentials_file_not_found",
Self::ExclusiveOptions => "exclusive_options",
Self::ExclusiveOptions(..) => "exclusive_options",
Self::FileNotFound => "file_not_found",
Self::InvalidCredentialsFile(_) => "invalid_credentials_file",
Self::InvalidDatabase => "invalid_database",
Expand Down Expand Up @@ -136,7 +130,6 @@ impl ParseError {
match self {
Self::EnvNotFound(..)
| Self::CredentialsFileNotFound
| Self::ExclusiveOptions
| Self::FileNotFound
| Self::InvalidCredentialsFile(_)
| Self::InvalidDatabase
Expand All @@ -150,15 +143,24 @@ impl ParseError {
| Self::InvalidUser
| Self::InvalidCertificate
| Self::InvalidDuration
| Self::MultipleCompoundEnv(_)
| Self::MultipleCompoundOpts(_)
| Self::NoOptionsOrToml
| Self::ProjectNotInitialised
| Self::UnixSocketUnsupported => {
// The argument is invalid
gel_errors::InvalidArgumentError::with_source(self)
}
Self::MultipleCompoundEnv(_)
| Self::MultipleCompoundOpts(_)
| Self::ExclusiveOptions(..) => {
// The argument is valid, but the use is invalid
gel_errors::InterfaceError::with_source(self)
}
Self::NoOptionsOrToml | Self::ProjectNotInitialised => {
// Credentials are missing
gel_errors::ClientNoCredentialsError::with_source(self)
}

Self::SecretKeyNotFound => gel_errors::NoCloudConfigFound::with_source(self),
Self::SecretKeyNotFound => {
// Required cloud configuration is missing
gel_errors::NoCloudConfigFound::with_source(self)
}
}
}
}
Expand Down
32 changes: 18 additions & 14 deletions gel-dsn/src/gel/param.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,15 +152,23 @@ pub enum Param<T: Clone> {
/// Unparsed value.
Unparsed(String),
/// Value from given environment variable.
Env(String),
Env(ParamSource, String),
/// Value from given file.
File(PathBuf),
/// Value from environment variable pointing to a file.
EnvFile(String),
EnvFile(ParamSource, String),
/// Parsed value.
Parsed(T),
}

#[derive(Debug, Copy, Clone, derive_more::Display, PartialEq, Eq, PartialOrd, Ord)]
pub enum ParamSource {
#[display("DSN")]
Dsn,
#[display("explicit")]
Explicit,
}

#[allow(private_bounds)]
impl<T: Clone> Param<T>
where
Expand Down Expand Up @@ -199,9 +207,9 @@ where
match self {
Self::None => Ok(Param::None),
Self::Unparsed(value) => Ok(Param::Unparsed(value)),
Self::Env(value) => Ok(Param::Env(value)),
Self::Env(source, value) => Ok(Param::Env(source, value)),
Self::File(value) => Ok(Param::File(value)),
Self::EnvFile(value) => Ok(Param::EnvFile(value)),
Self::EnvFile(source, value) => Ok(Param::EnvFile(source, value)),
Self::Parsed(value) => Err(Self::Parsed(value)),
}
}
Expand All @@ -212,15 +220,13 @@ where
return Ok(None);
}
Self::Unparsed(value) => value.clone(),
Self::Env(key) => {
context_trace!(context, "Reading env: {key}");
Self::Env(source, key) => {
context_trace!(context, "Reading env: {key} (from {source})");
context
.env()
.read(key)
.map(|s| s.to_string())
.map_err(|_| {
ParseError::EnvNotFound(EnvironmentSource::Param, key.to_string())
})?
.map_err(|_| ParseError::EnvNotFound(*source, key.to_string()))?
}
Self::File(path) => {
context_trace!(context, "Reading file: {path:?}");
Expand All @@ -232,14 +238,12 @@ where
context_trace!(context, "File content: {res:?}");
res?
}
Self::EnvFile(key) => {
context_trace!(context, "Reading env for file: {key}");
Self::EnvFile(source, key) => {
context_trace!(context, "Reading env for file: {key} (from {source})");
let env = context
.env()
.read(key)
.map_err(|_| {
ParseError::EnvNotFound(EnvironmentSource::Param, key.to_string())
})?
.map_err(|_| ParseError::EnvNotFound(*source, key.to_string()))?
.to_string();
context_trace!(context, "Reading file: {env}");
let res = context
Expand Down
Loading