feat: Add initial Tenant traits and data structures
This commit is contained in:
parent
88d6af9815
commit
895fb02f4e
186
harmony/src/domain/topology/tenant/mod.rs
Normal file
186
harmony/src/domain/topology/tenant/mod.rs
Normal file
@ -0,0 +1,186 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] // Assuming serde for Scores
|
||||
pub struct TenantConfig {
|
||||
/// A unique, human-readable name for the tenant (e.g., "client-alpha", "project-phoenix").
|
||||
/// This will be used as the primary identifier for management operations.
|
||||
pub name: String,
|
||||
|
||||
/// An optional description for the tenant.
|
||||
pub description: Option<String>,
|
||||
|
||||
/// Desired resource allocations and limits for the tenant.
|
||||
pub resource_limits: ResourceLimits,
|
||||
|
||||
/// High-level network isolation policies for the tenant.
|
||||
pub network_policy: TenantNetworkPolicy,
|
||||
|
||||
/// Key-value pairs for provider-specific tagging, labeling, or metadata.
|
||||
/// Useful for billing, organization, or filtering within the provider's console.
|
||||
pub labels_or_tags: HashMap<String, String>,
|
||||
// Note: User/group management for the tenant is deferred to a future ADR.
|
||||
// For now, the TenantManager sets up the space; how it's accessed internally
|
||||
// by the tenant's own users is a separate concern.
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct TenantContext {
|
||||
/// The provider-specific internal identifier for the tenant's primary isolation unit
|
||||
/// (e.g., Kubernetes namespace name, OpenStack project ID, AWS Account ID).
|
||||
pub provider_internal_id: String,
|
||||
|
||||
/// The logical name of the tenant, matching `TenantConfig.name`.
|
||||
pub name: String,
|
||||
|
||||
/// Current operational status of the tenant.
|
||||
pub status: TenantStatus,
|
||||
|
||||
/// Effective resource limits currently applied to the tenant.
|
||||
/// This might differ slightly from requested if the provider adjusted them.
|
||||
pub effective_resource_limits: ResourceLimits,
|
||||
|
||||
/// Effective network policy currently applied.
|
||||
pub effective_network_policy: TenantNetworkPolicy,
|
||||
|
||||
/// Additional provider-specific data or endpoints relevant to the tenant.
|
||||
/// (e.g., K8s API server endpoint scoped to the namespace, if applicable).
|
||||
pub provider_specific_data: HashMap<String, String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub enum TenantStatus {
|
||||
Provisioning,
|
||||
Active,
|
||||
Updating,
|
||||
Deleting,
|
||||
Error(String),
|
||||
Unknown,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
|
||||
pub struct ResourceLimits {
|
||||
/// Requested/guaranteed CPU cores (e.g., 2.0).
|
||||
pub cpu_request_cores: Option<f32>,
|
||||
/// Maximum CPU cores the tenant can burst to (e.g., 4.0).
|
||||
pub cpu_limit_cores: Option<f32>,
|
||||
|
||||
/// Requested/guaranteed memory in Gigabytes (e.g., 8.0).
|
||||
pub memory_request_gb: Option<f32>,
|
||||
/// Maximum memory in Gigabytes tenant can burst to (e.g., 16.0).
|
||||
pub memory_limit_gb: Option<f32>,
|
||||
|
||||
/// Total persistent storage allocation in Gigabytes across all volumes.
|
||||
pub storage_total_gb: Option<u64>,
|
||||
/// Maximum number of distinct persistent volumes/claims.
|
||||
pub persistent_volume_claim_count: Option<u32>,
|
||||
// /// Optional: Storage limits per class, if needed for more granular control.
|
||||
// pub storage_gb_per_class: Option<HashMap<String, u64>>,
|
||||
|
||||
/// Maximum number of load balancers.
|
||||
pub load_balancer_count: Option<u32>,
|
||||
/// Maximum number of public IP addresses.
|
||||
pub public_ip_count: Option<u32>,
|
||||
|
||||
/// Provider-specific or custom quotas (e.g., "gpu_count:2", "snapshot_count:10").
|
||||
/// Values are strings to accommodate various provider formats.
|
||||
pub custom_quotas: HashMap<String, String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct TenantNetworkPolicy {
|
||||
/// Policy for ingress traffic originating from other tenants within the same Harmony-managed environment.
|
||||
pub default_inter_tenant_ingress: InterTenantIngressPolicy,
|
||||
|
||||
/// Policy for egress traffic destined for the public internet.
|
||||
pub default_internet_egress: InternetEgressPolicy,
|
||||
|
||||
/// List of common cluster-internal services this tenant should be ableto access.
|
||||
pub allowed_cluster_services: Vec<ClusterServiceType>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub enum InterTenantIngressPolicy {
|
||||
/// Deny all traffic from other tenants by default.
|
||||
DenyAll,
|
||||
// Future: AllowFromSameGroup (if tenants can be logically grouped)
|
||||
// Future: AllowLabeled (if tenants can specify labels for selective inter-tenant comms)
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub enum InternetEgressPolicy {
|
||||
/// Allow all outbound traffic to the internet.
|
||||
AllowAll,
|
||||
/// Deny all outbound traffic to the internet by default.
|
||||
DenyAll,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub enum ClusterServiceType {
|
||||
/// e.g., kube-dns, CoreDNS.
|
||||
Dns,
|
||||
/// Access to an internal image registry.
|
||||
InternalImageRegistry,
|
||||
/// Access to centralized monitoring endpoints (e.g., Prometheus federation).
|
||||
MonitoringService,
|
||||
}
|
||||
|
||||
use async_trait::async_trait;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::executors::ExecutorError;
|
||||
|
||||
#[async_trait]
|
||||
pub trait TenantManager: Send + Sync + std::fmt::Debug {
|
||||
/// Provisions a new tenant based on the provided configuration.
|
||||
/// This operation should be idempotent; if a tenant with the same `config.name`
|
||||
/// already exists and matches the config, it may succeed without changes.
|
||||
/// If it exists but differs, it might return an error or attempt to update (TBD by implementer).
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `config`: The desired configuration for the new tenant.
|
||||
///
|
||||
/// # Returns
|
||||
/// A `TenantContext` representing the provisioned tenant.
|
||||
async fn provision_tenant(&self, config: &TenantConfig) -> Result<TenantContext, ExecutorError>;
|
||||
|
||||
/// Retrieves the current details and context of an existing tenant.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `tenant_name`: The logical name of the tenant to retrieve.
|
||||
///
|
||||
/// # Returns
|
||||
/// An `Option<TenantContext>`, which is `None` if the tenant does not exist.
|
||||
async fn get_tenant_details(&self, tenant_name: &str) -> Result<Option<TenantContext>, ExecutorError>;
|
||||
|
||||
/// Updates the resource limits for an existing tenant.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `tenant_name`: The logical name of the tenant to update.
|
||||
/// * `new_limits`: The new set of resource limits to apply.
|
||||
async fn update_tenant_resource_limits(
|
||||
&self,
|
||||
tenant_name: &str,
|
||||
new_limits: &ResourceLimits,
|
||||
) -> Result<(), ExecutorError>;
|
||||
|
||||
/// Updates the high-level network isolation policy for an existing tenant.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `tenant_name`: The logical name of the tenant to update.
|
||||
/// * `new_policy`: The new network policy to apply.
|
||||
async fn update_tenant_network_policy(
|
||||
&self,
|
||||
tenant_name: &str,
|
||||
new_policy: &TenantNetworkPolicy,
|
||||
) -> Result<(), ExecutorError>;
|
||||
|
||||
/// Decommissions an existing tenant, removing its isolated context and associated resources.
|
||||
/// This operation should be idempotent.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `tenant_name`: The logical name of the tenant to deprovision.
|
||||
async fn deprovision_tenant(&self, tenant_name: &str) -> Result<(), ExecutorError>;
|
||||
|
||||
/// Lists the logical names of all tenants currently managed by this `TenantManager` instance.
|
||||
async fn list_tenant_names(&self) -> Result<Vec<String>, ExecutorError>;
|
||||
}
|
Loading…
Reference in New Issue
Block a user