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