/*
* 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.services.impl.policy;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.kie.server.api.model.KieContainerStatus;
import org.kie.server.api.model.ServiceResponse;
import org.kie.server.services.api.KieServer;
import org.kie.server.services.api.KieServerRegistry;
import org.kie.server.services.api.Policy;
import org.kie.server.services.impl.KieContainerInstanceImpl;
import org.kie.server.services.impl.controller.DefaultRestControllerImpl;
import org.kie.server.services.impl.locator.LatestContainerLocator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Policy that will dispose older container and leave only latest one - latest according to version of ReleaseId.
*
* Policy by default is scheduled to run once a day, though it can be reconfigured with system properties:
* <ul>
* <li>policy.klo.interval - interval how often (expressed as duration) the policy should be applied</li>
* <li>policy.klo.unit - time unit that the interval was specified in - if not given milliseconds are assumed</li>
* </ul>
*
* Name of this policy (to be used to activate it) is <code>KeepLatestOnly</code>
*/
public class KeepLatestContainerOnlyPolicy implements Policy {
private static final Logger logger = LoggerFactory.getLogger(KeepLatestContainerOnlyPolicy.class);
private static final String INTERVAL_VALUE = "policy.klo.interval";
private static final String INTERVAL_TIME_UNIT = "policy.klo.unit";
private static final String NAME = "KeepLatestOnly";
private long interval;
@Override
public String getName() {
return NAME;
}
@Override
public long getInterval() {
return interval;
}
@Override
public void start() {
logger.debug("Starting KeepLatestContainerOnlyPolicy policy...");
TimeUnit timeUnit = TimeUnit.valueOf(System.getProperty(INTERVAL_TIME_UNIT, TimeUnit.MILLISECONDS.toString()));
long givenInterval = Long.parseLong(System.getProperty(INTERVAL_VALUE, "0"));
if (givenInterval > 0) {
timeUnit.convert(givenInterval, timeUnit);
this.interval = TimeUnit.MILLISECONDS.convert(givenInterval, timeUnit);
} else {
// default once a day
this.interval = TimeUnit.MILLISECONDS.convert(1L, TimeUnit.DAYS);
}
logger.debug("Started {} policy", this);
}
@Override
public void stop() {
this.interval = -1;
logger.debug("Stopped {} policy", this);
}
@Override
public void apply(KieServerRegistry kieServerRegistry, KieServer kieServer) {
DefaultRestControllerImpl controller = new DefaultRestControllerImpl(kieServerRegistry);
List<String> containerAliases = kieServerRegistry.getContainerAliases();
if (containerAliases.isEmpty()) {
logger.debug("No containers found, quiting");
return;
}
for (String alias : containerAliases) {
List<KieContainerInstanceImpl> containerInstances = kieServerRegistry.getContainersForAlias(alias);
if (containerInstances.isEmpty() || containerInstances.size() == 1) {
logger.debug("Containers for alias {} are already on expected level (number of containers is {})", alias, containerInstances.size());
continue;
}
String latestContainerId = LatestContainerLocator.get().locateContainer(alias, containerInstances);
final Map<String, String> report = new HashMap<>();
containerInstances.stream()
.filter(kci -> !kci.getContainerId().equals(latestContainerId))
.filter(kci -> !kci.getStatus().equals(KieContainerStatus.CREATING))
.forEach(kci -> {
ServiceResponse<Void> response = kieServer.disposeContainer(kci.getContainerId());
report.put(kci.getContainerId(), response.getType().toString());
logger.debug("Dispose of container {} completed with {} message {}", kci.getContainerId(), response.getType().toString(), response.getMsg());
if (response.getType().equals(ServiceResponse.ResponseType.SUCCESS)) {
controller.stopContainer(kci.getContainerId());
}
});
logger.info("KeepLatestContainerOnlyPolicy applied to {} successfully (report {})", alias, report);
}
}
@Override
public String toString() {
return "KeepLatestContainerOnlyPolicy{" +
"interval=" + interval + " ms" +
'}';
}
}