package com.sequenceiq.cloudbreak.cloud.gcp.network;
import static com.sequenceiq.cloudbreak.cloud.gcp.util.GcpStackUtil.getSubnetId;
import static com.sequenceiq.cloudbreak.cloud.gcp.util.GcpStackUtil.isExistingSubnet;
import static com.sequenceiq.cloudbreak.cloud.gcp.util.GcpStackUtil.legacyNetwork;
import static com.sequenceiq.cloudbreak.cloud.gcp.util.GcpStackUtil.newNetworkAndSubnet;
import static com.sequenceiq.cloudbreak.cloud.gcp.util.GcpStackUtil.newSubnetInExistingNetwork;
import static com.sequenceiq.cloudbreak.common.type.ResourceType.GCP_SUBNET;
import org.springframework.stereotype.Service;
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
import com.google.api.services.compute.Compute;
import com.google.api.services.compute.model.Operation;
import com.google.api.services.compute.model.Subnetwork;
import com.sequenceiq.cloudbreak.cloud.context.AuthenticatedContext;
import com.sequenceiq.cloudbreak.cloud.gcp.GcpResourceException;
import com.sequenceiq.cloudbreak.cloud.gcp.context.GcpContext;
import com.sequenceiq.cloudbreak.cloud.model.CloudResource;
import com.sequenceiq.cloudbreak.cloud.model.Network;
import com.sequenceiq.cloudbreak.cloud.model.Security;
import com.sequenceiq.cloudbreak.cloud.template.ResourceNotNeededException;
import com.sequenceiq.cloudbreak.common.type.ResourceType;
@Service
public class GcpSubnetResourceBuilder extends AbstractGcpNetworkBuilder {
public static final String SUBNET_NAME = "subnetName";
@Override
public CloudResource create(GcpContext context, AuthenticatedContext auth, Network network) {
if (legacyNetwork(network)) {
throw new ResourceNotNeededException("Legacy GCP networks doesn't support subnets. Subnet won't be created.");
}
String resourceName = isExistingSubnet(network) ? getSubnetId(network) : getResourceNameService().resourceName(resourceType(), context.getName());
return createNamedResource(resourceType(), resourceName);
}
@Override
public CloudResource build(GcpContext context, AuthenticatedContext auth, Network network, Security security, CloudResource resource) throws Exception {
if (newNetworkAndSubnet(network) || newSubnetInExistingNetwork(network)) {
Compute compute = context.getCompute();
String projectId = context.getProjectId();
Subnetwork gcpSubnet = new Subnetwork();
gcpSubnet.setName(resource.getName());
gcpSubnet.setIpCidrRange(network.getSubnet().getCidr());
String networkName = context.getStringParameter(GcpNetworkResourceBuilder.NETWORK_NAME);
gcpSubnet.setNetwork(String.format("https://www.googleapis.com/compute/v1/projects/%s/global/networks/%s", projectId, networkName));
Compute.Subnetworks.Insert snInsert = compute.subnetworks().insert(projectId, auth.getCloudContext().getLocation().getRegion().value(), gcpSubnet);
try {
Operation operation = snInsert.execute();
if (operation.getHttpErrorStatusCode() != null) {
throw new GcpResourceException(operation.getHttpErrorMessage(), resourceType(), resource.getName());
}
context.putParameter(SUBNET_NAME, resource.getName());
return createOperationAwareCloudResource(resource, operation);
} catch (GoogleJsonResponseException e) {
throw new GcpResourceException(checkException(e), resourceType(), resource.getName());
}
}
context.putParameter(SUBNET_NAME, resource.getName());
return new CloudResource.Builder().cloudResource(resource).persistent(false).build();
}
@Override
public CloudResource delete(GcpContext context, AuthenticatedContext auth, CloudResource resource, Network network) throws Exception {
if (newNetworkAndSubnet(network) || newSubnetInExistingNetwork(network)) {
Compute compute = context.getCompute();
String projectId = context.getProjectId();
try {
Operation operation = compute.subnetworks().delete(projectId, context.getLocation().getRegion().value(), resource.getName()).execute();
return createOperationAwareCloudResource(resource, operation);
} catch (GoogleJsonResponseException e) {
exceptionHandler(e, resource.getName(), resourceType());
return null;
}
}
return null;
}
@Override
public ResourceType resourceType() {
return GCP_SUBNET;
}
@Override
public int order() {
return 1;
}
}