diff --git a/openstack-reddwarf/src/main/java/org/jclouds/openstack/reddwarf/v1/RedDwarfApi.java b/openstack-reddwarf/src/main/java/org/jclouds/openstack/reddwarf/v1/RedDwarfApi.java index 089cee4..273f4dd 100644 --- a/openstack-reddwarf/src/main/java/org/jclouds/openstack/reddwarf/v1/RedDwarfApi.java +++ b/openstack-reddwarf/src/main/java/org/jclouds/openstack/reddwarf/v1/RedDwarfApi.java @@ -20,16 +20,15 @@ import java.io.Closeable; import java.util.Set; - import org.jclouds.javax.annotation.Nullable; import org.jclouds.location.Zone; import org.jclouds.location.functions.ZoneToEndpoint; import org.jclouds.openstack.keystone.v2_0.domain.Tenant; import org.jclouds.openstack.reddwarf.v1.features.FlavorApi; import org.jclouds.openstack.reddwarf.v1.features.InstanceApi; +import org.jclouds.openstack.reddwarf.v1.features.UserApi; import org.jclouds.rest.annotations.Delegate; import org.jclouds.rest.annotations.EndpointParam; - import com.google.common.base.Optional; import com.google.inject.Provides; @@ -61,6 +60,13 @@ FlavorApi getFlavorApiForZone( InstanceApi getInstanceApiForZone( @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone); + /** + * Provides access to User features. + */ + @Delegate + UserApi getUserApiForZone( + @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone); + /** * Provides the Tenant */ diff --git a/openstack-reddwarf/src/main/java/org/jclouds/openstack/redddwarf/v1/binders/BindCreateInstanceToJson.java b/openstack-reddwarf/src/main/java/org/jclouds/openstack/reddwarf/v1/binders/BindCreateInstanceToJson.java similarity index 97% rename from openstack-reddwarf/src/main/java/org/jclouds/openstack/redddwarf/v1/binders/BindCreateInstanceToJson.java rename to openstack-reddwarf/src/main/java/org/jclouds/openstack/reddwarf/v1/binders/BindCreateInstanceToJson.java index ff161a0..bb70d62 100644 --- a/openstack-reddwarf/src/main/java/org/jclouds/openstack/redddwarf/v1/binders/BindCreateInstanceToJson.java +++ b/openstack-reddwarf/src/main/java/org/jclouds/openstack/reddwarf/v1/binders/BindCreateInstanceToJson.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.jclouds.openstack.redddwarf.v1.binders; +package org.jclouds.openstack.reddwarf.v1.binders; import java.util.Map; import org.jclouds.http.HttpRequest; diff --git a/openstack-reddwarf/src/main/java/org/jclouds/openstack/reddwarf/v1/binders/BindCreateUserToJson.java b/openstack-reddwarf/src/main/java/org/jclouds/openstack/reddwarf/v1/binders/BindCreateUserToJson.java new file mode 100644 index 0000000..7e3010c --- /dev/null +++ b/openstack-reddwarf/src/main/java/org/jclouds/openstack/reddwarf/v1/binders/BindCreateUserToJson.java @@ -0,0 +1,67 @@ +/** + * 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.openstack.reddwarf.v1.binders; + +import java.util.Map; +import java.util.Set; + +import org.jclouds.http.HttpRequest; +import org.jclouds.openstack.reddwarf.v1.domain.Database; +import org.jclouds.openstack.reddwarf.v1.domain.User; +import org.jclouds.rest.MapBinder; +import org.jclouds.rest.binders.BindToJsonPayload; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Sets; +import com.google.inject.Inject; + +/** + * @author Zack Shoylev + */ +public class BindCreateUserToJson implements MapBinder { + + @Inject + private BindToJsonPayload jsonBinder; + + @SuppressWarnings("unchecked") + @Override + public R bindToRequest(R request, Map postParams) { + Set users = Sets.newHashSet(); + if( postParams.get("name") != null ) { + Database database = Database.builder().name((String) postParams.get("databaseName")).build(); + Set databases = Sets.newHashSet(); + databases.add(database); + User user = User.builder() + .name((String) postParams.get("name")) + .password((String) postParams.get("password")) + .databases(databases) + .build(); + users.add(user); + } + else if( postParams.get("users") != null ) { + users = (Set) postParams.get("users"); + } + return jsonBinder.bindToRequest(request, ImmutableMap.of("users", users)); + } + + @Override + public R bindToRequest(R request, Object toBind) { + throw new IllegalStateException("Create user is a POST operation"); + } +} diff --git a/openstack-reddwarf/src/main/java/org/jclouds/openstack/reddwarf/v1/binders/BindGrantUserToJson.java b/openstack-reddwarf/src/main/java/org/jclouds/openstack/reddwarf/v1/binders/BindGrantUserToJson.java new file mode 100644 index 0000000..8d8f5f2 --- /dev/null +++ b/openstack-reddwarf/src/main/java/org/jclouds/openstack/reddwarf/v1/binders/BindGrantUserToJson.java @@ -0,0 +1,59 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.openstack.reddwarf.v1.binders; + +import java.util.Map; +import java.util.Set; + +import org.jclouds.http.HttpRequest; +import org.jclouds.openstack.reddwarf.v1.domain.Database; +import org.jclouds.rest.MapBinder; +import org.jclouds.rest.binders.BindToJsonPayload; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Sets; +import com.google.inject.Inject; + +/** + * @author Zack Shoylev + */ +public class BindGrantUserToJson implements MapBinder { + + @Inject + private BindToJsonPayload jsonBinder; + + @SuppressWarnings("unchecked") + @Override + public R bindToRequest(R request, Map postParams) { + Set databases = Sets.newHashSet(); + if( postParams.get("databaseName")!=null ) { + Database database = Database.builder().name((String)postParams.get("databaseName")).build(); + databases.add(database); + } + else if( postParams.get("databases")!=null ) { + databases = (Set) postParams.get("databases"); + } + return jsonBinder.bindToRequest(request, ImmutableMap.of("databases", databases)); + } + + @Override + public R bindToRequest(R request, Object toBind) { + throw new IllegalStateException("Grant user is a PUT operation"); + } +} diff --git a/openstack-reddwarf/src/main/java/org/jclouds/openstack/reddwarf/v1/domain/Database.java b/openstack-reddwarf/src/main/java/org/jclouds/openstack/reddwarf/v1/domain/Database.java new file mode 100644 index 0000000..943725b --- /dev/null +++ b/openstack-reddwarf/src/main/java/org/jclouds/openstack/reddwarf/v1/domain/Database.java @@ -0,0 +1,112 @@ +/* + * 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.openstack.reddwarf.v1.domain; + +import static com.google.common.base.Preconditions.checkNotNull; +import java.beans.ConstructorProperties; +import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; + +/** + * An Openstack Reddwarf Database. + * + * @author Zack Shoylev + */ +public class Database implements Comparable{ + + private final String name; + + @ConstructorProperties({ + "name" + }) + protected Database(String name) { + this.name = checkNotNull(name, "name required"); + } + + /** + * @return the name of this database + * @see Database.Builder#name(String) + */ + public String getName() { + return this.name; + } + + @Override + public int hashCode() { + return Objects.hashCode(name); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + Database that = Database.class.cast(obj); + return Objects.equal(this.name, that.name); + } + + protected ToStringHelper string() { + return Objects.toStringHelper(this) + .add("name", name); + } + + @Override + public String toString() { + return string().toString(); + } + + public static Builder builder() { + return new Builder(); + } + + public Builder toBuilder() { + return new Builder().fromDatabase(this); + } + + public static class Builder { + protected String name; + + /** + * @param name The name of this database + * @return The builder object + * @see Database#getName() + */ + public Builder name(String name) { + this.name = name; + return this; + } + + /** + * + * @return A new Database object + */ + public Database build() { + return new Database(name); + } + + public Builder fromDatabase(Database in) { + return this + .name(in.getName()); + } + } + + @Override + public int compareTo(Database that) { + return this.getName().compareTo(that.getName()); + } +} diff --git a/openstack-reddwarf/src/main/java/org/jclouds/openstack/reddwarf/v1/domain/User.java b/openstack-reddwarf/src/main/java/org/jclouds/openstack/reddwarf/v1/domain/User.java new file mode 100644 index 0000000..a29ee9c --- /dev/null +++ b/openstack-reddwarf/src/main/java/org/jclouds/openstack/reddwarf/v1/domain/User.java @@ -0,0 +1,163 @@ +/* + * 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.openstack.reddwarf.v1.domain; + +import static com.google.common.base.Preconditions.checkNotNull; +import java.beans.ConstructorProperties; +import java.util.Set; +import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; +import com.google.common.collect.ImmutableSet; + +/** + * An Openstack Reddwarf Database User. + * + * @author Zack Shoylev + */ +public class User implements Comparable{ + private final String name; + private final String password; + private final Set databases; + + @ConstructorProperties({ + "name", "password", "databases" + }) + protected User(String name, String password, Set databases) { + this.name = checkNotNull(name, "name required"); + this.password = password; + if(databases == null)this.databases = ImmutableSet.of(); + else this.databases = databases; + } + + /** + * @return the name of this user + * @see User.Builder#name(String) + */ + public String getName() { + return this.name; + } + + /** + * @return the password for this user + * @see User.Builder#password(String) + */ + public String getPassword() { + return this.password; + } + + /** + * @return the databases for this user + * @see User.Builder#databases(String) + */ + public Set getDatabases() { + return this.databases; + } + + @Override + public int hashCode() { + return Objects.hashCode(name, password, databases); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + User that = User.class.cast(obj); + return Objects.equal(this.name, that.name) && + Objects.equal(this.password, that.password) && + Objects.equal(this.databases, that.databases); + } + + protected ToStringHelper string() { + return Objects.toStringHelper(this) + .add("name", name) + .add("password", password) + .add("databases", databases); + } + + @Override + public String toString() { + return string().toString(); + } + + public static Builder builder() { + return new Builder(); + } + + public Builder toBuilder() { + return new Builder().fromUser(this); + } + + public static class Builder { + protected String name; + protected String password; + protected Set databases; + + /** + * @param name The name of this user + * @return The builder object + * @see User#getName() + */ + public Builder name(String name) { + this.name = name; + return this; + } + + /** + * @param name The password for this user + * @return The builder object + * @see User#getPassword() + */ + public Builder password(String password) { + this.password = password; + return this; + } + + /** + * @param name The databases for this user + * @return The builder object + * @see User#getDatabases() + */ + public Builder databases(Set databases) { + this.databases = databases; + return this; + } + + /** + * + * @return A new User object + */ + public User build() { + return new User(name, password, databases); + } + + public Builder fromUser(User in) { + return this + .name(in.getName()) + .password(in.getPassword()) + .databases(in.getDatabases()); + } + } + + @Override + public int compareTo(User that) { + return this.getName().compareTo(that.getName()); + } +} diff --git a/openstack-reddwarf/src/main/java/org/jclouds/openstack/reddwarf/v1/features/InstanceApi.java b/openstack-reddwarf/src/main/java/org/jclouds/openstack/reddwarf/v1/features/InstanceApi.java index d63c388..d4d91ba 100644 --- a/openstack-reddwarf/src/main/java/org/jclouds/openstack/reddwarf/v1/features/InstanceApi.java +++ b/openstack-reddwarf/src/main/java/org/jclouds/openstack/reddwarf/v1/features/InstanceApi.java @@ -32,7 +32,7 @@ import org.jclouds.Fallbacks.NullOnNotFoundOr404; import org.jclouds.javax.annotation.Nullable; import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest; -import org.jclouds.openstack.redddwarf.v1.binders.BindCreateInstanceToJson; +import org.jclouds.openstack.reddwarf.v1.binders.BindCreateInstanceToJson; import org.jclouds.openstack.reddwarf.v1.domain.Instance; import org.jclouds.openstack.reddwarf.v1.functions.ParsePasswordFromRootedInstance; import org.jclouds.rest.ResourceNotFoundException; diff --git a/openstack-reddwarf/src/main/java/org/jclouds/openstack/reddwarf/v1/features/UserApi.java b/openstack-reddwarf/src/main/java/org/jclouds/openstack/reddwarf/v1/features/UserApi.java new file mode 100644 index 0000000..a55bbae --- /dev/null +++ b/openstack-reddwarf/src/main/java/org/jclouds/openstack/reddwarf/v1/features/UserApi.java @@ -0,0 +1,211 @@ +/* + * 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.openstack.reddwarf.v1.features; + +import java.util.Set; + +import javax.inject.Named; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.core.MediaType; + +import org.jclouds.Fallbacks.EmptyFluentIterableOnNotFoundOr404; +import org.jclouds.Fallbacks.FalseOnNotFoundOr404; +import org.jclouds.Fallbacks.NullOnNotFoundOr404; +import org.jclouds.javax.annotation.Nullable; +import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest; +import org.jclouds.openstack.reddwarf.v1.binders.BindCreateUserToJson; +import org.jclouds.openstack.reddwarf.v1.binders.BindGrantUserToJson; +import org.jclouds.openstack.reddwarf.v1.domain.Database; +import org.jclouds.openstack.reddwarf.v1.domain.User; +import org.jclouds.rest.annotations.Fallback; +import org.jclouds.rest.annotations.MapBinder; +import org.jclouds.rest.annotations.PayloadParam; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.SelectJson; +import org.jclouds.rest.annotations.SkipEncoding; + +import com.google.common.collect.FluentIterable; + +/** + * This API is for creating, listing, and deleting a User. Also allows listing, granting, and revoking access permissions for users. + * @see org.jclouds.openstack.reddwarf.v1.domain.User + * User + * + * @see api doc + * @see api + * src + * + * @author Zack Shoylev + */ +@SkipEncoding({'/', '='}) +@RequestFilters(AuthenticateRequest.class) +public interface UserApi { + + /** + * Create database users + * A user is granted all privileges on the specified databases. + * The following user name is reserved and cannot be used for creating users: root. + * + * @param instanceId The instance ID for the specified database instance. + * @param users List of users to be created + * @return true if successful + */ + @Named("user:create") + @POST + @Path("/instances/{instanceId}/users") + @Consumes(MediaType.APPLICATION_JSON) + @Fallback(FalseOnNotFoundOr404.class) + @MapBinder(BindCreateUserToJson.class) + boolean create(@PathParam("instanceId") String instanceId, @PayloadParam("users") Set users); + + /** + * Create a database user by name, password, and database name. Simpler overload for {@link #create(String, Set)} + * + * @param instanceId The instance ID for the specified database instance. + * @param userName Name of the user for the database. + * @param password User password for database access. + * @param databaseName Name of the database that the user can access. + * @return true if successful + */ + @Named("user:create") + @POST + @Path("/instances/{instanceId}/users") + @Consumes(MediaType.APPLICATION_JSON) + @Fallback(FalseOnNotFoundOr404.class) + @MapBinder(BindCreateUserToJson.class) + boolean create(@PathParam("instanceId") String instanceId, @PayloadParam("name") String userName, @PayloadParam("password") String password, @PayloadParam("databaseName") String databaseName); + + /** + * This operation grants access for the specified user to a database for the specified instance. + * The user is granted all privileges. + * + * @param instanceId The instance ID for the specified database instance. + * @param userName The name of the specified user. + * @param databases List of the databases that the user should be granted access to. + * @return true if successful + */ + @Named("user:grant") + @PUT + @Path("/instances/{instanceId}/users/{name}/databases") + @Consumes(MediaType.APPLICATION_JSON) + @Fallback(FalseOnNotFoundOr404.class) + @MapBinder(BindGrantUserToJson.class) + boolean grant(@PathParam("instanceId") String instanceId, @PathParam("name") String userName, @PayloadParam("databases") Set databases); + + /** + * This operation grants access for the specified user to a database for the specified instance. Simpler overload for {@link #create(String, Set)} + * The user is granted all privileges. + * + * @param instanceId The instance ID for the specified database instance. + * @param userName Name of the user for the database. + * @param databaseName Name of the database that the user can access. + * @return true if successful + */ + @Named("user:grant") + @PUT + @Path("/instances/{instanceId}/users/{name}/databases") + @Consumes(MediaType.APPLICATION_JSON) + @Fallback(FalseOnNotFoundOr404.class) + @MapBinder(BindGrantUserToJson.class) + boolean grant(@PathParam("instanceId") String instanceId, @PathParam("name") String userName, @PayloadParam("databaseName") String databaseName); + + /** + * This operation grants access for the specified user to a database for the specified instance. + * The user is granted all privileges. + * + * @param instanceId The instance ID for the specified database instance. + * @param userName Name of the user for the database. + * @param databaseName Name of the database that the user can access. + * @return true if successful + */ + @Named("user:revoke") + @DELETE + @Path("/instances/{instanceId}/users/{name}/databases/{databaseName}") + @Consumes(MediaType.APPLICATION_JSON) + @Fallback(FalseOnNotFoundOr404.class) + boolean revoke(@PathParam("instanceId") String instanceId, @PathParam("name") String userName, @PathParam("databaseName") String databaseName); + + /** + * This operation deletes the specified user for the specified database instance. + * + * @param instanceId The instance ID for the specified database instance. + * @param userName The name for the specified user. + * @return true if successful + */ + @Named("users:delete/{name}") + @DELETE + @Path("/instances/{instanceId}/users/{name}") + @Consumes(MediaType.APPLICATION_JSON) + @Fallback(FalseOnNotFoundOr404.class) + boolean delete(@PathParam("instanceId") String instanceId, @PathParam("name") String userName); + + /** + * This operation lists the users in the specified database instance. + * This operation does not return the system users (database administrators that administer the health of the database). Also, this operation returns the "root" user only if "root" user has been enabled. + * + * @param instanceId The instance ID for the specified database instance. + * @return The list of Users + */ + @Named("user:list/{instanceId}") + @GET + @Path("/instances/{instanceId}/users") + @SelectJson("users") + @Consumes(MediaType.APPLICATION_JSON) + @Fallback(EmptyFluentIterableOnNotFoundOr404.class) + FluentIterable list(@PathParam("instanceId") String instanceId); + + /** + * This operation shows a list of all databases a user has access to. + * + * @param instanceId The instance ID for the specified database instance. + * @param userName The name for the specified user. + * @return The list of Users + */ + @Named("user:getDatabaseList/{instanceId}/{name}") + @GET + @Path("/instances/{instanceId}/users/{name}/databases") + @SelectJson("databases") + @Consumes(MediaType.APPLICATION_JSON) + @Fallback(EmptyFluentIterableOnNotFoundOr404.class) + FluentIterable getDatabaseList(@PathParam("instanceId") String instanceId, @PathParam("name") String userName); + + /** + * Returns a User by name + * + * @param instanceId The instance ID for the specified database instance. + * @param userName The name for the specified user. + * @return User or Null on not found + */ + @Named("user:list/{instanceId}/{userName}") + @GET + @Path("/instances/{instanceId}/users/{name}") + @SelectJson("user") + @Consumes(MediaType.APPLICATION_JSON) + @Fallback(NullOnNotFoundOr404.class) + @Nullable + User get(@PathParam("instanceId") String instanceId, @PathParam("name") String userName); +} diff --git a/openstack-reddwarf/src/test/java/org/jclouds/openstack/reddwarf/v1/domain/UserTest.java b/openstack-reddwarf/src/test/java/org/jclouds/openstack/reddwarf/v1/domain/UserTest.java new file mode 100644 index 0000000..772288d --- /dev/null +++ b/openstack-reddwarf/src/test/java/org/jclouds/openstack/reddwarf/v1/domain/UserTest.java @@ -0,0 +1,49 @@ +/** + * 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.openstack.reddwarf.v1.domain; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import org.testng.annotations.Test; +import com.google.common.collect.ImmutableSet; + +@Test(groups = "unit", testName = "UserTest") +public class UserTest { + public void testUserForName() { + User user1 = forName("1"); + User user2 = forName("2"); + assertEquals(user1.getName(), "1"); + assertEquals(user2.getName(), "2"); + assertFalse(user1.equals(user2)); + } + + /** + * Creates a dummy User when you need an User with just the userName. + */ + public static User forName(String userName) { + return User.builder() + .name(userName) + .password("password") + .databases( + ImmutableSet.of( + Database.builder().name("db1").build(), + Database.builder().name("db2").build() + ) ).build(); + } +} diff --git a/openstack-reddwarf/src/test/java/org/jclouds/openstack/reddwarf/v1/features/InstanceApiLiveTest.java b/openstack-reddwarf/src/test/java/org/jclouds/openstack/reddwarf/v1/features/InstanceApiLiveTest.java index f585057..7f6898e 100644 --- a/openstack-reddwarf/src/test/java/org/jclouds/openstack/reddwarf/v1/features/InstanceApiLiveTest.java +++ b/openstack-reddwarf/src/test/java/org/jclouds/openstack/reddwarf/v1/features/InstanceApiLiveTest.java @@ -52,8 +52,8 @@ public void setup() { for (String zone : api.getConfiguredZones()) { List zoneList = Lists.newArrayList(); InstanceApi instanceApi = api.getInstanceApiForZone(zone); - zoneList.add(instanceApi.create("1", 1, "first")); - Instance second = instanceApi.create("1", 1, "second"); + zoneList.add(instanceApi.create("1", 1, "first_instance_testing")); + Instance second = instanceApi.create("1", 1, "second_instance_testing"); InstancePredicates.awaitAvailable(instanceApi).apply(second); instanceApi.enableRoot(second.getId()); zoneList.add(second); @@ -119,9 +119,14 @@ public void testGetInstanceWhenNotFound() { public void testGetRootStatus() { for (String zone : api.getConfiguredZones()) { InstanceApi instanceApi = api.getInstanceApiForZone(zone); - Iterator iterator = instanceApi.list().iterator(); - Instance first = iterator.next(); - Instance second = iterator.next(); + Iterator iterator = instanceApi.list().iterator(); + Instance first, second; + do{ + first = iterator.next(); + } while(!first.getName().contains("instance_testing")); + do{ + second = iterator.next(); + } while(!second.getName().contains("instance_testing")); assertTrue(instanceApi.isRooted(first.getId()) || instanceApi.isRooted(second.getId())); } } diff --git a/openstack-reddwarf/src/test/java/org/jclouds/openstack/reddwarf/v1/features/UserApiExpectTest.java b/openstack-reddwarf/src/test/java/org/jclouds/openstack/reddwarf/v1/features/UserApiExpectTest.java new file mode 100644 index 0000000..6e4db59 --- /dev/null +++ b/openstack-reddwarf/src/test/java/org/jclouds/openstack/reddwarf/v1/features/UserApiExpectTest.java @@ -0,0 +1,373 @@ +/** + * 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.openstack.reddwarf.v1.features; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.assertFalse; + +import java.net.URI; +import java.util.Set; + +import javax.ws.rs.core.MediaType; + +import org.jclouds.http.HttpResponse; +import org.jclouds.openstack.reddwarf.v1.domain.Database; +import org.jclouds.openstack.reddwarf.v1.domain.User; +import org.jclouds.openstack.reddwarf.v1.internal.BaseRedDwarfApiExpectTest; +import org.testng.annotations.Test; +import org.testng.internal.annotations.Sets; + +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.ImmutableSortedSet.Builder; + +/** + * Tests UserApi Guice wiring and parsing + * + * @author Zack Shoylev + */ +@Test(groups = "unit", testName = "UserApiExpectTest") +public class UserApiExpectTest extends BaseRedDwarfApiExpectTest { + + public void testCreateUserSimple() { + URI endpoint = URI.create("http://172.16.0.1:8776/v1/3456/instances/instanceId-1234-5678/users"); + UserApi api = requestsSendResponses( + keystoneAuthWithUsernameAndPasswordAndTenantName, + responseWithKeystoneAccess, + authenticatedGET().endpoint(endpoint) // bad naming convention, you should not be able to change the method to POST + .method("POST") + .payload(payloadFromResourceWithContentType("/user_create_simple_request.json", MediaType.APPLICATION_JSON)) + .build(), + HttpResponse.builder().statusCode(202).build() // response + ).getUserApiForZone("RegionOne"); + + boolean result = api.create("instanceId-1234-5678", "dbuser1", "password", "databaseA"); + assertTrue(result); + } + + public void testCreateUserSimpleFail() { + URI endpoint = URI.create("http://172.16.0.1:8776/v1/3456/instances/instanceId-1234-5678/users"); + UserApi api = requestsSendResponses( + keystoneAuthWithUsernameAndPasswordAndTenantName, + responseWithKeystoneAccess, + authenticatedGET().endpoint(endpoint) // bad naming convention, you should not be able to change the method to POST + .method("POST") + .payload(payloadFromResourceWithContentType("/user_create_simple_request.json", MediaType.APPLICATION_JSON)) + .build(), + HttpResponse.builder().statusCode(404).build() // response + ).getUserApiForZone("RegionOne"); + + boolean result = api.create("instanceId-1234-5678", "dbuser1", "password", "databaseA"); + assertFalse(result); + } + + public void testCreateUser() { + URI endpoint = URI.create("http://172.16.0.1:8776/v1/3456/instances/instanceId-1234-5678/users"); + UserApi api = requestsSendResponses( + keystoneAuthWithUsernameAndPasswordAndTenantName, + responseWithKeystoneAccess, + authenticatedGET().endpoint(endpoint) // bad naming convention, you should not be able to change the method to POST + .method("POST") + .payload(payloadFromResourceWithContentType("/user_create_request.json", MediaType.APPLICATION_JSON)) + .build(), + HttpResponse.builder().statusCode(202).build() // response + ).getUserApiForZone("RegionOne"); + + Set databases1 = Sets.newHashSet(); + databases1.add( Database.builder().name("databaseA").build() ); + Builder databases2builder = ImmutableSortedSet.naturalOrder(); + databases2builder.add( Database.builder().name("databaseB").build() ); + databases2builder.add( Database.builder().name("databaseC").build() ); + Set databases2 = databases2builder.build(); + Set databases3 = Sets.newHashSet(); + databases3.add( Database.builder().name("databaseD").build() ); + User user1 = User.builder().databases( databases1 ).name("dbuser1").password("password").build(); + User user2 = User.builder().databases( databases2 ).name("dbuser2").password("password").build(); + User user3 = User.builder().databases( databases3 ).name("dbuser3").password("password").build(); + Set users = Sets.newHashSet(); + users.add(user1); + users.add(user2); + users.add(user3); + + boolean result = api.create("instanceId-1234-5678", ImmutableSortedSet.naturalOrder().addAll(users).build()); + assertTrue(result); + } + + public void testCreateUserFail() { + URI endpoint = URI.create("http://172.16.0.1:8776/v1/3456/instances/instanceId-1234-5678/users"); + UserApi api = requestsSendResponses( + keystoneAuthWithUsernameAndPasswordAndTenantName, + responseWithKeystoneAccess, + authenticatedGET().endpoint(endpoint) // bad naming convention, you should not be able to change the method to POST + .method("POST") + .payload(payloadFromResourceWithContentType("/user_create_request.json", MediaType.APPLICATION_JSON)) + .build(), + HttpResponse.builder().statusCode(404).build() // response + ).getUserApiForZone("RegionOne"); + + Set databases1 = Sets.newHashSet(); + databases1.add( Database.builder().name("databaseA").build() ); + Builder databases2builder = ImmutableSortedSet.naturalOrder(); + databases2builder.add( Database.builder().name("databaseB").build() ); + databases2builder.add( Database.builder().name("databaseC").build() ); + Set databases2 = databases2builder.build(); + Set databases3 = Sets.newHashSet(); + databases3.add( Database.builder().name("databaseD").build() ); + User user1 = User.builder().databases( databases1 ).name("dbuser1").password("password").build(); + User user2 = User.builder().databases( databases2 ).name("dbuser2").password("password").build(); + User user3 = User.builder().databases( databases3 ).name("dbuser3").password("password").build(); + Set users = Sets.newHashSet(); + users.add(user1); + users.add(user2); + users.add(user3); + + boolean result = api.create("instanceId-1234-5678", ImmutableSortedSet.naturalOrder().addAll(users).build()); + assertFalse(result); + } + + public void testGrantUserSimple() { + URI endpoint = URI.create("http://172.16.0.1:8776/v1/3456/instances/instanceId-1234-5678/users/dbuser1/databases"); + UserApi api = requestsSendResponses( + keystoneAuthWithUsernameAndPasswordAndTenantName, + responseWithKeystoneAccess, + authenticatedGET().endpoint(endpoint) // bad naming convention, you should not be able to change the method to POST + .method("PUT") + .payload(payloadFromResourceWithContentType("/user_grant_simple_request.json", MediaType.APPLICATION_JSON)) + .build(), + HttpResponse.builder().statusCode(202).build() // response + ).getUserApiForZone("RegionOne"); + + boolean result = api.grant("instanceId-1234-5678", "dbuser1", "databaseZ"); + assertTrue(result); + } + + public void testGrantUserSimpleFail() { + URI endpoint = URI.create("http://172.16.0.1:8776/v1/3456/instances/instanceId-1234-5678/users/dbuser1/databases"); + UserApi api = requestsSendResponses( + keystoneAuthWithUsernameAndPasswordAndTenantName, + responseWithKeystoneAccess, + authenticatedGET().endpoint(endpoint) // bad naming convention, you should not be able to change the method to POST + .method("PUT") + .payload(payloadFromResourceWithContentType("/user_grant_simple_request.json", MediaType.APPLICATION_JSON)) + .build(), + HttpResponse.builder().statusCode(404).build() // response + ).getUserApiForZone("RegionOne"); + + boolean result = api.grant("instanceId-1234-5678", "dbuser1", "databaseZ"); + assertFalse(result); + } + + public void testGrantUser() { + URI endpoint = URI.create("http://172.16.0.1:8776/v1/3456/instances/instanceId-1234-5678/users/dbuser1/databases"); + UserApi api = requestsSendResponses( + keystoneAuthWithUsernameAndPasswordAndTenantName, + responseWithKeystoneAccess, + authenticatedGET().endpoint(endpoint) // bad naming convention, you should not be able to change the method to POST + .method("PUT") + .payload(payloadFromResourceWithContentType("/user_grant_request.json", MediaType.APPLICATION_JSON)) + .build(), + HttpResponse.builder().statusCode(202).build() // response + ).getUserApiForZone("RegionOne"); + + Builder databasesBuilder = ImmutableSortedSet.naturalOrder(); + databasesBuilder.add( Database.builder().name("databaseC").build() ); + databasesBuilder.add( Database.builder().name("databaseD").build() ); + Set databases = databasesBuilder.build(); + + boolean result = api.grant("instanceId-1234-5678", "dbuser1", databases); + assertTrue(result); + } + + public void testGrantUserFail() { + URI endpoint = URI.create("http://172.16.0.1:8776/v1/3456/instances/instanceId-1234-5678/users/dbuser1/databases"); + UserApi api = requestsSendResponses( + keystoneAuthWithUsernameAndPasswordAndTenantName, + responseWithKeystoneAccess, + authenticatedGET().endpoint(endpoint) // bad naming convention, you should not be able to change the method to POST + .method("PUT") + .payload(payloadFromResourceWithContentType("/user_grant_request.json", MediaType.APPLICATION_JSON)) + .build(), + HttpResponse.builder().statusCode(404).build() // response + ).getUserApiForZone("RegionOne"); + + Builder databasesBuilder = ImmutableSortedSet.naturalOrder(); + databasesBuilder.add( Database.builder().name("databaseC").build() ); + databasesBuilder.add( Database.builder().name("databaseD").build() ); + Set databases = databasesBuilder.build(); + + boolean result = api.grant("instanceId-1234-5678", "dbuser1", databases); + assertFalse(result); + } + + public void testRevokeUser() { + URI endpoint = URI.create("http://172.16.0.1:8776/v1/3456/instances/instanceId-1234-5678/users/dbuser1/databases/databaseA"); + UserApi api = requestsSendResponses( + keystoneAuthWithUsernameAndPasswordAndTenantName, + responseWithKeystoneAccess, + authenticatedGET().endpoint(endpoint) // bad naming convention, you should not be able to change the method to POST + .method("DELETE") + .build(), + HttpResponse.builder().statusCode(202).build() // response + ).getUserApiForZone("RegionOne"); + + Set databases = Sets.newHashSet(); + databases.add( Database.builder().name("databaseC").build() ); + databases.add( Database.builder().name("databaseD").build() ); + boolean result = api.revoke("instanceId-1234-5678", "dbuser1", "databaseA"); + assertTrue(result); + } + + public void testRevokeUserFail() { + URI endpoint = URI.create("http://172.16.0.1:8776/v1/3456/instances/instanceId-1234-5678/users/dbuser1/databases/databaseA"); + UserApi api = requestsSendResponses( + keystoneAuthWithUsernameAndPasswordAndTenantName, + responseWithKeystoneAccess, + authenticatedGET().endpoint(endpoint) // bad naming convention, you should not be able to change the method to POST + .method("DELETE") + .build(), + HttpResponse.builder().statusCode(404).build() // response + ).getUserApiForZone("RegionOne"); + + Set databases = Sets.newHashSet(); + databases.add( Database.builder().name("databaseC").build() ); + databases.add( Database.builder().name("databaseD").build() ); + boolean result = api.revoke("instanceId-1234-5678", "dbuser1", "databaseA"); + assertFalse(result); + } + + public void testDeleteUser() { + URI endpoint = URI.create("http://172.16.0.1:8776/v1/3456/instances/instanceId-1234-5678/users/dbuser1"); + UserApi api = requestsSendResponses( + keystoneAuthWithUsernameAndPasswordAndTenantName, + responseWithKeystoneAccess, + authenticatedGET().endpoint(endpoint) // bad naming convention, you should not be able to change the method to POST + .method("DELETE") + .build(), + HttpResponse.builder().statusCode(202).build() // response + ).getUserApiForZone("RegionOne"); + + Set databases = Sets.newHashSet(); + databases.add( Database.builder().name("databaseC").build() ); + databases.add( Database.builder().name("databaseD").build() ); + boolean result = api.delete("instanceId-1234-5678", "dbuser1"); + assertTrue(result); + } + + public void testDeleteUserFail() { + URI endpoint = URI.create("http://172.16.0.1:8776/v1/3456/instances/instanceId-1234-5678/users/dbuser1"); + UserApi api = requestsSendResponses( + keystoneAuthWithUsernameAndPasswordAndTenantName, + responseWithKeystoneAccess, + authenticatedGET().endpoint(endpoint) // bad naming convention, you should not be able to change the method to POST + .method("DELETE") + .build(), + HttpResponse.builder().statusCode(404).build() // response + ).getUserApiForZone("RegionOne"); + + Set databases = Sets.newHashSet(); + databases.add( Database.builder().name("databaseC").build() ); + databases.add( Database.builder().name("databaseD").build() ); + boolean result = api.delete("instanceId-1234-5678", "dbuser1"); + assertFalse(result); + } + + public void testListUsers() { + URI endpoint = URI.create("http://172.16.0.1:8776/v1/3456/instances/instanceId-1234-5678/users"); + UserApi api = requestsSendResponses( + keystoneAuthWithUsernameAndPasswordAndTenantName, + responseWithKeystoneAccess, + authenticatedGET().endpoint(endpoint).build(), + HttpResponse.builder().statusCode(200).payload(payloadFromResource("/reddwarf_user_list.json")).build() + ).getUserApiForZone("RegionOne"); + + Set users = api.list("instanceId-1234-5678").toSet(); + assertEquals(users.size(), 4); + assertEquals(users.iterator().next().getDatabases().size(), 0); + assertEquals(users.iterator().next().getName(), "dbuser1"); + } + + public void testListUsersFail() { + URI endpoint = URI.create("http://172.16.0.1:8776/v1/3456/instances/instanceId-1234-5678/users"); + UserApi api = requestsSendResponses( + keystoneAuthWithUsernameAndPasswordAndTenantName, + responseWithKeystoneAccess, + authenticatedGET().endpoint(endpoint).build(), + HttpResponse.builder().statusCode(404).payload(payloadFromResource("/reddwarf_user_list.json")).build() + ).getUserApiForZone("RegionOne"); + + Set users = api.list("instanceId-1234-5678").toSet(); + assertEquals(users.size(), 0); + } + + public void testUserGetDatabaseList() { + URI endpoint = URI.create("http://172.16.0.1:8776/v1/3456/instances/instanceId-1234-5678/users/dbuser1/databases"); + UserApi api = requestsSendResponses( + keystoneAuthWithUsernameAndPasswordAndTenantName, + responseWithKeystoneAccess, + authenticatedGET().endpoint(endpoint).build(), + HttpResponse.builder().statusCode(200).payload(payloadFromResource("/user_list_access.json")).build() + ).getUserApiForZone("RegionOne"); + + Set databases = api.getDatabaseList("instanceId-1234-5678", "dbuser1").toSet(); + assertEquals(databases.size(), 2); + assertEquals(databases.iterator().next().getName(), "databaseA"); + } + + public void testUserGetDatabaseListFail() { + URI endpoint = URI.create("http://172.16.0.1:8776/v1/3456/instances/instanceId-1234-5678/users/dbuser1/databases"); + UserApi api = requestsSendResponses( + keystoneAuthWithUsernameAndPasswordAndTenantName, + responseWithKeystoneAccess, + authenticatedGET().endpoint(endpoint).build(), + HttpResponse.builder().statusCode(404).payload(payloadFromResource("/user_list_access.json")).build() + ).getUserApiForZone("RegionOne"); + + Set databases = api.getDatabaseList("instanceId-1234-5678", "dbuser1").toSet(); + assertEquals(databases.size(), 0); + } + + public void testGetUser() { + URI endpoint = URI.create("http://172.16.0.1:8776/v1/3456/instances/instanceId-1234-5678/users/exampleuser"); + UserApi api = requestsSendResponses( + keystoneAuthWithUsernameAndPasswordAndTenantName, + responseWithKeystoneAccess, + authenticatedGET().endpoint(endpoint).build(), + HttpResponse.builder().statusCode(200).payload(payloadFromResource("/user_get.json")).build() + ).getUserApiForZone("RegionOne"); + + User user = api.get("instanceId-1234-5678", "exampleuser"); + assertEquals(user.getName(), "exampleuser"); + assertEquals(user.getDatabases().size(), 2); + assertEquals(user.getDatabases().iterator().next().getName(), "databaseA"); + } + + public void testGetUserFail() { + URI endpoint = URI.create("http://172.16.0.1:8776/v1/3456/instances/instanceId-1234-5678/users/exampleuser"); + UserApi api = requestsSendResponses( + keystoneAuthWithUsernameAndPasswordAndTenantName, + responseWithKeystoneAccess, + authenticatedGET().endpoint(endpoint).build(), + HttpResponse.builder().statusCode(404).payload(payloadFromResource("/user_get.json")).build() + ).getUserApiForZone("RegionOne"); + + User user = api.get("instanceId-1234-5678", "exampleuser"); + assertNull(user); + } +} diff --git a/openstack-reddwarf/src/test/java/org/jclouds/openstack/reddwarf/v1/features/UserApiLiveTest.java b/openstack-reddwarf/src/test/java/org/jclouds/openstack/reddwarf/v1/features/UserApiLiveTest.java new file mode 100644 index 0000000..578e3e3 --- /dev/null +++ b/openstack-reddwarf/src/test/java/org/jclouds/openstack/reddwarf/v1/features/UserApiLiveTest.java @@ -0,0 +1,205 @@ +/** + * 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.openstack.reddwarf.v1.features; + +import static com.google.common.base.Preconditions.checkArgument; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertTrue; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +import org.jclouds.openstack.reddwarf.v1.domain.Database; +import org.jclouds.openstack.reddwarf.v1.domain.Instance; +import org.jclouds.openstack.reddwarf.v1.domain.User; +import org.jclouds.openstack.reddwarf.v1.internal.BaseRedDwarfApiLiveTest; +import org.jclouds.openstack.reddwarf.v1.predicates.InstancePredicates; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + +/** + * @author Zack Shoylev + */ +@Test(groups = "live", testName = "UserApiLiveTest") +public class UserApiLiveTest extends BaseRedDwarfApiLiveTest { + + // zone to instance + private static Map> instancesToDelete = Maps.newHashMap(); + // not deleting users. they will be deleted when instances are deleted + + @Override + @BeforeClass(groups = { "integration", "live" }) + public void setup() { + super.setup(); + for (String zone : api.getConfiguredZones()) { + // create instances + List instanceList = Lists.newArrayList(); + InstanceApi instanceApi = api.getInstanceApiForZone(zone); + Instance first = instanceApi.create("1", 1, "first_user_testing"); + Instance second = instanceApi.create("1", 1, "second_user_testing"); + instanceList.add(first); + instanceList.add(second); + InstancePredicates.awaitAvailable(instanceApi).apply(first); + InstancePredicates.awaitAvailable(instanceApi).apply(second); + instancesToDelete.put(zone, instanceList); + // create users + User user1 = User.builder() + .name("user1") + .password(UUID.randomUUID().toString()) + .databases(ImmutableSet.of( + Database.builder().name("u1db1").build(), + Database.builder().name("u1db1").build())).build(); + User user2 = User.builder() + .name("user2") + .password(UUID.randomUUID().toString()) + .databases(ImmutableSet.of( + Database.builder().name("u2db1").build(), + Database.builder().name("u2db1").build())).build(); + User user3 = User.builder() + .name("user3") + .password(UUID.randomUUID().toString()) + .databases(ImmutableSet.of( + Database.builder().name("u3db1").build(), + Database.builder().name("u3db1").build())).build(); + UserApi userApi = api.getUserApiForZone(zone); + userApi.create(first.getId(), ImmutableSet.of(user1, user2)); + userApi.create(second.getId(), ImmutableSet.of(user3)); + } + } + + @Override + @AfterClass(groups = { "integration", "live" }) + public void tearDown(){ + for (String zone : api.getConfiguredZones()) { + InstanceApi instanceApi = api.getInstanceApiForZone(zone); + for(Instance instance : instancesToDelete.get(zone)){ + if( !instanceApi.delete(instance.getId() ) ) + throw new RuntimeException("Could not delete a database instance after tests!"); + } + } + super.tearDown(); + } + + private void checkUser(User user) { + assertNotNull(user.getName(), "Name cannot be null for " + user); + checkArgument(user.getDatabases().size() > 0, "Number of databases must not be 0"); + } + + @Test + public void testListUsers() { + for (String zone : api.getConfiguredZones()) { + InstanceApi instanceApi = api.getInstanceApiForZone(zone); + UserApi userApi = api.getUserApiForZone(zone); + assertTrue(instanceApi.list().size() >= 2); + for(Instance instance : instanceApi.list() ) { + if(!instance.getName().contains("user_testing"))continue; + assertTrue(userApi.list(instance.getId()).size() >=1); + for(User user : userApi.list(instance.getId())){ + checkUser(user); + } + } + } + } + + @Test + public void testGetUser() { + for (String zone : api.getConfiguredZones()) { + InstanceApi instanceApi = api.getInstanceApiForZone(zone); + UserApi userApi = api.getUserApiForZone(zone); + assertTrue(instanceApi.list().size() >= 2); + for(Instance instance : instanceApi.list() ) { + if(!instance.getName().contains("user_testing"))continue; + assertTrue(userApi.list(instance.getId()).size() >=1); + for(User user : userApi.list(instance.getId())){ + User userFromGet = userApi.get(instance.getId(), user.getName()); + assertEquals(userFromGet.getName(), user.getName()); + assertEquals(userFromGet.getDatabases(), user.getDatabases()); + } + } + } + } + + @Test + public void testGetDatabaseListForUser() { + for (String zone : api.getConfiguredZones()) { + InstanceApi instanceApi = api.getInstanceApiForZone(zone); + UserApi userApi = api.getUserApiForZone(zone); + assertTrue(instanceApi.list().size() >= 2 ); + for(Instance instance : instanceApi.list() ) { + if(!instance.getName().contains("user_testing"))continue; + assertTrue(userApi.list(instance.getId()).size() >=1); + for(User user : userApi.list(instance.getId())){ + assertTrue(userApi.getDatabaseList(instance.getId(), user.getName()).size()>0); + } + } + } + } + + @Test + public void testGrantAndRevokeAcccessForUser() { + for (String zone : api.getConfiguredZones()) { + InstanceApi instanceApi = api.getInstanceApiForZone(zone); + UserApi userApi = api.getUserApiForZone(zone); + assertTrue(instanceApi.list().size() >= 2); + for(Instance instance : instanceApi.list() ) { + if(!instance.getName().contains("user_testing"))continue; + assertTrue(userApi.list(instance.getId()).size() >=1); + for(User user : userApi.list(instance.getId())){ + userApi.grant(instance.getId(), user.getName(), "dbA"); + userApi.grant(instance.getId(), user.getName(), ImmutableSet.of( + Database.builder().name("dbB").build(), + Database.builder().name("dbC").build())); + + Set databases = userApi.getDatabaseList(instance.getId(), user.getName()).toSet(); + assertTrue(databases.contains(Database.builder().name("dbA").build())); + assertTrue(databases.contains(Database.builder().name("dbB").build())); + assertTrue(databases.contains(Database.builder().name("dbC").build())); + + userApi.revoke(instance.getId(), user.getName(), "dbA"); + userApi.revoke(instance.getId(), user.getName(), "dbB"); + userApi.revoke(instance.getId(), user.getName(), "dbC"); + + databases = userApi.getDatabaseList(instance.getId(), user.getName()).toSet(); + assertFalse(databases.contains(Database.builder().name("dbA").build())); + assertFalse(databases.contains(Database.builder().name("dbB").build())); + assertFalse(databases.contains(Database.builder().name("dbC").build())); + } + } + } + } + + @Test + public void testGetUserWhenNotFound() { + for (String zone : api.getConfiguredZones()) { + UserApi userApi = api.getUserApiForZone(zone); + assertNull(userApi.get(api.getInstanceApiForZone(zone).list().iterator().next().getId(), "9999")); + } + } +} diff --git a/openstack-reddwarf/src/test/java/org/jclouds/openstack/reddwarf/v1/parse/ParseUserListTest.java b/openstack-reddwarf/src/test/java/org/jclouds/openstack/reddwarf/v1/parse/ParseUserListTest.java new file mode 100644 index 0000000..a4f26ff --- /dev/null +++ b/openstack-reddwarf/src/test/java/org/jclouds/openstack/reddwarf/v1/parse/ParseUserListTest.java @@ -0,0 +1,67 @@ +/** + * 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.openstack.reddwarf.v1.parse; + +import java.util.Set; +import javax.ws.rs.Consumes; +import javax.ws.rs.core.MediaType; +import org.jclouds.json.BaseSetParserTest; +import org.jclouds.openstack.reddwarf.v1.domain.Database; +import org.jclouds.openstack.reddwarf.v1.domain.User; +import org.jclouds.rest.annotations.SelectJson; +import org.testng.annotations.Test; +import com.google.common.collect.ImmutableSet; + +/** + * + * @author Zack Shoylev + */ + +@Test(groups = "unit", testName = "ParseUserTest") +public class ParseUserListTest extends BaseSetParserTest { + + @Override + public String resource() { + return "/reddwarf_user_list.json"; + } + + /* + * The user needs to be comparable for this test to work + * */ + @Override + @Consumes(MediaType.APPLICATION_JSON) + @SelectJson("users") + public Set expected() { + return ImmutableSet + .of(User.builder() + .name("dbuser1") + .build(), + User.builder() + .name("dbuser2") + .databases( ImmutableSet.of( + Database.builder().name("databaseB").build(), + Database.builder().name("databaseC").build()) ) + .build(), + User.builder().name("dbuser3").build(), + User.builder().name("demouser").databases( + ImmutableSet.of(Database.builder().name("sampledb").build())) + .build() + ); + } +} diff --git a/openstack-reddwarf/src/test/resources/reddwarf_user_list.json b/openstack-reddwarf/src/test/resources/reddwarf_user_list.json new file mode 100644 index 0000000..55afb56 --- /dev/null +++ b/openstack-reddwarf/src/test/resources/reddwarf_user_list.json @@ -0,0 +1,31 @@ +{ + "users": [ + { + "databases": [], + "name": "dbuser1" + }, + { + "databases": [ + { + "name": "databaseB" + }, + { + "name": "databaseC" + } + ], + "name": "dbuser2" + }, + { + "databases": [], + "name": "dbuser3" + }, + { + "databases": [ + { + "name": "sampledb" + } + ], + "name": "demouser" + } + ] +} diff --git a/openstack-reddwarf/src/test/resources/user_create_request.json b/openstack-reddwarf/src/test/resources/user_create_request.json new file mode 100644 index 0000000..7742898 --- /dev/null +++ b/openstack-reddwarf/src/test/resources/user_create_request.json @@ -0,0 +1,34 @@ +{ + "users":[ + { + "databases":[ + { + "name":"databaseA" + } + ], + "name":"dbuser1", + "password":"password" + }, + { + "databases":[ + { + "name":"databaseB" + }, + { + "name":"databaseC" + } + ], + "name":"dbuser2", + "password":"password" + }, + { + "databases":[ + { + "name":"databaseD" + } + ], + "name":"dbuser3", + "password":"password" + } + ] +} diff --git a/openstack-reddwarf/src/test/resources/user_create_simple_request.json b/openstack-reddwarf/src/test/resources/user_create_simple_request.json new file mode 100644 index 0000000..921f68e --- /dev/null +++ b/openstack-reddwarf/src/test/resources/user_create_simple_request.json @@ -0,0 +1,13 @@ +{ + "users":[ + { + "databases":[ + { + "name":"databaseA" + } + ], + "name":"dbuser1", + "password":"password" + } + ] +} diff --git a/openstack-reddwarf/src/test/resources/user_get.json b/openstack-reddwarf/src/test/resources/user_get.json new file mode 100644 index 0000000..8d4169c --- /dev/null +++ b/openstack-reddwarf/src/test/resources/user_get.json @@ -0,0 +1,13 @@ +{ + "user": { + "name": "exampleuser", + "databases": [ + { + "name": "databaseA" + }, + { + "name": "databaseB" + } + ] + } +} diff --git a/openstack-reddwarf/src/test/resources/user_grant_request.json b/openstack-reddwarf/src/test/resources/user_grant_request.json new file mode 100644 index 0000000..97a1239 --- /dev/null +++ b/openstack-reddwarf/src/test/resources/user_grant_request.json @@ -0,0 +1,10 @@ +{ + "databases": [ + { + "name": "databaseC" + }, + { + "name": "databaseD" + } + ] +} diff --git a/openstack-reddwarf/src/test/resources/user_grant_simple_request.json b/openstack-reddwarf/src/test/resources/user_grant_simple_request.json new file mode 100644 index 0000000..5113e4f --- /dev/null +++ b/openstack-reddwarf/src/test/resources/user_grant_simple_request.json @@ -0,0 +1,7 @@ +{ + "databases": [ + { + "name": "databaseZ" + } + ] +} diff --git a/openstack-reddwarf/src/test/resources/user_list_access.json b/openstack-reddwarf/src/test/resources/user_list_access.json new file mode 100644 index 0000000..c58e1fa --- /dev/null +++ b/openstack-reddwarf/src/test/resources/user_list_access.json @@ -0,0 +1,10 @@ +{ + "databases": [ + { + "name": "databaseA" + }, + { + "name": "databaseB" + } + ] +} diff --git a/openstack-reddwarf/src/test/resources/user_password_request.json b/openstack-reddwarf/src/test/resources/user_password_request.json new file mode 100644 index 0000000..e42b277 --- /dev/null +++ b/openstack-reddwarf/src/test/resources/user_password_request.json @@ -0,0 +1,12 @@ +{ + "users": [ + { + "name": "dbuser1", + "password": "newpassword" + }, + { + "name": "dbuser2", + "password": "anotherpassword" + } + ] +}