-
Notifications
You must be signed in to change notification settings - Fork 34
/
Copy pathmod.rs
159 lines (135 loc) · 4.47 KB
/
mod.rs
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
151
152
153
154
155
156
157
158
159
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
mod command_discovery;
mod discovery_trait;
use crate::discovery::discovery_trait::ResourceDiscovery;
use crate::{dscresources::dscresource::DscResource, dscerror::DscError, util::ResourceFilter};
use std::collections::BTreeMap;
use tracing::error;
pub struct Discovery {
pub resources: BTreeMap<String, DscResource>,
}
impl Discovery {
/// Create a new `Discovery` instance.
///
/// # Errors
///
/// This function will return an error if the underlying instance creation fails.
///
pub fn new() -> Result<Self, DscError> {
Ok(Self {
resources: BTreeMap::new(),
})
}
/// List operation for getting available resources based on the filters.
///
/// # Arguments
///
/// * `type_name_filter` - The filter for the resource type name.
/// * `adapter_name_filter` - The filter for the adapter name.
///
/// # Returns
///
/// A vector of `DscResource` instances.
pub fn list_available_resources(&mut self, type_name_filter: &str, adapter_name_filter: &str) -> Vec<DscResource> {
let discovery_types: Vec<Box<dyn ResourceDiscovery>> = vec![
Box::new(command_discovery::CommandDiscovery::new()),
];
let mut resources: Vec<DscResource> = Vec::new();
for mut discovery_type in discovery_types {
let discovered_resources = match discovery_type.list_available_resources(type_name_filter, adapter_name_filter) {
Ok(value) => value,
Err(err) => {
error!("{err}");
continue;
}
};
for (_resource_name, found_resources) in discovered_resources {
for resource in found_resources {
resources.push(resource.clone());
}
};
}
resources
}
#[must_use]
pub fn find_resource(&self, type_name: &str) -> Option<&DscResource> {
self.resources.get(&type_name.to_lowercase())
}
/// Find resources based on the required resource types.
///
/// # Arguments
///
/// * `required_resource_types` - The required resource types.
pub fn find_resources(&mut self, required_resource_types: &[ResourceFilter]) {
let discovery_types: Vec<Box<dyn ResourceDiscovery>> = vec![
Box::new(command_discovery::CommandDiscovery::new()),
];
let mut remaining_required_resource_types = required_resource_types.to_owned();
for mut discovery_type in discovery_types {
let discovered_resources = match discovery_type.find_resources(&remaining_required_resource_types) {
Ok(value) => value,
Err(err) => {
error!("{err}");
continue;
}
};
for resource in discovered_resources {
self.resources.insert(resource.0.clone(), resource.1);
remaining_required_resource_types.retain(|x| *x.type_name_filter != resource.0);
};
}
}
}
fn convert_wildcard_to_regex(wildcard: &str) -> String {
let mut regex = wildcard.to_string().replace('.', "\\.").replace('?', ".").replace('*', ".*?");
regex.insert(0, '^');
regex.push('$');
regex
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_convert_wildcard_to_regex() {
let wildcard = "*";
let regex = convert_wildcard_to_regex(wildcard);
assert_eq!(regex, "^.*?$");
let wildcard = "File";
let regex = convert_wildcard_to_regex(wildcard);
assert_eq!(regex, "^File$");
let wildcard = "r*";
let regex = convert_wildcard_to_regex(wildcard);
assert_eq!(regex, "^r.*?$");
}
}
impl Default for Discovery {
fn default() -> Self {
Self::new().unwrap()
}
}
pub struct ResourceIterator {
resources: Vec<DscResource>,
index: usize,
}
impl ResourceIterator {
#[must_use]
pub fn new(resources: Vec<DscResource>) -> ResourceIterator {
ResourceIterator {
resources,
index: 0,
}
}
}
impl Iterator for ResourceIterator {
type Item = DscResource;
fn next(&mut self) -> Option<Self::Item> {
if self.index < self.resources.len() {
let resource = self.resources[self.index].clone();
self.index += 1;
Some(resource)
} else {
None
}
}
}