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

feat: add GrafanaConfig struct with a couple of useful keys #117

Merged
merged 1 commit into from
Sep 19, 2024
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

- Add `AppInstanceSettings::api_version` and `DataSourceInstanceSettings::api_version` fields.
- Add `PluginContext::grafana_config` field. This can be used to access a new struct,
`GrafanaConfig`, which contains the configuration passed to the plugin from Grafana.
Use the methods on `GrafanaConfig` to access the configuration.

### Changed

Expand Down
71 changes: 71 additions & 0 deletions crates/grafana-plugin-sdk/src/backend/grafana_config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
use std::collections::HashMap;

/// The error returned when Grafana does not provide a requested configuration option.
#[derive(Debug, Clone, thiserror::Error)]
#[error("key {key} not found in Grafana config; a more recent version of Grafana may be required")]
pub struct ConfigError {
key: String,
}

impl ConfigError {
fn from_key(key: String) -> Self {
Self { key }
}
}

type ConfigResult<T> = std::result::Result<T, ConfigError>;

/// Configuration passed to the plugin from Grafana.
#[derive(Clone)]
pub struct GrafanaConfig {
config: HashMap<String, String>,
}

impl GrafanaConfig {
const APP_URL: &'static str = "GF_APP_URL";
const APP_CLIENT_SECRET: &'static str = "GF_PLUGIN_APP_CLIENT_SECRET";
// const CONCURRENT_QUERY_COUNT: &'static str = "GF_CONCURRENT_QUERY_COUNT";
// const USER_FACING_DEFAULT_ERROR: &'static str = "GF_USER_FACING_DEFAULT_ERROR";
// const SQL_ROW_LIMIT: &'static str = "GF_SQL_ROW_LIMIT";
// const SQL_MAX_OPEN_CONNS_DEFAULT: &'static str = "GF_SQL_MAX_OPEN_CONNS_DEFAULT";
// const SQL_MAX_IDLE_CONNS_DEFAULT: &'static str = "GF_SQL_MAX_IDLE_CONNS_DEFAULT";
// const SQL_MAX_CONN_LIFETIME_SECONDS_DEFAULT: &'static str =
// "GF_SQL_MAX_CONN_LIFETIME_SECONDS_DEFAULT";
// const RESPONSE_LIMIT: &'static str = "GF_RESPONSE_LIMIT";

pub(crate) fn new(config: HashMap<String, String>) -> Self {
Self { config }
}

/// Get the value of a configuration option, if it was provided by Grafana.
fn get(&self, key: &str) -> ConfigResult<&String> {
self.config
.get(key)
.ok_or_else(|| ConfigError::from_key(key.to_string()))
}

/// Return the URL of the Grafana instance.
pub fn app_url(&self) -> ConfigResult<&String> {
self.get(Self::APP_URL)
}

/// Return the client secret for the app plugin's service account, if set.
///
/// Plugins can request a service account be created by Grafana at startup
/// time by using the `iam` field of their `plugin.json` file. This method
/// will then return the client secret for that service account, which can
/// be used to authenticate with the Grafana API.
///
/// See [this example plugin][example] for a full example of how to use this.
///
/// [example]: https://github.com/grafana/grafana-plugin-examples/tree/main/examples/app-with-service-account
pub fn plugin_app_client_secret(&self) -> ConfigResult<&String> {
self.get(Self::APP_CLIENT_SECRET)
}
}

impl std::fmt::Debug for GrafanaConfig {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("GrafanaConfig").finish()
}
}
6 changes: 6 additions & 0 deletions crates/grafana-plugin-sdk/src/backend/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ pub use tonic::async_trait;
mod data;
mod diagnostics;
mod error_source;
mod grafana_config;
mod noop;
mod resource;
mod stream;
Expand All @@ -172,6 +173,7 @@ pub use diagnostics::{
DiagnosticsService, HealthStatus, Payload as MetricsPayload,
};
pub use error_source::ErrorSource;
pub use grafana_config::{ConfigError, GrafanaConfig};
pub use resource::{
BoxResourceFuture, BoxResourceStream, CallResourceRequest, ErrIntoHttpResponse,
IntoHttpResponse, ResourceService,
Expand Down Expand Up @@ -1109,6 +1111,9 @@ where
pub instance_settings: Option<IS>,
_json_data: PhantomData<JsonData>,
_secure_json_data: PhantomData<SecureJsonData>,

/// Configuration passed to the plugin from Grafana.
pub grafana_config: GrafanaConfig,
}

impl<IS, JsonData, SecureJsonData> TryFrom<pluginv2::PluginContext>
Expand All @@ -1132,6 +1137,7 @@ where
instance_settings,
_json_data: PhantomData,
_secure_json_data: PhantomData,
grafana_config: GrafanaConfig::new(other.grafana_config),
})
}
}
Expand Down
Loading