-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add command to allow ip address on a capella cluster
- Loading branch information
Showing
5 changed files
with
198 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
use crate::cli::util::{cluster_from_conn_str, find_org_id, find_project_id}; | ||
use crate::cli::{client_error_to_shell_error, no_active_cluster_error}; | ||
use crate::state::State; | ||
use log::info; | ||
use nu_engine::CallExt; | ||
use nu_protocol::ast::Call; | ||
use nu_protocol::engine::{Command, EngineState, Stack}; | ||
use nu_protocol::{Category, PipelineData, ShellError, Signature, SyntaxShape, Value}; | ||
use std::ops::Add; | ||
use std::sync::{Arc, Mutex}; | ||
use tokio::time::Instant; | ||
|
||
#[derive(Clone)] | ||
pub struct AllowIP { | ||
state: Arc<Mutex<State>>, | ||
} | ||
|
||
impl crate::cli::AllowIP { | ||
pub fn new(state: Arc<Mutex<State>>) -> Self { | ||
Self { state } | ||
} | ||
} | ||
|
||
impl Command for crate::cli::AllowIP { | ||
fn name(&self) -> &str { | ||
"allow ip" | ||
} | ||
|
||
fn signature(&self) -> Signature { | ||
Signature::build("allow ip") | ||
.category(Category::Custom("couchbase".to_string())) | ||
.optional( | ||
"address", | ||
SyntaxShape::String, | ||
"ip address to allow access to the cluster", | ||
) | ||
} | ||
|
||
fn usage(&self) -> &str { | ||
"Adds IP address to allowlist on a Capella cluster" | ||
} | ||
|
||
fn run( | ||
&self, | ||
engine_state: &EngineState, | ||
stack: &mut Stack, | ||
call: &Call, | ||
input: PipelineData, | ||
) -> Result<PipelineData, ShellError> { | ||
allow_ip(self.state.clone(), engine_state, stack, call, input) | ||
} | ||
} | ||
|
||
fn allow_ip( | ||
state: Arc<Mutex<State>>, | ||
engine_state: &EngineState, | ||
stack: &mut Stack, | ||
call: &Call, | ||
input: PipelineData, | ||
) -> Result<PipelineData, ShellError> { | ||
let span = call.head; | ||
let ctrl_c = engine_state.ctrlc.as_ref().unwrap().clone(); | ||
let guard = state.lock().unwrap(); | ||
|
||
let ip_address = match input.into_value(span)? { | ||
Value::String { val, .. } => format_ip_address(val), | ||
Value::Nothing { .. } => { | ||
if let Some(address) = call.opt(engine_state, stack, 0)? { | ||
format_ip_address(address) | ||
} else { | ||
return Err(ShellError::GenericError { | ||
error: "No IP address provided".to_string(), | ||
msg: "".to_string(), | ||
span: None, | ||
help: Some("Provide IP as positional parameter or piped input".into()), | ||
inner: vec![], | ||
}); | ||
} | ||
} | ||
_ => { | ||
return Err(ShellError::GenericError { | ||
error: "IP address must be a string".to_string(), | ||
msg: "".to_string(), | ||
span: None, | ||
help: None, | ||
inner: vec![], | ||
}) | ||
} | ||
}; | ||
|
||
let active_cluster = match guard.active_cluster() { | ||
Some(c) => c, | ||
None => { | ||
return Err(no_active_cluster_error(span)); | ||
} | ||
}; | ||
let org = if let Some(cluster_org) = active_cluster.capella_org() { | ||
guard.get_capella_org(cluster_org) | ||
} else { | ||
guard.active_capella_org() | ||
}?; | ||
|
||
let client = org.client(); | ||
let deadline = Instant::now().add(org.timeout()); | ||
|
||
let org_id = find_org_id(ctrl_c.clone(), &client, deadline, span)?; | ||
|
||
let project_id = find_project_id( | ||
ctrl_c.clone(), | ||
guard.active_project().unwrap(), | ||
&client, | ||
deadline, | ||
span, | ||
org_id.clone(), | ||
)?; | ||
|
||
let json_cluster = cluster_from_conn_str( | ||
active_cluster.display_name().unwrap_or("".to_string()), | ||
ctrl_c.clone(), | ||
active_cluster.hostnames().clone(), | ||
&client, | ||
deadline, | ||
span, | ||
org_id.clone(), | ||
project_id.clone(), | ||
)?; | ||
|
||
client | ||
.allow_ip_address( | ||
org_id, | ||
project_id, | ||
json_cluster.id(), | ||
ip_address, | ||
deadline, | ||
ctrl_c, | ||
) | ||
.map_err(|e| client_error_to_shell_error(e, span))?; | ||
|
||
Ok(PipelineData::empty()) | ||
} | ||
|
||
fn format_ip_address(ip_address: String) -> String { | ||
if !ip_address.contains('/') { | ||
info!("IP address supplied without a subnet mask, defaulting to '/32'"); | ||
format!("{}/32", ip_address) | ||
} else { | ||
ip_address | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters