You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by ad...@apache.org on 2014/10/20 21:55:54 UTC

[04/11] git commit: Cleanup output-only Deployment object.

Cleanup output-only Deployment object.


Project: http://git-wip-us.apache.org/repos/asf/jclouds-labs/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds-labs/commit/ece9a967
Tree: http://git-wip-us.apache.org/repos/asf/jclouds-labs/tree/ece9a967
Diff: http://git-wip-us.apache.org/repos/asf/jclouds-labs/diff/ece9a967

Branch: refs/heads/master
Commit: ece9a96716a6575a8881e585437e6d27f054a872
Parents: ff9d3ce
Author: Adrian Cole <ad...@gmail.com>
Authored: Thu Oct 16 09:01:39 2014 -0700
Committer: Adrian Cole <ac...@twitter.com>
Committed: Mon Oct 20 13:26:53 2014 -0400

----------------------------------------------------------------------
 .../BindDeploymentParamsToXmlPayload.java       |  11 +-
 .../jclouds/azurecompute/domain/Deployment.java | 343 +++++++------------
 .../azurecompute/domain/DeploymentParams.java   |   2 +-
 .../azurecompute/domain/DeploymentSlot.java     |  42 ---
 .../azurecompute/domain/DeploymentStatus.java   |  43 ---
 .../azurecompute/domain/InstanceStatus.java     | 155 ---------
 .../jclouds/azurecompute/domain/RoleSize.java   |  23 +-
 .../azurecompute/xml/DeploymentHandler.java     | 172 ++++++----
 .../features/DeploymentApiMockTest.java         |  20 +-
 .../azurecompute/parse/GetDeploymentTest.java   |  62 ----
 .../azurecompute/xml/DeploymentHandlerTest.java |  86 +++++
 azurecompute/src/test/resources/deployment.xml  | 126 +++----
 12 files changed, 398 insertions(+), 687 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/ece9a967/azurecompute/src/main/java/org/jclouds/azurecompute/binders/BindDeploymentParamsToXmlPayload.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/binders/BindDeploymentParamsToXmlPayload.java b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/BindDeploymentParamsToXmlPayload.java
index 1c127f1..22aa011 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/binders/BindDeploymentParamsToXmlPayload.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/BindDeploymentParamsToXmlPayload.java
@@ -16,15 +16,20 @@
  */
 package org.jclouds.azurecompute.binders;
 
-import com.google.common.base.Throwables;
-import com.jamesmurty.utils.XMLBuilder;
+import static com.google.common.base.CaseFormat.UPPER_CAMEL;
+import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE;
+
 import javax.inject.Singleton;
+
 import org.jclouds.azurecompute.domain.DeploymentParams;
 import org.jclouds.azurecompute.domain.InputEndpoint;
 import org.jclouds.azurecompute.domain.OSType;
 import org.jclouds.http.HttpRequest;
 import org.jclouds.rest.Binder;
 
+import com.google.common.base.Throwables;
+import com.jamesmurty.utils.XMLBuilder;
+
 @Singleton
 public class BindDeploymentParamsToXmlPayload implements Binder {
 
@@ -95,7 +100,7 @@ public class BindDeploymentParamsToXmlPayload implements Binder {
             .e("SourceImageName").t(params.getSourceImageName()).up()
             .e("OS").t("Linux").up()
             .up() //OSVirtualHardDisk
-            .e("RoleSize").t(params.getSize().value()).up()
+            .e("RoleSize").t(UPPER_UNDERSCORE.to(UPPER_CAMEL, params.getSize().name())).up()
             .up() //Role
             .up(); //RoleList
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/ece9a967/azurecompute/src/main/java/org/jclouds/azurecompute/domain/Deployment.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/Deployment.java b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/Deployment.java
index 6bd179b..7a6986f 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/Deployment.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/Deployment.java
@@ -16,147 +16,73 @@
  */
 package org.jclouds.azurecompute.domain;
 
-import java.net.URI;
+import static com.google.common.base.Objects.equal;
+import static com.google.common.base.Objects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
 
-public class Deployment {
+import org.jclouds.javax.annotation.Nullable;
 
-   public static Builder builder() {
-      return new Builder();
-   }
-
-   public static class Builder {
-      private String deploymentName;
-      private DeploymentSlot deploymentSlot;
-      private DeploymentStatus deploymentStatus;
-      private String deploymentLabel;
-      private URI deploymentURL;
-      private String roleName;
-      private String instanceName;
-      private InstanceStatus instanceStatus;
-      private String instanceStateDetails;
-      private String instanceErrorCode;
-      private RoleSize instanceSize;
-      private String privateIpAddress;
-      private String publicIpAddress;
-
-      public Builder deploymentName(final String deploymentName) {
-         this.deploymentName = deploymentName;
-         return this;
-      }
-
-      public Builder deploymentSlot(final DeploymentSlot deploymentSlot) {
-         this.deploymentSlot = deploymentSlot;
-         return this;
-      }
-
-      public Builder deploymentStatus(final DeploymentStatus deploymentStatus) {
-         this.deploymentStatus = deploymentStatus;
-         return this;
-      }
+import com.google.common.base.Objects;
 
-      public Builder deploymentLabel(final String deploymentLabel) {
-         this.deploymentLabel = deploymentLabel;
-         return this;
-      }
-
-      public Builder deploymentURL(final URI deploymentURL) {
-         this.deploymentURL = deploymentURL;
-         return this;
-      }
-
-      public Builder instanceSize(final RoleSize instanceSize) {
-         this.instanceSize = instanceSize;
-         return this;
-      }
-
-      public Builder instanceName(final String instanceName) {
-         this.instanceName = instanceName;
-         return this;
-      }
+public final class Deployment {
 
-      public Builder instanceStatus(final InstanceStatus instanceStatus) {
-         this.instanceStatus = instanceStatus;
-         return this;
-      }
-
-      public Builder instanceStateDetails(final String instanceStateDetails) {
-         this.instanceStateDetails = instanceStateDetails;
-         return this;
-      }
-
-      public Builder instanceErrorCode(final String instanceErrorCode) {
-         this.instanceErrorCode = instanceErrorCode;
-         return this;
-      }
-
-      public Builder privateIpAddress(final String privateIpAddress) {
-         this.privateIpAddress = privateIpAddress;
-         return this;
-      }
-
-      public Builder publicIpAddress(final String publicIpAddress) {
-         this.publicIpAddress = publicIpAddress;
-         return this;
-      }
-
-      public Builder roleName(final String roleName) {
-         this.roleName = roleName;
-         return this;
-      }
+   public enum Slot {
+      PRODUCTION, STAGING,
+      UNRECOGNIZED;
+   }
 
-      public Deployment build() {
-         return new Deployment(deploymentName, deploymentSlot, deploymentStatus, deploymentLabel, deploymentURL,
-               roleName, instanceName, instanceStatus, instanceStateDetails, instanceErrorCode, instanceSize,
-               privateIpAddress, publicIpAddress);
-      }
+   public enum Status {
+      RUNNING, SUSPENDED, RUNNING_TRANSITIONING, SUSPENDED_TRANSITIONING, STARTING, SUSPENDING, DEPLOYING, DELETING,
+      UNRECOGNIZED;
+   }
 
+   public enum InstanceStatus {
+      CREATING_VM, STARTING_VM, CREATING_ROLE, STARTING_ROLE, READY_ROLE, BUSY_ROLE, STOPPING_ROLE, STOPPING_VM,
+      DELETING_VM, STOPPED_VM, RESTARTING_ROLE, CYCLING_ROLE, FAILED_STARTING_ROLE, FAILED_STARTING_VM, UNRESPONSIVE_ROLE,
+      STOPPED_DEALLOCATED, PREPARING,
+      /** Unknown to Azure. */
+      UNKNOWN,
+      /** Not parsable into one of the above. */
+      UNRECOGNIZED,
    }
 
-   /**
-    * The user-supplied name for this deployment.
-    */
-   private final String deploymentName;
+   /** The user-supplied name for this deployment. */
+   public String name() {
+      return name;
+   }
 
-   /**
-    * The environment to which the hosted service is deployed, either staging
-    * or production.
-    */
-   private final DeploymentSlot deploymentSlot;
+   /** The environment to which the hosted service is deployed. */
+   public Slot slot() {
+      return slot;
+   }
 
-   /**
-    * The status of the deployment.
-    */
-   private final DeploymentStatus deploymentStatus;
+   public Status status() {
+      return status;
+   }
 
    /**
     * The user-supplied name of the deployment returned as a base-64 encoded
     * string. This name can be used identify the deployment for your tracking
     * purposes.
     */
-   private final String deploymentLabel;
-
-   /**
-    * The URL used to access the hosted service. For example, if the service
-    * name is MyService you could access the access the service by calling:
-    * http://MyService.cloudapp.net
-    */
-   private final URI deploymentURL;
+   public String label() {
+      return label;
+   }
 
-   /**
-    * Specifies the name for the virtual machine. The name must be unique
-    * within Windows Azure.
-    */
-   private final String roleName;
+   /** Specifies the name for the virtual machine. The name must be unique within Windows Azure. */
+   public String virtualMachineName() {
+      return virtualMachineName;
+   }
 
-   /**
-    * The name of the specific role instance (if any).
-    */
-   private final String instanceName;
+   /** The name of the specific role instance (if any). */
+   @Nullable public String instanceName() {
+      return instanceName;
+   }
 
-   /**
-    * The current status of this instance.
-    */
-   private final InstanceStatus instanceStatus;
+   /** The current status of this instance. */
+   public InstanceStatus instanceStatus() {
+      return instanceStatus;
+   }
 
    /**
     * The instance state is returned as an English human-readable string that,
@@ -166,7 +92,9 @@ public class Deployment {
     * For example, when the instance is first being initialized a
     * "Preparing Windows for first use." could be returned.
     */
-   private final String instanceStateDetails;
+   @Nullable public String instanceStateDetails() {
+      return instanceStateDetails;
+   }
 
    /**
     * Error code of the latest role or VM start
@@ -187,123 +115,102 @@ public class Deployment {
     * For web and worker roles this field returns an error code that can be provided to Windows Azure support to assist
     * in resolution of errors. Typically this field will be empty.
     */
-   private final String instanceErrorCode;
-
-   /**
-    * The size of the role instance
-    */
-   private final RoleSize instanceSize;
-   private final String privateIpAddress;
-   private final String publicIpAddress;
-
-   public Deployment(String deploymentName, DeploymentSlot deploymentSlot, DeploymentStatus deploymentStatus,
-         String deploymentLabel, URI deploymentURL, String roleName, String instanceName, InstanceStatus instanceStatus,
-         String instanceStateDetails, String instanceErrorCode, RoleSize instanceSize, String privateIpAddress,
-         String publicIpAddress) {
-      this.deploymentName = deploymentName;
-      this.deploymentSlot = deploymentSlot;
-      this.deploymentStatus = deploymentStatus;
-      this.deploymentLabel = deploymentLabel;
-      this.deploymentURL = deploymentURL;
-      this.roleName = roleName;
-      this.instanceName = instanceName;
-      this.instanceStatus = instanceStatus;
-      this.instanceStateDetails = instanceStateDetails;
-      this.instanceErrorCode = instanceErrorCode;
-      this.instanceSize = instanceSize;
-      this.privateIpAddress = privateIpAddress;
-      this.publicIpAddress = publicIpAddress;
-   }
-
-   public String getDeploymentName() {
-      return deploymentName;
-   }
-
-   public DeploymentSlot getDeploymentSlot() {
-      return deploymentSlot;
-   }
-
-   public DeploymentStatus getDeploymentStatus() {
-      return deploymentStatus;
-   }
-
-   public String getDeploymentLabel() {
-      return deploymentLabel;
-   }
-
-   public URI getDeploymentURL() {
-      return deploymentURL;
-   }
-
-   public String getRoleName() {
-      return roleName;
-   }
-
-   public String getInstanceName() {
-      return instanceName;
-   }
-
-   public InstanceStatus getInstanceStatus() {
-      return instanceStatus;
-   }
-
-   public String getInstanceStateDetails() {
-      return instanceStateDetails;
-   }
-
-   public String getInstanceErrorCode() {
+   @Nullable public String instanceErrorCode() {
       return instanceErrorCode;
    }
 
-   public RoleSize getInstanceSize() {
+   public RoleSize instanceSize() {
       return instanceSize;
    }
 
-   public String getPrivateIpAddress() {
+   public String privateIpAddress() {
       return privateIpAddress;
    }
 
-   public String getPublicIpAddress() {
+   public String publicIpAddress() {
       return publicIpAddress;
    }
 
-   @Override
-   public int hashCode() {
-      final int prime = 31;
-      int result = 1;
-      result = prime * result + ((deploymentName == null) ? 0 : deploymentName.hashCode());
-      return result;
+   public static Deployment create(String name, Slot slot, Status status, String label, String virtualMachineName,
+         String instanceName, InstanceStatus instanceStatus, String instanceStateDetails, String instanceErrorCode,
+         RoleSize instanceSize, String privateIpAddress, String publicIpAddress) {
+      return new Deployment(name, slot, status, label, virtualMachineName, instanceName, instanceStatus, instanceStateDetails,
+            instanceErrorCode, instanceSize, privateIpAddress, publicIpAddress);
    }
 
+   // TODO: Remove from here down with @AutoValue.
+   private Deployment(String name, Slot slot, Status status, String label, String virtualMachineName, String instanceName,
+            InstanceStatus instanceStatus, String instanceStateDetails, String instanceErrorCode, RoleSize instanceSize,
+            String privateIpAddress, String publicIpAddress) {
+      this.name = checkNotNull(name, "name");
+      this.slot = checkNotNull(slot, "slot");
+      this.status = checkNotNull(status, "status");
+      this.label = checkNotNull(label, "label");
+      this.virtualMachineName = checkNotNull(virtualMachineName, "virtualMachineName");
+      this.instanceName = instanceName;
+      this.instanceStatus = checkNotNull(instanceStatus, "instanceStatus");
+      this.instanceStateDetails = instanceStateDetails;
+      this.instanceErrorCode = instanceErrorCode;
+      this.instanceSize = checkNotNull(instanceSize, "instanceSize");
+      this.privateIpAddress = checkNotNull(privateIpAddress, "privateIpAddress");
+      this.publicIpAddress = checkNotNull(publicIpAddress, "publicIpAddress");
+   }
+
+   private final String name;
+   private final Slot slot;
+   private final Status status;
+   private final String label;
+   private final String virtualMachineName;
+   private final String instanceName;
+   private final InstanceStatus instanceStatus;
+   private final String instanceStateDetails;
+   private final String instanceErrorCode;
+   private final RoleSize instanceSize;
+   private final String privateIpAddress;
+   private final String publicIpAddress;
+
    @Override
-   public boolean equals(Object obj) {
-      if (this == obj) {
+   public boolean equals(Object object) {
+      if (this == object) {
          return true;
       }
-      if (obj == null) {
-         return false;
-      }
-      if (getClass() != obj.getClass()) {
-         return false;
-      }
-      Deployment other = (Deployment) obj;
-      if (deploymentName == null) {
-         if (other.deploymentName != null) {
-            return false;
-         }
-      } else if (!deploymentName.equals(other.deploymentName)) {
+      if (object instanceof Deployment) {
+         Deployment that = Deployment.class.cast(object);
+         return equal(name, that.name)
+               && equal(slot, that.slot)
+               && equal(label, that.label)
+               && equal(virtualMachineName, that.virtualMachineName)
+               && equal(instanceName, that.instanceName)
+               && equal(instanceStatus, that.instanceStatus)
+               && equal(instanceStateDetails, that.instanceStateDetails)
+               && equal(instanceErrorCode, that.instanceErrorCode)
+               && equal(instanceSize, that.instanceSize)
+               && equal(privateIpAddress, that.privateIpAddress)
+               && equal(publicIpAddress, that.publicIpAddress);
+      } else {
          return false;
       }
-      return true;
+   }
+
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(name, slot, label, virtualMachineName, instanceName, instanceStatus, instanceStateDetails,
+            instanceErrorCode, instanceSize, privateIpAddress, publicIpAddress);
    }
 
    @Override
    public String toString() {
-      return "Deployment [deploymentName=" + deploymentName + ", deploymentSlot=" + deploymentSlot
-            + ", deploymentStatus=" + deploymentStatus + ", deploymentLabel=" + deploymentLabel + ", deploymentURL="
-            + deploymentURL + ", roleName=" + roleName + ", instanceName=" + instanceName + ", instanceStatus="
-            + instanceStatus + ", instanceStateDetails=" + instanceStateDetails + ", instanceErrorCode="
-            + instanceErrorCode + ", instanceSize=" + instanceSize + ", privateIpAddress=" + privateIpAddress
-            + ", publicIpAddress=" + publicIpAddress + "]";
+      return toStringHelper(this)
+            .add("name", name)
+            .add("slot", slot)
+            .add("label", label)
+            .add("virtualMachineName", virtualMachineName)
+            .add("instanceName", instanceName)
+            .add("instanceStatus", instanceStatus)
+            .add("instanceStateDetails", instanceStateDetails)
+            .add("instanceErrorCode", instanceErrorCode)
+            .add("instanceSize", instanceSize)
+            .add("privateIpAddress", privateIpAddress)
+            .add("publicIpAddress", publicIpAddress).toString();
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/ece9a967/azurecompute/src/main/java/org/jclouds/azurecompute/domain/DeploymentParams.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/DeploymentParams.java b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/DeploymentParams.java
index 9ee4423..54325ae 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/DeploymentParams.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/DeploymentParams.java
@@ -94,7 +94,7 @@ public class DeploymentParams {
       }
 
       public Builder fromDeploymentParams(DeploymentParams in) {
-         // TODO Since the roleName should be unique, is it a good idea to copy it ?
+         // TODO Since the virtualMachineName should be unique, is it a good idea to copy it ?
          return this.name(in.getName()).sourceImageName(in.getSourceImageName()).username(in.getUsername())
                .password(in.getPassword()).size(in.getSize());
       }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/ece9a967/azurecompute/src/main/java/org/jclouds/azurecompute/domain/DeploymentSlot.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/DeploymentSlot.java b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/DeploymentSlot.java
deleted file mode 100644
index 2e76b88..0000000
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/DeploymentSlot.java
+++ /dev/null
@@ -1,42 +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.azurecompute.domain;
-
-import com.google.common.base.CaseFormat;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-public enum DeploymentSlot {
-   PRODUCTION, STAGING;
-
-   public String value() {
-      return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name());
-   }
-
-   @Override
-   public String toString() {
-      return value();
-   }
-
-   public static DeploymentSlot fromValue(String type) {
-      try {
-         return valueOf(CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(type, "type")));
-      } catch (IllegalArgumentException e) {
-         return null;
-      }
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/ece9a967/azurecompute/src/main/java/org/jclouds/azurecompute/domain/DeploymentStatus.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/DeploymentStatus.java b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/DeploymentStatus.java
deleted file mode 100644
index eb34aa5..0000000
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/DeploymentStatus.java
+++ /dev/null
@@ -1,43 +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.azurecompute.domain;
-
-import com.google.common.base.CaseFormat;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-public enum DeploymentStatus {
-	RUNNING, SUSPENDED, RUNNING_TRANSITIONING, SUSPENDED_TRANSITIONING, STARTING, SUSPENDING, DEPLOYING, DELETING;
-
-	public String value() {
-		return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name());
-	}
-
-	@Override
-	public String toString() {
-		return value();
-	}
-
-	public static DeploymentStatus fromValue(String type) {
-		try {
-			return valueOf(CaseFormat.UPPER_CAMEL.to(
-					CaseFormat.UPPER_UNDERSCORE, checkNotNull(type, "type")));
-		} catch (IllegalArgumentException e) {
-			return null;
-		}
-	}
-}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/ece9a967/azurecompute/src/main/java/org/jclouds/azurecompute/domain/InstanceStatus.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/InstanceStatus.java b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/InstanceStatus.java
deleted file mode 100644
index 51b5d24..0000000
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/InstanceStatus.java
+++ /dev/null
@@ -1,155 +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.azurecompute.domain;
-
-import com.google.common.base.CaseFormat;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-public enum InstanceStatus {
-
-	/**
-	 * The role state is currently unknown. The state should automatically be
-	 * resolved once the role state is detected, so no action is required.
-	 */
-	ROLE_STATE_UNKNOWN,
-
-	/**
-	 * The host agent is currently creating resources for the Virtual Machine
-	 * (VM).
-	 */
-	CREATING_V_M,
-
-	/**
-	 * The host agent is starting the Virtual Machine.
-	 */
-	STARTING_V_M,
-
-	/**
-	 * Windows Azure is creating resources for the role.
-	 */
-	CREATING_ROLE,
-
-	/**
-	 * Windows Azure is starting the role.
-	 */
-	STARTING_ROLE,
-
-	/**
-	 * The role instance has started and is ready to be used.
-	 */
-	READY_ROLE,
-
-	/**
-	 * The role instance is unavailable for requests. This state is usually
-	 * generated while the role is being created or stopped.
-	 */
-	BUSY_ROLE,
-
-	/**
-	 * Windows Azure is stopping the role.
-	 */
-	STOPPING_ROLE,
-
-	/**
-	 * The host agent is stopping the Virtual Machine. This status also
-	 * indicates that the role has already been stopped.
-	 */
-	STOPPING_V_M,
-
-	/**
-	 * The Virtual Machine is being deleted by the host agent.
-	 */
-	DELETING_V_M,
-
-	/**
-	 * The Virtual Machine is not running. This is the final state of the
-	 * shutdown process, and no other status messages should be received after
-	 * StoppedVM.
-	 */
-	STOPPED_V_M,
-
-	/**
-	 * The role has unexpectedly stopped or has failed to start. This status
-	 * indicates that there is a problem with the role that is causing it to
-	 * crash or preventing it from starting, and must be corrected before the
-	 * role can be started. The InstanceStateDetails and InstanceErrorCode
-	 * fields can hold information about the role error that caused this state,
-	 * which may be useful for identifying and debugging the problem.
-	 */
-	RESTARTING_ROLE,
-
-	/**
-	 * The role has continually crashed after being started by Windows Azure.
-	 * This status indicates that there is a problem with the role that prevents
-	 * it from starting, and may be generated after the StartingRole even
-	 * ReadyRole statuses are received. The problem in the role must be found
-	 * and corrected before the role can be started. The InstanceStateDetails
-	 * and InstanceErrorCode fields can hold information about the role error
-	 * that caused this state, which may be useful for identifying and debugging
-	 * the problem.
-	 */
-	CYCLING_ROLE,
-
-	/**
-	 * The role has continually failed to start. This status indicates that
-	 * there is a problem with the role that prevents it from starting, and may
-	 * be generated after the process returns StartingRole. The problem in the
-	 * role must be found and corrected before the role can be started. The
-	 * InstanceStateDetails and InstanceErrorCode fields can hold information
-	 * about the role error that caused this state, which may be useful for
-	 * identifying and debugging the problem.
-	 */
-	FAILED_STARTING_ROLE,
-
-	/**
-	 * A Windows Azure or container error is preventing the Virtual Machine from
-	 * starting. This status is generated by Windows Azure, and does not
-	 * indicate an error with the role. It may be generated after the
-	 * StartingRole state.
-	 */
-	FAILED_STARTING_V_M,
-
-	/**
-	 * The role has timed out before receiving a status message and is not
-	 * responding to requests.
-	 */
-	UNRESPONSIVE_ROLE,
-
-	/**
-	 * UNDOCUMENTED BY AZURE
-	 */
-	PROVISIONING;
-
-	public String value() {
-		return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name());
-	}
-
-	@Override
-	public String toString() {
-		return value();
-	}
-
-	public static InstanceStatus fromValue(String type) {
-		try {
-			return valueOf(CaseFormat.UPPER_CAMEL.to(
-					CaseFormat.UPPER_UNDERSCORE, checkNotNull(type, "type")));
-		} catch (IllegalArgumentException e) {
-			return ROLE_STATE_UNKNOWN;
-		}
-	}
-}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/ece9a967/azurecompute/src/main/java/org/jclouds/azurecompute/domain/RoleSize.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/RoleSize.java b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/RoleSize.java
index 6839091..5e2aa8b 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/RoleSize.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/RoleSize.java
@@ -16,27 +16,6 @@
  */
 package org.jclouds.azurecompute.domain;
 
-import com.google.common.base.CaseFormat;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
 public enum RoleSize {
-   EXTRA_SMALL, SMALL, MEDIUM, LARGE, EXTRA_LARGE;
-
-   public String value() {
-      return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name());
-   }
-
-   @Override
-   public String toString() {
-      return value();
-   }
-
-   public static RoleSize fromValue(String type) {
-      try {
-         return valueOf(CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(type, "type")));
-      } catch (IllegalArgumentException e) {
-         return null;
-      }
-   }
+   EXTRA_SMALL, SMALL, MEDIUM, LARGE, EXTRA_LARGE, UNRECOGNIZED;
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/ece9a967/azurecompute/src/main/java/org/jclouds/azurecompute/xml/DeploymentHandler.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/xml/DeploymentHandler.java b/azurecompute/src/main/java/org/jclouds/azurecompute/xml/DeploymentHandler.java
index 8d92c72..50e8294 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/xml/DeploymentHandler.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/xml/DeploymentHandler.java
@@ -16,100 +16,130 @@
  */
 package org.jclouds.azurecompute.xml;
 
-import com.google.common.collect.Lists;
-import java.net.URI;
-import java.util.List;
+import static com.google.common.base.CaseFormat.UPPER_CAMEL;
+import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE;
+import static com.google.common.base.Charsets.UTF_8;
+import static com.google.common.io.BaseEncoding.base64;
+import static org.jclouds.util.SaxUtils.currentOrNull;
+
 import org.jclouds.azurecompute.domain.Deployment;
-import org.jclouds.azurecompute.domain.DeploymentSlot;
-import org.jclouds.azurecompute.domain.DeploymentStatus;
-import org.jclouds.azurecompute.domain.InstanceStatus;
+import org.jclouds.azurecompute.domain.Deployment.InstanceStatus;
+import org.jclouds.azurecompute.domain.Deployment.Slot;
+import org.jclouds.azurecompute.domain.Deployment.Status;
 import org.jclouds.azurecompute.domain.RoleSize;
 import org.jclouds.http.functions.ParseSax;
 import org.xml.sax.Attributes;
-import org.xml.sax.SAXException;
 
-import static com.google.common.base.Charsets.UTF_8;
-import static com.google.common.io.BaseEncoding.base64;
-import static org.jclouds.util.SaxUtils.currentOrNull;
-import static org.jclouds.util.SaxUtils.equalsOrSuffix;
+import com.google.common.annotations.VisibleForTesting;
 
 /**
- * @see <a href="http://msdn.microsoft.com/en-us/library/ee460804" >api</a>
+ * @see <a href="http://msdn.microsoft.com/en-us/library/ee460804" >Response body description</a>.
  */
-public class DeploymentHandler extends ParseSax.HandlerForGeneratedRequestWithResult<Deployment> {
+public final class DeploymentHandler extends ParseSax.HandlerForGeneratedRequestWithResult<Deployment> {
+   private String name;
+   private Slot slot;
+   private Status status;
+   private String label;
+   private String virtualMachineName;
+   private String instanceName;
+   private InstanceStatus instanceStatus;
+   private String instanceStateDetails;
+   private String instanceErrorCode;
+   private RoleSize instanceSize;
+   private String privateIpAddress;
+   private String publicIpAddress;
 
-   private List<String> elements = Lists.newArrayList();
-   private StringBuilder currentText = new StringBuilder();
-   private Deployment.Builder builder = Deployment.builder();
+   private int depth;
+   private final StringBuilder currentText = new StringBuilder();
 
-   @Override
-   public Deployment getResult() {
-      try {
-         return builder.build();
-      } finally {
-         builder = Deployment.builder();
-      }
+   @Override public Deployment getResult() { // Fields don't need to be reset as this isn't used in a loop.
+      return Deployment.create(name, slot, status, label, virtualMachineName, instanceName, instanceStatus, //
+            instanceStateDetails, instanceErrorCode, instanceSize, privateIpAddress, publicIpAddress);
    }
 
-   @Override
-   public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
-      elements.add(qName);
+   @Override public void startElement(String url, String name, String qName, Attributes attributes) {
+      depth++;
    }
 
-   @Override
-   public void endElement(String uri, String name, String qName) throws SAXException {
-      if (equalsOrSuffix(qName, "Name") && "Deployment".equals(elements.get(elements.size() - 2))) {
-         builder.deploymentName(currentOrNull(currentText));
-      } else if (equalsOrSuffix(qName, "DeploymentSlot")) {
-         final String dpltSlot = currentOrNull(currentText);
-         if (dpltSlot != null) {
-            builder.deploymentSlot(DeploymentSlot.fromValue(dpltSlot));
+   @Override public void endElement(String ignoredUri, String ignoredName, String qName) {
+      if (qName.equals("Name") && depth == 2) {
+         name = currentOrNull(currentText);
+      } else if (qName.equals("DeploymentSlot")) {
+         String slotText = currentOrNull(currentText);
+         if (slotText != null) {
+            slot = parseSlot(slotText);
          }
-      } else if (equalsOrSuffix(qName, "Status")) {
-         String deploymentStatus = currentOrNull(currentText);
-         if (deploymentStatus != null) {
-            builder.deploymentStatus(DeploymentStatus.fromValue(deploymentStatus));
+      } else if (qName.equals("Status")) {
+         String statusText = currentOrNull(currentText);
+         if (statusText != null) {
+            status = parseStatus(statusText);
          }
-      } else if (equalsOrSuffix(qName, "Label")) {
-         String label = currentOrNull(currentText);
-         if (label != null) {
-            builder.deploymentLabel(new String(base64().decode(label), UTF_8));
+      } else if (qName.equals("Label")) {
+         String labelText = currentOrNull(currentText);
+         if (labelText != null) {
+            label = new String(base64().decode(labelText), UTF_8);
          }
-      } else if (equalsOrSuffix(qName, "Url")) {
-         final String url = currentOrNull(currentText);
-         if (url != null) {
-            builder.deploymentURL(URI.create(url));
+      } else if (qName.equals("RoleName")) {
+         virtualMachineName = currentOrNull(currentText);
+      } else if (qName.equals("InstanceName")) {
+         instanceName = currentOrNull(currentText);
+      } else if (qName.equals("InstanceStatus")) {
+         String instanceStatusText = currentOrNull(currentText);
+         if (instanceStatusText != null) {
+            instanceStatus = parseInstanceStatus(instanceStatusText);
          }
-      } else if (equalsOrSuffix(qName, "RoleName")) {
-         builder.roleName(currentOrNull(currentText));
-      } else if (equalsOrSuffix(qName, "InstanceName")) {
-         builder.instanceName(currentOrNull(currentText));
-      } else if (equalsOrSuffix(qName, "InstanceStatus")) {
-         String instanceStatus = currentOrNull(currentText);
-         if (instanceStatus != null) {
-            builder.instanceStatus(InstanceStatus.fromValue(instanceStatus));
+      } else if (qName.equals("InstanceStateDetails")) {
+         instanceStateDetails = currentOrNull(currentText);
+      } else if (qName.equals("InstanceErrorCode")) {
+         instanceErrorCode = currentOrNull(currentText);
+      } else if (qName.equals("InstanceSize")) {
+         String instanceSizeText = currentOrNull(currentText);
+         if (instanceSizeText != null) {
+            instanceSize = parseRoleSize(instanceSizeText);
          }
-      } else if (equalsOrSuffix(qName, "InstanceStateDetails")) {
-         builder.instanceStateDetails(currentOrNull(currentText));
-      } else if (equalsOrSuffix(qName, "InstanceErrorCode")) {
-         builder.instanceErrorCode(currentOrNull(currentText));
-      } else if (equalsOrSuffix(qName, "InstanceSize")) {
-         String instanceSize = currentOrNull(currentText);
-         if (instanceSize != null) {
-            builder.instanceSize(RoleSize.fromValue(instanceSize));
-         }
-      } else if (equalsOrSuffix(qName, "IpAddress")) {
-         builder.privateIpAddress(currentOrNull(currentText));
-      } else if (equalsOrSuffix(qName, "Vip")) {
-         builder.publicIpAddress(currentOrNull(currentText));
+      } else if (qName.equals("IpAddress")) {
+         privateIpAddress = currentOrNull(currentText);
+      } else if (qName.equals("Vip")) {
+         publicIpAddress = currentOrNull(currentText);
       }
-
       currentText.setLength(0);
-      elements.remove(elements.size() - 1);
+      depth--;
    }
 
-   @Override
-   public void characters(char ch[], int start, int length) {
+   @Override public void characters(char ch[], int start, int length) {
       currentText.append(ch, start, length);
    }
+
+   private static Status parseStatus(String status) {
+      try {
+         return Status.valueOf(UPPER_CAMEL.to(UPPER_UNDERSCORE, status));
+      } catch (IllegalArgumentException e) {
+         return Status.UNRECOGNIZED;
+      }
+   }
+
+   private static Slot parseSlot(String slot) {
+      try {
+         return Slot.valueOf(UPPER_CAMEL.to(UPPER_UNDERSCORE, slot));
+      } catch (IllegalArgumentException e) {
+         return Slot.UNRECOGNIZED;
+      }
+   }
+
+   @VisibleForTesting static InstanceStatus parseInstanceStatus(String instanceStatus) {
+      try {
+         // Azure isn't exactly upper-camel, as some states end in VM, not Vm.
+         return InstanceStatus.valueOf(UPPER_CAMEL.to(UPPER_UNDERSCORE, instanceStatus).replace("V_M", "VM"));
+      } catch (IllegalArgumentException e) {
+         return InstanceStatus.UNRECOGNIZED;
+      }
+   }
+
+   private static RoleSize parseRoleSize(String roleSize) {
+      try {
+         return RoleSize.valueOf(UPPER_CAMEL.to(UPPER_UNDERSCORE, roleSize));
+      } catch (IllegalArgumentException e) {
+         return RoleSize.UNRECOGNIZED;
+      }
+   }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/ece9a967/azurecompute/src/test/java/org/jclouds/azurecompute/features/DeploymentApiMockTest.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/test/java/org/jclouds/azurecompute/features/DeploymentApiMockTest.java b/azurecompute/src/test/java/org/jclouds/azurecompute/features/DeploymentApiMockTest.java
index e0bd956..90f34a9 100644
--- a/azurecompute/src/test/java/org/jclouds/azurecompute/features/DeploymentApiMockTest.java
+++ b/azurecompute/src/test/java/org/jclouds/azurecompute/features/DeploymentApiMockTest.java
@@ -16,16 +16,18 @@
  */
 package org.jclouds.azurecompute.features;
 
-import com.squareup.okhttp.mockwebserver.MockResponse;
-import com.squareup.okhttp.mockwebserver.MockWebServer;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+
 import org.jclouds.azurecompute.domain.DeploymentParams;
 import org.jclouds.azurecompute.domain.OSType;
 import org.jclouds.azurecompute.domain.RoleSize;
 import org.jclouds.azurecompute.internal.BaseAzureComputeApiMockTest;
-import org.jclouds.azurecompute.parse.GetDeploymentTest;
+import org.jclouds.azurecompute.xml.DeploymentHandlerTest;
 import org.testng.annotations.Test;
 
-import static org.assertj.core.api.Assertions.assertThat;
+import com.squareup.okhttp.mockwebserver.MockResponse;
+import com.squareup.okhttp.mockwebserver.MockWebServer;
 
 @Test(groups = "unit", testName = "DeploymentApiMockTest")
 public class DeploymentApiMockTest extends BaseAzureComputeApiMockTest {
@@ -42,7 +44,7 @@ public class DeploymentApiMockTest extends BaseAzureComputeApiMockTest {
                .sourceImageName("OpenLogic__OpenLogic-CentOS-62-20120531-en-us-30GB.vhd")
                .storageAccount("portalvhds0g7xhnq2x7t21").build();
 
-         assertThat(api.create(params)).isEqualTo("request-1");
+         assertEquals(api.create(params), "request-1");
 
          assertSent(server, "POST", "/services/hostedservices/myservice/deployments", "/deploymentparams.xml");
       } finally {
@@ -57,7 +59,7 @@ public class DeploymentApiMockTest extends BaseAzureComputeApiMockTest {
       try {
          DeploymentApi api = api(server.getUrl("/")).getDeploymentApiForService("myservice");
 
-         assertThat(api.get("mydeployment")).isEqualTo(GetDeploymentTest.expected());
+         assertEquals(api.get("mydeployment"), DeploymentHandlerTest.expected());
 
          assertSent(server, "GET", "/services/hostedservices/myservice/deployments/mydeployment");
       } finally {
@@ -72,7 +74,7 @@ public class DeploymentApiMockTest extends BaseAzureComputeApiMockTest {
       try {
          DeploymentApi api = api(server.getUrl("/")).getDeploymentApiForService("myservice");
 
-         assertThat(api.get("mydeployment")).isNull();
+         assertNull(api.get("mydeployment"));
 
          assertSent(server, "GET", "/services/hostedservices/myservice/deployments/mydeployment");
       } finally {
@@ -87,7 +89,7 @@ public class DeploymentApiMockTest extends BaseAzureComputeApiMockTest {
       try {
          DeploymentApi api = api(server.getUrl("/")).getDeploymentApiForService("myservice");
 
-         assertThat(api.delete("mydeployment")).isEqualTo("request-1");
+         assertEquals(api.delete("mydeployment"), "request-1");
 
          assertSent(server, "DELETE", "/services/hostedservices/myservice/deployments/mydeployment");
       } finally {
@@ -102,7 +104,7 @@ public class DeploymentApiMockTest extends BaseAzureComputeApiMockTest {
       try {
          DeploymentApi api = api(server.getUrl("/")).getDeploymentApiForService("myservice");
 
-         assertThat(api.delete("mydeployment")).isNull();
+         assertNull(api.delete("mydeployment"));
 
          assertSent(server, "DELETE", "/services/hostedservices/myservice/deployments/mydeployment");
       } finally {

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/ece9a967/azurecompute/src/test/java/org/jclouds/azurecompute/parse/GetDeploymentTest.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/test/java/org/jclouds/azurecompute/parse/GetDeploymentTest.java b/azurecompute/src/test/java/org/jclouds/azurecompute/parse/GetDeploymentTest.java
deleted file mode 100644
index 76bad81..0000000
--- a/azurecompute/src/test/java/org/jclouds/azurecompute/parse/GetDeploymentTest.java
+++ /dev/null
@@ -1,62 +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.azurecompute.parse;
-
-import java.io.InputStream;
-import java.net.URI;
-import org.jclouds.azurecompute.domain.Deployment;
-import org.jclouds.azurecompute.domain.DeploymentSlot;
-import org.jclouds.azurecompute.domain.DeploymentStatus;
-import org.jclouds.azurecompute.domain.InstanceStatus;
-import org.jclouds.azurecompute.domain.RoleSize;
-import org.jclouds.azurecompute.xml.DeploymentHandler;
-import org.jclouds.http.functions.BaseHandlerTest;
-import org.testng.annotations.Test;
-
-import static org.testng.Assert.assertEquals;
-
-@Test(groups = "unit", testName = "GetDeploymentTest")
-public class GetDeploymentTest extends BaseHandlerTest {
-
-   public void test() {
-      InputStream is = getClass().getResourceAsStream("/deployment.xml");
-
-      Deployment expected = expected();
-
-      DeploymentHandler handler = injector.getInstance(DeploymentHandler.class);
-      Deployment result = factory.create(handler).parse(is);
-
-      assertEquals(result.toString(), expected.toString());
-   }
-
-   public static Deployment expected() {
-      return Deployment.builder()
-         .deploymentName("neotysss")
-         .deploymentSlot(DeploymentSlot.PRODUCTION)
-         .deploymentStatus(DeploymentStatus.RUNNING)
-         .deploymentLabel("neotysss")
-         .deploymentURL(URI.create("http://neotysss.cloudapp.net/"))
-         .roleName("neotysss")
-         .instanceName("neotysss")
-         .instanceStatus(InstanceStatus.READY_ROLE)
-         .instanceSize(RoleSize.MEDIUM)
-         .privateIpAddress("10.59.244.162")
-         .publicIpAddress("168.63.27.148")
-         .build();
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/ece9a967/azurecompute/src/test/java/org/jclouds/azurecompute/xml/DeploymentHandlerTest.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/test/java/org/jclouds/azurecompute/xml/DeploymentHandlerTest.java b/azurecompute/src/test/java/org/jclouds/azurecompute/xml/DeploymentHandlerTest.java
new file mode 100644
index 0000000..d622b42
--- /dev/null
+++ b/azurecompute/src/test/java/org/jclouds/azurecompute/xml/DeploymentHandlerTest.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.azurecompute.xml;
+
+import static org.jclouds.azurecompute.xml.DeploymentHandler.parseInstanceStatus;
+import static org.testng.Assert.assertEquals;
+
+import java.io.InputStream;
+
+import org.jclouds.azurecompute.domain.Deployment;
+import org.jclouds.azurecompute.domain.Deployment.InstanceStatus;
+import org.jclouds.azurecompute.domain.Deployment.Slot;
+import org.jclouds.azurecompute.domain.Deployment.Status;
+import org.jclouds.azurecompute.domain.RoleSize;
+import org.jclouds.http.functions.BaseHandlerTest;
+import org.testng.annotations.Test;
+
+@Test(groups = "unit", testName = "DeploymentHandlerTest")
+public class DeploymentHandlerTest extends BaseHandlerTest {
+
+   /**
+    * Covers values listed <a href="http://msdn.microsoft.com/en-us/library/azure/ee460804.aspx#RoleInstanceList">here</a>.
+    */
+   public void parseInstanceStatus_Recognized() {
+      assertEquals(parseInstanceStatus("Unknown"), InstanceStatus.UNKNOWN);
+      assertEquals(parseInstanceStatus("CreatingVM"), InstanceStatus.CREATING_VM);
+      assertEquals(parseInstanceStatus("StartingVM"), InstanceStatus.STARTING_VM);
+      assertEquals(parseInstanceStatus("CreatingRole"), InstanceStatus.CREATING_ROLE);
+      assertEquals(parseInstanceStatus("StartingRole"), InstanceStatus.STARTING_ROLE);
+      assertEquals(parseInstanceStatus("ReadyRole"), InstanceStatus.READY_ROLE);
+      assertEquals(parseInstanceStatus("BusyRole"), InstanceStatus.BUSY_ROLE);
+      assertEquals(parseInstanceStatus("StoppingRole"), InstanceStatus.STOPPING_ROLE);
+      assertEquals(parseInstanceStatus("StoppingVM"), InstanceStatus.STOPPING_VM);
+      assertEquals(parseInstanceStatus("DeletingVM"), InstanceStatus.DELETING_VM);
+      assertEquals(parseInstanceStatus("StoppedVM"), InstanceStatus.STOPPED_VM);
+      assertEquals(parseInstanceStatus("RestartingRole"), InstanceStatus.RESTARTING_ROLE);
+      assertEquals(parseInstanceStatus("CyclingRole"), InstanceStatus.CYCLING_ROLE);
+      assertEquals(parseInstanceStatus("FailedStartingRole"), InstanceStatus.FAILED_STARTING_ROLE);
+      assertEquals(parseInstanceStatus("FailedStartingVM"), InstanceStatus.FAILED_STARTING_VM);
+      assertEquals(parseInstanceStatus("UnresponsiveRole"), InstanceStatus.UNRESPONSIVE_ROLE);
+      assertEquals(parseInstanceStatus("StoppedDeallocated"), InstanceStatus.STOPPED_DEALLOCATED);
+      assertEquals(parseInstanceStatus("Preparing"), InstanceStatus.PREPARING);
+   }
+
+   public void parseInstanceStatus_Unrecognized() {
+      assertEquals(parseInstanceStatus("FooAddedToday"), InstanceStatus.UNRECOGNIZED);
+   }
+
+   public void test() {
+      InputStream is = getClass().getResourceAsStream("/deployment.xml");
+      Deployment result = factory.create(new DeploymentHandler()).parse(is);
+
+      assertEquals(result, expected());
+   }
+
+   public static Deployment expected() {
+      return Deployment.create( //
+            "deployment_name", // name
+            Slot.PRODUCTION, // slot
+            Status.RUNNING, // status
+            "neotysss", // label
+            "role_name_from_role_list", // virtualMachineName
+            "instance_name", // instanceName
+            InstanceStatus.READY_ROLE, // instanceStatus
+            null, // instanceStateDetails
+            null, // instanceErrorCode
+            RoleSize.MEDIUM, // instanceSize
+            "10.59.244.162", // privateIpAddress
+            "168.63.27.148" // publicIpAddress
+      );
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/ece9a967/azurecompute/src/test/resources/deployment.xml
----------------------------------------------------------------------
diff --git a/azurecompute/src/test/resources/deployment.xml b/azurecompute/src/test/resources/deployment.xml
index c44fc7a..b3029d6 100644
--- a/azurecompute/src/test/resources/deployment.xml
+++ b/azurecompute/src/test/resources/deployment.xml
@@ -1,70 +1,74 @@
 <Deployment xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
-    <Name>neotysss</Name>
-    <DeploymentSlot>Production</DeploymentSlot>
-    <PrivateID>05aa8ec5d8ee4215894431c7db401b31</PrivateID>
-    <Status>Running</Status>
-    <Label>bmVvdHlzc3M=</Label>
-    <Url>http://neotysss.cloudapp.net/</Url>
-    <Configuration>PFNlcnZpY2VDb25maWd1cmF0aW9uIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiIHhtbG5zOnhzZD0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiIHhtbG5zPSJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL1NlcnZpY2VIb3N0aW5nLzIwMDgvMTAvU2VydmljZUNvbmZpZ3VyYXRpb24iPg0KICA8Um9sZSBuYW1lPSJuZW90eXNzcyI+DQogICAgPEluc3RhbmNlcyBjb3VudD0iMSIgLz4NCiAgPC9Sb2xlPg0KPC9TZXJ2aWNlQ29uZmlndXJhdGlvbj4=</Configuration>
-    <RoleInstanceList>
-        <RoleInstance>
-        <RoleName>neotysss</RoleName>
-        <InstanceName>neotysss</InstanceName>
-        <InstanceStatus>ReadyRole</InstanceStatus>
-        <InstanceUpgradeDomain>0</InstanceUpgradeDomain>
-        <InstanceFaultDomain>0</InstanceFaultDomain>
-        <InstanceSize>Medium</InstanceSize>
-        <InstanceStateDetails/>
-        <IpAddress>10.59.244.162</IpAddress>
-        <InstanceEndpoints>
+  <Name>deployment_name</Name>
+  <DeploymentSlot>Production</DeploymentSlot>
+  <PrivateID>05aa8ec5d8ee4215894431c7db401b31</PrivateID>
+  <Status>Running</Status>
+  <Label>bmVvdHlzc3M=</Label>
+  <Url>http://neotysss.cloudapp.net/</Url>
+  <Configuration>
+    PFNlcnZpY2VDb25maWd1cmF0aW9uIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiIHhtbG5zOnhzZD0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiIHhtbG5zPSJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL1NlcnZpY2VIb3N0aW5nLzIwMDgvMTAvU2VydmljZUNvbmZpZ3VyYXRpb24iPg0KICA8Um9sZSBuYW1lPSJuZW90eXNzcyI+DQogICAgPEluc3RhbmNlcyBjb3VudD0iMSIgLz4NCiAgPC9Sb2xlPg0KPC9TZXJ2aWNlQ29uZmlndXJhdGlvbj4=
+  </Configuration>
+  <RoleInstanceList>
+    <RoleInstance>
+      <RoleName>role_name_from_instance</RoleName>
+      <InstanceName>instance_name</InstanceName>
+      <InstanceStatus>ReadyRole</InstanceStatus>
+      <InstanceUpgradeDomain>0</InstanceUpgradeDomain>
+      <InstanceFaultDomain>0</InstanceFaultDomain>
+      <InstanceSize>Medium</InstanceSize>
+      <InstanceStateDetails/>
+      <IpAddress>10.59.244.162</IpAddress>
+      <InstanceEndpoints>
         <InstanceEndpoint>
-            <Name>SSH</Name>
-            <Vip>168.63.27.148</Vip>
-            <PublicPort>22</PublicPort>
-            <LocalPort>22</LocalPort>
-            <Protocol>tcp</Protocol>
+          <Name>SSH</Name>
+          <Vip>168.63.27.148</Vip>
+          <PublicPort>22</PublicPort>
+          <LocalPort>22</LocalPort>
+          <Protocol>tcp</Protocol>
         </InstanceEndpoint>
-        </InstanceEndpoints>
-        <PowerState>Started</PowerState>
-        <HostName>neotys</HostName>
+      </InstanceEndpoints>
+      <PowerState>Started</PowerState>
+      <HostName>host_name</HostName>
     </RoleInstance>
-    </RoleInstanceList>
-    <UpgradeDomainCount>1</UpgradeDomainCount>
-    <RoleList>
-        <Role i:type="PersistentVMRole">
-        <RoleName>neotysss</RoleName>
-        <OsVersion/>
-        <RoleType>PersistentVMRole</RoleType>
-        <ConfigurationSets>
+  </RoleInstanceList>
+  <UpgradeDomainCount>1</UpgradeDomainCount>
+  <RoleList>
+    <Role i:type="PersistentVMRole">
+      <RoleName>role_name_from_role_list</RoleName>
+      <OsVersion/>
+      <RoleType>PersistentVMRole</RoleType>
+      <ConfigurationSets>
         <ConfigurationSet i:type="NetworkConfigurationSet">
-            <ConfigurationSetType>NetworkConfiguration</ConfigurationSetType>
-            <InputEndpoints>
+          <ConfigurationSetType>NetworkConfiguration</ConfigurationSetType>
+          <InputEndpoints>
             <InputEndpoint>
-                <LocalPort>22</LocalPort>
-                <Name>SSH</Name>
-                <Port>22</Port>
-                <Protocol>tcp</Protocol>
-                <Vip>168.63.27.148</Vip>
+              <LocalPort>22</LocalPort>
+              <Name>SSH</Name>
+              <Port>22</Port>
+              <Protocol>tcp</Protocol>
+              <Vip>168.63.27.148</Vip>
             </InputEndpoint>
-            </InputEndpoints>
-            <SubnetNames/>
+          </InputEndpoints>
+          <SubnetNames/>
         </ConfigurationSet>
-        </ConfigurationSets>
-        <DataVirtualHardDisks/>
-        <OSVirtualHardDisk>
-            <HostCaching>ReadWrite</HostCaching>
-            <DiskName>neotysss-neotysss-0-20120824091357</DiskName>
-            <MediaLink>http://portalvhds0g7xhnq2x7t21.blob.core.windows.net/disks/neotysss/MSFT__Win2K8R2SP1-120612-1520-121206-01-en-us-30GB.vhd</MediaLink>
-            <SourceImageName>MSFT__Win2K8R2SP1-120612-1520-121206-01-en-us-30GB.vhd</SourceImageName>
-            <OS>Windows</OS>
-        </OSVirtualHardDisk>
-        <RoleSize>Medium</RoleSize>
+      </ConfigurationSets>
+      <DataVirtualHardDisks/>
+      <OSVirtualHardDisk>
+        <HostCaching>ReadWrite</HostCaching>
+        <DiskName>neotysss-neotysss-0-20120824091357</DiskName>
+        <MediaLink>
+          http://portalvhds0g7xhnq2x7t21.blob.core.windows.net/disks/neotysss/MSFT__Win2K8R2SP1-120612-1520-121206-01-en-us-30GB.vhd
+        </MediaLink>
+        <SourceImageName>MSFT__Win2K8R2SP1-120612-1520-121206-01-en-us-30GB.vhd</SourceImageName>
+        <OS>Windows</OS>
+      </OSVirtualHardDisk>
+      <RoleSize>Medium</RoleSize>
     </Role>
-    </RoleList>
-    <SdkVersion/>
-    <Locked>false</Locked>
-    <RollbackAllowed>false</RollbackAllowed>
-    <CreatedTime>2012-08-24T09:13:53Z</CreatedTime>
-    <LastModifiedTime>2012-08-27T08:55:13Z</LastModifiedTime>
-    <ExtendedProperties/>
-</Deployment>
\ No newline at end of file
+  </RoleList>
+  <SdkVersion/>
+  <Locked>false</Locked>
+  <RollbackAllowed>false</RollbackAllowed>
+  <CreatedTime>2012-08-24T09:13:53Z</CreatedTime>
+  <LastModifiedTime>2012-08-27T08:55:13Z</LastModifiedTime>
+  <ExtendedProperties/>
+</Deployment>