1use crate::model::{load_inventory_from_file, EstimatedInventory};
9use aws_cloud_provider::*;
10use boavizta_api_v1::*;
11use cloud_provider::*;
12use impact_provider::ImpactProvider;
13use impact_provider::ImpactsSummary;
14use metric_exporter::*;
15use std::path::Path;
16
17#[macro_use]
18extern crate rocket;
19
20#[macro_use]
21extern crate log;
22use model::Inventory;
23use pkg_version::*;
24
25pub mod aws_cloud_provider;
26pub mod boavizta_api_v1;
27pub mod cloud_provider;
28pub mod estimated_inventory_exporter;
29pub mod impact_provider;
30pub mod inventory_exporter;
31pub mod metric_exporter;
32pub mod model;
33pub mod standalone_server;
34pub mod usage_location;
35
36use crate::estimated_inventory_exporter::build_impact_summary;
37use anyhow::{Context, Result};
38
39pub async fn estimate_impacts(
41 use_duration_hours: &f32,
42 tags: &[String],
43 aws_region: &str,
44 api_url: &str,
45 verbose: bool,
46 include_block_storage: bool,
47) -> Result<EstimatedInventory> {
48 let aws_provider: AwsCloudProvider = AwsCloudProvider::new(aws_region).await?;
49 let inventory: Inventory = aws_provider
50 .list_resources(tags, include_block_storage)
51 .await
52 .context("Cannot perform resources inventory")?;
53
54 let api: BoaviztaApiV1 = BoaviztaApiV1::new(api_url);
55 let estimated_inventory = api
56 .get_impacts(inventory, use_duration_hours, verbose)
57 .await
58 .context("Failure while retrieving impacts")?;
59
60 Ok(estimated_inventory)
61}
62
63pub async fn estimate_impacts_of_inventory_file(
65 use_duration_hours: &f32,
66 api_url: &str,
67 verbose: bool,
68 inventory_file: &Path,
69) -> Result<EstimatedInventory> {
70 let inventory = load_inventory_from_file(inventory_file)
71 .await
72 .context("Failed to load inventory file.")?;
73 let estimated_inventory =
74 estimate_impacts_of_inventory(use_duration_hours, api_url, verbose, inventory)
75 .await
76 .context("Cannot get estimations")?;
77 Ok(estimated_inventory)
78}
79
80pub async fn estimate_impacts_of_inventory(
82 use_duration_hours: &f32,
83 api_url: &str,
84 verbose: bool,
85 inventory: Inventory,
86) -> Result<EstimatedInventory> {
87 let api: BoaviztaApiV1 = BoaviztaApiV1::new(api_url);
88 let estimated_inventory = api
89 .get_impacts(inventory, use_duration_hours, verbose)
90 .await
91 .context("Failure while retrieving impacts")?;
92
93 Ok(estimated_inventory)
94}
95
96pub async fn get_impacts_as_metrics(
98 use_duration_hours: &f32,
99 tags: &[String],
100 aws_region: &str,
101 api_url: &str,
102 include_storage: bool,
103) -> Result<String> {
104 let resources_with_impacts = estimate_impacts(
105 use_duration_hours,
106 tags,
107 aws_region,
108 api_url,
109 false,
110 include_storage,
111 )
112 .await
113 .context("Cannot perform standard scan")?;
114
115 let summary: ImpactsSummary =
116 build_impact_summary(&resources_with_impacts, aws_region, use_duration_hours).await?;
117 debug!("Summary: {:#?}", summary);
118
119 let all_metrics = get_all_metrics(&summary, resources_with_impacts).with_context(|| {
120 format!(
121 "Unable to get resource impacts as metrics for region {}",
122 aws_region
123 )
124 })?;
125
126 Ok(all_metrics)
127}
128
129pub async fn get_inventory(
131 tags: &[String],
132 aws_region: &str,
133 include_block_storage: bool,
134) -> Result<Inventory> {
135 let aws_inventory: AwsCloudProvider = AwsCloudProvider::new(aws_region).await?;
136 let inventory: Inventory = aws_inventory
137 .list_resources(tags, include_block_storage)
138 .await
139 .context("Cannot perform inventory.")?;
140 Ok(inventory)
141}
142
143pub async fn serve_metrics(api_url: &str) -> Result<()> {
145 let config = standalone_server::Config {
146 boavizta_url: api_url.to_string(),
147 };
148 warn!("Starting server.");
149 standalone_server::run(config).await?;
150 Ok(())
151}
152pub fn get_version() -> String {
154 const MAJOR: u32 = pkg_version_major!();
155 const MINOR: u32 = pkg_version_minor!();
156 const PATCH: u32 = pkg_version_patch!();
157 format!("{}.{}.{}", MAJOR, MINOR, PATCH)
158}
159
160#[cfg(test)]
161mod tests {
162 use super::*;
163 use crate::model::EstimationMetadata;
164
165 #[tokio::test]
166 async fn summary_has_to_contain_a_usage_duration() {
167 use crate::impact_provider::CloudResourceWithImpacts;
168
169 let resources: Vec<CloudResourceWithImpacts> = Vec::new();
170
171 let resources_with_impacts: EstimatedInventory = EstimatedInventory {
172 impacting_resources: resources,
173 metadata: EstimationMetadata {
174 description: None,
175 boavizta_api_version: Some("v1.2.3".to_owned()),
176 cloud_scanner_version: Some("acb".to_owned()),
177 estimation_date: None,
178 execution_statistics: None,
179 },
180 };
181
182 let usage_duration_hours = 1.5;
183
184 let summary: ImpactsSummary = ImpactsSummary::new(
185 String::from("eu-west-1"),
186 String::from("IRL"),
187 &resources_with_impacts,
188 usage_duration_hours,
189 );
190
191 assert_eq!(
192 summary.duration_of_use_hours, usage_duration_hours,
193 "Duration of summary should match"
194 );
195 }
196}