Skip to main content

summer_pubsub/
config.rs

1use anyhow::Context;
2use google_cloud_auth::credentials::AccessTokenCredentials;
3use google_cloud_auth::credentials::{
4    external_account, impersonated, service_account, user_account, Credentials,
5};
6use schemars::JsonSchema;
7use serde::Deserialize;
8use serde_json::Value;
9use summer::config::Configurable;
10
11summer::submit_config_schema!("pubsub", PubSubConfig);
12
13#[derive(Debug, Configurable, Clone, JsonSchema, Deserialize)]
14#[config_prefix = "pubsub"]
15pub struct PubSubConfig {
16    /// When false, the plugin does not connect to Pub/Sub or register consumers.
17    #[serde(default = "default_enabled")]
18    pub enabled: bool,
19    /// GCP project id used to expand short subscription and topic names.
20    pub project_id: String,
21    /// Optional API endpoint (for example the Pub/Sub emulator).
22    pub endpoint: Option<String>,
23    /// Optional path to a service account or ADC JSON key file.
24    pub credentials: Option<String>,
25}
26
27fn default_enabled() -> bool {
28    true
29}
30
31pub fn credentials_from_json_value(json: Value) -> anyhow::Result<Credentials> {
32    let cred_type = json
33        .get("type")
34        .and_then(|v| v.as_str())
35        .context("credential JSON missing string field `type`")?;
36    let atc: AccessTokenCredentials = match cred_type {
37        "authorized_user" => user_account::Builder::new(json)
38            .build_access_token_credentials()
39            .map_err(|e| anyhow::anyhow!("{e}"))?,
40        "service_account" => service_account::Builder::new(json)
41            .build_access_token_credentials()
42            .map_err(|e| anyhow::anyhow!("{e}"))?,
43        "external_account" => external_account::Builder::new(json)
44            .build_access_token_credentials()
45            .map_err(|e| anyhow::anyhow!("{e}"))?,
46        "impersonated_service_account" => impersonated::Builder::new(json)
47            .build_access_token_credentials()
48            .map_err(|e| anyhow::anyhow!("{e}"))?,
49        other => anyhow::bail!("unsupported credential type: {other}"),
50    };
51    Ok(atc.into())
52}
53
54pub fn credentials_from_file(path: &str) -> anyhow::Result<Credentials> {
55    let raw = std::fs::read_to_string(path)
56        .with_context(|| format!("read pubsub credentials file {path}"))?;
57    let json: Value = serde_json::from_str(&raw).context("parse credentials JSON")?;
58    credentials_from_json_value(json)
59}