Azure compute DeploymentParams name is not globally unique.
Project: http://git-wip-us.apache.org/repos/asf/jclouds-labs/repo Commit: http://git-wip-us.apache.org/repos/asf/jclouds-labs/commit/a53689fb Tree: http://git-wip-us.apache.org/repos/asf/jclouds-labs/tree/a53689fb Diff: http://git-wip-us.apache.org/repos/asf/jclouds-labs/diff/a53689fb Branch: refs/heads/master Commit: a53689fb1b6b6949d6a182f718b794a018f22fcf Parents: bd8c0b9 Author: Adrian Cole <[email protected]> Authored: Tue Oct 21 21:44:42 2014 -0700 Committer: Adrian Cole <[email protected]> Committed: Wed Oct 22 17:11:19 2014 -0700 ---------------------------------------------------------------------- .../binders/CreateDeploymentToXML.java | 119 ------------------- .../binders/DeploymentParamsToXML.java | 112 +++++++++++++++++ .../azurecompute/domain/DeploymentParams.java | 39 ++++-- .../azurecompute/features/DeploymentApi.java | 16 +-- .../features/DeploymentApiMockTest.java | 6 +- 5 files changed, 148 insertions(+), 144 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a53689fb/azurecompute/src/main/java/org/jclouds/azurecompute/binders/CreateDeploymentToXML.java ---------------------------------------------------------------------- diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/binders/CreateDeploymentToXML.java b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/CreateDeploymentToXML.java deleted file mode 100644 index 67573a8..0000000 --- a/azurecompute/src/main/java/org/jclouds/azurecompute/binders/CreateDeploymentToXML.java +++ /dev/null @@ -1,119 +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.binders; - -import static com.google.common.base.CaseFormat.UPPER_CAMEL; -import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE; -import static com.google.common.base.Throwables.propagate; -import static org.jclouds.azurecompute.domain.Image.OSType.LINUX; - -import java.util.Map; - -import org.jclouds.azurecompute.domain.DeploymentParams; -import org.jclouds.azurecompute.domain.Image.OSType; -import org.jclouds.http.HttpRequest; -import org.jclouds.rest.MapBinder; - -import com.jamesmurty.utils.XMLBuilder; - -public final class CreateDeploymentToXML implements MapBinder { - - @Override public <R extends HttpRequest> R bindToRequest(R request, Map<String, Object> postParams) { - String name = postParams.get("name").toString(); - DeploymentParams params = DeploymentParams.class.cast(postParams.get("params")); - - try { - XMLBuilder builder = XMLBuilder.create("Deployment", "http://schemas.microsoft.com/windowsazure") - .e("Name").t(name).up() - .e("DeploymentSlot").t("Production").up() - .e("Label").t(name).up() - .e("RoleList") - .e("Role") - .e("RoleName").t(name).up() - .e("RoleType").t("PersistentVMRole").up() - .e("ConfigurationSets"); - - if (params.os() == OSType.WINDOWS) { - XMLBuilder configBuilder = builder.e("ConfigurationSet"); // Windows - configBuilder.e("ConfigurationSetType").t("WindowsProvisioningConfiguration").up() - .e("ComputerName").t(name).up() - .e("AdminPassword").t(params.password()).up() - .e("ResetPasswordOnFirstLogon").t("false").up() - .e("EnableAutomaticUpdate").t("false").up() - .e("DomainJoin") - .e("Credentials") - .e("Domain").t(name).up() - .e("Username").t(params.username()).up() - .e("Password").t(params.password()).up() - .up() // Credentials - .e("JoinDomain").t(name).up() - .up() // Domain Join - .e("StoredCertificateSettings").up() - .up(); // Windows ConfigurationSet - } else if (params.os() == OSType.LINUX) { - XMLBuilder configBuilder = builder.e("ConfigurationSet"); // Linux - configBuilder.e("ConfigurationSetType").t("LinuxProvisioningConfiguration").up() - .e("HostName").t(name).up() - .e("UserName").t(params.username()).up() - .e("UserPassword").t(params.password()).up() - .e("DisableSshPasswordAuthentication").t("false").up() - .e("SSH").up() - .up(); // Linux ConfigurationSet - } else { - throw new IllegalArgumentException("Unrecognized os type " + params); - } - - XMLBuilder configBuilder = builder.e("ConfigurationSet"); // Network - configBuilder.e("ConfigurationSetType").t("NetworkConfiguration").up(); - - XMLBuilder inputEndpoints = configBuilder.e("InputEndpoints"); - for (DeploymentParams.ExternalEndpoint endpoint : params.externalEndpoints()) { - XMLBuilder inputBuilder = inputEndpoints.e("InputEndpoint"); - inputBuilder.e("LocalPort").t(Integer.toString(endpoint.localPort())).up() - .e("Name").t(endpoint.name()).up() - .e("Port").t(Integer.toString(endpoint.port())).up() - .e("Protocol").t(endpoint.protocol().toLowerCase()).up() - .up(); //InputEndpoint - } - - inputEndpoints.up(); - configBuilder.e("SubnetNames").up() - .up(); - - builder.up() //ConfigurationSets - .e("DataVirtualHardDisks").up() - .e("OSVirtualHardDisk") - .e("HostCaching").t("ReadWrite").up() - .e("MediaLink").t(params.mediaLink().toASCIIString()).up() - .e("SourceImageName").t(params.sourceImageName()).up() - .e("OS").t(params.os() == LINUX ? "Linux" : "Windows").up() - .up() //OSVirtualHardDisk - .e("RoleSize").t(UPPER_UNDERSCORE.to(UPPER_CAMEL, params.size().name())).up() - .up() //Role - .up(); //RoleList - - // TODO: Undeprecate this method as forcing users to wrap a String in guava's ByteSource is not great. - return (R) request.toBuilder().payload(builder.asString()).build(); - } catch (Exception e) { - throw propagate(e); - } - } - - @Override public <R extends HttpRequest> R bindToRequest(R request, Object input) { - throw new UnsupportedOperationException("use map form"); - } -} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a53689fb/azurecompute/src/main/java/org/jclouds/azurecompute/binders/DeploymentParamsToXML.java ---------------------------------------------------------------------- diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/binders/DeploymentParamsToXML.java b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/DeploymentParamsToXML.java new file mode 100644 index 0000000..c493c90 --- /dev/null +++ b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/DeploymentParamsToXML.java @@ -0,0 +1,112 @@ +/* + * 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.binders; + +import static com.google.common.base.CaseFormat.UPPER_CAMEL; +import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE; +import static com.google.common.base.Throwables.propagate; +import static org.jclouds.azurecompute.domain.Image.OSType.LINUX; + +import org.jclouds.azurecompute.domain.DeploymentParams; +import org.jclouds.azurecompute.domain.Image.OSType; +import org.jclouds.http.HttpRequest; +import org.jclouds.rest.Binder; + +import com.jamesmurty.utils.XMLBuilder; + +public final class DeploymentParamsToXML implements Binder { + + @Override public <R extends HttpRequest> R bindToRequest(R request, Object input) { + DeploymentParams params = DeploymentParams.class.cast(input); + + try { + XMLBuilder builder = XMLBuilder.create("Deployment", "http://schemas.microsoft.com/windowsazure") + .e("Name").t(params.name()).up() + .e("DeploymentSlot").t("Production").up() + .e("Label").t(params.name()).up() + .e("RoleList") + .e("Role") + .e("RoleName").t(params.name()).up() + .e("RoleType").t("PersistentVMRole").up() + .e("ConfigurationSets"); + + if (params.os() == OSType.WINDOWS) { + XMLBuilder configBuilder = builder.e("ConfigurationSet"); // Windows + configBuilder.e("ConfigurationSetType").t("WindowsProvisioningConfiguration").up() + .e("ComputerName").t(params.name()).up() + .e("AdminPassword").t(params.password()).up() + .e("ResetPasswordOnFirstLogon").t("false").up() + .e("EnableAutomaticUpdate").t("false").up() + .e("DomainJoin") + .e("Credentials") + .e("Domain").t(params.name()).up() + .e("Username").t(params.username()).up() + .e("Password").t(params.password()).up() + .up() // Credentials + .e("JoinDomain").t(params.name()).up() + .up() // Domain Join + .e("StoredCertificateSettings").up() + .up(); // Windows ConfigurationSet + } else if (params.os() == OSType.LINUX) { + XMLBuilder configBuilder = builder.e("ConfigurationSet"); // Linux + configBuilder.e("ConfigurationSetType").t("LinuxProvisioningConfiguration").up() + .e("HostName").t(params.name()).up() + .e("UserName").t(params.username()).up() + .e("UserPassword").t(params.password()).up() + .e("DisableSshPasswordAuthentication").t("false").up() + .e("SSH").up() + .up(); // Linux ConfigurationSet + } else { + throw new IllegalArgumentException("Unrecognized os type " + params); + } + + XMLBuilder configBuilder = builder.e("ConfigurationSet"); // Network + configBuilder.e("ConfigurationSetType").t("NetworkConfiguration").up(); + + XMLBuilder inputEndpoints = configBuilder.e("InputEndpoints"); + for (DeploymentParams.ExternalEndpoint endpoint : params.externalEndpoints()) { + XMLBuilder inputBuilder = inputEndpoints.e("InputEndpoint"); + inputBuilder.e("LocalPort").t(Integer.toString(endpoint.localPort())).up() + .e("Name").t(endpoint.name()).up() + .e("Port").t(Integer.toString(endpoint.port())).up() + .e("Protocol").t(endpoint.protocol().toLowerCase()).up() + .up(); //InputEndpoint + } + + inputEndpoints.up(); + configBuilder.e("SubnetNames").up() + .up(); + + builder.up() //ConfigurationSets + .e("DataVirtualHardDisks").up() + .e("OSVirtualHardDisk") + .e("HostCaching").t("ReadWrite").up() + .e("MediaLink").t(params.mediaLink().toASCIIString()).up() + .e("SourceImageName").t(params.sourceImageName()).up() + .e("OS").t(params.os() == LINUX ? "Linux" : "Windows").up() + .up() //OSVirtualHardDisk + .e("RoleSize").t(UPPER_UNDERSCORE.to(UPPER_CAMEL, params.size().name())).up() + .up() //Role + .up(); //RoleList + + // TODO: Undeprecate this method as forcing users to wrap a String in guava's ByteSource is not great. + return (R) request.toBuilder().payload(builder.asString()).build(); + } catch (Exception e) { + throw propagate(e); + } + } +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a53689fb/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 2dd9ae5..ac06305 100644 --- a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/DeploymentParams.java +++ b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/DeploymentParams.java @@ -106,6 +106,11 @@ public final class DeploymentParams { } } + /** The user-supplied name for this deployment. */ + public String name() { + return name; + } + /** * Specifies the name of a user to be created in the sudoers group of the * virtual machine. User names are ASCII character strings 1 to 32 @@ -157,6 +162,7 @@ public final class DeploymentParams { } public static final class Builder { + private String name; private RoleSize size = RoleSize.SMALL; private String username; private String password; @@ -165,6 +171,11 @@ public final class DeploymentParams { private OSType os; private List<ExternalEndpoint> externalEndpoints = Lists.newArrayList(); + public Builder name(String name) { + this.name = name; + return this; + } + public Builder size(RoleSize size) { this.size = size; return this; @@ -206,12 +217,13 @@ public final class DeploymentParams { } public DeploymentParams build() { - return DeploymentParams.create(size, username, password, sourceImageName, mediaLink, os, + return DeploymentParams.create(name, size, username, password, sourceImageName, mediaLink, os, ImmutableList.copyOf(externalEndpoints)); } public Builder fromDeploymentParams(DeploymentParams in) { - return size(in.size()) + return name(in.name()) + .size(in.size()) .username(in.username()) .password(in.password()) .sourceImageName(in.sourceImageName()) @@ -221,14 +233,15 @@ public final class DeploymentParams { } } - private static DeploymentParams create(RoleSize size, String username, String password, String sourceImageName, + private static DeploymentParams create(String name, RoleSize size, String username, String password, String sourceImageName, URI mediaLink, OSType os, List<ExternalEndpoint> externalEndpoints) { - return new DeploymentParams(size, username, password, sourceImageName, mediaLink, os, externalEndpoints); + return new DeploymentParams(name, size, username, password, sourceImageName, mediaLink, os, externalEndpoints); } // TODO: Remove from here down with @AutoValue. - private DeploymentParams(RoleSize size, String username, String password, String sourceImageName, URI mediaLink, + private DeploymentParams(String name, RoleSize size, String username, String password, String sourceImageName, URI mediaLink, OSType os, List<ExternalEndpoint> externalEndpoints) { + this.name = checkNotNull(name, "name"); this.size = checkNotNull(size, "size"); this.username = checkNotNull(username, "username"); this.password = checkNotNull(password, "password"); @@ -238,6 +251,7 @@ public final class DeploymentParams { this.externalEndpoints = checkNotNull(externalEndpoints, "externalEndpoints"); } + private final String name; private final RoleSize size; private final String username; private final String password; @@ -246,19 +260,18 @@ public final class DeploymentParams { private final OSType os; private final List<ExternalEndpoint> externalEndpoints; - @Override - public int hashCode() { - return Objects.hashCode(sourceImageName, username, password, mediaLink, size, os, externalEndpoints); + @Override public int hashCode() { + return Objects.hashCode(name, sourceImageName, username, password, mediaLink, size, os, externalEndpoints); } - @Override - public boolean equals(Object object) { + @Override public boolean equals(Object object) { if (this == object) { return true; } if (object instanceof DeploymentParams) { DeploymentParams that = DeploymentParams.class.cast(object); - return equal(size, that.size) + return equal(name, that.name) + && equal(size, that.size) && equal(username, that.username) && equal(password, that.password) && equal(sourceImageName, that.sourceImageName) @@ -270,9 +283,9 @@ public final class DeploymentParams { } } - @Override - public String toString() { + @Override public String toString() { return toStringHelper(this) + .add("name", name) .add("size", size) .add("username", username) .add("password", password) http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a53689fb/azurecompute/src/main/java/org/jclouds/azurecompute/features/DeploymentApi.java ---------------------------------------------------------------------- diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/features/DeploymentApi.java b/azurecompute/src/main/java/org/jclouds/azurecompute/features/DeploymentApi.java index 37dfd4e..69ceba6 100644 --- a/azurecompute/src/main/java/org/jclouds/azurecompute/features/DeploymentApi.java +++ b/azurecompute/src/main/java/org/jclouds/azurecompute/features/DeploymentApi.java @@ -16,6 +16,8 @@ */ package org.jclouds.azurecompute.features; +import static org.jclouds.Fallbacks.NullOnNotFoundOr404; + import javax.inject.Named; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; @@ -25,20 +27,18 @@ import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; -import org.jclouds.azurecompute.binders.CreateDeploymentToXML; + +import org.jclouds.azurecompute.binders.DeploymentParamsToXML; import org.jclouds.azurecompute.domain.Deployment; import org.jclouds.azurecompute.domain.DeploymentParams; import org.jclouds.azurecompute.functions.ParseRequestIdHeader; import org.jclouds.azurecompute.xml.DeploymentHandler; +import org.jclouds.rest.annotations.BinderParam; import org.jclouds.rest.annotations.Fallback; import org.jclouds.rest.annotations.Headers; -import org.jclouds.rest.annotations.MapBinder; -import org.jclouds.rest.annotations.PayloadParam; import org.jclouds.rest.annotations.ResponseParser; import org.jclouds.rest.annotations.XMLResponseParser; -import static org.jclouds.Fallbacks.NullOnNotFoundOr404; - @Path("/services/hostedservices/{serviceName}/deployments") @Headers(keys = "x-ms-version", values = "{jclouds.api-version}") @Consumes(MediaType.APPLICATION_XML) @@ -57,15 +57,11 @@ public interface DeploymentApi { @Fallback(NullOnNotFoundOr404.class) Deployment get(@PathParam("name") String name); - /** - * @param name the name for the deployment and its virtual machine. The name must be unique within Windows Azure. - */ @Named("CreateVirtualMachineDeployment") @POST @Produces(MediaType.APPLICATION_XML) @ResponseParser(ParseRequestIdHeader.class) - @MapBinder(CreateDeploymentToXML.class) - String create(@PayloadParam("name") String name, @PayloadParam("params") DeploymentParams params); + String create(@BinderParam(DeploymentParamsToXML.class) DeploymentParams params); /** * The Delete Deployment operation deletes the specified deployment from Windows Azure. http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a53689fb/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 e665557..e6662ac 100644 --- a/azurecompute/src/test/java/org/jclouds/azurecompute/features/DeploymentApiMockTest.java +++ b/azurecompute/src/test/java/org/jclouds/azurecompute/features/DeploymentApiMockTest.java @@ -45,13 +45,14 @@ public class DeploymentApiMockTest extends BaseAzureComputeApiMockTest { Image image = ListImagesHandlerTest.expected().get(5); // CentOS DeploymentParams params = DeploymentParams.builder() + .name("mydeployment") .size(RoleSize.MEDIUM) .sourceImageName(image.name()).mediaLink(image.mediaLink()).os(image.os()) .username("username").password("testpwd") .externalEndpoint(inboundTcpToLocalPort(80, 8080)) .externalEndpoint(inboundUdpToLocalPort(53, 53)).build(); - assertEquals(api.create("mydeployment", params), "request-1"); + assertEquals(api.create(params), "request-1"); assertSent(server, "POST", "/services/hostedservices/myservice/deployments", "/deploymentparams.xml"); } finally { @@ -69,13 +70,14 @@ public class DeploymentApiMockTest extends BaseAzureComputeApiMockTest { Image image = ListImagesHandlerTest.expected().get(1); // Windows DeploymentParams params = DeploymentParams.builder() + .name("mydeployment") .size(RoleSize.MEDIUM) .sourceImageName(image.name()).mediaLink(image.mediaLink()).os(image.os()) .username("username").password("testpwd") .externalEndpoint(inboundTcpToLocalPort(80, 8080)) .externalEndpoint(inboundUdpToLocalPort(53, 53)).build(); - assertEquals(api.create("mydeployment", params), "request-1"); + assertEquals(api.create(params), "request-1"); assertSent(server, "POST", "/services/hostedservices/myservice/deployments", "/deploymentparams-windows.xml"); } finally {
