Skip to main content

greentic_runner_host/runner/
mod.rs

1pub mod adapt_messaging;
2pub mod adapt_slack;
3pub mod adapt_teams;
4pub mod adapt_timer;
5pub mod adapt_webchat;
6pub mod adapt_webex;
7pub mod adapt_webhook;
8pub mod adapt_whatsapp;
9pub mod engine;
10pub mod flow_adapter;
11pub mod ingress_util;
12pub mod mocks;
13pub mod operator;
14pub mod templating;
15
16use std::net::SocketAddr;
17use std::sync::Arc;
18
19use anyhow::Result;
20use axum::routing::{any, get, post};
21use axum::{Router, serve};
22use tokio::net::TcpListener;
23
24use crate::http::{self, admin, auth::AdminAuth, health::HealthState};
25use crate::routing::TenantRouting;
26use crate::runtime::ActivePacks;
27use crate::watcher::PackReloadHandle;
28
29pub struct HostServer {
30    addr: SocketAddr,
31    router: Router,
32    _state: ServerState,
33}
34
35impl HostServer {
36    pub fn new(
37        port: u16,
38        active: Arc<ActivePacks>,
39        routing: TenantRouting,
40        health: Arc<HealthState>,
41        reload: Option<PackReloadHandle>,
42        admin: AdminAuth,
43    ) -> Result<Self> {
44        let addr = SocketAddr::from(([0, 0, 0, 0], port));
45        let state = ServerState {
46            active,
47            routing,
48            health,
49            reload,
50            admin,
51        };
52        let router = Router::new()
53            .route(
54                "/messaging/telegram/webhook",
55                post(adapt_messaging::telegram_webhook),
56            )
57            .route("/webchat/activities", post(adapt_webchat::activities))
58            .route("/teams/activities", post(adapt_teams::activities))
59            .route("/slack/events", post(adapt_slack::events))
60            .route("/slack/interactive", post(adapt_slack::interactive))
61            .route("/webex/webhook", post(adapt_webex::webhook))
62            .route(
63                "/whatsapp/webhook",
64                get(adapt_whatsapp::verify).post(adapt_whatsapp::webhook),
65            )
66            .route("/webhook/{flow_id}", any(adapt_webhook::dispatch))
67            .route("/operator/op/invoke", post(operator::invoke))
68            .route("/healthz", get(http::health::handler))
69            .route("/admin/packs/status", get(admin::status))
70            .route("/admin/packs/reload", post(admin::reload))
71            .with_state(state.clone());
72        Ok(Self {
73            addr,
74            router,
75            _state: state,
76        })
77    }
78
79    pub async fn serve(self) -> Result<()> {
80        tracing::info!(addr = %self.addr, "starting host server");
81        let listener = TcpListener::bind(self.addr).await?;
82        serve(
83            listener,
84            self.router
85                .into_make_service_with_connect_info::<SocketAddr>(),
86        )
87        .await?;
88        Ok(())
89    }
90}
91
92#[derive(Clone)]
93pub struct ServerState {
94    pub active: Arc<ActivePacks>,
95    pub routing: TenantRouting,
96    pub health: Arc<HealthState>,
97    pub reload: Option<PackReloadHandle>,
98    pub admin: AdminAuth,
99}