mirror of https://github.com/apache/jclouds.git
updated IAM listing to be inline with other recent aws apis
This commit is contained in:
parent
1338daec50
commit
9741babe39
|
@ -62,5 +62,4 @@ public interface IAMAsyncApi {
|
|||
*/
|
||||
@Delegate
|
||||
UserAsyncApi getUserApi();
|
||||
|
||||
}
|
||||
|
|
|
@ -45,5 +45,4 @@ public class IAMRestClientModule extends FormSigningRestClientModule<IAMApi, IAM
|
|||
public IAMRestClientModule() {
|
||||
super(typeToken(IAMApi.class), typeToken(IAMAsyncApi.class), DELEGATE_MAP);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
*/
|
||||
package org.jclouds.iam.domain;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
|
@ -28,152 +30,58 @@ import com.google.common.base.Optional;
|
|||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class User {
|
||||
public static Builder<?> builder() {
|
||||
return new ConcreteBuilder();
|
||||
}
|
||||
public final class User {
|
||||
|
||||
public Builder<?> toBuilder() {
|
||||
return new ConcreteBuilder().fromUser(this);
|
||||
}
|
||||
|
||||
public abstract static class Builder<T extends Builder<T>> {
|
||||
protected abstract T self();
|
||||
|
||||
private Optional<String> path = Optional.absent();
|
||||
private String id;
|
||||
private Optional<String> name = Optional.absent();
|
||||
private String arn;
|
||||
private Date createDate;
|
||||
|
||||
/**
|
||||
* @see User#getPath()
|
||||
*/
|
||||
public T path(String path) {
|
||||
this.path = Optional.fromNullable(path);
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see User#getId()
|
||||
*/
|
||||
public T id(String id) {
|
||||
this.id = id;
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see User#getName()
|
||||
*/
|
||||
public T name(String name) {
|
||||
this.name = Optional.fromNullable(name);
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see User#getArn()
|
||||
*/
|
||||
public T arn(String arn) {
|
||||
this.arn = arn;
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see User#getCreateDate()
|
||||
*/
|
||||
public T createDate(Date createDate) {
|
||||
this.createDate = createDate;
|
||||
return self();
|
||||
}
|
||||
|
||||
public User build() {
|
||||
return new User(path, name, id, arn, createDate);
|
||||
}
|
||||
|
||||
public T fromUser(User in) {
|
||||
return this
|
||||
.path(in.getPath().orNull())
|
||||
.name(in.getName().orNull())
|
||||
.id(in.getId())
|
||||
.arn(in.getArn())
|
||||
.createDate(in.getCreateDate())
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
|
||||
@Override
|
||||
protected ConcreteBuilder self() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
private final Optional<String> path;
|
||||
private final Optional<String> name;
|
||||
private final String id;
|
||||
private final String arn;
|
||||
private final Date createDate;
|
||||
|
||||
protected User(Optional<String> path, Optional<String> name, String id, String arn, Date createDate) {
|
||||
this.path = path;
|
||||
this.name = name;
|
||||
this.id = id;
|
||||
this.arn = arn;
|
||||
this.createDate = createDate;
|
||||
|
||||
private User(String id, String arn, Optional<String> path, Optional<String> name, Date createDate) {
|
||||
this.id = checkNotNull(id, "id");
|
||||
this.arn = checkNotNull(arn, "arn for %s", id);
|
||||
this.path = checkNotNull(path, "path for %s", arn);
|
||||
this.name = checkNotNull(name, "name for %s", arn);
|
||||
this.createDate = checkNotNull(createDate, "createDate for %s", arn);
|
||||
}
|
||||
|
||||
/**
|
||||
* you can also optionally give the entity a path that you define. You might use the path to
|
||||
* identify which division or part of the organization the entity belongs in. For example:
|
||||
* /division_abc/subdivision_xyz/product_1234/engineering/
|
||||
*/
|
||||
public Optional<String> getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* When you create a user, a role, or a group, or when you upload a server certificate, you give
|
||||
* it a friendly name, such as Bob, TestApp1, Developers, or ProdServerCert. Whenever you need to
|
||||
* specify a particular entity in an API call to IAM (for example, to delete a user, or update a
|
||||
* group with a new user), you use the friendly name.
|
||||
*/
|
||||
public Optional<String> getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* We assign each user, group, and server certificate a globally unique identifier (GUID), which
|
||||
* we return to you when you use the API or CLI to create it. We recommend you store the GUID in
|
||||
* your own database along with the user, group, or certificate name. Internally we use the GUID
|
||||
* to identify the user, group, or certificate, and we translate the value into the ARN or
|
||||
* friendly name as appropriate when displaying the user, group, or certificate information to
|
||||
* you. If you delete a user, group, or server certificate, any residual remote references to
|
||||
* that item display the GUID as the friendly name part in the ARN. If you've stored the GUID in
|
||||
* your own system, you can then use the displayed GUID to identify the deleted item being
|
||||
* referred to.
|
||||
* a globally unique identifier (GUID), returned from the api.
|
||||
*/
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Although most resources have a friendly name (for example, a user named Bob or a group named
|
||||
* Developers), the access policy language requires you to specify the resource or resources
|
||||
* using the following Amazon Resource Name (ARN) format.
|
||||
*
|
||||
* how to specify the resource in the access policy language ex.
|
||||
* {@code arn:aws:<service>:<region>:<namespace>:<relative-id>}
|
||||
*/
|
||||
public String getArn() {
|
||||
return arn;
|
||||
}
|
||||
|
||||
/**
|
||||
* path ex {@code /division_abc/subdivision_xyz/product_1234/engineering/}
|
||||
*/
|
||||
public Optional<String> getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* friendly name ex. {@code Developers}
|
||||
*/
|
||||
public Optional<String> getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Date the user was created
|
||||
*/
|
||||
public Date getCreateDate() {
|
||||
return createDate;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
|
@ -189,9 +97,7 @@ public class User {
|
|||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
if (obj == null || getClass() != obj.getClass())
|
||||
return false;
|
||||
User other = (User) obj;
|
||||
return Objects.equal(this.id, other.id) && Objects.equal(this.arn, other.arn);
|
||||
|
@ -202,8 +108,71 @@ public class User {
|
|||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return Objects.toStringHelper(this).add("path", path).add("name", name).add("id", id).add("arn", arn).add(
|
||||
"createDate", createDate).toString();
|
||||
return Objects.toStringHelper(this).add("path", path).add("name", name).add("id", id).add("arn", arn)
|
||||
.add("createDate", createDate).toString();
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public Builder toBuilder() {
|
||||
return builder().from(this);
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private Optional<String> path = Optional.absent();
|
||||
private String id;
|
||||
private Optional<String> name = Optional.absent();
|
||||
private String arn;
|
||||
private Date createDate;
|
||||
|
||||
/**
|
||||
* @see User#getPath()
|
||||
*/
|
||||
public Builder path(String path) {
|
||||
this.path = Optional.fromNullable(path);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see User#getId()
|
||||
*/
|
||||
public Builder id(String id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see User#getName()
|
||||
*/
|
||||
public Builder name(String name) {
|
||||
this.name = Optional.fromNullable(name);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see User#getArn()
|
||||
*/
|
||||
public Builder arn(String arn) {
|
||||
this.arn = arn;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see User#getCreateDate()
|
||||
*/
|
||||
public Builder createDate(Date createDate) {
|
||||
this.createDate = createDate;
|
||||
return this;
|
||||
}
|
||||
|
||||
public User build() {
|
||||
return new User(id, arn, path, name, createDate);
|
||||
}
|
||||
|
||||
public Builder from(User in) {
|
||||
return this.path(in.path.orNull()).name(in.name.orNull()).id(in.id).arn(in.arn).createDate(in.createDate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ package org.jclouds.iam.features;
|
|||
import org.jclouds.collect.IterableWithMarker;
|
||||
import org.jclouds.collect.PagedIterable;
|
||||
import org.jclouds.iam.domain.User;
|
||||
import org.jclouds.iam.options.ListUsersOptions;
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
|
@ -37,6 +36,50 @@ public interface UserApi {
|
|||
*/
|
||||
User getCurrent();
|
||||
|
||||
/**
|
||||
* returns all users in order.
|
||||
*/
|
||||
PagedIterable<User> list();
|
||||
|
||||
/**
|
||||
* retrieves up to 100 users in order.
|
||||
*/
|
||||
IterableWithMarker<User> listFirstPage();
|
||||
|
||||
/**
|
||||
* retrieves up to 100 users in order, starting at {@code marker}
|
||||
*
|
||||
* @param marker
|
||||
* starting point to resume the list
|
||||
*/
|
||||
IterableWithMarker<User> listAt(String marker);
|
||||
|
||||
/**
|
||||
* returns all users in order at the specified {@code pathPrefix}.
|
||||
*
|
||||
* @param pathPrefix
|
||||
* ex. {@code /division_abc/subdivision_xyz/}
|
||||
*/
|
||||
PagedIterable<User> listPathPrefix(String pathPrefix);
|
||||
|
||||
/**
|
||||
* retrieves up to 100 users in order at the specified {@code pathPrefix}.
|
||||
*
|
||||
* @param pathPrefix
|
||||
* ex. {@code /division_abc/subdivision_xyz/}
|
||||
*/
|
||||
IterableWithMarker<User> listPathPrefixFirstPage(String pathPrefix);
|
||||
|
||||
/**
|
||||
* retrieves up to 100 users 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<User> listPathPrefixAt(String pathPrefix, String marker);
|
||||
|
||||
/**
|
||||
* Retrieves information about the specified user, including the user's path, GUID, and ARN.
|
||||
*
|
||||
|
@ -46,27 +89,4 @@ public interface UserApi {
|
|||
*/
|
||||
@Nullable
|
||||
User get(String name);
|
||||
|
||||
/**
|
||||
* Lists the users that have the specified path prefix. If there are none, the action returns an
|
||||
* empty list.
|
||||
*
|
||||
* <br/>
|
||||
* You can paginate the results using the {@link ListUsersOptions parameter}
|
||||
*
|
||||
* @param options
|
||||
* the options describing the users query
|
||||
*
|
||||
* @return the response object
|
||||
*/
|
||||
IterableWithMarker<User> list(ListUsersOptions options);
|
||||
|
||||
/**
|
||||
* Lists the users that have the specified path prefix. If there are none, the action returns an
|
||||
* empty list.
|
||||
*
|
||||
* @return the response object
|
||||
*/
|
||||
PagedIterable<User> list();
|
||||
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@ import org.jclouds.collect.IterableWithMarker;
|
|||
import org.jclouds.collect.PagedIterable;
|
||||
import org.jclouds.iam.domain.User;
|
||||
import org.jclouds.iam.functions.UsersToPagedIterable;
|
||||
import org.jclouds.iam.options.ListUsersOptions;
|
||||
import org.jclouds.iam.xml.ListUsersResultHandler;
|
||||
import org.jclouds.iam.xml.UserHandler;
|
||||
import org.jclouds.rest.annotations.Fallback;
|
||||
|
@ -52,6 +51,69 @@ import com.google.common.util.concurrent.ListenableFuture;
|
|||
@VirtualHost
|
||||
public interface UserAsyncApi {
|
||||
|
||||
/**
|
||||
* @see UserApi#list()
|
||||
*/
|
||||
@Named("ListUsers")
|
||||
@POST
|
||||
@Path("/")
|
||||
@FormParams(keys = "Action", values = "ListUsers")
|
||||
@XMLResponseParser(ListUsersResultHandler.class)
|
||||
@Transform(UsersToPagedIterable.class)
|
||||
ListenableFuture<PagedIterable<User>> list();
|
||||
|
||||
/**
|
||||
* @see UserApi#listFirstPage
|
||||
*/
|
||||
@Named("ListUsers")
|
||||
@POST
|
||||
@Path("/")
|
||||
@FormParams(keys = "Action", values = "ListUsers")
|
||||
@XMLResponseParser(ListUsersResultHandler.class)
|
||||
ListenableFuture<IterableWithMarker<User>> listFirstPage();
|
||||
|
||||
/**
|
||||
* @see UserApi#listAt(String)
|
||||
*/
|
||||
@Named("ListUsers")
|
||||
@POST
|
||||
@Path("/")
|
||||
@FormParams(keys = "Action", values = "ListUsers")
|
||||
@XMLResponseParser(ListUsersResultHandler.class)
|
||||
ListenableFuture<IterableWithMarker<User>> listAt(@FormParam("Marker") String marker);
|
||||
|
||||
/**
|
||||
* @see UserApi#listPathPrefix(String)
|
||||
*/
|
||||
@Named("ListUsers")
|
||||
@POST
|
||||
@Path("/")
|
||||
@FormParams(keys = "Action", values = "ListUsers")
|
||||
@XMLResponseParser(ListUsersResultHandler.class)
|
||||
@Transform(UsersToPagedIterable.class)
|
||||
ListenableFuture<PagedIterable<User>> listPathPrefix(@FormParam("PathPrefix") String pathPrefix);
|
||||
|
||||
/**
|
||||
* @see UserApi#listPathPrefixFirstPage(String)
|
||||
*/
|
||||
@Named("ListUsers")
|
||||
@POST
|
||||
@Path("/")
|
||||
@FormParams(keys = "Action", values = "ListUsers")
|
||||
@XMLResponseParser(ListUsersResultHandler.class)
|
||||
ListenableFuture<IterableWithMarker<User>> listPathPrefixFirstPage(@FormParam("PathPrefix") String pathPrefix);
|
||||
|
||||
/**
|
||||
* @see UserApi#listPathPrefixAt(String, String)
|
||||
*/
|
||||
@Named("ListUsers")
|
||||
@POST
|
||||
@Path("/")
|
||||
@FormParams(keys = "Action", values = "ListUsers")
|
||||
@XMLResponseParser(ListUsersResultHandler.class)
|
||||
ListenableFuture<IterableWithMarker<User>> listPathPrefixAt(@FormParam("PathPrefix") String pathPrefix,
|
||||
@FormParam("Marker") String marker);
|
||||
|
||||
/**
|
||||
* @see UserApi#getCurrent()
|
||||
*/
|
||||
|
@ -61,7 +123,7 @@ public interface UserAsyncApi {
|
|||
@XMLResponseParser(UserHandler.class)
|
||||
@FormParams(keys = "Action", values = "GetUser")
|
||||
ListenableFuture<User> getCurrent();
|
||||
|
||||
|
||||
/**
|
||||
* @see UserApi#get()
|
||||
*/
|
||||
|
@ -72,26 +134,4 @@ public interface UserAsyncApi {
|
|||
@FormParams(keys = "Action", values = "GetUser")
|
||||
@Fallback(NullOnNotFoundOr404.class)
|
||||
ListenableFuture<User> get(@FormParam("UserName") String name);
|
||||
|
||||
/**
|
||||
* @see UserApi#list()
|
||||
*/
|
||||
@Named("ListUsers")
|
||||
@POST
|
||||
@Path("/")
|
||||
@XMLResponseParser(ListUsersResultHandler.class)
|
||||
@Transform(UsersToPagedIterable.class)
|
||||
@FormParams(keys = "Action", values = "ListUsers")
|
||||
ListenableFuture<PagedIterable<User>> list();
|
||||
|
||||
/**
|
||||
* @see UserApi#list(ListUsersOptions)
|
||||
*/
|
||||
@Named("ListUsers")
|
||||
@POST
|
||||
@Path("/")
|
||||
@XMLResponseParser(ListUsersResultHandler.class)
|
||||
@FormParams(keys = "Action", values = "ListUsers")
|
||||
ListenableFuture<IterableWithMarker<User>> list(ListUsersOptions options);
|
||||
|
||||
}
|
||||
|
|
|
@ -23,43 +23,68 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||
import javax.inject.Inject;
|
||||
|
||||
import org.jclouds.collect.IterableWithMarker;
|
||||
import org.jclouds.collect.internal.CallerArg0ToPagedIterable;
|
||||
import org.jclouds.collect.internal.Arg0ToPagedIterable;
|
||||
import org.jclouds.iam.IAMApi;
|
||||
import org.jclouds.iam.domain.User;
|
||||
import org.jclouds.iam.features.UserApi;
|
||||
import org.jclouds.iam.options.ListUsersOptions;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Optional;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Beta
|
||||
public class UsersToPagedIterable extends CallerArg0ToPagedIterable<User, UsersToPagedIterable> {
|
||||
public class UsersToPagedIterable extends Arg0ToPagedIterable<User, UsersToPagedIterable> {
|
||||
|
||||
private final IAMApi api;
|
||||
private final UserApi api;
|
||||
|
||||
@Inject
|
||||
protected UsersToPagedIterable(IAMApi api) {
|
||||
this.api = checkNotNull(api, "api");
|
||||
this.api = checkNotNull(api, "api").getUserApi();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Function<Object, IterableWithMarker<User>> markerToNextForCallingArg0(String ignored) {
|
||||
final UserApi userApi = api.getUserApi();
|
||||
return new Function<Object, IterableWithMarker<User>>() {
|
||||
|
||||
@Override
|
||||
public IterableWithMarker<User> apply(Object input) {
|
||||
return userApi.list(ListUsersOptions.Builder.afterMarker(input.toString()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "listUsers()";
|
||||
}
|
||||
};
|
||||
protected Function<Object, IterableWithMarker<User>> markerToNextForArg0(Optional<Object> pathPrefix) {
|
||||
if (pathPrefix.isPresent())
|
||||
return new ListUsersUnderPathPrefixAtMarker(api, pathPrefix.get().toString());
|
||||
return new ListUsersAtMarker(api);
|
||||
}
|
||||
|
||||
private static class ListUsersUnderPathPrefixAtMarker implements Function<Object, IterableWithMarker<User>> {
|
||||
private final UserApi api;
|
||||
private final String pathPrefix;
|
||||
|
||||
@Inject
|
||||
protected ListUsersUnderPathPrefixAtMarker(UserApi api, String pathPrefix) {
|
||||
this.api = checkNotNull(api, "api");
|
||||
this.pathPrefix = checkNotNull(pathPrefix, "pathPrefix");
|
||||
}
|
||||
|
||||
public IterableWithMarker<User> apply(Object input) {
|
||||
return api.listPathPrefixAt(pathPrefix, input.toString());
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "ListUsersUnderPathPrefixAtMarker(" + pathPrefix + ")";
|
||||
}
|
||||
}
|
||||
|
||||
private static class ListUsersAtMarker implements Function<Object, IterableWithMarker<User>> {
|
||||
private final UserApi api;
|
||||
|
||||
@Inject
|
||||
protected ListUsersAtMarker(UserApi api) {
|
||||
this.api = checkNotNull(api, "api");
|
||||
}
|
||||
|
||||
public IterableWithMarker<User> apply(Object input) {
|
||||
return api.listAt(input.toString());
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "listUsersAtMarker()";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,144 +0,0 @@
|
|||
/**
|
||||
* 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.options;
|
||||
|
||||
import org.jclouds.http.options.BaseHttpRequestOptions;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
/**
|
||||
* Options used to list available users.
|
||||
*
|
||||
* @see <a href="http://docs.amazonwebservices.com/IAM/latest/APIReference/API_ListUsers.html" />
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class ListUsersOptions extends BaseHttpRequestOptions implements Cloneable {
|
||||
|
||||
private Integer maxItems;
|
||||
private String pathPrefix;
|
||||
private Object afterMarker;
|
||||
|
||||
/**
|
||||
* Use this parameter only when paginating results, and only in a subsequent request after you've
|
||||
* received a response where the results are truncated. Set it to the value of the Marker element
|
||||
* in the response you just received.
|
||||
*/
|
||||
public ListUsersOptions afterMarker(Object afterMarker) {
|
||||
this.afterMarker = afterMarker;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this parameter only when paginating results to indicate the maximum number of user names
|
||||
* you want in the response. If there are additional user names beyond the maximum you specify,
|
||||
* the IsTruncated response element is true.
|
||||
*/
|
||||
public ListUsersOptions maxItems(Integer maxItems) {
|
||||
this.maxItems = maxItems;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The path prefix for filtering the results. For example: /division_abc/subdivision_xyz/, which
|
||||
* would get all user names whose path starts with /division_abc/subdivision_xyz/.
|
||||
* <p/>
|
||||
* This parameter is optional. If it is not included, it defaults to a slash (/), listing all
|
||||
* user names.
|
||||
*/
|
||||
public ListUsersOptions pathPrefix(String pathPrefix) {
|
||||
this.pathPrefix = pathPrefix;
|
||||
return this;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
|
||||
/**
|
||||
* @see ListUsersOptions#afterMarker
|
||||
*/
|
||||
public static ListUsersOptions afterMarker(Object afterMarker) {
|
||||
return new ListUsersOptions().afterMarker(afterMarker);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ListUsersOptions#maxItems
|
||||
*/
|
||||
public static ListUsersOptions maxItems(Integer maxItems) {
|
||||
return new ListUsersOptions().maxItems(maxItems);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ListUsersOptions#pathPrefix
|
||||
*/
|
||||
public static ListUsersOptions pathPrefix(String pathPrefix) {
|
||||
return new ListUsersOptions().pathPrefix(pathPrefix);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Multimap<String, String> buildFormParameters() {
|
||||
Multimap<String, String> params = super.buildFormParameters();
|
||||
if (afterMarker != null)
|
||||
params.put("Marker", afterMarker.toString());
|
||||
if (maxItems != null)
|
||||
params.put("MaxItems", maxItems.toString());
|
||||
if (pathPrefix != null)
|
||||
params.put("PathPrefix", pathPrefix);
|
||||
return params;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(afterMarker, maxItems, pathPrefix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListUsersOptions clone() {
|
||||
return new ListUsersOptions().afterMarker(afterMarker).maxItems(maxItems).pathPrefix(pathPrefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
ListUsersOptions other = ListUsersOptions.class.cast(obj);
|
||||
return Objects.equal(this.afterMarker, other.afterMarker) && Objects.equal(this.maxItems, other.maxItems)
|
||||
&& Objects.equal(this.pathPrefix, other.pathPrefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return Objects.toStringHelper(this).omitNullValues().add("afterMarker", afterMarker).add("maxItems", maxItems).add(
|
||||
"pathPrefix", pathPrefix).toString();
|
||||
}
|
||||
}
|
|
@ -18,17 +18,17 @@
|
|||
*/
|
||||
package org.jclouds.iam.xml;
|
||||
|
||||
import java.util.Set;
|
||||
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.User;
|
||||
import org.jclouds.util.SaxUtils;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableList.Builder;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
|
@ -41,7 +41,7 @@ public class ListUsersResultHandler extends ParseSax.HandlerForGeneratedRequestW
|
|||
private final UserHandler userHandler;
|
||||
|
||||
private StringBuilder currentText = new StringBuilder();
|
||||
private Set<User> users = Sets.newLinkedHashSet();
|
||||
private Builder<User> users = ImmutableList.<User> builder();
|
||||
private boolean inUsers;
|
||||
private String afterMarker;
|
||||
|
||||
|
@ -50,20 +50,18 @@ public class ListUsersResultHandler extends ParseSax.HandlerForGeneratedRequestW
|
|||
this.userHandler = userHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public IterableWithMarker<User> getResult() {
|
||||
return IterableWithMarkers.from(users, afterMarker);
|
||||
try {
|
||||
return IterableWithMarkers.from(users.build(), afterMarker);
|
||||
} finally {
|
||||
users = ImmutableList.<User> builder();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void startElement(String url, String name, String qName, Attributes attributes) throws SAXException {
|
||||
if (SaxUtils.equalsOrSuffix(qName, "Users")) {
|
||||
public void startElement(String url, String name, String qName, Attributes attributes) {
|
||||
if (equalsOrSuffix(qName, "Users")) {
|
||||
inUsers = true;
|
||||
}
|
||||
if (inUsers) {
|
||||
|
@ -71,11 +69,8 @@ public class ListUsersResultHandler extends ParseSax.HandlerForGeneratedRequestW
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void endElement(String uri, String name, String qName) throws SAXException {
|
||||
public void endElement(String uri, String name, String qName) {
|
||||
if (inUsers) {
|
||||
if (qName.equals("Users")) {
|
||||
inUsers = false;
|
||||
|
@ -85,15 +80,12 @@ public class ListUsersResultHandler extends ParseSax.HandlerForGeneratedRequestW
|
|||
userHandler.endElement(uri, name, qName);
|
||||
}
|
||||
} else if (qName.equals("Marker")) {
|
||||
afterMarker = SaxUtils.currentOrNull(currentText);
|
||||
afterMarker = currentOrNull(currentText);
|
||||
}
|
||||
|
||||
currentText = new StringBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void characters(char ch[], int start, int length) {
|
||||
if (inUsers) {
|
||||
|
@ -102,5 +94,4 @@ public class ListUsersResultHandler extends ParseSax.HandlerForGeneratedRequestW
|
|||
currentText.append(ch, start, length);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,13 +18,14 @@
|
|||
*/
|
||||
package org.jclouds.iam.xml;
|
||||
|
||||
import static org.jclouds.util.SaxUtils.currentOrNull;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.jclouds.date.DateService;
|
||||
import org.jclouds.http.functions.ParseSax;
|
||||
import org.jclouds.iam.domain.User;
|
||||
import org.jclouds.util.SaxUtils;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.Attributes;
|
||||
|
||||
/**
|
||||
* @see <a href="http://docs.amazonwebservices.com/IAM/latest/APIReference/API_GetUser.html" />
|
||||
|
@ -40,11 +41,8 @@ public class UserHandler extends ParseSax.HandlerForGeneratedRequestWithResult<U
|
|||
}
|
||||
|
||||
private StringBuilder currentText = new StringBuilder();
|
||||
private User.Builder<?> builder = User.builder();
|
||||
private User.Builder builder = User.builder();
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public User getResult() {
|
||||
try {
|
||||
|
@ -54,31 +52,28 @@ public class UserHandler extends ParseSax.HandlerForGeneratedRequestWithResult<U
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void endElement(String uri, String name, String qName) throws SAXException {
|
||||
public void startElement(String url, String name, String qName, Attributes attributes) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endElement(String uri, String name, String qName) {
|
||||
if (qName.equals("Path")) {
|
||||
builder.path(SaxUtils.currentOrNull(currentText));
|
||||
builder.path(currentOrNull(currentText));
|
||||
} else if (qName.equals("UserName")) {
|
||||
builder.name(SaxUtils.currentOrNull(currentText));
|
||||
builder.name(currentOrNull(currentText));
|
||||
} else if (qName.equals("UserId")) {
|
||||
builder.id(SaxUtils.currentOrNull(currentText));
|
||||
builder.id(currentOrNull(currentText));
|
||||
} else if (qName.equals("Arn")) {
|
||||
builder.arn(SaxUtils.currentOrNull(currentText));
|
||||
builder.arn(currentOrNull(currentText));
|
||||
} else if (qName.equals("CreateDate")) {
|
||||
builder.createDate(dateService.iso8601SecondsDateParse(SaxUtils.currentOrNull(currentText)));
|
||||
builder.createDate(dateService.iso8601SecondsDateParse(currentOrNull(currentText)));
|
||||
}
|
||||
currentText = new StringBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void characters(char ch[], int start, int length) {
|
||||
currentText.append(ch, start, length);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
*/
|
||||
package org.jclouds.iam.features;
|
||||
|
||||
import static org.jclouds.iam.options.ListUsersOptions.Builder.pathPrefix;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertNull;
|
||||
|
||||
|
@ -114,7 +113,7 @@ public class UserApiExpectTest extends BaseIAMApiExpectTest {
|
|||
.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)
|
||||
|
@ -153,7 +152,58 @@ public class UserApiExpectTest extends BaseIAMApiExpectTest {
|
|||
ImmutableList.copyOf(Iterables.concat(new ListUsersResponseTest().expected(), new ListUsersResponseTest().expected())));
|
||||
}
|
||||
|
||||
|
||||
HttpRequest listPathPrefix = HttpRequest.builder()
|
||||
.method("POST")
|
||||
.endpoint("https://iam.amazonaws.com/")
|
||||
.addHeader("Host", "iam.amazonaws.com")
|
||||
.addFormParam("Action", "ListUsers")
|
||||
.addFormParam("PathPrefix", "/subdivision")
|
||||
.addFormParam("Signature", "giw/28vFH9GZoqf60bP4Ka80kBXhJDcncC%2BWA0Dkg/o%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_users.xml", "text/xml")).build();
|
||||
|
||||
IAMApi apiWhenExist = requestSendsResponse(
|
||||
listPathPrefix, listResponse);
|
||||
|
||||
assertEquals(apiWhenExist.getUserApi().listPathPrefix("/subdivision").get(0).toString(), new ListUsersResponseTest().expected().toString());
|
||||
}
|
||||
|
||||
public void testListPathPrefix2PagesWhenResponseIs2xx() throws Exception {
|
||||
|
||||
HttpResponse listResponse = HttpResponse.builder().statusCode(200)
|
||||
.payload(payloadFromResourceWithContentType("/list_users_marker.xml", "text/xml")).build();
|
||||
|
||||
HttpRequest listPathPrefix2 = HttpRequest.builder()
|
||||
.method("POST")
|
||||
.endpoint("https://iam.amazonaws.com/")
|
||||
.addHeader("Host", "iam.amazonaws.com")
|
||||
.addFormParam("Action", "ListUsers")
|
||||
.addFormParam("Marker", "MARKER")
|
||||
.addFormParam("PathPrefix", "/subdivision")
|
||||
.addFormParam("Signature", "JSAWWjJdoz8Twn3CSjkuqWIJmmokjQyKPOdekNeVl30%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_users.xml", "text/xml")).build();
|
||||
|
||||
IAMApi apiWhenExist = requestsSendResponses(listPathPrefix, listResponse, listPathPrefix2, list2Response);
|
||||
|
||||
assertEquals(apiWhenExist.getUserApi().listPathPrefix("/subdivision").concat().toList(),
|
||||
ImmutableList.copyOf(Iterables.concat(new ListUsersResponseTest().expected(), new ListUsersResponseTest().expected())));
|
||||
}
|
||||
|
||||
// TODO: this should really be an empty set
|
||||
@Test(expectedExceptions = ResourceNotFoundException.class)
|
||||
public void testListWhenResponseIs404() throws Exception {
|
||||
|
@ -166,7 +216,7 @@ public class UserApiExpectTest extends BaseIAMApiExpectTest {
|
|||
apiWhenDontExist.getUserApi().list().get(0);
|
||||
}
|
||||
|
||||
public void testListWithOptionsWhenResponseIs2xx() throws Exception {
|
||||
public void testListPathPrefixAtWhenResponseIs2xx() throws Exception {
|
||||
HttpRequest listWithOptions =
|
||||
HttpRequest.builder()
|
||||
.method("POST")
|
||||
|
@ -188,7 +238,7 @@ public class UserApiExpectTest extends BaseIAMApiExpectTest {
|
|||
IAMApi apiWhenWithOptionsExist = requestSendsResponse(listWithOptions,
|
||||
listWithOptionsResponse);
|
||||
|
||||
assertEquals(apiWhenWithOptionsExist.getUserApi().list(pathPrefix("/foo").afterMarker("MARKER")).toString(),
|
||||
assertEquals(apiWhenWithOptionsExist.getUserApi().listPathPrefixAt("/foo", "MARKER").toString(),
|
||||
new ListUsersResponseTest().expected().toString());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,15 +19,15 @@
|
|||
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 org.jclouds.collect.IterableWithMarker;
|
||||
import org.jclouds.iam.domain.User;
|
||||
import org.jclouds.iam.internal.BaseIAMApiLiveTest;
|
||||
import org.jclouds.iam.options.ListUsersOptions;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
|
@ -42,30 +42,23 @@ public class UserApiLiveTest extends BaseIAMApiLiveTest {
|
|||
}
|
||||
|
||||
private void checkUser(User user) {
|
||||
checkNotNull(user.getArn(), "Arn cannot be null for a User.");
|
||||
checkNotNull(user.getId(), "Id cannot be null for a User.");
|
||||
checkNotNull(user.getName(), "While Name can be null for a User, its Optional wrapper cannot.");
|
||||
checkNotNull(user.getPath(), "While Path can be null for a User, its Optional wrapper cannot.");
|
||||
checkNotNull(user.getCreateDate(), "CreateDate cannot be null for a 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);
|
||||
checkNotNull(user.getPath(), "While Path can be null for a User, its Optional wrapper cannot; user %s", user);
|
||||
checkNotNull(user.getCreateDate(), "CreateDate cannot be null for a User User %s", user);
|
||||
}
|
||||
|
||||
@Test
|
||||
protected void testListUsers() {
|
||||
IterableWithMarker<User> response = api().list().get(0);
|
||||
|
||||
for (User user : response) {
|
||||
checkUser(user);
|
||||
}
|
||||
|
||||
if (Iterables.size(response) > 0) {
|
||||
User user = response.iterator().next();
|
||||
Assert.assertEquals(api().get(user.getName().get()), user);
|
||||
}
|
||||
ImmutableList<User> users = api().list().concat().toList();
|
||||
getAnonymousLogger().info("users: " + users.size());
|
||||
|
||||
// Test with a Marker, even if it's null
|
||||
response = api().list(ListUsersOptions.Builder.afterMarker(response.nextMarker().orNull()));
|
||||
for (User user : response) {
|
||||
for (User user : users) {
|
||||
checkUser(user);
|
||||
assertEquals(api().get(user.getId()), user);
|
||||
if (user.getPath().isPresent())
|
||||
assertEquals(api().listPathPrefix(user.getPath().get()).toSet(), ImmutableSet.of(user));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
/**
|
||||
* 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.options;
|
||||
|
||||
import static org.jclouds.iam.options.ListUsersOptions.Builder.afterMarker;
|
||||
import static org.jclouds.iam.options.ListUsersOptions.Builder.maxItems;
|
||||
import static org.jclouds.iam.options.ListUsersOptions.Builder.pathPrefix;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
/**
|
||||
* Tests behavior of {@code ListUsersOptions}
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "maxItems", testName = "ListUsersOptionsTest")
|
||||
public class ListUsersOptionsTest {
|
||||
|
||||
public void testMarker() {
|
||||
ListUsersOptions options = new ListUsersOptions().afterMarker("FFFFF");
|
||||
assertEquals(ImmutableSet.of("FFFFF"), options.buildFormParameters().get("Marker"));
|
||||
}
|
||||
|
||||
public void testMarkerStatic() {
|
||||
ListUsersOptions options = afterMarker("FFFFF");
|
||||
assertEquals(ImmutableSet.of("FFFFF"), options.buildFormParameters().get("Marker"));
|
||||
}
|
||||
|
||||
public void testMaxItems() {
|
||||
ListUsersOptions options = new ListUsersOptions().maxItems(1000);
|
||||
assertEquals(ImmutableSet.of("1000"), options.buildFormParameters().get("MaxItems"));
|
||||
}
|
||||
|
||||
public void testMaxItemsStatic() {
|
||||
ListUsersOptions options = maxItems(1000);
|
||||
assertEquals(ImmutableSet.of("1000"), options.buildFormParameters().get("MaxItems"));
|
||||
}
|
||||
|
||||
public void testPathPrefix() {
|
||||
ListUsersOptions options = new ListUsersOptions().pathPrefix("/division_abc/subdivision_xyz/");
|
||||
assertEquals(ImmutableSet.of("/division_abc/subdivision_xyz/"), options.buildFormParameters().get("PathPrefix"));
|
||||
}
|
||||
|
||||
public void testPathPrefixStatic() {
|
||||
ListUsersOptions options = pathPrefix("/division_abc/subdivision_xyz/");
|
||||
assertEquals(ImmutableSet.of("/division_abc/subdivision_xyz/"), options.buildFormParameters().get("PathPrefix"));
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue