azure_script/
parser.rs

1//! This module provides functionality to parse and process Azure configuration files.
2//! It supports YAML-based configuration for Azure subscriptions, resource groups, and key vaults.
3//! The module also includes helpers for making authenticated API calls to Azure Resource Manager.
4
5use serde::{Deserialize, Serialize};
6use serde_yaml;
7use serde_json::json;
8use std::fs;
9use std::path::PathBuf;
10use crate::rest_helper;
11use crate::models::{Authentication, AzureConfig, ResourceGroup, Subscription};
12use crate::subscriptions::list_subscriptions;
13
14
15
16
17/// Parses an Azure configuration file from a YAML file.
18///
19/// # Arguments
20/// * `file_path` - The path to the YAML configuration file.
21/// * `access_token` - The Azure access token for API authentication.
22///
23/// # Returns
24/// * `Result<AzureConfig, Box<dyn std::error::Error>>` - The parsed configuration or an error.
25///
26/// # Example
27/// ```rust, ignore
28/// use std::path::PathBuf;
29/// let file_path = PathBuf::from("config.yaml");
30/// let access_token = "your_access_token";
31/// let config = parse(&file_path, access_token).await?;
32/// ```
33pub async fn parse(file_path: &PathBuf, access_token: &str) -> Result<AzureConfig, Box<dyn std::error::Error>> {
34    print!("Starting to parse the Azure configuration file...\n");
35    //store the access token for later use
36    let auth = Authentication {
37        access_token: access_token.to_string(),
38    };
39
40    //parse yaml file into AzureConfig struct.
41    let yaml_content = fs::read_to_string(file_path)?;
42    println!("YAML content read from file: \n{}", yaml_content);
43    let config: AzureConfig = match serde_yaml::from_str(&yaml_content) {
44    Ok(c) => c,
45    Err(e) => {
46        println!("Failed to parse YAML: {:?}", e);
47        return Err(Box::new(e));
48    }
49    };
50
51    //get the list of subscriptions from Azure API
52    let azure_subscriptions = list_subscriptions(&auth.access_token).await?;
53
54    //iterate over the subscriptions in the azure config
55    for subscription in &config.subscriptions {
56        //check if subscription actually exists in Azure
57        if !azure_subscriptions.iter().any(|sub| sub.id == subscription.id) {
58            println!("Subscription ID {} not found in Azure. Skipping...", subscription.id);
59            continue;
60        }
61        //if subscription exists, process it
62        println!("Processing subscription: {:?}", subscription);
63        parse_rg_call(subscription, &auth).await;
64    }
65
66    
67    Ok(config)
68}
69
70
71async fn parse_rg_call(subscription: &Subscription, access_token: &Authentication) {
72    let resource_groups = match &subscription.resource_groups {
73        Some(rg) if !rg.is_empty() => rg,
74        Some(_) => {
75            println!("The resource_groups vector is empty!");
76            return;
77        }
78        None => {
79            println!("No resource_groups found!");
80            return;
81        }
82    };
83
84    //iterate over the resourcegroups
85    for ResourceGroup in resource_groups {
86        println!("Processing Resource Group: {:?}", ResourceGroup);
87
88        let endpoint = format!(
89        "https://management.azure.com/subscriptions/{}/resourcegroups/{}?api-version=2021-04-01",
90        subscription.id,
91        ResourceGroup.name.as_deref().unwrap_or("unknown")
92        );
93
94        let body = json!({
95            "location": ResourceGroup.region.as_deref().unwrap_or("eastus"),
96        });
97
98        println!("Endpoint: {}", endpoint);
99        println!("Body: {}", body);
100
101        match rest_helper::call_azure_api(&endpoint, &access_token.access_token, &body).await {
102            Ok(response) => {
103                println!("API call successful. Response: {:?}", response);
104            }
105            Err(e) => {
106                println!("API call failed. Error: {:?}", e);
107            }
108        }
109        
110    } 
111    
112}
113
114