use crate::error::{GitLabError, Result};
use crate::models::{Variable, VariableOptions, VariableType};
use gitlab::Gitlab;
use gitlab::api::{ApiError, Query, projects::variables};
pub struct VariableBuilder<'a> {
client: &'a Gitlab,
project: String,
}
impl<'a> VariableBuilder<'a> {
pub(crate) fn new(client: &'a Gitlab, project: impl Into<String>) -> Self {
Self {
client,
project: project.into(),
}
}
pub async fn create(
&self,
key: impl AsRef<str>,
value: impl AsRef<str>,
opts: VariableOptions,
) -> Result<Variable> {
let key = key.as_ref();
let value = value.as_ref();
let mut builder = variables::CreateProjectVariable::builder();
builder
.project(&self.project)
.key(key)
.value(value)
.variable_type(match opts.variable_type {
VariableType::EnvVar => variables::ProjectVariableType::EnvVar,
VariableType::File => variables::ProjectVariableType::File,
})
.protected(opts.protected)
.masked(opts.masked)
.raw(opts.raw);
if let Some(scope) = opts.environment_scope {
builder.environment_scope(scope);
}
if let Some(desc) = opts.description {
builder.description(desc);
}
let endpoint = builder.build().map_err(|e| {
GitLabError::api(format!("Failed to build create variable request: {}", e))
})?;
endpoint.query(self.client).map_err(|e| match e {
ApiError::GitlabService { status, .. } if status.as_u16() == 400 => {
GitLabError::conflict(format!("Variable '{}' already exists", key))
}
_ => GitLabError::api(format!("Failed to create variable '{}': {}", key, e)),
})
}
pub async fn update(
&self,
key: impl AsRef<str>,
value: impl AsRef<str>,
opts: VariableOptions,
) -> Result<Variable> {
let key = key.as_ref();
let value = value.as_ref();
let mut builder = variables::UpdateProjectVariable::builder();
builder
.project(&self.project)
.key(key)
.value(value)
.variable_type(match opts.variable_type {
VariableType::EnvVar => variables::ProjectVariableType::EnvVar,
VariableType::File => variables::ProjectVariableType::File,
})
.protected(opts.protected)
.masked(opts.masked)
.raw(opts.raw);
if let Some(scope) = opts.environment_scope {
builder.environment_scope(scope);
}
if let Some(desc) = opts.description {
builder.description(desc);
}
let endpoint = builder.build().map_err(|e| {
GitLabError::api(format!("Failed to build update variable request: {}", e))
})?;
endpoint.query(self.client).map_err(|e| match e {
ApiError::GitlabService { status, .. } if status.as_u16() == 404 => {
GitLabError::not_found("Variable", key)
}
_ => GitLabError::api(format!("Failed to update variable '{}': {}", key, e)),
})
}
pub async fn set(
&self,
key: impl AsRef<str>,
value: impl AsRef<str>,
opts: VariableOptions,
) -> Result<Variable> {
let key = key.as_ref();
match self.update(key, value.as_ref(), opts.clone()).await {
Ok(var) => Ok(var),
Err(GitLabError::NotFound { .. }) => {
self.create(key, value.as_ref(), opts).await
}
Err(e) => Err(e),
}
}
pub async fn get(&self, key: impl AsRef<str>) -> Result<Variable> {
let key = key.as_ref();
let endpoint = variables::ProjectVariable::builder()
.project(&self.project)
.key(key)
.build()
.map_err(|e| {
GitLabError::api(format!("Failed to build get variable request: {}", e))
})?;
endpoint.query(self.client).map_err(|e| match e {
ApiError::GitlabService { status, .. } if status.as_u16() == 404 => {
GitLabError::not_found("Variable", key)
}
_ => GitLabError::api(format!("Failed to get variable '{}': {}", key, e)),
})
}
pub async fn list(&self) -> Result<Vec<Variable>> {
let endpoint = variables::ProjectVariables::builder()
.project(&self.project)
.build()
.map_err(|e| {
GitLabError::api(format!("Failed to build list variables request: {}", e))
})?;
endpoint
.query(self.client)
.map_err(|e| GitLabError::api(format!("Failed to list variables: {}", e)))
}
pub async fn delete(&self, key: impl AsRef<str>) -> Result<()> {
let key = key.as_ref();
let endpoint = variables::DeleteProjectVariable::builder()
.project(&self.project)
.key(key)
.build()
.map_err(|e| {
GitLabError::api(format!("Failed to build delete variable request: {}", e))
})?;
gitlab::api::ignore(endpoint)
.query(self.client)
.map_err(|e| match e {
ApiError::GitlabService { status, .. } if status.as_u16() == 404 => {
GitLabError::not_found("Variable", key)
}
_ => GitLabError::api(format!("Failed to delete variable '{}': {}", key, e)),
})?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_variable_builder() {
fn _compile_test(client: &Gitlab) {
let _builder = VariableBuilder::new(client, "project");
}
}
}