**Architecture Decision Record: Harmony Infrastructure Abstractions**

**Status**: Proposed

**Context**: Harmony is an infrastructure orchestrator written in pure Rust, aiming to provide real portability of automation across different cloud providers and infrastructure setups. To achieve this, we need to define infrastructure abstractions that are provider-agnostic and flexible enough to accommodate various use cases.

**Decision**: We will define our infrastructure abstractions using a domain-driven approach, focusing on the core logic of Harmony. These abstractions will only include the absolutely required elements for a specific resource, without referencing specific providers or implementations.

**Example: Database Abstraction**

To deploy a database to any cloud provider, we define an abstraction that includes essential elements such as:
```rust
// Database abstraction
trait Database {
    fn storage_space(&self) -> u64; // in GB
    fn driver_url(&self) -> String;
    fn credentials(&self) -> Credentials;
    fn storage_speed_target(&self) -> Option<u32>; // in MBps
    fn reliability_target(&self) -> Option<String>;
}
```
This abstraction does not specify a particular storage class (e.g., AmazonEBS or CephSSDBlock). Instead, it defines the required characteristics of the database, allowing infrastructure providers to implement these requirements using their own solutions.

**Example: OKD Upgrade Abstraction**

Similarly, for an OKD upgrade, we define an abstraction that includes essential elements such as:
```rust
// OKDUpgrade abstraction
trait OKDUpgrade {
    fn current_version(&self) -> String;
    fn target_version(&self) -> String;
    fn inventory(&self) -> Inventory;
    fn topology(&self) -> Topology;
}
```
This abstraction does not specify the upgrade process or the underlying infrastructure. Instead, it defines the required inputs and outputs for the upgrade, allowing Harmony to execute the upgrade using the provided abstractions.

**Implementation**

To implement these abstractions, users will create concrete implementations of the traits, specific to their infrastructure providers. For example:
```rust
// Implement Database trait for AmazonRDS
struct AmazonRDS {
    // implementation details
}

impl Database for AmazonRDS {
    fn storage_space(&self) -> u64 { /* implementation */ }
    fn driver_url(&self) -> String { /* implementation */ }
    // ...
}
```
By defining our infrastructure abstractions in this way, we ensure that Harmony remains provider-agnostic and flexible enough to accommodate various use cases. This approach enables real portability of automation across different cloud providers and infrastructure setups.


**Consequences**: This decision will lead to a more modular and flexible architecture for Harmony, allowing users to easily adopt harmony on their own infrastructure and eventually switch between different infrastructure providers and reuse their existing automation scripts. It will also simplify the development process for new features and use cases, as we can focus on implementing the core domain logic without worrying about provider-specific details.
