From 83a36148eedb6c98c8f0715632cd658e24ae98c2 Mon Sep 17 00:00:00 2001 From: Adrian Cole Date: Mon, 25 Feb 2013 10:14:40 -0800 Subject: [PATCH 1/2] switched iam to use logback --- labs/iam/pom.xml | 6 +- labs/iam/src/test/resources/log4j.xml | 166 ------------------------ labs/iam/src/test/resources/logback.xml | 38 ++++++ 3 files changed, 41 insertions(+), 169 deletions(-) delete mode 100644 labs/iam/src/test/resources/log4j.xml create mode 100644 labs/iam/src/test/resources/logback.xml diff --git a/labs/iam/pom.xml b/labs/iam/pom.xml index 52dac1315c..3e24fce391 100644 --- a/labs/iam/pom.xml +++ b/labs/iam/pom.xml @@ -60,13 +60,13 @@ org.jclouds.driver - jclouds-log4j + jclouds-slf4j ${project.version} test - log4j - log4j + ch.qos.logback + logback-classic test diff --git a/labs/iam/src/test/resources/log4j.xml b/labs/iam/src/test/resources/log4j.xml deleted file mode 100644 index 7527432931..0000000000 --- a/labs/iam/src/test/resources/log4j.xml +++ /dev/null @@ -1,166 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/labs/iam/src/test/resources/logback.xml b/labs/iam/src/test/resources/logback.xml new file mode 100644 index 0000000000..9679b2e03a --- /dev/null +++ b/labs/iam/src/test/resources/logback.xml @@ -0,0 +1,38 @@ + + + + target/test-data/jclouds.log + + + %d %-5p [%c] [%thread] %m%n + + + + + target/test-data/jclouds-wire.log + + + %d %-5p [%c] [%thread] %m%n + + + + + + + + + + + + + + + + + + + + + + + From 58dc9b97965d0e2f6ec12ee880870b34d6c2eab8 Mon Sep 17 00:00:00 2001 From: Adrian Cole Date: Mon, 25 Feb 2013 10:15:36 -0800 Subject: [PATCH 2/2] added iam instance profile support --- .../AWSInstanceProfileApiLiveTest.java | 32 ++ .../src/main/java/org/jclouds/iam/IAMApi.java | 7 + .../java/org/jclouds/iam/IAMAsyncApi.java | 7 + .../iam/config/IAMRestClientModule.java | 3 + .../jclouds/iam/domain/InstanceProfile.java | 197 +++++++++++ .../iam/features/InstanceProfileApi.java | 127 +++++++ .../iam/features/InstanceProfileAsyncApi.java | 180 ++++++++++ .../org/jclouds/iam/features/RoleApi.java | 27 ++ .../jclouds/iam/features/RoleAsyncApi.java | 36 ++ ...nstanceProfilesForRoleToPagedIterable.java | 73 ++++ .../InstanceProfilesToPagedIterable.java | 90 +++++ .../iam/xml/InstanceProfileHandler.java | 108 ++++++ .../ListInstanceProfilesResultHandler.java | 104 ++++++ .../InstanceProfileApiExpectTest.java | 314 ++++++++++++++++++ .../features/InstanceProfileApiLiveTest.java | 124 +++++++ .../iam/features/RoleApiExpectTest.java | 52 +++ .../jclouds/iam/features/RoleApiLiveTest.java | 18 +- .../iam/features/RolePolicyApiLiveTest.java | 7 +- .../jclouds/iam/features/UserApiLiveTest.java | 2 +- .../parse/GetInstanceProfileResponseTest.java | 73 ++++ .../ListInstanceProfilesResponseTest.java | 80 +++++ .../resources/delete_instance_profile.xml | 5 + .../test/resources/get_instance_profile.xml | 24 ++ .../test/resources/list_instance_profiles.xml | 37 +++ .../list_instance_profiles_marker.xml | 39 +++ 25 files changed, 1757 insertions(+), 9 deletions(-) create mode 100644 labs/aws-iam/src/test/java/org/jclouds/aws/iam/features/AWSInstanceProfileApiLiveTest.java create mode 100644 labs/iam/src/main/java/org/jclouds/iam/domain/InstanceProfile.java create mode 100644 labs/iam/src/main/java/org/jclouds/iam/features/InstanceProfileApi.java create mode 100644 labs/iam/src/main/java/org/jclouds/iam/features/InstanceProfileAsyncApi.java create mode 100644 labs/iam/src/main/java/org/jclouds/iam/functions/InstanceProfilesForRoleToPagedIterable.java create mode 100644 labs/iam/src/main/java/org/jclouds/iam/functions/InstanceProfilesToPagedIterable.java create mode 100644 labs/iam/src/main/java/org/jclouds/iam/xml/InstanceProfileHandler.java create mode 100644 labs/iam/src/main/java/org/jclouds/iam/xml/ListInstanceProfilesResultHandler.java create mode 100644 labs/iam/src/test/java/org/jclouds/iam/features/InstanceProfileApiExpectTest.java create mode 100644 labs/iam/src/test/java/org/jclouds/iam/features/InstanceProfileApiLiveTest.java create mode 100644 labs/iam/src/test/java/org/jclouds/iam/parse/GetInstanceProfileResponseTest.java create mode 100644 labs/iam/src/test/java/org/jclouds/iam/parse/ListInstanceProfilesResponseTest.java create mode 100644 labs/iam/src/test/resources/delete_instance_profile.xml create mode 100644 labs/iam/src/test/resources/get_instance_profile.xml create mode 100644 labs/iam/src/test/resources/list_instance_profiles.xml create mode 100644 labs/iam/src/test/resources/list_instance_profiles_marker.xml diff --git a/labs/aws-iam/src/test/java/org/jclouds/aws/iam/features/AWSInstanceProfileApiLiveTest.java b/labs/aws-iam/src/test/java/org/jclouds/aws/iam/features/AWSInstanceProfileApiLiveTest.java new file mode 100644 index 0000000000..ae03a87514 --- /dev/null +++ b/labs/aws-iam/src/test/java/org/jclouds/aws/iam/features/AWSInstanceProfileApiLiveTest.java @@ -0,0 +1,32 @@ +/** + * 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.aws.iam.features; + +import org.jclouds.iam.features.InstanceProfileApiLiveTest; +import org.testng.annotations.Test; + +/** + * @author Adrian Cole + */ +@Test(groups = "live", testName = "AWSInstanceProfileApiLiveTest") +public class AWSInstanceProfileApiLiveTest extends InstanceProfileApiLiveTest { + public AWSInstanceProfileApiLiveTest() { + provider = "aws-iam"; + } +} diff --git a/labs/iam/src/main/java/org/jclouds/iam/IAMApi.java b/labs/iam/src/main/java/org/jclouds/iam/IAMApi.java index 2688b869f3..c693ad2bf1 100644 --- a/labs/iam/src/main/java/org/jclouds/iam/IAMApi.java +++ b/labs/iam/src/main/java/org/jclouds/iam/IAMApi.java @@ -21,6 +21,7 @@ package org.jclouds.iam; import javax.ws.rs.FormParam; import org.jclouds.iam.domain.User; +import org.jclouds.iam.features.InstanceProfileApi; import org.jclouds.iam.features.RoleApi; import org.jclouds.iam.features.RolePolicyApi; import org.jclouds.iam.features.UserApi; @@ -56,4 +57,10 @@ public interface IAMApi { */ @Delegate RolePolicyApi getPolicyApiForRole(@FormParam("RoleName") String roleName); + + /** + * Provides synchronous access to Instance Profile features. + */ + @Delegate + InstanceProfileApi getInstanceProfileApi(); } diff --git a/labs/iam/src/main/java/org/jclouds/iam/IAMAsyncApi.java b/labs/iam/src/main/java/org/jclouds/iam/IAMAsyncApi.java index e5db49a125..66784cb091 100644 --- a/labs/iam/src/main/java/org/jclouds/iam/IAMAsyncApi.java +++ b/labs/iam/src/main/java/org/jclouds/iam/IAMAsyncApi.java @@ -25,6 +25,7 @@ import javax.ws.rs.Path; import org.jclouds.aws.filters.FormSigner; import org.jclouds.iam.domain.User; +import org.jclouds.iam.features.InstanceProfileAsyncApi; import org.jclouds.iam.features.RoleAsyncApi; import org.jclouds.iam.features.RolePolicyAsyncApi; import org.jclouds.iam.features.UserAsyncApi; @@ -75,4 +76,10 @@ public interface IAMAsyncApi { */ @Delegate RolePolicyAsyncApi getPolicyApiForRole(@FormParam("RoleName") String roleName); + + /** + * Provides asynchronous access to Instance Profile features. + */ + @Delegate + InstanceProfileAsyncApi getInstanceProfileApi(); } diff --git a/labs/iam/src/main/java/org/jclouds/iam/config/IAMRestClientModule.java b/labs/iam/src/main/java/org/jclouds/iam/config/IAMRestClientModule.java index 7484540b8c..6763557f8a 100644 --- a/labs/iam/src/main/java/org/jclouds/iam/config/IAMRestClientModule.java +++ b/labs/iam/src/main/java/org/jclouds/iam/config/IAMRestClientModule.java @@ -25,6 +25,8 @@ import java.util.Map; import org.jclouds.aws.config.FormSigningRestClientModule; import org.jclouds.iam.IAMApi; import org.jclouds.iam.IAMAsyncApi; +import org.jclouds.iam.features.InstanceProfileApi; +import org.jclouds.iam.features.InstanceProfileAsyncApi; import org.jclouds.iam.features.RoleApi; import org.jclouds.iam.features.RoleAsyncApi; import org.jclouds.iam.features.RolePolicyApi; @@ -46,6 +48,7 @@ public class IAMRestClientModule extends FormSigningRestClientModule + * + * @author Adrian Cole + */ +public final class InstanceProfile { + + private final String arn; + private final String id; + private final String name; + private final String path; + private final Date createDate; + private final ImmutableList roles; + + private InstanceProfile(String arn, String id, String name, String path, Date createDate, ImmutableList roles) { + this.arn = checkNotNull(arn, "arn"); + this.id = checkNotNull(id, "id for %s", arn); + this.name = checkNotNull(name, "name for %s", arn); + this.path = checkNotNull(path, "path for %s", arn); + this.createDate = checkNotNull(createDate, "createDate for %s", arn); + this.roles = checkNotNull(roles, "roles for %s", arn); + } + + /** + * how to specify the resource in the access policy language ex. + * {@code arn:aws::::} + */ + public String getArn() { + return arn; + } + + /** + * a globally unique identifier (GUID), returned from the api. + */ + public String getId() { + return id; + } + + /** + * friendly name ex. {@code Developers} + */ + public String getName() { + return name; + } + + /** + * path ex {@code /division_abc/subdivision_xyz/product_1234/engineering/} + */ + public String getPath() { + return path; + } + + /** + * Date the instance profile was created + */ + public Date getCreateDate() { + return createDate; + } + + /** + * The roles assigned to the instance profile + */ + public ImmutableList getRoles() { + return roles; + } + + @Override + public int hashCode() { + return Objects.hashCode(arn, id); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null || getClass() != obj.getClass()) + return false; + InstanceProfile that = InstanceProfile.class.cast(obj); + return equal(this.arn, that.arn) && equal(this.id, that.id); + } + + @Override + public String toString() { + return toStringHelper(this).add("arn", arn).add("id", id).add("name", name).add("path", path) + .add("createDate", createDate).add("roles", roles).toString(); + } + + public static Builder builder() { + return new Builder(); + } + + public Builder toBuilder() { + return builder().from(this); + } + + public static class Builder { + private String arn; + private String id; + private String name; + private String path; + private Date createDate; + private ImmutableList.Builder roles = ImmutableList. builder(); + + /** + * @see InstanceProfile#getArn() + */ + public Builder arn(String arn) { + this.arn = arn; + return this; + } + + /** + * @see InstanceProfile#getId() + */ + public Builder id(String id) { + this.id = id; + return this; + } + + /** + * @see InstanceProfile#getName() + */ + public Builder name(String name) { + this.name = name; + return this; + } + + /** + * @see InstanceProfile#getPath() + */ + public Builder path(String path) { + this.path = path; + return this; + } + + /** + * @see InstanceProfile#getCreateDate() + */ + public Builder createDate(Date createDate) { + this.createDate = createDate; + return this; + } + + /** + * @see InstanceProfile#getRoles() + */ + public Builder role(Role role) { + this.roles.add(checkNotNull(role, "role")); + return this; + } + + /** + * @see InstanceProfile#getRoles() + */ + public Builder roles(Iterable roles) { + this.roles.addAll(checkNotNull(roles, "roles")); + return this; + } + + public InstanceProfile build() { + return new InstanceProfile(arn, id, name, path, createDate, roles.build()); + } + + public Builder from(InstanceProfile in) { + return arn(in.arn).id(in.id).name(in.name).path(in.path).createDate(in.createDate).roles(in.roles); + } + } +} diff --git a/labs/iam/src/main/java/org/jclouds/iam/features/InstanceProfileApi.java b/labs/iam/src/main/java/org/jclouds/iam/features/InstanceProfileApi.java new file mode 100644 index 0000000000..92e9c94684 --- /dev/null +++ b/labs/iam/src/main/java/org/jclouds/iam/features/InstanceProfileApi.java @@ -0,0 +1,127 @@ +/** + * 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.iam.features; + +import org.jclouds.collect.IterableWithMarker; +import org.jclouds.collect.PagedIterable; +import org.jclouds.iam.domain.InstanceProfile; +import org.jclouds.javax.annotation.Nullable; + +/** + * @see InstanceProfileAsyncApi + * @author Adrian Cole + */ +public interface InstanceProfileApi { + + /** + * Creates a new instance profile for your AWS account + * + * @param name + * Name of the instance profile to create. + * @return the new instance profile + */ + InstanceProfile create(String name); + + /** + * like {@link #create(String)}, except you can specify a path. + */ + InstanceProfile createWithPath(String name, String path); + + /** + * returns all instance profiles in order. + */ + PagedIterable list(); + + /** + * retrieves up to 100 instance profiles in order. + */ + IterableWithMarker listFirstPage(); + + /** + * retrieves up to 100 instance profiles in order, starting at {@code marker} + * + * @param marker + * starting point to resume the list + */ + IterableWithMarker listAt(String marker); + + /** + * returns all instance profiles in order at the specified {@code pathPrefix}. + * + * @param pathPrefix + * ex. {@code /division_abc/subdivision_xyz/} + */ + PagedIterable listPathPrefix(String pathPrefix); + + /** + * retrieves up to 100 instance profiles in order at the specified {@code pathPrefix}. + * + * @param pathPrefix + * ex. {@code /division_abc/subdivision_xyz/} + */ + IterableWithMarker listPathPrefixFirstPage(String pathPrefix); + + /** + * retrieves up to 100 instance profiles in order at the specified {@code pathPrefix}, starting at {@code marker}. + * + * @param pathPrefix + * ex. {@code /division_abc/subdivision_xyz/} + * @param marker + * starting point to resume the list + */ + IterableWithMarker listPathPrefixAt(String pathPrefix, String marker); + + /** + * Retrieves information about the specified instance profile, including the instance profile's path, GUID, and ARN. + * + * @param name + * Name of the instance profile to get information about. + * @return null if not found + */ + @Nullable + InstanceProfile get(String name); + + /** + * Deletes the specified instanceProfile. The instance profile must not have any policies attached. + * + * @param name + * Name of the instance profile to delete + */ + void delete(String name); + + /** + * Adds the specified role to the specified instance profile. + * + * @param name + * Name of the instance profile to update. + * @param roleName + * Name of the role to add + */ + void addRole(String name, String roleName); + + /** + * Removes the specified role from the specified instance profile. + * + * @param name + * Name of the instance profile to update. + * @param roleName + * Name of the role to remove + */ + void removeRole(String name, String roleName); +} diff --git a/labs/iam/src/main/java/org/jclouds/iam/features/InstanceProfileAsyncApi.java b/labs/iam/src/main/java/org/jclouds/iam/features/InstanceProfileAsyncApi.java new file mode 100644 index 0000000000..e11998988b --- /dev/null +++ b/labs/iam/src/main/java/org/jclouds/iam/features/InstanceProfileAsyncApi.java @@ -0,0 +1,180 @@ +/** + * 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.iam.features; + +import javax.inject.Named; +import javax.ws.rs.FormParam; +import javax.ws.rs.POST; +import javax.ws.rs.Path; + +import org.jclouds.Fallbacks.NullOnNotFoundOr404; +import org.jclouds.Fallbacks.VoidOnNotFoundOr404; +import org.jclouds.aws.filters.FormSigner; +import org.jclouds.collect.IterableWithMarker; +import org.jclouds.collect.PagedIterable; +import org.jclouds.iam.domain.InstanceProfile; +import org.jclouds.iam.functions.InstanceProfilesToPagedIterable; +import org.jclouds.iam.xml.InstanceProfileHandler; +import org.jclouds.iam.xml.ListInstanceProfilesResultHandler; +import org.jclouds.rest.annotations.Fallback; +import org.jclouds.rest.annotations.FormParams; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.Transform; +import org.jclouds.rest.annotations.VirtualHost; +import org.jclouds.rest.annotations.XMLResponseParser; + +import com.google.common.util.concurrent.ListenableFuture; + +/** + * Provides access to Amazon IAM via the Query API + *

+ * + * @see + * @author Adrian Cole + */ +@RequestFilters(FormSigner.class) +@VirtualHost +public interface InstanceProfileAsyncApi { + /** + * @see InstanceProfileApi#create + */ + @Named("CreateInstanceProfile") + @POST + @Path("/") + @FormParams(keys = "Action", values = "CreateInstanceProfile") + @XMLResponseParser(InstanceProfileHandler.class) + ListenableFuture create(@FormParam("InstanceProfileName") String name); + + /** + * @see InstanceProfileApi#createWithPath + */ + @Named("CreateInstanceProfile") + @POST + @Path("/") + @FormParams(keys = "Action", values = "CreateInstanceProfile") + @XMLResponseParser(InstanceProfileHandler.class) + ListenableFuture createWithPath(@FormParam("InstanceProfileName") String name, + @FormParam("Path") String path); + + /** + * @see InstanceProfileApi#list() + */ + @Named("ListInstanceProfiles") + @POST + @Path("/") + @FormParams(keys = "Action", values = "ListInstanceProfiles") + @XMLResponseParser(ListInstanceProfilesResultHandler.class) + @Transform(InstanceProfilesToPagedIterable.class) + ListenableFuture> list(); + + /** + * @see InstanceProfileApi#listFirstPage + */ + @Named("ListInstanceProfiles") + @POST + @Path("/") + @FormParams(keys = "Action", values = "ListInstanceProfiles") + @XMLResponseParser(ListInstanceProfilesResultHandler.class) + ListenableFuture> listFirstPage(); + + /** + * @see InstanceProfileApi#listAt(String) + */ + @Named("ListInstanceProfiles") + @POST + @Path("/") + @FormParams(keys = "Action", values = "ListInstanceProfiles") + @XMLResponseParser(ListInstanceProfilesResultHandler.class) + ListenableFuture> listAt(@FormParam("Marker") String marker); + + /** + * @see InstanceProfileApi#listPathPrefix(String) + */ + @Named("ListInstanceProfiles") + @POST + @Path("/") + @FormParams(keys = "Action", values = "ListInstanceProfiles") + @XMLResponseParser(ListInstanceProfilesResultHandler.class) + @Transform(InstanceProfilesToPagedIterable.class) + ListenableFuture> listPathPrefix(@FormParam("PathPrefix") String pathPrefix); + + /** + * @see InstanceProfileApi#listPathPrefixFirstPage(String) + */ + @Named("ListInstanceProfiles") + @POST + @Path("/") + @FormParams(keys = "Action", values = "ListInstanceProfiles") + @XMLResponseParser(ListInstanceProfilesResultHandler.class) + ListenableFuture> listPathPrefixFirstPage( + @FormParam("PathPrefix") String pathPrefix); + + /** + * @see InstanceProfileApi#listPathPrefixAt(String, String) + */ + @Named("ListInstanceProfiles") + @POST + @Path("/") + @FormParams(keys = "Action", values = "ListInstanceProfiles") + @XMLResponseParser(ListInstanceProfilesResultHandler.class) + ListenableFuture> listPathPrefixAt(@FormParam("PathPrefix") String pathPrefix, + @FormParam("Marker") String marker); + + /** + * @see InstanceProfileApi#get() + */ + @Named("GetInstanceProfile") + @POST + @Path("/") + @XMLResponseParser(InstanceProfileHandler.class) + @FormParams(keys = "Action", values = "GetInstanceProfile") + @Fallback(NullOnNotFoundOr404.class) + ListenableFuture get(@FormParam("InstanceProfileName") String name); + + /** + * @see InstanceProfileApi#delete() + */ + @Named("DeleteInstanceProfile") + @POST + @Path("/") + @FormParams(keys = "Action", values = "DeleteInstanceProfile") + @Fallback(VoidOnNotFoundOr404.class) + ListenableFuture delete(@FormParam("InstanceProfileName") String name); + + /** + * @see InstanceProfileApi#addRole() + */ + @Named("AddRoleToInstanceProfile") + @POST + @Path("/") + @FormParams(keys = "Action", values = "AddRoleToInstanceProfile") + @Fallback(VoidOnNotFoundOr404.class) + ListenableFuture addRole(@FormParam("InstanceProfileName") String name, @FormParam("RoleName") String roleName); + + /** + * @see InstanceProfileApi#removeRole() + */ + @Named("RemoveRoleFromInstanceProfile") + @POST + @Path("/") + @FormParams(keys = "Action", values = "RemoveRoleFromInstanceProfile") + @Fallback(VoidOnNotFoundOr404.class) + ListenableFuture removeRole(@FormParam("InstanceProfileName") String name, + @FormParam("RoleName") String roleName); +} diff --git a/labs/iam/src/main/java/org/jclouds/iam/features/RoleApi.java b/labs/iam/src/main/java/org/jclouds/iam/features/RoleApi.java index a6ecc3c511..78e278646c 100644 --- a/labs/iam/src/main/java/org/jclouds/iam/features/RoleApi.java +++ b/labs/iam/src/main/java/org/jclouds/iam/features/RoleApi.java @@ -20,6 +20,7 @@ package org.jclouds.iam.features; import org.jclouds.collect.IterableWithMarker; import org.jclouds.collect.PagedIterable; +import org.jclouds.iam.domain.InstanceProfile; import org.jclouds.iam.domain.Role; import org.jclouds.javax.annotation.Nullable; @@ -99,6 +100,32 @@ public interface RoleApi { @Nullable Role get(String name); + /** + * returns all instance profiles in order for this role. + * + * @param name + * Name of the role to get instance profiles for. + */ + PagedIterable listInstanceProfiles(String name); + + /** + * retrieves up to 100 instance profiles in order for this role. + * + * @param name + * Name of the role to get instance profiles for. + */ + IterableWithMarker listFirstPageOfInstanceProfiles(String name); + + /** + * retrieves up to 100 instance profiles in order for this role, starting at {@code marker} + * + * @param name + * Name of the role to get instance profiles for. + * @param marker + * starting point to resume the list + */ + IterableWithMarker listInstanceProfilesAt(String name, String marker); + /** * Deletes the specified role. The role must not have any policies attached. * diff --git a/labs/iam/src/main/java/org/jclouds/iam/features/RoleAsyncApi.java b/labs/iam/src/main/java/org/jclouds/iam/features/RoleAsyncApi.java index afb9c44c09..20e5986e73 100644 --- a/labs/iam/src/main/java/org/jclouds/iam/features/RoleAsyncApi.java +++ b/labs/iam/src/main/java/org/jclouds/iam/features/RoleAsyncApi.java @@ -28,8 +28,11 @@ import org.jclouds.Fallbacks.VoidOnNotFoundOr404; import org.jclouds.aws.filters.FormSigner; import org.jclouds.collect.IterableWithMarker; import org.jclouds.collect.PagedIterable; +import org.jclouds.iam.domain.InstanceProfile; import org.jclouds.iam.domain.Role; +import org.jclouds.iam.functions.InstanceProfilesForRoleToPagedIterable; import org.jclouds.iam.functions.RolesToPagedIterable; +import org.jclouds.iam.xml.ListInstanceProfilesResultHandler; import org.jclouds.iam.xml.ListRolesResultHandler; import org.jclouds.iam.xml.RoleHandler; import org.jclouds.rest.annotations.Fallback; @@ -147,6 +150,39 @@ public interface RoleAsyncApi { @Fallback(NullOnNotFoundOr404.class) ListenableFuture get(@FormParam("RoleName") String name); + /** + * @see RoleApi#listInstanceProfiles() + */ + @Named("ListInstanceProfilesForRole") + @POST + @Path("/") + @FormParams(keys = "Action", values = "ListInstanceProfilesForRole") + @XMLResponseParser(ListInstanceProfilesResultHandler.class) + @Transform(InstanceProfilesForRoleToPagedIterable.class) + ListenableFuture> listInstanceProfiles(@FormParam("RoleName") String name); + + /** + * @see RoleApi#listFirstPageOfInstanceProfiles + */ + @Named("ListInstanceProfilesForRole") + @POST + @Path("/") + @FormParams(keys = "Action", values = "ListInstanceProfilesForRole") + @XMLResponseParser(ListInstanceProfilesResultHandler.class) + ListenableFuture> listFirstPageOfInstanceProfiles( + @FormParam("RoleName") String name); + + /** + * @see RoleApi#listInstanceProfilesAt(String) + */ + @Named("ListInstanceProfilesForRole") + @POST + @Path("/") + @FormParams(keys = "Action", values = "ListInstanceProfilesForRole") + @XMLResponseParser(ListInstanceProfilesResultHandler.class) + ListenableFuture> listInstanceProfilesAt(@FormParam("RoleName") String name, + @FormParam("Marker") String marker); + /** * @see RoleApi#delete() */ diff --git a/labs/iam/src/main/java/org/jclouds/iam/functions/InstanceProfilesForRoleToPagedIterable.java b/labs/iam/src/main/java/org/jclouds/iam/functions/InstanceProfilesForRoleToPagedIterable.java new file mode 100644 index 0000000000..b91fd56536 --- /dev/null +++ b/labs/iam/src/main/java/org/jclouds/iam/functions/InstanceProfilesForRoleToPagedIterable.java @@ -0,0 +1,73 @@ +/** + * 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.iam.functions; + +import static com.google.common.base.Preconditions.checkNotNull; + +import javax.inject.Inject; + +import org.jclouds.collect.IterableWithMarker; +import org.jclouds.collect.internal.Arg0ToPagedIterable; +import org.jclouds.iam.IAMApi; +import org.jclouds.iam.domain.InstanceProfile; +import org.jclouds.iam.features.RoleApi; + +import com.google.common.annotations.Beta; +import com.google.common.base.Function; +import com.google.common.base.Optional; + +/** + * @author Adrian Cole + */ +@Beta +public class InstanceProfilesForRoleToPagedIterable extends + Arg0ToPagedIterable { + + private final RoleApi api; + + @Inject + protected InstanceProfilesForRoleToPagedIterable(IAMApi api) { + this.api = checkNotNull(api, "api").getRoleApi(); + } + + @Override + protected Function> markerToNextForArg0(Optional name) { + return new ListInstanceProfilesPrefixAtMarker(api, name.get().toString()); + } + + private static class ListInstanceProfilesPrefixAtMarker implements + Function> { + private final RoleApi api; + private final String name; + + @Inject + protected ListInstanceProfilesPrefixAtMarker(RoleApi api, String name) { + this.api = checkNotNull(api, "api"); + this.name = checkNotNull(name, "name"); + } + + public IterableWithMarker apply(Object input) { + return api.listInstanceProfilesAt(name, input.toString()); + } + + public String toString() { + return "ListInstanceProfilesPrefixAtMarker(" + name + ")"; + } + } +} diff --git a/labs/iam/src/main/java/org/jclouds/iam/functions/InstanceProfilesToPagedIterable.java b/labs/iam/src/main/java/org/jclouds/iam/functions/InstanceProfilesToPagedIterable.java new file mode 100644 index 0000000000..77bf6b1432 --- /dev/null +++ b/labs/iam/src/main/java/org/jclouds/iam/functions/InstanceProfilesToPagedIterable.java @@ -0,0 +1,90 @@ +/** + * 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.iam.functions; + +import static com.google.common.base.Preconditions.checkNotNull; + +import javax.inject.Inject; + +import org.jclouds.collect.IterableWithMarker; +import org.jclouds.collect.internal.Arg0ToPagedIterable; +import org.jclouds.iam.IAMApi; +import org.jclouds.iam.domain.InstanceProfile; +import org.jclouds.iam.features.InstanceProfileApi; + +import com.google.common.annotations.Beta; +import com.google.common.base.Function; +import com.google.common.base.Optional; + +/** + * @author Adrian Cole + */ +@Beta +public class InstanceProfilesToPagedIterable extends Arg0ToPagedIterable { + + private final InstanceProfileApi api; + + @Inject + protected InstanceProfilesToPagedIterable(IAMApi api) { + this.api = checkNotNull(api, "api").getInstanceProfileApi(); + } + + @Override + protected Function> markerToNextForArg0(Optional pathPrefix) { + if (pathPrefix.isPresent()) + return new ListInstanceProfilesUnderPathPrefixAtMarker(api, pathPrefix.get().toString()); + return new ListInstanceProfilesAtMarker(api); + } + + private static class ListInstanceProfilesUnderPathPrefixAtMarker implements Function> { + private final InstanceProfileApi api; + private final String pathPrefix; + + @Inject + protected ListInstanceProfilesUnderPathPrefixAtMarker(InstanceProfileApi api, String pathPrefix) { + this.api = checkNotNull(api, "api"); + this.pathPrefix = checkNotNull(pathPrefix, "pathPrefix"); + } + + public IterableWithMarker apply(Object input) { + return api.listPathPrefixAt(pathPrefix, input.toString()); + } + + public String toString() { + return "ListInstanceProfilesUnderPathPrefixAtMarker(" + pathPrefix + ")"; + } + } + + private static class ListInstanceProfilesAtMarker implements Function> { + private final InstanceProfileApi api; + + @Inject + protected ListInstanceProfilesAtMarker(InstanceProfileApi api) { + this.api = checkNotNull(api, "api"); + } + + public IterableWithMarker apply(Object input) { + return api.listAt(input.toString()); + } + + public String toString() { + return "listInstanceProfilesAtMarker()"; + } + } +} diff --git a/labs/iam/src/main/java/org/jclouds/iam/xml/InstanceProfileHandler.java b/labs/iam/src/main/java/org/jclouds/iam/xml/InstanceProfileHandler.java new file mode 100644 index 0000000000..f90b594476 --- /dev/null +++ b/labs/iam/src/main/java/org/jclouds/iam/xml/InstanceProfileHandler.java @@ -0,0 +1,108 @@ +/** + * 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.iam.xml; + +import static org.jclouds.util.SaxUtils.currentOrNull; +import static org.jclouds.util.SaxUtils.equalsOrSuffix; + +import javax.inject.Inject; + +import org.jclouds.date.DateService; +import org.jclouds.http.functions.ParseSax; +import org.jclouds.iam.domain.InstanceProfile; +import org.xml.sax.Attributes; + +/** + * @see + * + * @author Adrian Cole + */ +public class InstanceProfileHandler extends ParseSax.HandlerForGeneratedRequestWithResult { + + private final DateService dateService; + private final RoleHandler roleHandler; + + @Inject + protected InstanceProfileHandler(DateService dateService, RoleHandler roleHandler) { + this.dateService = dateService; + this.roleHandler = roleHandler; + } + + private StringBuilder currentText = new StringBuilder(); + private InstanceProfile.Builder builder = InstanceProfile.builder(); + + @Override + public InstanceProfile getResult() { + try { + return builder.build(); + } finally { + builder = InstanceProfile.builder(); + } + } + + private boolean inRoles; + + @Override + public void startElement(String url, String name, String qName, Attributes attributes) { + if (equalsOrSuffix(qName, "Roles")) { + inRoles = true; + } + if (inRoles) { + roleHandler.startElement(url, name, qName, attributes); + } + } + + @Override + public void endElement(String uri, String name, String qName) { + if (inRoles) { + if (qName.equals("Roles")) { + inRoles = false; + } else if (qName.equals("member")) { + builder.role(roleHandler.getResult()); + } else { + roleHandler.endElement(uri, name, qName); + } + } else if (qName.equals("Path")) { + builder.path(currentOrNull(currentText)); + } else if (qName.equals("InstanceProfileName")) { + builder.name(currentOrNull(currentText)); + } else if (qName.equals("InstanceProfileId")) { + builder.id(currentOrNull(currentText)); + } else if (qName.equals("Arn")) { + builder.arn(currentOrNull(currentText)); + } else if (qName.equals("CreateDate")) { + try { + builder.createDate(dateService.iso8601SecondsDateParse(currentOrNull(currentText))); + } catch (IllegalArgumentException e) { + // on create, milliseconds are present + builder.createDate(dateService.iso8601DateParse(currentOrNull(currentText))); + } + } + currentText = new StringBuilder(); + } + + @Override + public void characters(char ch[], int start, int length) { + if (inRoles) { + roleHandler.characters(ch, start, length); + } else { + currentText.append(ch, start, length); + } + } +} diff --git a/labs/iam/src/main/java/org/jclouds/iam/xml/ListInstanceProfilesResultHandler.java b/labs/iam/src/main/java/org/jclouds/iam/xml/ListInstanceProfilesResultHandler.java new file mode 100644 index 0000000000..ccc3e104da --- /dev/null +++ b/labs/iam/src/main/java/org/jclouds/iam/xml/ListInstanceProfilesResultHandler.java @@ -0,0 +1,104 @@ +/** + * 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.iam.xml; + +import static org.jclouds.util.SaxUtils.currentOrNull; +import static org.jclouds.util.SaxUtils.equalsOrSuffix; + +import org.jclouds.collect.IterableWithMarker; +import org.jclouds.collect.IterableWithMarkers; +import org.jclouds.http.functions.ParseSax; +import org.jclouds.iam.domain.InstanceProfile; +import org.xml.sax.Attributes; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableList.Builder; +import com.google.inject.Inject; + +/** + * @see + * + * @author Adrian Cole + */ +public class ListInstanceProfilesResultHandler extends + ParseSax.HandlerForGeneratedRequestWithResult> { + + private final InstanceProfileHandler instanceProfileHandler; + + private StringBuilder currentText = new StringBuilder(); + private Builder instanceProfiles = ImmutableList. builder(); + private String afterMarker; + + @Inject + public ListInstanceProfilesResultHandler(InstanceProfileHandler instanceProfileHandler) { + this.instanceProfileHandler = instanceProfileHandler; + } + + @Override + public IterableWithMarker getResult() { + try { + return IterableWithMarkers.from(instanceProfiles.build(), afterMarker); + } finally { + instanceProfiles = ImmutableList. builder(); + } + } + + private boolean inInstanceProfiles; + private boolean inRoles; + + @Override + public void startElement(String url, String name, String qName, Attributes attributes) { + if (equalsOrSuffix(qName, "InstanceProfiles")) { + inInstanceProfiles = true; + } else if (equalsOrSuffix(qName, "Roles")) { + inRoles = true; + } + if (inInstanceProfiles) { + instanceProfileHandler.startElement(url, name, qName, attributes); + } + } + + @Override + public void endElement(String uri, String name, String qName) { + if (inInstanceProfiles) { + if (qName.equals("Roles")) + inRoles = false; + if (qName.equals("InstanceProfiles")) { + inInstanceProfiles = false; + } else if (qName.equals("member") && !inRoles) { + instanceProfiles.add(instanceProfileHandler.getResult()); + } else { + instanceProfileHandler.endElement(uri, name, qName); + } + } else if (qName.equals("Marker")) { + afterMarker = currentOrNull(currentText); + } + + currentText = new StringBuilder(); + } + + @Override + public void characters(char ch[], int start, int length) { + if (inInstanceProfiles) { + instanceProfileHandler.characters(ch, start, length); + } else { + currentText.append(ch, start, length); + } + } +} diff --git a/labs/iam/src/test/java/org/jclouds/iam/features/InstanceProfileApiExpectTest.java b/labs/iam/src/test/java/org/jclouds/iam/features/InstanceProfileApiExpectTest.java new file mode 100644 index 0000000000..18a7a4e79c --- /dev/null +++ b/labs/iam/src/test/java/org/jclouds/iam/features/InstanceProfileApiExpectTest.java @@ -0,0 +1,314 @@ +/** + * 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 + * + * Unles 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 expres or implied. See the License for the + * specific language governing permisions and limitations + * under the License. + */ +package org.jclouds.iam.features; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; + +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.iam.IAMApi; +import org.jclouds.iam.internal.BaseIAMApiExpectTest; +import org.jclouds.iam.parse.GetInstanceProfileResponseTest; +import org.jclouds.iam.parse.ListInstanceProfilesResponseTest; +import org.jclouds.rest.ResourceNotFoundException; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; + +/** + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "InstanceProfileApiExpectTest") +public class InstanceProfileApiExpectTest extends BaseIAMApiExpectTest { + HttpRequest create = HttpRequest.builder() + .method("POST") + .endpoint("https://iam.amazonaws.com/") + .addHeader("Host", "iam.amazonaws.com") + .addFormParam("Action", "CreateInstanceProfile") + .addFormParam("InstanceProfileName", "name") + .addFormParam("Signature", "UIosTnnvBVHY7m7rqz1489RQ90Mf81/aOXgh8x2mLWU%3D") + .addFormParam("SignatureMethod", "HmacSHA256") + .addFormParam("SignatureVersion", "2") + .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") + .addFormParam("Version", "2010-05-08") + .addFormParam("AWSAccessKeyId", "identity").build(); + + public void testCreateWhenResponseIs2xx() throws Exception { + + HttpResponse getResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/get_instance_profile.xml", "text/xml")).build(); + + IAMApi apiWhenExist = requestSendsResponse(create, getResponse); + + assertEquals(apiWhenExist.getInstanceProfileApi().create("name").toString(), new GetInstanceProfileResponseTest().expected().toString()); + } + + HttpRequest get = HttpRequest.builder() + .method("POST") + .endpoint("https://iam.amazonaws.com/") + .addHeader("Host", "iam.amazonaws.com") + .addFormParam("Action", "GetInstanceProfile") + .addFormParam("InstanceProfileName", "name") + .addFormParam("Signature", "uw5Ix/UFRqENsSWProK3%2BDMIezmvd3fFhTFMaooxFMg%3D") + .addFormParam("SignatureMethod", "HmacSHA256") + .addFormParam("SignatureVersion", "2") + .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") + .addFormParam("Version", "2010-05-08") + .addFormParam("AWSAccessKeyId", "identity").build(); + + public void testGetWhenResponseIs2xx() throws Exception { + + HttpResponse getResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/get_instance_profile.xml", "text/xml")).build(); + + IAMApi apiWhenExist = requestSendsResponse(get, getResponse); + + assertEquals(apiWhenExist.getInstanceProfileApi().get("name").toString(), new GetInstanceProfileResponseTest().expected().toString()); + } + + public void testGetWhenResponseIs404() throws Exception { + + HttpResponse getResponse = HttpResponse.builder().statusCode(404).build(); + + IAMApi apiWhenDontExist = requestSendsResponse( + get, getResponse); + + assertNull(apiWhenDontExist.getInstanceProfileApi().get("name")); + } + + HttpRequest delete = HttpRequest.builder() + .method("POST") + .endpoint("https://iam.amazonaws.com/") + .addHeader("Host", "iam.amazonaws.com") + .addFormParam("Action", "DeleteInstanceProfile") + .addFormParam("InstanceProfileName", "name") + .addFormParam("Signature", "7W47Gj/6NE6p6drXMtqozYOlUOQN7CzbXgrIup4iowk%3D") + .addFormParam("SignatureMethod", "HmacSHA256") + .addFormParam("SignatureVersion", "2") + .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") + .addFormParam("Version", "2010-05-08") + .addFormParam("AWSAccessKeyId", "identity").build(); + + public void testDeleteWhenResponseIs2xx() throws Exception { + + HttpResponse deleteResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/delete_instance_profile.xml", "text/xml")).build(); + + IAMApi apiWhenExist = requestSendsResponse(delete, deleteResponse); + + apiWhenExist.getInstanceProfileApi().delete("name"); + } + + public void testDeleteWhenResponseIs404() throws Exception { + + HttpResponse deleteResponse = HttpResponse.builder().statusCode(404).build(); + + IAMApi apiWhenDontExist = requestSendsResponse(delete, deleteResponse); + + apiWhenDontExist.getInstanceProfileApi().delete("name"); + } + + HttpRequest list = HttpRequest.builder() + .method("POST") + .endpoint("https://iam.amazonaws.com/") + .addHeader("Host", "iam.amazonaws.com") + .addFormParam("Action", "ListInstanceProfiles") + .addFormParam("Signature", "i2V6ZeplNRVaZ/9XfD4jv53Qh%2BNQdl3ZuoZc%2BLguf0o%3D") + .addFormParam("SignatureMethod", "HmacSHA256") + .addFormParam("SignatureVersion", "2") + .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") + .addFormParam("Version", "2010-05-08") + .addFormParam("AWSAccessKeyId", "identity").build(); + + public void testListWhenResponseIs2xx() throws Exception { + + HttpResponse listResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/list_instance_profiles.xml", "text/xml")).build(); + + IAMApi apiWhenExist = requestSendsResponse(list, listResponse); + + assertEquals(apiWhenExist.getInstanceProfileApi().list().get(0).toString(), new ListInstanceProfilesResponseTest().expected().toString()); + } + + public void testList2PagesWhenResponseIs2xx() throws Exception { + + HttpResponse listResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/list_instance_profiles_marker.xml", "text/xml")).build(); + + HttpRequest list2 = HttpRequest.builder() + .method("POST") + .endpoint("https://iam.amazonaws.com/") + .addHeader("Host", "iam.amazonaws.com") + .addFormParam("Action", "ListInstanceProfiles") + .addFormParam("Marker", "MARKER") + .addFormParam("Signature", "x7G5OvKxTIMEjl58OVurKrwf7wEA7exXSml63T89mSY%3D") + .addFormParam("SignatureMethod", "HmacSHA256") + .addFormParam("SignatureVersion", "2") + .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") + .addFormParam("Version", "2010-05-08") + .addFormParam("AWSAccessKeyId", "identity").build(); + + HttpResponse list2Response = HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/list_instance_profiles.xml", "text/xml")).build(); + + IAMApi apiWhenExist = requestsSendResponses(list, listResponse, list2, list2Response); + + assertEquals(apiWhenExist.getInstanceProfileApi().list().concat().toList(), + ImmutableList.copyOf(Iterables.concat(new ListInstanceProfilesResponseTest().expected(), new ListInstanceProfilesResponseTest().expected()))); + } + + HttpRequest listPathPrefix = HttpRequest.builder() + .method("POST") + .endpoint("https://iam.amazonaws.com/") + .addHeader("Host", "iam.amazonaws.com") + .addFormParam("Action", "ListInstanceProfiles") + .addFormParam("PathPrefix", "/subdivision") + .addFormParam("Signature", "EEVeWhJhORpibHahIj1skQ3rhHaVb/iaqD22vIFQH7o%3D") + .addFormParam("SignatureMethod", "HmacSHA256") + .addFormParam("SignatureVersion", "2") + .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") + .addFormParam("Version", "2010-05-08") + .addFormParam("AWSAccessKeyId", "identity").build(); + + public void testListPathPrefixWhenResponseIs2xx() throws Exception { + + HttpResponse listResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/list_instance_profiles.xml", "text/xml")).build(); + + IAMApi apiWhenExist = requestSendsResponse(listPathPrefix, listResponse); + + assertEquals(apiWhenExist.getInstanceProfileApi().listPathPrefix("/subdivision").get(0).toString(), new ListInstanceProfilesResponseTest().expected().toString()); + } + + public void testListPathPrefix2PagesWhenResponseIs2xx() throws Exception { + + HttpResponse listResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/list_instance_profiles_marker.xml", "text/xml")).build(); + + HttpRequest listPathPrefix2 = HttpRequest.builder() + .method("POST") + .endpoint("https://iam.amazonaws.com/") + .addHeader("Host", "iam.amazonaws.com") + .addFormParam("Action", "ListInstanceProfiles") + .addFormParam("Marker", "MARKER") + .addFormParam("PathPrefix", "/subdivision") + .addFormParam("Signature", "8xo94VlrqsoMoa6bpbqQbuVx8TLh8UmiQnc9QC58EhU%3D") + .addFormParam("SignatureMethod", "HmacSHA256") + .addFormParam("SignatureVersion", "2") + .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") + .addFormParam("Version", "2010-05-08") + .addFormParam("AWSAccessKeyId", "identity").build(); + + HttpResponse list2Response = HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/list_instance_profiles.xml", "text/xml")).build(); + + IAMApi apiWhenExist = requestsSendResponses(listPathPrefix, listResponse, listPathPrefix2, list2Response); + + assertEquals(apiWhenExist.getInstanceProfileApi().listPathPrefix("/subdivision").concat().toList(), + ImmutableList.copyOf(Iterables.concat(new ListInstanceProfilesResponseTest().expected(), new ListInstanceProfilesResponseTest().expected()))); + } + + // TODO: this should really be an empty set + @Test(expectedExceptions = ResourceNotFoundException.class) + public void testListWhenResponseIs404() throws Exception { + + HttpResponse listResponse = HttpResponse.builder().statusCode(404).build(); + + IAMApi apiWhenDontExist = requestSendsResponse( + list, listResponse); + + apiWhenDontExist.getInstanceProfileApi().list().get(0); + } + + public void testListPathPrefixAtWhenResponseIs2xx() throws Exception { + HttpRequest listWithOptions = + HttpRequest.builder() + .method("POST") + .endpoint("https://iam.amazonaws.com/") + .addHeader("Host", "iam.amazonaws.com") + .addFormParam("Action", "ListInstanceProfiles") + .addFormParam("Marker", "MARKER") + .addFormParam("PathPrefix", "/foo") + .addFormParam("Signature", "IBRktzqZ/GE8Y7DZqsjuOUNfJZTbkCnOZnHAmzwtju8%3D") + .addFormParam("SignatureMethod", "HmacSHA256") + .addFormParam("SignatureVersion", "2") + .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") + .addFormParam("Version", "2010-05-08") + .addFormParam("AWSAccessKeyId", "identity").build(); + + HttpResponse listWithOptionsResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/list_instance_profiles.xml", "text/xml")).build(); + + IAMApi apiWhenWithOptionsExist = requestSendsResponse(listWithOptions, + listWithOptionsResponse); + + assertEquals(apiWhenWithOptionsExist.getInstanceProfileApi().listPathPrefixAt("/foo", "MARKER").toString(), + new ListInstanceProfilesResponseTest().expected().toString()); + } + + HttpRequest addRole = HttpRequest.builder() + .method("POST") + .endpoint("https://iam.amazonaws.com/") + .addHeader("Host", "iam.amazonaws.com") + .addFormParam("Action", "AddRoleToInstanceProfile") + .addFormParam("InstanceProfileName", "name") + .addFormParam("RoleName", "WebServer") + .addFormParam("Signature", "QTM12yD9GwUKEE9wqbt03VlfZ/%2BfO0UWe9SbNoI9d3c%3D") + .addFormParam("SignatureMethod", "HmacSHA256") + .addFormParam("SignatureVersion", "2") + .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") + .addFormParam("Version", "2010-05-08") + .addFormParam("AWSAccessKeyId", "identity").build(); + + public void testAddRoleWhenResponseIs2xx() throws Exception { + + HttpResponse addRoleResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/delete_instance_profile.xml", "text/xml")).build(); + + IAMApi apiWhenExist = requestSendsResponse(addRole, addRoleResponse); + + apiWhenExist.getInstanceProfileApi().addRole("name", "WebServer"); + } + + HttpRequest removeRole = HttpRequest.builder() + .method("POST") + .endpoint("https://iam.amazonaws.com/") + .addHeader("Host", "iam.amazonaws.com") + .addFormParam("Action", "RemoveRoleFromInstanceProfile") + .addFormParam("InstanceProfileName", "name") + .addFormParam("RoleName", "WebServer") + .addFormParam("Signature", "o1Uz2bOwe8H3DOnyNL5TK9lNDoKvWo7CNhspN7ml5Sc%3D") + .addFormParam("SignatureMethod", "HmacSHA256") + .addFormParam("SignatureVersion", "2") + .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") + .addFormParam("Version", "2010-05-08") + .addFormParam("AWSAccessKeyId", "identity").build(); + + public void testRemoveRoleWhenResponseIs2xx() throws Exception { + + HttpResponse removeRoleResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/delete_instance_profile.xml", "text/xml")).build(); + + IAMApi apiWhenExist = requestSendsResponse(removeRole, removeRoleResponse); + + apiWhenExist.getInstanceProfileApi().removeRole("name", "WebServer"); + } +} diff --git a/labs/iam/src/test/java/org/jclouds/iam/features/InstanceProfileApiLiveTest.java b/labs/iam/src/test/java/org/jclouds/iam/features/InstanceProfileApiLiveTest.java new file mode 100644 index 0000000000..2f5ad5d0a0 --- /dev/null +++ b/labs/iam/src/test/java/org/jclouds/iam/features/InstanceProfileApiLiveTest.java @@ -0,0 +1,124 @@ +/** + * 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.iam.features; + +import static com.google.common.base.Preconditions.checkNotNull; +import static java.util.logging.Logger.getAnonymousLogger; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertTrue; + +import org.jclouds.iam.domain.InstanceProfile; +import org.jclouds.iam.domain.Role; +import org.jclouds.iam.internal.BaseIAMApiLiveTest; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; + +/** + * @author Adrian Cole + */ +@Test(groups = "live", testName = "InstanceProfileApiLiveTest") +public class InstanceProfileApiLiveTest extends BaseIAMApiLiveTest { + + static void checkInstanceProfile(InstanceProfile instanceProfile) { + checkNotNull(instanceProfile.getArn(), "Arn cannot be null for InstanceProfile %s", instanceProfile); + checkNotNull(instanceProfile.getId(), "Id cannot be null for InstanceProfile %s", instanceProfile); + checkNotNull(instanceProfile.getName(), "Name cannot be null for InstanceProfile %s", instanceProfile); + checkNotNull(instanceProfile.getPath(), "Path cannot be null for InstanceProfile %s", instanceProfile); + checkNotNull(instanceProfile.getRoles(), "Roles cannot be null for InstanceProfile %s", instanceProfile); + checkNotNull(instanceProfile.getCreateDate(), + "CreateDate cannot be null for a InstanceProfile InstanceProfile %s", instanceProfile); + for (Role role : instanceProfile.getRoles()) { + RoleApiLiveTest.checkRole(role); + } + } + + @Test + protected void testListInstanceProfiles() { + ImmutableList instanceProfiles = api().list().concat().toList(); + getAnonymousLogger().info("instanceProfiles: " + instanceProfiles.size()); + + for (InstanceProfile instanceProfile : instanceProfiles) { + checkInstanceProfile(instanceProfile); + assertEquals(api().get(instanceProfile.getName()), instanceProfile); + ImmutableSet instanceProfilesAtPath = api().listPathPrefix(instanceProfile.getPath()) + .concat().toSet(); + assertTrue(instanceProfilesAtPath.contains(instanceProfile), instanceProfile + " not in " + + instanceProfilesAtPath); + } + } + + @Test + public void testGetInstanceProfileWhenNotFound() { + assertNull(api().get("AAAAAAAAAAAAAAAA")); + } + + @Test + public void testDeleteInstanceProfileWhenNotFound() { + api().delete("AAAAAAAAAAAAAAAA"); + } + + String name = System.getProperty("user.name").replace('.', '-') + ".instanceProfile.iamtest.jclouds.org."; + + @Test + public void testCreateInstanceProfile() { + InstanceProfile newInstanceProfile = api().create(name); + getAnonymousLogger().info("created instanceProfile: " + newInstanceProfile); + checkInstanceProfile(newInstanceProfile); + assertEquals(newInstanceProfile.getName(), name); + } + + @Test(dependsOnMethods = "testCreateInstanceProfile") + public void testAddRoleRemoveRoleFromInstanceProfile() { + try { + createRoleWithPolicy(name); + api().addRole(name, name); + InstanceProfile updated = api().get(name); + RoleApiLiveTest.checkRole(updated.getRoles().get(0)); + + api().removeRole(name, name); + updated = api().get(name); + assertEquals(updated.getRoles(), ImmutableList.of()); + } finally { + tearDownRoleWithPolicy(name); + } + } + + @Test(dependsOnMethods = "testAddRoleRemoveRoleFromInstanceProfile") + public void testDeleteInstanceProfile() { + api().delete(name); + assertNull(api().get(name)); + } + + protected InstanceProfileApi api() { + return context.getApi().getInstanceProfileApi(); + } + + void createRoleWithPolicy(String roleName) { + context.getApi().getRoleApi().createWithPolicy(roleName, RoleApiLiveTest.assumeRolePolicy); + context.getApi().getPolicyApiForRole(roleName).create("S3Access", RolePolicyApiLiveTest.s3Policy); + } + + void tearDownRoleWithPolicy(String roleName) { + context.getApi().getPolicyApiForRole(roleName).delete("S3Access"); + context.getApi().getRoleApi().delete(roleName); + } +} diff --git a/labs/iam/src/test/java/org/jclouds/iam/features/RoleApiExpectTest.java b/labs/iam/src/test/java/org/jclouds/iam/features/RoleApiExpectTest.java index 5d3ee9ade6..67c9476501 100644 --- a/labs/iam/src/test/java/org/jclouds/iam/features/RoleApiExpectTest.java +++ b/labs/iam/src/test/java/org/jclouds/iam/features/RoleApiExpectTest.java @@ -26,6 +26,7 @@ import org.jclouds.http.HttpResponse; import org.jclouds.iam.IAMApi; import org.jclouds.iam.internal.BaseIAMApiExpectTest; import org.jclouds.iam.parse.GetRoleResponseTest; +import org.jclouds.iam.parse.ListInstanceProfilesResponseTest; import org.jclouds.iam.parse.ListRolesResponseTest; import org.jclouds.rest.ResourceNotFoundException; import org.testng.annotations.Test; @@ -269,4 +270,55 @@ public class RoleApiExpectTest extends BaseIAMApiExpectTest { assertEquals(apiWhenWithOptionsExist.getRoleApi().listPathPrefixAt("/foo", "MARKER").toString(), new ListRolesResponseTest().expected().toString()); } + + HttpRequest listInstanceProfiles = HttpRequest.builder() + .method("POST") + .endpoint("https://iam.amazonaws.com/") + .addHeader("Host", "iam.amazonaws.com") + .addFormParam("Action", "ListInstanceProfilesForRole") + .addFormParam("RoleName", "WebServer") + .addFormParam("Signature", "WLWyoNHcR09MJ9JN0qGIzzPsZtlTX6UbqsAkaxp9utg%3D") + .addFormParam("SignatureMethod", "HmacSHA256") + .addFormParam("SignatureVersion", "2") + .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") + .addFormParam("Version", "2010-05-08") + .addFormParam("AWSAccessKeyId", "identity").build(); + + public void testListInstanceProfilesWhenResponseIs2xx() throws Exception { + + HttpResponse listInstanceProfilesResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/list_instance_profiles.xml", "text/xml")).build(); + + IAMApi apiWhenExist = requestSendsResponse(listInstanceProfiles, listInstanceProfilesResponse); + + assertEquals(apiWhenExist.getRoleApi().listInstanceProfiles("WebServer").get(0).toString(), new ListInstanceProfilesResponseTest().expected().toString()); + } + + public void testListInstanceProfiles2PagesWhenResponseIs2xx() throws Exception { + + HttpResponse listInstanceProfilesResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/list_instance_profiles_marker.xml", "text/xml")).build(); + + HttpRequest listInstanceProfiles2 = HttpRequest.builder() + .method("POST") + .endpoint("https://iam.amazonaws.com/") + .addHeader("Host", "iam.amazonaws.com") + .addFormParam("Action", "ListInstanceProfilesForRole") + .addFormParam("Marker", "MARKER") + .addFormParam("RoleName", "WebServer") + .addFormParam("Signature", "LHwKxeK/Hwqbv90tSG0tRJl/4BLrPqi%2BMvBnXvxUybs%3D") + .addFormParam("SignatureMethod", "HmacSHA256") + .addFormParam("SignatureVersion", "2") + .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") + .addFormParam("Version", "2010-05-08") + .addFormParam("AWSAccessKeyId", "identity").build(); + + HttpResponse listInstanceProfiles2Response = HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/list_instance_profiles.xml", "text/xml")).build(); + + IAMApi apiWhenExist = requestsSendResponses(listInstanceProfiles, listInstanceProfilesResponse, listInstanceProfiles2, listInstanceProfiles2Response); + + assertEquals(apiWhenExist.getRoleApi().listInstanceProfiles("WebServer").concat().toList(), + ImmutableList.copyOf(Iterables.concat(new ListInstanceProfilesResponseTest().expected(), new ListInstanceProfilesResponseTest().expected()))); + } } diff --git a/labs/iam/src/test/java/org/jclouds/iam/features/RoleApiLiveTest.java b/labs/iam/src/test/java/org/jclouds/iam/features/RoleApiLiveTest.java index c0defa332d..574c8f88fd 100644 --- a/labs/iam/src/test/java/org/jclouds/iam/features/RoleApiLiveTest.java +++ b/labs/iam/src/test/java/org/jclouds/iam/features/RoleApiLiveTest.java @@ -24,6 +24,7 @@ import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; +import org.jclouds.iam.domain.InstanceProfile; import org.jclouds.iam.domain.Role; import org.jclouds.iam.internal.BaseIAMApiLiveTest; import org.testng.annotations.Test; @@ -37,7 +38,7 @@ import com.google.common.collect.ImmutableSet; @Test(groups = "live", testName = "RoleApiLiveTest") public class RoleApiLiveTest extends BaseIAMApiLiveTest { - private void checkRole(Role role) { + static void checkRole(Role role) { checkNotNull(role.getArn(), "Arn cannot be null for Role %s", role); checkNotNull(role.getId(), "Id cannot be null for Role %s", role); checkNotNull(role.getName(), "Name cannot be null for Role %s", role); @@ -59,6 +60,15 @@ public class RoleApiLiveTest extends BaseIAMApiLiveTest { } } + @Test + protected void testListInstanceProfiles() { + for (Role role : api().list().concat()) { + for (InstanceProfile instanceProfile : api().listInstanceProfiles(role.getName()).concat()) { + InstanceProfileApiLiveTest.checkInstanceProfile(instanceProfile); + } + } + } + @Test public void testGetRoleWhenNotFound() { assertNull(api().get("AAAAAAAAAAAAAAAA")); @@ -69,17 +79,17 @@ public class RoleApiLiveTest extends BaseIAMApiLiveTest { api().delete("AAAAAAAAAAAAAAAA"); } - String policy = "{\"Version\":\"2008-10-17\",\"Statement\":[{\"Sid\":\"\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"ec2.amazonaws.com\"},\"Action\":\"sts:AssumeRole\"}]}"; + static String assumeRolePolicy = "{\"Version\":\"2008-10-17\",\"Statement\":[{\"Sid\":\"\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"ec2.amazonaws.com\"},\"Action\":\"sts:AssumeRole\"}]}"; @Test public void testCreateAndDeleteRole() { String name = System.getProperty("user.name").replace('.', '-') + ".role.iamtest.jclouds.org."; Role newRole; try { - newRole = api().createWithPolicy(name, policy); + newRole = api().createWithPolicy(name, assumeRolePolicy); getAnonymousLogger().info("created role: " + newRole); checkRole(newRole); - assertEquals(newRole.getAssumeRolePolicy(), policy); + assertEquals(newRole.getAssumeRolePolicy(), assumeRolePolicy); } finally { api().delete(name); assertNull(api().get(name)); diff --git a/labs/iam/src/test/java/org/jclouds/iam/features/RolePolicyApiLiveTest.java b/labs/iam/src/test/java/org/jclouds/iam/features/RolePolicyApiLiveTest.java index db0b8477ad..2b6f04a2f8 100644 --- a/labs/iam/src/test/java/org/jclouds/iam/features/RolePolicyApiLiveTest.java +++ b/labs/iam/src/test/java/org/jclouds/iam/features/RolePolicyApiLiveTest.java @@ -34,7 +34,7 @@ import org.testng.annotations.Test; @Test(groups = "live", testName = "RolePolicyApiLiveTest") public class RolePolicyApiLiveTest extends BaseIAMApiLiveTest { - private void checkPolicy(Policy policy) { + static void checkPolicy(Policy policy) { checkNotNull(policy.getOwner(), "Owner cannot be null for Policy %s", policy); checkNotNull(policy.getName(), "Name cannot be null for Policy %s", policy); checkNotNull(policy.getDocument(), "Document cannot be null for Policy %s", policy); @@ -49,15 +49,14 @@ public class RolePolicyApiLiveTest extends BaseIAMApiLiveTest { } } - String assumeRolePolicy = "{\"Version\":\"2008-10-17\",\"Statement\":[{\"Sid\":\"\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"ec2.amazonaws.com\"},\"Action\":\"sts:AssumeRole\"}]}"; - String s3Policy = "{\"Statement\":[{\"Effect\":\"Allow\",\"Action\":\"s3:*\",\"Resource\":\"*\"}]}"; + static String s3Policy = "{\"Statement\":[{\"Effect\":\"Allow\",\"Action\":\"s3:*\",\"Resource\":\"*\"}]}"; @Test public void testCreateAndDeleteRolePolicy() { String roleName = System.getProperty("user.name").replace('.', '-') + ".role_policy.iamtest.jclouds.org."; Role newRole; try { - newRole = context.getApi().getRoleApi().createWithPolicy(roleName, assumeRolePolicy); + newRole = context.getApi().getRoleApi().createWithPolicy(roleName, RoleApiLiveTest.assumeRolePolicy); getAnonymousLogger().info("created role: " + newRole); api(roleName).create("S3Access", s3Policy); Policy newPolicy = api(roleName).get("S3Access"); diff --git a/labs/iam/src/test/java/org/jclouds/iam/features/UserApiLiveTest.java b/labs/iam/src/test/java/org/jclouds/iam/features/UserApiLiveTest.java index 6c8369fd55..0982461b6d 100644 --- a/labs/iam/src/test/java/org/jclouds/iam/features/UserApiLiveTest.java +++ b/labs/iam/src/test/java/org/jclouds/iam/features/UserApiLiveTest.java @@ -42,7 +42,7 @@ public class UserApiLiveTest extends BaseIAMApiLiveTest { checkUser(user); } - private void checkUser(User user) { + static void checkUser(User user) { checkNotNull(user.getArn(), "Arn cannot be null for User %s", user); checkNotNull(user.getId(), "Id cannot be null for User %s", user); checkNotNull(user.getName(), "While Name can be null for a User, its Optional wrapper cannot; user %s", user); diff --git a/labs/iam/src/test/java/org/jclouds/iam/parse/GetInstanceProfileResponseTest.java b/labs/iam/src/test/java/org/jclouds/iam/parse/GetInstanceProfileResponseTest.java new file mode 100644 index 0000000000..6d76371c7c --- /dev/null +++ b/labs/iam/src/test/java/org/jclouds/iam/parse/GetInstanceProfileResponseTest.java @@ -0,0 +1,73 @@ +/** + * 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.iam.parse; + +import static org.testng.Assert.assertEquals; + +import java.io.InputStream; + +import org.jclouds.date.DateService; +import org.jclouds.date.internal.SimpleDateFormatDateService; +import org.jclouds.http.functions.BaseHandlerTest; +import org.jclouds.iam.domain.InstanceProfile; +import org.jclouds.iam.domain.Role; +import org.jclouds.iam.xml.InstanceProfileHandler; +import org.testng.annotations.Test; + +/** + * @author Adrian Cole + */ +// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire +@Test(groups = "unit", testName = "GetInstanceProfileResponseTest") +public class GetInstanceProfileResponseTest extends BaseHandlerTest { + + public void test() { + InputStream is = getClass().getResourceAsStream("/get_instance_profile.xml"); + + InstanceProfile expected = expected(); + + InstanceProfileHandler handler = injector.getInstance(InstanceProfileHandler.class); + InstanceProfile result = factory.create(handler).parse(is); + + assertEquals(result, expected); + assertEquals(result.getPath(), expected.getPath()); + assertEquals(result.getName(), expected.getName()); + assertEquals(result.getCreateDate(), expected.getCreateDate()); + assertEquals(result.getRoles(), expected.getRoles()); + } + + DateService date = new SimpleDateFormatDateService(); + + public InstanceProfile expected() { + return InstanceProfile.builder() + .arn("arn:aws:iam::123456789012:instance-profile/application_abc/component_xyz/Webserver") + .id("AIPAD5ARO2C5EXAMPLE3G") + .name("Webserver") + .path("/application_abc/component_xyz/") + .role(Role.builder() + .arn("arn:aws:iam::123456789012:role/application_abc/component_xyz/S3Access") + .id("AROACVYKSVTSZFEXAMPLE") + .name("S3Access") + .path("/application_abc/component_xyz/") + .assumeRolePolicy("{\"Version\":\"2008-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"Service\":[\"ec2.amazonaws.com\"]},\"Action\":[\"sts:AssumeRole\"]}]}") + .createDate(date.iso8601SecondsDateParse("2012-05-09T15:45:35Z")).build()) + .createDate(date.iso8601SecondsDateParse("2012-05-09T16:11:10Z")).build(); + } + +} diff --git a/labs/iam/src/test/java/org/jclouds/iam/parse/ListInstanceProfilesResponseTest.java b/labs/iam/src/test/java/org/jclouds/iam/parse/ListInstanceProfilesResponseTest.java new file mode 100644 index 0000000000..e33962b0d4 --- /dev/null +++ b/labs/iam/src/test/java/org/jclouds/iam/parse/ListInstanceProfilesResponseTest.java @@ -0,0 +1,80 @@ +/** + * 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.iam.parse; + +import static org.testng.Assert.assertEquals; + +import java.io.InputStream; + +import org.jclouds.collect.IterableWithMarker; +import org.jclouds.collect.IterableWithMarkers; +import org.jclouds.date.DateService; +import org.jclouds.date.internal.SimpleDateFormatDateService; +import org.jclouds.http.functions.BaseHandlerTest; +import org.jclouds.iam.domain.InstanceProfile; +import org.jclouds.iam.domain.Role; +import org.jclouds.iam.xml.ListInstanceProfilesResultHandler; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableSet; + +/** + * @author Adrian Cole + */ +// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire +@Test(groups = "unit", testName = "ListInstanceProfilesResponseTest") +public class ListInstanceProfilesResponseTest extends BaseHandlerTest { + + public void test() { + InputStream is = getClass().getResourceAsStream("/list_instance_profiles.xml"); + + IterableWithMarker expected = expected(); + + ListInstanceProfilesResultHandler handler = injector.getInstance(ListInstanceProfilesResultHandler.class); + IterableWithMarker result = factory.create(handler).parse(is); + + assertEquals(result.toString(), expected.toString()); + + } + + DateService date = new SimpleDateFormatDateService(); + + public IterableWithMarker expected() { + return IterableWithMarkers.from(ImmutableSet.of( + InstanceProfile.builder() + .arn("arn:aws:iam::123456789012:instance-profile/application_abc/component_xyz/Database") + .id("AIPACIFN4OZXG7EXAMPLE") + .name("Database") + .path("/application_abc/component_xyz/") + .role(Role.builder() + .arn("arn:aws:iam::123456789012:role/application_abc/component_xyz/S3Access") + .id("AROACVYKSVTSZFEXAMPLE") + .name("S3Access") + .path("/application_abc/component_xyz/") + .assumeRolePolicy("{\"Version\":\"2008-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"Service\":[\"ec2.amazonaws.com\"]},\"Action\":[\"sts:AssumeRole\"]}]}") + .createDate(date.iso8601SecondsDateParse("2012-05-09T15:45:35Z")).build()) + .createDate(date.iso8601SecondsDateParse("2012-05-09T16:27:03Z")).build(), + InstanceProfile.builder() + .arn("arn:aws:iam::123456789012:instance-profile/application_abc/component_xyz/Webserver") + .id("AIPACZLSXM2EYYEXAMPLE") + .name("Webserver") + .path("/application_abc/component_xyz/") + .createDate(date.iso8601SecondsDateParse("2012-05-09T16:27:11Z")).build())); + } +} diff --git a/labs/iam/src/test/resources/delete_instance_profile.xml b/labs/iam/src/test/resources/delete_instance_profile.xml new file mode 100644 index 0000000000..defab565c0 --- /dev/null +++ b/labs/iam/src/test/resources/delete_instance_profile.xml @@ -0,0 +1,5 @@ + + + 913e3f37-99ed-11e1-a4c3-270EXAMPLE04 + + \ No newline at end of file diff --git a/labs/iam/src/test/resources/get_instance_profile.xml b/labs/iam/src/test/resources/get_instance_profile.xml new file mode 100644 index 0000000000..71c57d545e --- /dev/null +++ b/labs/iam/src/test/resources/get_instance_profile.xml @@ -0,0 +1,24 @@ + + + + AIPAD5ARO2C5EXAMPLE3G + + + /application_abc/component_xyz/ + arn:aws:iam::123456789012:role/application_abc/component_xyz/S3Access + S3Access + {"Version":"2008-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":["ec2.amazonaws.com"]},"Action":["sts:AssumeRole"]}]} + 2012-05-09T15:45:35Z + AROACVYKSVTSZFEXAMPLE + + + Webserver + /application_abc/component_xyz/ + arn:aws:iam::123456789012:instance-profile/application_abc/component_xyz/Webserver + 2012-05-09T16:11:10Z + + + + 37289fda-99f2-11e1-a4c3-27EXAMPLE804 + + \ No newline at end of file diff --git a/labs/iam/src/test/resources/list_instance_profiles.xml b/labs/iam/src/test/resources/list_instance_profiles.xml new file mode 100644 index 0000000000..9477982faf --- /dev/null +++ b/labs/iam/src/test/resources/list_instance_profiles.xml @@ -0,0 +1,37 @@ + + + false + + + AIPACIFN4OZXG7EXAMPLE + + + /application_abc/component_xyz/ + arn:aws:iam::123456789012:role/application_abc/component_xyz/S3Access + S3Access + {"Version":"2008-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":["ec2.amazonaws.com"]},"Action":["sts:AssumeRole"]}]} + + 2012-05-09T15:45:35Z + AROACVYKSVTSZFEXAMPLE + + + Database + /application_abc/component_xyz/ + arn:aws:iam::123456789012:instance-profile/application_abc/component_xyz/Database + 2012-05-09T16:27:03Z + + + AIPACZLSXM2EYYEXAMPLE + + Webserver + /application_abc/component_xyz/ + arn:aws:iam::123456789012:instance-profile/application_abc/component_xyz/Webserver + 2012-05-09T16:27:11Z + + + + + fd74fa8d-99f3-11e1-a4c3-27EXAMPLE804 + + \ No newline at end of file diff --git a/labs/iam/src/test/resources/list_instance_profiles_marker.xml b/labs/iam/src/test/resources/list_instance_profiles_marker.xml new file mode 100644 index 0000000000..c300affea5 --- /dev/null +++ b/labs/iam/src/test/resources/list_instance_profiles_marker.xml @@ -0,0 +1,39 @@ + + + false + + + AIPACIFN4OZXG7EXAMPLE + + + /application_abc/component_xyz/ + arn:aws:iam::123456789012:role/application_abc/component_xyz/S3Access + S3Access + {"Version":"2008-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":["ec2.amazonaws.com"]},"Action":["sts:AssumeRole"]}]} + + 2012-05-09T15:45:35Z + AROACVYKSVTSZFEXAMPLE + + + Database + /application_abc/component_xyz/ + arn:aws:iam::123456789012:instance-profile/application_abc/component_xyz/Database + 2012-05-09T16:27:03Z + + + AIPACZLSXM2EYYEXAMPLE + + Webserver + /application_abc/component_xyz/ + arn:aws:iam::123456789012:instance-profile/application_abc/component_xyz/Webserver + 2012-05-09T16:27:11Z + + + MARKER + false + + + fd74fa8d-99f3-11e1-a4c3-27EXAMPLE804 + +