athena_cli/
context.rs

1use crate::cli::{AwsArgs, DisplayArgs};
2use crate::config::Config;
3use anyhow::Result;
4use std::env;
5use std::sync::Arc;
6
7/// Holds all runtime context including config, CLI args, and AWS clients
8pub struct Context {
9    config: Config,
10    aws_args: AwsArgs,
11    display_args: DisplayArgs,
12    aws_config: Arc<aws_config::SdkConfig>,
13}
14
15impl Context {
16    pub async fn new(config: Config, aws_args: AwsArgs, display_args: DisplayArgs) -> Result<Self> {
17        let ctx = Self {
18            config,
19            aws_args,
20            display_args,
21            aws_config: Arc::new(aws_config::SdkConfig::builder().build()),
22        };
23
24        let aws_config = Arc::new(crate::aws::build_aws_config(ctx.profile(), ctx.region()).await?);
25
26        Ok(Self { aws_config, ..ctx })
27    }
28
29    pub fn profile(&self) -> Option<String> {
30        self.aws_args
31            .profile
32            .clone()
33            .or_else(|| env::var("AWS_PROFILE").ok())
34            .or_else(|| env::var("AWS_DEFAULT_PROFILE").ok())
35            .or_else(|| self.config.aws.profile.clone())
36    }
37
38    pub fn region(&self) -> String {
39        let region = self
40            .aws_args
41            .region
42            .as_ref()
43            .cloned()
44            .or_else(|| env::var("AWS_REGION").ok())
45            .or_else(|| self.config.aws.region.clone())
46            .unwrap_or_else(|| "eu-west-1".to_string());
47
48        region
49    }
50
51    pub fn database(&self) -> Option<String> {
52        self.aws_args
53            .database
54            .clone()
55            .or_else(|| env::var("AWS_ATHENA_DATABASE").ok())
56            .or_else(|| self.config.aws.database.clone())
57    }
58
59    pub fn workgroup(&self) -> String {
60        self.aws_args
61            .workgroup
62            .as_ref()
63            .cloned()
64            .or_else(|| env::var("AWS_ATHENA_WORKGROUP").ok())
65            .or_else(|| self.config.aws.workgroup.clone())
66            .unwrap_or_else(|| "primary".to_string())
67    }
68
69    pub fn catalog(&self) -> String {
70        self.aws_args
71            .catalog
72            .as_ref()
73            .cloned()
74            .or_else(|| env::var("AWS_ATHENA_CATALOG").ok())
75            .or_else(|| self.config.aws.catalog.clone())
76            .unwrap_or_else(|| "AwsDataCatalog".to_string())
77    }
78
79    pub fn output_location(&self) -> Option<String> {
80        self.aws_args
81            .output_location
82            .clone()
83            .or_else(|| env::var("AWS_ATHENA_OUTPUT_LOCATION").ok())
84            .or(Some(self.config.aws.output_location.clone()))
85    }
86
87    pub fn aws_config(&self) -> &aws_config::SdkConfig {
88        &self.aws_config
89    }
90
91    pub fn create_athena_client(&self) -> aws_sdk_athena::Client {
92        aws_sdk_athena::Client::new(&self.aws_config)
93    }
94
95    pub fn quiet(&self) -> bool {
96        self.display_args.quiet
97    }
98
99    pub fn history_size(&self) -> i32 {
100        self.config.app.history_size
101    }
102}