package jetbrains.buildServer.clouds.vmware;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import java.util.*;
import java.util.stream.StreamSupport;
import jetbrains.buildServer.clouds.CloudConstants;
import jetbrains.buildServer.clouds.CloudImageParameters;
import jetbrains.buildServer.clouds.server.CloudManagerBase;
import jetbrains.buildServer.clouds.vmware.web.VMWareWebConstants;
import jetbrains.buildServer.serverSide.InvalidProperty;
import jetbrains.buildServer.serverSide.PropertiesProcessor;
import jetbrains.buildServer.util.StringUtil;
import org.jetbrains.annotations.NotNull;
/**
* Created by Sergey.Pak on 1/29/2016.
*/
public class VmwarePropertiesProcessor implements PropertiesProcessor {
@NotNull private final CloudManagerBase myCloudManager;
public VmwarePropertiesProcessor(@NotNull final CloudManagerBase cloudManager){
myCloudManager = cloudManager;
}
@NotNull
public Collection<InvalidProperty> process(final Map<String, String> properties) {
List<InvalidProperty> list = new ArrayList<InvalidProperty>();
notEmpty(properties, VMWareWebConstants.SECURE_PASSWORD, list);
notEmpty(properties, VMWareWebConstants.USERNAME, list);
notEmpty(properties, VMWareWebConstants.SERVER_URL, list);
final String instancesLimit = properties.get(VMWareWebConstants.PROFILE_INSTANCE_LIMIT);
if (!StringUtil.isEmpty(instancesLimit)){
if (!StringUtil.isAPositiveNumber(instancesLimit)){
list.add(new InvalidProperty(VMWareWebConstants.PROFILE_INSTANCE_LIMIT, "Must be a positive integer or empty"));
}
}
if (list.size() > 0)
return list;
final String serverURL = properties.get(VMWareWebConstants.SERVER_URL);
final String currentProfileId = properties.get(CloudConstants.PROFILE_ID);
final Map<String, String> existingImages = new HashMap<>();
myCloudManager.listAllProfiles().stream()
.filter(p->(VmwareConstants.TYPE.equals(p.getCloudCode())
&& (currentProfileId == null || !currentProfileId.equals(p.getProfileId()))
&& (serverURL.equals(p.getParameters().getParameter(VMWareWebConstants.SERVER_URL))))
)
.forEach(p->
myCloudManager
.getClient(p.getProjectId(), p.getProfileId())
.getImages()
.stream()
.forEach(i->existingImages.put(i.getId().toUpperCase(), p.getProfileName()))
);
final String imagesData = properties.get(CloudImageParameters.SOURCE_IMAGES_JSON);
if (StringUtil.isEmpty(imagesData))
return list; // allowing empty profiles
JsonParser parser = new JsonParser();
final JsonElement element = parser.parse(imagesData);
if (element.isJsonArray()){
StreamSupport.stream(element.getAsJsonArray().spliterator(), false)
.map(JsonElement::getAsJsonObject)
.map(obj->obj.getAsJsonPrimitive(CloudImageParameters.SOURCE_ID_FIELD))
.filter(Objects::nonNull)
.map(json->json.getAsString().toUpperCase())
.filter(existingImages::containsKey)
.map(id->new InvalidProperty(CloudImageParameters.SOURCE_IMAGES_JSON,
String.format("The cloud profile '%s' already contains an image named '%s'. Select a different VM or change the custom name.", existingImages.get(id), id)
)).forEachOrdered(list::add);
} else {
list.add(new InvalidProperty(CloudImageParameters.SOURCE_IMAGES_JSON, "Unable to parse images data - bad format"));
}
return list;
}
private void notEmpty(@NotNull final Map<String, String> props,
@NotNull final String key,
@NotNull final Collection<InvalidProperty> col) {
if (!props.containsKey(key) || StringUtil.isEmptyOrSpaces(props.get(key))) {
col.add(new InvalidProperty(key, "Value should be set"));
}
}
}