package io.fathom.cloud.compute.api.os.resources; import io.fathom.cloud.CloudException; import io.fathom.cloud.compute.api.os.model.ServerMetadata; import io.fathom.cloud.compute.services.ComputeServices; import io.fathom.cloud.compute.services.MetadataServices; import io.fathom.cloud.protobuf.CloudModel.InstanceData; import io.fathom.cloud.protobuf.CloudModel.MetadataData; import java.util.Map; import java.util.Map.Entry; import javax.inject.Inject; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.inject.persist.Transactional; @Path("/openstack/compute/{project}/servers/{serverId}/metadata") @Transactional public class ServerMetadataResource extends ComputeResourceBase { private static final Logger log = LoggerFactory.getLogger(ServerMetadataResource.class); @Inject ComputeServices computeServices; @Inject MetadataServices metadataServices; @PathParam("serverId") long instanceId; @GET public ServerMetadata getMetadata() throws CloudException { InstanceData instance = getInstance(); return buildResponse(instance); } @GET @Path("{key}") public ServerMetadata getMetadataKey(@PathParam("key") String key) throws CloudException { InstanceData instance = getInstance(); ServerMetadata response = buildResponse(instance); String value = response.metadata.get(key); response.metadata.clear(); if (value != null) { response.metadata.put(key, value); } return response; } @DELETE @Path("{key}") public ServerMetadata deleteMetadataKey(@PathParam("key") String key) throws CloudException { InstanceData instance = getInstance(); InstanceData updated = metadataServices.replaceMetadataKey(getProject(), instance.getId(), key, null); return buildResponse(updated); } private ServerMetadata buildResponse(InstanceData instance) { ServerMetadata response = new ServerMetadata(); MetadataData metadata = instance.getMetadata(); response.metadata = MetadataServices.toMap(metadata); return response; } @PUT @Path("{key}") public ServerMetadata setMetadataKey(@PathParam("key") String key, ServerMetadata metadata) throws CloudException { InstanceData instance = getInstance(); if (metadata.metadata == null) { metadata.metadata = metadata.meta; } if (metadata.metadata == null) { throw new IllegalArgumentException(); } Map<String, String> model = metadata.metadata; for (Entry<String, String> entry : model.entrySet()) { if (key.equals(entry.getKey())) { instance = metadataServices.replaceMetadataKey(getProject(), instance.getId(), key, entry.getValue()); } else { throw new IllegalArgumentException(); } } return buildResponse(instance); } @PUT public ServerMetadata replaceMetadata(ServerMetadata metadata) throws CloudException { return updateMetadata(metadata, true); } @POST public ServerMetadata mergeMetadata(ServerMetadata metadata) throws CloudException { return updateMetadata(metadata, false); } private ServerMetadata updateMetadata(ServerMetadata metadata, boolean replace) throws CloudException { if (metadata.metadata == null) { metadata.metadata = metadata.meta; } if (metadata.metadata == null) { throw new IllegalArgumentException(); } Map<String, String> model = metadata.metadata; InstanceData instance = getInstance(); InstanceData updated = metadataServices.replaceMetadata(getProject(), instance.getId(), model, replace); return buildResponse(updated); } private InstanceData getInstance() throws CloudException { InstanceData instance = computeServices.findInstance(getProject().getId(), instanceId); notFoundIfNull(instance); return instance; } }