You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by na...@apache.org on 2017/07/06 14:18:35 UTC
[2/2] jclouds-labs git commit: JCLOUDS-1255 Dimension Data Network
API implementation.
JCLOUDS-1255 Dimension Data Network API implementation.
Project: http://git-wip-us.apache.org/repos/asf/jclouds-labs/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds-labs/commit/2495dd9a
Tree: http://git-wip-us.apache.org/repos/asf/jclouds-labs/tree/2495dd9a
Diff: http://git-wip-us.apache.org/repos/asf/jclouds-labs/diff/2495dd9a
Branch: refs/heads/master
Commit: 2495dd9a6453450c7341b66043b8ed82bc377600
Parents: 4febcfa
Author: Trevor Flanagan <tr...@itaas.dimensiondata.com>
Authored: Wed Jun 28 13:44:47 2017 +0100
Committer: Ignasi Barrera <na...@apache.org>
Committed: Thu Jul 6 16:14:10 2017 +0200
----------------------------------------------------------------------
.../DimensionDataCloudControlApi.java | 4 +
.../cloudcontrol/domain/NetworkDomain.java | 6 +-
.../cloudcontrol/domain/Server.java | 24 -
.../cloudcontrol/domain/State.java | 43 ++
.../dimensiondata/cloudcontrol/domain/Vlan.java | 6 +-
.../cloudcontrol/features/NetworkApi.java | 487 +++++++++++++++++++
.../predicates/NetworkDomainStatus.java | 50 ++
.../cloudcontrol/predicates/VlanStatus.java | 52 ++
.../DimensionDataCloudControlResponseUtils.java | 52 ++
.../cloudcontrol/utils/ParseResponse.java | 86 ++++
.../features/NetworkApiLiveTest.java | 126 +++++
.../features/NetworkApiMockTest.java | 392 +++++++++++++++
.../BaseDimensionDataCloudControlMockTest.java | 9 +
.../parse/FirewallRulesParseTest.java | 52 ++
.../cloudcontrol/parse/NatRulesParseTest.java | 49 ++
.../parse/NetworkDomainsParseTest.java | 49 ++
.../parse/PublicIpBlocksParseTest.java | 46 ++
.../cloudcontrol/parse/VlansParseTest.java | 52 ++
.../cloudcontrol/utils/ResponseParseTest.java | 56 +++
.../src/test/resources/firewallRules-page1.json | 283 +++++++++++
.../src/test/resources/firewallRules-page2.json | 108 ++++
.../src/test/resources/firewallRules.json | 33 ++
dimensiondata/src/test/resources/natRule.json | 9 +
.../src/test/resources/natRules-page1.json | 98 ++++
.../src/test/resources/natRules-page2.json | 98 ++++
dimensiondata/src/test/resources/natRules.json | 26 +
.../src/test/resources/networkDomain.json | 10 +
.../test/resources/networkDomains-page1.json | 108 ++++
.../test/resources/networkDomains-page2.json | 108 ++++
.../src/test/resources/networkDomains.json | 18 +
dimensiondata/src/test/resources/portList.json | 16 +
dimensiondata/src/test/resources/portLists.json | 32 ++
.../src/test/resources/publicIpBlock.json | 9 +
.../test/resources/publicIpBlocks-page1.json | 98 ++++
.../test/resources/publicIpBlocks-page2.json | 98 ++++
.../src/test/resources/publicIpBlocks.json | 17 +
dimensiondata/src/test/resources/response.json | 30 ++
dimensiondata/src/test/resources/vlan.json | 22 +
.../src/test/resources/vlans-page1.json | 228 +++++++++
.../src/test/resources/vlans-page2.json | 228 +++++++++
dimensiondata/src/test/resources/vlans.json | 30 ++
41 files changed, 3318 insertions(+), 30 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2495dd9a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/DimensionDataCloudControlApi.java
----------------------------------------------------------------------
diff --git a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/DimensionDataCloudControlApi.java b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/DimensionDataCloudControlApi.java
index 7e21571..5967453 100644
--- a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/DimensionDataCloudControlApi.java
+++ b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/DimensionDataCloudControlApi.java
@@ -18,6 +18,7 @@ package org.jclouds.dimensiondata.cloudcontrol;
import org.jclouds.dimensiondata.cloudcontrol.features.AccountApi;
import org.jclouds.dimensiondata.cloudcontrol.features.InfrastructureApi;
+import org.jclouds.dimensiondata.cloudcontrol.features.NetworkApi;
import org.jclouds.dimensiondata.cloudcontrol.features.ServerImageApi;
import org.jclouds.rest.annotations.Delegate;
@@ -33,4 +34,7 @@ public interface DimensionDataCloudControlApi extends Closeable {
@Delegate
ServerImageApi getServerImageApi();
+
+ @Delegate
+ NetworkApi getNetworkApi();
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2495dd9a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/NetworkDomain.java
----------------------------------------------------------------------
diff --git a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/NetworkDomain.java b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/NetworkDomain.java
index eb6c291..acdaf75 100644
--- a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/NetworkDomain.java
+++ b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/NetworkDomain.java
@@ -47,7 +47,7 @@ public abstract class NetworkDomain {
public abstract String description();
@Nullable
- public abstract String state();
+ public abstract State state();
@Nullable
public abstract Type type();
@@ -59,7 +59,7 @@ public abstract class NetworkDomain {
public abstract Date createTime();
@SerializedNames({ "id", "datacenterId", "name", "description", "state", "type", "snatIpv4Address", "createTime" })
- public static NetworkDomain create(String id, String datacenterId, String name, String description, String state,
+ public static NetworkDomain create(String id, String datacenterId, String name, String description, State state,
Type type, String snatIpv4Address, Date createTime) {
return builder().id(id).datacenterId(datacenterId).name(name).description(description).state(state).type(type)
.snatIpv4Address(snatIpv4Address).createTime(createTime).build();
@@ -77,7 +77,7 @@ public abstract class NetworkDomain {
public abstract Builder description(String description);
- public abstract Builder state(String state);
+ public abstract Builder state(State state);
public abstract Builder type(Type type);
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2495dd9a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/Server.java
----------------------------------------------------------------------
diff --git a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/Server.java b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/Server.java
index 9be5f33..79de501 100644
--- a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/Server.java
+++ b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/Server.java
@@ -17,7 +17,6 @@
package org.jclouds.dimensiondata.cloudcontrol.domain;
import com.google.auto.value.AutoValue;
-import com.google.common.base.CaseFormat;
import com.google.common.collect.ImmutableList;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.json.SerializedNames;
@@ -25,32 +24,9 @@ import org.jclouds.json.SerializedNames;
import java.util.Date;
import java.util.List;
-import static com.google.common.base.Preconditions.checkNotNull;
-
@AutoValue
public abstract class Server {
- public enum State {
- NORMAL, FAILED_ADD, FAILED_CHANGE, FAILED_DELETE, PENDING_DELETE, DELETED, UNRECOGNIZED;
-
- @Override
- public String toString() {
- return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name());
- }
-
- public static State fromValue(String state) {
- try {
- return valueOf(CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(state, "state")));
- } catch (IllegalArgumentException e) {
- return UNRECOGNIZED;
- }
- }
-
- public boolean isFailed() {
- return this == FAILED_ADD || this == FAILED_CHANGE || this == FAILED_DELETE;
- }
- }
-
Server() {
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2495dd9a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/State.java
----------------------------------------------------------------------
diff --git a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/State.java b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/State.java
new file mode 100644
index 0000000..e832264
--- /dev/null
+++ b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/State.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.dimensiondata.cloudcontrol.domain;
+
+import com.google.common.base.CaseFormat;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+public enum State {
+
+ NORMAL, FAILED_ADD, FAILED_CHANGE, FAILED_DELETE, PENDING_DELETE, DELETED, UNRECOGNIZED;
+
+ @Override
+ public String toString() {
+ return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name());
+ }
+
+ public static State fromValue(String state) {
+ try {
+ return valueOf(CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(state, "state")));
+ } catch (IllegalArgumentException e) {
+ return UNRECOGNIZED;
+ }
+ }
+
+ public boolean isFailed() {
+ return this == FAILED_ADD || this == FAILED_CHANGE || this == FAILED_DELETE;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2495dd9a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/Vlan.java
----------------------------------------------------------------------
diff --git a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/Vlan.java b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/Vlan.java
index 7a62543..4e40beb 100644
--- a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/Vlan.java
+++ b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/Vlan.java
@@ -39,7 +39,7 @@ public abstract class Vlan {
public abstract String datacenterId();
- public abstract String state();
+ public abstract State state();
public abstract Date createTime();
@@ -55,7 +55,7 @@ public abstract class Vlan {
@SerializedNames({ "id", "name", "description", "datacenterId", "state", "createTime", "ipv4GatewayAddress",
"ipv6GatewayAddress", "networkDomain", "privateIpv4Range", "ipv6Range" })
- public static Vlan create(String id, String name, String description, String datacenterId, String state,
+ public static Vlan create(String id, String name, String description, String datacenterId, State state,
Date createTime, String ipv4GatewayAddress, String ipv6GatewayAddress, NetworkDomain networkDomain,
IpRange privateIpv4Range, IpRange ipv6Range) {
return builder().id(id).name(name).description(description).datacenterId(datacenterId).state(state)
@@ -75,7 +75,7 @@ public abstract class Vlan {
public abstract Builder datacenterId(String datacenterId);
- public abstract Builder state(String state);
+ public abstract Builder state(State state);
public abstract Builder createTime(Date createTime);
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2495dd9a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/features/NetworkApi.java
----------------------------------------------------------------------
diff --git a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/features/NetworkApi.java b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/features/NetworkApi.java
new file mode 100644
index 0000000..129fa99
--- /dev/null
+++ b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/features/NetworkApi.java
@@ -0,0 +1,487 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.dimensiondata.cloudcontrol.features;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.inject.TypeLiteral;
+import org.jclouds.Fallbacks;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.collect.IterableWithMarker;
+import org.jclouds.collect.PagedIterable;
+import org.jclouds.collect.internal.Arg0ToPagedIterable;
+import org.jclouds.dimensiondata.cloudcontrol.DimensionDataCloudControlApi;
+import org.jclouds.dimensiondata.cloudcontrol.domain.FirewallRule;
+import org.jclouds.dimensiondata.cloudcontrol.domain.FirewallRuleTarget;
+import org.jclouds.dimensiondata.cloudcontrol.domain.FirewallRuleTarget.Port;
+import org.jclouds.dimensiondata.cloudcontrol.domain.FirewallRules;
+import org.jclouds.dimensiondata.cloudcontrol.domain.NatRule;
+import org.jclouds.dimensiondata.cloudcontrol.domain.NatRules;
+import org.jclouds.dimensiondata.cloudcontrol.domain.NetworkDomain;
+import org.jclouds.dimensiondata.cloudcontrol.domain.NetworkDomains;
+import org.jclouds.dimensiondata.cloudcontrol.domain.PaginatedCollection;
+import org.jclouds.dimensiondata.cloudcontrol.domain.Placement;
+import org.jclouds.dimensiondata.cloudcontrol.domain.PublicIpBlock;
+import org.jclouds.dimensiondata.cloudcontrol.domain.PublicIpBlocks;
+import org.jclouds.dimensiondata.cloudcontrol.domain.Response;
+import org.jclouds.dimensiondata.cloudcontrol.domain.Vlan;
+import org.jclouds.dimensiondata.cloudcontrol.domain.Vlans;
+import org.jclouds.dimensiondata.cloudcontrol.filters.OrganisationIdFilter;
+import org.jclouds.dimensiondata.cloudcontrol.options.PaginationOptions;
+import org.jclouds.dimensiondata.cloudcontrol.utils.ParseResponse;
+import org.jclouds.http.filters.BasicAuthentication;
+import org.jclouds.http.functions.ParseJson;
+import org.jclouds.json.Json;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.MapBinder;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.Transform;
+import org.jclouds.rest.binders.BindToJsonPayload;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import java.util.List;
+
+@RequestFilters({ BasicAuthentication.class, OrganisationIdFilter.class })
+@Consumes(MediaType.APPLICATION_JSON)
+@Path("/{jclouds.api-version}/network")
+public interface NetworkApi {
+
+ @Named("network:deployNetworkDomain")
+ @POST
+ @Path("/deployNetworkDomain")
+ @Produces(MediaType.APPLICATION_JSON)
+ @MapBinder(BindToJsonPayload.class)
+ @ResponseParser(ParseNetworkDomainId.class)
+ String deployNetworkDomain(@PayloadParam("datacenterId") String datacenterId, @PayloadParam("name") String name,
+ @PayloadParam("description") String description, @PayloadParam("type") String type);
+
+ @Named("networkDomain:get")
+ @GET
+ @Path("/networkDomain/{id}")
+ @Fallback(NullOnNotFoundOr404.class)
+ NetworkDomain getNetworkDomain(@PathParam("id") String networkDomainId);
+
+ @Named("networkDomain:listWithDatacenterIdAndName")
+ @GET
+ @Path("/networkDomain")
+ @Transform(ParseNetworkDomains.ToPagedIterable.class)
+ @ResponseParser(ParseNetworkDomains.class)
+ @Fallback(Fallbacks.EmptyPagedIterableOnNotFoundOr404.class)
+ PagedIterable<NetworkDomain> listNetworkDomainsWithDatacenterIdAndName(
+ @QueryParam("datacenterId") String datacenterId, @QueryParam("name") String name);
+
+ @Named("networkDomain:list")
+ @GET
+ @Path("/networkDomain")
+ @ResponseParser(ParseNetworkDomains.class)
+ @Fallback(Fallbacks.EmptyIterableWithMarkerOnNotFoundOr404.class)
+ PaginatedCollection<NetworkDomain> listNetworkDomains(PaginationOptions options);
+
+ @Named("networkDomain:list")
+ @GET
+ @Path("/networkDomain")
+ @Transform(ParseNetworkDomains.ToPagedIterable.class)
+ @ResponseParser(ParseNetworkDomains.class)
+ @Fallback(Fallbacks.EmptyPagedIterableOnNotFoundOr404.class)
+ PagedIterable<NetworkDomain> listNetworkDomains();
+
+ @Named("networkDomain:delete")
+ @POST
+ @Path("/deleteNetworkDomain")
+ @Produces(MediaType.APPLICATION_JSON)
+ @MapBinder(BindToJsonPayload.class)
+ @Fallback(Fallbacks.VoidOnNotFoundOr404.class)
+ void deleteNetworkDomain(@PayloadParam("id") String networkDomainId);
+
+ @Named("vlan:deploy")
+ @POST
+ @Path("/deployVlan")
+ @Produces(MediaType.APPLICATION_JSON)
+ @MapBinder(BindToJsonPayload.class)
+ @ResponseParser(ParseVlanId.class)
+ String deployVlan(@PayloadParam("networkDomainId") String networkDomainId, @PayloadParam("name") String name,
+ @PayloadParam("description") String description,
+ @PayloadParam("privateIpv4BaseAddress") String privateIpv4BaseAddress,
+ @PayloadParam("privateIpv4PrefixSize") Integer privateIpv4PrefixSize);
+
+ @Named("vlan:get")
+ @GET
+ @Path("/vlan/{id}")
+ @Fallback(NullOnNotFoundOr404.class)
+ Vlan getVlan(@PathParam("id") String vlanId);
+
+ @Named("vlan:list")
+ @GET
+ @Path("/vlan")
+ @ResponseParser(ParseVlans.class)
+ @Fallback(Fallbacks.EmptyIterableWithMarkerOnNotFoundOr404.class)
+ PaginatedCollection<Vlan> listVlans(@QueryParam("networkDomainId") String networkDomainId,
+ PaginationOptions options);
+
+ @Named("vlan:list")
+ @GET
+ @Path("/vlan")
+ @Transform(ParseVlans.ToPagedIterable.class)
+ @ResponseParser(ParseVlans.class)
+ @Fallback(Fallbacks.EmptyPagedIterableOnNotFoundOr404.class)
+ PagedIterable<Vlan> listVlans(@QueryParam("networkDomainId") String networkDomainId);
+
+ @Named("vlan:delete")
+ @POST
+ @Path("/deleteVlan")
+ @Produces(MediaType.APPLICATION_JSON)
+ @MapBinder(BindToJsonPayload.class)
+ @Fallback(Fallbacks.VoidOnNotFoundOr404.class)
+ void deleteVlan(@PayloadParam("id") String vlanId);
+
+ @Named("networkDomain:addPublicIpBlock")
+ @POST
+ @Path("/addPublicIpBlock")
+ @Produces(MediaType.APPLICATION_JSON)
+ @MapBinder(BindToJsonPayload.class)
+ Response addPublicIpBlock(@PayloadParam("networkDomainId") String networkDomainId);
+
+ @Named("networkDomain:listPublicIPv4AddressBlocks")
+ @GET
+ @Path("/publicIpBlock")
+ @ResponseParser(ParsePublicIpBlocks.class)
+ @Fallback(Fallbacks.EmptyIterableWithMarkerOnNotFoundOr404.class)
+ PaginatedCollection<PublicIpBlock> listPublicIPv4AddressBlocks(@QueryParam("networkDomainId") String networkDomainId,
+ PaginationOptions options);
+
+ @Named("networkDomain:listPublicIPv4AddressBlock")
+ @GET
+ @Path("/publicIpBlock")
+ @Transform(ParsePublicIpBlocks.ToPagedIterable.class)
+ @ResponseParser(ParsePublicIpBlocks.class)
+ @Fallback(Fallbacks.EmptyPagedIterableOnNotFoundOr404.class)
+ PagedIterable<PublicIpBlock> listPublicIPv4AddressBlocks(@QueryParam("networkDomainId") String networkDomainId);
+
+ @Named("networkDomain:removePublicIpBlock")
+ @POST
+ @Path("/removePublicIpBlock")
+ @Produces(MediaType.APPLICATION_JSON)
+ @MapBinder(BindToJsonPayload.class)
+ @Fallback(Fallbacks.VoidOnNotFoundOr404.class)
+ void removePublicIpBlock(@PayloadParam("id") String publicIpBlockId);
+
+ @Named("networkDomain:getPublicIPv4AddressBlock")
+ @GET
+ @Path("/publicIpBlock/{id}")
+ @Fallback(NullOnNotFoundOr404.class)
+ PublicIpBlock getPublicIPv4AddressBlock(@PathParam("id") String publicIPv4AddressBlockId);
+
+ @Named("network:createNatRule")
+ @POST
+ @Path("/createNatRule")
+ @Produces(MediaType.APPLICATION_JSON)
+ @MapBinder(BindToJsonPayload.class)
+ @Fallback(Fallbacks.VoidOnNotFoundOr404.class)
+ Response createNatRule(@PayloadParam("networkDomainId") String networkDomainId,
+ @PayloadParam("internalIp") String internalIp, @PayloadParam("externalIp") String externalIp);
+
+ @Named("networkDomain:listNatRules")
+ @GET
+ @Path("/natRule")
+ @ResponseParser(ParseNatRules.class)
+ @Fallback(Fallbacks.EmptyIterableWithMarkerOnNotFoundOr404.class)
+ PaginatedCollection<NatRule> listNatRules(@QueryParam("networkDomainId") String networkDomainId,
+ PaginationOptions options);
+
+ @Named("networkDomain:listNatRules")
+ @GET
+ @Path("/natRule")
+ @Transform(ParseNatRules.ToPagedIterable.class)
+ @ResponseParser(ParseNatRules.class)
+ @Fallback(Fallbacks.EmptyPagedIterableOnNotFoundOr404.class)
+ PagedIterable<NatRule> listNatRules(@QueryParam("networkDomainId") String networkDomainId);
+
+ @Named("network:getNatRule")
+ @GET
+ @Path("/natRule/{id}")
+ @Fallback(NullOnNotFoundOr404.class)
+ NatRule getNatRule(@PathParam("id") String natRuleId);
+
+ @Named("network:deleteNatRule")
+ @POST
+ @Path("/deleteNatRule")
+ @Produces(MediaType.APPLICATION_JSON)
+ @MapBinder(BindToJsonPayload.class)
+ @Fallback(Fallbacks.VoidOnNotFoundOr404.class)
+ void deleteNatRule(@PayloadParam("id") String natRuleId);
+
+ @Named("networkDomain:createFirewallRule")
+ @POST
+ @Path("/createFirewallRule")
+ @Produces(MediaType.APPLICATION_JSON)
+ @MapBinder(BindToJsonPayload.class)
+ @ResponseParser(FirewallRuleId.class)
+ String createFirewallRule(@PayloadParam("networkDomainId") String networkDomainId, @PayloadParam("name") String name,
+ @PayloadParam("action") String action, @PayloadParam("ipVersion") String ipVersion,
+ @PayloadParam("protocol") String protocol, @PayloadParam("source") FirewallRuleTarget source,
+ @PayloadParam("destination") FirewallRuleTarget destination, @PayloadParam("enabled") Boolean enabled,
+ @PayloadParam("placement") Placement placement);
+
+ @Named("networkDomain:listFirewallRules")
+ @GET
+ @Path("/firewallRule")
+ @ResponseParser(ParseFirewallRules.class)
+ @Fallback(Fallbacks.EmptyIterableWithMarkerOnNotFoundOr404.class)
+ PaginatedCollection<FirewallRule> listFirewallRules(@QueryParam("networkDomainId") String networkDomainId,
+ PaginationOptions options);
+
+ @Named("networkDomain:listFirewallRules")
+ @GET
+ @Path("/firewallRule")
+ @Transform(ParseFirewallRules.ToPagedIterable.class)
+ @ResponseParser(ParseFirewallRules.class)
+ @Fallback(Fallbacks.EmptyPagedIterableOnNotFoundOr404.class)
+ PagedIterable<FirewallRule> listFirewallRules(@QueryParam("networkDomainId") String networkDomainId);
+
+ @Named("networkDomain:deleteFirewallRule")
+ @POST
+ @Path("/deleteFirewallRule")
+ @Produces(MediaType.APPLICATION_JSON)
+ @MapBinder(BindToJsonPayload.class)
+ @Fallback(Fallbacks.VoidOnNotFoundOr404.class)
+ void deleteFirewallRule(@PayloadParam("id") String firewallRuleId);
+
+ @Named("networkDomain:createPortList")
+ @POST
+ @Path("/createPortList")
+ @Produces(MediaType.APPLICATION_JSON)
+ @MapBinder(BindToJsonPayload.class)
+ @ResponseParser(PortListId.class)
+ String createPortList(@PayloadParam("networkDomainId") String networkDomainId, @PayloadParam("name") String name,
+ @PayloadParam("description") String description, @PayloadParam("port") List<Port> port,
+ @PayloadParam("childPortListId") List<String> childPortListId);
+
+ @Named("networkDomain:getPortList")
+ @GET
+ @Path("/portList/{id}")
+ @Fallback(NullOnNotFoundOr404.class)
+ FirewallRuleTarget.PortList getPortList(@PathParam("id") String portListId);
+
+ @Named("networkDomain:deletePortList")
+ @POST
+ @Path("/deletePortList")
+ @Produces(MediaType.APPLICATION_JSON)
+ @MapBinder(BindToJsonPayload.class)
+ @Fallback(Fallbacks.VoidOnNotFoundOr404.class)
+ void deletePortList(@PayloadParam("id") String portListId);
+
+ @Singleton
+ final class ParseFirewallRules extends ParseJson<FirewallRules> {
+
+ @Inject
+ ParseFirewallRules(Json json) {
+ super(json, TypeLiteral.get(FirewallRules.class));
+ }
+
+ private static class ToPagedIterable
+ extends Arg0ToPagedIterable<FirewallRule, ParseFirewallRules.ToPagedIterable> {
+
+ private DimensionDataCloudControlApi api;
+
+ @Inject
+ ToPagedIterable(DimensionDataCloudControlApi api) {
+ this.api = api;
+ }
+
+ @Override
+ protected Function<Object, IterableWithMarker<FirewallRule>> markerToNextForArg0(Optional<Object> optional) {
+ return new Function<Object, IterableWithMarker<FirewallRule>>() {
+ @Override
+ public IterableWithMarker<FirewallRule> apply(Object input) {
+ PaginationOptions paginationOptions = PaginationOptions.class.cast(input);
+ return api.getNetworkApi().listFirewallRules(getArgs(request).get(0).toString(), paginationOptions);
+ }
+ };
+ }
+ }
+ }
+
+ @Singleton
+ final class ParseNatRules extends ParseJson<NatRules> {
+
+ @Inject
+ ParseNatRules(Json json) {
+ super(json, TypeLiteral.get(NatRules.class));
+ }
+
+ private static class ToPagedIterable extends Arg0ToPagedIterable<NatRule, ToPagedIterable> {
+
+ private DimensionDataCloudControlApi api;
+
+ @Inject
+ ToPagedIterable(DimensionDataCloudControlApi api) {
+ this.api = api;
+ }
+
+ @Override
+ protected Function<Object, IterableWithMarker<NatRule>> markerToNextForArg0(Optional<Object> optional) {
+ return new Function<Object, IterableWithMarker<NatRule>>() {
+ @Override
+ public IterableWithMarker<NatRule> apply(Object input) {
+ PaginationOptions paginationOptions = PaginationOptions.class.cast(input);
+ return api.getNetworkApi().listNatRules(getArgs(request).get(0).toString(), paginationOptions);
+ }
+ };
+ }
+ }
+ }
+
+ @Singleton
+ final class ParseNetworkDomains extends ParseJson<NetworkDomains> {
+
+ @Inject
+ ParseNetworkDomains(Json json) {
+ super(json, TypeLiteral.get(NetworkDomains.class));
+ }
+
+ private static class ToPagedIterable extends Arg0ToPagedIterable<NetworkDomain, ToPagedIterable> {
+
+ private DimensionDataCloudControlApi api;
+
+ @Inject
+ ToPagedIterable(DimensionDataCloudControlApi api) {
+ this.api = api;
+ }
+
+ @Override
+ protected Function<Object, IterableWithMarker<NetworkDomain>> markerToNextForArg0(Optional<Object> optional) {
+ return new Function<Object, IterableWithMarker<NetworkDomain>>() {
+ @Override
+ public IterableWithMarker<NetworkDomain> apply(Object input) {
+ PaginationOptions paginationOptions = PaginationOptions.class.cast(input);
+ return api.getNetworkApi().listNetworkDomains(paginationOptions);
+ }
+ };
+ }
+ }
+ }
+
+ @Singleton
+ final class ParsePublicIpBlocks extends ParseJson<PublicIpBlocks> {
+
+ @Inject
+ ParsePublicIpBlocks(Json json) {
+ super(json, TypeLiteral.get(PublicIpBlocks.class));
+ }
+
+ private static class ToPagedIterable extends Arg0ToPagedIterable<PublicIpBlock, ToPagedIterable> {
+
+ private DimensionDataCloudControlApi api;
+
+ @Inject
+ ToPagedIterable(DimensionDataCloudControlApi api) {
+ this.api = api;
+ }
+
+ @Override
+ protected Function<Object, IterableWithMarker<PublicIpBlock>> markerToNextForArg0(Optional<Object> optional) {
+ return new Function<Object, IterableWithMarker<PublicIpBlock>>() {
+ @Override
+ public IterableWithMarker<PublicIpBlock> apply(Object input) {
+ PaginationOptions paginationOptions = PaginationOptions.class.cast(input);
+ return api.getNetworkApi()
+ .listPublicIPv4AddressBlocks(getArgs(request).get(0).toString(), paginationOptions);
+ }
+ };
+ }
+ }
+ }
+
+ @Singleton
+ final class ParseVlans extends ParseJson<Vlans> {
+
+ @Inject
+ ParseVlans(Json json) {
+ super(json, TypeLiteral.get(Vlans.class));
+ }
+
+ static class ToPagedIterable extends Arg0ToPagedIterable<Vlan, ToPagedIterable> {
+
+ private DimensionDataCloudControlApi api;
+
+ @Inject
+ ToPagedIterable(DimensionDataCloudControlApi api) {
+ this.api = api;
+ }
+
+ @Override
+ protected Function<Object, IterableWithMarker<Vlan>> markerToNextForArg0(Optional<Object> optional) {
+ return new Function<Object, IterableWithMarker<Vlan>>() {
+ @Override
+ public IterableWithMarker<Vlan> apply(Object input) {
+ PaginationOptions paginationOptions = PaginationOptions.class.cast(input);
+ return api.getNetworkApi().listVlans(getArgs(request).get(0).toString(), paginationOptions);
+ }
+ };
+ }
+ }
+ }
+
+ @Singleton
+ final class ParseNetworkDomainId extends ParseResponse {
+
+ @Inject
+ ParseNetworkDomainId(Json json) {
+ super(json, "networkDomainId");
+ }
+ }
+
+ @Singleton
+ final class ParseVlanId extends ParseResponse {
+
+ @Inject
+ ParseVlanId(Json json) {
+ super(json, "vlanId");
+ }
+ }
+
+ @Singleton
+ final class PortListId extends ParseResponse {
+
+ @Inject
+ PortListId(Json json) {
+ super(json, "portListId");
+ }
+ }
+
+ @Singleton
+ final class FirewallRuleId extends ParseResponse {
+
+ @Inject
+ FirewallRuleId(Json json) {
+ super(json, "firewallRuleId");
+ }
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2495dd9a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/predicates/NetworkDomainStatus.java
----------------------------------------------------------------------
diff --git a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/predicates/NetworkDomainStatus.java b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/predicates/NetworkDomainStatus.java
new file mode 100644
index 0000000..94882d1
--- /dev/null
+++ b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/predicates/NetworkDomainStatus.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.dimensiondata.cloudcontrol.predicates;
+
+import com.google.common.base.Predicate;
+import org.jclouds.dimensiondata.cloudcontrol.domain.NetworkDomain;
+import org.jclouds.dimensiondata.cloudcontrol.domain.State;
+import org.jclouds.dimensiondata.cloudcontrol.features.NetworkApi;
+import org.jclouds.logging.Logger;
+
+import javax.annotation.Resource;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+public class NetworkDomainStatus implements Predicate<String> {
+
+ @Resource
+ protected Logger logger = Logger.NULL;
+
+ private final State state;
+ private final NetworkApi networkApi;
+
+ public NetworkDomainStatus(NetworkApi networkApi, State state) {
+ this.networkApi = networkApi;
+ this.state = state;
+ }
+
+ @Override
+ public boolean apply(String networkDomainId) {
+ checkNotNull(networkDomainId, "networkDomainId");
+ logger.trace("looking for state on network domain %s", networkDomainId);
+ final NetworkDomain networkDomain = networkApi.getNetworkDomain(networkDomainId);
+ final boolean isDeleted = networkDomain == null && state == State.DELETED;
+ return isDeleted || (networkDomain != null && networkDomain.state() == state);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2495dd9a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/predicates/VlanStatus.java
----------------------------------------------------------------------
diff --git a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/predicates/VlanStatus.java b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/predicates/VlanStatus.java
new file mode 100644
index 0000000..79aa75a
--- /dev/null
+++ b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/predicates/VlanStatus.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.dimensiondata.cloudcontrol.predicates;
+
+import com.google.common.base.Predicate;
+import org.jclouds.dimensiondata.cloudcontrol.domain.State;
+import org.jclouds.dimensiondata.cloudcontrol.domain.Vlan;
+import org.jclouds.dimensiondata.cloudcontrol.features.NetworkApi;
+import org.jclouds.logging.Logger;
+
+import javax.annotation.Resource;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+public class VlanStatus implements Predicate<String> {
+
+ @Resource
+ protected Logger logger = Logger.NULL;
+
+ private final State state;
+ private final NetworkApi networkApi;
+
+ public VlanStatus(NetworkApi networkApi, State state) {
+ this.networkApi = networkApi;
+ this.state = state;
+ }
+
+ @Override
+ public boolean apply(String vlanId) {
+ checkNotNull(vlanId, "vlanId");
+ logger.trace("looking for state on vlan %s", vlanId);
+ final Vlan vlan = networkApi.getVlan(vlanId);
+ final boolean isDeleted = (vlan == null) && (state == State.DELETED);
+ return isDeleted || ((vlan != null) && vlan.state() == state);
+
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2495dd9a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/utils/DimensionDataCloudControlResponseUtils.java
----------------------------------------------------------------------
diff --git a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/utils/DimensionDataCloudControlResponseUtils.java b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/utils/DimensionDataCloudControlResponseUtils.java
new file mode 100644
index 0000000..2c80d7c
--- /dev/null
+++ b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/utils/DimensionDataCloudControlResponseUtils.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.dimensiondata.cloudcontrol.utils;
+
+import org.jclouds.dimensiondata.cloudcontrol.domain.State;
+import org.jclouds.dimensiondata.cloudcontrol.features.NetworkApi;
+import org.jclouds.dimensiondata.cloudcontrol.predicates.NetworkDomainStatus;
+import org.jclouds.dimensiondata.cloudcontrol.predicates.VlanStatus;
+
+import static org.jclouds.util.Predicates2.retry;
+
+public class DimensionDataCloudControlResponseUtils {
+
+ private static String convertServerId(String serverId) {
+ return serverId.replaceAll("-", "_");
+ }
+
+ public static String generateFirewallRuleName(String serverId) {
+ return String.format("fw.%s", convertServerId(serverId));
+ }
+
+ public static void waitForNetworkDomainStatus(NetworkApi api, String networkDomainId, State state,
+ long timeoutMillis, String message) {
+ boolean isNetworkDomainInState = retry(new NetworkDomainStatus(api, state), timeoutMillis).apply(networkDomainId);
+ if (!isNetworkDomainInState) {
+ throw new IllegalStateException(message);
+ }
+ }
+
+ public static void waitForVlanStatus(NetworkApi api, String vlanId, State state, long timeoutMillis,
+ String message) {
+ boolean isVlanInstate = retry(new VlanStatus(api, state), timeoutMillis).apply(vlanId);
+ if (!isVlanInstate) {
+ throw new IllegalStateException(message);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2495dd9a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/utils/ParseResponse.java
----------------------------------------------------------------------
diff --git a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/utils/ParseResponse.java b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/utils/ParseResponse.java
new file mode 100644
index 0000000..6f8b5de
--- /dev/null
+++ b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/utils/ParseResponse.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.dimensiondata.cloudcontrol.utils;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.collect.FluentIterable;
+import com.google.inject.TypeLiteral;
+import org.jclouds.dimensiondata.cloudcontrol.domain.Property;
+import org.jclouds.dimensiondata.cloudcontrol.domain.Response;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.http.HttpResponseException;
+import org.jclouds.json.Json;
+import org.jclouds.logging.Logger;
+
+import javax.annotation.Resource;
+import java.io.InputStream;
+
+import static org.jclouds.http.HttpUtils.releasePayload;
+
+public class ParseResponse implements Function<HttpResponse, String> {
+
+ @Resource
+ protected Logger logger = Logger.NULL;
+ protected final Json json;
+ protected final String propertyName;
+
+ protected ParseResponse(Json json, String propertyName) {
+ this.json = json;
+ this.propertyName = propertyName;
+ }
+
+ public String apply(HttpResponse from) {
+ try {
+ InputStream gson = from.getPayload().openStream();
+
+ final Response response = json.fromJson(gson, TypeLiteral.get(Response.class).getType());
+ return tryFindInfoPropertyValue(response);
+ } catch (Exception e) {
+ StringBuilder message = new StringBuilder();
+ message.append("Error parsing input: ");
+ message.append(e.getMessage());
+ logger.error(e, message.toString());
+ throw new HttpResponseException(message.toString() + "\n" + from, null, from, e);
+ } finally {
+ releasePayload(from);
+ }
+ }
+
+ String tryFindInfoPropertyValue(Response response) {
+ if (!response.info().isEmpty()) {
+ Optional<String> optionalPropertyName = FluentIterable.from(response.info())
+ .firstMatch(new Predicate<Property>() {
+ @Override
+ public boolean apply(Property input) {
+ return input.name().equals(propertyName);
+ }
+ }).transform(new Function<Property, String>() {
+ @Override
+ public String apply(Property input) {
+ return input.value();
+ }
+ });
+ if (!optionalPropertyName.isPresent()) {
+ throw new IllegalStateException("Could not find expected property name: " + propertyName);
+ }
+ return optionalPropertyName.get();
+ }
+ return "";
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2495dd9a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/NetworkApiLiveTest.java
----------------------------------------------------------------------
diff --git a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/NetworkApiLiveTest.java b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/NetworkApiLiveTest.java
new file mode 100644
index 0000000..424eecc
--- /dev/null
+++ b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/NetworkApiLiveTest.java
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.dimensiondata.cloudcontrol.features;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import org.jclouds.dimensiondata.cloudcontrol.domain.FirewallRuleTarget;
+import org.jclouds.dimensiondata.cloudcontrol.domain.IpRange;
+import org.jclouds.dimensiondata.cloudcontrol.domain.Placement;
+import org.jclouds.dimensiondata.cloudcontrol.domain.State;
+import org.jclouds.dimensiondata.cloudcontrol.internal.BaseDimensionDataCloudControlApiLiveTest;
+import org.jclouds.rest.ResourceAlreadyExistsException;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import java.util.List;
+
+import static org.jclouds.dimensiondata.cloudcontrol.features.NetworkApiMockTest.DEFAULT_ACTION;
+import static org.jclouds.dimensiondata.cloudcontrol.features.NetworkApiMockTest.DEFAULT_IP_VERSION;
+import static org.jclouds.dimensiondata.cloudcontrol.utils.DimensionDataCloudControlResponseUtils.generateFirewallRuleName;
+import static org.jclouds.dimensiondata.cloudcontrol.utils.DimensionDataCloudControlResponseUtils.waitForNetworkDomainStatus;
+import static org.jclouds.dimensiondata.cloudcontrol.utils.DimensionDataCloudControlResponseUtils.waitForVlanStatus;
+import static org.testng.Assert.assertNotNull;
+
+@Test(groups = "live", testName = "NetworkApiLiveTest", singleThreaded = true)
+public class NetworkApiLiveTest extends BaseDimensionDataCloudControlApiLiveTest {
+
+ private static final String DATACENTER = "NW20-EPC-LAB04";
+
+ private static final String DEFAULT_PRIVATE_IPV4_BASE_ADDRESS = "10.0.0.0";
+ private static final Integer DEFAULT_PRIVATE_IPV4_PREFIX_SIZE = 24;
+ private static final String DEFAULT_PROTOCOL = "TCP";
+
+ private String networkDomainId;
+ private String vlanId;
+ private String portListId;
+ private List<String> firewallRuleIds;
+
+ @BeforeClass
+ public void init() {
+ firewallRuleIds = Lists.newArrayList();
+ }
+
+ @Test(dependsOnMethods = "testDeployVlan")
+ public void testCreatePortList() {
+ portListId = api()
+ .createPortList(networkDomainId, this.getClass().getCanonicalName(), this.getClass().getCanonicalName(),
+ ImmutableList.of(FirewallRuleTarget.Port.create(22, null)), Lists.<String>newArrayList());
+ assertNotNull(portListId);
+ }
+
+ @Test(dependsOnMethods = "testCreatePortList")
+ public void testCreateFirewallRuleWithPortList() {
+ String id = api().createFirewallRule(networkDomainId, generateFirewallRuleName("server-id"), DEFAULT_ACTION,
+ DEFAULT_IP_VERSION, DEFAULT_PROTOCOL, FirewallRuleTarget.builder().ip(IpRange.create("ANY", null)).build(),
+ FirewallRuleTarget.builder().ip(IpRange.create("ANY", null)).portListId(portListId).build(), Boolean.TRUE,
+ Placement.builder().position("LAST").build());
+ firewallRuleIds.add(id);
+ }
+
+ @Test(dependsOnMethods = "testDeployNetworkDomain")
+ public void testDeployVlan() {
+ vlanId = api().deployVlan(networkDomainId, NetworkApiLiveTest.class.getSimpleName(),
+ NetworkApiLiveTest.class.getSimpleName(), DEFAULT_PRIVATE_IPV4_BASE_ADDRESS,
+ DEFAULT_PRIVATE_IPV4_PREFIX_SIZE);
+ assertNotNull(vlanId);
+ waitForVlanStatus(api(), vlanId, State.NORMAL, 30 * 60 * 1000, "Error - unable to deploy vlan");
+ }
+
+ @Test
+ public void testDeployNetworkDomain() {
+ String networkDomainName = NetworkApiLiveTest.class.getSimpleName();
+ networkDomainId = api()
+ .deployNetworkDomain(DATACENTER, networkDomainName, NetworkApiLiveTest.class.getSimpleName(), "ESSENTIALS");
+ assertNotNull(networkDomainId);
+ waitForNetworkDomainStatus(api(), networkDomainId, State.NORMAL, 30 * 60 * 1000,
+ "Error - unable to deploy network domain");
+ }
+
+ @Test(expectedExceptions = ResourceAlreadyExistsException.class)
+ public void testDeploySameNetworkDomain() {
+ api().deployNetworkDomain(DATACENTER, NetworkApiLiveTest.class.getSimpleName(),
+ NetworkApiLiveTest.class.getSimpleName(), "ESSENTIALS");
+ }
+
+ @AfterClass
+ public void tearDown() {
+ if (!firewallRuleIds.isEmpty()) {
+ for (String firewallRuleId : firewallRuleIds) {
+ api().deleteFirewallRule(firewallRuleId);
+ }
+ }
+ if (portListId != null) {
+ api().deletePortList(portListId);
+ }
+ if (vlanId != null) {
+ api().deleteVlan(vlanId);
+ waitForVlanStatus(api(), vlanId, State.DELETED, 30 * 60 * 1000, "Error deleting vlan");
+ }
+ if (networkDomainId != null) {
+ api().deleteNetworkDomain(networkDomainId);
+ waitForNetworkDomainStatus(api(), networkDomainId, State.DELETED, 30 * 60 * 1000,
+ "Error deleting network domain");
+ }
+ }
+
+ private NetworkApi api() {
+ return api.getNetworkApi();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2495dd9a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/NetworkApiMockTest.java
----------------------------------------------------------------------
diff --git a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/NetworkApiMockTest.java b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/NetworkApiMockTest.java
new file mode 100644
index 0000000..6e4fc86
--- /dev/null
+++ b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/NetworkApiMockTest.java
@@ -0,0 +1,392 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.dimensiondata.cloudcontrol.features;
+
+import com.squareup.okhttp.mockwebserver.MockResponse;
+import org.jclouds.dimensiondata.cloudcontrol.domain.FirewallRule;
+import org.jclouds.dimensiondata.cloudcontrol.domain.FirewallRuleTarget;
+import org.jclouds.dimensiondata.cloudcontrol.domain.IpRange;
+import org.jclouds.dimensiondata.cloudcontrol.domain.NatRule;
+import org.jclouds.dimensiondata.cloudcontrol.domain.NetworkDomain;
+import org.jclouds.dimensiondata.cloudcontrol.domain.Placement;
+import org.jclouds.dimensiondata.cloudcontrol.domain.PublicIpBlock;
+import org.jclouds.dimensiondata.cloudcontrol.domain.Vlan;
+import org.jclouds.dimensiondata.cloudcontrol.internal.BaseAccountAwareCloudControlMockTest;
+import org.jclouds.dimensiondata.cloudcontrol.parse.PublicIpBlocksParseTest;
+import org.jclouds.dimensiondata.cloudcontrol.parse.VlansParseTest;
+import org.jclouds.http.Uris;
+import org.testng.annotations.Test;
+
+import javax.ws.rs.HttpMethod;
+
+import static ch.qos.logback.core.net.ssl.SSL.DEFAULT_PROTOCOL;
+import static com.google.common.collect.Iterables.size;
+import static javax.ws.rs.HttpMethod.GET;
+import static javax.ws.rs.HttpMethod.POST;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+/**
+ * Mock tests for the {@link org.jclouds.dimensiondata.cloudcontrol.features.NetworkApi} class.
+ */
+@Test(groups = "unit", testName = "NetworkApiMockTest", singleThreaded = true)
+public class NetworkApiMockTest extends BaseAccountAwareCloudControlMockTest {
+
+ public static final String DEFAULT_ACTION = "ACCEPT_DECISIVELY";
+ public static final String DEFAULT_IP_VERSION = "IPV4";
+
+ public void testListNetworkDomains() throws Exception {
+ server.enqueue(jsonResponse("/networkDomains.json"));
+ Iterable<NetworkDomain> networkDomains = api.getNetworkApi().listNetworkDomains().concat();
+ assertEquals(size(networkDomains), 1); // Force the PagedIterable to advance
+ assertEquals(server.getRequestCount(), 2);
+
+ assertSent(GET, "/caas/2.4/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/networkDomain");
+ }
+
+ public void testListNetworkDomainsWithPagination() throws Exception {
+ server.enqueue(jsonResponse("/networkDomains-page1.json"));
+ server.enqueue(jsonResponse("/networkDomains-page2.json"));
+ Iterable<NetworkDomain> networkDomains = api.getNetworkApi().listNetworkDomains().concat().toList();
+
+ consumeIterableAndAssertAdditionalPagesRequested(networkDomains, 20, 0);
+
+ assertSent(HttpMethod.GET, expectedListNetworkDomainsUriBuilder().toString());
+ assertSent(HttpMethod.GET, addPageNumberToUriBuilder(expectedListNetworkDomainsUriBuilder(), 2).toString());
+ }
+
+ public void testGetNetworkDomain() throws Exception {
+ server.enqueue(jsonResponse("/networkDomain.json"));
+ api.getNetworkApi().getNetworkDomain("networkDomainId");
+ assertSent(GET, "/caas/2.4/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/networkDomain/networkDomainId");
+ }
+
+ public void testGetNetworkDomain_404() throws Exception {
+ server.enqueue(response404());
+ api.getNetworkApi().listNetworkDomainsWithDatacenterIdAndName("testDatacenterId", "testName").concat();
+ assertSent(GET, "/caas/2.4/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/networkDomain"
+ + "?datacenterId=testDatacenterId&name=testName");
+ }
+
+ public void testListNetworkDomainsWithName() throws Exception {
+ server.enqueue(jsonResponse("/networkDomains.json"));
+ api.getNetworkApi().listNetworkDomainsWithDatacenterIdAndName("testDatacenterId", "testName").concat();
+ assertSent(GET, "/caas/2.4/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/networkDomain"
+ + "?datacenterId=testDatacenterId&name=testName");
+ }
+
+ public void testListNetworkDomainsWithNameWithPagination() throws Exception {
+ server.enqueue(jsonResponse("/networkDomains-page1.json"));
+ server.enqueue(jsonResponse("/networkDomains-page2.json"));
+ Iterable<NetworkDomain> networkDomains = api.getNetworkApi()
+ .listNetworkDomainsWithDatacenterIdAndName("testDatacenterId", "testName").concat();
+
+ consumeIterableAndAssertAdditionalPagesRequested(networkDomains, 20, 1);
+
+ assertSent(GET, "/caas/2.4/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/networkDomain"
+ + "?datacenterId=testDatacenterId&name=testName");
+ assertSent(GET, "/caas/2.4/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/networkDomain" + "?pageNumber=2");
+ }
+
+ public void testListNetworkDomainsWithName_404() throws Exception {
+ server.enqueue(response404());
+ api.getNetworkApi().listNetworkDomainsWithDatacenterIdAndName("testDatacenterId", "testName").concat();
+ assertSent(GET, "/caas/2.4/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/networkDomain"
+ + "?datacenterId=testDatacenterId&name=testName");
+ }
+
+ public void testListVlansWithNetworkDomainId() throws Exception {
+ server.enqueue(jsonResponse("/vlans.json"));
+ api.getNetworkApi().listVlans("testNetworkDomainId");
+ assertSent(GET,
+ "/caas/2.4/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/vlan?networkDomainId=testNetworkDomainId");
+ }
+
+ public void testListVlansWithNetworkDomainId_404() throws Exception {
+ server.enqueue(response404());
+ api.getNetworkApi().listVlans("testNetworkDomainId");
+ assertSent(GET,
+ "/caas/2.4/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/vlan?networkDomainId=testNetworkDomainId");
+ }
+
+ public void testListVlanssWithPagination() throws Exception {
+ server.enqueue(jsonResponse("/vlans-page1.json"));
+ server.enqueue(jsonResponse("/vlans-page2.json"));
+ Iterable<Vlan> vlans = api.getNetworkApi().listVlans("12345").concat().toList();
+
+ consumeIterableAndAssertAdditionalPagesRequested(vlans, 20, 0);
+
+ assertSent(HttpMethod.GET, expectedListVlansRulesUriBuilder().toString());
+ assertSent(HttpMethod.GET, addPageNumberToUriBuilder(expectedListVlansRulesUriBuilder(), 2).toString());
+ }
+
+ public void testListVlans() throws Exception {
+ server.enqueue(new MockResponse().setBody(payloadFromResource("/vlans.json")));
+ assertEquals(api.getNetworkApi().listVlans("12345").concat().toList(), new VlansParseTest().expected().toList());
+ assertSent(GET, "/caas/2.4/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/vlan?networkDomainId=12345");
+ }
+
+ public void testListVlans_404() throws Exception {
+ server.enqueue(response404());
+ assertTrue(api.getNetworkApi().listVlans("12345").concat().isEmpty());
+ assertSent(GET, "/caas/2.4/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/vlan?networkDomainId=12345");
+ }
+
+ public void testGetVlan() throws Exception {
+ server.enqueue(new MockResponse().setBody(payloadFromResource("/vlan.json")));
+ api.getNetworkApi().getVlan("12345");
+ assertSent(GET, "/caas/2.4/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/vlan/12345");
+ }
+
+ public void testGetVlan_404() throws Exception {
+ server.enqueue(response404());
+ api.getNetworkApi().getVlan("12345");
+ assertSent(GET, "/caas/2.4/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/vlan/12345");
+ }
+
+ public void testListPublicIPv4AddressBlock() throws Exception {
+ server.enqueue(new MockResponse().setBody(payloadFromResource("/publicIpBlocks.json")));
+ assertEquals(api.getNetworkApi().listPublicIPv4AddressBlocks("12345").concat().toList(),
+ new PublicIpBlocksParseTest().expected().toList());
+ assertSent(GET, "/caas/2.4/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/publicIpBlock?networkDomainId=12345");
+ }
+
+ public void testListPublicIPv4AddressBlock_404() throws Exception {
+ server.enqueue(response404());
+ assertTrue(api.getNetworkApi().listPublicIPv4AddressBlocks("12345").concat().isEmpty());
+ assertSent(GET, "/caas/2.4/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/publicIpBlock?networkDomainId=12345");
+ }
+
+ public void testListPublicIPv4AddressBlockWithPagination() throws Exception {
+ server.enqueue(jsonResponse("/publicIpBlocks-page1.json"));
+ server.enqueue(jsonResponse("/publicIpBlocks-page2.json"));
+ Iterable<PublicIpBlock> ipBlocks = api.getNetworkApi().listPublicIPv4AddressBlocks("12345").concat().toList();
+
+ consumeIterableAndAssertAdditionalPagesRequested(ipBlocks, 20, 0);
+
+ assertSent(HttpMethod.GET, expectedListPublicIpBlockUriBuilder().toString());
+ assertSent(HttpMethod.GET, addPageNumberToUriBuilder(expectedListPublicIpBlockUriBuilder(), 2).toString());
+ }
+
+ public void testCreateFirewallRule() throws Exception {
+ server.enqueue(new MockResponse().setResponseCode(200).setBody(
+ "{\n" + "\"operation\": \"CREATE_FIREWALL_RULE\",\n" + "\"responseCode\": \"OK\",\n"
+ + "\"message\": \"Request create Firewall Rule 'My.Rule' successful\", \"info\": [\n" + "{\n"
+ + "\"name\": \"firewallRuleId\",\n" + "\"value\": \"dc545f3e-823c-4500-93c9-8d7f576311de\"\n"
+ + "} ],\n" + "\"warning\": [],\n" + "\"error\": [],\n"
+ + "\"requestId\": \"NA9/2015-03-05T13:46:34.848-05:00/f8fdef24-8a12-45ea-a831-\n"
+ + "d5463212ef6a\" }"));
+ api.getNetworkApi().createFirewallRule("123456", "test", DEFAULT_ACTION, DEFAULT_IP_VERSION, DEFAULT_PROTOCOL,
+ FirewallRuleTarget.builder().ip(IpRange.create("ANY", null)).build(),
+ FirewallRuleTarget.builder().ip(IpRange.create("ANY", null)).build(), true,
+ Placement.builder().position("LAST").build());
+ assertSent(POST, "/caas/2.4/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/createFirewallRule");
+ }
+
+ public void testDeleteNetworkDomain() throws Exception {
+ server.enqueue(new MockResponse().setResponseCode(200).setBody(
+ "{\n" + "\"operation\": \"DELETE_NETWORK_DOMAIN\",\n" + "\"responseCode\": \"IN_PROGRESS\",\n"
+ + "\"message\": \"Request to Delete Network Domain (Id:12623a68-ebdb-11e3-9153-001b21cfdbe0)"
+ + " has been accepted and is being processed\", \"info\": [],\n" + "\"warning\": [],\n"
+ + "\"error\": [],\n" + "\"requestId\": \"NA9/2015-03-05T13:46:34.848-05:00/f8fdef24-8a12-45ea-a831-\n"
+ + "d5463212ef6a\" }"));
+ api.getNetworkApi().deleteNetworkDomain("networkDomainId");
+ assertSent(POST, "/caas/2.4/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/deleteNetworkDomain");
+ }
+
+ public void testDeleteNetworkDomain_404() throws Exception {
+ server.enqueue(response404());
+ api.getNetworkApi().deleteNetworkDomain("networkDomainId");
+ assertSent(POST, "/caas/2.4/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/deleteNetworkDomain");
+ }
+
+ public void testRemovePublicIpBlock() throws Exception {
+ server.enqueue(new MockResponse().setResponseCode(200).setBody(
+ "{\n" + "\"operation\": \"REMOVE_PUBLIC_IP_BLOCK\",\n" + "\"responseCode\": \"OK\",\n"
+ + "\"message\": \"Public Ip Block (Id:12623a68-ebdb-11e3-9153-001b21cfdbe0) has been removed successfully\","
+ + " \"info\": [],\n" + "\"warning\": [],\n" + "\"error\": [],\n"
+ + "\"requestId\": \"NA9/2015-03-05T13:46:34.848-05:00/f8fdef24-8a12-45ea-a831-\n"
+ + "d5463212ef6a\" }"));
+ api.getNetworkApi().removePublicIpBlock("publicIpBlockId");
+ assertSent(POST, "/caas/2.4/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/removePublicIpBlock");
+ }
+
+ public void testRemovePublicIpBlock_404() throws Exception {
+ server.enqueue(response404());
+ api.getNetworkApi().removePublicIpBlock("publicIpBlockId");
+ assertSent(POST, "/caas/2.4/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/removePublicIpBlock");
+ }
+
+ public void testGetPublicIpBlock() throws Exception {
+ server.enqueue(jsonResponse("/publicIpBlock.json"));
+ api.getNetworkApi().getPublicIPv4AddressBlock("publicIpBlockId");
+ assertSent(GET, "/caas/2.4/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/publicIpBlock/publicIpBlockId");
+ }
+
+ public void testGetPublicIpBlock_404() throws Exception {
+ server.enqueue(response404());
+ api.getNetworkApi().getPublicIPv4AddressBlock("publicIpBlockId");
+ assertSent(GET, "/caas/2.4/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/publicIpBlock/publicIpBlockId");
+ }
+
+ public void testCreateNatRule() throws Exception {
+ server.enqueue(new MockResponse().setResponseCode(200).setBody(
+ "{\n" + "\"operation\": \"CREATE_NAT_RULE\",\n" + "\"responseCode\": \"OK\",\n"
+ + "\"message\": \"Create Nat Rule Complete\", \"info\": [\n" + "{\n" + "\"name\": \"natRuleId\",\n"
+ + "\"value\": \"dc545f3e-823c-4500-93c9-8d7f576311de\"\n" + "} ],\n" + "\"warning\": [],\n"
+ + "\"error\": [],\n" + "\"requestId\": \"NA9/2015-03-05T13:46:34.848-05:00/f8fdef24-8a12-45ea-a831-\n"
+ + "d5463212ef6a\" }"));
+ api.getNetworkApi().createNatRule("networkDomainId", "10.0.0.5", "155.143.0.54");
+ assertSent(POST, "/caas/2.4/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/createNatRule");
+ }
+
+ public void testListNatRules() throws Exception {
+ server.enqueue(new MockResponse().setBody(payloadFromResource("/natRules.json")));
+ api.getNetworkApi().listNatRules("12345").concat().toList();
+ assertSent(GET, "/caas/2.4/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/natRule?networkDomainId=12345");
+ }
+
+ public void testListNatRulesWithPagination() throws Exception {
+ server.enqueue(jsonResponse("/natRules-page1.json"));
+ server.enqueue(jsonResponse("/natRules-page2.json"));
+ Iterable<NatRule> natRules = api.getNetworkApi().listNatRules("12345").concat().toList();
+
+ consumeIterableAndAssertAdditionalPagesRequested(natRules, 20, 0);
+
+ assertSent(HttpMethod.GET, expectedListNatRulesUriBuilder().toString());
+ assertSent(HttpMethod.GET, addPageNumberToUriBuilder(expectedListNatRulesUriBuilder(), 2).toString());
+ }
+
+ public void testListNatRules_404() throws Exception {
+ server.enqueue(response404());
+ assertTrue(api.getNetworkApi().listNatRules("12345").concat().isEmpty());
+ assertSent(GET, "/caas/2.4/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/natRule?networkDomainId=12345");
+ }
+
+ public void testGetNatRule() throws Exception {
+ server.enqueue(jsonResponse("/natRule.json"));
+ api.getNetworkApi().getNatRule("natRuleId");
+ assertSent(GET, "/caas/2.4/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/natRule/natRuleId");
+ }
+
+ public void testGetNatRule_404() throws Exception {
+ server.enqueue(response404());
+ api.getNetworkApi().getNatRule("natRuleId");
+ assertSent(GET, "/caas/2.4/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/natRule/natRuleId");
+ }
+
+ public void testListFirewallRules() throws Exception {
+ server.enqueue(new MockResponse().setBody(payloadFromResource("/firewallRules.json")));
+ api.getNetworkApi().listFirewallRules("12345").concat().toList();
+ assertSent(GET, "/caas/2.4/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/firewallRule?networkDomainId=12345");
+ }
+
+ public void testListFirewallRules_404() throws Exception {
+ server.enqueue(response404());
+ api.getNetworkApi().listFirewallRules("12345").concat().toList();
+ assertSent(GET, "/caas/2.4/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/firewallRule?networkDomainId=12345");
+ }
+
+ public void testListFirewallRulesWithPagination() throws Exception {
+ server.enqueue(jsonResponse("/firewallRules-page1.json"));
+ server.enqueue(jsonResponse("/firewallRules-page2.json"));
+ Iterable<FirewallRule> firewallRules = api.getNetworkApi().listFirewallRules("12345").concat().toList();
+
+ consumeIterableAndAssertAdditionalPagesRequested(firewallRules, 15, 0);
+
+ assertSent(HttpMethod.GET, expectedListFirewallRulesUriBuilder().toString());
+ assertSent(HttpMethod.GET, addPageNumberToUriBuilder(expectedListFirewallRulesUriBuilder(), 2).toString());
+ }
+
+ public void testDeleteFirewallRule() throws Exception {
+ server.enqueue(new MockResponse().setResponseCode(200).setBody(
+ "{\n" + "\"operation\": \"DELETE_FIREWALL_RULE\",\n" + "\"responseCode\": \"IN_PROGRESS\",\n"
+ + "\"message\": \"Delete Firewall Rule (Id:12623a68-ebdb-11e3-9153-001b21cfdbe0) complete\", "
+ + "\"info\": [],\n" + "\"warning\": [],\n" + "\"error\": [],\n"
+ + "\"requestId\": \"NA9/2015-03-05T13:46:34.848-05:00/f8fdef24-8a12-45ea-a831-\n"
+ + "d5463212ef6a\" }"));
+ api.getNetworkApi().deleteFirewallRule("firewallRuleId");
+ assertSent(POST, "/caas/2.4/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/deleteFirewallRule");
+ }
+
+ public void testDeleteFirewallRule_404() throws Exception {
+ server.enqueue(response404());
+ api.getNetworkApi().deleteFirewallRule("firewallRuleId");
+ assertSent(POST, "/caas/2.4/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/deleteFirewallRule");
+ }
+
+ public void testGetPortList() throws Exception {
+ server.enqueue(new MockResponse().setBody(payloadFromResource("/portList.json")));
+ api.getNetworkApi().getPortList("portListId");
+ assertSent(GET, "/caas/2.4/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/portList/portListId");
+ }
+
+ public void testGetPortList_404() throws Exception {
+ server.enqueue(response404());
+ api.getNetworkApi().getPortList("portListId");
+ assertSent(GET, "/caas/2.4/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/portList/portListId");
+ }
+
+ public void testDeletePortList() throws Exception {
+ server.enqueue(new MockResponse().setResponseCode(200).setBody(
+ "{\n" + "\"operation\": \"DELETE_PORT_LIST\",\n" + "\"responseCode\": \"IN_PROGRESS\",\n"
+ + "\"message\": \"Port List with id portListId has been deleted.\", " + "\"info\": [],\n"
+ + "\"warning\": [],\n" + "\"error\": [],\n"
+ + "\"requestId\": \"NA9/2015-03-05T13:46:34.848-05:00/f8fdef24-8a12-45ea-a831-\n"
+ + "d5463212ef6a\" }"));
+ api.getNetworkApi().deletePortList("portListId");
+ assertSent(POST, "/caas/2.4/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/deletePortList");
+ }
+
+ public void testDeletePortList_404() throws Exception {
+ server.enqueue(response404());
+ api.getNetworkApi().deletePortList("portListId");
+ assertSent(POST, "/caas/2.4/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/deletePortList");
+ }
+
+ private Uris.UriBuilder expectedListFirewallRulesUriBuilder() {
+ Uris.UriBuilder uriBuilder = Uris
+ .uriBuilder("/caas/" + VERSION + "/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/firewallRule");
+ uriBuilder.addQuery("networkDomainId", "12345");
+ return uriBuilder;
+ }
+
+ private Uris.UriBuilder expectedListNatRulesUriBuilder() {
+ Uris.UriBuilder uriBuilder = Uris
+ .uriBuilder("/caas/" + VERSION + "/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/natRule");
+ uriBuilder.addQuery("networkDomainId", "12345");
+ return uriBuilder;
+ }
+
+ private Uris.UriBuilder expectedListNetworkDomainsUriBuilder() {
+ return Uris.uriBuilder("/caas/" + VERSION + "/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/networkDomain");
+ }
+
+ private Uris.UriBuilder expectedListVlansRulesUriBuilder() {
+ Uris.UriBuilder uriBuilder = Uris
+ .uriBuilder("/caas/" + VERSION + "/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/vlan");
+ uriBuilder.addQuery("networkDomainId", "12345");
+ return uriBuilder;
+ }
+
+ private Uris.UriBuilder expectedListPublicIpBlockUriBuilder() {
+ Uris.UriBuilder uriBuilder = Uris
+ .uriBuilder("/caas/" + VERSION + "/6ac1e746-b1ea-4da5-a24e-caf1a978789d/network/publicIpBlock");
+ uriBuilder.addQuery("networkDomainId", "12345");
+ return uriBuilder;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2495dd9a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/internal/BaseDimensionDataCloudControlMockTest.java
----------------------------------------------------------------------
diff --git a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/internal/BaseDimensionDataCloudControlMockTest.java b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/internal/BaseDimensionDataCloudControlMockTest.java
index 92079a0..7856524 100644
--- a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/internal/BaseDimensionDataCloudControlMockTest.java
+++ b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/internal/BaseDimensionDataCloudControlMockTest.java
@@ -47,6 +47,7 @@ import java.util.Set;
import static com.google.common.collect.Iterables.size;
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.jclouds.util.Strings2.toStringAndClose;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.fail;
@@ -208,4 +209,12 @@ public class BaseDimensionDataCloudControlMockTest implements IHookable {
uriBuilder.addQuery("pageNumber", Integer.toString(pageNumber));
return uriBuilder;
}
+
+ public byte[] payloadFromResource(String resource) {
+ try {
+ return toStringAndClose(getClass().getResourceAsStream(resource)).getBytes(Charsets.UTF_8);
+ } catch (IOException e) {
+ throw Throwables.propagate(e);
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2495dd9a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/parse/FirewallRulesParseTest.java
----------------------------------------------------------------------
diff --git a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/parse/FirewallRulesParseTest.java b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/parse/FirewallRulesParseTest.java
new file mode 100644
index 0000000..2fe920c
--- /dev/null
+++ b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/parse/FirewallRulesParseTest.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.dimensiondata.cloudcontrol.parse;
+
+import com.google.common.collect.ImmutableList;
+import org.jclouds.dimensiondata.cloudcontrol.domain.FirewallRule;
+import org.jclouds.dimensiondata.cloudcontrol.domain.FirewallRuleTarget;
+import org.jclouds.dimensiondata.cloudcontrol.domain.FirewallRules;
+import org.jclouds.dimensiondata.cloudcontrol.domain.IpRange;
+import org.jclouds.dimensiondata.cloudcontrol.internal.BaseDimensionDataCloudControlParseTest;
+import org.testng.annotations.Test;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+import java.util.List;
+
+@Test(groups = "unit")
+public class FirewallRulesParseTest extends BaseDimensionDataCloudControlParseTest<FirewallRules> {
+
+ @Override
+ public String resource() {
+ return "/firewallRules.json";
+ }
+
+ @Override
+ @Consumes(MediaType.APPLICATION_JSON)
+ public FirewallRules expected() {
+ List<FirewallRule> firewallRules = ImmutableList
+ .of(FirewallRule.builder().id("1aa3d0ce-d95d-4296-8338-9717e0d37ff9")
+ .name("CCDEFAULT.BlockOutboundMailIPv6Secure").state("NORMAL").action("DROP").ipVersion("IPV6")
+ .protocol("TCP").source(FirewallRuleTarget.builder().ip(IpRange.create("ANY", null)).build())
+ .destination(FirewallRuleTarget.builder().ip(IpRange.create("ANY", null))
+ .port(FirewallRuleTarget.Port.create(587, null)).build()).ruleType("DEFAULT_RULE")
+ .networkDomainId("484174a2-ae74-4658-9e56-50fc90e086cf").enabled(Boolean.TRUE).datacenterId("NA9")
+ .build());
+ return new FirewallRules(firewallRules, 1, 2, 2, 250);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2495dd9a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/parse/NatRulesParseTest.java
----------------------------------------------------------------------
diff --git a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/parse/NatRulesParseTest.java b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/parse/NatRulesParseTest.java
new file mode 100644
index 0000000..7858a0e
--- /dev/null
+++ b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/parse/NatRulesParseTest.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.dimensiondata.cloudcontrol.parse;
+
+import com.google.common.collect.ImmutableList;
+import org.jclouds.dimensiondata.cloudcontrol.domain.NatRule;
+import org.jclouds.dimensiondata.cloudcontrol.domain.NatRules;
+import org.jclouds.dimensiondata.cloudcontrol.internal.BaseDimensionDataCloudControlParseTest;
+import org.testng.annotations.Test;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+import java.util.List;
+
+@Test(groups = "unit")
+public class NatRulesParseTest extends BaseDimensionDataCloudControlParseTest<NatRules> {
+
+ @Override
+ public String resource() {
+ return "/natRules.json";
+ }
+
+ @Override
+ @Consumes(MediaType.APPLICATION_JSON)
+ public NatRules expected() {
+ List<NatRule> natRules = ImmutableList.of(NatRule.builder().id("2187a636-7ebb-49a1-a2ff-5d617f496dce")
+ .createTime(parseDate("2015-03-06T13:43:45.000Z")).state("NORMAL").externalIp("165.180.12.18")
+ .internalIp("10.0.0.15").networkDomainId("484174a2-ae74-4658-9e56-50fc90e086cf").datacenterId("NA9")
+ .build(), NatRule.builder().id("2169a38e-5692-497e-a22a-701a838a6539")
+ .createTime(parseDate("2015-03-06T13:45:10.000Z")).state("NORMAL").externalIp("165.180.12.19")
+ .internalIp("10.0.0.16").networkDomainId("484174a2-ae74-4658-9e56-50fc90e086cf").datacenterId("NA9")
+ .build());
+ return new NatRules(natRules, 1, 2, 2, 250);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2495dd9a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/parse/NetworkDomainsParseTest.java
----------------------------------------------------------------------
diff --git a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/parse/NetworkDomainsParseTest.java b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/parse/NetworkDomainsParseTest.java
new file mode 100644
index 0000000..c1eec7f
--- /dev/null
+++ b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/parse/NetworkDomainsParseTest.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.dimensiondata.cloudcontrol.parse;
+
+import com.google.common.collect.ImmutableList;
+import org.jclouds.dimensiondata.cloudcontrol.domain.NetworkDomain;
+import org.jclouds.dimensiondata.cloudcontrol.domain.NetworkDomains;
+import org.jclouds.dimensiondata.cloudcontrol.domain.State;
+import org.jclouds.dimensiondata.cloudcontrol.internal.BaseDimensionDataCloudControlParseTest;
+import org.testng.annotations.Test;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+import java.util.List;
+
+import static org.jclouds.dimensiondata.cloudcontrol.domain.NetworkDomain.Type.ESSENTIALS;
+
+@Test(groups = "unit")
+public class NetworkDomainsParseTest extends BaseDimensionDataCloudControlParseTest<NetworkDomains> {
+
+ @Override
+ public String resource() {
+ return "/networkDomains.json";
+ }
+
+ @Override
+ @Consumes(MediaType.APPLICATION_JSON)
+ public NetworkDomains expected() {
+ List<NetworkDomain> networkDomains = ImmutableList
+ .of(NetworkDomain.builder().id("8e082ed6-c198-4eff-97cb-aeac6f9685d8").datacenterId("NA9").name("test")
+ .description("").state(State.NORMAL).type(ESSENTIALS).snatIpv4Address("168.128.3.44")
+ .createTime(parseDate("2016-03-08T14:39:47.000Z")).build());
+ return new NetworkDomains(networkDomains, 1, 5, 5, 250);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2495dd9a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/parse/PublicIpBlocksParseTest.java
----------------------------------------------------------------------
diff --git a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/parse/PublicIpBlocksParseTest.java b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/parse/PublicIpBlocksParseTest.java
new file mode 100644
index 0000000..97c9512
--- /dev/null
+++ b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/parse/PublicIpBlocksParseTest.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.dimensiondata.cloudcontrol.parse;
+
+import com.google.common.collect.ImmutableList;
+import org.jclouds.dimensiondata.cloudcontrol.domain.PublicIpBlock;
+import org.jclouds.dimensiondata.cloudcontrol.domain.PublicIpBlocks;
+import org.jclouds.dimensiondata.cloudcontrol.internal.BaseDimensionDataCloudControlParseTest;
+import org.testng.annotations.Test;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+import java.util.List;
+
+@Test(groups = "unit")
+public class PublicIpBlocksParseTest extends BaseDimensionDataCloudControlParseTest<PublicIpBlocks> {
+
+ @Override
+ public String resource() {
+ return "/publicIpBlocks.json";
+ }
+
+ @Override
+ @Consumes(MediaType.APPLICATION_JSON)
+ public PublicIpBlocks expected() {
+ List<PublicIpBlock> publicIpBlocks = ImmutableList
+ .of(PublicIpBlock.builder().networkDomainId("690de302-bb80-49c6-b401-8c02bbefb945")
+ .id("9993e5fc-bdce-11e4-8c14-b8ca3a5d9ef8").createTime(parseDate("2016-03-14T11:49:33.000Z"))
+ .state("NORMAL").datacenterId("NA9").size(2).baseIp("168.128.6.216").build());
+ return new PublicIpBlocks(publicIpBlocks, 1, 5, 5, 250);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2495dd9a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/parse/VlansParseTest.java
----------------------------------------------------------------------
diff --git a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/parse/VlansParseTest.java b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/parse/VlansParseTest.java
new file mode 100644
index 0000000..cb74939
--- /dev/null
+++ b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/parse/VlansParseTest.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.dimensiondata.cloudcontrol.parse;
+
+import com.google.common.collect.ImmutableList;
+import org.jclouds.dimensiondata.cloudcontrol.domain.IpRange;
+import org.jclouds.dimensiondata.cloudcontrol.domain.NetworkDomain;
+import org.jclouds.dimensiondata.cloudcontrol.domain.State;
+import org.jclouds.dimensiondata.cloudcontrol.domain.Vlan;
+import org.jclouds.dimensiondata.cloudcontrol.domain.Vlans;
+import org.jclouds.dimensiondata.cloudcontrol.internal.BaseDimensionDataCloudControlParseTest;
+import org.testng.annotations.Test;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+import java.util.List;
+
+@Test(groups = "unit")
+public class VlansParseTest extends BaseDimensionDataCloudControlParseTest<Vlans> {
+
+ @Override
+ public String resource() {
+ return "/vlans.json";
+ }
+
+ @Override
+ @Consumes(MediaType.APPLICATION_JSON)
+ public Vlans expected() {
+ List<Vlan> vlans = ImmutableList.of(Vlan.builder()
+ .networkDomain(NetworkDomain.builder().id("690de302-bb80-49c6-b401-8c02bbefb945").name("test").build())
+ .id("6b25b02e-d3a2-4e69-8ca7-9bab605deebd").name("vlan1").description("")
+ .privateIpv4Range(IpRange.create("10.0.0.0", 24))
+ .ipv6Range(IpRange.create("2607:f480:111:1575:0:0:0:0", 64)).ipv4GatewayAddress("10.0.0.1")
+ .ipv6GatewayAddress("2607:f480:111:1575:0:0:0:1").createTime(parseDate("2016-03-11T10:41:19.000Z"))
+ .state(State.NORMAL).datacenterId("NA9").build());
+ return new Vlans(vlans, 1, 5, 5, 250);
+ }
+}