diff --git a/core/src/main/resources/rest.properties b/core/src/main/resources/rest.properties index 38119c9163..2424c1903d 100644 --- a/core/src/main/resources/rest.properties +++ b/core/src/main/resources/rest.properties @@ -50,6 +50,9 @@ trmk-vcloudexpress.propertiesbuilder=org.jclouds.trmk.vcloudexpress.TerremarkVCl trmk-ecloud.contextbuilder=org.jclouds.trmk.ecloud.TerremarkECloudContextBuilder trmk-ecloud.propertiesbuilder=org.jclouds.trmk.ecloud.TerremarkECloudPropertiesBuilder +trmk-enterprisecloud.contextbuilder=org.jclouds.trmk.enterprisecloud.TerremarkEnterpriseCloudContextBuilder +trmk-enterprisecloud.propertiesbuilder=org.jclouds.trmk.enterprisecloud.TerremarkEnterpriseCloudPropertiesBuilder + chef.contextbuilder=org.jclouds.chef.ChefContextBuilder chef.propertiesbuilder=org.jclouds.chef.ChefPropertiesBuilder diff --git a/sandbox-providers/trmk-enterprisecloud/pom.xml b/sandbox-providers/trmk-enterprisecloud/pom.xml new file mode 100644 index 0000000000..346302da5b --- /dev/null +++ b/sandbox-providers/trmk-enterprisecloud/pom.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Licensed to jclouds, Inc. (jclouds) under one or more + contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. jclouds licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.jclouds</groupId> + <artifactId>jclouds-project</artifactId> + <version>1.3.0-SNAPSHOT</version> + <relativePath>../../project/pom.xml</relativePath> + </parent> + <groupId>org.jclouds.provider</groupId> + <artifactId>trmk-enterprisecloud</artifactId> + <name>jclouds Terremark Enterprise Cloud core</name> + <description>jclouds components to access Terremark Enterprise Cloud</description> + <packaging>bundle</packaging> + + <!-- bootstrapping: need to fetch the project POM --> + <repositories> + <repository> + <id>jclouds-sona-snapshots-nexus</id> + <url>https://oss.sonatype.org/content/repositories/snapshots</url> + <releases> + <enabled>false</enabled> + </releases> + <snapshots> + <enabled>true</enabled> + </snapshots> + </repository> + </repositories> + + <properties> + <test.trmk-enterprisecloud.endpoint>http://209.251.187.125/livespec</test.trmk-enterprisecloud.endpoint> + <test.trmk-enterprisecloud.apiversion>2011-07-01</test.trmk-enterprisecloud.apiversion> + <test.trmk-enterprisecloud.identity>readonly@terremark.com</test.trmk-enterprisecloud.identity> + <test.trmk-enterprisecloud.credential>T3rr3m@rk</test.trmk-enterprisecloud.credential> + </properties> + <dependencies> + <dependency> + <groupId>org.jclouds</groupId> + <artifactId>jclouds-compute</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.jclouds</groupId> + <artifactId>jclouds-core</artifactId> + <version>${project.version}</version> + <type>test-jar</type> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.jclouds</groupId> + <artifactId>jclouds-compute</artifactId> + <version>${project.version}</version> + <type>test-jar</type> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.jclouds.driver</groupId> + <artifactId>jclouds-log4j</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.jclouds.driver</groupId> + <artifactId>jclouds-sshj</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> + </dependencies> + <profiles> + <profile> + <id>live</id> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <executions> + <execution> + <id>integration</id> + <phase>integration-test</phase> + <goals> + <goal>test</goal> + </goals> + <configuration> + <systemProperties> + <property> + <name>test.trmk-enterprisecloud.endpoint</name> + <value>${test.trmk-enterprisecloud.endpoint}</value> + </property> + <property> + <name>test.trmk-enterprisecloud.apiversion</name> + <value>${test.trmk-enterprisecloud.apiversion}</value> + </property> + <property> + <name>test.trmk-enterprisecloud.identity</name> + <value>${test.trmk-enterprisecloud.identity}</value> + </property> + <property> + <name>test.trmk-enterprisecloud.credential</name> + <value>${test.trmk-enterprisecloud.credential}</value> + </property> + </systemProperties> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> + </profiles> + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <configuration> + <instructions> + <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName> + <Export-Package>org.jclouds.trmk.enterprisecloud.*;version="${project.version}"</Export-Package> + <Import-Package>org.jclouds.*;version="${project.version}",*</Import-Package> + </instructions> + </configuration> + </plugin> + </plugins> + </build> +</project> diff --git a/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/TerremarkEnterpriseCloudAsyncClient.java b/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/TerremarkEnterpriseCloudAsyncClient.java new file mode 100644 index 0000000000..1aaddc622b --- /dev/null +++ b/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/TerremarkEnterpriseCloudAsyncClient.java @@ -0,0 +1,41 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.trmk.enterprisecloud; + +import org.jclouds.rest.annotations.Delegate; +import org.jclouds.trmk.enterprisecloud.features.TaskAsyncClient; + +/** + * Provides asynchronous access to TerremarkEnterpriseCloud via their REST API. + * <p/> + * + * @see TerremarkEnterpriseCloudClient + * @see <a href= + * "http://support.theenterprisecloud.com/kb/default.asp?id=984&Lang=1&SID=" + * /> + * @author Adrian Cole + */ +public interface TerremarkEnterpriseCloudAsyncClient { + + /** + * Provides asynchronous access to Task features. + */ + @Delegate + TaskAsyncClient getTaskClient(); +} diff --git a/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/TerremarkEnterpriseCloudClient.java b/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/TerremarkEnterpriseCloudClient.java new file mode 100644 index 0000000000..5040bc888c --- /dev/null +++ b/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/TerremarkEnterpriseCloudClient.java @@ -0,0 +1,45 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.trmk.enterprisecloud; + +import java.util.concurrent.TimeUnit; + +import org.jclouds.concurrent.Timeout; +import org.jclouds.rest.annotations.Delegate; +import org.jclouds.trmk.enterprisecloud.features.TaskClient; + +/** + * Provides synchronous access to TerremarkEnterpriseCloud. + * <p/> + * + * @see TerremarkEnterpriseCloudAsyncClient + * @see <a href= + * "http://support.theenterprisecloud.com/kb/default.asp?id=984&Lang=1&SID=" + * /> + * @author Adrian Cole + */ +@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS) +public interface TerremarkEnterpriseCloudClient { + + /** + * Provides synchronous access to Task features. + */ + @Delegate + TaskClient getTaskClient(); +} diff --git a/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/TerremarkEnterpriseCloudContextBuilder.java b/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/TerremarkEnterpriseCloudContextBuilder.java new file mode 100644 index 0000000000..af79376876 --- /dev/null +++ b/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/TerremarkEnterpriseCloudContextBuilder.java @@ -0,0 +1,45 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.trmk.enterprisecloud; + +import java.util.List; +import java.util.Properties; + +import org.jclouds.rest.RestContextBuilder; +import org.jclouds.trmk.enterprisecloud.config.TerremarkEnterpriseCloudRestClientModule; + +import com.google.inject.Module; + +/** + * + * @author Adrian Cole + */ +public class TerremarkEnterpriseCloudContextBuilder extends + RestContextBuilder<TerremarkEnterpriseCloudClient, TerremarkEnterpriseCloudAsyncClient> { + + public TerremarkEnterpriseCloudContextBuilder(Properties props) { + super(TerremarkEnterpriseCloudClient.class, TerremarkEnterpriseCloudAsyncClient.class, props); + } + + @Override + protected void addClientModule(List<Module> modules) { + modules.add(new TerremarkEnterpriseCloudRestClientModule()); + } + +} diff --git a/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/TerremarkEnterpriseCloudPropertiesBuilder.java b/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/TerremarkEnterpriseCloudPropertiesBuilder.java new file mode 100644 index 0000000000..8c50bb1a92 --- /dev/null +++ b/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/TerremarkEnterpriseCloudPropertiesBuilder.java @@ -0,0 +1,47 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.trmk.enterprisecloud; + +import static org.jclouds.Constants.PROPERTY_API_VERSION; +import static org.jclouds.Constants.PROPERTY_ENDPOINT; + +import java.util.Properties; + +import org.jclouds.PropertiesBuilder; + +/** + * Builds properties used in TerremarkEnterpriseCloud Clients + * + * @author Adrian Cole + */ +public class TerremarkEnterpriseCloudPropertiesBuilder extends PropertiesBuilder { + @Override + protected Properties defaultProperties() { + Properties properties = super.defaultProperties(); + // TODO replace with the actual rest url + properties.setProperty(PROPERTY_ENDPOINT, "http://209.251.187.125/livespec"); + properties.setProperty(PROPERTY_API_VERSION, "2011-07-01"); + return properties; + } + + public TerremarkEnterpriseCloudPropertiesBuilder(Properties properties) { + super(properties); + } + +} diff --git a/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/TerremarkEnterpriseCloudProviderMetadata.java b/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/TerremarkEnterpriseCloudProviderMetadata.java new file mode 100644 index 0000000000..30dec708f6 --- /dev/null +++ b/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/TerremarkEnterpriseCloudProviderMetadata.java @@ -0,0 +1,117 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.trmk.enterprisecloud; + +import java.net.URI; +import java.util.Set; + +import org.jclouds.providers.BaseProviderMetadata; +import org.jclouds.providers.ProviderMetadata; + +import com.google.common.collect.ImmutableSet; + +/** + * Implementation of {@link org.jclouds.types.ProviderMetadata} for Terremark + * Enterprise Cloud. + * + * @author Adrian Cole + */ +public class TerremarkEnterpriseCloudProviderMetadata extends BaseProviderMetadata { + + /** + * {@inheritDoc} + */ + @Override + public String getId() { + return "trmk-enterprisecloud"; + } + + /** + * {@inheritDoc} + */ + @Override + public String getType() { + return ProviderMetadata.COMPUTE_TYPE; + } + + /** + * {@inheritDoc} + */ + @Override + public String getName() { + return "Terremark Enterprise Cloud"; + } + + /** + * {@inheritDoc} + */ + @Override + public String getIdentityName() { + return "Email"; + } + + /** + * {@inheritDoc} + */ + @Override + public String getCredentialName() { + return "Password"; + } + + /** + * {@inheritDoc} + */ + @Override + public URI getHomepage() { + return URI.create("TODO"); + } + + /** + * {@inheritDoc} + */ + @Override + public URI getConsole() { + return URI.create("TODO"); + } + + /** + * {@inheritDoc} + */ + @Override + public URI getApiDocumentation() { + return URI.create("http://support.theenterprisecloud.com/kb/default.asp?id=984&Lang=1&SID="); + } + + /** + * {@inheritDoc} + */ + @Override + public Set<String> getLinkedServices() { + return ImmutableSet.of("trmk-enterprisecloud", "trmk-ecloud", "trmk-vcloudexpress"); + } + + /** + * {@inheritDoc} + */ + @Override + public Set<String> getIso3166Codes() { + return ImmutableSet.of("TODO"); + } + +} diff --git a/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/config/TerremarkEnterpriseCloudRestClientModule.java b/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/config/TerremarkEnterpriseCloudRestClientModule.java new file mode 100644 index 0000000000..87047033ae --- /dev/null +++ b/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/config/TerremarkEnterpriseCloudRestClientModule.java @@ -0,0 +1,75 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.trmk.enterprisecloud.config; + +import java.util.Map; + +import org.jclouds.http.HttpErrorHandler; +import org.jclouds.http.HttpRetryHandler; +import org.jclouds.http.RequiresHttp; +import org.jclouds.http.annotation.ClientError; +import org.jclouds.http.annotation.Redirection; +import org.jclouds.http.annotation.ServerError; +import org.jclouds.http.handlers.BackoffLimitedRetryHandler; +import org.jclouds.rest.ConfiguresRestClient; +import org.jclouds.rest.config.RestClientModule; +import org.jclouds.trmk.enterprisecloud.TerremarkEnterpriseCloudAsyncClient; +import org.jclouds.trmk.enterprisecloud.TerremarkEnterpriseCloudClient; +import org.jclouds.trmk.enterprisecloud.features.TaskAsyncClient; +import org.jclouds.trmk.enterprisecloud.features.TaskClient; +import org.jclouds.trmk.enterprisecloud.handlers.TerremarkEnterpriseCloudErrorHandler; + +import com.google.common.collect.ImmutableMap; + +/** + * Configures the TerremarkEnterpriseCloud connection. + * + * @author Adrian Cole + */ +@RequiresHttp +@ConfiguresRestClient +public class TerremarkEnterpriseCloudRestClientModule extends + RestClientModule<TerremarkEnterpriseCloudClient, TerremarkEnterpriseCloudAsyncClient> { + + public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>> builder()// + .put(TaskClient.class, TaskAsyncClient.class)// + .build(); + + public TerremarkEnterpriseCloudRestClientModule() { + super(TerremarkEnterpriseCloudClient.class, TerremarkEnterpriseCloudAsyncClient.class, DELEGATE_MAP); + } + + @Override + protected void configure() { + super.configure(); + } + + @Override + protected void bindErrorHandlers() { + bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(TerremarkEnterpriseCloudErrorHandler.class); + bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(TerremarkEnterpriseCloudErrorHandler.class); + bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(TerremarkEnterpriseCloudErrorHandler.class); + } + + @Override + protected void bindRetryHandlers() { + bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(BackoffLimitedRetryHandler.class); + } + +} diff --git a/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/domain/Action.java b/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/domain/Action.java new file mode 100644 index 0000000000..d37d6acc1f --- /dev/null +++ b/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/domain/Action.java @@ -0,0 +1,132 @@ +package org.jclouds.trmk.enterprisecloud.domain; + +import static com.google.common.base.CaseFormat.LOWER_CAMEL; +import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.net.URI; +import java.util.Map; + +import org.jclouds.javax.annotation.Nullable; +import org.jclouds.trmk.enterprisecloud.domain.internal.BaseNamedResource; + +/** + * + * @author Adrian Cole + * + */ +public class Action extends BaseNamedResource<Action> { + public static enum ActionDisabled { + /** + * The actionDisabled attribute will have a value of noAccess when a user + * does not have permission to perform the action. For example, for a user + * with read-only access, all actions have actionDisabled="noAccess" set. + */ + NO_ACCESS, + /** + * The attribute will have a value of disabled when the action is contrary + * to business rules. For example, the action virtual machine with + * name="power:powerOff" has actionDisabled="disabled" when the virtual + * machine is currently powered off; a virtual machine, which is currently + * off, may not be powered off; it may only be powered on. If both + * conditions apply, actions have actionDisabled="noAccess" set. If + * neither condition applies, the attribute will not appear. + */ + DISABLED, + /** + * ActionDisabled was not parsed by jclouds. + */ + UNRECOGNIZED; + + public String value() { + return UPPER_UNDERSCORE.to(LOWER_CAMEL, name()); + } + + @Override + public String toString() { + return value(); + } + + public static ActionDisabled fromValue(String actionDisabled) { + try { + return valueOf(LOWER_CAMEL.to(UPPER_UNDERSCORE, checkNotNull(actionDisabled, "actionDisabled"))); + } catch (IllegalArgumentException e) { + return UNRECOGNIZED; + } + } + } + + @SuppressWarnings("unchecked") + public static Builder builder() { + return new Builder(); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder toBuilder() { + return new Builder().fromAction(this); + } + + public static class Builder extends BaseNamedResource.Builder<Action> { + + protected ActionDisabled actionDisabled; + + /** + * @see Action#getActionDisabled + */ + public Builder actionDisabled(ActionDisabled actionDisabled) { + this.actionDisabled = actionDisabled; + return this; + } + + @Override + public Action build() { + return new Action(href, type, name, actionDisabled); + } + + public Builder fromAction(Action in) { + return fromNamedResource(in).actionDisabled(in.getActionDisabled()); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder fromNamedResource(BaseNamedResource<Action> in) { + return Builder.class.cast(super.fromNamedResource(in)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder fromAttributes(Map<String, String> attributes) { + super.fromAttributes(attributes); + if (attributes.containsKey("actionDisabled")) + actionDisabled(ActionDisabled.fromValue(attributes.get("actionDisabled"))); + return this; + } + + } + + protected final ActionDisabled actionDisabled; + + public Action(URI href, String type, String name, @Nullable ActionDisabled actionDisabled) { + super(href, type, name); + this.actionDisabled = actionDisabled; + } + + /** + * The attribute actionDisabled appears only when the example has an action + * disabled for business rules. + * + * @return + */ + @Nullable + public ActionDisabled getActionDisabled() { + return actionDisabled; + } + +} \ No newline at end of file diff --git a/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/domain/Link.java b/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/domain/Link.java new file mode 100644 index 0000000000..c261ffe724 --- /dev/null +++ b/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/domain/Link.java @@ -0,0 +1,138 @@ +package org.jclouds.trmk.enterprisecloud.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.net.URI; +import java.util.Map; + +import org.jclouds.trmk.enterprisecloud.domain.internal.BaseNamedResource; + +/** + * + * @author Adrian Cole + * + */ +public class Link extends BaseNamedResource<Link> { + public static enum Relationship { + /** + * The entity in the link owns the entity in the response + */ + UP, + /** + * The entity in the response owns the entity in the link + */ + DOWN, + /** + * The entity in the link is an alternate view of the entity in the + * response + */ + ALTERNATE, + /** + * The link is a path to the first page in the pages of responses + */ + FIRST, + /** + * The link is a path to the previous page in the pages of responses + */ + PREVIOUS, + /** + * The link is a path to the next page in the pages of responses + */ + NEXT, + /** + * The link is a path to the last page in the pages of responses + */ + LAST, + /** + * Relationship was not parsed by jclouds. + */ + UNRECOGNIZED; + + public String value() { + return name().toLowerCase(); + } + + @Override + public String toString() { + return value(); + } + + public static Relationship fromValue(String rel) { + try { + return valueOf(checkNotNull(rel, "rel").toUpperCase()); + } catch (IllegalArgumentException e) { + return UNRECOGNIZED; + } + } + } + + @SuppressWarnings("unchecked") + public static Builder builder() { + return new Builder(); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder toBuilder() { + return new Builder().fromLink(this); + } + + public static class Builder extends BaseNamedResource.Builder<Link> { + + protected Relationship rel; + + /** + * @see Link#getRelationship + */ + public Builder rel(Relationship rel) { + this.rel = rel; + return this; + } + + @Override + public Link build() { + return new Link(href, name, type, rel); + } + + public Builder fromLink(Link in) { + return fromNamedResource(in).rel(in.getRelationship()); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder fromNamedResource(BaseNamedResource<Link> in) { + return Builder.class.cast(super.fromNamedResource(in)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder fromAttributes(Map<String, String> attributes) { + super.fromAttributes(attributes); + if (attributes.containsKey("rel")) + rel(Relationship.fromValue(attributes.get("rel"))); + return this; + } + } + + protected final Relationship rel; + + public Link(URI href, String type, String name, Relationship rel) { + super(href, type, name); + this.rel = checkNotNull(rel, "rel"); + } + + /** + * + * @return + */ + public Relationship getRelationship() { + return rel; + } + +} \ No newline at end of file diff --git a/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/domain/NamedResource.java b/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/domain/NamedResource.java new file mode 100644 index 0000000000..5952e58268 --- /dev/null +++ b/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/domain/NamedResource.java @@ -0,0 +1,83 @@ +package org.jclouds.trmk.enterprisecloud.domain; + +import java.net.URI; +import java.util.Map; + +import org.jclouds.trmk.enterprisecloud.domain.internal.BaseNamedResource; + +/** + * + * @author Adrian Cole + * + */ +public class NamedResource extends BaseNamedResource<NamedResource> { + + @SuppressWarnings("unchecked") + public static Builder builder() { + return new Builder(); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder toBuilder() { + return new Builder().fromNamedResource(this); + } + + public static class Builder extends BaseNamedResource.Builder<NamedResource> { + + /** + * {@inheritDoc} + */ + @Override + public NamedResource build() { + return new NamedResource(href, type, name); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder name(String name) { + return Builder.class.cast(super.name(name)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder type(String type) { + return Builder.class.cast(super.type(type)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder href(URI href) { + return Builder.class.cast(super.href(href)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder fromNamedResource(BaseNamedResource<NamedResource> in) { + return Builder.class.cast(super.fromNamedResource(in)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder fromAttributes(Map<String, String> in) { + return Builder.class.cast(super.fromAttributes(in)); + } + + } + + public NamedResource(URI href, String type, String name) { + super(href, type, name); + } +} \ No newline at end of file diff --git a/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/domain/Task.java b/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/domain/Task.java new file mode 100644 index 0000000000..281436dd9e --- /dev/null +++ b/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/domain/Task.java @@ -0,0 +1,291 @@ +package org.jclouds.trmk.enterprisecloud.domain; + +import static com.google.common.base.CaseFormat.UPPER_CAMEL; +import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.net.URI; +import java.util.Date; +import java.util.Map; + +import org.jclouds.javax.annotation.Nullable; +import org.jclouds.trmk.enterprisecloud.domain.internal.BaseResource; + +/** + * + * @author Adrian Cole + * + */ +public class Task extends BaseResource<Task> { + public static enum Status { + /** + * the task is queued for execution. + */ + QUEUED, + /** + * the task is running. + */ + RUNNING, + /** + * the task failed. + */ + FAILED, + /** + * the task completed successfully. + */ + SUCCESS, + /** + * the task failed with an error. + */ + ERROR, + /** + * Status was not parsed by jclouds. + */ + UNRECOGNIZED; + + public String value() { + return UPPER_UNDERSCORE.to(UPPER_CAMEL, name()); + } + + @Override + public String toString() { + return value(); + } + + public static Status fromValue(String status) { + try { + return valueOf(UPPER_CAMEL.to(UPPER_UNDERSCORE, checkNotNull(status, "status"))); + } catch (IllegalArgumentException e) { + return UNRECOGNIZED; + } + } + } + + @SuppressWarnings("unchecked") + public static Builder builder() { + return new Builder(); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder toBuilder() { + return new Builder().fromTask(this); + } + + public static class Builder extends BaseResource.Builder<Task> { + protected String operation; + protected Status status; + protected NamedResource impactedItem; + protected Date startTime; + protected Date completedTime; + protected String notes; + protected String errorMessage; + protected NamedResource initiatedBy; + + /** + * @see Task#getOperation + */ + public Builder operation(String operation) { + this.operation = operation; + return this; + } + + /** + * @see Task#getStatus + */ + public Builder status(Status status) { + this.status = status; + return this; + } + + /** + * @see Task#getImpactedItem + */ + public Builder impactedItem(NamedResource impactedItem) { + this.impactedItem = impactedItem; + return this; + } + + /** + * @see Task#getStartTime + */ + public Builder startTime(Date startTime) { + this.startTime = startTime; + return this; + } + + /** + * @see Task#getCompletedTime + */ + public Builder completedTime(Date completedTime) { + this.completedTime = completedTime; + return this; + } + + /** + * @see Task#getNotes + */ + public Builder notes(String notes) { + this.notes = notes; + return this; + } + + /** + * @see Task#getErrorMessage + */ + public Builder errorMessage(String errorMessage) { + this.errorMessage = errorMessage; + return this; + } + + /** + * @see Task#getInitiatedBy + */ + public Builder initiatedBy(NamedResource initiatedBy) { + this.initiatedBy = initiatedBy; + return this; + } + + @Override + public Task build() { + return new Task(href, type, operation, status, impactedItem, startTime, completedTime, notes, errorMessage, + initiatedBy); + } + + public Builder fromTask(Task in) { + return fromResource(in).operation(in.getOperation()).status(in.getStatus()).impactedItem(in.getImpactedItem()) + .startTime(in.getStartTime()).completedTime(in.getCompletedTime()).notes(in.getNotes()) + .errorMessage(in.getErrorMessage()).initiatedBy(in.getInitiatedBy()); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder fromResource(BaseResource<Task> in) { + return Builder.class.cast(super.fromResource(in)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder type(String type) { + return Builder.class.cast(super.type(type)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder href(URI href) { + return Builder.class.cast(super.href(href)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder fromAttributes(Map<String, String> attributes) { + return Builder.class.cast(super.fromAttributes(attributes)); + } + + } + + protected final String operation; + protected final Status status; + protected final NamedResource impactedItem; + protected final Date startTime; + protected final Date completedTime; + protected final String notes; + protected final String errorMessage; + protected final NamedResource initiatedBy; + + public Task(URI href, String type, String operation, Status status, NamedResource impactedItem, Date startTime, + @Nullable Date completedTime, @Nullable String notes, @Nullable String errorMessage, NamedResource initiatedBy) { + super(href, type); + this.operation = checkNotNull(operation, "operation"); + this.status = checkNotNull(status, "status"); + this.impactedItem = checkNotNull(impactedItem, "impactedItem"); + this.startTime = checkNotNull(startTime, "startTime"); + this.completedTime = completedTime;// null if Queued or Running + this.notes = notes; + this.errorMessage = errorMessage; + this.initiatedBy = checkNotNull(initiatedBy, "initiatedBy"); + } + + /** + * + * + * @return name of action performed + */ + public String getOperation() { + return operation; + } + + /** + * + * + * @return the status of the task + */ + public Status getStatus() { + return status; + } + + /** + * + * @return the item acted upon + */ + public NamedResource getImpactedItem() { + return impactedItem; + } + + /** + * + * @return time action started + */ + public Date getStartTime() { + return startTime; + } + + /** + * + * @return time action completed, or null if Queued or Running + */ + @Nullable + public Date getCompletedTime() { + return completedTime; + } + + /** + * @return notes on action + */ + public String getNotes() { + return notes; + } + + /** + * @return error message + */ + public String getErrorMessage() { + return errorMessage; + } + + /** + * + * @return the item acted upon + */ + public NamedResource getInitiatedBy() { + return initiatedBy; + } + + @Override + public String toString() { + return "[type=" + type + ", href=" + href + ", operation=" + operation + ", status=" + status + ", impactedItem=" + + impactedItem + ", startTime=" + startTime + ", completedTime=" + completedTime + ", notes=" + notes + + ", errorMessage=" + errorMessage + ", initiatedBy=" + initiatedBy + "]"; + } + +} \ No newline at end of file diff --git a/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/domain/internal/BaseNamedResource.java b/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/domain/internal/BaseNamedResource.java new file mode 100644 index 0000000000..f0ed4477d6 --- /dev/null +++ b/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/domain/internal/BaseNamedResource.java @@ -0,0 +1,114 @@ +package org.jclouds.trmk.enterprisecloud.domain.internal; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.net.URI; +import java.util.Map; + +/** + * Location of a Rest resource + * + * @author Adrian Cole + * + */ +public class BaseNamedResource<T extends BaseNamedResource<T>> extends BaseResource<T> { + + public static <T extends BaseNamedResource<T>> Builder<T> builder() { + return new Builder<T>(); + } + + public Builder<T> toBuilder() { + return new Builder<T>().fromNamedResource(this); + } + + public static class Builder<T extends BaseNamedResource<T>> extends BaseResource.Builder<T> { + + protected String name; + + /** + * @see BaseNamedResource#getName + */ + public Builder<T> name(String name) { + this.name = name; + return this; + } + + public BaseNamedResource<T> build() { + return new BaseNamedResource<T>(href, type, name); + } + + public Builder<T> fromNamedResource(BaseNamedResource<T> in) { + return fromResource(in).name(in.getName()); + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + public Builder<T> fromAttributes(Map<String, String> attributes) { + return Builder.class.cast(super.fromAttributes(attributes)).name(attributes.get("name")); + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + @Override + public Builder<T> fromResource(BaseResource<T> in) { + return Builder.class.cast(super.fromResource(in)); + } + } + + protected final String name; + + public BaseNamedResource(URI href, String type, String name) { + super(href, type); + this.name = checkNotNull(name, "name"); + } + + public String getName() { + return name; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((href == null) ? 0 : href.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((type == null) ? 0 : type.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + BaseNamedResource<?> other = (BaseNamedResource<?>) obj; + if (href == null) { + if (other.href != null) + return false; + } else if (!href.equals(other.href)) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (type == null) { + if (other.type != null) + return false; + } else if (!type.equals(other.type)) + return false; + return true; + } + + @Override + public String toString() { + return "[href=" + href + ", name=" + name + ", type=" + type + "]"; + } +} \ No newline at end of file diff --git a/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/domain/internal/BaseResource.java b/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/domain/internal/BaseResource.java new file mode 100644 index 0000000000..0bd85cb087 --- /dev/null +++ b/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/domain/internal/BaseResource.java @@ -0,0 +1,118 @@ +package org.jclouds.trmk.enterprisecloud.domain.internal; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.net.URI; +import java.util.Map; + +/** + * Location of a Rest resource + * + * @author Adrian Cole + * + */ +public class BaseResource<T extends BaseResource<T>> { + + public static <T extends BaseResource<T>> Builder<T> builder() { + return new Builder<T>(); + } + + public Builder<T> toBuilder() { + return new Builder<T>().fromResource(this); + } + + public static class Builder<T extends BaseResource<T>> { + + protected String type; + protected URI href; + + /** + * @see BaseResource#getType + */ + public Builder<T> type(String type) { + this.type = type; + return this; + } + + /** + * @see BaseResource#getHref + */ + public Builder<T> href(URI href) { + this.href = href; + return this; + } + + public BaseResource<T> build() { + return new BaseResource<T>(href, type); + } + + public Builder<T> fromResource(BaseResource<T> in) { + return type(in.getType()).href(in.getHref()); + } + + public Builder<T> fromAttributes(Map<String, String> attributes) { + return href(URI.create(attributes.get("href"))).type(attributes.get("type")); + } + + } + + protected final String type; + protected final URI href; + + public BaseResource(URI href, String type) { + this.type = checkNotNull(type, "type"); + this.href = checkNotNull(href, "href"); + } + + /** + * + * @return type definition, type, expressed as an HTTP Content-Type + */ + public String getType() { + return type; + } + + /** + * + * @return an opaque reference and should never be parsed + */ + public URI getHref() { + return href; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((href == null) ? 0 : href.hashCode()); + result = prime * result + ((type == null) ? 0 : type.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + BaseResource<?> other = (BaseResource<?>) obj; + if (href == null) { + if (other.href != null) + return false; + } else if (!href.equals(other.href)) + return false; + if (type == null) { + if (other.type != null) + return false; + } else if (!type.equals(other.type)) + return false; + return true; + } + + @Override + public String toString() { + return "[href=" + href + ", type=" + type + "]"; + } +} \ No newline at end of file diff --git a/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/features/TaskAsyncClient.java b/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/features/TaskAsyncClient.java new file mode 100644 index 0000000000..7053820e67 --- /dev/null +++ b/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/features/TaskAsyncClient.java @@ -0,0 +1,76 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.trmk.enterprisecloud.features; + +import java.net.URI; +import java.util.Set; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; + +import org.jclouds.http.filters.BasicAuthentication; +import org.jclouds.rest.annotations.EndpointParam; +import org.jclouds.rest.annotations.ExceptionParser; +import org.jclouds.rest.annotations.Headers; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.XMLResponseParser; +import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; +import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; +import org.jclouds.trmk.enterprisecloud.domain.Task; +import org.jclouds.trmk.enterprisecloud.xml.TaskHandler; +import org.jclouds.trmk.enterprisecloud.xml.TasksHandler; + +import com.google.common.util.concurrent.ListenableFuture; + +/** + * Provides asynchronous access to Task via their REST API. + * <p/> + * + * @see TaskClient + * @see <a href= + * "http://support.theenterprisecloud.com/kb/default.asp?id=984&Lang=1&SID=" + * /> + * @author Adrian Cole + */ +@RequestFilters(BasicAuthentication.class) +@Headers(keys = "x-trmk-version", values = "{jclouds.api-version}") +public interface TaskAsyncClient { + + /** + * @see TaskClient#getTasksInEnvironment + */ + @GET + @Path("/tasks/environments/{environmentId}") + @Consumes("application/vnd.tmrk.cloud.task; type=collection") + @XMLResponseParser(TasksHandler.class) + @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) + ListenableFuture<Set<Task>> getTasksInEnvironment(@PathParam("environmentId") long environmentId); + + /** + * @see TaskClient#getTask + */ + @GET + @Consumes("application/vnd.tmrk.cloud.task") + @XMLResponseParser(TaskHandler.class) + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture<Task> getTask(@EndpointParam URI taskId); + +} diff --git a/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/features/TaskClient.java b/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/features/TaskClient.java new file mode 100644 index 0000000000..fefef7cdcd --- /dev/null +++ b/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/features/TaskClient.java @@ -0,0 +1,57 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.trmk.enterprisecloud.features; + +import java.net.URI; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import org.jclouds.concurrent.Timeout; +import org.jclouds.trmk.enterprisecloud.domain.Task; + +/** + * Provides synchronous access to Task. + * <p/> + * + * @see TaskAsyncClient + * @see <a href= + * "http://support.theenterprisecloud.com/kb/default.asp?id=984&Lang=1&SID=" + * /> + * @author Adrian Cole + */ +@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS) +public interface TaskClient { + + /** + * The Get Tasks call returns information regarding the tasks in an + * environment. The task list is a history of changes to the environment. + * + * @return a history of changes to the environment. + */ + Set<Task> getTasksInEnvironment(long environmentId); + + /** + * The Get Tasks by ID call returns information regarding a specified task in + * an environment. + * + * @return the task or null if not found + */ + Task getTask(URI taskId); + +} diff --git a/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/handlers/TerremarkEnterpriseCloudErrorHandler.java b/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/handlers/TerremarkEnterpriseCloudErrorHandler.java new file mode 100644 index 0000000000..f3645de2e9 --- /dev/null +++ b/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/handlers/TerremarkEnterpriseCloudErrorHandler.java @@ -0,0 +1,92 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.trmk.enterprisecloud.handlers; + +import java.io.IOException; + +import javax.inject.Singleton; + +import org.jclouds.http.HttpCommand; +import org.jclouds.http.HttpErrorHandler; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.HttpResponseException; +import org.jclouds.rest.AuthorizationException; +import org.jclouds.rest.ResourceNotFoundException; +import org.jclouds.util.Strings2; + +import com.google.common.base.Throwables; +import com.google.common.io.Closeables; + +/** + * This will parse and set an appropriate exception on the command object. + * + * @author Adrian Cole + * + */ +@Singleton +public class TerremarkEnterpriseCloudErrorHandler implements HttpErrorHandler { + + public void handleError(HttpCommand command, HttpResponse response) { + // it is important to always read fully and close streams + String message = parseMessage(response); + Exception exception = message != null ? new HttpResponseException(command, response, message) + : new HttpResponseException(command, response); + try { + message = message != null ? message : String.format("%s -> %s", command.getCurrentRequest().getRequestLine(), + response.getStatusLine()); + switch (response.getStatusCode()) { + case 401: + case 403: + exception = new AuthorizationException(message, exception); + break; + case 404: + if (!command.getCurrentRequest().getMethod().equals("DELETE")) { + exception = new ResourceNotFoundException(message, exception); + } + break; + case 409: + exception = new IllegalStateException(message, exception); + case 500: + if (message != null && message.indexOf("Unable to determine package for") != -1) { + exception = new ResourceNotFoundException(message, exception); + } + } + } finally { + if (response.getPayload() != null) + Closeables.closeQuietly(response.getPayload().getInput()); + command.setException(exception); + } + } + + public String parseMessage(HttpResponse response) { + if (response.getPayload() == null) + return null; + try { + return Strings2.toStringAndClose(response.getPayload().getInput()); + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + try { + response.getPayload().getInput().close(); + } catch (IOException e) { + Throwables.propagate(e); + } + } + } +} diff --git a/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/xml/TaskHandler.java b/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/xml/TaskHandler.java new file mode 100644 index 0000000000..d2e8272b63 --- /dev/null +++ b/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/xml/TaskHandler.java @@ -0,0 +1,100 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.trmk.enterprisecloud.xml; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.util.SaxUtils.currentOrNull; +import static org.jclouds.util.SaxUtils.equalsOrSuffix; + +import java.util.Map; + +import javax.inject.Inject; + +import org.jclouds.date.DateService; +import org.jclouds.http.functions.ParseSax; +import org.jclouds.trmk.enterprisecloud.domain.NamedResource; +import org.jclouds.trmk.enterprisecloud.domain.Task; +import org.jclouds.util.SaxUtils; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; + +/** + * @author Adrian Cole + */ +public class TaskHandler extends ParseSax.HandlerWithResult<Task> { + + protected final DateService dateService; + + protected StringBuilder currentText = new StringBuilder(); + protected Task.Builder builder = Task.builder(); + + @Inject + public TaskHandler(DateService dateService) { + this.dateService = checkNotNull(dateService, "dateService"); + } + + public Task getResult() { + try { + return builder.build(); + } finally { + builder = Task.builder(); + } + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException { + Map<String, String> attributes = SaxUtils.cleanseAttributes(attrs); + if (equalsOrSuffix(qName, "Task")) { + builder.fromAttributes(attributes); + } else if (equalsOrSuffix(qName, "ImpactedItem")) { + builder.impactedItem(NamedResource.builder().fromAttributes(attributes).build()); + } else if (equalsOrSuffix(qName, "InitiatedBy")) { + builder.initiatedBy(NamedResource.builder().fromAttributes(attributes).build()); + } + } + + @Override + public void endElement(String uri, String localName, String qName) { + if (equalsOrSuffix(qName, "Operation")) { + builder.operation(currentOrNull(currentText)); + } else if (equalsOrSuffix(qName, "Status")) { + String status = currentOrNull(currentText); + if (status != null) + builder.status(Task.Status.fromValue(status)); + } else if (equalsOrSuffix(qName, "StartTime")) { + String date = currentOrNull(currentText); + if (date != null) + builder.startTime(dateService.iso8601DateParse(date)); + } else if (equalsOrSuffix(qName, "CompletedTime")) { + String date = currentOrNull(currentText); + if (date != null) + builder.completedTime(dateService.iso8601DateParse(date)); + } else if (equalsOrSuffix(qName, "Notes")) { + builder.notes(currentOrNull(currentText)); + } else if (equalsOrSuffix(qName, "ErrorMessage")) { + builder.errorMessage(currentOrNull(currentText)); + + } + currentText = new StringBuilder(); + } + + public void characters(char ch[], int start, int length) { + currentText.append(ch, start, length); + } +} diff --git a/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/xml/TasksHandler.java b/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/xml/TasksHandler.java new file mode 100644 index 0000000000..c2e8325795 --- /dev/null +++ b/sandbox-providers/trmk-enterprisecloud/src/main/java/org/jclouds/trmk/enterprisecloud/xml/TasksHandler.java @@ -0,0 +1,95 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.trmk.enterprisecloud.xml; + +import static org.jclouds.util.SaxUtils.equalsOrSuffix; + +import java.util.Set; + +import javax.inject.Inject; + +import org.jclouds.http.functions.ParseSax; +import org.jclouds.trmk.enterprisecloud.domain.Task; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSet.Builder; + +/** + * @author Adrian Cole + */ +public class TasksHandler extends ParseSax.HandlerWithResult<Set<Task>> { + public Set<Task> getResult() { + try { + return builder.build(); + } finally { + builder = ImmutableSet.<Task> builder(); + } + } + + protected final TaskHandler taskHandler; + + protected Builder<Task> builder = ImmutableSet.<Task> builder(); + + @Inject + public TasksHandler(TaskHandler taskHandler) { + this.taskHandler = taskHandler; + } + + protected boolean inTask; + + protected int depth = 0; + + public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException { + depth++; + if (depth == 2) { + if (equalsOrSuffix(qName, "Task")) { + inTask = true; + } + } + + if (inTask) { + taskHandler.startElement(uri, localName, qName, attrs); + } + + } + + @Override + public void endElement(String uri, String localName, String qName) { + depth--; + if (depth == 1) { + if (equalsOrSuffix(qName, "Task")) { + inTask = false; + builder.add(taskHandler.getResult()); + } + } + + if (inTask) { + taskHandler.endElement(uri, localName, qName); + } + } + + @Override + public void characters(char ch[], int start, int length) { + if (inTask) { + taskHandler.characters(ch, start, length); + } + } +} diff --git a/sandbox-providers/trmk-enterprisecloud/src/main/resources/META-INF/services/org.jclouds.providers.ProviderMetadata b/sandbox-providers/trmk-enterprisecloud/src/main/resources/META-INF/services/org.jclouds.providers.ProviderMetadata new file mode 100644 index 0000000000..73821bd35a --- /dev/null +++ b/sandbox-providers/trmk-enterprisecloud/src/main/resources/META-INF/services/org.jclouds.providers.ProviderMetadata @@ -0,0 +1 @@ +org.jclouds.trmk.enterprisecloud.TerremarkEnterpriseCloudProviderMetadata \ No newline at end of file diff --git a/sandbox-providers/trmk-enterprisecloud/src/test/java/org/jclouds/trmk/enterprisecloud/TerremarkEnterpriseCloudAsyncClientTest.java b/sandbox-providers/trmk-enterprisecloud/src/test/java/org/jclouds/trmk/enterprisecloud/TerremarkEnterpriseCloudAsyncClientTest.java new file mode 100644 index 0000000000..e1d3070c45 --- /dev/null +++ b/sandbox-providers/trmk-enterprisecloud/src/test/java/org/jclouds/trmk/enterprisecloud/TerremarkEnterpriseCloudAsyncClientTest.java @@ -0,0 +1,72 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.trmk.enterprisecloud; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +import org.jclouds.http.HttpRequest; +import org.jclouds.rest.internal.RestAnnotationProcessor; +import org.jclouds.trmk.enterprisecloud.features.BaseTerremarkEnterpriseCloudAsyncClientTest; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import com.google.inject.TypeLiteral; + +/** + * Tests behavior of {@code TerremarkEnterpriseCloudAsyncClient} + * + * @author Adrian Cole + */ +// NOTE:without testName, this will not call @Before* and fail w/NPE during +// surefire +@Test(groups = "unit", testName = "TerremarkEnterpriseCloudAsyncClientTest") +public class TerremarkEnterpriseCloudAsyncClientTest extends + BaseTerremarkEnterpriseCloudAsyncClientTest<TerremarkEnterpriseCloudAsyncClient> { + + private TerremarkEnterpriseCloudAsyncClient asyncClient; + private TerremarkEnterpriseCloudClient syncClient; + + public void testSync() throws SecurityException, NoSuchMethodException, InterruptedException, ExecutionException { + assert syncClient.getTaskClient() != null; + } + + public void testAsync() throws SecurityException, NoSuchMethodException, InterruptedException, ExecutionException { + assert asyncClient.getTaskClient() != null; + } + + @Override + protected TypeLiteral<RestAnnotationProcessor<TerremarkEnterpriseCloudAsyncClient>> createTypeLiteral() { + return new TypeLiteral<RestAnnotationProcessor<TerremarkEnterpriseCloudAsyncClient>>() { + }; + } + + @BeforeClass + @Override + protected void setupFactory() throws IOException { + super.setupFactory(); + asyncClient = injector.getInstance(TerremarkEnterpriseCloudAsyncClient.class); + syncClient = injector.getInstance(TerremarkEnterpriseCloudClient.class); + } + + @Override + protected void checkFilters(HttpRequest request) { + + } +} diff --git a/sandbox-providers/trmk-enterprisecloud/src/test/java/org/jclouds/trmk/enterprisecloud/TerremarkEnterpriseCloudErrorHandlerTest.java b/sandbox-providers/trmk-enterprisecloud/src/test/java/org/jclouds/trmk/enterprisecloud/TerremarkEnterpriseCloudErrorHandlerTest.java new file mode 100644 index 0000000000..21b7d7aad1 --- /dev/null +++ b/sandbox-providers/trmk-enterprisecloud/src/test/java/org/jclouds/trmk/enterprisecloud/TerremarkEnterpriseCloudErrorHandlerTest.java @@ -0,0 +1,118 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.trmk.enterprisecloud; + +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.reportMatcher; +import static org.easymock.classextension.EasyMock.createMock; +import static org.easymock.classextension.EasyMock.replay; +import static org.easymock.classextension.EasyMock.verify; + +import java.net.URI; + +import org.easymock.IArgumentMatcher; +import org.jclouds.http.HttpCommand; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.io.Payloads; +import org.jclouds.rest.AuthorizationException; +import org.jclouds.rest.ResourceNotFoundException; +import org.jclouds.trmk.enterprisecloud.handlers.TerremarkEnterpriseCloudErrorHandler; +import org.jclouds.util.Strings2; +import org.testng.annotations.Test; + +import com.google.inject.Guice; + +/** + * + * @author Adrian Cole + */ +@Test(groups = { "unit" }) +public class TerremarkEnterpriseCloudErrorHandlerTest { + + @Test + public void test401MakesAuthorizationException() { + assertCodeMakes("GET", URI.create("https://api.trmk-enterprisecloud.com/foo"), 401, "", "Unauthorized", + AuthorizationException.class); + } + + @Test + public void test404MakesResourceNotFoundException() { + assertCodeMakes("GET", URI.create("https://api.trmk-enterprisecloud.com/foo"), 404, "", "Not Found", + ResourceNotFoundException.class); + } + + @Test + public void test409AlreadyExists4MakesIllegalStateExceptionException() { + assertCodeMakes( + "GET", + URI.create("https://api.trmk-enterprisecloud.com/foo"), + 409, + "", + "<Error message=\"Catalog item with that name already exists.\" majorErrorCode=\"409\" minorErrorCode=\"CatalogItemAlreadyExists\"/>", + IllegalStateException.class); + } + + private void assertCodeMakes(String method, URI uri, int statusCode, String message, String content, + Class<? extends Exception> expected) { + assertCodeMakes(method, uri, statusCode, message, "text/xml", content, expected); + } + + private void assertCodeMakes(String method, URI uri, int statusCode, String message, String contentType, + String content, Class<? extends Exception> expected) { + + TerremarkEnterpriseCloudErrorHandler function = Guice.createInjector().getInstance( + TerremarkEnterpriseCloudErrorHandler.class); + + HttpCommand command = createMock(HttpCommand.class); + HttpRequest request = new HttpRequest(method, uri); + HttpResponse response = new HttpResponse(statusCode, message, Payloads.newInputStreamPayload(Strings2 + .toInputStream(content))); + response.getPayload().getContentMetadata().setContentType(contentType); + + expect(command.getCurrentRequest()).andReturn(request).atLeastOnce(); + command.setException(classEq(expected)); + + replay(command); + + function.handleError(command, response); + + verify(command); + } + + public static Exception classEq(final Class<? extends Exception> in) { + reportMatcher(new IArgumentMatcher() { + + @Override + public void appendTo(StringBuffer buffer) { + buffer.append("classEq("); + buffer.append(in); + buffer.append(")"); + } + + @Override + public boolean matches(Object arg) { + return arg.getClass() == in; + } + + }); + return null; + } + +} diff --git a/sandbox-providers/trmk-enterprisecloud/src/test/java/org/jclouds/trmk/enterprisecloud/TerremarkEnterpriseCloudProviderTest.java b/sandbox-providers/trmk-enterprisecloud/src/test/java/org/jclouds/trmk/enterprisecloud/TerremarkEnterpriseCloudProviderTest.java new file mode 100644 index 0000000000..cc8be97093 --- /dev/null +++ b/sandbox-providers/trmk-enterprisecloud/src/test/java/org/jclouds/trmk/enterprisecloud/TerremarkEnterpriseCloudProviderTest.java @@ -0,0 +1,35 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.trmk.enterprisecloud; + +import org.jclouds.providers.BaseProviderMetadataTest; +import org.jclouds.providers.ProviderMetadata; +import org.testng.annotations.Test; + +/** + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "TerremarkEnterpriseCloudProviderTest") +public class TerremarkEnterpriseCloudProviderTest extends BaseProviderMetadataTest { + + public TerremarkEnterpriseCloudProviderTest() { + super(new TerremarkEnterpriseCloudProviderMetadata(), ProviderMetadata.COMPUTE_TYPE); + } +} diff --git a/sandbox-providers/trmk-enterprisecloud/src/test/java/org/jclouds/trmk/enterprisecloud/features/BaseTerremarkEnterpriseCloudAsyncClientTest.java b/sandbox-providers/trmk-enterprisecloud/src/test/java/org/jclouds/trmk/enterprisecloud/features/BaseTerremarkEnterpriseCloudAsyncClientTest.java new file mode 100644 index 0000000000..e9eab59db9 --- /dev/null +++ b/sandbox-providers/trmk-enterprisecloud/src/test/java/org/jclouds/trmk/enterprisecloud/features/BaseTerremarkEnterpriseCloudAsyncClientTest.java @@ -0,0 +1,50 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.trmk.enterprisecloud.features; + +import static org.testng.Assert.assertEquals; + +import java.util.Properties; + +import org.jclouds.http.HttpRequest; +import org.jclouds.http.filters.BasicAuthentication; +import org.jclouds.rest.RestClientTest; +import org.jclouds.rest.RestContextFactory; +import org.jclouds.rest.RestContextSpec; +import org.jclouds.trmk.enterprisecloud.TerremarkEnterpriseCloudAsyncClient; +import org.jclouds.trmk.enterprisecloud.TerremarkEnterpriseCloudClient; + +/** + * @author Adrian Cole + */ +public abstract class BaseTerremarkEnterpriseCloudAsyncClientTest<T> extends RestClientTest<T> { + + @Override + protected void checkFilters(HttpRequest request) { + assertEquals(request.getFilters().size(), 1); + assertEquals(request.getFilters().get(0).getClass(), BasicAuthentication.class); + } + + @Override + public RestContextSpec<TerremarkEnterpriseCloudClient, TerremarkEnterpriseCloudAsyncClient> createContextSpec() { + Properties props = new Properties(); + return new RestContextFactory().createContextSpec("trmk-enterprisecloud", "apiKey", "secretKey", props); + } + +} diff --git a/sandbox-providers/trmk-enterprisecloud/src/test/java/org/jclouds/trmk/enterprisecloud/features/BaseTerremarkEnterpriseCloudClientLiveTest.java b/sandbox-providers/trmk-enterprisecloud/src/test/java/org/jclouds/trmk/enterprisecloud/features/BaseTerremarkEnterpriseCloudClientLiveTest.java new file mode 100644 index 0000000000..d51c6d13fc --- /dev/null +++ b/sandbox-providers/trmk-enterprisecloud/src/test/java/org/jclouds/trmk/enterprisecloud/features/BaseTerremarkEnterpriseCloudClientLiveTest.java @@ -0,0 +1,65 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.trmk.enterprisecloud.features; + +import java.util.Properties; + +import org.jclouds.logging.log4j.config.Log4JLoggingModule; +import org.jclouds.rest.RestContext; +import org.jclouds.rest.RestContextFactory; +import org.jclouds.sshj.config.SshjSshClientModule; +import org.jclouds.trmk.enterprisecloud.TerremarkEnterpriseCloudAsyncClient; +import org.jclouds.trmk.enterprisecloud.TerremarkEnterpriseCloudClient; +import org.testng.annotations.AfterGroups; +import org.testng.annotations.BeforeGroups; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableSet; +import com.google.inject.Module; + +/** + * Tests behavior of {@code TerremarkEnterpriseCloudClient} + * + * @author Adrian Cole + */ +@Test(groups = "live") +public class BaseTerremarkEnterpriseCloudClientLiveTest { + + protected RestContext<TerremarkEnterpriseCloudClient, TerremarkEnterpriseCloudAsyncClient> context; + protected Module module; + + @BeforeGroups(groups = { "live" }) + public void setupClient() { + // TODO organize this like other compute tests + String identity = System.getProperty("test.trmk-enterprisecloud.identity", "readonly@terremark.com"); + String credential = System.getProperty("test.trmk-enterprisecloud.credential", "T3rr3m@rk"); + + Properties props = new Properties(); + + context = new RestContextFactory().createContext("trmk-enterprisecloud", identity, credential, + ImmutableSet.<Module> of(new Log4JLoggingModule(), new SshjSshClientModule()), props); + } + + @AfterGroups(groups = "live") + protected void tearDown() { + if (context != null) + context.close(); + } + +} diff --git a/sandbox-providers/trmk-enterprisecloud/src/test/java/org/jclouds/trmk/enterprisecloud/features/TaskAsyncClientTest.java b/sandbox-providers/trmk-enterprisecloud/src/test/java/org/jclouds/trmk/enterprisecloud/features/TaskAsyncClientTest.java new file mode 100644 index 0000000000..660a7f8b52 --- /dev/null +++ b/sandbox-providers/trmk-enterprisecloud/src/test/java/org/jclouds/trmk/enterprisecloud/features/TaskAsyncClientTest.java @@ -0,0 +1,82 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.trmk.enterprisecloud.features; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.net.URI; + +import org.jclouds.http.HttpRequest; +import org.jclouds.http.functions.ParseSax; +import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; +import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; +import org.jclouds.rest.internal.RestAnnotationProcessor; +import org.jclouds.trmk.enterprisecloud.xml.TaskHandler; +import org.jclouds.trmk.enterprisecloud.xml.TasksHandler; +import org.testng.annotations.Test; + +import com.google.inject.TypeLiteral; + +/** + * Tests annotation parsing of {@code TaskAsyncClient} + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "TaskAsyncClientTest") +public class TaskAsyncClientTest extends BaseTerremarkEnterpriseCloudAsyncClientTest<TaskAsyncClient> { + + public void testGetTasksInEnvironment() throws SecurityException, NoSuchMethodException, IOException { + Method method = TaskAsyncClient.class.getMethod("getTasksInEnvironment", long.class); + HttpRequest httpRequest = processor.createRequest(method, 1l); + + assertRequestLineEquals(httpRequest, "GET http://209.251.187.125/livespec/tasks/environments/1 HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, + "Accept: application/vnd.tmrk.cloud.task; type=collection\nx-trmk-version: 2011-07-01\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, ParseSax.class); + assertSaxResponseParserClassEquals(method, TasksHandler.class); + assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class); + + checkFilters(httpRequest); + + } + + public void testGetTask() throws SecurityException, NoSuchMethodException, IOException { + Method method = TaskAsyncClient.class.getMethod("getTask", URI.class); + HttpRequest httpRequest = processor.createRequest(method, URI.create("http://209.251.187.125/livespec/tasks/1")); + + assertRequestLineEquals(httpRequest, "GET http://209.251.187.125/livespec/tasks/1 HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: application/vnd.tmrk.cloud.task\nx-trmk-version: 2011-07-01\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, ParseSax.class); + assertSaxResponseParserClassEquals(method, TaskHandler.class); + assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class); + + checkFilters(httpRequest); + + } + + @Override + protected TypeLiteral<RestAnnotationProcessor<TaskAsyncClient>> createTypeLiteral() { + return new TypeLiteral<RestAnnotationProcessor<TaskAsyncClient>>() { + }; + } +} diff --git a/sandbox-providers/trmk-enterprisecloud/src/test/java/org/jclouds/trmk/enterprisecloud/features/TaskClientLiveTest.java b/sandbox-providers/trmk-enterprisecloud/src/test/java/org/jclouds/trmk/enterprisecloud/features/TaskClientLiveTest.java new file mode 100644 index 0000000000..09cd937d64 --- /dev/null +++ b/sandbox-providers/trmk-enterprisecloud/src/test/java/org/jclouds/trmk/enterprisecloud/features/TaskClientLiveTest.java @@ -0,0 +1,59 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.trmk.enterprisecloud.features; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +import java.util.Set; + +import org.jclouds.trmk.enterprisecloud.domain.Task; +import org.testng.annotations.BeforeGroups; +import org.testng.annotations.Test; + +/** + * Tests behavior of {@code TaskClient} + * + * @author Adrian Cole + */ +@Test(groups = "live", testName = "TaskClientLiveTest") +public class TaskClientLiveTest extends BaseTerremarkEnterpriseCloudClientLiveTest { + @BeforeGroups(groups = { "live" }) + public void setupClient() { + super.setupClient(); + client = context.getApi().getTaskClient(); + } + + private TaskClient client; + + @Test + public void testGetTasks() { + // TODO: don't hard-code id + // TODO: docs say don't parse the href, yet no xml includes "identifier", + // I suspect we may need to change to URI args as opposed to long + Set<Task> response = client.getTasksInEnvironment(1); + assert null != response; + + assertTrue(response.size() >= 0); + for (Task task : response) { + assertEquals(client.getTask(task.getHref()), task); + assert task.getStatus() != Task.Status.UNRECOGNIZED : response; + } + } +} diff --git a/sandbox-providers/trmk-enterprisecloud/src/test/java/org/jclouds/trmk/enterprisecloud/xml/TaskHandlerTest.java b/sandbox-providers/trmk-enterprisecloud/src/test/java/org/jclouds/trmk/enterprisecloud/xml/TaskHandlerTest.java new file mode 100644 index 0000000000..f628bb4720 --- /dev/null +++ b/sandbox-providers/trmk-enterprisecloud/src/test/java/org/jclouds/trmk/enterprisecloud/xml/TaskHandlerTest.java @@ -0,0 +1,69 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.trmk.enterprisecloud.xml; + +import static org.testng.Assert.assertEquals; + +import java.io.InputStream; +import java.net.URI; + +import org.jclouds.date.internal.SimpleDateFormatDateService; +import org.jclouds.http.functions.ParseSax; +import org.jclouds.http.functions.ParseSax.Factory; +import org.jclouds.http.functions.config.SaxParserModule; +import org.jclouds.trmk.enterprisecloud.domain.NamedResource; +import org.jclouds.trmk.enterprisecloud.domain.Task; +import org.testng.annotations.Test; + +import com.google.inject.Guice; +import com.google.inject.Injector; + +/** + * Tests behavior of {@code TaskHandler} + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "TaskHandlerTest") +public class TaskHandlerTest { + static SimpleDateFormatDateService dateService = new SimpleDateFormatDateService(); + static Task expected = Task + .builder() + .href(URI.create("/livespec/tasks/1002")) + .type("application/vnd.tmrk.cloud.task") + .operation("Add Node Service") + .status(Task.Status.ERROR) + .impactedItem( + NamedResource.builder().href(URI.create("/livespec/nodeservices/1")).name("sample node internet 1") + .type("application/vnd.tmrk.cloud.nodeService").build()) + .startTime(dateService.iso8601DateParse("2011-11-07T11:19:13.38225Z")) + .completedTime(dateService.iso8601DateParse("2011-11-07T11:20:13.38225Z")) + .notes("Some notes about the operation.") + .errorMessage("sample error message 1 here") + .initiatedBy( + NamedResource.builder().href(URI.create("/livespec/admin/users/1")).name("User 1") + .type("application/vnd.tmrk.cloud.admin.user").build()).build(); + + public void test() { + InputStream is = getClass().getResourceAsStream("/task.xml"); + Injector injector = Guice.createInjector(new SaxParserModule()); + Factory factory = injector.getInstance(ParseSax.Factory.class); + Task result = factory.create(injector.getInstance(TaskHandler.class)).parse(is); + assertEquals(result.toString(), expected.toString()); + } +} diff --git a/sandbox-providers/trmk-enterprisecloud/src/test/java/org/jclouds/trmk/enterprisecloud/xml/TasksHandlerTest.java b/sandbox-providers/trmk-enterprisecloud/src/test/java/org/jclouds/trmk/enterprisecloud/xml/TasksHandlerTest.java new file mode 100644 index 0000000000..f40d173b72 --- /dev/null +++ b/sandbox-providers/trmk-enterprisecloud/src/test/java/org/jclouds/trmk/enterprisecloud/xml/TasksHandlerTest.java @@ -0,0 +1,55 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.trmk.enterprisecloud.xml; + +import static org.testng.Assert.assertEquals; + +import java.io.InputStream; +import java.util.Set; + +import org.jclouds.http.functions.ParseSax; +import org.jclouds.http.functions.ParseSax.Factory; +import org.jclouds.http.functions.config.SaxParserModule; +import org.jclouds.trmk.enterprisecloud.domain.Task; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableSet; +import com.google.inject.Guice; +import com.google.inject.Injector; + +/** + * Tests behavior of {@code TasksHandler} + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "TasksHandlerTest") +public class TasksHandlerTest { + + public void test() { + + InputStream is = getClass().getResourceAsStream("/tasks.xml"); + Injector injector = Guice.createInjector(new SaxParserModule()); + Factory factory = injector.getInstance(ParseSax.Factory.class); + Set<Task> result = factory.create(injector.getInstance(TasksHandler.class)).parse(is); + Set<Task> expected = ImmutableSet.of(TaskHandlerTest.expected); + + assertEquals(result.toString(), expected.toString()); + + } +} diff --git a/sandbox-providers/trmk-enterprisecloud/src/test/resources/log4j.xml b/sandbox-providers/trmk-enterprisecloud/src/test/resources/log4j.xml new file mode 100644 index 0000000000..63810d3ca0 --- /dev/null +++ b/sandbox-providers/trmk-enterprisecloud/src/test/resources/log4j.xml @@ -0,0 +1,151 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> + + <!-- + For more configuration infromation and examples see the Apache + Log4j website: http://logging.apache.org/log4j/ + --> +<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" + debug="false"> + + <!-- A time/date based rolling appender --> + <appender name="WIREFILE" class="org.apache.log4j.DailyRollingFileAppender"> + <param name="File" value="target/test-data/jclouds-wire.log" /> + <param name="Append" value="true" /> + + <!-- Rollover at midnight each day --> + <param name="DatePattern" value="'.'yyyy-MM-dd" /> + + <param name="Threshold" value="TRACE" /> + + <layout class="org.apache.log4j.PatternLayout"> + <!-- The default pattern: Date Priority [Category] Message\n --> + <param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" /> + + <!-- + The full pattern: Date MS Priority [Category] + (Thread:NDC) Message\n <param name="ConversionPattern" + value="%d %-5r %-5p [%c] (%t:%x) %m%n"/> + --> + </layout> + </appender> + + <!-- A time/date based rolling appender --> + <appender name="FILE" class="org.apache.log4j.DailyRollingFileAppender"> + <param name="File" value="target/test-data/jclouds.log" /> + <param name="Append" value="true" /> + + <!-- Rollover at midnight each day --> + <param name="DatePattern" value="'.'yyyy-MM-dd" /> + + <param name="Threshold" value="TRACE" /> + + <layout class="org.apache.log4j.PatternLayout"> + <!-- The default pattern: Date Priority [Category] Message\n --> + <param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" /> + + <!-- + The full pattern: Date MS Priority [Category] + (Thread:NDC) Message\n <param name="ConversionPattern" + value="%d %-5r %-5p [%c] (%t:%x) %m%n"/> + --> + </layout> + </appender> + + <!-- A time/date based rolling appender --> + <appender name="COMPUTEFILE" class="org.apache.log4j.DailyRollingFileAppender"> + <param name="File" value="target/test-data/jclouds-compute.log" /> + <param name="Append" value="true" /> + + <!-- Rollover at midnight each day --> + <param name="DatePattern" value="'.'yyyy-MM-dd" /> + + <param name="Threshold" value="TRACE" /> + + <layout class="org.apache.log4j.PatternLayout"> + <!-- The default pattern: Date Priority [Category] Message\n --> + <param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" /> + + <!-- + The full pattern: Date MS Priority [Category] + (Thread:NDC) Message\n <param name="ConversionPattern" + value="%d %-5r %-5p [%c] (%t:%x) %m%n"/> + --> + </layout> + </appender> + + <!-- A time/date based rolling appender --> + <appender name="SSHFILE" class="org.apache.log4j.DailyRollingFileAppender"> + <param name="File" value="target/test-data/jclouds-ssh.log" /> + <param name="Append" value="true" /> + + <!-- Rollover at midnight each day --> + <param name="DatePattern" value="'.'yyyy-MM-dd" /> + + <param name="Threshold" value="TRACE" /> + + <layout class="org.apache.log4j.PatternLayout"> + <!-- The default pattern: Date Priority [Category] Message\n --> + <param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" /> + + <!-- + The full pattern: Date MS Priority [Category] + (Thread:NDC) Message\n <param name="ConversionPattern" + value="%d %-5r %-5p [%c] (%t:%x) %m%n"/> + --> + </layout> + </appender> + + <appender name="ASYNCCOMPUTE" class="org.apache.log4j.AsyncAppender"> + <appender-ref ref="COMPUTEFILE" /> + </appender> + + <appender name="ASYNCSSH" class="org.apache.log4j.AsyncAppender"> + <appender-ref ref="SSHFILE" /> + </appender> + + <appender name="ASYNC" class="org.apache.log4j.AsyncAppender"> + <appender-ref ref="FILE" /> + </appender> + + <appender name="ASYNCWIRE" class="org.apache.log4j.AsyncAppender"> + <appender-ref ref="WIREFILE" /> + </appender> + + <!-- ================ --> + <!-- Limit categories --> + <!-- ================ --> + + <category name="org.jclouds"> + <priority value="DEBUG" /> + <appender-ref ref="ASYNC" /> + </category> + + <category name="jclouds.headers"> + <priority value="DEBUG" /> + <appender-ref ref="ASYNCWIRE" /> + </category> + + <category name="jclouds.ssh"> + <priority value="DEBUG" /> + <appender-ref ref="ASYNCSSH" /> + </category> + + <category name="jclouds.wire"> + <priority value="DEBUG" /> + <appender-ref ref="ASYNCWIRE" /> + </category> + + <category name="jclouds.compute"> + <priority value="TRACE" /> + <appender-ref ref="ASYNCCOMPUTE" /> + </category> + <!-- ======================= --> + <!-- Setup the Root category --> + <!-- ======================= --> + + <root> + <priority value="WARN" /> + </root> + +</log4j:configuration> diff --git a/sandbox-providers/trmk-enterprisecloud/src/test/resources/task.xml b/sandbox-providers/trmk-enterprisecloud/src/test/resources/task.xml new file mode 100644 index 0000000000..7ab78f7a11 --- /dev/null +++ b/sandbox-providers/trmk-enterprisecloud/src/test/resources/task.xml @@ -0,0 +1,10 @@ +<Task href="/livespec/tasks/1002" type="application/vnd.tmrk.cloud.task"> + <Operation>Add Node Service</Operation> + <Status>Error</Status> + <ImpactedItem href="/livespec/nodeservices/1" name="sample node internet 1" type="application/vnd.tmrk.cloud.nodeService"/> + <StartTime>2011-11-07T11:19:13.38225Z</StartTime> + <CompletedTime>2011-11-07T11:20:13.38225Z</CompletedTime> + <Notes>Some notes about the operation.</Notes> + <ErrorMessage>sample error message 1 here</ErrorMessage> + <InitiatedBy href="/livespec/admin/users/1" name="User 1" type="application/vnd.tmrk.cloud.admin.user"/> +</Task> \ No newline at end of file diff --git a/sandbox-providers/trmk-enterprisecloud/src/test/resources/tasks.xml b/sandbox-providers/trmk-enterprisecloud/src/test/resources/tasks.xml new file mode 100644 index 0000000000..ef8fa1b9e3 --- /dev/null +++ b/sandbox-providers/trmk-enterprisecloud/src/test/resources/tasks.xml @@ -0,0 +1,12 @@ + <Tasks href="/livespec/tasks/environments/1" type="application/vnd.tmrk.cloud.task; type=collection"> + <Task href="/livespec/tasks/1002" type="application/vnd.tmrk.cloud.task"> + <Operation>Add Node Service</Operation> + <Status>Error</Status> + <ImpactedItem href="/livespec/nodeservices/1" name="sample node internet 1" type="application/vnd.tmrk.cloud.nodeService"/> + <StartTime>2011-11-07T11:19:13.38225Z</StartTime> + <CompletedTime>2011-11-07T11:20:13.38225Z</CompletedTime> + <Notes>Some notes about the operation.</Notes> + <ErrorMessage>sample error message 1 here</ErrorMessage> + <InitiatedBy href="/livespec/admin/users/1" name="User 1" type="application/vnd.tmrk.cloud.admin.user"/> +</Task> +</Tasks> \ No newline at end of file