JCLOUDS-664 Azurecompute-arm ResourceGroupApi
Project: http://git-wip-us.apache.org/repos/asf/jclouds-labs/repo Commit: http://git-wip-us.apache.org/repos/asf/jclouds-labs/commit/a4334d46 Tree: http://git-wip-us.apache.org/repos/asf/jclouds-labs/tree/a4334d46 Diff: http://git-wip-us.apache.org/repos/asf/jclouds-labs/diff/a4334d46 Branch: refs/heads/master Commit: a4334d46d8ac45859945978771fc481303d65af9 Parents: ff028de Author: Rita Zhang <[email protected]> Authored: Thu Feb 11 18:43:45 2016 -0800 Committer: Ignasi Barrera <[email protected]> Committed: Wed Apr 6 21:23:08 2016 +0200 ---------------------------------------------------------------------- README.md | 2 +- azurecompute-arm/README.md | 109 ++++++++++++ azurecompute-arm/pom.xml | 177 +++++++++++++++++++ .../azurecompute.arm/AzureComputeApi.java | 43 +++++ .../AzureComputeProviderMetadata.java | 94 ++++++++++ .../AzureManagementApiMetadata.java | 86 +++++++++ .../config/AzureComputeHttpApiModule.java | 57 ++++++ .../config/AzureComputeParserModule.java | 29 +++ .../config/AzureComputeProperties.java | 34 ++++ .../azurecompute.arm/domain/ResourceGroup.java | 51 ++++++ .../azurecompute.arm/features/JobApi.java | 41 +++++ .../features/ResourceGroupApi.java | 96 ++++++++++ .../functions/ParseJobStatus.java | 54 ++++++ .../azurecompute.arm/functions/URIParser.java | 39 ++++ .../handlers/AzureComputeErrorHandler.java | 86 +++++++++ .../AzureComputeProviderMetadataTest.java | 28 +++ .../features/JobApiMockTest.java | 62 +++++++ .../features/ResourceGroupApiLiveTest.java | 137 ++++++++++++++ .../features/ResourceGroupApiMockTest.java | 150 ++++++++++++++++ .../functions/URIParserTest.java | 51 ++++++ .../AbstractAzureComputeApiLiveTest.java | 69 ++++++++ .../internal/AzureLiveTestUtils.java | 34 ++++ .../internal/BaseAzureComputeApiLiveTest.java | 65 +++++++ .../internal/BaseAzureComputeApiMockTest.java | 134 ++++++++++++++ .../src/test/resources/resourcegroup.json | 11 ++ .../src/test/resources/resourcegroups.json | 22 +++ .../test/resources/resourcegroupupdated.json | 9 + pom.xml | 1 + 28 files changed, 1770 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a4334d46/README.md ---------------------------------------------------------------------- diff --git a/README.md b/README.md index 91c4b50..b656b5d 100644 --- a/README.md +++ b/README.md @@ -7,4 +7,4 @@ License ------- Copyright (C) 2009-2014 The Apache Software Foundation -Licensed under the Apache License, Version 2.0 +Licensed under the Apache License, Version 2.0 \ No newline at end of file http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a4334d46/azurecompute-arm/README.md ---------------------------------------------------------------------- diff --git a/azurecompute-arm/README.md b/azurecompute-arm/README.md new file mode 100644 index 0000000..a3abe63 --- /dev/null +++ b/azurecompute-arm/README.md @@ -0,0 +1,109 @@ +jclouds Labs - Azure Compute ARM Provider +============ + +Build status for azurecomputearm module: +[](http://devopsfunjenkins.westus.cloudapp.azure.com:8080/job/jclouds-labs-azurecompute-arm/org.apache.jclouds.labs$azurecomputearm/) + + +## Setting Up Test Credentials + +### Create a Service Principal + +Install and configure Azure CLI following these [steps](http://azure.microsoft.com/en-us/documentation/articles/xplat-cli/). + +Using the Azure CLI, run the following commands to create a service principal + +```bash +# Set mode to ARM +azure config mode arm + +# Enter your Microsoft account credentials when prompted +azure login + +# Set current subscription to create a service principal +azure account set <Subscription-id> + +# Create an AAD application with your information. +azure ad app create --name <name> --password <password> --home-page <home-page> --identifier-uris <identifier-uris> + +# For example: azure ad app create --name "jcloudsarm" --password abcd --home-page "https://jcloudsarm" --identifier-uris "https://jcloudsarm" + +# Output will include a value for `Application Id`, which will be used for the live tests + +# Create a Service Principal +azure ad sp create <Application-id> + +# Output will include a value for `Object Id` + +``` + +Run the following commands to assign roles to the service principal + +```bash +# Assign roles for this service principal +azure role assignment create --objectId <Object-id> -o Contributor -c /subscriptions/<Subscription-id>/ + +``` + +Verify service principal + +```bash +azure login -u <Application-id> -p <password> --service-principal --tenant <Tenant-id> + +``` + +## Run Live Tests + + +Use the following to run the live tests + +```bash +# ResourceGroupApiLiveTest: + +mvn -Dtest=ResourceGroupApiLiveTest -Dtest.azurecompute-arm.identity=<Application-id> -Dtest.azurecompute-arm.subscriptionid=<Subscription-id> -Dtest.azurecompute-arm.credential=<password> -Dtest.azurecompute-arm.endpoint="https://management.azure.com" -Dtest.jclouds.oauth.resource="https://management.azure.com/" -Dtest.oauth.endpoint="https://login.microsoftonline.com/<Tenant-id>/oauth2/token" test + +# AuthorizationApiLiveTest: + +mvn -Dtest=AuthorizationApiLiveTest -Dtest.oauth.identity=<Application-id> -Dtest.oauth.credential=<password> -Dtest.jclouds.oauth.resource="https://management.azure.com/" -Dtest.oauth.endpoint="https://login.microsoftonline.com/<Tenant-id>/oauth2/token" -Dtest.jclouds.oauth.audience="https://management.azure.com/" test + +# LocationApiLiveTest: + +mvn -Dtest=LocationApiLiveTest -Dtest.azurecompute-arm.identity=<Application-id> -Dtest.azurecompute-arm.subscriptionid=<Subscription-id> -Dtest.azurecompute-arm.credential=<password> -Dtest.azurecompute-arm.endpoint="https://management.azure.com" -Dtest.jclouds.oauth.resource="https://management.azure.com/" -Dtest.oauth.endpoint="https://login.microsoftonline.com/<Tenant-id>/oauth2/token" test + +# StorageAccountApiLiveTest: + +mvn -Dtest=StorageAccountApiLiveTest -Dtest.azurecompute-arm.identity=<Application-id> -Dtest.azurecompute-arm.subscriptionid=<Subscription-id> -Dtest.azurecompute-arm.credential=<password> -Dtest.azurecompute-arm.endpoint="https://management.azure.com" -Dtest.jclouds.oauth.resource="https://management.azure.com/" -Dtest.oauth.endpoint="https://login.microsoftonline.com/<Tenant-id>/oauth2/token" test + +# VirtualNetworkApiLiveTest: + +mvn -Dtest=VirtualNetworkApiLiveTest -Dtest.azurecompute-arm.identity=<Application-id> -Dtest.azurecompute-arm.subscriptionid=<Subscription-id> -Dtest.azurecompute-arm.credential=<password> -Dtest.azurecompute-arm.resourcegroup="jcloudstest" -Dtest.azurecompute-arm.endpoint="https://management.azure.com" -Dtest.jclouds.oauth.resource="https://management.azure.com/" -Dtest.oauth.endpoint="https://login.microsoftonline.com/<Tenant-id>/oauth2/token" test + +# SubnetApiLiveTest + +mvn -Dtest=SubnetApiLiveTest -Dtest.azurecompute-arm.identity=<Application-id> -Dtest.azurecompute-arm.subscriptionid=<Subscription-id> -Dtest.azurecompute-arm.credential=<password> -Dtest.azurecompute-arm.resourcegroup="jcloudstest" -Dtest.azurecompute-arm.endpoint="https://management.azure.com" -Dtest.jclouds.oauth.resource="https://management.azure.com/" -Dtest.oauth.endpoint="https://login.microsoftonline.com/<Tenant-id>/oauth2/token" test + +# NetworkInterfaceCardApiLiveTest + +mvn -Dtest=NetworkInterfaceCardApiLiveTest -Dtest.azurecompute-arm.identity=<Application-id> -Dtest.azurecompute-arm.subscriptionid=<Subscription-id> -Dtest.azurecompute-arm.credential=<password> -Dtest.azurecompute-arm.resourcegroup="jcloudstest" -Dtest.azurecompute-arm.endpoint="https://management.azure.com" -Dtest.jclouds.oauth.resource="https://management.azure.com/" -Dtest.oauth.endpoint="https://login.microsoftonline.com/<Tenant-id>/oauth2/token" test + +# VirtualMachineApiLiveTest: + +mvn -Dtest=VirtualMachineApiLiveTest -Dtest.azurecompute-arm.identity=<Application-id> -Dtest.azurecompute-arm.subscriptionid=<Subscription-id> -Dtest.azurecompute-arm.credential=<password> -Dtest.azurecompute-arm.endpoint="https://management.azure.com" -Dtest.jclouds.oauth.resource="https://management.azure.com/" -Dtest.oauth.endpoint="https://login.microsoftonline.com/<Tenant-id>/oauth2/token" test + +# VMSizeApiLiveTest: + +mvn -Dtest=VMSizeApiLiveTest -Dtest.azurecompute-arm.identity=<Application-id> -Dtest.azurecompute-arm.subscriptionid=<Subscription-id> -Dtest.azurecompute-arm.credential=<password> -Dtest.azurecompute-arm.endpoint="https://management.azure.com" -Dtest.jclouds.oauth.resource="https://management.azure.com/" -Dtest.oauth.endpoint="https://login.microsoftonline.com/<Tenant-id>/oauth2/token" test + +# PublicIPAddressApiLiveTest + +mvn -Dtest=PublicIPAddressApiLiveTest -Dtest.azurecompute-arm.identity=<Application-id> -Dtest.azurecompute-arm.subscriptionid=<Subscription-id> -Dtest.azurecompute-arm.credential=<password> -Dtest.azurecompute-arm.endpoint="https://management.azure.com" -Dtest.jclouds.oauth.resource="https://management.azure.com/" -Dtest.oauth.endpoint="https://login.microsoftonline.com/<Tenant-id>/oauth2/token" test + +# OSImageApiLiveTest: + +mvn -Dtest=OSImageApiLiveTest -Dtest.azurecompute-arm.identity=<Application-id> -Dtest.azurecompute-arm.subscriptionid=<Subscription-id> -Dtest.azurecompute-arm.credential=<password> -Dtest.azurecompute-arm.endpoint="https://management.azure.com" -Dtest.jclouds.oauth.resource="https://management.azure.com/" -Dtest.oauth.endpoint="https://login.microsoftonline.com/<Tenant-id>/oauth2/token" test + +# DeploymentApiLiveTest: + +mvn -Dtest=DeploymentApiLiveTest -Dtest.azurecompute-arm.identity=<Application-id> -Dtest.azurecompute-arm.subscriptionid=<Subscription-id> -Dtest.azurecompute-arm.credential=<password> -Dtest.azurecompute-arm.endpoint="https://management.azure.com/" -Dtest.jclouds.oauth.resource="https://management.azure.com/" -Dtest.oauth.endpoint="https://login.microsoftonline.com/<Tenant-id>/oauth2/token" test + +``` \ No newline at end of file http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a4334d46/azurecompute-arm/pom.xml ---------------------------------------------------------------------- diff --git a/azurecompute-arm/pom.xml b/azurecompute-arm/pom.xml new file mode 100644 index 0000000..807ab20 --- /dev/null +++ b/azurecompute-arm/pom.xml @@ -0,0 +1,177 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +--> +<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/xsd/maven-4.0.0.xsd"> + + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.jclouds.labs</groupId> + <artifactId>jclouds-labs</artifactId> + <version>2.0.0-SNAPSHOT</version> + </parent> + <artifactId>azurecompute-arm</artifactId> + <name>jclouds Azure Compute ARM API</name> + <description>jclouds components to access an implementation of Azure's ARM Compute Service</description> + <packaging>bundle</packaging> + + <properties> + <test.jclouds.azurecompute-arm.subscription-id>FIXME_subscription-id</test.jclouds.azurecompute-arm.subscription-id> + <test.jclouds.azurecompute-arm.tenant-id>FIXME_tenant-id</test.jclouds.azurecompute-arm.tenant-id> + <test.azurecompute-arm.endpoint>https://management.azure.com/subscriptions/${test.jclouds.azurecompute-arm.subscription-id}</test.azurecompute-arm.endpoint> + <test.azurecompute-arm.api-version>2014-04-01-preview</test.azurecompute-arm.api-version> + <test.azurecompute-arm.build-version /> + <test.azurecompute-arm.identity>app id</test.azurecompute-arm.identity> + <test.azurecompute-arm.credential>app password</test.azurecompute-arm.credential> + <jclouds.osgi.export>org.jclouds.azurecompute-arm*;version="${project.version}"</jclouds.osgi.export> + <jclouds.osgi.import>org.jclouds*;version="${project.version}",*</jclouds.osgi.import> + </properties> + + <dependencies> + <dependency> + <groupId>org.apache.jclouds</groupId> + <artifactId>jclouds-compute</artifactId> + <version>${project.parent.version}</version> + </dependency> + <dependency> + <groupId>com.google.auto.service</groupId> + <artifactId>auto-service</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.google.auto.value</groupId> + <artifactId>auto-value</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.apache.jclouds</groupId> + <artifactId>jclouds-core</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.apache.jclouds.api</groupId> + <artifactId>oauth</artifactId> + <version>${project.version}</version> + <type>jar</type> + </dependency> + <dependency> + <groupId>org.apache.jclouds.api</groupId> + <artifactId>oauth</artifactId> + <version>${project.version}</version> + <type>test-jar</type> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.jclouds</groupId> + <artifactId>jclouds-compute</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.apache.jclouds</groupId> + <artifactId>jclouds-compute</artifactId> + <version>${project.version}</version> + <type>test-jar</type> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.jclouds</groupId> + <artifactId>jclouds-core</artifactId> + <version>${project.version}</version> + <type>test-jar</type> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.jclouds.driver</groupId> + <artifactId>jclouds-slf4j</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.jclouds.driver</groupId> + <artifactId>jclouds-sshj</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.jclouds.driver</groupId> + <artifactId>jclouds-slf4j</artifactId> + <version>${project.parent.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>ch.qos.logback</groupId> + <artifactId>logback-classic</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.jclouds.driver</groupId> + <artifactId>jclouds-okhttp</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>com.squareup.okhttp</groupId> + <artifactId>mockwebserver</artifactId> + <scope>test</scope> + <exclusions> + <!-- Already provided by jclouds-sshj --> + <exclusion> + <groupId>org.bouncycastle</groupId> + <artifactId>bcprov-jdk15on</artifactId> + </exclusion> + </exclusions> + </dependency> + </dependencies> + + <profiles> + <profile> + <id>live</id> + + <build> + <defaultGoal>clean verify</defaultGoal> + + <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> + <systemPropertyVariables> + <test.azurecompute-arm.endpoint>${test.azurecompute-arm.endpoint}</test.azurecompute-arm.endpoint> + <test.azurecompute-arm.api-version>${test.azurecompute-arm.api-version}</test.azurecompute-arm.api-version> + <test.azurecompute-arm.build-version>${test.azurecompute-arm.build-version}</test.azurecompute-arm.build-version> + <test.azurecompute-arm.identity>${test.azurecompute-arm.identity}</test.azurecompute-arm.identity> + <test.azurecompute-arm.credential>${test.azurecompute-arm.credential}</test.azurecompute-arm.credential> + <test.jclouds.azurecompute-arm.subscription-id>${test.jclouds.azurecompute-arm.subscription-id}</test.jclouds.azurecompute-arm.subscription-id> + <test.jclouds.azurecompute-arm.tenant-id>${test.jclouds.azurecompute-arm.tenant-id}</test.jclouds.azurecompute-arm.tenant-id> + </systemPropertyVariables> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> + </profiles> + +</project> http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a4334d46/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/AzureComputeApi.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/AzureComputeApi.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/AzureComputeApi.java new file mode 100644 index 0000000..a897c9a --- /dev/null +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/AzureComputeApi.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.azurecompute.arm; + +import java.io.Closeable; + +import org.jclouds.azurecompute.arm.features.JobApi; +import org.jclouds.azurecompute.arm.features.ResourceGroupApi; +import org.jclouds.rest.annotations.Delegate; + +/** + * The Azure Resource Manager API is a REST API for managing your services and deployments. + * <p/> + * + * @see <a href="https://msdn.microsoft.com/en-us/library/azure/dn790568.aspx" >doc</a> + */ +public interface AzureComputeApi extends Closeable { + + /** + * The Azure Resource Manager API includes operations for managing resource groups in your subscription. + * + * @see <a href="https://msdn.microsoft.com/en-us/library/azure/dn790546.aspx">docs</a> + */ + @Delegate + ResourceGroupApi getResourceGroupApi(); + + @Delegate + JobApi getJobApi(); +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a4334d46/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/AzureComputeProviderMetadata.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/AzureComputeProviderMetadata.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/AzureComputeProviderMetadata.java new file mode 100644 index 0000000..68d7a86 --- /dev/null +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/AzureComputeProviderMetadata.java @@ -0,0 +1,94 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.azurecompute.arm; + +import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_POLL_INITIAL_PERIOD; +import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_POLL_MAX_PERIOD; +import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_TIMEOUT; +import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TCP_RULE_FORMAT; +import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TCP_RULE_REGEXP; +import static org.jclouds.oauth.v2.config.CredentialType.CLIENT_CREDENTIALS_SECRET; +import static org.jclouds.oauth.v2.config.OAuthProperties.RESOURCE; +import static org.jclouds.oauth.v2.config.OAuthProperties.CREDENTIAL_TYPE; + +import java.net.URI; +import java.util.Properties; +import org.jclouds.providers.ProviderMetadata; +import org.jclouds.providers.internal.BaseProviderMetadata; + +import com.google.auto.service.AutoService; + +@AutoService(ProviderMetadata.class) +public class AzureComputeProviderMetadata extends BaseProviderMetadata { + + public static Builder builder() { + return new Builder(); + } + + @Override + public Builder toBuilder() { + return builder().fromProviderMetadata(this); + } + + public AzureComputeProviderMetadata() { + super(builder()); + } + + public static Properties defaultProperties() { + final Properties properties = AzureManagementApiMetadata.defaultProperties(); + properties.setProperty(OPERATION_TIMEOUT, "60000"); + properties.setProperty(OPERATION_POLL_INITIAL_PERIOD, "5"); + properties.setProperty(OPERATION_POLL_MAX_PERIOD, "15"); + properties.setProperty(TCP_RULE_FORMAT, "tcp_%s-%s"); + properties.setProperty(TCP_RULE_REGEXP, "tcp_\\d{1,5}-\\d{1,5}"); + properties.put("oauth.endpoint", "https://login.microsoftonline.com/oauth2/token"); + properties.put(RESOURCE, "https://management.azure.com"); + properties.put(CREDENTIAL_TYPE, CLIENT_CREDENTIALS_SECRET.toString()); + return properties; + } + + public AzureComputeProviderMetadata(final Builder builder) { + super(builder); + } + + public static class Builder extends BaseProviderMetadata.Builder { + + protected Builder() { + super(); + + id("azurecompute-arm") + .name("Azure Resource Management ") + .apiMetadata(new AzureManagementApiMetadata()) + .endpoint("https://management.azure.com/subscriptions/SUBSCRIPTION_ID") + .homepage(URI.create("https://www.windowsazure.com/")) + .console(URI.create("https://windows.azure.com/default.aspx")) + .linkedServices("azureblob") + .defaultProperties(AzureComputeProviderMetadata.defaultProperties()); + } + + @Override + public AzureComputeProviderMetadata build() { + return new AzureComputeProviderMetadata(this); + } + + @Override + public Builder fromProviderMetadata(final ProviderMetadata providerMetadata) { + super.fromProviderMetadata(providerMetadata); + return this; + } + } +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a4334d46/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/AzureManagementApiMetadata.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/AzureManagementApiMetadata.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/AzureManagementApiMetadata.java new file mode 100644 index 0000000..9a3292c --- /dev/null +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/AzureManagementApiMetadata.java @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.azurecompute.arm; + +import static org.jclouds.reflect.Reflection2.typeToken; + +import java.net.URI; +import java.util.Properties; + +import org.jclouds.apis.ApiMetadata; +import org.jclouds.azurecompute.arm.config.AzureComputeHttpApiModule; +import org.jclouds.compute.ComputeServiceContext; +import org.jclouds.rest.internal.BaseHttpApiMetadata; +import org.jclouds.oauth.v2.config.OAuthModule; + +import com.google.common.collect.ImmutableSet; +import com.google.inject.Module; +import org.jclouds.http.okhttp.config.OkHttpCommandExecutorServiceModule; + +/** + * Implementation of {@link ApiMetadata} for Microsoft Azure Resource Manager REST API + */ +public class AzureManagementApiMetadata extends BaseHttpApiMetadata<AzureComputeApi> { + + @Override + public Builder toBuilder() { + return new Builder().fromApiMetadata(this); + } + + public AzureManagementApiMetadata() { + this(new Builder()); + } + + protected AzureManagementApiMetadata(final Builder builder) { + super(builder); + } + + public static Properties defaultProperties() { + final Properties properties = BaseHttpApiMetadata.defaultProperties(); + return properties; + } + + public static class Builder extends BaseHttpApiMetadata.Builder<AzureComputeApi, Builder> { + + protected Builder() { + super(); + + id("azurecompute-arm") + .name("Microsoft Azure Resource Manager REST API") + .identityName("Azure Service Principal Application Id") + .credentialName("Azure Service Principal Application Password") + .endpointName("Resource Manager Endpoint ending in your Subscription Id") + .documentation(URI.create("https://msdn.microsoft.com/en-us/library/azure/dn790568.aspx")) + .defaultProperties(AzureManagementApiMetadata.defaultProperties()) + .view(typeToken(ComputeServiceContext.class)) + .defaultModules(ImmutableSet.<Class<? extends Module>>builder() + .add(OAuthModule.class) + .add(OkHttpCommandExecutorServiceModule.class) + .add(AzureComputeHttpApiModule.class).build()); + } + + @Override + public AzureManagementApiMetadata build() { + return new AzureManagementApiMetadata(this); + } + + @Override + protected Builder self() { + return this; + } + } +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a4334d46/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/config/AzureComputeHttpApiModule.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/config/AzureComputeHttpApiModule.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/config/AzureComputeHttpApiModule.java new file mode 100644 index 0000000..9041d96 --- /dev/null +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/config/AzureComputeHttpApiModule.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.azurecompute.arm.config; +import org.jclouds.azurecompute.arm.AzureComputeApi; +import org.jclouds.azurecompute.arm.handlers.AzureComputeErrorHandler; +import org.jclouds.http.HttpErrorHandler; +import org.jclouds.http.annotation.ClientError; +import org.jclouds.http.annotation.Redirection; +import org.jclouds.http.annotation.ServerError; +import org.jclouds.location.suppliers.ImplicitLocationSupplier; +import org.jclouds.location.suppliers.implicit.OnlyLocationOrFirstRegionOptionallyMatchingRegionId; + +import org.jclouds.rest.ConfiguresHttpApi; +import org.jclouds.rest.config.HttpApiModule; +import org.jclouds.oauth.v2.config.OAuthScopes; + +import com.google.inject.Scopes; + +@ConfiguresHttpApi +public class AzureComputeHttpApiModule extends HttpApiModule<AzureComputeApi> { + + @Override + protected void bindErrorHandlers() { + bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(AzureComputeErrorHandler.class); + bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(AzureComputeErrorHandler.class); + bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(AzureComputeErrorHandler.class); + } + + @Override + protected void installLocations() { + super.installLocations(); + bind(ImplicitLocationSupplier.class). + to(OnlyLocationOrFirstRegionOptionallyMatchingRegionId.class). + in(Scopes.SINGLETON); + } + + @Override + protected void configure() { + install(new AzureComputeParserModule()); + super.configure(); + bind(OAuthScopes.class).toInstance(OAuthScopes.ReadOrWriteScopes.create("read", "read write")); + } +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a4334d46/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/config/AzureComputeParserModule.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/config/AzureComputeParserModule.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/config/AzureComputeParserModule.java new file mode 100644 index 0000000..396f5be --- /dev/null +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/config/AzureComputeParserModule.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.azurecompute.arm.config; + +import org.jclouds.json.config.GsonModule; + +import com.google.inject.AbstractModule; + +public class AzureComputeParserModule extends AbstractModule { + + @Override + protected void configure() { + bind(GsonModule.DateAdapter.class).to(GsonModule.Iso8601DateAdapter.class); + } +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a4334d46/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/config/AzureComputeProperties.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/config/AzureComputeProperties.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/config/AzureComputeProperties.java new file mode 100644 index 0000000..e16b5da --- /dev/null +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/config/AzureComputeProperties.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.azurecompute.arm.config; + +/** + * Configuration properties and constants used in Azure Resource Manager connections. + */ +public class AzureComputeProperties { + + public static final String OPERATION_TIMEOUT = "jclouds.azurecompute.arm.operation.timeout"; + + public static final String OPERATION_POLL_INITIAL_PERIOD = "jclouds.azurecompute.arm.operation.poll.initial.period"; + + public static final String OPERATION_POLL_MAX_PERIOD = "jclouds.azurecompute.arm.operation.poll.max.period"; + + public static final String TCP_RULE_FORMAT = "jclouds.azurecompute.arm.tcp.rule.format"; + + public static final String TCP_RULE_REGEXP = "jclouds.azurecompute.arm.tcp.rule.regexp"; + +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a4334d46/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/domain/ResourceGroup.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/domain/ResourceGroup.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/domain/ResourceGroup.java new file mode 100644 index 0000000..1be93ab --- /dev/null +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/domain/ResourceGroup.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.azurecompute.arm.domain; + +import com.google.auto.value.AutoValue; +import java.util.Map; +import org.jclouds.javax.annotation.Nullable; +import org.jclouds.json.SerializedNames; +import com.google.common.collect.ImmutableMap; + + +@AutoValue +public abstract class ResourceGroup { + + @AutoValue + public abstract static class ResourceGroupProperties{ + @Nullable + public abstract String provisioningState(); + + @SerializedNames({"provisioningState"}) + public static ResourceGroupProperties create(final String provisioningState) { + return new AutoValue_ResourceGroup_ResourceGroupProperties(provisioningState); + } + } + + public abstract String id(); + public abstract String name(); + public abstract String location(); + @Nullable + public abstract Map<String, String> tags(); + public abstract ResourceGroupProperties properties(); + + @SerializedNames({"id", "name", "location", "tags", "properties"}) + public static ResourceGroup create(String id, String name, String location, @Nullable Map<String, String> tags, ResourceGroupProperties properties) { + return new AutoValue_ResourceGroup(id, name, location, tags == null ? ImmutableMap.<String, String>builder().build() : ImmutableMap.copyOf(tags), properties); + } +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a4334d46/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/features/JobApi.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/features/JobApi.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/features/JobApi.java new file mode 100644 index 0000000..7dd75a9 --- /dev/null +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/features/JobApi.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.azurecompute.arm.features; +import java.io.Closeable; +import java.net.URI; +import javax.ws.rs.Consumes; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.GET; +import org.jclouds.oauth.v2.filters.OAuthFilter; +import org.jclouds.rest.annotations.EndpointParam; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.ResponseParser; +import org.jclouds.azurecompute.arm.functions.ParseJobStatus; +import org.jclouds.azurecompute.arm.functions.ParseJobStatus.JobStatus; + +/** + * The Azure Resource Manager API checks for job status and progress. + */ + +@RequestFilters(OAuthFilter.class) +@Consumes(MediaType.APPLICATION_JSON) +public interface JobApi extends Closeable{ + @GET + @ResponseParser(ParseJobStatus.class) + JobStatus jobStatus(@EndpointParam URI jobURI); +} + http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a4334d46/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/features/ResourceGroupApi.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/features/ResourceGroupApi.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/features/ResourceGroupApi.java new file mode 100644 index 0000000..1ad47d9 --- /dev/null +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/features/ResourceGroupApi.java @@ -0,0 +1,96 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.azurecompute.arm.features; +import java.io.Closeable; +import java.net.URI; +import java.util.List; +import java.util.Map; +import javax.inject.Named; +import javax.ws.rs.Consumes; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; + +import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404; +import org.jclouds.Fallbacks.NullOnNotFoundOr404; +import org.jclouds.azurecompute.arm.domain.ResourceGroup; +import org.jclouds.javax.annotation.Nullable; +import org.jclouds.oauth.v2.filters.OAuthFilter; +import org.jclouds.rest.annotations.QueryParams; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.SelectJson; +import org.jclouds.rest.annotations.Fallback; +import org.jclouds.rest.annotations.MapBinder; +import org.jclouds.rest.annotations.PayloadParam; +import org.jclouds.rest.annotations.PATCH; +import org.jclouds.rest.annotations.ResponseParser; +import org.jclouds.azurecompute.arm.functions.URIParser; + + +import org.jclouds.rest.binders.BindToJsonPayload; + +/** + * The Azure Resource Manager API includes operations for managing resource groups in your subscription. + * + * @see <a href="https://msdn.microsoft.com/en-us/library/azure/dn790546.aspx">docs</a> + */ +@Path("/resourcegroups") + +@QueryParams(keys = "api-version", values = "2015-01-01") +@RequestFilters(OAuthFilter.class) +@Consumes(MediaType.APPLICATION_JSON) +public interface ResourceGroupApi extends Closeable{ + + @Named("resourcegroup:list") + @SelectJson("value") + @GET + @Fallback(EmptyListOnNotFoundOr404.class) + List<ResourceGroup> list(); + + @Named("resourcegroup:create") + @PUT + @Path("/{name}") + @Produces(MediaType.APPLICATION_JSON) + @MapBinder(BindToJsonPayload.class) + ResourceGroup create(@PathParam("name") String name, @PayloadParam("location") String location, @Nullable @PayloadParam("tags")Map<String, String> tags); + + @Named("resourcegroup:get") + @GET + @Path("/{name}") + @Fallback(NullOnNotFoundOr404.class) + @Nullable + ResourceGroup get(@PathParam("name") String name); + + @Named("resourcegroup:update") + @PATCH + @Produces(MediaType.APPLICATION_JSON) + @Path("/{name}") + @MapBinder(BindToJsonPayload.class) + ResourceGroup update(@PathParam("name") String name, @Nullable @PayloadParam("tags")Map<String, String> tags); + + @Named("resourcegroup:delete") + @DELETE + @ResponseParser(URIParser.class) + @Path("/{name}") + @Fallback(NullOnNotFoundOr404.class) + URI delete(@PathParam("name") String name); +} + http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a4334d46/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/functions/ParseJobStatus.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/functions/ParseJobStatus.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/functions/ParseJobStatus.java new file mode 100644 index 0000000..f39db90 --- /dev/null +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/functions/ParseJobStatus.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.azurecompute.arm.functions; +import com.google.common.base.Function; +import org.jclouds.http.HttpResponse; + +import javax.inject.Singleton; +/** + * Parses job status from http response + */ +@Singleton +public class ParseJobStatus implements Function<HttpResponse, ParseJobStatus.JobStatus> { + public enum JobStatus { + + DONE, + IN_PROGRESS, + FAILED, + UNRECOGNIZED; + + public static JobStatus fromString(final String text) { + if (text != null) { + for (JobStatus status : JobStatus.values()) { + if (text.equalsIgnoreCase(status.name())) { + return status; + } + } + } + return UNRECOGNIZED; + } + } + public JobStatus apply(final HttpResponse from) { + if (from.getStatusCode() == 202 ){ + return JobStatus.IN_PROGRESS; + } else if (from.getStatusCode() == 200 ){ + return JobStatus.DONE; + } else { + return JobStatus.FAILED; + } + } +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a4334d46/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/functions/URIParser.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/functions/URIParser.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/functions/URIParser.java new file mode 100644 index 0000000..78fd10d --- /dev/null +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/functions/URIParser.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.azurecompute.arm.functions; +import com.google.common.base.Function; +import org.jclouds.http.HttpResponse; + +import javax.inject.Singleton; + +import java.net.URI; +/** + * Parses job status from http response + */ +@Singleton +public class URIParser implements Function<HttpResponse, URI> { + public URI apply(final HttpResponse from) { + if (from.getStatusCode() == 202 && from.getHeaders().containsKey("Location")){ + String uri = from.getFirstHeaderOrNull("Location"); + return URI.create(uri); + + } else if (from.getStatusCode() == 200){ + return null; + } + throw new IllegalStateException("did not receive expected response code and header in: " + from); + } +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a4334d46/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/handlers/AzureComputeErrorHandler.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/handlers/AzureComputeErrorHandler.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/handlers/AzureComputeErrorHandler.java new file mode 100644 index 0000000..d5a2d69 --- /dev/null +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute.arm/handlers/AzureComputeErrorHandler.java @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.azurecompute.arm.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.Closeables2; +import org.jclouds.util.Strings2; + +/** + * This will parse and set an appropriate exception on the command object. + */ +@Singleton +public class AzureComputeErrorHandler implements HttpErrorHandler { + + @Override + public void handleError(final HttpCommand command, final HttpResponse response) { + // it is important to always read fully and close streams + String message = parseMessage(response); + Exception exception = message == null + ? new HttpResponseException(command, response) + : new HttpResponseException(command, response, message); + try { + message = message == null + ? String.format("%s -> %s", command.getCurrentRequest().getRequestLine(), response.getStatusLine()) + : message; + switch (response.getStatusCode()) { + case 400: + exception = new IllegalArgumentException(message, exception); + break; + 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); + break; + + default: + } + } finally { + Closeables2.closeQuietly(response.getPayload()); + command.setException(exception); + } + } + + public String parseMessage(final HttpResponse response) { + if (response.getPayload() == null) { + return null; + } + try { + return Strings2.toStringAndClose(response.getPayload().openStream()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a4334d46/azurecompute-arm/src/test/java/org/jclouds/azurecompute.arm/AzureComputeProviderMetadataTest.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute.arm/AzureComputeProviderMetadataTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute.arm/AzureComputeProviderMetadataTest.java new file mode 100644 index 0000000..2003f9a --- /dev/null +++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute.arm/AzureComputeProviderMetadataTest.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.azurecompute.arm; + +import org.jclouds.providers.internal.BaseProviderMetadataTest; +import org.testng.annotations.Test; + +@Test(groups = "unit", testName = "AzureManagementProviderMetadataTest") +public class AzureComputeProviderMetadataTest extends BaseProviderMetadataTest { + + public AzureComputeProviderMetadataTest() { + super(new AzureComputeProviderMetadata(), new AzureManagementApiMetadata()); + } +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a4334d46/azurecompute-arm/src/test/java/org/jclouds/azurecompute.arm/features/JobApiMockTest.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute.arm/features/JobApiMockTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute.arm/features/JobApiMockTest.java new file mode 100644 index 0000000..ba87ca5 --- /dev/null +++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute.arm/features/JobApiMockTest.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.azurecompute.arm.features; + +import java.io.IOException; +import java.net.URI; +import org.jclouds.azurecompute.arm.functions.ParseJobStatus.JobStatus; +import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiMockTest; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +@Test(groups = "unit", testName = "JobApiMockTest", singleThreaded = true) +public class JobApiMockTest extends BaseAzureComputeApiMockTest { + + final String requestUrl = "/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1SVEVTVC1DRU5UUkFMVVMiLCJqb2JMb2NhdGlvbiI6ImNlbnRyYWx1cyJ9?api-version=2014-04-01"; + + public void testGetJobStatus() throws IOException, InterruptedException { + server.enqueue(response200()); + + JobStatus status = api.getJobApi().jobStatus(URI.create(requestUrl)); + + assertEquals(status, JobStatus.DONE); + + assertSent(server, "GET", requestUrl); + } + + public void testGetJobStatusInProgress() throws InterruptedException { + server.enqueue(response202WithHeader()); + + JobStatus status = api.getJobApi().jobStatus(URI.create(requestUrl)); + + assertEquals(status, JobStatus.IN_PROGRESS); + + assertSent(server, "GET", requestUrl); + } + + public void testGetJobStatusFailed() throws InterruptedException { + server.enqueue(jsonResponse("/resourcegroup.json").setStatus("HTTP/1.1 204 No Content")); + + JobStatus status = api.getJobApi().jobStatus(URI.create(requestUrl)); + + assertEquals(status, JobStatus.FAILED); + + assertSent(server, "GET", requestUrl); + } + +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a4334d46/azurecompute-arm/src/test/java/org/jclouds/azurecompute.arm/features/ResourceGroupApiLiveTest.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute.arm/features/ResourceGroupApiLiveTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute.arm/features/ResourceGroupApiLiveTest.java new file mode 100644 index 0000000..1ad8bf3 --- /dev/null +++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute.arm/features/ResourceGroupApiLiveTest.java @@ -0,0 +1,137 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.azurecompute.arm.features; + +import com.google.common.base.Predicate; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; + +import java.net.URI; +import java.util.List; + +import org.jclouds.azurecompute.arm.domain.ResourceGroup; +import org.jclouds.azurecompute.arm.functions.ParseJobStatus.JobStatus; +import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiLiveTest; + +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.assertEquals; +import org.jclouds.util.Predicates2; + + +@Test(groups = "live", testName = "ResourceGroupApiLiveTest") +public class ResourceGroupApiLiveTest extends BaseAzureComputeApiLiveTest { + private String resourcegroup; + + @BeforeClass + @Override + public void setup(){ + super.setup(); + resourcegroup = getResourceGroupName(); + } + + private ResourceGroupApi api() { + return api.getResourceGroupApi(); + } + + @Test(dependsOnMethods = "testCreate") + public void testList() { + final List<ResourceGroup> resourceGroups = api().list(); + + assertTrue(resourceGroups.size() > 0); + + assertTrue(Iterables.any(resourceGroups, new Predicate<ResourceGroup>() { + + @Override + public boolean apply(final ResourceGroup group) { + return resourcegroup.equals(group.name()); + } + })); + } + + @Test(dependsOnMethods = "testCreate") + public void testRead() { + final ResourceGroup group = api().get(resourcegroup); + assertNotNull(group); + assertEquals(group.name(), resourcegroup); + assertEquals(group.location(), LOCATION); + } + + public void testCreate() { + + final ResourceGroup resourceGroup = api().create("jcloudstest", LOCATION, null); + assertEquals(resourceGroup.name(), "jcloudstest"); + assertEquals(resourceGroup.location(), LOCATION); + assertEquals(resourceGroup.tags().size(), 0); + assertTrue(resourceGroup.id().contains("jcloudstest")); + assertEquals(resourceGroup.properties().provisioningState(), "Succeeded"); + } + + @Test(dependsOnMethods = "testCreate") + public void testUpdateWithEmptyTag() { + ImmutableMap<String, String> tags = ImmutableMap.<String, String>builder().build(); + + final ResourceGroup resourceGroup = api().update("jcloudstest", tags); + + assertEquals(resourceGroup.tags().size(), 0); + assertEquals(resourceGroup.properties().provisioningState(), "Succeeded"); + } + + @Test(dependsOnMethods = "testCreate") + public void testUpdateWithTag() { + ImmutableMap<String, String> tags = ImmutableMap.<String, String>builder().put("test1", "value1").build(); + + final ResourceGroup resourceGroup = api().update("jcloudstest", tags); + + assertEquals(resourceGroup.tags().size(), 1); + assertEquals(resourceGroup.properties().provisioningState(), "Succeeded"); + } + + @AfterClass(alwaysRun = true) + public void testDelete() throws Exception { + URI uri = api().delete(resourcegroup); + + if (uri != null){ + assertTrue(uri.toString().contains("api-version")); + assertTrue(uri.toString().contains("operationresults")); + + boolean jobDone = Predicates2.retry(new Predicate<URI>() { + @Override public boolean apply(URI uri) { + return JobStatus.DONE == api.getJobApi().jobStatus(uri); + } + }, 60 * 1 * 1000 /* 1 minute timeout */).apply(uri); + assertTrue(jobDone, "delete operation did not complete in the configured timeout"); + } + + uri = api().delete("jcloudstest"); + if (uri != null){ + assertTrue(uri.toString().contains("api-version")); + assertTrue(uri.toString().contains("operationresults")); + + boolean jobDone = Predicates2.retry(new Predicate<URI>() { + @Override public boolean apply(URI uri) { + return JobStatus.DONE == api.getJobApi().jobStatus(uri); + } + }, 60 * 1 * 1000 /* 1 minute timeout */).apply(uri); + assertTrue(jobDone, "delete operation did not complete in the configured timeout"); + } + } +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a4334d46/azurecompute-arm/src/test/java/org/jclouds/azurecompute.arm/features/ResourceGroupApiMockTest.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute.arm/features/ResourceGroupApiMockTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute.arm/features/ResourceGroupApiMockTest.java new file mode 100644 index 0000000..91cb2b1 --- /dev/null +++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute.arm/features/ResourceGroupApiMockTest.java @@ -0,0 +1,150 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.azurecompute.arm.features; + +import static com.google.common.collect.Iterables.isEmpty; +import static com.google.common.collect.Iterables.size; +import static org.testng.Assert.assertNotNull; + +import java.net.URI; +import java.util.List; +import com.google.common.collect.ImmutableMap; + +import org.jclouds.azurecompute.arm.domain.ResourceGroup; +import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiMockTest; +import org.testng.annotations.Test; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertEquals; + +@Test(groups = "unit", testName = "ResourceGroupApiMockTest", singleThreaded = true) +public class ResourceGroupApiMockTest extends BaseAzureComputeApiMockTest { + + final String subscriptionid = "12345678-1234-1234-1234-123456789012"; + final String requestUrl = "/subscriptions/" + subscriptionid + "/resourcegroups"; + final String version = "?api-version=2015-01-01"; + + public void testListResourceGroups() throws InterruptedException { + server.enqueue(jsonResponse("/resourcegroups.json")); + + List<ResourceGroup> resourceGroups = api.getResourceGroupApi().list(); + + assertEquals(size(resourceGroups), 2); + + assertSent(server, "GET", requestUrl + version); + } + + public void testListResourceGroupsReturns404() throws InterruptedException { + server.enqueue(response404()); + + List<ResourceGroup> resourceGroups = api.getResourceGroupApi().list(); + + assertTrue(isEmpty(resourceGroups)); + + assertEquals(server.getRequestCount(), 1); + assertSent(server, "GET", requestUrl + version); + } + + public void testCreateResourceGroup() throws InterruptedException { + server.enqueue(jsonResponse("/resourcegroup.json").setStatus("HTTP/1.1 201 Created")); + + ImmutableMap<String, String> tags = ImmutableMap.<String, String>builder().put("tagname1", "tagvalue1").build(); + + ResourceGroup resourceGroup = api.getResourceGroupApi().create("jcloudstest", "West US", tags); + + assertEquals(resourceGroup.name(), "jcloudstest"); + assertEquals(resourceGroup.location(), "westus"); + assertEquals(resourceGroup.tags().size(), 1); + assertTrue(resourceGroup.id().contains("jcloudstest")); + + assertEquals(server.getRequestCount(), 1); + assertSent(server, "PUT", requestUrl + "/jcloudstest" + version, String.format("{\"location\":\"%s\", \"tags\":{\"tagname1\":\"tagvalue1\"}}", "West US")); + } + + public void testCreateResourceGroupWithNoTag() throws InterruptedException { + server.enqueue(jsonResponse("/resourcegroup.json").setStatus("HTTP/1.1 201 Created")); + + ResourceGroup resourceGroup = api.getResourceGroupApi().create("jcloudstest", "West US", null); + + assertEquals(resourceGroup.name(), "jcloudstest"); + assertEquals(resourceGroup.location(), "westus"); + assertTrue(resourceGroup.id().contains("jcloudstest")); + + assertEquals(server.getRequestCount(), 1); + assertSent(server, "PUT", requestUrl + "/jcloudstest" + version, String.format("{\"location\":\"%s\"}", "West US")); + } + + public void testGetResourceGroup() throws InterruptedException { + server.enqueue(jsonResponse("/resourcegroup.json")); + + ResourceGroup resourceGroup = api.getResourceGroupApi().get("jcloudstest"); + + assertEquals(resourceGroup.name(), "jcloudstest"); + + assertEquals(server.getRequestCount(), 1); + assertSent(server, "GET", requestUrl + "/jcloudstest" + version); + } + + public void testGetResourceGroupReturns404() throws InterruptedException { + server.enqueue(response404()); + + ResourceGroup resourceGroup = api.getResourceGroupApi().get("jcloudstest"); + + assertNull(resourceGroup); + + assertEquals(server.getRequestCount(), 1); + assertSent(server, "GET", requestUrl + "/jcloudstest" + version); + } + + public void testUpdateResourceGroupTags() throws InterruptedException { + server.enqueue(jsonResponse("/resourcegroupupdated.json")); + + ImmutableMap<String, String> tags = ImmutableMap.<String, String>builder().build(); + + ResourceGroup resourceGroup = api.getResourceGroupApi().update("jcloudstest", tags); + + + assertEquals(resourceGroup.tags().size(), 0); + assertEquals(resourceGroup.properties().provisioningState(), "Succeeded"); + + assertEquals(server.getRequestCount(), 1); + assertSent(server, "PATCH", requestUrl + "/jcloudstest" + version, "{\"tags\":{}}"); + } + + public void testDeleteResourceGroup() throws InterruptedException { + server.enqueue(response202WithHeader()); + + URI uri = api.getResourceGroupApi().delete("jcloudstest"); + + assertEquals(server.getRequestCount(), 1); + assertSent(server, "DELETE", requestUrl + "/jcloudstest" + version); + assertNotNull(uri); + + assertTrue(uri.toString().contains("api-version")); + assertTrue(uri.toString().contains("operationresults")); + } + + public void testDeleteResourceGroupReturns404() throws InterruptedException { + server.enqueue(response404()); + + URI uri = api.getResourceGroupApi().delete("jcloudstest"); + assertNull(uri); + assertEquals(server.getRequestCount(), 1); + assertSent(server, "DELETE", requestUrl + "/jcloudstest" + version); + } + +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a4334d46/azurecompute-arm/src/test/java/org/jclouds/azurecompute.arm/functions/URIParserTest.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute.arm/functions/URIParserTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute.arm/functions/URIParserTest.java new file mode 100644 index 0000000..f7b234d --- /dev/null +++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute.arm/functions/URIParserTest.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.azurecompute.arm.functions; + +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertNotNull; + +import java.net.URI; + +import org.jclouds.http.HttpResponse; +import org.testng.annotations.Test; +import com.google.common.collect.Multimap; +import com.google.common.collect.LinkedHashMultimap; + +@Test(groups = "unit", testName = "URIParserTest") +public class URIParserTest { + + public void testApply() { + URIParser parser = new URIParser(); + Multimap<String, String> headers = LinkedHashMultimap.<String, String> create(); + + URI uri = parser.apply(HttpResponse.builder().statusCode(200).build()); + assertNull(uri); + + try { + uri = parser.apply(HttpResponse.builder().statusCode(202).build()); + } catch (IllegalStateException ex){ + assertNotNull(ex); + } + + headers.put("Location", "https://someuri"); + + uri = parser.apply(HttpResponse.builder().statusCode(202).headers(headers).build()); + assertNotNull(uri); + + } +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a4334d46/azurecompute-arm/src/test/java/org/jclouds/azurecompute.arm/internal/AbstractAzureComputeApiLiveTest.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute.arm/internal/AbstractAzureComputeApiLiveTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute.arm/internal/AbstractAzureComputeApiLiveTest.java new file mode 100644 index 0000000..aa0663a --- /dev/null +++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute.arm/internal/AbstractAzureComputeApiLiveTest.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.azurecompute.arm.internal; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_POLL_INITIAL_PERIOD; +import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_POLL_MAX_PERIOD; +import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_TIMEOUT; +import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TCP_RULE_FORMAT; +import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TCP_RULE_REGEXP; +import java.util.Properties; +import java.util.Random; + +import org.jclouds.apis.BaseApiLiveTest; +import org.jclouds.azurecompute.arm.AzureComputeApi; +import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata; +import org.jclouds.compute.config.ComputeServiceProperties; +import org.jclouds.providers.ProviderMetadata; + +public abstract class AbstractAzureComputeApiLiveTest extends BaseApiLiveTest<AzureComputeApi> { + + protected static final int RAND = new Random().nextInt(999); + + public AbstractAzureComputeApiLiveTest() { + provider = "azurecompute-arm"; + } + + @Override protected Properties setupProperties() { + Properties properties = super.setupProperties(); + properties.put(ComputeServiceProperties.POLL_INITIAL_PERIOD, 1000); + properties.put(ComputeServiceProperties.POLL_MAX_PERIOD, 10000); + properties.setProperty(OPERATION_TIMEOUT, "60000"); + properties.setProperty(OPERATION_POLL_INITIAL_PERIOD, "5"); + properties.setProperty(OPERATION_POLL_MAX_PERIOD, "15"); + properties.setProperty(TCP_RULE_FORMAT, "tcp_%s-%s"); + properties.setProperty(TCP_RULE_REGEXP, "tcp_\\d{1,5}-\\d{1,5}"); + + // for oauth + AzureLiveTestUtils.defaultProperties(properties); + checkNotNull(setIfTestSystemPropertyPresent(properties, "jclouds.oauth.resource"), "test.jclouds.oauth.resource"); + checkNotNull(setIfTestSystemPropertyPresent(properties, "oauth.endpoint"), "test.oauth.endpoint"); + return properties; + } + + @Override + protected ProviderMetadata createProviderMetadata() { + AzureComputeProviderMetadata pm = AzureComputeProviderMetadata.builder().build(); + String endpoint = null; + if (System.getProperty("test.azurecompute-arm.endpoint") != null){ + endpoint = System.getProperty("test.azurecompute-arm.endpoint"); + pm.toBuilder().endpoint(endpoint); + } + return pm; + } +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a4334d46/azurecompute-arm/src/test/java/org/jclouds/azurecompute.arm/internal/AzureLiveTestUtils.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute.arm/internal/AzureLiveTestUtils.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute.arm/internal/AzureLiveTestUtils.java new file mode 100644 index 0000000..c578e84 --- /dev/null +++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute.arm/internal/AzureLiveTestUtils.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.azurecompute.arm.internal; + +import java.util.Properties; +import static org.jclouds.oauth.v2.config.OAuthProperties.CREDENTIAL_TYPE; +import static org.jclouds.oauth.v2.config.CredentialType.CLIENT_CREDENTIALS_SECRET; + +public class AzureLiveTestUtils { + + public static Properties defaultProperties(Properties properties) { + properties = properties == null ? new Properties() : properties; + properties.put("oauth.identity", "foo"); + properties.put("oauth.credential", "password"); + properties.put("oauth.endpoint", "https://login.microsoftonline.com/oauth2/token"); + properties.put(CREDENTIAL_TYPE, CLIENT_CREDENTIALS_SECRET.toString()); + return properties; + } +} + http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a4334d46/azurecompute-arm/src/test/java/org/jclouds/azurecompute.arm/internal/BaseAzureComputeApiLiveTest.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute.arm/internal/BaseAzureComputeApiLiveTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute.arm/internal/BaseAzureComputeApiLiveTest.java new file mode 100644 index 0000000..fb2e42a --- /dev/null +++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute.arm/internal/BaseAzureComputeApiLiveTest.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.azurecompute.arm.internal; +import static org.testng.Assert.assertNotNull; + +import com.google.common.collect.ImmutableMap; +import org.jclouds.azurecompute.arm.domain.ResourceGroup; + +import org.testng.annotations.AfterClass; + +public class BaseAzureComputeApiLiveTest extends AbstractAzureComputeApiLiveTest { + public static final String LOCATION = "westeurope"; + private String resourceGroupName = null; + + protected String getEndpoint() { + String endpoint = null; + if (System.getProperty("test.azurecompute-arm.endpoint") != null) { + endpoint = System.getProperty("test.azurecompute-arm.endpoint"); + } + assertNotNull(endpoint); + return endpoint; + } + + protected String getResourceGroupName() { + if (resourceGroupName == null) { + resourceGroupName = String.format("%3.24s", + System.getProperty("user.name") + RAND + "groupjclouds"); + createResourceGroup(resourceGroupName); + } + return resourceGroupName; + } + + private void createResourceGroup(String name) { + ImmutableMap<String, String> tags = ImmutableMap.<String, String>builder().build(); + + final ResourceGroup resourceGroup = api.getResourceGroupApi().create( + name, LOCATION, tags); + } + + private void deleteResourceGroup(String name) { + api.getResourceGroupApi().delete(name); + } + + + @AfterClass(alwaysRun = true) + @Override + protected void tearDown() { + super.tearDown(); + deleteResourceGroup(getResourceGroupName()); + } +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a4334d46/azurecompute-arm/src/test/java/org/jclouds/azurecompute.arm/internal/BaseAzureComputeApiMockTest.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute.arm/internal/BaseAzureComputeApiMockTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute.arm/internal/BaseAzureComputeApiMockTest.java new file mode 100644 index 0000000..fdbdf70 --- /dev/null +++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute.arm/internal/BaseAzureComputeApiMockTest.java @@ -0,0 +1,134 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.azurecompute.arm.internal; +import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor; +import static org.testng.Assert.assertEquals; +import static org.jclouds.oauth.v2.config.CredentialType.BEARER_TOKEN_CREDENTIALS; +import static org.jclouds.oauth.v2.config.OAuthProperties.CREDENTIAL_TYPE; + +import java.io.IOException; +import java.util.Properties; +import java.util.Set; + +import org.jclouds.ContextBuilder; +import org.jclouds.concurrent.config.ExecutorServiceModule; +import org.jclouds.azurecompute.arm.AzureComputeApi; +import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata; +import org.jclouds.json.Json; +import org.jclouds.rest.ApiContext; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; + +import com.google.common.base.Charsets; +import com.google.common.base.Throwables; +import com.google.common.collect.ImmutableSet; +import com.google.common.io.Resources; +import com.google.gson.JsonParser; +import com.google.inject.Module; +import com.squareup.okhttp.mockwebserver.MockResponse; +import com.squareup.okhttp.mockwebserver.MockWebServer; +import com.squareup.okhttp.mockwebserver.RecordedRequest; + +public class BaseAzureComputeApiMockTest { + + private static final String MOCK_BEARER_TOKEN = "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik1uQ19WWmNBVGZNNXBPWWlKSE1iYTlnb0VLWSIsImtpZCI6Ik1uQ19WWmNBVGZNNXBPWWlKSE1iYTlnb0VLWSJ9"; + private static final String DEFAULT_ENDPOINT = new AzureComputeProviderMetadata().getEndpoint(); + + private final Set<Module> modules = ImmutableSet.<Module> of(new ExecutorServiceModule(sameThreadExecutor())); + + protected MockWebServer server; + protected AzureComputeApi api; + private Json json; + + // So that we can ignore formatting. + private final JsonParser parser = new JsonParser(); + + @BeforeMethod + public void start() throws IOException { + server = new MockWebServer(); + server.play(); + Properties properties = new Properties(); + properties.put(CREDENTIAL_TYPE, BEARER_TOKEN_CREDENTIALS.toString()); + AzureComputeProviderMetadata pm = AzureComputeProviderMetadata.builder().build(); + ApiContext<AzureComputeApi> ctx = ContextBuilder.newBuilder(pm) + .credentials("", MOCK_BEARER_TOKEN) + .endpoint(server.getUrl("/").toString() + "subscriptions/12345678-1234-1234-1234-123456789012") + .modules(modules) + .overrides(properties) + .build(); + json = ctx.utils().injector().getInstance(Json.class); + api = ctx.getApi(); + } + + @AfterMethod(alwaysRun = true) + public void stop() throws IOException { + server.shutdown(); + api.close(); + } + + protected String url(String path) { + return server.getUrl(path).toString(); + } + + protected MockResponse jsonResponse(String resource) { + return new MockResponse().addHeader("Content-Type", "application/json").setBody(stringFromResource(resource)); + } + + protected MockResponse response404() { + return new MockResponse().setStatus("HTTP/1.1 404 Not Found"); + } + + protected MockResponse response200() { + return new MockResponse().setStatus("HTTP/1.1 200 OK"); + } + + protected MockResponse response202() { + return new MockResponse().setStatus("HTTP/1.1 202 Accepted"); + } + + protected MockResponse response202WithHeader() { + return new MockResponse() + .setStatus("HTTP/1.1 202 Accepted") + .addHeader("Location", "https://management.azure.com/subscriptions/12345678-1234-1234-1234-123456789012/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1SVEVTVC1DRU5UUkFMVVMiLCJqb2JMb2NhdGlvbiI6ImNlbnRyYWx1cyJ9?api-version=2014-04-01"); + } + + protected String stringFromResource(String resourceName) { + try { + return Resources.toString(getClass().getResource(resourceName), Charsets.UTF_8) + .replace(DEFAULT_ENDPOINT, url("")); + } catch (IOException e) { + throw Throwables.propagate(e); + } + } + + protected RecordedRequest assertSent(MockWebServer server, String method, String path) throws InterruptedException { + RecordedRequest request = server.takeRequest(); + assertEquals(request.getMethod(), method); + assertEquals(request.getPath(), path); + assertEquals(request.getHeader("Accept"), "application/json"); + assertEquals(request.getHeader("Authorization"), "Bearer " + MOCK_BEARER_TOKEN); + return request; + } + + protected RecordedRequest assertSent(MockWebServer server, String method, String path, String json) + throws InterruptedException { + RecordedRequest request = assertSent(server, method, path); + assertEquals(request.getHeader("Content-Type"), "application/json"); + assertEquals(parser.parse(new String(request.getBody(), Charsets.UTF_8)), parser.parse(json)); + return request; + } +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a4334d46/azurecompute-arm/src/test/resources/resourcegroup.json ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/test/resources/resourcegroup.json b/azurecompute-arm/src/test/resources/resourcegroup.json new file mode 100644 index 0000000..1d0cc68 --- /dev/null +++ b/azurecompute-arm/src/test/resources/resourcegroup.json @@ -0,0 +1,11 @@ +{ + "id": "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/jcloudstest", + "name": "jcloudstest", + "location": "westus", + "tags": { + "tagname1": "tagvalue1" + }, + "properties": { + "provisioningState": "Succeeded" + } +} \ No newline at end of file
