haproxy_config/config/
backend.rs

1use std::collections::{HashMap, HashSet};
2
3use super::Address;
4use super::{Acl, error::Error, Name, Server};
5use crate::section::borrowed::Section;
6use crate::line::borrowed::Line; 
7
8/// Frontends specify whether to forward traffic here 
9/// using [`config::backends`][super::frontend::Backend].
10#[derive(Debug, Clone, PartialEq, Eq)]
11pub struct Backend {
12    pub name: String,
13    pub config: HashMap<String, Option<String>>,
14    pub options: HashMap<String, Option<String>>,
15    pub acls: HashSet<Acl>,
16    pub servers: Vec<Server>,
17}
18
19type Pair = (Name, Backend);
20impl<'a> TryFrom<&'a Section<'a>> for Pair {
21    type Error = Error;
22
23    fn try_from(entry: &'a Section<'a>) -> Result<(Name, Backend), Self::Error> {
24        let Section::Backend{ proxy, lines,  ..} = entry else {
25            unreachable!()
26        };
27
28        let mut config = HashMap::new();
29        let mut options = HashMap::new();
30        let mut acls = HashSet::new();
31        let mut servers = Vec::new();
32        let mut other = Vec::new();
33
34        for line in lines
35            .iter()
36            .filter(|l| !matches!(l, Line::Blank | Line::Comment(_)))
37        {
38            match line {
39                Line::Config { key, value, .. } => {
40                    let key = (*key).to_string();
41                    let value = value.map(ToOwned::to_owned);
42                    config.insert(key, value);
43                }
44                Line::Option {
45                    keyword: key,
46                    value,
47                    ..
48                } => {
49                    let key = (*key).to_string();
50                    let value = value.map(ToOwned::to_owned);
51                    options.insert(key, value);
52                }
53                Line::Acl { name, rule, .. } => {
54                    acls.insert(Acl {
55                        name: (*name).to_string(),
56                        rule: rule.ok_or(Error::acl_without_rule(name))?.to_string(),
57                    });
58                }
59                Line::Server {
60                    name, addr, option, ..
61                } => servers.push(Server {
62                    name: (*name).to_string(),
63                    addr: Address::from(addr),
64                    option: option.map(ToOwned::to_owned),
65                }),
66                wrong => other.push(wrong),
67            }
68        }
69
70        if !other.is_empty() {
71            return Err(Error::wrong_backend_lines(other));
72        }
73
74        Ok((
75            (*proxy).to_string(),
76            Backend {
77                name: (*proxy).to_string(),
78                config,
79                options,
80                acls,
81                servers,
82            },
83        ))
84    }
85}
86
87impl<'a> Backend {
88    pub(crate) fn parse_multiple(entries: &'a [Section<'a>]) -> Result<HashMap<Name, Self>, Error> {
89        entries
90            .iter()
91            .filter(|e| matches!(e, Section::Backend { .. }))
92            .map(Pair::try_from)
93            .collect()
94    }
95}