You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by ab...@apache.org on 2014/10/22 01:32:45 UTC

[2/7] JCLOUDS-756. Add support for tags to CloudStack.

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/TagApiExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/TagApiExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/TagApiExpectTest.java
new file mode 100644
index 0000000..a198579
--- /dev/null
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/TagApiExpectTest.java
@@ -0,0 +1,153 @@
+/*
+ * 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.cloudstack.features;
+
+import static org.jclouds.util.Strings2.urlEncode;
+import static org.testng.Assert.assertEquals;
+
+import java.net.URI;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import org.jclouds.cloudstack.CloudStackContext;
+import org.jclouds.cloudstack.domain.AsyncCreateResponse;
+import org.jclouds.cloudstack.domain.Tag;
+import org.jclouds.cloudstack.internal.BaseCloudStackExpectTest;
+import org.jclouds.cloudstack.options.CreateTagsOptions;
+import org.jclouds.cloudstack.options.DeleteTagsOptions;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.testng.annotations.Test;
+
+/**
+ * Test the CloudStack TagApi
+ */
+@Test(groups = "unit", testName = "TagApiExpectTest")
+public class TagApiExpectTest extends BaseCloudStackExpectTest<TagApi> {
+
+
+   public void testListTagsWhenResponseIs2xx() {
+      TagApi client = requestSendsResponse(
+            HttpRequest.builder().method("GET")
+                  .endpoint("http://localhost:8080/client/api")
+                  .addQueryParam("response", "json")
+                  .addQueryParam("command", "listTags")
+                  .addQueryParam("listAll", "true")
+                  .addQueryParam("apiKey", "identity")
+                  .addQueryParam("signature", "amvtC2a0VHzzDF5SUAIOZpXHd0A%3D")
+                  .addHeader("Accept", "application/json")
+                  .build(),
+            HttpResponse.builder()
+                  .statusCode(200)
+                  .payload(payloadFromResource("/listtagsresponse.json"))
+                  .build()
+      );
+
+      assertEquals(client.listTags(),
+            ImmutableSet.<Tag>of(
+                  Tag.builder()
+                        .account("admin")
+                        .domain("ROOT")
+                        .domainId("79dc06c4-4432-11e4-b70d-000c29e19aa0")
+                        .key("test-tag")
+                        .resourceId("54fe1d53-5d73-4184-8b62-948b9d8e08fb")
+                        .resourceType(Tag.ResourceType.TEMPLATE)
+                        .value("true").build()
+            )
+      );
+   }
+
+   public void testListTagsWhenResponseIs404() {
+      TagApi client = requestSendsResponse(
+         HttpRequest.builder()
+            .method("GET")
+            .endpoint(
+                  URI.create("http://localhost:8080/client/api?response=json&" +
+                        "command=listTags&listAll=true&apiKey=identity&signature=amvtC2a0VHzzDF5SUAIOZpXHd0A%3D")
+            )
+            .addHeader("Accept", "application/json")
+            .build(),
+         HttpResponse.builder()
+            .statusCode(404)
+            .build());
+
+      assertEquals(client.listTags(), ImmutableSet.of());
+   }
+
+   public void testCreateTagsWhenResponseIs2xx() {
+      TagApi client = requestSendsResponse(
+            HttpRequest.builder().method("GET")
+                  .endpoint("http://localhost:8080/client/api")
+                  .addQueryParam("response", "json")
+                  .addQueryParam("command", "createTags")
+                  .addQueryParam("resourcetype", "Template")
+                  .addQueryParam("resourceids", "52d89d5d-6070-4fd4-8131-c6c9ca4b062e")
+                  .addQueryParam(urlEncode("tags[0].key"), "some-tag")
+                  .addQueryParam(urlEncode("tags[0].value"), "some-value")
+                  .addQueryParam("apiKey", "identity")
+                  .addQueryParam("signature", "HDGTKGG9kONEwh5xlLe9R72z%2B9Q%3D")
+                  .addHeader("Accept", "application/json")
+                  .build(),
+            HttpResponse.builder()
+                  .statusCode(200)
+                  .payload(payloadFromResource("/createtagsresponse.json"))
+                  .build()
+      );
+
+      AsyncCreateResponse async = client.createTags(CreateTagsOptions.Builder.resourceType("Template")
+            .resourceIds("52d89d5d-6070-4fd4-8131-c6c9ca4b062e")
+            .tags(ImmutableMap.of("some-tag", "some-value")));
+
+      assertEquals(
+            async,
+            AsyncCreateResponse.builder().jobId("32cfab73-f221-4b2b-a728-a73e924ac95d").build());
+   }
+
+   public void testDeleteTagsWhenResponseIs2xx() {
+      TagApi client = requestSendsResponse(
+            HttpRequest.builder().method("GET")
+                  .endpoint("http://localhost:8080/client/api")
+                  .addQueryParam("response", "json")
+                  .addQueryParam("command", "deleteTags")
+                  .addQueryParam("resourcetype", "Template")
+                  .addQueryParam("resourceids", "52d89d5d-6070-4fd4-8131-c6c9ca4b062e")
+                  .addQueryParam(urlEncode("tags[0].key"), "some-tag")
+                  .addQueryParam(urlEncode("tags[0].value"), "some-value")
+                  .addQueryParam("apiKey", "identity")
+                  .addQueryParam("signature", "inAqWH/GkkGipkZFG5Wfmxa8vOE%3D")
+                  .addHeader("Accept", "application/json")
+                  .build(),
+            HttpResponse.builder()
+                  .statusCode(200)
+                  .payload(payloadFromResource("/deletetagsresponse.json"))
+                  .build()
+      );
+
+      AsyncCreateResponse async = client.deleteTags(DeleteTagsOptions.Builder.resourceType("Template")
+            .resourceIds("52d89d5d-6070-4fd4-8131-c6c9ca4b062e")
+            .tags(ImmutableMap.of("some-tag", "some-value")));
+
+      assertEquals(
+            async,
+            AsyncCreateResponse.builder().jobId("32cfab73-f221-4b2b-a728-a73e924ac95d").build());
+   }
+
+   @Override
+   protected TagApi clientFrom(CloudStackContext context) {
+      return context.getApi().getTagApi();
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/TagApiLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/TagApiLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/TagApiLiveTest.java
new file mode 100644
index 0000000..4f58a1e
--- /dev/null
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/TagApiLiveTest.java
@@ -0,0 +1,147 @@
+/*
+ * 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.cloudstack.features;
+
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertFalse;
+import static org.testng.AssertJUnit.assertNotNull;
+import static org.testng.AssertJUnit.assertTrue;
+
+import javax.annotation.Resource;
+import java.util.Set;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+import org.jclouds.cloudstack.domain.AsyncCreateResponse;
+import org.jclouds.cloudstack.domain.DiskOffering;
+import org.jclouds.cloudstack.domain.Tag;
+import org.jclouds.cloudstack.domain.Volume;
+import org.jclouds.cloudstack.domain.Zone;
+import org.jclouds.cloudstack.internal.BaseCloudStackApiLiveTest;
+import org.jclouds.cloudstack.options.CreateTagsOptions;
+import org.jclouds.cloudstack.options.DeleteTagsOptions;
+import org.jclouds.cloudstack.options.ListTagsOptions;
+import org.jclouds.cloudstack.options.ListVolumesOptions;
+import org.jclouds.logging.Logger;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ * Tests behavior of {@code TagApi}
+ */
+@Test(groups = "live", singleThreaded = true, testName = "TagApiLiveTest")
+public class TagApiLiveTest extends BaseCloudStackApiLiveTest {
+
+   @Resource Logger logger = Logger.NULL;
+
+   protected String prefix = System.getProperty("user.name") + "-" + getClass().getSimpleName();
+   protected String volumeToDelete;
+   private String zoneId;
+
+   @BeforeMethod(groups = "live")
+   public void setZoneId() {
+      Set<Zone> zones = client.getZoneApi().listZones();
+      assertNotNull(zones);
+      assertFalse(zones.isEmpty());
+      zoneId = Iterables.get(zones, 0).getId();
+   }
+
+   public void testCreateTags() {
+      createVolumeToTag();
+
+      AsyncCreateResponse job = client.getTagApi().createTags(CreateTagsOptions.Builder.resourceType("Volume")
+            .resourceIds(volumeToDelete)
+            .tags(ImmutableMap.of(prefix + "-first-tag", "first-tag-value",
+                  prefix + "-second-tag", "second-tag-value")));
+      assertTrue(jobComplete.apply(job.getJobId()));
+   }
+
+   @Test(dependsOnMethods = "testCreateTags")
+   public void testListTags() {
+      Set<Tag> tags = client.getTagApi().listTags();
+      assertNotNull(tags);
+      assertFalse(tags.isEmpty());
+
+      for (Tag tag : tags) {
+         checkTag(tag);
+      }
+   }
+
+   @Test(dependsOnMethods = "testListTags")
+   public void testListSingleTag() {
+      Set<Tag> tags = client.getTagApi().listTags(ListTagsOptions.Builder.key(prefix + "-second-tag"));
+      assertNotNull(tags);
+      assertFalse(tags.isEmpty());
+      assertEquals(1, tags.size());
+      for (Tag tag : tags) {
+         assertEquals(volumeToDelete, tag.getResourceId());
+         checkTag(tag);
+      }
+   }
+
+   @Test(dependsOnMethods = "testListSingleTag")
+   public void testListResourceByTag() {
+      Set<Volume> volumes = client.getVolumeApi().listVolumes(ListVolumesOptions.Builder.tags(ImmutableMap.of(prefix + "-second-tag", "second-tag-value")));
+      assertNotNull(volumes);
+      assertFalse(volumes.isEmpty());
+      assertEquals(1, volumes.size());
+   }
+
+   @Test(dependsOnMethods = "testListResourceByTag")
+   public void testDeleteTags() {
+      AsyncCreateResponse job = client.getTagApi().deleteTags(DeleteTagsOptions.Builder.resourceType("Volume")
+            .resourceIds(volumeToDelete)
+            .tags(ImmutableMap.of(prefix + "-first-tag", "first-tag-value",
+                  prefix + "-second-tag", "second-tag-value")));
+      assertTrue(jobComplete.apply(job.getJobId()));
+   }
+
+   static void checkTag(final Tag tag) {
+      assertNotNull(tag.getAccount());
+      assertNotNull(tag.getResourceId());
+   }
+
+   protected DiskOffering getPreferredDiskOffering() {
+      for (DiskOffering candidate : client.getOfferingApi().listDiskOfferings()) {
+         if (!candidate.isCustomized()) {
+            return candidate;
+         }
+      }
+      throw new AssertionError("No suitable DiskOffering found.");
+   }
+
+   protected void createVolumeToTag() {
+      AsyncCreateResponse job = client.getVolumeApi().createVolumeFromDiskOfferingInZone(prefix + "-jclouds-volume",
+            getPreferredDiskOffering().getId(), zoneId);
+      assertTrue(jobComplete.apply(job.getJobId()));
+      logger.info("created volume " + job.getId());
+      volumeToDelete = job.getId();
+   }
+
+   @Override
+   @AfterClass(groups = "live")
+   protected void tearDownContext() {
+      try {
+         client.getVolumeApi().deleteVolume(volumeToDelete);
+      } catch (Exception e) {
+         // Don't really care if there's an exception here
+      }
+      super.tearDownContext();
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/TagApiTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/TagApiTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/TagApiTest.java
new file mode 100644
index 0000000..01b1fe5
--- /dev/null
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/TagApiTest.java
@@ -0,0 +1,123 @@
+/*
+ * 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.cloudstack.features;
+
+import static org.jclouds.reflect.Reflection2.method;
+import static org.jclouds.util.Strings2.urlEncode;
+
+import java.io.IOException;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.reflect.Invokable;
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.cloudstack.domain.Tag;
+import org.jclouds.cloudstack.internal.BaseCloudStackApiTest;
+import org.jclouds.cloudstack.options.CreateTagsOptions;
+import org.jclouds.cloudstack.options.DeleteTagsOptions;
+import org.jclouds.cloudstack.options.ListTagsOptions;
+import org.jclouds.fallbacks.MapHttp4xxCodesToExceptions;
+import org.jclouds.http.functions.ParseFirstJsonValueNamed;
+import org.jclouds.http.functions.UnwrapOnlyJsonValue;
+import org.jclouds.rest.internal.GeneratedHttpRequest;
+import org.testng.annotations.Test;
+
+/**
+ * Tests behavior of {@code TagApi}
+ */
+// NOTE:without testName, this will not call @Before* and fail w/NPE during
+// surefire
+@Test(groups = "unit", testName = "TagApiTest")
+public class TagApiTest extends BaseCloudStackApiTest<TagApi> {
+   public void testListTags() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(TagApi.class, "listTags", ListTagsOptions[].class);
+      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.of());
+
+      assertRequestLineEquals(httpRequest,
+            "GET http://localhost:8080/client/api?response=json&command=listTags&listAll=true HTTP/1.1");
+      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
+      assertPayloadEquals(httpRequest, null, null, false);
+
+      assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(httpRequest);
+
+   }
+
+   public void testListTagsOptions() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(TagApi.class, "listTags", ListTagsOptions[].class);
+      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(
+            ListTagsOptions.Builder.accountInDomain("adrian", "6").resourceType(Tag.ResourceType.TEMPLATE)));
+
+      assertRequestLineEquals(
+            httpRequest,
+            "GET http://localhost:8080/client/api?response=json&command=listTags&listAll=true&account=adrian&domainid=6&resourcetype=Template HTTP/1.1");
+      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
+      assertPayloadEquals(httpRequest, null, null, false);
+
+      assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(httpRequest);
+
+   }
+
+   public void testCreateTags() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(TagApi.class, "createTags", CreateTagsOptions.class);
+      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(
+            CreateTagsOptions.Builder.resourceIds("1")
+                  .resourceType(Tag.ResourceType.TEMPLATE)
+                  .tags(ImmutableMap.of("some-tag", "some-value"))
+      ));
+
+      assertRequestLineEquals(httpRequest,
+            "GET http://localhost:8080/client/api?response=json&command=createTags&resourceids=1&resourcetype=Template&"
+                  + urlEncode("tags[0].key") + "=some-tag&" + urlEncode("tags[0].value") + "=some-value HTTP/1.1");
+                  assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
+      assertPayloadEquals(httpRequest, null, null, false);
+
+      assertResponseParserClassEquals(method, httpRequest, UnwrapOnlyJsonValue.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, MapHttp4xxCodesToExceptions.class);
+
+      checkFilters(httpRequest);
+   }
+
+   public void testDeleteTags() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(TagApi.class, "deleteTags", DeleteTagsOptions.class);
+      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(
+            DeleteTagsOptions.Builder.resourceIds("1")
+                  .resourceType(Tag.ResourceType.TEMPLATE)
+                  .tags(ImmutableMap.of("some-tag", "some-value"))
+      ));
+
+      assertRequestLineEquals(httpRequest,
+            "GET http://localhost:8080/client/api?response=json&command=deleteTags&resourceids=1&resourcetype=Template&"
+                  + urlEncode("tags[0].key") + "=some-tag&" + urlEncode("tags[0].value") + "=some-value HTTP/1.1");
+      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
+      assertPayloadEquals(httpRequest, null, null, false);
+
+      assertResponseParserClassEquals(method, httpRequest, UnwrapOnlyJsonValue.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, MapHttp4xxCodesToExceptions.class);
+
+      checkFilters(httpRequest);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ZoneApiExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ZoneApiExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ZoneApiExpectTest.java
index 2d709ad..6032ceb 100644
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ZoneApiExpectTest.java
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ZoneApiExpectTest.java
@@ -22,6 +22,7 @@ import java.net.URI;
 
 import org.jclouds.cloudstack.CloudStackContext;
 import org.jclouds.cloudstack.domain.NetworkType;
+import org.jclouds.cloudstack.domain.Tag;
 import org.jclouds.cloudstack.domain.Zone;
 import org.jclouds.cloudstack.internal.BaseCloudStackExpectTest;
 import org.jclouds.http.HttpRequest;
@@ -61,10 +62,20 @@ public class ZoneApiExpectTest extends BaseCloudStackExpectTest<ZoneApi> {
                .networkType(NetworkType.ADVANCED)
                .securityGroupsEnabled(false).build(),
             Zone.builder()
-               .id("2")
-               .name("Chicago")
-               .networkType(NetworkType.ADVANCED)
-               .securityGroupsEnabled(true).build()));
+                  .id("2")
+                  .name("Chicago")
+                  .networkType(NetworkType.ADVANCED)
+                  .securityGroupsEnabled(true)
+                  .tags(Tag.builder()
+                        .account("1")
+                        .domain("ROOT")
+                        .domainId("1")
+                        .key("some-tag")
+                        .resourceId("2")
+                        .resourceType(Tag.ResourceType.ZONE)
+                        .value("some-value")
+                        .build())
+                  .build()));
    }
 
    public void testListZonesWhenResponseIs404() {

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/CreateTagsOptionsTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/CreateTagsOptionsTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/CreateTagsOptionsTest.java
new file mode 100644
index 0000000..2fbcc5d
--- /dev/null
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/CreateTagsOptionsTest.java
@@ -0,0 +1,102 @@
+/*
+ * 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.cloudstack.options;
+
+import static org.jclouds.cloudstack.options.CreateTagsOptions.Builder.customer;
+import static org.jclouds.cloudstack.options.CreateTagsOptions.Builder.resourceIds;
+import static org.jclouds.cloudstack.options.CreateTagsOptions.Builder.resourceType;
+import static org.jclouds.cloudstack.options.CreateTagsOptions.Builder.tags;
+import static org.testng.Assert.assertEquals;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import org.jclouds.cloudstack.domain.Tag;
+import org.testng.annotations.Test;
+
+/**
+ * Tests behavior of {@code CreateTagsOptions}
+ */
+@Test(groups = "unit")
+public class CreateTagsOptionsTest {
+
+   public void testCustomer() {
+      CreateTagsOptions options = new CreateTagsOptions().customer("some-customer");
+      assertEquals(ImmutableList.of("some-customer"), options.buildQueryParameters().get("customer"));
+   }
+
+   public void testCustomerStatic() {
+      CreateTagsOptions options = customer("some-customer");
+      assertEquals(ImmutableList.of("some-customer"), options.buildQueryParameters().get("customer"));
+   }
+
+   public void testResourceIds() {
+      CreateTagsOptions options = new CreateTagsOptions().resourceIds("1", "2", "3");
+      assertEquals(ImmutableList.of("1,2,3"), options.buildQueryParameters().get("resourceids"));
+   }
+
+   public void testResourceIdsStatic() {
+      CreateTagsOptions options = resourceIds("1", "2", "3");
+      assertEquals(ImmutableList.of("1,2,3"), options.buildQueryParameters().get("resourceids"));
+   }
+
+   public void testResourceIdsAsSet() {
+      CreateTagsOptions options = new CreateTagsOptions().resourceIds(ImmutableSet.of("1", "2", "3"));
+      assertEquals(ImmutableList.of("1,2,3"), options.buildQueryParameters().get("resourceids"));
+   }
+
+   public void testResourceIdsAsSetStatic() {
+      CreateTagsOptions options = resourceIds(ImmutableSet.of("1", "2", "3"));
+      assertEquals(ImmutableList.of("1,2,3"), options.buildQueryParameters().get("resourceids"));
+   }
+
+   public void testResourceType() {
+      CreateTagsOptions options = new CreateTagsOptions().resourceType(Tag.ResourceType.TEMPLATE);
+      assertEquals(ImmutableList.of("Template"), options.buildQueryParameters().get("resourcetype"));
+   }
+
+   public void testResourceTypeStatic() {
+      CreateTagsOptions options = resourceType(Tag.ResourceType.TEMPLATE);
+      assertEquals(ImmutableList.of("Template"), options.buildQueryParameters().get("resourcetype"));
+   }
+
+   public void testResourceTypeAsString() {
+      CreateTagsOptions options = new CreateTagsOptions().resourceType("Template");
+      assertEquals(ImmutableList.of("Template"), options.buildQueryParameters().get("resourcetype"));
+   }
+
+   public void testResourceTypeAsStringStatic() {
+      CreateTagsOptions options = resourceType("Template");
+      assertEquals(ImmutableList.of("Template"), options.buildQueryParameters().get("resourcetype"));
+   }
+
+   public void testTags() {
+      CreateTagsOptions options = new CreateTagsOptions().tags(ImmutableMap.of("tag1", "val1", "tag2", "val2"));
+      assertEquals(ImmutableList.of("tag1"), options.buildQueryParameters().get("tags[0].key"));
+      assertEquals(ImmutableList.of("tag2"), options.buildQueryParameters().get("tags[1].key"));
+      assertEquals(ImmutableList.of("val1"), options.buildQueryParameters().get("tags[0].value"));
+      assertEquals(ImmutableList.of("val2"), options.buildQueryParameters().get("tags[1].value"));
+   }
+
+   public void testTagsStatic() {
+      CreateTagsOptions options = tags(ImmutableMap.of("tag1", "val1", "tag2", "val2"));
+      assertEquals(ImmutableList.of("tag1"), options.buildQueryParameters().get("tags[0].key"));
+      assertEquals(ImmutableList.of("tag2"), options.buildQueryParameters().get("tags[1].key"));
+      assertEquals(ImmutableList.of("val1"), options.buildQueryParameters().get("tags[0].value"));
+      assertEquals(ImmutableList.of("val2"), options.buildQueryParameters().get("tags[1].value"));
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/DeleteTagsOptionsTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/DeleteTagsOptionsTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/DeleteTagsOptionsTest.java
new file mode 100644
index 0000000..c99edd6
--- /dev/null
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/DeleteTagsOptionsTest.java
@@ -0,0 +1,91 @@
+/*
+ * 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.cloudstack.options;
+
+import static org.jclouds.cloudstack.options.DeleteTagsOptions.Builder.resourceIds;
+import static org.jclouds.cloudstack.options.DeleteTagsOptions.Builder.resourceType;
+import static org.jclouds.cloudstack.options.DeleteTagsOptions.Builder.tags;
+import static org.testng.Assert.assertEquals;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import org.jclouds.cloudstack.domain.Tag;
+import org.testng.annotations.Test;
+
+/**
+ * Tests behavior of {@code DeleteTagsOptions}
+ */
+@Test(groups = "unit")
+public class DeleteTagsOptionsTest {
+
+   public void testResourceIds() {
+      DeleteTagsOptions options = new DeleteTagsOptions().resourceIds("1", "2", "3");
+      assertEquals(ImmutableList.of("1,2,3"), options.buildQueryParameters().get("resourceids"));
+   }
+
+   public void testResourceIdsStatic() {
+      DeleteTagsOptions options = resourceIds("1", "2", "3");
+      assertEquals(ImmutableList.of("1,2,3"), options.buildQueryParameters().get("resourceids"));
+   }
+
+   public void testResourceIdsAsSet() {
+      DeleteTagsOptions options = new DeleteTagsOptions().resourceIds(ImmutableSet.of("1", "2", "3"));
+      assertEquals(ImmutableList.of("1,2,3"), options.buildQueryParameters().get("resourceids"));
+   }
+
+   public void testResourceIdsAsSetStatic() {
+      DeleteTagsOptions options = resourceIds(ImmutableSet.of("1", "2", "3"));
+      assertEquals(ImmutableList.of("1,2,3"), options.buildQueryParameters().get("resourceids"));
+   }
+
+   public void testResourceType() {
+      DeleteTagsOptions options = new DeleteTagsOptions().resourceType(Tag.ResourceType.TEMPLATE);
+      assertEquals(ImmutableList.of("Template"), options.buildQueryParameters().get("resourcetype"));
+   }
+
+   public void testResourceTypeStatic() {
+      DeleteTagsOptions options = resourceType(Tag.ResourceType.TEMPLATE);
+      assertEquals(ImmutableList.of("Template"), options.buildQueryParameters().get("resourcetype"));
+   }
+
+   public void testResourceTypeAsString() {
+      DeleteTagsOptions options = new DeleteTagsOptions().resourceType("Template");
+      assertEquals(ImmutableList.of("Template"), options.buildQueryParameters().get("resourcetype"));
+   }
+
+   public void testResourceTypeAsStringStatic() {
+      DeleteTagsOptions options = resourceType("Template");
+      assertEquals(ImmutableList.of("Template"), options.buildQueryParameters().get("resourcetype"));
+   }
+
+   public void testTags() {
+      DeleteTagsOptions options = new DeleteTagsOptions().tags(ImmutableMap.of("tag1", "val1", "tag2", "val2"));
+      assertEquals(ImmutableList.of("tag1"), options.buildQueryParameters().get("tags[0].key"));
+      assertEquals(ImmutableList.of("tag2"), options.buildQueryParameters().get("tags[1].key"));
+      assertEquals(ImmutableList.of("val1"), options.buildQueryParameters().get("tags[0].value"));
+      assertEquals(ImmutableList.of("val2"), options.buildQueryParameters().get("tags[1].value"));
+   }
+
+   public void testTagsStatic() {
+      DeleteTagsOptions options = tags(ImmutableMap.of("tag1", "val1", "tag2", "val2"));
+      assertEquals(ImmutableList.of("tag1"), options.buildQueryParameters().get("tags[0].key"));
+      assertEquals(ImmutableList.of("tag2"), options.buildQueryParameters().get("tags[1].key"));
+      assertEquals(ImmutableList.of("val1"), options.buildQueryParameters().get("tags[0].value"));
+      assertEquals(ImmutableList.of("val2"), options.buildQueryParameters().get("tags[1].value"));
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListIPForwardingRulesOptionsTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListIPForwardingRulesOptionsTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListIPForwardingRulesOptionsTest.java
index 34bc42f..0fac32b 100644
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListIPForwardingRulesOptionsTest.java
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListIPForwardingRulesOptionsTest.java
@@ -16,6 +16,7 @@
  */
 package org.jclouds.cloudstack.options;
 
+import static org.jclouds.cloudstack.options.ListIPForwardingRulesOptions.Builder.tags;
 import static org.jclouds.cloudstack.options.ListIPForwardingRulesOptions.Builder.IPAddressId;
 import static org.jclouds.cloudstack.options.ListIPForwardingRulesOptions.Builder.accountInDomain;
 import static org.jclouds.cloudstack.options.ListIPForwardingRulesOptions.Builder.domainId;
@@ -23,6 +24,7 @@ import static org.jclouds.cloudstack.options.ListIPForwardingRulesOptions.Builde
 import static org.jclouds.cloudstack.options.ListIPForwardingRulesOptions.Builder.virtualMachineId;
 import static org.testng.Assert.assertEquals;
 
+import com.google.common.collect.ImmutableMap;
 import org.testng.annotations.Test;
 
 import com.google.common.collect.ImmutableList;
@@ -84,4 +86,21 @@ public class ListIPForwardingRulesOptionsTest {
       ListIPForwardingRulesOptions options = virtualMachineId("6");
       assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("virtualmachineid"));
    }
+
+   public void testTags() {
+      ListIPForwardingRulesOptions options = new ListIPForwardingRulesOptions().tags(ImmutableMap.of("tag1", "val1", "tag2", "val2"));
+      assertEquals(ImmutableList.of("tag1"), options.buildQueryParameters().get("tags[0].key"));
+      assertEquals(ImmutableList.of("tag2"), options.buildQueryParameters().get("tags[1].key"));
+      assertEquals(ImmutableList.of("val1"), options.buildQueryParameters().get("tags[0].value"));
+      assertEquals(ImmutableList.of("val2"), options.buildQueryParameters().get("tags[1].value"));
+   }
+
+   public void testTagsStatic() {
+      ListIPForwardingRulesOptions options = tags(ImmutableMap.of("tag1", "val1", "tag2", "val2"));
+      assertEquals(ImmutableList.of("tag1"), options.buildQueryParameters().get("tags[0].key"));
+      assertEquals(ImmutableList.of("tag2"), options.buildQueryParameters().get("tags[1].key"));
+      assertEquals(ImmutableList.of("val1"), options.buildQueryParameters().get("tags[0].value"));
+      assertEquals(ImmutableList.of("val2"), options.buildQueryParameters().get("tags[1].value"));
+   }
+
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListISOsOptionsTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListISOsOptionsTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListISOsOptionsTest.java
index 2494a66..97646d3 100644
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListISOsOptionsTest.java
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListISOsOptionsTest.java
@@ -16,6 +16,7 @@
  */
 package org.jclouds.cloudstack.options;
 
+import static org.jclouds.cloudstack.options.ListISOsOptions.Builder.tags;
 import static org.jclouds.cloudstack.options.ListISOsOptions.Builder.bootable;
 import static org.jclouds.cloudstack.options.ListISOsOptions.Builder.hypervisor;
 import static org.jclouds.cloudstack.options.ListISOsOptions.Builder.id;
@@ -32,6 +33,8 @@ import static org.testng.Assert.assertEquals;
 
 import java.util.Set;
 
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
 import org.jclouds.cloudstack.domain.ISO;
 import org.testng.annotations.Test;
 
@@ -164,4 +167,20 @@ public class ListISOsOptionsTest {
       ListISOsOptions options = zoneId("6");
       assertEquals(ImmutableSet.of("6"), options.buildQueryParameters().get("zoneid"));
    }
+
+   public void testTags() {
+      ListISOsOptions options = new ListISOsOptions().tags(ImmutableMap.of("tag1", "val1", "tag2", "val2"));
+      assertEquals(ImmutableList.of("tag1"), options.buildQueryParameters().get("tags[0].key"));
+      assertEquals(ImmutableList.of("tag2"), options.buildQueryParameters().get("tags[1].key"));
+      assertEquals(ImmutableList.of("val1"), options.buildQueryParameters().get("tags[0].value"));
+      assertEquals(ImmutableList.of("val2"), options.buildQueryParameters().get("tags[1].value"));
+   }
+
+   public void testTagsStatic() {
+      ListISOsOptions options = tags(ImmutableMap.of("tag1", "val1", "tag2", "val2"));
+      assertEquals(ImmutableList.of("tag1"), options.buildQueryParameters().get("tags[0].key"));
+      assertEquals(ImmutableList.of("tag2"), options.buildQueryParameters().get("tags[1].key"));
+      assertEquals(ImmutableList.of("val1"), options.buildQueryParameters().get("tags[0].value"));
+      assertEquals(ImmutableList.of("val2"), options.buildQueryParameters().get("tags[1].value"));
+   }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListNetworksOptionsTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListNetworksOptionsTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListNetworksOptionsTest.java
index 0db9e5a..41e6c8f 100644
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListNetworksOptionsTest.java
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListNetworksOptionsTest.java
@@ -16,6 +16,7 @@
  */
 package org.jclouds.cloudstack.options;
 
+import static org.jclouds.cloudstack.options.ListNetworksOptions.Builder.tags;
 import static org.jclouds.cloudstack.options.ListNetworksOptions.Builder.accountInDomain;
 import static org.jclouds.cloudstack.options.ListNetworksOptions.Builder.domainId;
 import static org.jclouds.cloudstack.options.ListNetworksOptions.Builder.id;
@@ -27,6 +28,7 @@ import static org.jclouds.cloudstack.options.ListNetworksOptions.Builder.type;
 import static org.jclouds.cloudstack.options.ListNetworksOptions.Builder.zoneId;
 import static org.testng.Assert.assertEquals;
 
+import com.google.common.collect.ImmutableMap;
 import org.jclouds.cloudstack.domain.NetworkType;
 import org.jclouds.cloudstack.domain.TrafficType;
 import org.testng.annotations.Test;
@@ -139,4 +141,21 @@ public class ListNetworksOptionsTest {
       ListNetworksOptions options = type(NetworkType.ADVANCED);
       assertEquals(ImmutableList.of("Advanced"), options.buildQueryParameters().get("type"));
    }
+
+   public void testTags() {
+      ListNetworksOptions options = new ListNetworksOptions().tags(ImmutableMap.of("tag1", "val1", "tag2", "val2"));
+      assertEquals(ImmutableList.of("tag1"), options.buildQueryParameters().get("tags[0].key"));
+      assertEquals(ImmutableList.of("tag2"), options.buildQueryParameters().get("tags[1].key"));
+      assertEquals(ImmutableList.of("val1"), options.buildQueryParameters().get("tags[0].value"));
+      assertEquals(ImmutableList.of("val2"), options.buildQueryParameters().get("tags[1].value"));
+   }
+
+   public void testTagsStatic() {
+      ListNetworksOptions options = tags(ImmutableMap.of("tag1", "val1", "tag2", "val2"));
+      assertEquals(ImmutableList.of("tag1"), options.buildQueryParameters().get("tags[0].key"));
+      assertEquals(ImmutableList.of("tag2"), options.buildQueryParameters().get("tags[1].key"));
+      assertEquals(ImmutableList.of("val1"), options.buildQueryParameters().get("tags[0].value"));
+      assertEquals(ImmutableList.of("val2"), options.buildQueryParameters().get("tags[1].value"));
+   }
+
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListPortForwardingRulesOptionsTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListPortForwardingRulesOptionsTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListPortForwardingRulesOptionsTest.java
index 82402ea..677b506 100644
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListPortForwardingRulesOptionsTest.java
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListPortForwardingRulesOptionsTest.java
@@ -16,11 +16,13 @@
  */
 package org.jclouds.cloudstack.options;
 
+import static org.jclouds.cloudstack.options.ListPortForwardingRulesOptions.Builder.tags;
 import static org.jclouds.cloudstack.options.ListPortForwardingRulesOptions.Builder.accountInDomain;
 import static org.jclouds.cloudstack.options.ListPortForwardingRulesOptions.Builder.domainId;
 import static org.jclouds.cloudstack.options.ListPortForwardingRulesOptions.Builder.ipAddressId;
 import static org.testng.Assert.assertEquals;
 
+import com.google.common.collect.ImmutableMap;
 import org.testng.annotations.Test;
 
 import com.google.common.collect.ImmutableList;
@@ -63,4 +65,20 @@ public class ListPortForwardingRulesOptionsTest {
       assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("domainid"));
    }
 
+   public void testTags() {
+      ListPortForwardingRulesOptions options = new ListPortForwardingRulesOptions().tags(ImmutableMap.of("tag1", "val1", "tag2", "val2"));
+      assertEquals(ImmutableList.of("tag1"), options.buildQueryParameters().get("tags[0].key"));
+      assertEquals(ImmutableList.of("tag2"), options.buildQueryParameters().get("tags[1].key"));
+      assertEquals(ImmutableList.of("val1"), options.buildQueryParameters().get("tags[0].value"));
+      assertEquals(ImmutableList.of("val2"), options.buildQueryParameters().get("tags[1].value"));
+   }
+
+   public void testTagsStatic() {
+      ListPortForwardingRulesOptions options = tags(ImmutableMap.of("tag1", "val1", "tag2", "val2"));
+      assertEquals(ImmutableList.of("tag1"), options.buildQueryParameters().get("tags[0].key"));
+      assertEquals(ImmutableList.of("tag2"), options.buildQueryParameters().get("tags[1].key"));
+      assertEquals(ImmutableList.of("val1"), options.buildQueryParameters().get("tags[0].value"));
+      assertEquals(ImmutableList.of("val2"), options.buildQueryParameters().get("tags[1].value"));
+   }
+
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListPublicIPAddressesOptionsTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListPublicIPAddressesOptionsTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListPublicIPAddressesOptionsTest.java
index fb606ae..7077ee0 100644
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListPublicIPAddressesOptionsTest.java
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListPublicIPAddressesOptionsTest.java
@@ -16,6 +16,7 @@
  */
 package org.jclouds.cloudstack.options;
 
+import static org.jclouds.cloudstack.options.ListPublicIPAddressesOptions.Builder.tags;
 import static org.jclouds.cloudstack.options.ListPublicIPAddressesOptions.Builder.IPAddress;
 import static org.jclouds.cloudstack.options.ListPublicIPAddressesOptions.Builder.VLANId;
 import static org.jclouds.cloudstack.options.ListPublicIPAddressesOptions.Builder.accountInDomain;
@@ -27,6 +28,7 @@ import static org.jclouds.cloudstack.options.ListPublicIPAddressesOptions.Builde
 import static org.jclouds.cloudstack.options.ListPublicIPAddressesOptions.Builder.zoneId;
 import static org.testng.Assert.assertEquals;
 
+import com.google.common.collect.ImmutableMap;
 import org.testng.annotations.Test;
 
 import com.google.common.collect.ImmutableList;
@@ -128,4 +130,20 @@ public class ListPublicIPAddressesOptionsTest {
       ListPublicIPAddressesOptions options = domainId("6");
       assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("domainid"));
    }
+
+   public void testTags() {
+      ListPublicIPAddressesOptions options = new ListPublicIPAddressesOptions().tags(ImmutableMap.of("tag1", "val1", "tag2", "val2"));
+      assertEquals(ImmutableList.of("tag1"), options.buildQueryParameters().get("tags[0].key"));
+      assertEquals(ImmutableList.of("tag2"), options.buildQueryParameters().get("tags[1].key"));
+      assertEquals(ImmutableList.of("val1"), options.buildQueryParameters().get("tags[0].value"));
+      assertEquals(ImmutableList.of("val2"), options.buildQueryParameters().get("tags[1].value"));
+   }
+
+   public void testTagsStatic() {
+      ListPublicIPAddressesOptions options = tags(ImmutableMap.of("tag1", "val1", "tag2", "val2"));
+      assertEquals(ImmutableList.of("tag1"), options.buildQueryParameters().get("tags[0].key"));
+      assertEquals(ImmutableList.of("tag2"), options.buildQueryParameters().get("tags[1].key"));
+      assertEquals(ImmutableList.of("val1"), options.buildQueryParameters().get("tags[0].value"));
+      assertEquals(ImmutableList.of("val2"), options.buildQueryParameters().get("tags[1].value"));
+   }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListSecurityGroupsOptionsTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListSecurityGroupsOptionsTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListSecurityGroupsOptionsTest.java
index 6b5a6e8..624e080 100644
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListSecurityGroupsOptionsTest.java
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListSecurityGroupsOptionsTest.java
@@ -16,6 +16,7 @@
  */
 package org.jclouds.cloudstack.options;
 
+import static org.jclouds.cloudstack.options.ListSecurityGroupsOptions.Builder.tags;
 import static org.jclouds.cloudstack.options.ListSecurityGroupsOptions.Builder.accountInDomain;
 import static org.jclouds.cloudstack.options.ListSecurityGroupsOptions.Builder.domainId;
 import static org.jclouds.cloudstack.options.ListSecurityGroupsOptions.Builder.id;
@@ -23,6 +24,7 @@ import static org.jclouds.cloudstack.options.ListSecurityGroupsOptions.Builder.n
 import static org.jclouds.cloudstack.options.ListSecurityGroupsOptions.Builder.virtualMachineId;
 import static org.testng.Assert.assertEquals;
 
+import com.google.common.collect.ImmutableMap;
 import org.testng.annotations.Test;
 
 import com.google.common.collect.ImmutableList;
@@ -82,4 +84,20 @@ public class ListSecurityGroupsOptionsTest {
       ListSecurityGroupsOptions options = virtualMachineId("6");
       assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("virtualmachineid"));
    }
+
+   public void testTags() {
+      ListSecurityGroupsOptions options = new ListSecurityGroupsOptions().tags(ImmutableMap.of("tag1", "val1", "tag2", "val2"));
+      assertEquals(ImmutableList.of("tag1"), options.buildQueryParameters().get("tags[0].key"));
+      assertEquals(ImmutableList.of("tag2"), options.buildQueryParameters().get("tags[1].key"));
+      assertEquals(ImmutableList.of("val1"), options.buildQueryParameters().get("tags[0].value"));
+      assertEquals(ImmutableList.of("val2"), options.buildQueryParameters().get("tags[1].value"));
+   }
+
+   public void testTagsStatic() {
+      ListSecurityGroupsOptions options = tags(ImmutableMap.of("tag1", "val1", "tag2", "val2"));
+      assertEquals(ImmutableList.of("tag1"), options.buildQueryParameters().get("tags[0].key"));
+      assertEquals(ImmutableList.of("tag2"), options.buildQueryParameters().get("tags[1].key"));
+      assertEquals(ImmutableList.of("val1"), options.buildQueryParameters().get("tags[0].value"));
+      assertEquals(ImmutableList.of("val2"), options.buildQueryParameters().get("tags[1].value"));
+   }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListTagsOptionsTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListTagsOptionsTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListTagsOptionsTest.java
new file mode 100644
index 0000000..9fa59de
--- /dev/null
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListTagsOptionsTest.java
@@ -0,0 +1,152 @@
+/*
+ * 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.cloudstack.options;
+
+import static org.jclouds.cloudstack.options.ListTagsOptions.Builder.accountInDomain;
+import static org.jclouds.cloudstack.options.ListTagsOptions.Builder.customer;
+import static org.jclouds.cloudstack.options.ListTagsOptions.Builder.domainId;
+import static org.jclouds.cloudstack.options.ListTagsOptions.Builder.isRecursive;
+import static org.jclouds.cloudstack.options.ListTagsOptions.Builder.key;
+import static org.jclouds.cloudstack.options.ListTagsOptions.Builder.keyword;
+import static org.jclouds.cloudstack.options.ListTagsOptions.Builder.projectId;
+import static org.jclouds.cloudstack.options.ListTagsOptions.Builder.resourceId;
+import static org.jclouds.cloudstack.options.ListTagsOptions.Builder.resourceType;
+import static org.jclouds.cloudstack.options.ListTagsOptions.Builder.value;
+import static org.testng.Assert.assertEquals;
+
+import com.google.common.collect.ImmutableList;
+import org.jclouds.cloudstack.domain.Tag;
+import org.testng.annotations.Test;
+
+/**
+ * Tests behavior of {@code ListTagsOptions}
+ */
+@Test(groups = "unit")
+public class ListTagsOptionsTest {
+
+   public void testCustomer() {
+      ListTagsOptions options = new ListTagsOptions().customer("6");
+      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("customer"));
+   }
+
+   public void testCustomerStatic() {
+      ListTagsOptions options = customer("6");
+      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("customer"));
+   }
+
+   public void testDomainId() {
+      ListTagsOptions options = new ListTagsOptions().domainId("6");
+      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("domainid"));
+   }
+
+   public void testDomainIdStatic() {
+      ListTagsOptions options = domainId("6");
+      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("domainid"));
+   }
+
+   public void testAccountInDomainId() {
+      ListTagsOptions options = new ListTagsOptions().accountInDomain("adrian", "6");
+      assertEquals(ImmutableList.of("adrian"), options.buildQueryParameters().get("account"));
+      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("domainid"));
+   }
+
+   public void testAccountInDomainIdStatic() {
+      ListTagsOptions options = accountInDomain("adrian", "6");
+      assertEquals(ImmutableList.of("adrian"), options.buildQueryParameters().get("account"));
+      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("domainid"));
+   }
+
+   public void testIsRecursive() {
+      ListTagsOptions options = new ListTagsOptions().isRecursive(true);
+      assertEquals(ImmutableList.of("true"), options.buildQueryParameters().get("isrecursive"));
+   }
+
+   public void testIsRecursiveStatic() {
+      ListTagsOptions options = isRecursive(true);
+      assertEquals(ImmutableList.of("true"), options.buildQueryParameters().get("isrecursive"));
+   }
+
+   public void testKey() {
+      ListTagsOptions options = new ListTagsOptions().key("6");
+      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("key"));
+   }
+
+   public void testKeyStatic() {
+      ListTagsOptions options = key("6");
+      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("key"));
+   }
+
+   public void testKeyword() {
+      ListTagsOptions options = new ListTagsOptions().keyword("6");
+      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("keyword"));
+   }
+
+   public void testKeywordStatic() {
+      ListTagsOptions options = keyword("6");
+      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("keyword"));
+   }
+
+   public void testProjectId() {
+      ListTagsOptions options = new ListTagsOptions().projectId("6");
+      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("projectid"));
+   }
+
+   public void testProjectIdStatic() {
+      ListTagsOptions options = projectId("6");
+      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("projectid"));
+   }
+
+   public void testResourceId() {
+      ListTagsOptions options = new ListTagsOptions().resourceId("6");
+      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("resourceid"));
+   }
+
+   public void testResourceIdStatic() {
+      ListTagsOptions options = resourceId("6");
+      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("resourceid"));
+   }
+
+   public void testResourceType() {
+      ListTagsOptions options = new ListTagsOptions().resourceType(Tag.ResourceType.TEMPLATE);
+      assertEquals(ImmutableList.of("Template"), options.buildQueryParameters().get("resourcetype"));
+   }
+
+   public void testResourceTypeStatic() {
+      ListTagsOptions options = resourceType(Tag.ResourceType.TEMPLATE);
+      assertEquals(ImmutableList.of("Template"), options.buildQueryParameters().get("resourcetype"));
+   }
+
+   public void testResourceTypeAsString() {
+      ListTagsOptions options = new ListTagsOptions().resourceType("Template");
+      assertEquals(ImmutableList.of("Template"), options.buildQueryParameters().get("resourcetype"));
+   }
+
+   public void testResourceTypeAsStringStatic() {
+      ListTagsOptions options = resourceType("Template");
+      assertEquals(ImmutableList.of("Template"), options.buildQueryParameters().get("resourcetype"));
+   }
+
+   public void testValue() {
+      ListTagsOptions options = new ListTagsOptions().value("some-value");
+      assertEquals(ImmutableList.of("some-value"), options.buildQueryParameters().get("value"));
+   }
+
+   public void testValueStatic() {
+      ListTagsOptions options = value("some-value");
+      assertEquals(ImmutableList.of("some-value"), options.buildQueryParameters().get("value"));
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListTemplatesOptionsTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListTemplatesOptionsTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListTemplatesOptionsTest.java
index 17be0e0..c246217 100644
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListTemplatesOptionsTest.java
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListTemplatesOptionsTest.java
@@ -16,6 +16,7 @@
  */
 package org.jclouds.cloudstack.options;
 
+import static org.jclouds.cloudstack.options.ListTemplatesOptions.Builder.tags;
 import static org.jclouds.cloudstack.options.ListTemplatesOptions.Builder.accountInDomain;
 import static org.jclouds.cloudstack.options.ListTemplatesOptions.Builder.domainId;
 import static org.jclouds.cloudstack.options.ListTemplatesOptions.Builder.filter;
@@ -24,6 +25,7 @@ import static org.jclouds.cloudstack.options.ListTemplatesOptions.Builder.id;
 import static org.jclouds.cloudstack.options.ListTemplatesOptions.Builder.zoneId;
 import static org.testng.Assert.assertEquals;
 
+import com.google.common.collect.ImmutableMap;
 import org.jclouds.cloudstack.domain.TemplateFilter;
 import org.testng.annotations.Test;
 
@@ -111,4 +113,20 @@ public class ListTemplatesOptionsTest {
       ListTemplatesOptions options = filter(TemplateFilter.SELF_EXECUTABLE);
       assertEquals(ImmutableList.of("self-executable"), options.buildQueryParameters().get("templatefilter"));
    }
+
+   public void testTags() {
+      ListTemplatesOptions options = new ListTemplatesOptions().tags(ImmutableMap.of("tag1", "val1", "tag2", "val2"));
+      assertEquals(ImmutableList.of("tag1"), options.buildQueryParameters().get("tags[0].key"));
+      assertEquals(ImmutableList.of("tag2"), options.buildQueryParameters().get("tags[1].key"));
+      assertEquals(ImmutableList.of("val1"), options.buildQueryParameters().get("tags[0].value"));
+      assertEquals(ImmutableList.of("val2"), options.buildQueryParameters().get("tags[1].value"));
+   }
+
+   public void testTagsStatic() {
+      ListTemplatesOptions options = tags(ImmutableMap.of("tag1", "val1", "tag2", "val2"));
+      assertEquals(ImmutableList.of("tag1"), options.buildQueryParameters().get("tags[0].key"));
+      assertEquals(ImmutableList.of("tag2"), options.buildQueryParameters().get("tags[1].key"));
+      assertEquals(ImmutableList.of("val1"), options.buildQueryParameters().get("tags[0].value"));
+      assertEquals(ImmutableList.of("val2"), options.buildQueryParameters().get("tags[1].value"));
+   }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListVirtualMachesOptionsTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListVirtualMachesOptionsTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListVirtualMachesOptionsTest.java
deleted file mode 100644
index bb5df4c..0000000
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListVirtualMachesOptionsTest.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * 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.cloudstack.options;
-
-import static org.jclouds.cloudstack.options.ListVirtualMachinesOptions.Builder.accountInDomain;
-import static org.jclouds.cloudstack.options.ListVirtualMachinesOptions.Builder.domainId;
-import static org.jclouds.cloudstack.options.ListVirtualMachinesOptions.Builder.groupId;
-import static org.jclouds.cloudstack.options.ListVirtualMachinesOptions.Builder.hostId;
-import static org.jclouds.cloudstack.options.ListVirtualMachinesOptions.Builder.id;
-import static org.jclouds.cloudstack.options.ListVirtualMachinesOptions.Builder.networkId;
-import static org.jclouds.cloudstack.options.ListVirtualMachinesOptions.Builder.podId;
-import static org.jclouds.cloudstack.options.ListVirtualMachinesOptions.Builder.state;
-import static org.jclouds.cloudstack.options.ListVirtualMachinesOptions.Builder.usesVirtualNetwork;
-import static org.jclouds.cloudstack.options.ListVirtualMachinesOptions.Builder.zoneId;
-import static org.testng.Assert.assertEquals;
-
-import org.testng.annotations.Test;
-
-import com.google.common.collect.ImmutableList;
-
-/**
- * Tests behavior of {@code ListVirtualMachinesOptions}
- */
-@Test(groups = "unit")
-public class ListVirtualMachesOptionsTest {
-
-   public void testHostId() {
-      ListVirtualMachinesOptions options = new ListVirtualMachinesOptions().hostId("6");
-      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("hostid"));
-   }
-
-   public void testHostIdStatic() {
-      ListVirtualMachinesOptions options = hostId("6");
-      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("hostid"));
-   }
-
-   public void testPodId() {
-      ListVirtualMachinesOptions options = new ListVirtualMachinesOptions().podId("6");
-      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("podid"));
-   }
-
-   public void testPodIdStatic() {
-      ListVirtualMachinesOptions options = podId("6");
-      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("podid"));
-   }
-
-   public void testNetworkId() {
-      ListVirtualMachinesOptions options = new ListVirtualMachinesOptions().networkId("6");
-      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("networkid"));
-   }
-
-   public void testNetworkIdStatic() {
-      ListVirtualMachinesOptions options = networkId("6");
-      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("networkid"));
-   }
-
-   public void testGroupId() {
-      ListVirtualMachinesOptions options = new ListVirtualMachinesOptions().groupId("6");
-      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("groupid"));
-   }
-
-   public void testGroupIdStatic() {
-      ListVirtualMachinesOptions options = groupId("6");
-      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("groupid"));
-   }
-
-   public void testAccountInDomainId() {
-      ListVirtualMachinesOptions options = new ListVirtualMachinesOptions().accountInDomain("adrian", "6");
-      assertEquals(ImmutableList.of("adrian"), options.buildQueryParameters().get("account"));
-      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("domainid"));
-   }
-
-   public void testAccountInDomainIdStatic() {
-      ListVirtualMachinesOptions options = accountInDomain("adrian", "6");
-      assertEquals(ImmutableList.of("adrian"), options.buildQueryParameters().get("account"));
-      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("domainid"));
-   }
-
-   public void testName() {
-      ListVirtualMachinesOptions options = new ListVirtualMachinesOptions().id("6");
-      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("id"));
-   }
-
-   public void testNameStatic() {
-      ListVirtualMachinesOptions options = id("6");
-      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("id"));
-   }
-
-   public void testZoneId() {
-      ListVirtualMachinesOptions options = new ListVirtualMachinesOptions().zoneId("6");
-      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("zoneid"));
-   }
-
-   public void testZoneIdStatic() {
-      ListVirtualMachinesOptions options = zoneId("6");
-      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("zoneid"));
-   }
-
-   public void testState() {
-      ListVirtualMachinesOptions options = new ListVirtualMachinesOptions().state("state");
-      assertEquals(ImmutableList.of("state"), options.buildQueryParameters().get("state"));
-   }
-
-   public void testStateStatic() {
-      ListVirtualMachinesOptions options = state("state");
-      assertEquals(ImmutableList.of("state"), options.buildQueryParameters().get("state"));
-   }
-
-   public void testUsingVirtualNetwork() {
-      ListVirtualMachinesOptions options = new ListVirtualMachinesOptions().usesVirtualNetwork(true);
-      assertEquals(ImmutableList.of("true"), options.buildQueryParameters().get("forvirtualnetwork"));
-   }
-
-   public void testUsingVirtualNetworkStatic() {
-      ListVirtualMachinesOptions options = usesVirtualNetwork(true);
-      assertEquals(ImmutableList.of("true"), options.buildQueryParameters().get("forvirtualnetwork"));
-   }
-
-   public void testId() {
-      ListVirtualMachinesOptions options = new ListVirtualMachinesOptions().id("6");
-      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("id"));
-   }
-
-   public void testDomainId() {
-      ListVirtualMachinesOptions options = new ListVirtualMachinesOptions().domainId("6");
-      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("domainid"));
-   }
-
-   public void testIdStatic() {
-      ListVirtualMachinesOptions options = id("6");
-      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("id"));
-   }
-
-   public void testDomainIdStatic() {
-      ListVirtualMachinesOptions options = domainId("6");
-      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("domainid"));
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListVirtualMachinesOptionsTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListVirtualMachinesOptionsTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListVirtualMachinesOptionsTest.java
new file mode 100644
index 0000000..5288b1a
--- /dev/null
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListVirtualMachinesOptionsTest.java
@@ -0,0 +1,170 @@
+/*
+ * 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.cloudstack.options;
+
+import static org.jclouds.cloudstack.options.ListVirtualMachinesOptions.Builder.tags;
+import static org.jclouds.cloudstack.options.ListVirtualMachinesOptions.Builder.accountInDomain;
+import static org.jclouds.cloudstack.options.ListVirtualMachinesOptions.Builder.domainId;
+import static org.jclouds.cloudstack.options.ListVirtualMachinesOptions.Builder.groupId;
+import static org.jclouds.cloudstack.options.ListVirtualMachinesOptions.Builder.hostId;
+import static org.jclouds.cloudstack.options.ListVirtualMachinesOptions.Builder.id;
+import static org.jclouds.cloudstack.options.ListVirtualMachinesOptions.Builder.networkId;
+import static org.jclouds.cloudstack.options.ListVirtualMachinesOptions.Builder.podId;
+import static org.jclouds.cloudstack.options.ListVirtualMachinesOptions.Builder.state;
+import static org.jclouds.cloudstack.options.ListVirtualMachinesOptions.Builder.usesVirtualNetwork;
+import static org.jclouds.cloudstack.options.ListVirtualMachinesOptions.Builder.zoneId;
+import static org.testng.Assert.assertEquals;
+
+import com.google.common.collect.ImmutableMap;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Tests behavior of {@code ListVirtualMachinesOptions}
+ */
+@Test(groups = "unit")
+public class ListVirtualMachinesOptionsTest {
+
+   public void testHostId() {
+      ListVirtualMachinesOptions options = new ListVirtualMachinesOptions().hostId("6");
+      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("hostid"));
+   }
+
+   public void testHostIdStatic() {
+      ListVirtualMachinesOptions options = hostId("6");
+      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("hostid"));
+   }
+
+   public void testPodId() {
+      ListVirtualMachinesOptions options = new ListVirtualMachinesOptions().podId("6");
+      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("podid"));
+   }
+
+   public void testPodIdStatic() {
+      ListVirtualMachinesOptions options = podId("6");
+      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("podid"));
+   }
+
+   public void testNetworkId() {
+      ListVirtualMachinesOptions options = new ListVirtualMachinesOptions().networkId("6");
+      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("networkid"));
+   }
+
+   public void testNetworkIdStatic() {
+      ListVirtualMachinesOptions options = networkId("6");
+      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("networkid"));
+   }
+
+   public void testGroupId() {
+      ListVirtualMachinesOptions options = new ListVirtualMachinesOptions().groupId("6");
+      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("groupid"));
+   }
+
+   public void testGroupIdStatic() {
+      ListVirtualMachinesOptions options = groupId("6");
+      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("groupid"));
+   }
+
+   public void testAccountInDomainId() {
+      ListVirtualMachinesOptions options = new ListVirtualMachinesOptions().accountInDomain("adrian", "6");
+      assertEquals(ImmutableList.of("adrian"), options.buildQueryParameters().get("account"));
+      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("domainid"));
+   }
+
+   public void testAccountInDomainIdStatic() {
+      ListVirtualMachinesOptions options = accountInDomain("adrian", "6");
+      assertEquals(ImmutableList.of("adrian"), options.buildQueryParameters().get("account"));
+      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("domainid"));
+   }
+
+   public void testName() {
+      ListVirtualMachinesOptions options = new ListVirtualMachinesOptions().id("6");
+      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("id"));
+   }
+
+   public void testNameStatic() {
+      ListVirtualMachinesOptions options = id("6");
+      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("id"));
+   }
+
+   public void testZoneId() {
+      ListVirtualMachinesOptions options = new ListVirtualMachinesOptions().zoneId("6");
+      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("zoneid"));
+   }
+
+   public void testZoneIdStatic() {
+      ListVirtualMachinesOptions options = zoneId("6");
+      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("zoneid"));
+   }
+
+   public void testState() {
+      ListVirtualMachinesOptions options = new ListVirtualMachinesOptions().state("state");
+      assertEquals(ImmutableList.of("state"), options.buildQueryParameters().get("state"));
+   }
+
+   public void testStateStatic() {
+      ListVirtualMachinesOptions options = state("state");
+      assertEquals(ImmutableList.of("state"), options.buildQueryParameters().get("state"));
+   }
+
+   public void testUsingVirtualNetwork() {
+      ListVirtualMachinesOptions options = new ListVirtualMachinesOptions().usesVirtualNetwork(true);
+      assertEquals(ImmutableList.of("true"), options.buildQueryParameters().get("forvirtualnetwork"));
+   }
+
+   public void testUsingVirtualNetworkStatic() {
+      ListVirtualMachinesOptions options = usesVirtualNetwork(true);
+      assertEquals(ImmutableList.of("true"), options.buildQueryParameters().get("forvirtualnetwork"));
+   }
+
+   public void testId() {
+      ListVirtualMachinesOptions options = new ListVirtualMachinesOptions().id("6");
+      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("id"));
+   }
+
+   public void testDomainId() {
+      ListVirtualMachinesOptions options = new ListVirtualMachinesOptions().domainId("6");
+      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("domainid"));
+   }
+
+   public void testIdStatic() {
+      ListVirtualMachinesOptions options = id("6");
+      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("id"));
+   }
+
+   public void testDomainIdStatic() {
+      ListVirtualMachinesOptions options = domainId("6");
+      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("domainid"));
+   }
+
+   public void testTags() {
+      ListVirtualMachinesOptions options = new ListVirtualMachinesOptions().tags(ImmutableMap.of("tag1", "val1", "tag2", "val2"));
+      assertEquals(ImmutableList.of("tag1"), options.buildQueryParameters().get("tags[0].key"));
+      assertEquals(ImmutableList.of("tag2"), options.buildQueryParameters().get("tags[1].key"));
+      assertEquals(ImmutableList.of("val1"), options.buildQueryParameters().get("tags[0].value"));
+      assertEquals(ImmutableList.of("val2"), options.buildQueryParameters().get("tags[1].value"));
+   }
+
+   public void testTagsStatic() {
+      ListVirtualMachinesOptions options = tags(ImmutableMap.of("tag1", "val1", "tag2", "val2"));
+      assertEquals(ImmutableList.of("tag1"), options.buildQueryParameters().get("tags[0].key"));
+      assertEquals(ImmutableList.of("tag2"), options.buildQueryParameters().get("tags[1].key"));
+      assertEquals(ImmutableList.of("val1"), options.buildQueryParameters().get("tags[0].value"));
+      assertEquals(ImmutableList.of("val2"), options.buildQueryParameters().get("tags[1].value"));
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListZonesOptionsTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListZonesOptionsTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListZonesOptionsTest.java
index 17d1146..49ae57e 100644
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListZonesOptionsTest.java
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/ListZonesOptionsTest.java
@@ -16,11 +16,13 @@
  */
 package org.jclouds.cloudstack.options;
 
+import static org.jclouds.cloudstack.options.ListZonesOptions.Builder.tags;
 import static org.jclouds.cloudstack.options.ListZonesOptions.Builder.available;
 import static org.jclouds.cloudstack.options.ListZonesOptions.Builder.domainId;
 import static org.jclouds.cloudstack.options.ListZonesOptions.Builder.id;
 import static org.testng.Assert.assertEquals;
 
+import com.google.common.collect.ImmutableMap;
 import org.testng.annotations.Test;
 
 import com.google.common.collect.ImmutableList;
@@ -60,4 +62,20 @@ public class ListZonesOptionsTest {
       ListZonesOptions options = domainId("6");
       assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("domainid"));
    }
+
+   public void testTags() {
+      ListZonesOptions options = new ListZonesOptions().tags(ImmutableMap.of("tag1", "val1", "tag2", "val2"));
+      assertEquals(ImmutableList.of("tag1"), options.buildQueryParameters().get("tags[0].key"));
+      assertEquals(ImmutableList.of("tag2"), options.buildQueryParameters().get("tags[1].key"));
+      assertEquals(ImmutableList.of("val1"), options.buildQueryParameters().get("tags[0].value"));
+      assertEquals(ImmutableList.of("val2"), options.buildQueryParameters().get("tags[1].value"));
+   }
+
+   public void testTagsStatic() {
+      ListZonesOptions options = tags(ImmutableMap.of("tag1", "val1", "tag2", "val2"));
+      assertEquals(ImmutableList.of("tag1"), options.buildQueryParameters().get("tags[0].key"));
+      assertEquals(ImmutableList.of("tag2"), options.buildQueryParameters().get("tags[1].key"));
+      assertEquals(ImmutableList.of("val1"), options.buildQueryParameters().get("tags[0].value"));
+      assertEquals(ImmutableList.of("val2"), options.buildQueryParameters().get("tags[1].value"));
+   }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/test/java/org/jclouds/cloudstack/parse/ListFirewallRulesResponseTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/parse/ListFirewallRulesResponseTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/parse/ListFirewallRulesResponseTest.java
index 6af9dff..ed3b07b 100644
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/parse/ListFirewallRulesResponseTest.java
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/parse/ListFirewallRulesResponseTest.java
@@ -19,6 +19,7 @@ package org.jclouds.cloudstack.parse;
 import java.util.Set;
 
 import org.jclouds.cloudstack.domain.FirewallRule;
+import org.jclouds.cloudstack.domain.Tag;
 import org.jclouds.json.BaseSetParserTest;
 import org.jclouds.json.config.GsonModule;
 import org.jclouds.rest.annotations.SelectJson;
@@ -59,8 +60,10 @@ public class ListFirewallRulesResponseTest extends BaseSetParserTest<FirewallRul
          FirewallRule.builder().id("2016").protocol(FirewallRule.Protocol.TCP).startPort(22)
             .endPort(22).ipAddressId("2").ipAddress("10.27.27.51").state(FirewallRule.State.ACTIVE).CIDRs(CIDRs).build(),
          FirewallRule.builder().id("10").protocol(FirewallRule.Protocol.TCP).startPort(22)
-            .endPort(22).ipAddressId("8").ipAddress("10.27.27.57").state(FirewallRule.State.ACTIVE).CIDRs(CIDRs).build()
-      );
+            .endPort(22).ipAddressId("8").ipAddress("10.27.27.57").state(FirewallRule.State.ACTIVE).CIDRs(CIDRs)
+            .tags(Tag.builder().account("1").domain("ROOT").domainId("1").key("some-tag").resourceId("10")
+                        .resourceType(Tag.ResourceType.FIREWALL_RULE).value("some-value").build()).build()
+               );
    }
 
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/test/java/org/jclouds/cloudstack/parse/ListIPForwardingRulesResponseTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/parse/ListIPForwardingRulesResponseTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/parse/ListIPForwardingRulesResponseTest.java
index 203c41e..92eee75 100644
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/parse/ListIPForwardingRulesResponseTest.java
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/parse/ListIPForwardingRulesResponseTest.java
@@ -19,6 +19,7 @@ package org.jclouds.cloudstack.parse;
 import java.util.Set;
 
 import org.jclouds.cloudstack.domain.IPForwardingRule;
+import org.jclouds.cloudstack.domain.Tag;
 import org.jclouds.json.BaseSetParserTest;
 import org.jclouds.rest.annotations.SelectJson;
 import org.testng.annotations.Test;
@@ -37,9 +38,11 @@ public class ListIPForwardingRulesResponseTest extends BaseSetParserTest<IPForwa
    @SelectJson("ipforwardingrule")
    public Set<IPForwardingRule> expected() {
       return ImmutableSet.<IPForwardingRule> of(
-         IPForwardingRule.builder().id("66").protocol("tcp").startPort(22).endPort(22).virtualMachineId("58")
-            .virtualMachineDisplayName("i-4-58-VM").virtualMachineName("i-4-58-VM")
-            .IPAddressId("15").IPAddress("10.27.27.64").state("Active").build());
+            IPForwardingRule.builder().id("66").protocol("tcp").startPort(22).endPort(22).virtualMachineId("58")
+                  .virtualMachineDisplayName("i-4-58-VM").virtualMachineName("i-4-58-VM")
+                  .IPAddressId("15").IPAddress("10.27.27.64").state("Active")
+                  .tags(Tag.builder().account("1").domain("ROOT").domainId("1").key("some-tag").resourceId("66")
+                        .resourceType(Tag.ResourceType.PORT_FORWARDING_RULE).value("some-value").build()).build());
    }
 
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/test/java/org/jclouds/cloudstack/parse/ListNetworksResponseTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/parse/ListNetworksResponseTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/parse/ListNetworksResponseTest.java
index 65ed915..ca0c109 100644
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/parse/ListNetworksResponseTest.java
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/parse/ListNetworksResponseTest.java
@@ -22,6 +22,7 @@ import java.util.Set;
 import org.jclouds.cloudstack.domain.GuestIPType;
 import org.jclouds.cloudstack.domain.Network;
 import org.jclouds.cloudstack.domain.NetworkService;
+import org.jclouds.cloudstack.domain.Tag;
 import org.jclouds.cloudstack.domain.TrafficType;
 import org.jclouds.json.BaseSetParserTest;
 import org.jclouds.rest.annotations.SelectJson;
@@ -75,13 +76,17 @@ public class ListNetworksResponseTest extends BaseSetParserTest<Network> {
                               NetworkService.builder().name("Gateway").build(),
                               NetworkService.builder().name("UserData").build(),
                               NetworkService.builder().name("Dhcp").build(),
-                              NetworkService.builder().name("Firewall").capabilities(ImmutableSortedMap.<String, String> naturalOrder()
+                              NetworkService.builder().name("Firewall").capabilities(ImmutableSortedMap.<String, String>naturalOrder()
                                     .put("SupportedSourceNatTypes", "per account").put("StaticNat", "true")
                                     .put("TrafficStatistics", "per public ip").put("PortForwarding", "true")
                                     .put("MultipleIps", "true").put("SupportedProtocols", "tcp,udp").build()).build(),
                               NetworkService.builder().name("Dns").build(),
                               NetworkService.builder().name("Lb").capabilities(ImmutableMap.of("SupportedLbAlgorithms",
-                                    "roundrobin,leastconn,source", "SupportedProtocols", "tcp, udp")).build()))
-                  .networkDomain("cs3cloud.internal").build());
+                                    "roundrobin,leastconn,source", "SupportedProtocols", "tcp, udp")).build()
+                        )
+                  )
+                  .networkDomain("cs3cloud.internal")
+                  .tags(Tag.builder().account("1").domain("ROOT").domainId("1").key("some-tag").resourceId("204")
+                        .resourceType(Tag.ResourceType.NETWORK).value("some-value").build()).build());
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/test/java/org/jclouds/cloudstack/parse/ListPortForwardingRulesResponseTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/parse/ListPortForwardingRulesResponseTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/parse/ListPortForwardingRulesResponseTest.java
index 6356c7d..3038977 100644
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/parse/ListPortForwardingRulesResponseTest.java
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/parse/ListPortForwardingRulesResponseTest.java
@@ -19,6 +19,7 @@ package org.jclouds.cloudstack.parse;
 import java.util.Set;
 
 import org.jclouds.cloudstack.domain.PortForwardingRule;
+import org.jclouds.cloudstack.domain.Tag;
 import org.jclouds.json.BaseSetParserTest;
 import org.jclouds.json.config.GsonModule;
 import org.jclouds.rest.annotations.SelectJson;
@@ -54,12 +55,14 @@ public class ListPortForwardingRulesResponseTest extends BaseSetParserTest<PortF
    public Set<PortForwardingRule> expected() {
       Set<String> cidrs = ImmutableSet.of("0.0.0.0/1", "128.0.0.0/1");
       return ImmutableSet.<PortForwardingRule> of(
-         PortForwardingRule.builder().id("15").privatePort(22).protocol(PortForwardingRule.Protocol.TCP)
-            .publicPort(2022).virtualMachineId("3").virtualMachineName("i-3-3-VM").IPAddressId("3")
-            .IPAddress("72.52.126.32").state(PortForwardingRule.State.ACTIVE).CIDRs(cidrs).build(),
-         PortForwardingRule.builder().id("18").privatePort(22).protocol(PortForwardingRule.Protocol.TCP)
-            .publicPort(22).virtualMachineId("89").virtualMachineName("i-3-89-VM").IPAddressId("34")
-            .IPAddress("72.52.126.63").state(PortForwardingRule.State.ACTIVE).build());
+            PortForwardingRule.builder().id("15").privatePort(22).protocol(PortForwardingRule.Protocol.TCP)
+                  .publicPort(2022).virtualMachineId("3").virtualMachineName("i-3-3-VM").IPAddressId("3")
+                  .IPAddress("72.52.126.32").state(PortForwardingRule.State.ACTIVE)
+                  .CIDRs(cidrs).tags(Tag.builder().account("1").domain("ROOT").domainId("1").key("some-tag").resourceId("15")
+                  .resourceType(Tag.ResourceType.PORT_FORWARDING_RULE).value("some-value").build()).build(),
+            PortForwardingRule.builder().id("18").privatePort(22).protocol(PortForwardingRule.Protocol.TCP)
+                  .publicPort(22).virtualMachineId("89").virtualMachineName("i-3-89-VM").IPAddressId("34")
+                  .IPAddress("72.52.126.63").state(PortForwardingRule.State.ACTIVE).build());
    }
 
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/test/java/org/jclouds/cloudstack/parse/ListPublicIPAddressesResponseTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/parse/ListPublicIPAddressesResponseTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/parse/ListPublicIPAddressesResponseTest.java
index a9547d4..a6cfaf8 100644
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/parse/ListPublicIPAddressesResponseTest.java
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/parse/ListPublicIPAddressesResponseTest.java
@@ -19,6 +19,7 @@ package org.jclouds.cloudstack.parse;
 import java.util.Set;
 
 import org.jclouds.cloudstack.domain.PublicIPAddress;
+import org.jclouds.cloudstack.domain.Tag;
 import org.jclouds.date.internal.SimpleDateFormatDateService;
 import org.jclouds.json.BaseSetParserTest;
 import org.jclouds.rest.annotations.SelectJson;
@@ -41,7 +42,17 @@ public class ListPublicIPAddressesResponseTest extends BaseSetParserTest<PublicI
             .allocated(new SimpleDateFormatDateService().iso8601SecondsDateParse("2011-02-19T21:15:01-0800")).zoneId("1")
             .zoneName("San Jose 1").isSourceNAT(false).account("adrian").domainId("1").domain("ROOT")
             .usesVirtualNetwork(true).isStaticNAT(false).associatedNetworkId("204").networkId("200")
-            .state(PublicIPAddress.State.ALLOCATED).build());
+            .state(PublicIPAddress.State.ALLOCATED)
+            .tags(Tag.builder()
+                  .account("adrian")
+                  .domain("ROOT")
+                  .domainId("1")
+                  .key("some-tag")
+                  .resourceId("30")
+                  .resourceType(Tag.ResourceType.PUBLIC_IP_ADDRESS)
+                  .value("some-value")
+                  .build())
+            .build());
    }
 
 }