use crate::api::machine::{
Bootstrap as ProtoBootstrap, BootstrapRequest as ProtoRequest,
BootstrapResponse as ProtoResponse,
};
#[derive(Debug, Clone, Copy, Default)]
pub struct BootstrapRequest {
pub recover_etcd: bool,
pub recover_skip_hash_check: bool,
}
impl BootstrapRequest {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn builder() -> BootstrapRequestBuilder {
BootstrapRequestBuilder::default()
}
#[must_use]
pub fn recovery() -> Self {
Self {
recover_etcd: true,
recover_skip_hash_check: false,
}
}
#[must_use]
pub fn recovery_skip_hash() -> Self {
Self {
recover_etcd: true,
recover_skip_hash_check: true,
}
}
}
impl From<BootstrapRequest> for ProtoRequest {
fn from(req: BootstrapRequest) -> Self {
ProtoRequest {
recover_etcd: req.recover_etcd,
recover_skip_hash_check: req.recover_skip_hash_check,
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct BootstrapRequestBuilder {
recover_etcd: bool,
recover_skip_hash_check: bool,
}
impl BootstrapRequestBuilder {
#[must_use]
pub fn recover_etcd(mut self, recover: bool) -> Self {
self.recover_etcd = recover;
self
}
#[must_use]
pub fn recover_skip_hash_check(mut self, skip: bool) -> Self {
self.recover_skip_hash_check = skip;
self
}
#[must_use]
pub fn build(self) -> BootstrapRequest {
BootstrapRequest {
recover_etcd: self.recover_etcd,
recover_skip_hash_check: self.recover_skip_hash_check,
}
}
}
#[derive(Debug, Clone)]
pub struct BootstrapResult {
pub node: Option<String>,
}
impl From<ProtoBootstrap> for BootstrapResult {
fn from(proto: ProtoBootstrap) -> Self {
Self {
node: proto.metadata.map(|m| m.hostname),
}
}
}
#[derive(Debug, Clone)]
pub struct BootstrapResponse {
pub results: Vec<BootstrapResult>,
}
impl From<ProtoResponse> for BootstrapResponse {
fn from(proto: ProtoResponse) -> Self {
Self {
results: proto.messages.into_iter().map(Into::into).collect(),
}
}
}
impl BootstrapResponse {
#[must_use]
pub fn is_success(&self) -> bool {
!self.results.is_empty()
}
#[must_use]
pub fn first(&self) -> Option<&BootstrapResult> {
self.results.first()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_bootstrap_request_new() {
let request = BootstrapRequest::new();
assert!(!request.recover_etcd);
assert!(!request.recover_skip_hash_check);
}
#[test]
fn test_bootstrap_request_recovery() {
let request = BootstrapRequest::recovery();
assert!(request.recover_etcd);
assert!(!request.recover_skip_hash_check);
}
#[test]
fn test_bootstrap_request_recovery_skip_hash() {
let request = BootstrapRequest::recovery_skip_hash();
assert!(request.recover_etcd);
assert!(request.recover_skip_hash_check);
}
#[test]
fn test_bootstrap_request_builder() {
let request = BootstrapRequest::builder()
.recover_etcd(true)
.recover_skip_hash_check(true)
.build();
assert!(request.recover_etcd);
assert!(request.recover_skip_hash_check);
}
#[test]
fn test_proto_conversion() {
let request = BootstrapRequest::builder()
.recover_etcd(true)
.recover_skip_hash_check(false)
.build();
let proto: ProtoRequest = request.into();
assert!(proto.recover_etcd);
assert!(!proto.recover_skip_hash_check);
}
#[test]
fn test_bootstrap_response_is_success() {
let response = BootstrapResponse {
results: vec![BootstrapResult {
node: Some("controlplane-1".to_string()),
}],
};
assert!(response.is_success());
let empty_response = BootstrapResponse { results: vec![] };
assert!(!empty_response.is_success());
}
}