Struct ConversionWebhookServer

Source
pub struct ConversionWebhookServer { /* private fields */ }
Expand description

A ready-to-use CRD conversion webhook server.

See ConversionWebhookServer::new() for usage examples.

Implementations§

Source§

impl ConversionWebhookServer

Source

pub async fn new<H>( crds_and_handlers: impl IntoIterator<Item = (CustomResourceDefinition, H)>, options: ConversionWebhookOptions, client: Client, ) -> Result<Self, ConversionWebhookError>
where H: WebhookHandler<ConversionReview, ConversionReview> + Clone + Send + Sync + 'static,

Creates a new conversion webhook server, which expects POST requests being made to the /convert/{crd name} endpoint.

You need to provide a few things for every CRD passed in via the crds_and_handlers argument:

  1. The CRD
  2. A conversion function to convert between CRD versions. Typically you would use the the auto-generated try_convert function on CRD spec definition structs for this.
  3. A [kube::Client] used to create/update the CRDs.

The ConversionWebhookServer takes care of reconciling the CRDs into the Kubernetes cluster and takes care of adding itself as conversion webhook. This includes TLS certificates and CA bundles.

§Example
use clap::Parser;
use stackable_webhook::{
    servers::{ConversionWebhookServer, ConversionWebhookOptions},
    constants::CONVERSION_WEBHOOK_HTTPS_PORT,
    WebhookOptions
};
use stackable_operator::{
    kube::Client,
    crd::s3::{S3Connection, S3ConnectionVersion},
    cli::ProductOperatorRun,
};

// Things that should already be in you operator:
const OPERATOR_NAME: &str = "product-operator";
let client = Client::try_default().await.expect("failed to create Kubernetes client");
let ProductOperatorRun {
    operator_environment,
    disable_crd_maintenance,
    ..
} = ProductOperatorRun::parse();

 let crds_and_handlers = [
    (
        S3Connection::merged_crd(S3ConnectionVersion::V1Alpha1)
            .expect("failed to merge S3Connection CRD"),
        S3Connection::try_convert as fn(_) -> _,
    ),
];

let options = ConversionWebhookOptions {
    socket_addr: format!("0.0.0.0:{CONVERSION_WEBHOOK_HTTPS_PORT}")
        .parse()
        .expect("static address is always valid"),
    namespace: operator_environment.operator_namespace,
    service_name: operator_environment.operator_service_name,
    maintain_crds: !disable_crd_maintenance,
    field_manager: OPERATOR_NAME.to_owned(),
};

// Construct the conversion webhook server
let conversion_webhook = ConversionWebhookServer::new(
    crds_and_handlers,
    options,
    client,
)
.await
.expect("failed to create ConversionWebhookServer");

conversion_webhook.run().await.expect("failed to run ConversionWebhookServer");
Source

pub async fn run(self) -> Result<(), ConversionWebhookError>

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> FutureExt for T

§

fn with_context(self, otel_cx: Context) -> WithContext<Self>

Attaches the provided Context to this type, returning a WithContext wrapper. Read more
§

fn with_current_context(self) -> WithContext<Self>

Attaches the current Context to this type, returning a WithContext wrapper. Read more
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

impl<T> IntoRequest<T> for T

§

fn into_request(self) -> Request<T>

Wrap the input message T in a tonic::Request
§

impl<L> LayerExt<L> for L

§

fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>
where L: Layer<S>,

Applies the layer to a service and wraps it in [Layered].
§

impl<T> PolicyExt for T
where T: ?Sized,

§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] only if self and other return Action::Follow. Read more
§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where T: 'static,