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

Add app config #30

Merged
merged 1 commit into from
Oct 30, 2023
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
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.8.0] - 2023-10-26
## [0.10.0] - 2023-10-29
### Added
- Introduced a config file allowing to configure the list of supported auth providers

## [0.9.0] - 2023-10-26
### Added
- FlightSQL endpoint

Expand Down
94 changes: 91 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ kamu-adapter-flight-sql = { git = "https://github.com/kamu-data/kamu-cli", tag =


[workspace.package]
version = "0.9.0"
version = "0.10.0"
edition = "2021"
homepage = "https://github.com/kamu-data/kamu-platform"
repository = "https://github.com/kamu-data/kamu-platform"
Expand Down
2 changes: 1 addition & 1 deletion LICENSE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Additional Use Grant: You may use the Licensed Work for any purpose,
Licensed Work where data or transformations are
controlled by such third parties.

Change Date: 2027-10-26
Change Date: 2027-10-29

Change License: Apache License, Version 2.0

Expand Down
3 changes: 2 additions & 1 deletion src/app/api-server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,10 @@ async-trait = { version = "0.1", default-features = false }
chrono = "0.4"
clap = "4"
datafusion = "31"
figment = { version = "0.10", features = ["env", "yaml", "json"] }
futures = "0.3"
indoc = "2"
serde = "1"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
tempfile = "3"
tokio = { version = "1", default-features = false, features = ["macros"] }
Expand Down
57 changes: 51 additions & 6 deletions src/app/api-server/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ use kamu::utils::smart_transfer_protocol::SmartTransferProtocolClient;
use tracing::info;
use url::Url;

use crate::config::{ApiServerConfig, AuthProviderConfig};
use crate::dummy_auth_provider::DummyAuthProvider;

/////////////////////////////////////////////////////////////////////////////////////////

pub const BINARY_NAME: &str = env!("CARGO_PKG_NAME");
Expand All @@ -27,6 +30,8 @@ const DEFAULT_LOGGING_CONFIG: &str = "info,tower_http=trace";
pub async fn run(matches: clap::ArgMatches) -> Result<(), InternalError> {
init_logging();

let config = load_config(matches.get_one("config"))?;

let repo_url = if let Some(repo_url) = matches.get_one::<Url>("repo-url").cloned() {
repo_url
} else {
Expand All @@ -51,7 +56,9 @@ pub async fn run(matches: clap::ArgMatches) -> Result<(), InternalError> {
BINARY_NAME
);

let catalog = init_dependencies(&repo_url, local_dir.path()).await.build();
let catalog = init_dependencies(config, &repo_url, local_dir.path())
.await
.build();

match matches.subcommand() {
Some(("gql", sub)) => match sub.subcommand() {
Expand Down Expand Up @@ -145,7 +152,29 @@ fn init_logging() {

/////////////////////////////////////////////////////////////////////////////////////////

pub async fn init_dependencies(repo_url: &Url, local_dir: &Path) -> CatalogBuilder {
pub fn load_config(path: Option<&PathBuf>) -> Result<ApiServerConfig, InternalError> {
use figment::providers::Format;

let Some(path) = path else {
return Ok(ApiServerConfig::default());
};

figment::Figment::from(figment::providers::Serialized::defaults(
ApiServerConfig::default(),
))
.merge(figment::providers::Yaml::file(path))
.merge(figment::providers::Env::prefixed("KAMU_API_SERVER_").lowercase(false))
.extract()
.int_err()
}

/////////////////////////////////////////////////////////////////////////////////////////

pub async fn init_dependencies(
config: ApiServerConfig,
repo_url: &Url,
local_dir: &Path,
) -> CatalogBuilder {
let mut b = dill::CatalogBuilder::new();

// TODO: Improve output multiplexing and cache interface
Expand Down Expand Up @@ -256,8 +285,8 @@ pub async fn init_dependencies(repo_url: &Url, local_dir: &Path) -> CatalogBuild
b.add::<kamu::ObjectStoreBuilderLocalFs>();
b.bind::<dyn kamu::domain::ObjectStoreBuilder, kamu::ObjectStoreBuilderLocalFs>();

b.add::<crate::builtin_authentication_provider::BuiltinAuthenticationProvider>();
b.bind::<dyn kamu::domain::auth::AuthenticationProvider, crate::builtin_authentication_provider::BuiltinAuthenticationProvider>();
b.add_value(DummyAuthProvider::new_with_default_account());
b.bind::<dyn kamu::domain::auth::AuthenticationProvider, DummyAuthProvider>();
}
"s3" | "s3+http" | "s3+https" => {
let s3_context = kamu::utils::s3_context::S3Context::from_url(&repo_url).await;
Expand All @@ -272,8 +301,24 @@ pub async fn init_dependencies(repo_url: &Url, local_dir: &Path) -> CatalogBuild
b.add_value(kamu::ObjectStoreBuilderS3::new(s3_context, false))
.bind::<dyn kamu::domain::ObjectStoreBuilder, kamu::ObjectStoreBuilderS3>();

b.add::<kamu_adapter_oauth::OAuthGithub>();
b.bind::<dyn kamu::domain::auth::AuthenticationProvider, kamu_adapter_oauth::OAuthGithub>();
// Default to GitHub auth
if config.auth.providers.is_empty() {
b.add::<kamu_adapter_oauth::OAuthGithub>();
b.bind::<dyn kamu::domain::auth::AuthenticationProvider, kamu_adapter_oauth::OAuthGithub>();
}

for provider in config.auth.providers {
match provider {
AuthProviderConfig::Github(_) => {
b.add::<kamu_adapter_oauth::OAuthGithub>();
b.bind::<dyn kamu::domain::auth::AuthenticationProvider, kamu_adapter_oauth::OAuthGithub>();
}
AuthProviderConfig::Dummy(prov) => {
b.add_value(DummyAuthProvider::new(prov.accounts));
b.bind::<dyn kamu::domain::auth::AuthenticationProvider, DummyAuthProvider>();
}
}
}
}
_ => panic!("Unsupported repository scheme: {}", repo_url.scheme()),
}
Expand Down
14 changes: 10 additions & 4 deletions src/app/api-server/src/cli_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,16 @@ pub fn cli() -> Command {
kamu-api-server <command> <sub-command> -h
"
))
.args([Arg::new("repo-url")
.long("repo-url")
.value_parser(value_parse_repo_url)
.help("URL of the remote dataset repository")])
.args([
Arg::new("config")
.long("config")
.value_parser(value_parser!(std::path::PathBuf))
.help("Path to the config file"),
Arg::new("repo-url")
.long("repo-url")
.value_parser(value_parse_repo_url)
.help("URL of the remote dataset repository"),
])
.subcommands([
Command::new("run").about("Run the server").args([
Arg::new("address")
Expand Down
50 changes: 50 additions & 0 deletions src/app/api-server/src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright Kamu Data, Inc. and contributors. All rights reserved.
//
// Use of this software is governed by the Business Source License
// included in the LICENSE file.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0.

use serde::{Deserialize, Serialize};

/////////////////////////////////////////////////////////////////////////////////////////

#[derive(Debug, Default, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ApiServerConfig {
pub auth: AuthConfig,
}

/////////////////////////////////////////////////////////////////////////////////////////

#[derive(Debug, Default, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AuthConfig {
pub providers: Vec<AuthProviderConfig>,
}

/////////////////////////////////////////////////////////////////////////////////////////

#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[serde(tag = "kind")]
pub enum AuthProviderConfig {
Github(AuthProviderConfigGitHub),
Dummy(AuthProviderConfigDummy),
}

/////////////////////////////////////////////////////////////////////////////////////////

#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AuthProviderConfigGitHub {}

/////////////////////////////////////////////////////////////////////////////////////////

#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AuthProviderConfigDummy {
pub accounts: Vec<kamu::domain::auth::AccountInfo>,
}
Loading
Loading