diff options
author | Smokowski, Steven <steve.smokowski@att.com> | 2020-02-12 11:13:08 -0500 |
---|---|---|
committer | Benjamin, Max (mb388a) <mb388a@att.com> | 2020-02-12 11:13:09 -0500 |
commit | 5ba5518f6b9dffbf0fed7f3655b1635cd818bc1e (patch) | |
tree | 417a3b906a03726a760ffbfc3c543f20022ff707 | |
parent | 1980195d94d2208c8f5c8951885cfe345fbc8dd1 (diff) |
mso to add support for creating the cloud region
Initial check in to support cloud region create
Add additional junit tests
Add additional integration tests
Updated junit to use spy and removed setter method
Issue-ID: SO-2657
Signed-off-by: Benjamin, Max (mb388a) <mb388a@att.com>
Change-Id: I6a93f3b4caf7d640ffa5842981247d284b9013ad
7 files changed, 404 insertions, 5 deletions
diff --git a/adapters/mso-catalog-db-adapter/src/test/java/org/onap/so/db/catalog/client/CatalogDbClientTest.java b/adapters/mso-catalog-db-adapter/src/test/java/org/onap/so/db/catalog/client/CatalogDbClientTest.java index 707a2a45af..739b4b62de 100644 --- a/adapters/mso-catalog-db-adapter/src/test/java/org/onap/so/db/catalog/client/CatalogDbClientTest.java +++ b/adapters/mso-catalog-db-adapter/src/test/java/org/onap/so/db/catalog/client/CatalogDbClientTest.java @@ -22,8 +22,8 @@ package org.onap.so.db.catalog.client; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -428,7 +428,7 @@ public class CatalogDbClientTest extends CatalogDbAdapterBaseTest { } @Test - public void testPostCloudSite() { + public void testCloudSiteClient() { CatalogDbClientPortChanger localClient = new CatalogDbClientPortChanger( "http://localhost:" + client.wiremockPort, msoAdaptersAuth, client.wiremockPort); CloudSite cloudSite = new CloudSite(); @@ -455,6 +455,19 @@ public class CatalogDbClientTest extends CatalogDbAdapterBaseTest { assertEquals("TESTCLLI", getCloudSite.getClli()); assertEquals("regionId", getCloudSite.getRegionId()); assertEquals("RANDOMID", getCloudSite.getIdentityServiceId()); + + getCloudSite.setClli("clli2"); + getCloudSite.setRegionId("region2"); + + CloudSite updatedCloudSite = this.client.updateCloudSite(getCloudSite); + assertNotNull(updatedCloudSite); + assertNotNull(updatedCloudSite.getIdentityService()); + assertEquals("clli2", updatedCloudSite.getClli()); + assertEquals("region2", updatedCloudSite.getRegionId()); + + this.client.deleteCloudSite(getCloudSite.getId()); + getCloudSite = this.client.getCloudSite("MTN6"); + assertNull(getCloudSite); } @Test diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/cloudregion/CloudException.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/cloudregion/CloudException.java new file mode 100644 index 0000000000..9cdf7e3b2a --- /dev/null +++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/cloudregion/CloudException.java @@ -0,0 +1,14 @@ +package org.onap.so.adapters.cloudregion; + +public class CloudException extends RuntimeException { + + /** + * + */ + private static final long serialVersionUID = -2631715095942372451L; + + public CloudException(String error, Exception e) { + super(error, e); + } + +} diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/cloudregion/CloudRegionRestV1.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/cloudregion/CloudRegionRestV1.java new file mode 100644 index 0000000000..780480507b --- /dev/null +++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/cloudregion/CloudRegionRestV1.java @@ -0,0 +1,102 @@ +/*- + * ============LICENSE_START======================================================= + * OPENECOMP - SO + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Modifications Copyright (C) 2018 IBM. + * Modifications Copyright (c) 2019 Samsung + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.so.adapters.cloudregion; + + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import org.apache.http.HttpStatus; +import org.onap.so.db.catalog.beans.CloudSite; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; + + +@Path("/v1/cloud-region") +@Api(value = "/v1/cloud-region", description = "root of cloud region adapter") +@Component +public class CloudRegionRestV1 { + private static Logger logger = LoggerFactory.getLogger(CloudRegionRestV1.class); + + @Autowired + private CloudRestImpl cloudRestImpl; + + @POST + @Path("{cloud-region-id}/{cloud-owner}") + @Consumes({MediaType.APPLICATION_JSON}) + @Produces({MediaType.APPLICATION_JSON}) + @ApiOperation(value = "CreateCloudRegion", response = Response.class, + notes = "Create a cloud site in MSO and Region In AAI") + @ApiResponses({@ApiResponse(code = 201, message = "Cloud Region has been created"), + @ApiResponse(code = 500, message = "Create Cloud Region has failed")}) + public Response createCloudRegion( + @ApiParam(value = "cloud-region-id", required = true) @PathParam("cloud-region-id") String cloudRegionId, + @ApiParam(value = "cloud-owner", required = true) @PathParam("cloud-owner") String cloudOwner, + @ApiParam(value = "CloudSite", required = true) final CloudSite cloudSite) { + cloudRestImpl.createCloudRegion(cloudSite, cloudOwner); + return Response.status(HttpStatus.SC_CREATED).build(); + } + + @DELETE + @Path("{cloud-region-id}/{cloud-owner}") + @Consumes({MediaType.APPLICATION_JSON}) + @Produces({MediaType.APPLICATION_JSON}) + @ApiOperation(value = "CreateCloudRegion", response = Response.class, notes = "Delete an cloud Region in SO") + @ApiResponses({@ApiResponse(code = 204, message = "cloud Region has been deleted"), + @ApiResponse(code = 500, message = "Cloud Region delete has failed")}) + public Response deleteCloudRegion( + @ApiParam(value = "cloud-region-id", required = true) @PathParam("cloud-region-id") String cloudRegionId, + @ApiParam(value = "cloud-owner", required = true) @PathParam("cloud-owner") String cloudOwner) { + cloudRestImpl.deleteCloudRegion(cloudRegionId); + return Response.status(HttpStatus.SC_NO_CONTENT).build(); + } + + @PUT + @Path("{cloud-region-id}/{cloud-owner}") + @Consumes({MediaType.APPLICATION_JSON}) + @Produces({MediaType.APPLICATION_JSON}) + @ApiOperation(value = "CreateCloudRegion", response = Response.class, notes = "Update an existing Cloud Region") + @ApiResponses({@ApiResponse(code = 200, message = "Cloud Region has been updated"), + @ApiResponse(code = 500, message = "Update Cloud Region has failed examine entity object for details")}) + public Response updateCloudRegion( + @ApiParam(value = "cloud-region-id", required = true) @PathParam("cloud-region-id") String cloudRegionId, + @ApiParam(value = "cloud-owner", required = true) @PathParam("cloud-owner") String cloudOwner, + @ApiParam(value = "CloudSite", required = true) final CloudSite cloudSite) { + cloudRestImpl.updateCloudRegion(cloudSite, cloudOwner); + return Response.status(HttpStatus.SC_OK).build(); + } +} diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/cloudregion/CloudRestImpl.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/cloudregion/CloudRestImpl.java new file mode 100644 index 0000000000..4cde8655ae --- /dev/null +++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/cloudregion/CloudRestImpl.java @@ -0,0 +1,97 @@ +package org.onap.so.adapters.cloudregion; + +import java.util.Optional; +import org.onap.aai.domain.yang.CloudRegion; +import org.onap.so.client.aai.AAIObjectType; +import org.onap.so.client.aai.AAIResourcesClient; +import org.onap.so.client.aai.entities.uri.AAIResourceUri; +import org.onap.so.client.aai.entities.uri.AAIUriFactory; +import org.onap.so.db.catalog.beans.CloudSite; +import org.onap.so.db.catalog.client.CatalogDbClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + + +@Component +public class CloudRestImpl { + private static final Logger logger = LoggerFactory.getLogger(CloudRestImpl.class); + + private AAIResourcesClient aaiClient; + + @Autowired + private CatalogDbClient catalogDBClient; + + public void createCloudRegion(CloudSite cloudSite, String cloudOwner) throws CloudException { + createRegionInCatalogDb(cloudSite); + createCloudRegionInAAI(cloudSite, cloudOwner); + } + + public void updateCloudRegion(CloudSite cloudSite, String cloudOwner) throws CloudException { + updateRegionInCatalogDb(cloudSite); + } + + protected void updateRegionInCatalogDb(CloudSite cloudSite) { + try { + catalogDBClient.updateCloudSite(cloudSite); + } catch (Exception e) { + logger.error("Error updating cloud region in catalogdb", e); + throw new CloudException("Error updating cloud region in Catalog: " + e.getMessage(), e); + } + } + + public void deleteCloudRegion(String cloudRegionId) throws CloudException { + try { + catalogDBClient.deleteCloudSite(cloudRegionId); + } catch (Exception e) { + logger.error("Error deleting cloud region in catalogdb", e); + throw new CloudException("Error deleting cloud region in Catalog: " + e.getMessage(), e); + } + } + + protected void createCloudRegionInAAI(CloudSite cloudSite, String cloudOwner) { + try { + CloudRegion cloudRegion = mapCloudRegion(cloudSite, cloudOwner); + AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIObjectType.CLOUD_REGION, + cloudRegion.getCloudOwner(), cloudRegion.getCloudRegionId()); + getAaiClient().createIfNotExists(uri, Optional.of(cloudRegion)); + } catch (Exception e) { + logger.error("Error creating cloud region in AAI", e); + throw new CloudException("Error creating cloud region in AAI: " + e.getMessage(), e); + } + } + + protected void createRegionInCatalogDb(CloudSite cloudSite) throws CloudException { + try { + CloudSite existingCloudSite = catalogDBClient.getCloudSite(cloudSite.getRegionId()); + if (existingCloudSite == null) { + catalogDBClient.postCloudSite(cloudSite); + } + } catch (Exception e) { + logger.error("Error creating cloud site in Catalog Adapter: " + e.getMessage(), e); + throw new CloudException("Error creating cloud site in Catalog Adapter", e); + } + } + + protected CloudRegion mapCloudRegion(CloudSite cloudSite, String cloudOwner) { + CloudRegion region = new CloudRegion(); + region.setCloudOwner(cloudOwner); + region.setCloudRegionId(cloudSite.getRegionId()); + region.setCloudRegionVersion(cloudSite.getCloudVersion()); + region.setOwnerDefinedType("cLCP"); + region.setOrchestrationDisabled(false); + region.setComplexName("NA"); + region.setInMaint(false); + region.setCloudType("openstack"); + return region; + } + + protected AAIResourcesClient getAaiClient() { + if (aaiClient == null) + return new AAIResourcesClient(); + else + return aaiClient; + } + +} diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/openstack/CXFConfiguration.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/openstack/CXFConfiguration.java index 9fc5c979d8..9badd795eb 100644 --- a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/openstack/CXFConfiguration.java +++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/openstack/CXFConfiguration.java @@ -32,6 +32,7 @@ import org.apache.cxf.jaxrs.JAXRSServerFactoryBean; import org.apache.cxf.jaxrs.swagger.Swagger2Feature; import org.apache.cxf.jaxws.EndpointImpl; import org.apache.cxf.transport.servlet.CXFServlet; +import org.onap.so.adapters.cloudregion.CloudRegionRestV1; import org.onap.so.adapters.network.MsoNetworkAdapterAsyncImpl; import org.onap.so.adapters.network.MsoNetworkAdapterImpl; import org.onap.so.adapters.network.NetworkAdapterRest; @@ -47,10 +48,12 @@ import org.onap.so.adapters.vnf.VolumeAdapterRestV2; import org.onap.so.client.policy.JettisonStyleMapperProvider; import org.onap.so.logging.cxf.interceptor.SOAPLoggingInInterceptor; import org.onap.so.logging.cxf.interceptor.SOAPLoggingOutInterceptor; +import org.onap.so.logging.jaxrs.filter.SOAuditLogContainerFilter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider; @@ -81,7 +84,14 @@ public class CXFConfiguration { @Autowired private MsoVnfCloudifyAdapterImpl vnfCloudifyAdapterImpl; @Autowired + private CloudRegionRestV1 cloudRegionRestV1; + @Autowired private JettisonStyleMapperProvider jettisonStyleObjectMapper; + @Autowired + private ObjectMapper mapper; + @Autowired + private SOAuditLogContainerFilter soAuditLogContainerFilter; + @Bean(name = Bus.DEFAULT_BUS_ID) public SpringBus springBus() { @@ -170,6 +180,7 @@ public class CXFConfiguration { return endpoint; } + // Uses Jettson Style marshalling semantics @Bean public Server rsServer() { JAXRSServerFactoryBean endpoint = new JAXRSServerFactoryBean(); @@ -178,7 +189,20 @@ public class CXFConfiguration { vnfAdapterRestV2, volumeAdapterRest, volumeAdapterRestV2)); endpoint.setAddress("/rest"); endpoint.setFeatures(Arrays.asList(createSwaggerFeature(), new LoggingFeature())); - endpoint.setProvider(new JacksonJsonProvider(jettisonStyleObjectMapper.getMapper())); + endpoint.setProviders(Arrays.asList(new JacksonJsonProvider(jettisonStyleObjectMapper.getMapper()), + soAuditLogContainerFilter)); + return endpoint.create(); + } + + // Uses normal Jackson marshalling semantics + @Bean + public Server rsServerApi() { + JAXRSServerFactoryBean endpoint = new JAXRSServerFactoryBean(); + endpoint.setBus(springBus()); + endpoint.setServiceBeans(Arrays.<Object>asList(cloudRegionRestV1)); + endpoint.setAddress("/api"); + endpoint.setFeatures(Arrays.asList(new LoggingFeature())); + endpoint.setProviders(Arrays.asList(new JacksonJsonProvider(mapper), soAuditLogContainerFilter)); return endpoint.create(); } diff --git a/adapters/mso-openstack-adapters/src/test/java/org/onap/so/adapters/cloudregion/CloudRegionRestImplTest.java b/adapters/mso-openstack-adapters/src/test/java/org/onap/so/adapters/cloudregion/CloudRegionRestImplTest.java new file mode 100644 index 0000000000..9c62c286ac --- /dev/null +++ b/adapters/mso-openstack-adapters/src/test/java/org/onap/so/adapters/cloudregion/CloudRegionRestImplTest.java @@ -0,0 +1,96 @@ +package org.onap.so.adapters.cloudregion; + +import static com.shazam.shazamcrest.MatcherAssert.assertThat; +import static com.shazam.shazamcrest.matcher.Matchers.sameBeanAs; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import java.util.Optional; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnitRunner; +import org.onap.aai.domain.yang.CloudRegion; +import org.onap.so.client.aai.AAIObjectType; +import org.onap.so.client.aai.AAIResourcesClient; +import org.onap.so.client.aai.entities.uri.AAIResourceUri; +import org.onap.so.client.aai.entities.uri.AAIUriFactory; +import org.onap.so.db.catalog.beans.CloudSite; +import org.onap.so.db.catalog.client.CatalogDbClient; + + +@RunWith(MockitoJUnitRunner.class) +public class CloudRegionRestImplTest { + + @Spy + @InjectMocks + private CloudRestImpl cloudRestImpl; + + @Mock + private CatalogDbClient catalogDbClientMock; + + @Mock + private AAIResourcesClient aaiResClientMock; + + private CloudSite cloudSite = new CloudSite(); + + private CloudRegion testCloudRegion = new CloudRegion(); + + @Before + public void setup() { + cloudSite.setCloudVersion("1.0"); + cloudSite.setRegionId("region1"); + Mockito.doReturn(aaiResClientMock).when(cloudRestImpl).getAaiClient(); + testCloudRegion.setCloudOwner("bob"); + testCloudRegion.setCloudRegionId("region1"); + testCloudRegion.setCloudRegionVersion("1.0"); + testCloudRegion.setInMaint(false); + testCloudRegion.setOrchestrationDisabled(false); + testCloudRegion.setComplexName("NA"); + testCloudRegion.setCloudRegionVersion("1.0"); + testCloudRegion.setOwnerDefinedType("cLCP"); + testCloudRegion.setCloudType("openstack"); + } + + @Test + public void mapCloudRegionTest() { + CloudRegion mappedRegion = cloudRestImpl.mapCloudRegion(cloudSite, "bob"); + assertThat(mappedRegion, sameBeanAs(testCloudRegion)); + } + + @Test + public void createCloudRegionTest() { + when(catalogDbClientMock.getCloudSite("region1")).thenReturn(null); + when(catalogDbClientMock.postCloudSite(cloudSite)).thenReturn(cloudSite); + AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIObjectType.CLOUD_REGION, "bob", "region1"); + cloudRestImpl.createCloudRegion(cloudSite, "bob"); + ArgumentCaptor<AAIResourceUri> actualURI = ArgumentCaptor.forClass(AAIResourceUri.class); + ArgumentCaptor<Optional<Object>> actualCloudRegion = ArgumentCaptor.forClass(Optional.class); + verify(catalogDbClientMock, times(1)).getCloudSite("region1"); + verify(catalogDbClientMock, times(1)).postCloudSite(cloudSite); + verify(aaiResClientMock, times(1)).createIfNotExists(Mockito.eq(uri), Mockito.any()); + verify(aaiResClientMock, times(1)).createIfNotExists(actualURI.capture(), actualCloudRegion.capture()); + assertThat((CloudRegion) actualCloudRegion.getValue().get(), sameBeanAs(testCloudRegion)); + } + + @Test + public void updateCloudRegionTest() { + when(catalogDbClientMock.updateCloudSite(cloudSite)).thenReturn(cloudSite); + cloudRestImpl.updateCloudRegion(cloudSite, "bob"); + verify(catalogDbClientMock, times(1)).updateCloudSite(cloudSite); + } + + @Test + public void deleteCloudRegionTest() { + doNothing().when(catalogDbClientMock).deleteCloudSite("region1"); + cloudRestImpl.deleteCloudRegion(cloudSite.getRegionId()); + verify(catalogDbClientMock, times(1)).deleteCloudSite("region1"); + } + +} diff --git a/mso-catalog-db/src/main/java/org/onap/so/db/catalog/client/CatalogDbClient.java b/mso-catalog-db/src/main/java/org/onap/so/db/catalog/client/CatalogDbClient.java index 7f5907e9bf..161ca2a2fb 100644 --- a/mso-catalog-db/src/main/java/org/onap/so/db/catalog/client/CatalogDbClient.java +++ b/mso-catalog-db/src/main/java/org/onap/so/db/catalog/client/CatalogDbClient.java @@ -764,8 +764,61 @@ public class CatalogDbClient { return this.getSingleResource(cloudSiteClient, getUri(uri + id)); } - public void postCloudSite(CloudSite cloudSite) { - this.postSingleResource(cloudSiteClient, cloudSite); + public CloudSite postCloudSite(CloudSite cloudSite) { + if (cloudSite == null) { + throw new EntityNotFoundException("CloudSite passed as null"); + } + try { + HttpHeaders headers = getHttpHeaders(); + HttpEntity<CloudSite> entity = new HttpEntity<>(cloudSite, headers); + CloudSite updatedCloudSite = restTemplate + .exchange(UriComponentsBuilder.fromUriString(endpoint + "/cloudSite").build().encode().toString(), + HttpMethod.POST, entity, CloudSite.class) + .getBody(); + return updatedCloudSite; + } catch (HttpClientErrorException e) { + if (HttpStatus.SC_NOT_FOUND == e.getStatusCode().value()) { + throw new EntityNotFoundException("Unable to find CloudSite with Cloud Site Id: " + cloudSite.getId()); + } + throw e; + } + } + + public CloudSite updateCloudSite(CloudSite cloudSite) { + if (cloudSite == null) { + throw new EntityNotFoundException("CloudSite passed as null"); + } + try { + HttpHeaders headers = getHttpHeaders(); + HttpEntity<CloudSite> entity = new HttpEntity<>(cloudSite, headers); + CloudSite updatedCloudSite = restTemplate + .exchange(UriComponentsBuilder.fromUriString(endpoint + "/cloudSite/" + cloudSite.getId()).build() + .encode().toString(), HttpMethod.PUT, entity, CloudSite.class) + .getBody(); + return updatedCloudSite; + } catch (HttpClientErrorException e) { + if (HttpStatus.SC_NOT_FOUND == e.getStatusCode().value()) { + throw new EntityNotFoundException("Unable to find CloudSite with Cloud Site Id: " + cloudSite.getId()); + } + throw e; + } + } + + public void deleteCloudSite(String cloudSiteId) { + if (cloudSiteId == null) { + throw new EntityNotFoundException("CloudSiteId passed as null"); + } + try { + HttpHeaders headers = getHttpHeaders(); + HttpEntity<String> entity = new HttpEntity<>(null, headers); + restTemplate.exchange(UriComponentsBuilder.fromUriString(endpoint + "/cloudSite/" + cloudSiteId).build() + .encode().toString(), HttpMethod.DELETE, entity, CloudSite.class).getBody(); + } catch (HttpClientErrorException e) { + if (HttpStatus.SC_NOT_FOUND == e.getStatusCode().value()) { + throw new EntityNotFoundException("Unable to find CloudSite with Cloud Site Id: " + cloudSiteId); + } + throw e; + } } public List<CloudSite> getCloudSites() { |