package io.cattle.platform.storage.api.filter;
import io.cattle.platform.archaius.util.ArchaiusUtil;
import io.cattle.platform.core.constants.InstanceConstants;
import io.cattle.platform.core.model.Instance;
import io.cattle.platform.docker.client.DockerImage;
import io.cattle.platform.storage.service.StorageService;
import io.cattle.platform.util.type.CollectionUtils;
import io.github.ibuildthecloud.gdapi.exception.ClientVisibleException;
import io.github.ibuildthecloud.gdapi.exception.ValidationErrorException;
import io.github.ibuildthecloud.gdapi.factory.SchemaFactory;
import io.github.ibuildthecloud.gdapi.request.ApiRequest;
import io.github.ibuildthecloud.gdapi.request.resource.AbstractResourceManagerFilter;
import io.github.ibuildthecloud.gdapi.request.resource.ResourceManager;
import io.github.ibuildthecloud.gdapi.util.ResponseCodes;
import io.github.ibuildthecloud.gdapi.validation.ValidationErrorCodes;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import org.apache.commons.lang3.StringUtils;
import com.netflix.config.DynamicStringListProperty;
import com.netflix.config.DynamicStringProperty;
public class ExternalTemplateInstanceFilter extends AbstractResourceManagerFilter {
SchemaFactory schemaFactory;
@Inject
StorageService storageService;
public static final DynamicStringProperty DEFAULT_REGISTRY = ArchaiusUtil.getString("registry.default");
public static final DynamicStringListProperty WHITELIST_REGISTRIES = ArchaiusUtil.getList("registry.whitelist");
@Override
public Object create(String type, ApiRequest request, ResourceManager next) {
Map<String, Object> data = CollectionUtils.toMap(request.getRequestObject());
Object imageUuid = data.get(InstanceConstants.FIELD_IMAGE_UUID);
if (imageUuid != null) {
String image = imageUuid.toString();
String fullImageName = getImageUuid(image, storageService);
if (!StringUtils.equals(image, fullImageName)) {
data.put(InstanceConstants.FIELD_IMAGE_UUID, fullImageName);
request.setRequestObject(data);
}
}
return super.create(type, request, next);
}
public static String getImageUuid(String image, StorageService storageService) {
validateImageUuid(image);
DockerImage dockerImage = DockerImage.parse(image);
if (dockerImage == null) {
throw new ValidationErrorException(ValidationErrorCodes.INVALID_REFERENCE, InstanceConstants.FIELD_IMAGE_UUID);
}
String fullImageName = dockerImage.getFullName();
String registry = dockerImage.getServer();
if (!fullImageName.startsWith(registry)) {
String defaultRegistry = DEFAULT_REGISTRY.get();
if (image.contains(registry)) {
fullImageName = registry + "/" + fullImageName;
}
else if (!StringUtils.isBlank(defaultRegistry) && !StringUtils.isEmpty(defaultRegistry)) {
fullImageName = defaultRegistry + "/" + fullImageName;
}
}
if (image.startsWith(DockerImage.KIND_PREFIX)) {
fullImageName = DockerImage.KIND_PREFIX + fullImageName;
}
if (image.startsWith(DockerImage.SIM_PREFIX) && !fullImageName.startsWith(DockerImage.SIM_PREFIX)) {
fullImageName = DockerImage.SIM_PREFIX + fullImageName;
}
if (!storageService.isValidUUID(fullImageName.toString())) {
throw new ValidationErrorException(ValidationErrorCodes.INVALID_REFERENCE, InstanceConstants.FIELD_IMAGE_UUID);
}
return fullImageName;
}
protected static void validateImageUuid(String image) {
DockerImage dockerImage = DockerImage.parse(image);
if (dockerImage == null) {
return;
}
String registry = dockerImage.getServer();
List<String> whitelistRegistries = WHITELIST_REGISTRIES.get();
String defaultRegistry = DEFAULT_REGISTRY.get();
String userProvidedRegistry = dockerImage.getServer();
if (!image.contains(registry)) {
if(!StringUtils.isBlank(defaultRegistry)) {
userProvidedRegistry = defaultRegistry;
}
}
if (whitelistRegistries.size() > 0) {
if (!StringUtils.isEmpty(userProvidedRegistry) && !StringUtils.isBlank(userProvidedRegistry)) {
if (!whitelistRegistries.contains(userProvidedRegistry)) {
throw new ClientVisibleException(ResponseCodes.UNPROCESSABLE_ENTITY, ValidationErrorCodes.INVALID_OPTION,
"The provided registry is not whitelisted", null);
}
}
else {
if (!StringUtils.isEmpty(defaultRegistry) && !StringUtils.isBlank(defaultRegistry)) {
if (!whitelistRegistries.contains(defaultRegistry)) {
throw new ClientVisibleException(ResponseCodes.UNPROCESSABLE_ENTITY, ValidationErrorCodes.INVALID_OPTION,
"The default registry is not whitelisted", null);
}
}
}
}
}
@Override
public String[] getTypes() {
List<String> types = schemaFactory.getSchemaNames(Instance.class);
return types.toArray(new String[types.size()]);
}
public SchemaFactory getSchemaFactory() {
return schemaFactory;
}
public void setSchemaFactory(SchemaFactory schemaFactory) {
this.schemaFactory = schemaFactory;
}
}