iota_aws_orchestrator/
error.rs

1// Copyright (c) Mysten Labs, Inc.
2// Modifications Copyright (c) 2024 IOTA Stiftung
3// SPDX-License-Identifier: Apache-2.0
4
5use std::net::SocketAddr;
6
7use reqwest::Url;
8
9#[macro_export(local_inner_macros)]
10macro_rules! ensure {
11    ($cond:expr, $e:expr) => {
12        if !($cond) {
13            return Err($e);
14        }
15    };
16}
17
18pub type SettingsResult<T> = Result<T, SettingsError>;
19
20#[derive(thiserror::Error, Debug)]
21pub enum SettingsError {
22    #[error("Failed to read settings file '{file:?}': {message}")]
23    InvalidSettings { file: String, message: String },
24
25    #[error("Failed to read token file '{file:?}': {message}")]
26    InvalidTokenFile { file: String, message: String },
27
28    #[error("Failed to read ssh public key file '{file:?}': {message}")]
29    InvalidSshPublicKeyFile { file: String, message: String },
30
31    #[error("Malformed repository url: {0:?}")]
32    MalformedRepositoryUrl(Url),
33}
34
35pub type CloudProviderResult<T> = Result<T, CloudProviderError>;
36
37#[derive(thiserror::Error, Debug)]
38pub enum CloudProviderError {
39    #[error("Failed to send server request: {0}")]
40    Request(String),
41
42    #[error("Unexpected response: {0}")]
43    UnexpectedResponse(String),
44
45    #[error("Received error status code ({0}): {1}")]
46    FailureResponseCode(String, String),
47
48    #[error("SSH key \"{0}\" not found")]
49    SshKeyNotFound(String),
50
51    #[error("Spot Instances cannot be stopped: Instance Id: {0}")]
52    FailedToStopSpotInstance(String),
53}
54
55pub type SshResult<T> = Result<T, SshError>;
56
57#[derive(thiserror::Error, Debug)]
58pub enum SshError {
59    #[error("Failed to load private key for {address}: {error}")]
60    PrivateKeyError {
61        address: SocketAddr,
62        error: russh_keys::Error,
63    },
64
65    #[error("Failed to create ssh session with {address}: {error}")]
66    SessionError {
67        address: SocketAddr,
68        error: russh::Error,
69    },
70
71    #[error("Failed to connect to instance {address}: {error}")]
72    ConnectionError {
73        address: SocketAddr,
74        error: russh::Error,
75    },
76
77    #[error("Remote execution cmd '{command}' on {address} returned exit code ({code}): {message}")]
78    NonZeroExitCode {
79        address: SocketAddr,
80        code: u32,
81        message: String,
82        command: String,
83    },
84}
85
86pub type MonitorResult<T> = Result<T, MonitorError>;
87
88#[derive(thiserror::Error, Debug)]
89pub enum MonitorError {
90    #[error(transparent)]
91    Ssh(#[from] SshError),
92
93    #[error("Failed to start Grafana: {0}")]
94    Grafana(String),
95}
96
97pub type TestbedResult<T> = Result<T, TestbedError>;
98
99#[derive(thiserror::Error, Debug)]
100pub enum TestbedError {
101    #[error(transparent)]
102    Settings(#[from] SettingsError),
103
104    #[error(transparent)]
105    CloudProvider(#[from] CloudProviderError),
106
107    #[error(transparent)]
108    Ssh(#[from] SshError),
109
110    #[error("Not enough instances: missing {0} instances")]
111    InsufficientCapacity(usize),
112
113    #[error("Metrics instance is missing")]
114    MetricsServerMissing(),
115
116    #[error("Not enough dedicated client instances: missing {0} instances")]
117    InsufficientDedicatedClientCapacity(usize),
118
119    #[error(transparent)]
120    Monitor(#[from] MonitorError),
121
122    #[error(transparent)]
123    BuildCacheError(#[from] iota_build_cache_server::client::BuildCacheError),
124}