Skip to main content

rustfs_targets/catalog/
mod.rs

1// Copyright 2024 RustFS Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15pub mod builtin;
16pub mod extension;
17
18use crate::control_plane::external_target_plugin_installation;
19use crate::domain::TargetDomain;
20use crate::manifest::{
21    TargetPluginArtifactManifest, TargetPluginDistributionManifest, TargetPluginEntrypointKind,
22    TargetPluginExternalRuntimeContract, TargetPluginManifest, TargetPluginMarketplaceManifest, TargetPluginRuntimeTransport,
23    installable_target_marketplace_manifest,
24};
25use crate::runtime::sidecar::{SidecarPluginRuntime, SidecarRuntimePolicy, SidecarRuntimeSafetyChecks};
26use crate::runtime::sidecar_protocol::{SIDECAR_RUNTIME_PROTOCOL_VERSION, SidecarHandshake, SidecarPluginCapability};
27
28#[derive(Debug, Clone, PartialEq, Eq)]
29pub struct ExampleInstallableTargetPlugin {
30    pub manifest: TargetPluginMarketplaceManifest,
31    pub installation: crate::TargetPluginInstallation,
32    pub runtime: SidecarPluginRuntime,
33    pub valid_fields: Vec<String>,
34}
35
36/// Test/demo fixture describing what an installable external plugin would
37/// look like. It must never be exposed through production admin responses;
38/// it exists so control-plane planning and contract tests can exercise the
39/// external-plugin shape before a real marketplace source exists.
40/// Test/demo fixture describing what an installable external plugin would
41/// look like. It must never be exposed through production admin responses;
42/// it exists so control-plane planning and contract tests can exercise the
43/// external-plugin shape before a real marketplace source exists.
44pub fn example_external_webhook_plugin() -> ExampleInstallableTargetPlugin {
45    let base = TargetPluginManifest {
46        plugin_id: "external:webhook-sidecar",
47        display_name: "Webhook Sidecar",
48        provider: "rustfs-labs",
49        version: "1.0.0",
50        target_type: "webhook",
51        supported_domains: &[TargetDomain::Notify],
52        secret_fields: &["auth_token"],
53    };
54    let manifest = installable_target_marketplace_manifest(
55        base,
56        TargetPluginEntrypointKind::Sidecar,
57        TargetPluginExternalRuntimeContract {
58            protocol_version: SIDECAR_RUNTIME_PROTOCOL_VERSION,
59            transport: TargetPluginRuntimeTransport::Grpc,
60        },
61        TargetPluginDistributionManifest {
62            artifacts: &[TargetPluginArtifactManifest {
63                artifact_id: "sidecar-linux-amd64",
64                target_triple: "x86_64-unknown-linux-gnu",
65                download_uri: "https://plugins.example.test/webhook-sidecar.tar.zst",
66                digest_sha256: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
67                signature_uri: "https://plugins.example.test/webhook-sidecar.tar.zst.sig",
68                provenance_uri: "https://plugins.example.test/webhook-sidecar.tar.zst.intoto.jsonl",
69                size_bytes: 8192,
70            }],
71        },
72    );
73
74    let handshake = SidecarHandshake {
75        protocol_version: SIDECAR_RUNTIME_PROTOCOL_VERSION.to_string(),
76        plugin_id: base.plugin_id.to_string(),
77        plugin_version: base.version.to_string(),
78        supported_domains: vec![TargetDomain::Notify],
79        capabilities: vec![
80            SidecarPluginCapability::HealthCheck,
81            SidecarPluginCapability::SendEvent,
82            SidecarPluginCapability::Shutdown,
83        ],
84    };
85    let mut runtime = SidecarPluginRuntime::new("grpc://127.0.0.1:50051", handshake);
86    runtime
87        .enable_with_policy(
88            base.plugin_id,
89            TargetDomain::Notify,
90            &SidecarRuntimePolicy::verified_external(16, std::time::Duration::from_secs(5), 3),
91            &SidecarRuntimeSafetyChecks::verified(0),
92        )
93        .expect("example sidecar plugin policy should validate");
94
95    ExampleInstallableTargetPlugin {
96        manifest,
97        installation: external_target_plugin_installation(
98            base.version,
99            "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
100            "sidecar-linux-amd64",
101            Some("2026-05-13T20:00:00Z".to_string()),
102        ),
103        runtime,
104        valid_fields: vec!["endpoint".to_string(), "auth_token".to_string()],
105    }
106}
107
108#[cfg(test)]
109mod tests {
110    use super::example_external_webhook_plugin;
111
112    #[test]
113    fn example_external_plugin_exposes_installation_and_runtime_metadata() {
114        let example = example_external_webhook_plugin();
115
116        assert_eq!(example.manifest.plugin_id, "external:webhook-sidecar");
117        assert_eq!(example.installation.install_state, crate::TargetPluginInstallState::Installed);
118        assert!(example.runtime.healthy);
119        assert_eq!(example.valid_fields, vec!["endpoint".to_string(), "auth_token".to_string()]);
120    }
121}