This is an automated email from the ASF dual-hosted git repository. nizhikov pushed a commit to branch IGNITE-15629 in repository https://gitbox.apache.org/repos/asf/ignite-extensions.git
commit 3ebec825c8096950fc285cb9405aae364bd8d3ce Author: nizhikov <[email protected]> AuthorDate: Wed Apr 19 12:00:22 2023 +0300 IGNITE-15629 One more invoker implemented --- modules/openapi-management-ext/pom.xml | 105 ++++++++ .../internal/management/openapi/HeaderFilter.java | 63 +++++ .../management/openapi/ManagementApiServlet.java | 123 +++++++++ .../OpenApiCommandsRegistryInvokerPlugin.java | 288 +++++++++++++++++++++ ...enApiCommandsRegistryInvokerPluginProvider.java | 109 ++++++++ .../management/openapi/OpenApiSelfTest.java | 41 +++ pom.xml | 1 + 7 files changed, 730 insertions(+) diff --git a/modules/openapi-management-ext/pom.xml b/modules/openapi-management-ext/pom.xml new file mode 100644 index 00000000..4241681e --- /dev/null +++ b/modules/openapi-management-ext/pom.xml @@ -0,0 +1,105 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<!-- + POM file. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.ignite</groupId> + <artifactId>ignite-parent-ext-internal</artifactId> + <version>1</version> + <relativePath>../../parent-internal/pom.xml</relativePath> + </parent> + + <properties> + <swagger.version>2.2.9</swagger.version> + </properties> + + <artifactId>ignite-openapi-management-ext</artifactId> + <version>1.0.0-SNAPSHOT</version> + <url>https://ignite.apache.org</url> + + <dependencies> + <dependency> + <groupId>org.apache.ignite</groupId> + <artifactId>ignite-core</artifactId> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>org.apache.ignite</groupId> + <artifactId>ignite-log4j2</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.apache.ignite</groupId> + <artifactId>ignite-spring</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.apache.ignite</groupId> + <artifactId>ignite-core</artifactId> + <type>test-jar</type> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>io.swagger.core.v3</groupId> + <artifactId>swagger-jaxrs2</artifactId> + <version>${swagger.version}</version> + </dependency> + + <dependency> + <groupId>io.swagger.core.v3</groupId> + <artifactId>swagger-jaxrs2-servlet-initializer</artifactId> + <version>${swagger.version}</version> + </dependency> + + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-server</artifactId> + <version>${jetty.version}</version> + </dependency> + + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-servlet</artifactId> + <version>${jetty.version}</version> + </dependency> + + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + <version>${slf4j.version}</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-simple</artifactId> + <version>${slf4j.version}</version> + <scope>test</scope> + </dependency> + </dependencies> +</project> diff --git a/modules/openapi-management-ext/src/main/java/org/apache/ignite/internal/management/openapi/HeaderFilter.java b/modules/openapi-management-ext/src/main/java/org/apache/ignite/internal/management/openapi/HeaderFilter.java new file mode 100644 index 00000000..e45b6006 --- /dev/null +++ b/modules/openapi-management-ext/src/main/java/org/apache/ignite/internal/management/openapi/HeaderFilter.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.management.openapi; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * + */ +public class HeaderFilter implements Filter { + /** {@inheritDoc} */ + @Override public void doFilter( + ServletRequest req, + ServletResponse resp, + FilterChain chain + ) throws ServletException, IOException { + HttpServletResponse response = (HttpServletResponse) resp; + HttpServletRequest request = (HttpServletRequest) req; + + response.setHeader("Access-Control-Allow-Origin", "*"); + response.setHeader("X-Frame-Options", "SAMEORIGIN"); + response.setHeader("Access-Control-Allow-Methods", "DELETE, HEAD, GET, OPTIONS, POST, PUT"); + response.setHeader("Access-Control-Max-Age", "3600"); + response.setHeader("Access-Control-Allow-Credentials", "true"); + response.setHeader("Access-Control-Allow-Origin", "*"); + response.setHeader("Access-Control-Allow-Headers", "Content-Type, api_key, Authorization "); + + chain.doFilter(req, resp); + } + + /** {@inheritDoc} */ + @Override public void init(FilterConfig filterConfig) { + // No-op. + } + + /** {@inheritDoc} */ + @Override public void destroy() { + // No-op. + } +} diff --git a/modules/openapi-management-ext/src/main/java/org/apache/ignite/internal/management/openapi/ManagementApiServlet.java b/modules/openapi-management-ext/src/main/java/org/apache/ignite/internal/management/openapi/ManagementApiServlet.java new file mode 100644 index 00000000..c07f77d7 --- /dev/null +++ b/modules/openapi-management-ext/src/main/java/org/apache/ignite/internal/management/openapi/ManagementApiServlet.java @@ -0,0 +1,123 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.management.openapi; + +import org.apache.ignite.IgniteException; +import org.apache.ignite.internal.IgniteEx; +import org.apache.ignite.internal.dto.IgniteDataTransferObject; +import org.apache.ignite.internal.management.api.Command; +import org.apache.ignite.internal.management.api.CommandUtils; +import org.apache.ignite.internal.management.api.CommandsRegistry; + +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.apache.ignite.internal.management.api.CommandUtils.CMD_WORDS_DELIM; +import static org.apache.ignite.internal.management.api.CommandUtils.executeAndPrint; +import static org.apache.ignite.internal.management.api.CommandUtils.formattedName; +import static org.apache.ignite.internal.management.api.CommandUtils.fromFormattedName; +import static org.apache.ignite.internal.management.api.CommandUtils.parseVal; +import static org.apache.ignite.internal.management.openapi.OpenApiCommandsRegistryInvokerPlugin.TEXT_PLAIN; + +/** */ +public class ManagementApiServlet extends HttpServlet { + /** */ + private final IgniteEx grid; + + /** */ + private final String root; + + /** */ + public ManagementApiServlet(IgniteEx grid, String root) { + this.grid = grid; + this.root = root; + } + + /** {@inheritDoc} */ + @Override protected void doGet( + HttpServletRequest req, + HttpServletResponse resp + ) throws IOException { + resp.setStatus(HttpServletResponse.SC_OK); + resp.setContentType(TEXT_PLAIN); + resp.setCharacterEncoding("UTF-8"); + + String uri = req.getRequestURI(); + + if (!uri.startsWith(root)) + throw new IllegalArgumentException("Wrong URI: " + uri); + + String[] cmdPathAndPosArgs = uri.substring(root.length() + 1).split("/"); + + if (cmdPathAndPosArgs.length == 0) + throw new IllegalArgumentException("Empty command path: " + uri); + + Command<?, ?, ?> cmd = + grid.context().commands().command(fromFormattedName(cmdPathAndPosArgs[0], CMD_WORDS_DELIM)); + + if (cmd == null) + throw new IllegalArgumentException("Unknown command: " + cmdPathAndPosArgs[0]); + + AtomicInteger i = new AtomicInteger(1); + + while (cmd instanceof CommandsRegistry && i.get() < cmdPathAndPosArgs.length) { + Command<?, ?, ?> cmd0 = + ((CommandsRegistry)cmd).command(fromFormattedName(cmdPathAndPosArgs[i.get()], CMD_WORDS_DELIM)); + + if (cmd0 == null) + break; + + cmd = cmd0; + + i.incrementAndGet(); + } + + parseAndExecute(req, resp, cmdPathAndPosArgs, cmd, i); + } + + /** */ + private <A extends IgniteDataTransferObject> void parseAndExecute( + HttpServletRequest req, + HttpServletResponse resp, + String[] cmdPathAndPosArgs, + Command<A, ?, ?> cmd, + AtomicInteger i + ) throws IOException { + try { + A arg = CommandUtils.arguments( + cmd.args(), + (fld, pos) -> i.get() + pos < cmdPathAndPosArgs.length + ? parseVal(cmdPathAndPosArgs[i.get() + pos], fld.getType()) + : null, + fld -> { + String val = req.getParameter(formattedName(fld.getName(), CMD_WORDS_DELIM)); + + return val == null ? null : parseVal(val, fld.getType()); + } + ); + + executeAndPrint(grid, cmd, arg, resp.getWriter()::println); + } + catch (InstantiationException | IllegalAccessException e) { + throw new IgniteException(e); + } + } +} diff --git a/modules/openapi-management-ext/src/main/java/org/apache/ignite/internal/management/openapi/OpenApiCommandsRegistryInvokerPlugin.java b/modules/openapi-management-ext/src/main/java/org/apache/ignite/internal/management/openapi/OpenApiCommandsRegistryInvokerPlugin.java new file mode 100644 index 00000000..73b51d16 --- /dev/null +++ b/modules/openapi-management-ext/src/main/java/org/apache/ignite/internal/management/openapi/OpenApiCommandsRegistryInvokerPlugin.java @@ -0,0 +1,288 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.management.openapi; + +import io.swagger.v3.jaxrs2.integration.OpenApiServlet; +import io.swagger.v3.oas.integration.GenericOpenApiContextBuilder; +import io.swagger.v3.oas.integration.OpenApiContextLocator; +import io.swagger.v3.oas.integration.SwaggerConfiguration; +import io.swagger.v3.oas.integration.api.OpenApiContext; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.PathItem; +import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.media.ArraySchema; +import io.swagger.v3.oas.models.media.BooleanSchema; +import io.swagger.v3.oas.models.media.Content; +import io.swagger.v3.oas.models.media.IntegerSchema; +import io.swagger.v3.oas.models.media.MediaType; +import io.swagger.v3.oas.models.media.NumberSchema; +import io.swagger.v3.oas.models.media.Schema; +import io.swagger.v3.oas.models.media.StringSchema; +import io.swagger.v3.oas.models.parameters.Parameter; +import io.swagger.v3.oas.models.responses.ApiResponse; +import io.swagger.v3.oas.models.responses.ApiResponses; +import org.apache.ignite.IgniteException; +import org.apache.ignite.IgniteLogger; +import org.apache.ignite.internal.IgniteEx; +import org.apache.ignite.internal.IgniteVersionUtils; +import org.apache.ignite.internal.dto.IgniteDataTransferObject; +import org.apache.ignite.internal.management.api.Argument; +import org.apache.ignite.internal.management.api.Command; +import org.apache.ignite.internal.management.api.CommandWithSubs; +import org.apache.ignite.internal.management.api.CommandsRegistry; +import org.apache.ignite.internal.management.api.PositionalArgument; +import org.apache.ignite.lang.IgniteUuid; +import org.apache.ignite.plugin.IgnitePlugin; +import org.apache.ignite.plugin.PluginContext; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.function.Consumer; + +import static io.swagger.v3.oas.integration.api.OpenApiContext.OPENAPI_CONTEXT_ID_KEY; +import static io.swagger.v3.oas.models.parameters.Parameter.StyleEnum.SIMPLE; +import static java.util.Collections.singletonList; +import static javax.servlet.DispatcherType.REQUEST; +import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR; +import static javax.servlet.http.HttpServletResponse.SC_OK; +import static org.apache.ignite.internal.management.api.CommandUtils.CMD_WORDS_DELIM; +import static org.apache.ignite.internal.management.api.CommandUtils.PARAM_WORDS_DELIM; +import static org.apache.ignite.internal.management.api.CommandUtils.formattedName; +import static org.apache.ignite.internal.management.api.CommandUtils.valueExample; +import static org.apache.ignite.internal.management.api.CommandUtils.visitCommandParams; + +/** + * + */ +public class OpenApiCommandsRegistryInvokerPlugin implements IgnitePlugin { + /** */ + public static final String API_CTX_ID = "ignite-management-api-ctx"; + + /** */ + public static final String API_ID = "ignite-management-api"; + + /** */ + public static final String INVOKER_BASE_URL = "/management"; + + /** */ + public static final String TEXT_PLAIN = "text/plain"; + + /** */ + private PluginContext ctx; + + /** */ + private IgniteLogger log; + + /** */ + private IgniteEx grid; + + /** */ + private Server srv; + + /** */ + private final OpenAPI api = new OpenAPI(); + + /** */ + public void context(PluginContext ctx) { + this.ctx = ctx; + grid = (IgniteEx)ctx.grid(); + log = ctx.log(OpenApiCommandsRegistryInvokerPlugin.class); + } + + /** */ + public void onIgniteStart() { + // TODO: make this configurable. + int port = 8080; + String host = "localhost"; + String protocol = "http"; + + api.info(new Info() + .title("Ignite management API") + .description("This endpoint expose Apache Ignite management API methods") + .version(IgniteVersionUtils.VER_STR) + ).servers(singletonList( + new io.swagger.v3.oas.models.servers.Server() + .url(protocol + "://" + host + ":" + port + INVOKER_BASE_URL) + .description("Ignite node[id=" + grid.localNode().id() + ']') + )); + + grid.commands().forEach(cmd -> register(cmd.getKey(), new LinkedList<>(), cmd.getValue())); + + try { + SwaggerConfiguration cfg = new SwaggerConfiguration(); + + cfg.setId(API_ID); + cfg.setOpenAPI(api); + cfg.prettyPrint(true); + + OpenApiContext ctx = new GenericOpenApiContextBuilder<>() + .ctxId(API_CTX_ID) + .openApiConfiguration(cfg) + .buildContext(true); + + OpenApiContextLocator.getInstance().putOpenApiContext(API_CTX_ID, ctx); + + srv = new Server(); + + ServerConnector connector = new ServerConnector(srv); + + connector.setPort(port); + connector.setHost(host); + + srv.addConnector(connector); + + ServletContextHandler handler = new ServletContextHandler(); + + ServletHolder apiExposeServlet = new ServletHolder(OpenApiServlet.class); + + apiExposeServlet.setInitParameter(OPENAPI_CONTEXT_ID_KEY, API_CTX_ID); + + handler.addServlet(apiExposeServlet, "/api/*"); + handler.addServlet( + new ServletHolder(new ManagementApiServlet(grid, INVOKER_BASE_URL)), + INVOKER_BASE_URL + "/*" + ); + handler.addFilter(HeaderFilter.class, "/*", EnumSet.of(REQUEST)); + + srv.setHandler(handler); + + srv.start(); + } + catch (Exception e) { + throw new IgniteException(e); + } + } + + /** */ + public <A extends IgniteDataTransferObject> void register(String name, List<String> parents, Command<A, ?, ?> cmd) { + if (cmd instanceof CommandsRegistry) { + parents.add(formattedName(name, CMD_WORDS_DELIM)); + + ((Iterable<Map.Entry<String, Command<?, ?, ?>>>)cmd).forEach( + cmd0 -> register(cmd0.getKey(), parents, cmd0.getValue()) + ); + + parents.remove(parents.size() - 1); + + if (!((CommandWithSubs)cmd).canBeExecuted()) + return; + } + + StringBuilder path = new StringBuilder(); + + for (String parent : parents) + path.append('/').append(parent); + + path.append('/').append(formattedName(name, CMD_WORDS_DELIM)); + + List<Parameter> params = new ArrayList<>(); + + Consumer<Field> fldCnsmr = fld -> params.add(new Parameter() + .style(SIMPLE) + .in("query") + .name(formattedName(fld.getName(), CMD_WORDS_DELIM)) + .schema(schema(fld.getType())) + .description(fld.getAnnotation(Argument.class).description()) + .example(valueExample(fld)) + .required(!fld.getAnnotation(Argument.class).optional())); + + // TODO: support oneOf in spec. + visitCommandParams( + cmd.args(), + fld -> { + assert !fld.getAnnotation(PositionalArgument.class).optional(); + + path.append("/{").append(formattedName(fld.getName(), PARAM_WORDS_DELIM)).append('}'); + + params.add(new Parameter() + .style(SIMPLE) + .in("path") + .name(formattedName(fld.getName(), PARAM_WORDS_DELIM)) + .description(fld.getAnnotation(PositionalArgument.class).description()) + .example(valueExample(fld))); + }, + fldCnsmr, + (optional, flds) -> flds.forEach(fldCnsmr) + ); + + Content plainText = new Content().addMediaType(TEXT_PLAIN, new MediaType()); + + api.path( + path.toString(), + new PathItem().get(new Operation() + .description(cmd.description()) + .parameters(params) + .responses(new ApiResponses() + .addApiResponse(Integer.toString(SC_OK), new ApiResponse() + .description("Command output") + .content(plainText)) + .addApiResponse(Integer.toString(SC_INTERNAL_SERVER_ERROR), new ApiResponse() + .description("Error text") + .content(plainText))) + )); + } + + private Schema<?> schema(Class<?> cls) { + if (cls == Float.class || cls == float.class) + return new NumberSchema().format("float"); + else if (cls == Double.class || cls == double.class) + return new NumberSchema().format("double"); + else if (cls == short.class + || cls == Short.class + || cls == byte.class + || cls == Byte.class) + return new IntegerSchema().format(null); + else if (cls == int.class || cls == Integer.class) + return new IntegerSchema(); + else if (cls == long.class || cls == Long.class) + return new IntegerSchema().format("int64"); + else if (cls == Boolean.class || cls == boolean.class) + return new BooleanSchema(); + else if (cls == String.class) + return new StringSchema(); + else if (cls == UUID.class) + return new StringSchema().format("uuid"); + else if (cls == IgniteUuid.class) + return new StringSchema(); + else if (cls.isArray()) + return new ArraySchema().items(schema(cls.getComponentType())); + + throw new IllegalArgumentException("Type not supported: " + cls); + } + + /** */ + public void onIgniteStop() { + try { + if (srv != null) + srv.stop(); + } + catch (Exception e) { + log.warning("Error stop OpenApi server", e); + } + } +} \ No newline at end of file diff --git a/modules/openapi-management-ext/src/main/java/org/apache/ignite/internal/management/openapi/OpenApiCommandsRegistryInvokerPluginProvider.java b/modules/openapi-management-ext/src/main/java/org/apache/ignite/internal/management/openapi/OpenApiCommandsRegistryInvokerPluginProvider.java new file mode 100644 index 00000000..f887dc94 --- /dev/null +++ b/modules/openapi-management-ext/src/main/java/org/apache/ignite/internal/management/openapi/OpenApiCommandsRegistryInvokerPluginProvider.java @@ -0,0 +1,109 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.management.openapi; + +import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.cluster.ClusterNode; +import org.apache.ignite.internal.IgniteVersionUtils; +import org.apache.ignite.plugin.CachePluginContext; +import org.apache.ignite.plugin.CachePluginProvider; +import org.apache.ignite.plugin.ExtensionRegistry; +import org.apache.ignite.plugin.IgnitePlugin; +import org.apache.ignite.plugin.PluginContext; +import org.apache.ignite.plugin.PluginProvider; +import org.apache.ignite.plugin.PluginValidationException; +import org.jetbrains.annotations.Nullable; + +import java.io.Serializable; +import java.util.UUID; + +/** */ +public class OpenApiCommandsRegistryInvokerPluginProvider implements PluginProvider { + /** */ + private OpenApiCommandsRegistryInvokerPlugin invoker = new OpenApiCommandsRegistryInvokerPlugin(); + + /** {@inheritDoc} */ + @Override public String name() { + return "JMX invoker of CommandRegistry"; + } + + /** {@inheritDoc} */ + @Override public String version() { + return IgniteVersionUtils.VER_STR; + } + + /** {@inheritDoc} */ + @Override public String copyright() { + return IgniteVersionUtils.COPYRIGHT; + } + + /** {@inheritDoc} */ + @Override public IgnitePlugin plugin() { + return invoker; + } + + /** {@inheritDoc} */ + @Override public void initExtensions(PluginContext ctx, ExtensionRegistry registry) throws IgniteCheckedException { + invoker.context(ctx); + } + + /** {@inheritDoc} */ + @Override public CachePluginProvider createCacheProvider(CachePluginContext ctx) { + return null; + } + + /** {@inheritDoc} */ + @Override public void onIgniteStart() throws IgniteCheckedException { + invoker.onIgniteStart(); + } + + /** {@inheritDoc} */ + @Override public void onIgniteStop(boolean cancel) { + invoker.onIgniteStop(); + } + + /** {@inheritDoc} */ + @Override public @Nullable Serializable provideDiscoveryData(UUID nodeId) { + return null; + } + + /** {@inheritDoc} */ + @Override public void receiveDiscoveryData(UUID nodeId, Serializable data) { + // No-op. + } + + /** {@inheritDoc} */ + @Override public void validateNewNode(ClusterNode node) throws PluginValidationException { + // No-op. + } + + /** {@inheritDoc} */ + @Override public Object createComponent(PluginContext ctx, Class cls) { + return null; + } + + /** {@inheritDoc} */ + @Override public void start(PluginContext ctx) throws IgniteCheckedException { + // No-op. + } + + /** {@inheritDoc} */ + @Override public void stop(boolean cancel) throws IgniteCheckedException { + // No-op. + } +} diff --git a/modules/openapi-management-ext/src/test/java/org/apache/ignite/internal/management/openapi/OpenApiSelfTest.java b/modules/openapi-management-ext/src/test/java/org/apache/ignite/internal/management/openapi/OpenApiSelfTest.java new file mode 100644 index 00000000..3babb97c --- /dev/null +++ b/modules/openapi-management-ext/src/test/java/org/apache/ignite/internal/management/openapi/OpenApiSelfTest.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.management.openapi; + +import org.apache.ignite.configuration.IgniteConfiguration; +import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; +import org.junit.Test; + +/** + * + */ +public class OpenApiSelfTest extends GridCommonAbstractTest { + /** {@inheritDoc} */ + @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception { + return super.getConfiguration(igniteInstanceName) + .setPluginProviders(new OpenApiCommandsRegistryInvokerPluginProvider()); + } + + /** */ + @Test + public void testExportOpenApiDefinition() throws Exception { + startGrid(0); + + Thread.sleep(3 * 60_000); + } +} diff --git a/pom.xml b/pom.xml index c1f8a1a5..37b5a88e 100644 --- a/pom.xml +++ b/pom.xml @@ -63,6 +63,7 @@ <module>modules/cloud-ext</module> <module>modules/osgi-ext</module> <module>modules/ssh-ext</module> + <module>modules/openapi-management-ext</module> </modules> <profiles>
