redis_enterprise/
license.rs

1//! License management and validation
2//!
3//! ## Overview
4//! - Query license status
5//! - Update license keys
6//! - Monitor license expiration
7
8use crate::client::RestClient;
9use crate::error::Result;
10use serde::{Deserialize, Serialize};
11use serde_json::Value;
12use typed_builder::TypedBuilder;
13
14/// License information
15#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct License {
17    /// License key - the actual field name returned by API
18    #[serde(skip_serializing_if = "Option::is_none")]
19    pub key: Option<String>,
20
21    /// License string
22    #[serde(skip_serializing_if = "Option::is_none")]
23    pub license: Option<String>,
24
25    /// License type (trial, commercial, etc.)
26    #[serde(rename = "type")]
27    pub type_: Option<String>,
28
29    /// Mark license expired or not
30    pub expired: bool,
31
32    /// License activation date
33    #[serde(skip_serializing_if = "Option::is_none")]
34    pub activation_date: Option<String>,
35
36    /// License expiration date
37    #[serde(skip_serializing_if = "Option::is_none")]
38    pub expiration_date: Option<String>,
39
40    /// The cluster name as appears in the license
41    #[serde(skip_serializing_if = "Option::is_none")]
42    pub cluster_name: Option<String>,
43
44    /// Owner of license
45    #[serde(skip_serializing_if = "Option::is_none")]
46    pub owner: Option<String>,
47
48    /// Shards limit
49    #[serde(skip_serializing_if = "Option::is_none")]
50    pub shards_limit: Option<u32>,
51
52    /// Amount of RAM shards in use
53    #[serde(skip_serializing_if = "Option::is_none")]
54    pub ram_shards_in_use: Option<u32>,
55
56    /// Amount of RAM shards allowed
57    #[serde(skip_serializing_if = "Option::is_none")]
58    pub ram_shards_limit: Option<u32>,
59
60    /// Amount of flash shards in use
61    #[serde(skip_serializing_if = "Option::is_none")]
62    pub flash_shards_in_use: Option<u32>,
63
64    /// Amount of flash shards allowed
65    #[serde(skip_serializing_if = "Option::is_none")]
66    pub flash_shards_limit: Option<u32>,
67
68    /// Node limit (deprecated in favor of shards_limit)
69    #[serde(skip_serializing_if = "Option::is_none")]
70    pub node_limit: Option<u32>,
71
72    /// List of features supported by license
73    #[serde(skip_serializing_if = "Option::is_none")]
74    pub features: Option<Vec<String>>,
75
76    #[serde(flatten)]
77    pub extra: Value,
78}
79
80/// License update request
81#[derive(Debug, Clone, Serialize, Deserialize, TypedBuilder)]
82pub struct LicenseUpdateRequest {
83    /// New license key to install
84    #[builder(setter(into))]
85    pub license: String,
86}
87
88/// License usage statistics
89#[derive(Debug, Clone, Serialize, Deserialize)]
90pub struct LicenseUsage {
91    /// Number of shards currently in use
92    pub shards_used: u32,
93    /// Maximum number of shards allowed by license
94    pub shards_limit: u32,
95    /// Number of nodes currently in use
96    pub nodes_used: u32,
97    /// Maximum number of nodes allowed by license
98    pub nodes_limit: u32,
99    /// Amount of RAM currently in use (bytes)
100    #[serde(skip_serializing_if = "Option::is_none")]
101    pub ram_used: Option<u64>,
102    /// Maximum amount of RAM allowed by license (bytes)
103    #[serde(skip_serializing_if = "Option::is_none")]
104    pub ram_limit: Option<u64>,
105
106    #[serde(flatten)]
107    pub extra: Value,
108}
109
110/// License handler
111pub struct LicenseHandler {
112    client: RestClient,
113}
114
115impl LicenseHandler {
116    pub fn new(client: RestClient) -> Self {
117        LicenseHandler { client }
118    }
119
120    /// Get current license information
121    pub async fn get(&self) -> Result<License> {
122        self.client.get("/v1/license").await
123    }
124
125    /// Update license
126    pub async fn update(&self, request: LicenseUpdateRequest) -> Result<License> {
127        self.client.put("/v1/license", &request).await
128    }
129
130    /// Get license usage statistics
131    pub async fn usage(&self) -> Result<LicenseUsage> {
132        self.client.get("/v1/license/usage").await
133    }
134
135    /// Validate a license key
136    pub async fn validate(&self, license_key: &str) -> Result<License> {
137        let request = LicenseUpdateRequest {
138            license: license_key.to_string(),
139        };
140        self.client.post("/v1/license/validate", &request).await
141    }
142
143    /// Get license from cluster
144    pub async fn cluster_license(&self) -> Result<License> {
145        self.client.get("/v1/cluster/license").await
146    }
147}