Merge pull request #108 from jsonking/master

SoftLayer: Added Regions to Datacenter (for dasein). Fixed tests for Amsterdam DC and region info.
This commit is contained in:
Adrian Cole 2011-10-12 08:17:38 -07:00
commit 0e9d3666ad
8 changed files with 186 additions and 13 deletions

View File

@ -18,6 +18,13 @@
*/
package org.jclouds.softlayer.domain;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
/**
*
* @author Adrian Cole
@ -34,6 +41,7 @@ public class Datacenter implements Comparable<Datacenter> {
private String name;
private String longName;
private Address locationAddress;
private Set<Region> regions = Sets.newLinkedHashSet();
public Builder id(int id) {
this.id = id;
@ -55,12 +63,24 @@ public class Datacenter implements Comparable<Datacenter> {
return this;
}
public Builder region(Region regions) {
this.regions.add(checkNotNull(regions, "regions"));
return this;
}
public Builder regions(Iterable<Region> regions) {
this.regions = ImmutableSet.<Region> copyOf(checkNotNull(regions, "regions"));
return this;
}
public Datacenter build() {
return new Datacenter(id, name, longName, locationAddress);
return new Datacenter(id, name, longName, locationAddress, regions);
}
public static Builder fromDatacenter(Datacenter in) {
return Datacenter.builder().id(in.getId()).name(in.getName()).longName(in.getLongName()).locationAddress(in.getLocationAddress());
return Datacenter.builder().id(in.getId()).name(in.getName())
.longName(in.getLongName()).locationAddress(in.getLocationAddress())
.regions(in.getRegions());
}
}
@ -68,17 +88,18 @@ public class Datacenter implements Comparable<Datacenter> {
private String name;
private String longName;
private Address locationAddress;
private Set<Region> regions = Sets.newLinkedHashSet();
// for deserializer
Datacenter() {
}
public Datacenter(int id, String name, String longName, Address locationAddress) {
public Datacenter(int id, String name, String longName, Address locationAddress, Iterable<Region> regions) {
this.id = id;
this.name = name;
this.longName = longName;
this.locationAddress = locationAddress;
this.regions = ImmutableSet.<Region> copyOf(checkNotNull(regions, "regions"));
}
@Override
@ -114,6 +135,16 @@ public class Datacenter implements Comparable<Datacenter> {
return locationAddress;
}
/**
* A location can be a member of 1 or more regions.
* Sometimes the list of regions is empty, for example as a new Datacenter is being added.
* The list of regions usually contains one with keyName=FIRST_AVAILABLE which should be ignored.
* @return The regions to which a location belongs.
*/
public Set<Region> getRegions() {
return regions;
}
public Builder toBuilder() {
return Builder.fromDatacenter(this);
}
@ -142,7 +173,7 @@ public class Datacenter implements Comparable<Datacenter> {
@Override
public String toString() {
return "[id=" + id + ", country=" + name + ", state=" + longName + "], locationAddress=" + locationAddress + "]";
return "[id=" + id + ", country=" + name + ", state=" + longName + "], locationAddress=" + locationAddress + ", regions="+regions+"]";
}

View File

@ -0,0 +1,128 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you 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.
*/
package org.jclouds.softlayer.domain;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Strings.emptyToNull;
/**
* A region is made up of a keyname and a description of that region.
* A region keyname can be used as part of an order.
* Check the SoftLayer_Product_Order service for more details.
*
* @author Jason King
* @see <a href= "http://sldn.softlayer.com/reference/datatypes/SoftLayer_Location_Region"
* />
*/
public class Region implements Comparable<Region> {
public static Builder builder() {
return new Builder();
}
public static class Builder {
private String keyname;
private String description;
public Builder keyname(String keyname) {
this.keyname = keyname;
return this;
}
public Builder description(String description) {
this.description = description;
return this;
}
public Region build() {
return new Region(keyname, description);
}
public static Builder fromAddress(Region in) {
return Region.builder().keyname(in.getKeyname())
.description(in.getDescription());
}
}
/* An integer representing the order in which this element is displayed */
private int sortOrder = 0;
private String keyname;
private String description;
// for deserializer
Region() {
}
public Region(String keyname, String description) {
this.keyname = checkNotNull(emptyToNull(keyname),"keyname cannot be null or empty:"+keyname);
this.description = checkNotNull(emptyToNull(description),"country cannot be null or empty:"+description);
}
@Override
public int compareTo(Region arg0) {
return new Integer(sortOrder).compareTo(arg0.sortOrder);
}
/**
* @return A unique key name for a region. Provided for easy debugging. This is to be sent in with an order.
*/
public String getKeyname() {
return keyname;
}
/**
* @return A short description of a region's name. This description is seen on the order forms.
*/
public String getDescription() {
return description;
}
public Builder toBuilder() {
return Builder.fromAddress(this);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Region region = (Region) o;
if (sortOrder != region.sortOrder) return false;
if (!description.equals(region.description)) return false;
if (!keyname.equals(region.keyname)) return false;
return true;
}
@Override
public int hashCode() {
int result = sortOrder;
result = 31 * result + keyname.hashCode();
result = 31 * result + description.hashCode();
return result;
}
@Override
public String toString() {
return "[keyname=" + keyname + ", description=" + description + "]";
}
}

View File

@ -53,7 +53,7 @@ public interface DatacenterAsyncClient {
*/
@GET
@Path("/SoftLayer_Location_Datacenter/Datacenters.json")
@QueryParams(keys = "objectMask", values = "locationAddress")
@QueryParams(keys = "objectMask", values = "locationAddress;regions")
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Set<Datacenter>> listDatacenters();
@ -63,7 +63,7 @@ public interface DatacenterAsyncClient {
*/
@GET
@Path("/SoftLayer_Location_Datacenter/{id}.json")
@QueryParams(keys = "objectMask", values = "locationAddress")
@QueryParams(keys = "objectMask", values = "locationAddress;regions")
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Datacenter> getDatacenter(@PathParam("id") long id);

View File

@ -43,7 +43,7 @@ import javax.ws.rs.core.MediaType;
@RequestFilters(BasicAuthentication.class)
@Path("/v{jclouds.api-version}")
public interface ProductPackageAsyncClient {
public static String PRODUCT_MASK = "items.prices;items.categories;locations.locationAddress";
public static String PRODUCT_MASK = "items.prices;items.categories;locations.locationAddress;locations.regions";
/**
* @see ProductPackageClient#getProductPackage

View File

@ -44,7 +44,7 @@ public class DatacenterAsyncClientTest extends BaseSoftLayerAsyncClientTest<Data
HttpRequest httpRequest = processor.createRequest(method);
assertRequestLineEquals(httpRequest,
"GET https://api.softlayer.com/rest/v3/SoftLayer_Location_Datacenter/Datacenters.json?objectMask=locationAddress HTTP/1.1");
"GET https://api.softlayer.com/rest/v3/SoftLayer_Location_Datacenter/Datacenters.json?objectMask=locationAddress%3Bregions HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
@ -53,7 +53,7 @@ public class DatacenterAsyncClientTest extends BaseSoftLayerAsyncClientTest<Data
httpRequest = Iterables.getOnlyElement(httpRequest.getFilters()).filter(httpRequest);
assertRequestLineEquals(httpRequest,
"GET https://api.softlayer.com/rest/v3/SoftLayer_Location_Datacenter/Datacenters.json?objectMask=locationAddress HTTP/1.1");
"GET https://api.softlayer.com/rest/v3/SoftLayer_Location_Datacenter/Datacenters.json?objectMask=locationAddress%3Bregions HTTP/1.1");
// for example, using basic authentication, we should get "only one"
// header
assertNonPayloadHeadersEqual(httpRequest,
@ -73,7 +73,7 @@ public class DatacenterAsyncClientTest extends BaseSoftLayerAsyncClientTest<Data
HttpRequest httpRequest = processor.createRequest(method, 1234);
assertRequestLineEquals(httpRequest,
"GET https://api.softlayer.com/rest/v3/SoftLayer_Location_Datacenter/1234.json?objectMask=locationAddress HTTP/1.1");
"GET https://api.softlayer.com/rest/v3/SoftLayer_Location_Datacenter/1234.json?objectMask=locationAddress%3Bregions HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);

View File

@ -25,6 +25,7 @@ import java.util.Set;
import org.jclouds.softlayer.domain.Address;
import org.jclouds.softlayer.domain.Datacenter;
import org.jclouds.softlayer.domain.Region;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
@ -61,6 +62,7 @@ public class DatacenterClientLiveTest extends BaseSoftLayerClientLiveTest {
@Test
public void testListDatacentersContent() {
Builder<Datacenter> builder = ImmutableSet.<Datacenter> builder();
builder.add(Datacenter.builder().id(265592).name("ams01").longName("Amsterdam 1").build());
builder.add(Datacenter.builder().id(3).name("dal01").longName("Dallas").build());
builder.add(Datacenter.builder().id(18171).name("sea01").longName("Seattle").build());
builder.add(Datacenter.builder().id(168642).name("sjc01").longName("San Jose 1").build());
@ -91,6 +93,12 @@ public class DatacenterClientLiveTest extends BaseSoftLayerClientLiveTest {
assert dc.getId() > 0 : dc;
assert dc.getName() != null : dc;
assert dc.getLongName() != null : dc;
for( Region region: dc.getRegions()) checkRegion(region);
}
private void checkRegion(Region region) {
assert !region.getDescription().isEmpty() : region;
assert !region.getKeyname().isEmpty() : region;
}
private void checkAddress(Address address) {

View File

@ -43,7 +43,7 @@ public class ProductPackageAsyncClientTest extends BaseSoftLayerAsyncClientTest<
assertRequestLineEquals(
httpRequest,
"GET https://api.softlayer.com/rest/v3/SoftLayer_Product_Package/1234.json?objectMask=items.prices%3Bitems.categories%3Blocations.locationAddress HTTP/1.1");
"GET https://api.softlayer.com/rest/v3/SoftLayer_Product_Package/1234.json?objectMask=items.prices%3Bitems.categories%3Blocations.locationAddress%3Blocations.regions HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);

View File

@ -39,7 +39,7 @@ import static org.testng.Assert.*;
*
* @author Adrian Cole
*/
@Test(groups = "live")
@Test(groups = "live", sequential = true)
public class ProductPackageClientLiveTest extends BaseSoftLayerClientLiveTest {
/**
@ -183,6 +183,12 @@ public class ProductPackageClientLiveTest extends BaseSoftLayerClientLiveTest {
assert datacenter.getId() > 0 : datacenter;
assert datacenter.getName() != null : datacenter;
assert datacenter.getLongName() != null : datacenter;
for( Region region: datacenter.getRegions()) checkRegion(region);
}
private void checkRegion(Region region) {
assert !region.getDescription().isEmpty() : region;
assert !region.getKeyname().isEmpty() : region;
}
private void checkAddress(Address address) {