1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Use of this software is governed by the Business Source License
4// included in the LICENSE file.
5//
6// As of the Change Date specified in that file, in accordance with
7// the Business Source License, use of this software will be governed
8// by the Apache License, Version 2.0.
910//! VpcEndpoint custom resource, to be reconciled into an AWS VPC Endpoint by the
11//! environment-controller.
12use std::fmt;
1314use k8s_openapi::apimachinery::pkg::apis::meta::v1::Condition;
15use kube::CustomResource;
16use schemars::JsonSchema;
17use serde::{Deserialize, Serialize};
1819pub mod v1 {
20use super::*;
2122/// Describes an AWS VPC endpoint to create.
23#[derive(CustomResource, Clone, Debug, Default, Deserialize, Serialize, JsonSchema)]
24 #[serde(rename_all = "camelCase")]
25 #[kube(
26 group = "materialize.cloud",
27 version = "v1",
28 kind = "VpcEndpoint",
29 singular = "vpcendpoint",
30 plural = "vpcendpoints",
31 shortname = "vpce",
32 namespaced,
33 status = "VpcEndpointStatus",
34 printcolumn = r#"{"name": "AwsServiceName", "type": "string", "description": "Name of the VPC Endpoint Service to connect to.", "jsonPath": ".spec.awsServiceName", "priority": 1}"#,
35 printcolumn = r#"{"name": "AvailabilityZoneIDs", "type": "string", "description": "Availability Zone IDs", "jsonPath": ".spec.availabilityZoneIds", "priority": 1}"#
36)]
37// If making changes to this spec,
38 // you must also update src/cloud-resources/gen/vpcendpoints.crd.json
39 // so that cloudtest can register the CRD.
40pub struct VpcEndpointSpec {
41/// The name of the service to connect to.
42pub aws_service_name: String,
43/// The IDs of the availability zones in which the service is available.
44pub availability_zone_ids: Vec<String>,
45/// A suffix to use in the name of the IAM role that is created.
46pub role_suffix: String,
47 }
4849#[derive(Clone, Debug, Default, Deserialize, Serialize, JsonSchema, PartialEq)]
50 #[serde(rename_all = "camelCase")]
51pub struct VpcEndpointStatus {
52// This will be None if the customer hasn't allowed our principal, got the name of their
53 // VPC Endpoint Service wrong, or we've otherwise failed to create the VPC Endpoint.
54pub vpc_endpoint_id: Option<String>,
55pub state: Option<VpcEndpointState>,
56pub conditions: Option<Vec<Condition>>,
57 }
5859#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema, PartialEq)]
60 #[serde(rename_all = "camelCase")]
61pub enum VpcEndpointState {
62// Internal States
63PendingServiceDiscovery,
64 CreatingEndpoint,
65 RecreatingEndpoint,
66 UpdatingEndpoint,
6768// AWS States
69 // Connection established to the customer's VPC Endpoint Service.
70Available,
71 Deleted,
72 Deleting,
73 Expired,
74 Failed,
75// Customer has approved the connection. It should eventually move to Available.
76Pending,
77// Waiting on the customer to approve the connection.
78PendingAcceptance,
79 Rejected,
80 Unknown,
81 }
8283impl fmt::Display for VpcEndpointState {
84fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
85let repr = match self {
86 VpcEndpointState::PendingServiceDiscovery => "pending-service-discovery",
87 VpcEndpointState::CreatingEndpoint => "creating-endpoint",
88 VpcEndpointState::RecreatingEndpoint => "recreating-endpoint",
89 VpcEndpointState::UpdatingEndpoint => "updating-endpoint",
90 VpcEndpointState::Available => "available",
91 VpcEndpointState::Deleted => "deleted",
92 VpcEndpointState::Deleting => "deleting",
93 VpcEndpointState::Expired => "expired",
94 VpcEndpointState::Failed => "failed",
95 VpcEndpointState::Pending => "pending",
96 VpcEndpointState::PendingAcceptance => "pending-acceptance",
97 VpcEndpointState::Rejected => "rejected",
98 VpcEndpointState::Unknown => "unknown",
99 };
100write!(f, "{}", repr)
101 }
102 }
103}
104105#[cfg(test)]
106mod tests {
107use std::fs;
108109use kube::CustomResourceExt;
110use kube::core::crd::merge_crds;
111112#[mz_ore::test]
113fn test_vpc_endpoint_crd_matches() {
114let crd = merge_crds(vec![super::v1::VpcEndpoint::crd()], "v1").unwrap();
115let crd_json = serde_json::to_string(&serde_json::json!(&crd)).unwrap();
116let exported_crd_json = fs::read_to_string("src/crd/generated/vpcendpoints.json").unwrap();
117let exported_crd_json = exported_crd_json.trim();
118assert_eq!(
119&crd_json, exported_crd_json,
120"VpcEndpoint CRD json does not match exported json.\n\nCRD:\n{}\n\nExported CRD:\n{}",
121&crd_json, exported_crd_json,
122 );
123 }
124}