vault_mgmt_lib/
step_down.rs

1use http_body_util::{BodyExt, Empty};
2use hyper::body::Bytes;
3use secrecy::Secret;
4
5use crate::{step_down_request, BytesBody, HttpRequest};
6
7/// Step down vault pod from active to standby
8#[async_trait::async_trait]
9pub trait StepDown {
10    /// Step down vault pod from active to standby
11    async fn step_down(&mut self, token: Secret<String>) -> anyhow::Result<()>;
12}
13
14#[async_trait::async_trait]
15impl<T> StepDown for T
16where
17    T: HttpRequest<BytesBody> + Send + Sync + 'static,
18{
19    async fn step_down(&mut self, token: Secret<String>) -> anyhow::Result<()> {
20        let http_req = step_down_request(token, Empty::<Bytes>::new().boxed())?;
21
22        let (parts, body) = self.send_request(http_req).await?.into_parts();
23
24        let body = String::from_utf8(body.to_vec())?;
25
26        if parts.status != hyper::StatusCode::NO_CONTENT {
27            return Err(anyhow::anyhow!("stepping-down: {}", body));
28        }
29
30        Ok(())
31    }
32}
33
34#[cfg(test)]
35mod tests {
36    use std::str::FromStr;
37
38    use http::{Method, StatusCode};
39    use secrecy::Secret;
40    use wiremock::{
41        matchers::{header, method, path},
42        Mock, MockServer, ResponseTemplate,
43    };
44
45    use crate::{HttpForwarderService, StepDown};
46
47    #[tokio::test]
48    async fn stepdown_calls_api() {
49        let mock_server = MockServer::start().await;
50
51        Mock::given(method(Method::PUT))
52            .and(path("/v1/sys/step-down"))
53            .and(header("X-Vault-Request", "true"))
54            .and(header("X-Vault-Token", "abc"))
55            .respond_with(ResponseTemplate::new(StatusCode::NO_CONTENT))
56            .expect(1)
57            .mount(&mock_server)
58            .await;
59
60        let mut client = HttpForwarderService::http(
61            tokio::net::TcpStream::connect(mock_server.uri().strip_prefix("http://").unwrap())
62                .await
63                .unwrap(),
64        )
65        .await
66        .unwrap();
67
68        let outcome = client.step_down(Secret::from_str("abc").unwrap()).await;
69
70        assert!(outcome.is_ok());
71    }
72}