Skip to main content

headless_lms_chatbot/
azure_datasources.rs

1use secrecy::ExposeSecret;
2use serde_json::json;
3
4use crate::prelude::*;
5
6pub const API_VERSION: &str = "2024-07-01";
7
8pub async fn does_azure_datasource_exist(
9    datasource_name: &str,
10    app_config: &ApplicationConfiguration,
11) -> anyhow::Result<bool> {
12    let azure_config = app_config.azure_configuration.as_ref().ok_or_else(|| {
13        anyhow::anyhow!("Azure configuration is missing from the application configuration")
14    })?;
15
16    let search_config = azure_config.search_config.as_ref().ok_or_else(|| {
17        anyhow::anyhow!("Azure search configuration is missing from the Azure configuration")
18    })?;
19    let mut url = search_config.search_endpoint.clone();
20    url.set_path(&format!("datasources('{}')", datasource_name));
21    url.set_query(Some(&format!("api-version={}", API_VERSION)));
22
23    let response = REQWEST_CLIENT
24        .get(url)
25        .header("Content-Type", "application/json")
26        .header("api-key", search_config.search_api_key.expose_secret())
27        .send()
28        .await?;
29
30    if response.status().is_success() {
31        Ok(true)
32    } else if response.status() == 404 {
33        Ok(false)
34    } else {
35        let status = response.status();
36        let error_text = response.text().await?;
37        Err(anyhow::anyhow!(
38            "Error checking if index exists. Status: {}. Error: {}",
39            status,
40            error_text
41        ))
42    }
43}
44
45pub async fn create_azure_datasource(
46    datasource_name: &str,
47    container_name: &str,
48    app_config: &ApplicationConfiguration,
49) -> anyhow::Result<()> {
50    // Retrieve Azure configurations from the application configuration
51    let azure_config = app_config.azure_configuration.as_ref().ok_or_else(|| {
52        anyhow::anyhow!("Azure configuration is missing from the application configuration")
53    })?;
54
55    let search_config = azure_config.search_config.as_ref().ok_or_else(|| {
56        anyhow::anyhow!("Azure search configuration is missing from the Azure configuration")
57    })?;
58
59    let blob_storage_config = azure_config.blob_storage_config.as_ref().ok_or_else(|| {
60        anyhow::anyhow!("Blob storage configuration is missing from the Azure configuration")
61    })?;
62
63    let connection_string = blob_storage_config.connection_string()?;
64
65    let mut url = search_config.search_endpoint.clone();
66    url.set_path(&format!("datasources/{}", datasource_name));
67    url.set_query(Some(&format!("api-version={}", API_VERSION)));
68
69    let datasource_definition = json!({
70        "name": datasource_name,
71        "type": "azureblob",
72        "container": {
73            "name": container_name,
74        },
75        "credentials": {
76            "connectionString": connection_string.expose_secret(),
77        },
78        "dataDeletionDetectionPolicy": {
79            "@odata.type": "#Microsoft.Azure.Search.NativeBlobSoftDeleteDeletionDetectionPolicy",
80        }
81    });
82
83    let response = REQWEST_CLIENT
84        .put(url)
85        .header("Content-Type", "application/json")
86        .header("api-key", search_config.search_api_key.expose_secret())
87        .json(&datasource_definition)
88        .send()
89        .await?;
90
91    if response.status().is_success() {
92        Ok(())
93    } else {
94        let status = response.status();
95        let error_text = response.text().await?;
96        Err(anyhow::anyhow!(
97            "Error creating datasource. Status: {}. Error: {}",
98            status,
99            error_text
100        ))
101    }
102}