Skip to content

Commit 6df5824

Browse files
feat(enterprise): add JSON schema command (#167) (#298)
- Simple get command to retrieve API schema - Useful for validation and documentation - JMESPath query support for extracting definitions - Comprehensive mdBook documentation
1 parent edab00f commit 6df5824

File tree

6 files changed

+363
-0
lines changed

6 files changed

+363
-0
lines changed

crates/redisctl/src/cli.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,6 +1023,10 @@ pub enum EnterpriseCommands {
10231023
#[command(subcommand, name = "job-scheduler")]
10241024
JobScheduler(crate::commands::enterprise::job_scheduler::JobSchedulerCommands),
10251025

1026+
/// JSON schema operations
1027+
#[command(subcommand)]
1028+
Jsonschema(crate::commands::enterprise::jsonschema::JsonSchemaCommands),
1029+
10261030
/// Log operations
10271031
#[command(subcommand)]
10281032
Logs(crate::commands::enterprise::logs::LogsCommands),
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
use anyhow::Context;
2+
use clap::Subcommand;
3+
4+
use crate::{cli::OutputFormat, connection::ConnectionManager, error::Result as CliResult};
5+
6+
#[allow(dead_code)]
7+
pub async fn handle_jsonschema_command(
8+
conn_mgr: &ConnectionManager,
9+
profile_name: Option<&str>,
10+
jsonschema_cmd: JsonSchemaCommands,
11+
output_format: OutputFormat,
12+
query: Option<&str>,
13+
) -> CliResult<()> {
14+
jsonschema_cmd
15+
.execute(conn_mgr, profile_name, output_format, query)
16+
.await
17+
}
18+
19+
#[derive(Debug, Clone, Subcommand)]
20+
pub enum JsonSchemaCommands {
21+
/// Get JSON schema for API validation
22+
Get,
23+
}
24+
25+
impl JsonSchemaCommands {
26+
#[allow(dead_code)]
27+
pub async fn execute(
28+
&self,
29+
conn_mgr: &ConnectionManager,
30+
profile_name: Option<&str>,
31+
output_format: OutputFormat,
32+
query: Option<&str>,
33+
) -> CliResult<()> {
34+
handle_jsonschema_command_impl(conn_mgr, profile_name, self, output_format, query).await
35+
}
36+
}
37+
38+
#[allow(dead_code)]
39+
async fn handle_jsonschema_command_impl(
40+
conn_mgr: &ConnectionManager,
41+
profile_name: Option<&str>,
42+
command: &JsonSchemaCommands,
43+
output_format: OutputFormat,
44+
query: Option<&str>,
45+
) -> CliResult<()> {
46+
let client = conn_mgr.create_enterprise_client(profile_name).await?;
47+
48+
match command {
49+
JsonSchemaCommands::Get => {
50+
let response: serde_json::Value = client
51+
.get("/v1/jsonschema")
52+
.await
53+
.context("Failed to get JSON schema")?;
54+
55+
let output_data = if let Some(q) = query {
56+
super::utils::apply_jmespath(&response, q)?
57+
} else {
58+
response
59+
};
60+
61+
super::utils::print_formatted_output(output_data, output_format)?;
62+
}
63+
}
64+
65+
Ok(())
66+
}
67+
68+
#[cfg(test)]
69+
mod tests {
70+
use super::*;
71+
72+
#[test]
73+
fn test_jsonschema_command_parsing() {
74+
use clap::Parser;
75+
76+
#[derive(Parser)]
77+
struct TestCli {
78+
#[command(subcommand)]
79+
cmd: JsonSchemaCommands,
80+
}
81+
82+
// Test get command
83+
let cli = TestCli::parse_from(["test", "get"]);
84+
assert!(matches!(cli.cmd, JsonSchemaCommands::Get));
85+
}
86+
}

crates/redisctl/src/commands/enterprise/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ pub mod database_impl;
1313
pub mod diagnostics;
1414
pub mod endpoint;
1515
pub mod job_scheduler;
16+
pub mod jsonschema;
1617
pub mod logs;
1718
pub mod logs_impl;
1819
pub mod migration;

crates/redisctl/src/main.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,16 @@ async fn execute_enterprise_command(
324324
)
325325
.await
326326
}
327+
Jsonschema(jsonschema_cmd) => {
328+
commands::enterprise::jsonschema::handle_jsonschema_command(
329+
conn_mgr,
330+
profile,
331+
jsonschema_cmd.clone(),
332+
output,
333+
query,
334+
)
335+
.await
336+
}
327337
Logs(logs_cmd) => {
328338
commands::enterprise::logs_impl::handle_logs_commands(
329339
conn_mgr, profile, logs_cmd, output, query,

docs/src/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
- [Diagnostics](./enterprise/diagnostics.md)
4747
- [Endpoints](./enterprise/endpoints.md)
4848
- [Job Scheduler](./enterprise/job-scheduler.md)
49+
- [JSON Schema](./enterprise/jsonschema.md)
4950
- [Workflows](./enterprise/workflows.md)
5051
- [Raw API Access](./enterprise/api-access.md)
5152

docs/src/enterprise/jsonschema.md

Lines changed: 261 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,261 @@
1+
# JSON Schema
2+
3+
The JSON schema command provides access to the Redis Enterprise API schema definitions, useful for validation, documentation, and code generation.
4+
5+
## Available Commands
6+
7+
### Get JSON Schema
8+
9+
Retrieve the complete JSON schema for the Redis Enterprise API:
10+
11+
```bash
12+
# Get full JSON schema
13+
redisctl enterprise jsonschema get
14+
15+
# Get schema as YAML
16+
redisctl enterprise jsonschema get -o yaml
17+
18+
# Extract specific schema definitions
19+
redisctl enterprise jsonschema get -q 'definitions'
20+
21+
# Get schema for a specific resource
22+
redisctl enterprise jsonschema get -q 'definitions.bdb'
23+
24+
# List all available definitions
25+
redisctl enterprise jsonschema get -q 'definitions | keys(@)'
26+
```
27+
28+
## Output Examples
29+
30+
### Schema Structure
31+
```json
32+
{
33+
"$schema": "http://json-schema.org/draft-07/schema#",
34+
"title": "Redis Enterprise API Schema",
35+
"version": "1.0.0",
36+
"definitions": {
37+
"bdb": {
38+
"type": "object",
39+
"properties": {
40+
"uid": {
41+
"type": "integer",
42+
"description": "Database unique ID"
43+
},
44+
"name": {
45+
"type": "string",
46+
"description": "Database name"
47+
},
48+
"memory_size": {
49+
"type": "integer",
50+
"description": "Memory limit in bytes"
51+
},
52+
"shards_count": {
53+
"type": "integer",
54+
"minimum": 1,
55+
"description": "Number of database shards"
56+
}
57+
},
58+
"required": ["name", "memory_size"]
59+
},
60+
"node": {
61+
"type": "object",
62+
"properties": {
63+
"uid": {
64+
"type": "integer",
65+
"description": "Node unique ID"
66+
},
67+
"addr": {
68+
"type": "string",
69+
"format": "ipv4",
70+
"description": "Node IP address"
71+
}
72+
}
73+
}
74+
},
75+
"paths": {
76+
"/v1/bdbs": {
77+
"post": {
78+
"requestBody": {
79+
"$ref": "#/definitions/bdb"
80+
}
81+
}
82+
}
83+
}
84+
}
85+
```
86+
87+
## Common Use Cases
88+
89+
### API Validation
90+
91+
Validate request payloads against the schema:
92+
93+
```bash
94+
# Get schema for database creation
95+
redisctl enterprise jsonschema get -q 'definitions.bdb'
96+
97+
# Extract required fields
98+
redisctl enterprise jsonschema get -q 'definitions.bdb.required'
99+
100+
# Get property types
101+
redisctl enterprise jsonschema get -q 'definitions.bdb.properties | to_entries[] | {property: .key, type: .value.type}'
102+
```
103+
104+
### Code Generation
105+
106+
Generate TypeScript or other language definitions:
107+
108+
```bash
109+
# Export schema for code generation
110+
redisctl enterprise jsonschema get -o json > redis-enterprise-schema.json
111+
112+
# Extract definitions for specific resources
113+
redisctl enterprise jsonschema get -q 'definitions.{database: bdb, cluster: cluster, node: node}' > resources.json
114+
115+
# Generate TypeScript interfaces (using external tool)
116+
redisctl enterprise jsonschema get | npx json-schema-to-typescript > redis-enterprise.d.ts
117+
```
118+
119+
### Documentation
120+
121+
Extract schema information for documentation:
122+
123+
```bash
124+
# Get all resource definitions
125+
redisctl enterprise jsonschema get -q 'definitions | keys(@)' -o json
126+
127+
# Get descriptions for properties
128+
redisctl enterprise jsonschema get -q 'definitions.bdb.properties | to_entries[] | {property: .key, description: .value.description}'
129+
130+
# List all API paths
131+
redisctl enterprise jsonschema get -q 'paths | keys(@)'
132+
133+
# Get operations for a path
134+
redisctl enterprise jsonschema get -q 'paths."/v1/bdbs" | keys(@)'
135+
```
136+
137+
### Schema Discovery
138+
139+
Explore available schemas and their structures:
140+
141+
```bash
142+
# List all top-level schema properties
143+
redisctl enterprise jsonschema get -q 'keys(@)'
144+
145+
# Find schemas with specific properties
146+
redisctl enterprise jsonschema get -q 'definitions | to_entries[] | select(.value.properties.memory_size) | .key'
147+
148+
# Get enum values for properties
149+
redisctl enterprise jsonschema get -q 'definitions.*.properties.* | select(.enum) | {property: @, values: .enum}'
150+
151+
# Find required properties across all schemas
152+
redisctl enterprise jsonschema get -q 'definitions | to_entries[] | {schema: .key, required: .value.required}'
153+
```
154+
155+
## Integration Examples
156+
157+
### Validation Script
158+
159+
Create a validation script using the schema:
160+
161+
```bash
162+
#!/bin/bash
163+
# validate-payload.sh
164+
165+
SCHEMA=$(redisctl enterprise jsonschema get -q 'definitions.bdb')
166+
PAYLOAD=$1
167+
168+
echo "$PAYLOAD" | jq --argjson schema "$SCHEMA" '
169+
# Simple validation example
170+
if .name == null then
171+
error("name is required")
172+
elif .memory_size == null then
173+
error("memory_size is required")
174+
else
175+
.
176+
end
177+
'
178+
```
179+
180+
### OpenAPI Generation
181+
182+
Convert to OpenAPI specification:
183+
184+
```bash
185+
# Extract and format for OpenAPI
186+
redisctl enterprise jsonschema get -o json | jq '{
187+
openapi: "3.0.0",
188+
info: {
189+
title: "Redis Enterprise API",
190+
version: .version
191+
},
192+
components: {
193+
schemas: .definitions
194+
},
195+
paths: .paths
196+
}' > openapi.json
197+
```
198+
199+
### Schema Comparison
200+
201+
Compare schemas across versions:
202+
203+
```bash
204+
# Save current schema
205+
redisctl enterprise jsonschema get -o json > schema-current.json
206+
207+
# Later, compare with new version
208+
redisctl enterprise jsonschema get -o json > schema-new.json
209+
diff <(jq -S . schema-current.json) <(jq -S . schema-new.json)
210+
211+
# Find new properties
212+
jq -r '.definitions | keys(@)' schema-new.json | \
213+
comm -13 <(jq -r '.definitions | keys(@)' schema-current.json | sort) -
214+
```
215+
216+
## Best Practices
217+
218+
1. **Cache Schema**: The schema doesn't change frequently, so cache it locally
219+
2. **Version Control**: Store schema snapshots in version control for tracking changes
220+
3. **Validation**: Use the schema to validate payloads before API calls
221+
4. **Code Generation**: Generate client code from schema for type safety
222+
5. **Documentation**: Keep schema-based documentation up to date
223+
224+
## Troubleshooting
225+
226+
### Schema Retrieval Issues
227+
228+
If schema retrieval fails:
229+
230+
```bash
231+
# Check API connectivity
232+
redisctl enterprise cluster get -q 'name'
233+
234+
# Try raw API access
235+
redisctl api enterprise get /v1/jsonschema
236+
237+
# Check with curl
238+
curl -k -u "$REDIS_ENTERPRISE_USER:$REDIS_ENTERPRISE_PASSWORD" \
239+
https://$REDIS_ENTERPRISE_URL/v1/jsonschema
240+
```
241+
242+
### Schema Validation
243+
244+
Validate that the schema is well-formed:
245+
246+
```bash
247+
# Check if valid JSON
248+
redisctl enterprise jsonschema get | jq empty && echo "Valid JSON"
249+
250+
# Validate schema structure
251+
redisctl enterprise jsonschema get | jq 'has("definitions") and has("$schema")'
252+
253+
# Check for required sections
254+
redisctl enterprise jsonschema get -q '[has("definitions"), has("properties"), has("paths")] | all'
255+
```
256+
257+
## Related Commands
258+
259+
- `redisctl api enterprise` - Direct API access for testing
260+
- `redisctl enterprise database create` - Use schema for creating resources
261+
- `redisctl enterprise cluster` - Cluster configuration that follows schema

0 commit comments

Comments
 (0)