summaryrefslogtreecommitdiff
path: root/crates/common/src/manager/reload.rs
blob: 143d4008a25a8fcf145f0113fae7be70c60f57a7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/*
 * SPDX-FileCopyrightText: 2020 Stalwart Labs Ltd <hello@stalw.art>
 *
 * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
 */

use ahash::AHashMap;
use arc_swap::ArcSwap;
use store::Stores;
use utils::config::Config;

use crate::{
    config::{
        server::{tls::parse_certificates, Listeners},
        telemetry::Telemetry,
    },
    listener::blocked::{BlockedIps, BLOCKED_IP_KEY},
    Core, Server,
};

use super::config::{ConfigManager, Patterns};

pub struct ReloadResult {
    pub config: Config,
    pub new_core: Option<Core>,
    pub tracers: Option<Telemetry>,
}

impl Server {
    pub async fn reload_blocked_ips(&self) -> trc::Result<ReloadResult> {
        let mut config = self
            .core
            .storage
            .config
            .build_config(BLOCKED_IP_KEY)
            .await?;
        *self.inner.data.blocked_ips.write() = BlockedIps::parse(&mut config).blocked_ip_addresses;

        Ok(config.into())
    }

    pub async fn reload_certificates(&self) -> trc::Result<ReloadResult> {
        let mut config = self.core.storage.config.build_config("certificate").await?;
        let mut certificates = self.inner.data.tls_certificates.load().as_ref().clone();

        parse_certificates(&mut config, &mut certificates, &mut Default::default());

        self.inner.data.tls_certificates.store(certificates.into());

        Ok(config.into())
    }

    pub async fn reload_lookups(&self) -> trc::Result<ReloadResult> {
        let mut config = self.core.storage.config.build_config("lookup").await?;
        let mut stores = Stores::default();
        stores.parse_memory_stores(&mut config);

        let mut core = self.core.as_ref().clone();
        for (id, store) in stores.lookup_stores {
            core.storage.lookups.insert(id, store);
        }

        Ok(ReloadResult {
            config,
            new_core: core.into(),
            tracers: None,
        })
    }

    pub async fn reload(&self) -> trc::Result<ReloadResult> {
        let mut config = self.core.storage.config.build_config("").await?;

        // Load stores
        let mut stores = Stores {
            stores: self.core.storage.stores.clone(),
            blob_stores: self.core.storage.blobs.clone(),
            fts_stores: self.core.storage.ftss.clone(),
            lookup_stores: self.core.storage.lookups.clone(),
            purge_schedules: Default::default(),
        };
        stores.parse_stores(&mut config).await;
        stores.parse_lookups(&mut config).await;

        // Parse tracers
        let tracers = Telemetry::parse(&mut config, &stores);

        if !config.errors.is_empty() {
            return Ok(config.into());
        }

        // Build manager
        let manager = ConfigManager {
            cfg_local: ArcSwap::from_pointee(
                self.core.storage.config.cfg_local.load().as_ref().clone(),
            ),
            cfg_local_path: self.core.storage.config.cfg_local_path.clone(),
            cfg_local_patterns: Patterns::parse(&mut config).into(),
            cfg_store: config
                .value("storage.data")
                .and_then(|id| stores.stores.get(id))
                .cloned()
                .unwrap_or_default(),
        };

        // Parse settings and build shared core
        let core = Core::parse(&mut config, stores, manager).await;
        if !config.errors.is_empty() {
            return Ok(config.into());
        }

        // Update TLS certificates
        let mut new_certificates = AHashMap::new();
        parse_certificates(&mut config, &mut new_certificates, &mut Default::default());
        let mut current_certificates = self.inner.data.tls_certificates.load().as_ref().clone();
        for (cert_id, cert) in new_certificates {
            current_certificates.insert(cert_id, cert);
        }
        self.inner
            .data
            .tls_certificates
            .store(current_certificates.into());

        // Update blocked IPs
        *self.inner.data.blocked_ips.write() = BlockedIps::parse(&mut config).blocked_ip_addresses;

        // Parser servers
        let mut servers = Listeners::parse(&mut config);
        servers.parse_tcp_acceptors(&mut config, self.inner.clone());

        Ok(if config.errors.is_empty() {
            ReloadResult {
                config,
                new_core: core.into(),
                tracers: tracers.into(),
            }
        } else {
            config.into()
        })
    }
}

impl From<Config> for ReloadResult {
    fn from(config: Config) -> Self {
        Self {
            config,
            new_core: None,
            tracers: None,
        }
    }
}