#![allow(unknown_lints)]
#![allow(clippy::style)]
#![allow(clippy::complexity)]
#![allow(clippy::large_enum_variant)]
#![allow(clippy::mutable_key_type)]
#![allow(clippy::stable_sort_primitive)]
#![allow(clippy::map_entry)]
#![allow(clippy::box_default)]
#![allow(clippy::drain_collect)]
#![warn(clippy::bool_comparison)]
#![warn(clippy::clone_on_ref_ptr)]
#![warn(clippy::no_effect)]
#![warn(clippy::unnecessary_unwrap)]
#![warn(clippy::dbg_macro)]
#![warn(clippy::todo)]
#![warn(clippy::wildcard_dependencies)]
#![warn(clippy::zero_prefixed_literal)]
#![warn(clippy::borrowed_box)]
#![warn(clippy::deref_addrof)]
#![warn(clippy::double_must_use)]
#![warn(clippy::double_parens)]
#![warn(clippy::extra_unused_lifetimes)]
#![warn(clippy::needless_borrow)]
#![warn(clippy::needless_question_mark)]
#![warn(clippy::needless_return)]
#![warn(clippy::redundant_pattern)]
#![warn(clippy::redundant_slicing)]
#![warn(clippy::redundant_static_lifetimes)]
#![warn(clippy::single_component_path_imports)]
#![warn(clippy::unnecessary_cast)]
#![warn(clippy::useless_asref)]
#![warn(clippy::useless_conversion)]
#![warn(clippy::builtin_type_shadow)]
#![warn(clippy::duplicate_underscore_argument)]
#![warn(clippy::double_neg)]
#![warn(clippy::unnecessary_mut_passed)]
#![warn(clippy::wildcard_in_or_patterns)]
#![warn(clippy::crosspointer_transmute)]
#![warn(clippy::excessive_precision)]
#![warn(clippy::overflow_check_conditional)]
#![warn(clippy::as_conversions)]
#![warn(clippy::match_overlapping_arm)]
#![warn(clippy::zero_divided_by_zero)]
#![warn(clippy::must_use_unit)]
#![warn(clippy::suspicious_assignment_formatting)]
#![warn(clippy::suspicious_else_formatting)]
#![warn(clippy::suspicious_unary_op_formatting)]
#![warn(clippy::mut_mutex_lock)]
#![warn(clippy::print_literal)]
#![warn(clippy::same_item_push)]
#![warn(clippy::useless_format)]
#![warn(clippy::write_literal)]
#![warn(clippy::redundant_closure)]
#![warn(clippy::redundant_closure_call)]
#![warn(clippy::unnecessary_lazy_evaluations)]
#![warn(clippy::partialeq_ne_impl)]
#![warn(clippy::redundant_field_names)]
#![warn(clippy::transmutes_expressible_as_ptr_casts)]
#![warn(clippy::unused_async)]
#![warn(clippy::disallowed_methods)]
#![warn(clippy::disallowed_macros)]
#![warn(clippy::disallowed_types)]
#![warn(clippy::from_over_into)]
use std::collections::BTreeMap;
use std::fmt::{self, Debug};
use std::str::FromStr;
use std::sync::Arc;
use async_trait::async_trait;
use chrono::{DateTime, Utc};
use futures::stream::BoxStream;
use mz_repr::GlobalId;
use serde::{Deserialize, Serialize};
use crate::crd::vpc_endpoint::v1::{VpcEndpointState, VpcEndpointStatus};
pub mod crd;
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct AwsExternalIdPrefix(String);
impl AwsExternalIdPrefix {
pub fn new_from_cli_argument_or_environment_variable(
aws_external_id_prefix: &str,
) -> AwsExternalIdPrefix {
AwsExternalIdPrefix(aws_external_id_prefix.into())
}
}
impl fmt::Display for AwsExternalIdPrefix {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(&self.0)
}
}
pub struct VpcEndpointConfig {
pub aws_service_name: String,
pub availability_zone_ids: Vec<String>,
}
#[async_trait]
pub trait CloudResourceController: CloudResourceReader {
async fn ensure_vpc_endpoint(
&self,
id: GlobalId,
vpc_endpoint: VpcEndpointConfig,
) -> Result<(), anyhow::Error>;
async fn delete_vpc_endpoint(&self, id: GlobalId) -> Result<(), anyhow::Error>;
async fn list_vpc_endpoints(
&self,
) -> Result<BTreeMap<GlobalId, VpcEndpointStatus>, anyhow::Error>;
async fn watch_vpc_endpoints(&self) -> BoxStream<'static, VpcEndpointEvent>;
fn reader(&self) -> Arc<dyn CloudResourceReader>;
}
#[async_trait]
pub trait CloudResourceReader: Debug + Send + Sync {
async fn read(&self, id: GlobalId) -> Result<VpcEndpointStatus, anyhow::Error>;
}
pub fn vpc_endpoint_name(id: GlobalId) -> String {
format!("connection-{id}")
}
pub fn id_from_vpc_endpoint_name(vpc_endpoint_name: &str) -> Option<GlobalId> {
vpc_endpoint_name
.split_once('-')
.and_then(|(_, id_str)| GlobalId::from_str(id_str).ok())
}
pub fn vpc_endpoint_host(id: GlobalId, availability_zone: Option<&str>) -> String {
let name = vpc_endpoint_name(id);
match availability_zone {
Some(az) => format!("{name}-{az}"),
None => name,
}
}
#[derive(Debug)]
pub struct VpcEndpointEvent {
pub connection_id: GlobalId,
pub status: VpcEndpointState,
pub time: DateTime<Utc>,
}