package io.cattle.platform.host.stats.api;
import io.cattle.platform.api.link.LinkHandler;
import io.cattle.platform.core.constants.CommonStatesConstants;
import io.cattle.platform.core.constants.InstanceConstants;
import io.cattle.platform.core.model.Host;
import io.cattle.platform.core.model.Instance;
import io.cattle.platform.core.model.Service;
import io.cattle.platform.docker.util.DockerUtils;
import io.cattle.platform.host.model.HostApiAccess;
import io.cattle.platform.host.service.HostApiService;
import io.cattle.platform.host.stats.utils.StatsConstants;
import io.cattle.platform.object.ObjectManager;
import io.cattle.platform.token.TokenService;
import io.github.ibuildthecloud.gdapi.context.ApiContext;
import io.github.ibuildthecloud.gdapi.request.ApiRequest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import org.apache.commons.lang3.StringUtils;
public class ServiceContainerStatsLinkHandler implements LinkHandler {
@Inject
HostApiService hostApiService;
@Inject
ObjectManager objectManager;
@Inject
TokenService tokenService;
private static final String SERVICE_PATH = "/service/";
@Override
public String[] getTypes() {
return new String[] { "service", "loadBalancerService" };
}
@Override
public boolean handles(String type, String id, String link, ApiRequest request) {
return StatsConstants.CONTAINER_STATS.equalsIgnoreCase(link);
}
@Override
public Object link(String name, Object obj, ApiRequest request) throws IOException {
Service service = (Service) obj;
if (service == null) {
return null;
}
List<Instance> serviceInstances = objectManager.mappedChildren(service, Instance.class);
String metaUrl = null;
StatsAccess meta = new StatsAccess();
List<StatsAccess> serviceStatsQuery = new ArrayList<>();
for (Instance instance : serviceInstances) {
List<String> invalidStates = Arrays.asList(CommonStatesConstants.REMOVING, CommonStatesConstants.REMOVED,
InstanceConstants.STATE_ERRORING, InstanceConstants.STATE_ERROR);
if (instance.getRemoved() != null || invalidStates.contains(instance.getState())) {
continue;
}
String dockerId = DockerUtils.getDockerIdentifier(instance);
//This is true if the container is in CREATING state, where it doesn't have a dockerId, but it is not in REMOVED state
if (StringUtils.isEmpty(dockerId)) {
continue;
}
Host host = DockerUtils.getHostFromContainer(objectManager, instance);
if (host == null) {
// host can be null when initial instance.start failed, so its being stopped/error out as a result
continue;
}
Map<String, Object> payload = new HashMap<>();
Map<String, Object> containerIdsMap = new HashMap<String, Object>();
containerIdsMap.put(DockerUtils.getDockerIdentifier(instance),
ApiContext.getContext().getIdFormatter().formatId(objectManager.getType(instance), instance.getId()));
payload.put("containerIds", containerIdsMap);
HostApiAccess apiAccess = hostApiService.getAccess(request, host.getId(), payload, new String[] { StatsConstants.CONTAINER_STATS_PATH.get() });
if (apiAccess == null) {
continue;
}
StringBuilder url = new StringBuilder();
url.append(apiAccess.getUrl());
metaUrl = url.toString() + SERVICE_PATH;
url.append("/").append(dockerId);
StatsAccess statsAccess = new StatsAccess();
statsAccess.setToken(apiAccess.getAuthenticationToken());
statsAccess.setUrl(url.toString());
serviceStatsQuery.add(statsAccess);
}
Map<String, Object> metaQueryPayload = new HashMap<>();
metaQueryPayload.put("service", serviceStatsQuery);
meta.setToken(tokenService.generateToken(metaQueryPayload));
meta.setUrl(metaUrl);
return meta;
}
}