/* * Copyright 2016 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * * 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.kie.server.router.handlers; import java.net.URI; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.jboss.logging.Logger; import org.json.JSONObject; import org.kie.server.router.Configuration; import org.kie.server.router.ContainerInfo; import org.kie.server.router.KieServerRouterConstants; import org.kie.server.router.proxy.KieServerProxyClient; import org.kie.server.router.proxy.aggragate.JSONResponseAggregator; import org.kie.server.router.proxy.aggragate.JaxbXMLResponseAggregator; import org.kie.server.router.proxy.aggragate.ResponseAggregator; import org.kie.server.router.proxy.aggragate.XstreamXMLResponseAggregator; import org.kie.server.router.repository.ConfigurationMarshaller; import org.kie.server.router.repository.FileRepository; import io.undertow.server.HttpHandler; import io.undertow.server.HttpServerExchange; import io.undertow.server.handlers.ResponseCodeHandler; import io.undertow.util.Headers; import org.kie.server.router.spi.ConfigRepository; import org.kie.server.router.utils.HttpUtils; public class AdminHttpHandler implements HttpHandler { private static final Logger log = Logger.getLogger(AdminHttpHandler.class); private static final String CONTROLLER = System.getProperty(KieServerRouterConstants.CONTROLLER); // private KieServerProxyClient proxyClient; private Configuration configuration = new Configuration(); private List<ResponseAggregator> aggregators = new ArrayList<>(); private ConfigRepository repository = null; private ConfigurationMarshaller marshaller = new ConfigurationMarshaller(); private Set<String> controllerContainers = new HashSet<>(); private static final String CONTAINER_SPEC_JSON = "{\n" + " \"container-id\" : \"#1@\",\n" + " \"container-name\" : \"#2@\",\n" + " \"server-template-key\" : {\n" + " \"server-id\" : \"kie-server-router\",\n" + " \"server-name\" : \"KIE Server Router\"\n" + " },\n" + " \"release-id\" : {\n" + " \"group-id\" : \"#3@\",\n" + " \"artifact-id\" : \"#4@\",\n" + " \"version\" : \"#5@\"\n" + " },\n" + " \"configuration\" : { },\n" + " \"status\" : \"STARTED\"\n" + " }"; public AdminHttpHandler(Configuration configuration, ConfigRepository repository) { this.configuration = configuration; this.repository = repository; this.aggregators.add(new JSONResponseAggregator()); this.aggregators.add(new XstreamXMLResponseAggregator()); this.aggregators.add(new JaxbXMLResponseAggregator()); } @Override public void handleRequest(final HttpServerExchange exchange) throws Exception { final String path = exchange.getRelativePath(); if (path.startsWith("/list")) { String jsonConfig = marshaller.marshall(configuration); exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "application/json"); exchange.getResponseHeaders().put(Headers.CONTENT_LENGTH, jsonConfig.getBytes("UTF-8").length); exchange.getResponseSender().send(jsonConfig); return; } exchange.getRequestReceiver().receiveFullString((ex, data) -> { try { JSONObject jsonData = new JSONObject(data); String containerId = jsonData.getString("containerId"); String alias = jsonData.getString("alias"); String serverId = jsonData.getString("serverId"); String serverUrl = jsonData.getString("serverUrl"); String releaseId = jsonData.getString("releaseId"); ContainerInfo containerInfo = new ContainerInfo(containerId, alias, releaseId); if (path.startsWith("/add")) { log.infof("Added %s as server location for container %s ", serverUrl, containerId); synchronized (configuration) { configuration.addContainerHost(containerId, serverUrl); configuration.addContainerHost(alias, serverUrl); configuration.addServerHost(serverId, serverUrl); configuration.addContainerInfo(containerInfo); repository.persist(configuration); } if (CONTROLLER != null && releaseId != null && !controllerContainers.contains(containerId)) { try { String[] gav = releaseId.split(":"); String jsonPayload = CONTAINER_SPEC_JSON .replaceFirst("#1@", containerId) .replaceFirst("#2@", alias) .replaceFirst("#3@", gav[0]) .replaceFirst("#4@", gav[1]) .replaceFirst("#5@", gav[2]); HttpUtils.putHttpCall(CONTROLLER + "/management/servers/kie-server-router/containers/" + containerId, jsonPayload); controllerContainers.add(containerId); log.infof("Added %s container into controller at %s ", containerId, CONTROLLER); } catch (Exception e) { log.warn("Exception when notifying controller about new container " + e.getMessage(), e); } } ResponseCodeHandler.HANDLE_200.handleRequest(exchange); } else if (path.startsWith("/remove")) { log.infof("Removed %s as server location for container %s ", serverUrl, containerId); synchronized (configuration) { configuration.removeContainerHost(containerId, serverUrl); configuration.removeContainerHost(alias, serverUrl); configuration.removeServerHost(serverId, serverUrl); configuration.removeContainerInfo(containerInfo.getContainerId(), containerInfo.getAlias()); repository.persist(configuration); } if (CONTROLLER != null && controllerContainers.contains(containerId)) { Set<String> hostsPerContainer = configuration.getHostsPerContainer().getOrDefault(containerId, Collections.EMPTY_SET); if (hostsPerContainer.isEmpty()) { try { HttpUtils.deleteHttpCall(CONTROLLER + "/management/servers/kie-server-router/containers/" + containerId); controllerContainers.remove(containerId); log.infof("Removed %s container from controller at %s ", containerId, CONTROLLER); } catch (Exception e) { log.warn("Exception when notifying controller about deleted containers " + e.getMessage(), e); } } } ResponseCodeHandler.HANDLE_200.handleRequest(exchange); } else { exchange.getResponseHeaders().put(Headers.STATUS, ""); ResponseCodeHandler.HANDLE_404.handleRequest(exchange); } } catch (Exception e) { log.error("Error while performing admin operation", e); } }); } public Map<String, Set<String>> getHostsPerServer() { return configuration.getHostsPerServer(); } public List<ResponseAggregator> getAggregators() { return Collections.unmodifiableList(aggregators); } public void addControllerContainers(List<String> containers) { this.controllerContainers.addAll(containers); } public Configuration getConfiguration() { return configuration; } }