Skip to content

Commit 0e3230d

Browse files
committed
feat(core): add api-resources schema command for JSON Schema generation
Add getResourceSchema() to JikkouApi to generate JSON Schema for any registered resource type. Includes CLI command, API server endpoint, and API client support.
1 parent 6603855 commit 0e3230d

17 files changed

Lines changed: 393 additions & 33 deletions

File tree

cli/src/main/java/io/streamthoughts/jikkou/client/Jikkou.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
import io.streamthoughts.jikkou.client.command.reconcile.PatchResourceCommand;
3535
import io.streamthoughts.jikkou.client.command.reconcile.ReplaceResourceCommand;
3636
import io.streamthoughts.jikkou.client.command.reconcile.UpdateResourceCommand;
37-
import io.streamthoughts.jikkou.client.command.resources.ListApiResourcesCommand;
37+
import io.streamthoughts.jikkou.client.command.resources.ApiResourceCommand;
3838
import io.streamthoughts.jikkou.client.command.server.ServerInfoCommand;
3939
import io.streamthoughts.jikkou.client.command.validate.ValidateCommand;
4040
import io.streamthoughts.jikkou.client.context.ConfigurationContext;
@@ -88,7 +88,7 @@
8888
ReplaceResourceCommand.class,
8989
ApiExtensionCommand.class,
9090
ApiProviderCommand.class,
91-
ListApiResourcesCommand.class,
91+
ApiResourceCommand.class,
9292
ConfigCommand.class,
9393
DiffCommand.class,
9494
PrepareCommand.class,
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright (c) The original authors
4+
*
5+
* Licensed under the Apache Software License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
6+
*/
7+
package io.streamthoughts.jikkou.client.command.resources;
8+
9+
import io.streamthoughts.jikkou.client.command.CLIBaseCommand;
10+
import jakarta.inject.Singleton;
11+
import picocli.CommandLine.Command;
12+
13+
@Command(name = "api-resources",
14+
header = "Print the supported API resources",
15+
description = {
16+
"List and describe the API resources supported by the Jikkou CLI or Jikkou API Server (in proxy mode)."
17+
},
18+
subcommands = {
19+
ListApiResourcesCommand.class,
20+
GetApiResourceSchemaCommand.class,
21+
})
22+
@Singleton
23+
public class ApiResourceCommand extends CLIBaseCommand {}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright (c) The original authors
4+
*
5+
* Licensed under the Apache Software License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
6+
*/
7+
package io.streamthoughts.jikkou.client.command.resources;
8+
9+
import io.streamthoughts.jikkou.client.command.CLIBaseCommand;
10+
import io.streamthoughts.jikkou.core.JikkouApi;
11+
import io.streamthoughts.jikkou.core.io.Jackson;
12+
import io.streamthoughts.jikkou.core.models.ApiResourceSchema;
13+
import io.streamthoughts.jikkou.core.models.ResourceType;
14+
import jakarta.inject.Inject;
15+
import jakarta.inject.Singleton;
16+
import java.util.concurrent.Callable;
17+
import picocli.CommandLine;
18+
import picocli.CommandLine.Command;
19+
import picocli.CommandLine.Option;
20+
21+
@Command(name = "schema",
22+
header = "Print the JSON Schema of a resource type",
23+
description = "Get the JSON Schema for a specific API resource type."
24+
)
25+
@Singleton
26+
public class GetApiResourceSchemaCommand extends CLIBaseCommand implements Callable<Integer> {
27+
28+
@Option(names = {"--api-version"},
29+
required = true,
30+
description = "The API version of the resource (e.g., 'kafka.jikkou.io/v1')."
31+
)
32+
public String apiVersion;
33+
34+
@Option(names = {"--kind"},
35+
required = true,
36+
description = "The kind of the resource (e.g., 'KafkaTopic')."
37+
)
38+
public String kind;
39+
40+
@Inject
41+
private JikkouApi api;
42+
43+
/** {@inheritDoc} **/
44+
@Override
45+
public Integer call() throws Exception {
46+
ResourceType resourceType = ResourceType.of(kind, apiVersion);
47+
ApiResourceSchema schema = api.getResourceSchema(resourceType);
48+
String json = Jackson.JSON_OBJECT_MAPPER
49+
.writerWithDefaultPrettyPrinter()
50+
.writeValueAsString(schema.schema());
51+
System.out.println(json);
52+
return CommandLine.ExitCode.OK;
53+
}
54+
}

cli/src/main/java/io/streamthoughts/jikkou/client/command/resources/ListApiResourcesCommand.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
import picocli.CommandLine.Mixin;
3030
import picocli.CommandLine.Option;
3131

32-
@Command(name = "api-resources",
32+
@Command(name = "list",
3333
header = "Print the supported API resources",
3434
description = "List the API resources supported by the Jikkou CLI or Jikkou API Server (in proxy mode)."
3535
)

cli/src/test/java/io/streamthoughts/jikkou/client/JikkouTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ void shouldReturnUsageCodeForNoArgs() {
3535

3636
@Test
3737
void shouldPrintApiResources() {
38-
int execute = Jikkou.execute(new String[]{"api-resources"});
38+
int execute = Jikkou.execute(new String[]{"api-resources", "list"});
3939
Assertions.assertEquals(CommandLine.ExitCode.OK, execute);
4040
}
4141

core/pom.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,14 @@
8787
<artifactId>avro</artifactId>
8888
<version>${avro.version}</version>
8989
</dependency>
90+
<dependency>
91+
<groupId>com.github.victools</groupId>
92+
<artifactId>jsonschema-generator</artifactId>
93+
</dependency>
94+
<dependency>
95+
<groupId>com.github.victools</groupId>
96+
<artifactId>jsonschema-module-jackson</artifactId>
97+
</dependency>
9098
</dependencies>
9199

92100
</project>

core/src/main/java/io/streamthoughts/jikkou/core/DefaultApi.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import io.streamthoughts.jikkou.core.models.ApiResource;
4242
import io.streamthoughts.jikkou.core.models.ApiResourceChangeList;
4343
import io.streamthoughts.jikkou.core.models.ApiResourceList;
44+
import io.streamthoughts.jikkou.core.models.ApiResourceSchema;
4445
import io.streamthoughts.jikkou.core.models.ApiResourceVerbOptionList;
4546
import io.streamthoughts.jikkou.core.models.ApiValidationResult;
4647
import io.streamthoughts.jikkou.core.models.CoreAnnotations;
@@ -64,6 +65,7 @@
6465
import io.streamthoughts.jikkou.core.reconciler.ResourceChangeFilter;
6566
import io.streamthoughts.jikkou.core.reconciler.config.ApiOptionSpecFactory;
6667
import io.streamthoughts.jikkou.core.reporter.CombineChangeReporter;
68+
import io.streamthoughts.jikkou.core.resource.JacksonResourceSchemaGenerator;
6769
import io.streamthoughts.jikkou.core.resource.ResourceDescriptor;
6870
import io.streamthoughts.jikkou.core.resource.ResourceRegistry;
6971
import io.streamthoughts.jikkou.core.selector.Selector;
@@ -149,6 +151,21 @@ private DefaultApi(@NotNull final ExtensionFactory extensionFactory,
149151
this.resourceRegistry = Objects.requireNonNull(resourceRegistry, "resourceRegistry must not be null");
150152
}
151153

154+
/**
155+
* {@inheritDoc}
156+
**/
157+
@Override
158+
public ApiResourceSchema getResourceSchema(@NotNull ResourceType resourceType) {
159+
ResourceDescriptor descriptor = resourceRegistry.findDescriptorByType(resourceType)
160+
.orElseThrow(() -> new ResourceNotFoundException(
161+
String.format("No resource found for type: apiVersion='%s', kind='%s'",
162+
resourceType.apiVersion(), resourceType.kind())));
163+
JacksonResourceSchemaGenerator generator = new JacksonResourceSchemaGenerator();
164+
com.fasterxml.jackson.databind.JsonNode schema = generator.generate(descriptor.resourceClass());
165+
String groupVersion = resourceType.group() + GROUP_API_VERSION_SEPARATOR + resourceType.apiVersion();
166+
return new ApiResourceSchema(groupVersion, resourceType.kind(), schema);
167+
}
168+
152169
/**
153170
* {@inheritDoc}
154171
**/

core/src/main/java/io/streamthoughts/jikkou/core/JikkouApi.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import io.streamthoughts.jikkou.core.models.ApiProviderList;
2727
import io.streamthoughts.jikkou.core.models.ApiResourceChangeList;
2828
import io.streamthoughts.jikkou.core.models.ApiResourceList;
29+
import io.streamthoughts.jikkou.core.models.ApiResourceSchema;
2930
import io.streamthoughts.jikkou.core.models.ApiValidationResult;
3031
import io.streamthoughts.jikkou.core.models.HasItems;
3132
import io.streamthoughts.jikkou.core.models.HasMetadata;
@@ -170,6 +171,17 @@ <T extends Extension> B register(@NotNull Class<T> type,
170171
ApiResourceList listApiResources(@NotNull String group,
171172
@NotNull String version);
172173

174+
/**
175+
* Gets the JSON Schema for the specified resource type.
176+
*
177+
* @param resourceType the resource type.
178+
* @return an {@link ApiResourceSchema} containing the JSON Schema.
179+
* @throws io.streamthoughts.jikkou.core.exceptions.ResourceNotFoundException
180+
* if no resource is registered for the given type.
181+
* @since 0.38.0
182+
*/
183+
ApiResourceSchema getResourceSchema(@NotNull ResourceType resourceType);
184+
173185
/**
174186
* List the supported API groups.
175187
*
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright (c) The original authors
4+
*
5+
* Licensed under the Apache Software License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
6+
*/
7+
package io.streamthoughts.jikkou.core.models;
8+
9+
import com.fasterxml.jackson.annotation.JsonProperty;
10+
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
11+
import com.fasterxml.jackson.databind.JsonNode;
12+
import io.streamthoughts.jikkou.core.annotation.Reflectable;
13+
14+
/**
15+
* Represents the JSON Schema for a resource type.
16+
*
17+
* @param apiVersion the API version of the resource.
18+
* @param kind the kind of the resource.
19+
* @param schema the JSON Schema.
20+
* @since 0.38.0
21+
*/
22+
@Reflectable
23+
@JsonPropertyOrder({"apiVersion", "kind", "schema"})
24+
public record ApiResourceSchema(
25+
@JsonProperty("apiVersion") String apiVersion,
26+
@JsonProperty("kind") String kind,
27+
@JsonProperty("schema") JsonNode schema
28+
) {}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright (c) The original authors
4+
*
5+
* Licensed under the Apache Software License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
6+
*/
7+
package io.streamthoughts.jikkou.core.resource;
8+
9+
import com.fasterxml.jackson.databind.JsonNode;
10+
import io.streamthoughts.jikkou.core.models.Resource;
11+
import org.jetbrains.annotations.NotNull;
12+
13+
/**
14+
* Generates a JSON Schema for a given resource class.
15+
*/
16+
public interface ResourceSchemaGenerator {
17+
18+
/**
19+
* Generates a JSON Schema for the specified resource class.
20+
*
21+
* @param resourceClass the resource class.
22+
* @return a {@link JsonNode} representing the JSON Schema.
23+
*/
24+
JsonNode generate(@NotNull Class<? extends Resource> resourceClass);
25+
}

0 commit comments

Comments
 (0)