use super::super::{DataSource, data_stream::DataStreamDocument};
use crate::data::u64_from_string;
use serde::{Deserialize, Deserializer, Serialize};
use serde_json::{Value, json, value::RawValue};
use serde_with::skip_serializing_none;
use std::collections::HashMap;
pub type IndicesSettings = HashMap<String, Settings>;
#[skip_serializing_none]
#[derive(Clone, Deserialize, Serialize)]
pub struct IndexSettings {
pub allocation: Option<Box<RawValue>>,
pub auto_expand_replicas: Option<String>,
pub blocks: Option<Box<RawValue>>,
#[serde(default = "default_to_default", deserialize_with = "deserialize_codec")]
pub codec: String,
#[serde(deserialize_with = "u64_from_string")]
pub creation_date: Option<u64>,
pub default_pipeline: Option<String>,
pub final_pipeline: Option<String>,
pub hidden: Option<String>,
#[serde(default)]
pub is_write_index: bool,
pub lifecycle: Option<Box<RawValue>>,
pub mapping: Option<Box<RawValue>>,
#[serde(default = "default_to_standard")]
pub mode: String,
#[serde(deserialize_with = "u64_from_string")]
pub number_of_replicas: Option<u64>,
#[serde(deserialize_with = "u64_from_string")]
pub number_of_shards: Option<u64>,
pub priority: Option<String>,
pub provided_name: Option<String>,
pub query: Option<Box<RawValue>>,
#[serde(default = "default_to_default")]
pub refresh_interval: String,
pub routing: Option<Box<RawValue>>,
pub shard: Option<Box<RawValue>>,
pub shard_limit: Option<Box<RawValue>>,
pub sort: Option<Box<RawValue>>,
pub source: Option<String>,
pub store: Option<StoreSettings>,
pub uuid: String,
pub version: Option<Box<RawValue>>,
#[serde(skip_deserializing)]
pub age: Option<u64>,
#[serde(skip_deserializing)]
pub data_stream: Option<DataStreamDocument>,
#[serde(skip_deserializing)]
pub name: Option<String>,
}
#[skip_serializing_none]
#[derive(Clone, Serialize, Deserialize)]
pub struct StoreSettings {
pub config: Option<String>,
pub store_type: Option<String>,
pub snapshot: Option<StoreSnapshot>,
}
#[skip_serializing_none]
#[derive(Clone, Serialize, Deserialize)]
pub struct StoreSnapshot {
pub snapshot_name: String,
pub index_uuid: String,
pub repository_uuid: Option<String>,
pub index_name: String,
pub partial: Option<String>,
pub repository_name: String,
pub snapshot_uuid: String,
}
impl IndexSettings {
pub fn build(mut self) -> Self {
let source = self.source_mode();
let config = format!("{}-{}-{}", &self.mode, source, &self.codec);
match self.store.as_mut() {
Some(store) => {
store.config = Some(config);
}
None => {
self.store = Some(StoreSettings {
config: Some(config),
store_type: None,
snapshot: None,
});
}
}
self.source = Some(source);
self
}
pub fn age(self, epoch_millis: u64) -> Self {
Self {
age: self.creation_date.map(|date| epoch_millis - date),
..self
}
}
pub fn data_stream(self, data_stream: Option<DataStreamDocument>) -> Self {
let is_data_stream_write_index = data_stream.as_ref().is_some_and(|ds| ds.is_write_index);
Self {
data_stream,
is_write_index: self.is_write_index || is_data_stream_write_index,
..self
}
}
pub fn name(self, name: String) -> Self {
Self {
name: Some(name),
..self
}
}
fn source_mode(&self) -> String {
let mapping = self
.mapping
.as_ref()
.and_then(|r| serde_json::from_str::<Value>(r.get()).ok())
.unwrap_or(Value::Null);
mapping
.as_object()
.and_then(|mapping| mapping.get("source"))
.and_then(|source| source.get("mode"))
.and_then(|mode| mode.as_str())
.unwrap_or("default")
.to_string()
}
pub fn get_lifecycle(&self) -> Value {
let lifecycle = self
.lifecycle
.as_ref()
.and_then(|r| serde_json::from_str::<Value>(r.get()).ok())
.unwrap_or(Value::Null);
json!({
"name": lifecycle.get("name"),
"rollover_alias": lifecycle.get("rollover_alias"),
"indexing_complete": lifecycle.get("indexing_complete"),
})
}
}
impl std::default::Default for IndexSettings {
fn default() -> Self {
IndexSettings {
allocation: None,
auto_expand_replicas: None,
blocks: None,
codec: "unknown".to_string(),
creation_date: None,
default_pipeline: None,
final_pipeline: None,
hidden: None,
is_write_index: false,
lifecycle: None,
mapping: None,
mode: "unkown".to_string(),
number_of_replicas: None,
number_of_shards: None,
priority: None,
provided_name: None,
query: None,
refresh_interval: "unkown".to_string(),
routing: None,
shard: None,
shard_limit: None,
source: None,
store: None,
sort: None,
uuid: "".to_string(),
version: None,
age: None,
data_stream: None,
name: None,
}
}
}
#[derive(Deserialize, Serialize)]
pub struct Settings {
pub settings: Index,
}
#[derive(Deserialize, Serialize)]
pub struct Index {
pub index: IndexSettings,
}
fn default_to_default() -> String {
String::from("default")
}
fn default_to_standard() -> String {
String::from("standard")
}
fn deserialize_codec<'de, D>(deserializer: D) -> Result<String, D::Error>
where
D: Deserializer<'de>,
{
let value: Option<Value> = Deserialize::deserialize(deserializer)?;
match value {
Some(Value::String(s)) => Ok(s),
Some(Value::Null) => Ok(default_to_default()),
Some(_) => Err(serde::de::Error::custom("codec expects a string or null")),
None => Ok(default_to_default()),
}
}
impl DataSource for IndicesSettings {
fn name() -> String {
"indices_settings".to_string()
}
fn aliases() -> Vec<&'static str> {
vec!["settings"]
}
}