Merge pull request #232 from andreisavu/domain-user-account

Implement account & user management (global & domain API)
This commit is contained in:
Adrian Cole 2011-12-12 14:46:05 -08:00
commit 53b64e6c19
35 changed files with 1793 additions and 21 deletions

View File

@ -20,6 +20,7 @@ package org.jclouds.cloudstack;
import org.jclouds.cloudstack.features.DomainAccountAsyncClient;
import org.jclouds.cloudstack.features.DomainLimitAsyncClient;
import org.jclouds.cloudstack.features.DomainUserAsyncClient;
import org.jclouds.rest.annotations.Delegate;
/**
@ -48,4 +49,10 @@ public interface CloudStackDomainAsyncClient extends CloudStackAsyncClient {
@Override
DomainAccountAsyncClient getAccountClient();
/**
* Provides asynchronous access to Users
*/
@Delegate
DomainUserAsyncClient getUserClient();
}

View File

@ -22,6 +22,7 @@ import java.util.concurrent.TimeUnit;
import org.jclouds.cloudstack.features.DomainAccountClient;
import org.jclouds.cloudstack.features.DomainLimitClient;
import org.jclouds.cloudstack.features.DomainUserClient;
import org.jclouds.concurrent.Timeout;
import org.jclouds.rest.annotations.Delegate;
@ -51,4 +52,10 @@ public interface CloudStackDomainClient extends CloudStackClient {
@Delegate
@Override
DomainAccountClient getAccountClient();
/**
* Provides synchronous access to Users
*/
@Delegate
DomainUserClient getUserClient();
}

View File

@ -23,6 +23,7 @@ import org.jclouds.cloudstack.features.GlobalAlertAsyncClient;
import org.jclouds.cloudstack.features.GlobalCapacityAsyncClient;
import org.jclouds.cloudstack.features.GlobalHostAsyncClient;
import org.jclouds.cloudstack.features.GlobalOfferingAsyncClient;
import org.jclouds.cloudstack.features.GlobalUserAsyncClient;
import org.jclouds.rest.annotations.Delegate;
/**
@ -44,6 +45,13 @@ public interface CloudStackGlobalAsyncClient extends CloudStackDomainAsyncClient
@Override
GlobalAccountAsyncClient getAccountClient();
/**
* Provides asynchronous access to Users
*/
@Delegate
@Override
GlobalUserAsyncClient getUserClient();
/**
* Provides asynchronous access to Alerts
*/

View File

@ -25,6 +25,7 @@ import org.jclouds.cloudstack.features.GlobalAlertClient;
import org.jclouds.cloudstack.features.GlobalCapacityClient;
import org.jclouds.cloudstack.features.GlobalHostClient;
import org.jclouds.cloudstack.features.GlobalOfferingClient;
import org.jclouds.cloudstack.features.GlobalUserClient;
import org.jclouds.concurrent.Timeout;
import org.jclouds.rest.annotations.Delegate;
@ -48,6 +49,13 @@ public interface CloudStackGlobalClient extends CloudStackDomainClient {
@Override
GlobalAccountClient getAccountClient();
/**
* Provides synchronous access to Users
*/
@Delegate
@Override
GlobalUserClient getUserClient();
/**
* Provides synchronous access to Alerts
*/

View File

@ -36,6 +36,7 @@ public class CloudStackPropertiesBuilder extends PropertiesBuilder {
properties.setProperty(PROPERTY_API_VERSION, "2.2");
properties.setProperty("jclouds.ssh.max-retries", "7");
properties.setProperty("jclouds.ssh.retry-auth", "true");
properties.setProperty("jclouds.cloudstack.integration-api-port", "8096");
return properties;
}

View File

@ -0,0 +1,38 @@
/**
* 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.cloudstack.collections;
import javax.inject.Qualifier;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Change the endpoint as needed for the integration API
*
* @author Andrei Savu
*
*/
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = { ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
@Qualifier
public @interface Integration {
}

View File

@ -19,13 +19,17 @@
package org.jclouds.cloudstack.config;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Provides;
import com.google.inject.Singleton;
import com.google.inject.TypeLiteral;
import com.google.inject.name.Named;
import org.jclouds.cloudstack.CloudStackAsyncClient;
import org.jclouds.cloudstack.CloudStackClient;
import org.jclouds.cloudstack.CloudStackDomainAsyncClient;
import org.jclouds.cloudstack.CloudStackDomainClient;
import org.jclouds.cloudstack.CloudStackGlobalAsyncClient;
import org.jclouds.cloudstack.CloudStackGlobalClient;
import org.jclouds.cloudstack.collections.Integration;
import org.jclouds.cloudstack.features.AccountAsyncClient;
import org.jclouds.cloudstack.features.AccountClient;
import org.jclouds.cloudstack.features.AddressAsyncClient;
@ -38,6 +42,8 @@ import org.jclouds.cloudstack.features.DomainAccountAsyncClient;
import org.jclouds.cloudstack.features.DomainAccountClient;
import org.jclouds.cloudstack.features.DomainLimitAsyncClient;
import org.jclouds.cloudstack.features.DomainLimitClient;
import org.jclouds.cloudstack.features.DomainUserAsyncClient;
import org.jclouds.cloudstack.features.DomainUserClient;
import org.jclouds.cloudstack.features.EventAsyncClient;
import org.jclouds.cloudstack.features.EventClient;
import org.jclouds.cloudstack.features.FirewallAsyncClient;
@ -52,6 +58,8 @@ import org.jclouds.cloudstack.features.GlobalHostAsyncClient;
import org.jclouds.cloudstack.features.GlobalHostClient;
import org.jclouds.cloudstack.features.GlobalOfferingAsyncClient;
import org.jclouds.cloudstack.features.GlobalOfferingClient;
import org.jclouds.cloudstack.features.GlobalUserAsyncClient;
import org.jclouds.cloudstack.features.GlobalUserClient;
import org.jclouds.cloudstack.features.GuestOSAsyncClient;
import org.jclouds.cloudstack.features.GuestOSClient;
import org.jclouds.cloudstack.features.HypervisorAsyncClient;
@ -92,12 +100,15 @@ import org.jclouds.http.annotation.Redirection;
import org.jclouds.http.annotation.ServerError;
import org.jclouds.json.config.GsonModule.DateAdapter;
import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
import org.jclouds.location.Provider;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.RestContext;
import org.jclouds.rest.config.BinderUtils;
import org.jclouds.rest.config.RestClientModule;
import org.jclouds.rest.internal.RestContextImpl;
import javax.ws.rs.core.UriBuilder;
import java.net.URI;
import java.util.Map;
/**
@ -126,7 +137,9 @@ public class CloudStackRestClientModule extends RestClientModule<CloudStackClien
.put(ConfigurationClient.class, ConfigurationAsyncClient.class)//
.put(AccountClient.class, AccountAsyncClient.class)//
.put(DomainAccountClient.class, DomainAccountAsyncClient.class)//
.put(DomainUserClient.class, DomainUserAsyncClient.class)//
.put(GlobalAccountClient.class, GlobalAccountAsyncClient.class)//
.put(GlobalUserClient.class, GlobalUserAsyncClient.class)//
.put(EventClient.class, EventAsyncClient.class)//
.put(LimitClient.class, LimitAsyncClient.class)//
.put(DomainLimitClient.class, DomainLimitAsyncClient.class)//
@ -185,4 +198,12 @@ public class CloudStackRestClientModule extends RestClientModule<CloudStackClien
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(CloudStackErrorHandler.class);
}
@Singleton
@Provides
@Integration
protected URI providesIntegrationEndpoint(@Provider URI normal,
@Named("jclouds.cloudstack.integration-api-port") int port,
com.google.inject.Provider<UriBuilder> uriBuilder) {
return uriBuilder.get().uri(normal).port(port).build();
}
}

View File

@ -273,7 +273,7 @@ public class Account extends ForwardingSet<User> implements Comparable<Account>
@Override
public String toString() {
return name();
return "" + code;
}
public static Type fromValue(String type) {

View File

@ -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.cloudstack.domain;
import com.google.gson.annotations.SerializedName;
/**
* Representation of the API keypair response
*
* @author Andrei Savu
*/
public class ApiKeyPair implements Comparable<ApiKeyPair> {
public static Builder builder() {
return new Builder();
}
public static class Builder {
private String apiKey;
private String secretKey;
public Builder apiKey(String apiKey) {
this.apiKey = apiKey;
return this;
}
public Builder secretKey(String secretKey) {
this.secretKey = secretKey;
return this;
}
public ApiKeyPair build() {
return new ApiKeyPair(apiKey, secretKey);
}
}
// for deserialization
ApiKeyPair() {
}
@SerializedName("apikey")
private String apiKey;
@SerializedName("secretkey")
private String secretKey;
public ApiKeyPair(String apiKey, String secretKey) {
this.apiKey = apiKey;
this.secretKey = secretKey;
}
public String getSecretKey() {
return secretKey;
}
public String getApiKey() {
return apiKey;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ApiKeyPair that = (ApiKeyPair) o;
if (apiKey != null ? !apiKey.equals(that.apiKey) : that.apiKey != null)
return false;
if (secretKey != null ? !secretKey.equals(that.secretKey) : that.secretKey != null)
return false;
return true;
}
@Override
public int hashCode() {
int result = apiKey != null ? apiKey.hashCode() : 0;
result = 31 * result + (secretKey != null ? secretKey.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "ApiKeyPair{" +
"apiKey='" + apiKey + '\'' +
", secretKey='" + secretKey + '\'' +
'}';
}
@Override
public int compareTo(ApiKeyPair arg0) {
return apiKey.compareTo(arg0.getApiKey());
}
}

View File

@ -30,6 +30,25 @@ import com.google.gson.annotations.SerializedName;
*/
public class User implements Comparable<User> {
public static enum State {
ENABLED,
DISABLED,
UNKNOWN;
public static State fromValue(String value) {
try {
return valueOf(value.toUpperCase());
} catch(IllegalArgumentException e) {
return UNKNOWN;
}
}
@Override
public String toString() {
return name().toLowerCase();
}
}
public static Builder builder() {
return new Builder();
}
@ -41,7 +60,7 @@ public class User implements Comparable<User> {
private String lastName;
private String email;
private Date created;
private String state;
private State state;
private String account;
private Account.Type accountType;
private String domain;
@ -80,7 +99,7 @@ public class User implements Comparable<User> {
return this;
}
public Builder state(String state) {
public Builder state(State state) {
this.state = state;
return this;
}
@ -143,7 +162,7 @@ public class User implements Comparable<User> {
private String lastName;
private String email;
private Date created;
private String state;
private State state;
private String account;
@SerializedName("accounttype")
private Account.Type accountType;
@ -157,7 +176,7 @@ public class User implements Comparable<User> {
@SerializedName("secretkey")
private String secretKey;
public User(long id, String name, String firstname, String lastname, String email, Date created, String state,
public User(long id, String name, String firstname, String lastname, String email, Date created, State state,
String account, Type accountType, String domain, long domainId, String timeZone, String apiKey,
String secretKey) {
this.id = id;
@ -228,7 +247,7 @@ public class User implements Comparable<User> {
*
* @return the user state
*/
public String getState() {
public State getState() {
return state;
}

View File

@ -18,9 +18,21 @@
*/
package org.jclouds.cloudstack.features;
import com.google.common.util.concurrent.ListenableFuture;
import org.jclouds.cloudstack.domain.Account;
import org.jclouds.cloudstack.domain.AsyncCreateResponse;
import org.jclouds.cloudstack.filters.QuerySigner;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.annotations.Unwrap;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
/**
* Provides asynchronous access to CloudStack Account features available to Domain
@ -35,4 +47,26 @@ import org.jclouds.rest.annotations.RequestFilters;
@QueryParams(keys = "response", values = "json")
public interface DomainAccountAsyncClient extends AccountAsyncClient {
/**
* @see DomainAccountClient#enableAccount
*/
@GET
@QueryParams(keys = "command", values = "enableAccount")
@SelectJson("account")
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Account> enableAccount(@QueryParam("account") String accountName, @QueryParam("domainid") long domainId);
/**
* @see DomainAccountAsyncClient#disableAccount
*/
@GET
@QueryParams(keys = "command", values = "disableAccount")
@Unwrap
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<AsyncCreateResponse> disableAccount(@QueryParam("account") String accountName,
@QueryParam("domainid") long domainId, @QueryParam("lock") boolean onlyLock);
}

View File

@ -20,6 +20,8 @@ package org.jclouds.cloudstack.features;
import java.util.concurrent.TimeUnit;
import org.jclouds.cloudstack.domain.Account;
import org.jclouds.cloudstack.domain.AsyncCreateResponse;
import org.jclouds.concurrent.Timeout;
/**
@ -34,5 +36,26 @@ import org.jclouds.concurrent.Timeout;
@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
public interface DomainAccountClient extends AccountClient {
/**
* Enable an account
*
* @param accountName
* the account name you are enabling
* @param domainId
* the domain ID
*/
Account enableAccount(String accountName, long domainId);
/**
* Disable or lock an account
*
* @param accountName
* the account name you are disabling
* @param domainId
* the domain ID
* @param onlyLock
* only lock if true disable otherwise
*/
AsyncCreateResponse disableAccount(String accountName, long domainId, boolean onlyLock);
}

View File

@ -0,0 +1,83 @@
/**
* 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.cloudstack.features;
import com.google.common.util.concurrent.ListenableFuture;
import org.jclouds.cloudstack.domain.AsyncCreateResponse;
import org.jclouds.cloudstack.domain.User;
import org.jclouds.cloudstack.filters.QuerySigner;
import org.jclouds.cloudstack.options.ListUsersOptions;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.annotations.Unwrap;
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import java.util.Set;
/**
* Provides asynchronous access to CloudStack User features available to Domain
* Admin users.
*
* @author Andrei Savu
* @see <a href=
* "http://download.cloud.com/releases/2.2.0/api_2.2.12/TOC_Domain_Admin.html"
* />
*/
@RequestFilters(QuerySigner.class)
@QueryParams(keys = "response", values = "json")
public interface DomainUserAsyncClient {
/**
* @see DomainUserClient#listUsers
*/
@GET
@QueryParams(keys = "command", values = "listUsers")
@SelectJson("user")
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Set<User>> listUsers(ListUsersOptions... options);
/**
* @see DomainUserClient#enableUser
*/
@GET
@QueryParams(keys = "command", values = "enableUser")
@SelectJson("user")
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<User> enableUser(@QueryParam("id") long userId);
/**
* @see DomainUserClient#disableUser
*/
@GET
@QueryParams(keys = "command", values = "disableUser")
@Unwrap
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<AsyncCreateResponse> disableUser(@QueryParam("id") long userId);
}

View File

@ -0,0 +1,63 @@
/**
* 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.cloudstack.features;
import org.jclouds.cloudstack.domain.AsyncCreateResponse;
import org.jclouds.cloudstack.domain.User;
import org.jclouds.cloudstack.options.ListUsersOptions;
import org.jclouds.concurrent.Timeout;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* Provides synchronous access to CloudStack User features available to Domain
* Admin users.
*
* @author Andrei Savu
* @see <a href=
* "http://download.cloud.com/releases/2.2.0/api_2.2.12/TOC_Domain_Admin.html"
* />
*/
@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
public interface DomainUserClient {
/**
* Lists Users
*
* @param options
* if present, how to constrain the list.
* @return Users matching query, or empty set, if no Accounts are found
*/
Set<User> listUsers(ListUsersOptions... options);
/**
* Enable a user with a specific ID
*
* @param userId
* the user ID to enable
*/
User enableUser(long userId);
/**
* Disable a user with a specific ID
*/
AsyncCreateResponse disableUser(long userId);
}

View File

@ -18,15 +18,28 @@
*/
package org.jclouds.cloudstack.features;
import com.google.common.util.concurrent.ListenableFuture;
import org.jclouds.cloudstack.domain.Account;
import org.jclouds.cloudstack.filters.QuerySigner;
import org.jclouds.cloudstack.options.CreateAccountOptions;
import org.jclouds.cloudstack.options.UpdateAccountOptions;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import java.util.Set;
/**
* Provides asynchronous access to CloudStack Account features available to Global
* Admin users.
*
* @author Adrian Cole
* @author Adrian Cole, Andrei Savu
* @see <a href=
* "http://download.cloud.com/releases/2.2.0/api_2.2.12/TOC_Global_Admin.html"
* />
@ -35,4 +48,36 @@ import org.jclouds.rest.annotations.RequestFilters;
@QueryParams(keys = "response", values = "json")
public interface GlobalAccountAsyncClient extends DomainAccountAsyncClient {
/**
* @see GlobalAccountClient#createAccount
*/
@GET
@QueryParams(keys = "command", values = "createAccount")
@SelectJson("account")
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Account> createAccount(@QueryParam("username") String userName,
@QueryParam("accounttype") Account.Type accountType, @QueryParam("email") String email,
@QueryParam("firstname") String firstName, @QueryParam("lastname") String lastName,
@QueryParam("password") String hashedPassword, CreateAccountOptions... options);
/**
* @see GlobalAccountClient#updateAccount
*/
@GET
@QueryParams(keys = "command", values = "updateAccount")
@SelectJson("account")
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Account> updateAccount(@QueryParam("account") String accountName,
@QueryParam("domainid") long domainId, @QueryParam("newname") String newName, UpdateAccountOptions... options);
/**
* @see GlobalAccountClient#deleteAccount
*/
@GET
@QueryParams(keys = "command", values = "deleteAccount")
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Void> deleteAccount(@QueryParam("id") long id);
}

View File

@ -20,13 +20,16 @@ package org.jclouds.cloudstack.features;
import java.util.concurrent.TimeUnit;
import org.jclouds.cloudstack.domain.Account;
import org.jclouds.cloudstack.options.CreateAccountOptions;
import org.jclouds.cloudstack.options.UpdateAccountOptions;
import org.jclouds.concurrent.Timeout;
/**
* Provides synchronous access to CloudStack Account features available to Global
* Admin users.
*
* @author Adrian Cole
* @author Adrian Cole, Andrei Savu
* @see <a href=
* "http://download.cloud.com/releases/2.2.0/api_2.2.12/TOC_Global_Admin.html"
* />
@ -34,5 +37,41 @@ import org.jclouds.concurrent.Timeout;
@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
public interface GlobalAccountClient extends DomainAccountClient {
/**
* Create a new Cloudstack account
*
* @param userName unique username.
* @param accountType type of account
* @param email
* @param firstName
* @param lastName
* @param hashedPassword
* Hashed password (Default is MD5). If you wish to use any other
* hashing algorithm, you would need to write a custom authentication adapter See Docs section.
* @param options
* optional parameters
* @return
*/
Account createAccount(String userName, Account.Type accountType, String email,
String firstName, String lastName, String hashedPassword, CreateAccountOptions... options);
/**
* Update an existing account
*
* @param accountName the current account name
* @param domainId the ID of the domain were the account exists
* @param newName new name for the account
* @param options optional arguments
* @return
*/
Account updateAccount(String accountName, long domainId, String newName, UpdateAccountOptions... options);
/**
* Delete an account with the specified ID
*
* @param accountId
* @return
*/
Void deleteAccount(long accountId);
}

View File

@ -0,0 +1,93 @@
/**
* 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.cloudstack.features;
import com.google.common.util.concurrent.ListenableFuture;
import org.jclouds.cloudstack.collections.Integration;
import org.jclouds.cloudstack.domain.ApiKeyPair;
import org.jclouds.cloudstack.domain.User;
import org.jclouds.cloudstack.filters.QuerySigner;
import org.jclouds.cloudstack.options.CreateUserOptions;
import org.jclouds.cloudstack.options.UpdateUserOptions;
import org.jclouds.rest.annotations.Endpoint;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
/**
* Provides asynchronous access to CloudStack User features available to Global
* Admin users.
*
* @author Andrei Savu
* @see <a href=
* "http://download.cloud.com/releases/2.2.0/api_2.2.12/TOC_Global_Admin.html"
* />
*/
@RequestFilters(QuerySigner.class)
@QueryParams(keys = "response", values = "json")
public interface GlobalUserAsyncClient extends DomainUserAsyncClient {
/**
* @see GlobalUserClient#createUser
*/
@GET
@QueryParams(keys = "command", values = "createUser")
@SelectJson("user")
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<User>createUser(@QueryParam("username") String userName, @QueryParam("account") String accountName,
@QueryParam("email") String email, @QueryParam("password") String hashedPassword,
@QueryParam("firstname") String firstName, @QueryParam("lastname") String lastName, CreateUserOptions... options);
/**
* @see GlobalUserClient#registerUserKeys
*/
@GET
@QueryParams(keys = "comand", values = "registerUserKeys")
@Endpoint(Integration.class)
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<ApiKeyPair> registerUserKeys(@QueryParam("id") long userId);
/**
* @see GlobalUserClient#updateUser
*/
@GET
@QueryParams(keys = "command", values = "updateUser")
@SelectJson("user")
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<User> updateUser(@QueryParam("id") long id, UpdateUserOptions... options);
/**
* @see GlobalUserClient#deleteUser
*/
@GET
@QueryParams(keys = "command", values = "deleteUser")
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Void> deleteUser(@QueryParam("id") long id);
}

View File

@ -0,0 +1,85 @@
/**
* 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.cloudstack.features;
import java.util.concurrent.TimeUnit;
import org.jclouds.cloudstack.domain.ApiKeyPair;
import org.jclouds.cloudstack.domain.User;
import org.jclouds.cloudstack.options.CreateUserOptions;
import org.jclouds.cloudstack.options.UpdateUserOptions;
import org.jclouds.concurrent.Timeout;
/**
* Provides synchronous access to CloudStack User features available to Global
* Admin users.
*
* @author Andrei savu
* @see <a href=
* "http://download.cloud.com/releases/2.2.0/api_2.2.12/TOC_Global_Admin.html"
* />
*/
@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
public interface GlobalUserClient extends DomainUserClient {
/**
* Create an user for an account that already exists
*
* @param userName unique user name
* @param accountName Creates the user under the specified account. If no
* account is specified, the username will be used as the account name.
* @param email
* @param hashedPassword Hashed password (Default is MD5). If you wish to use
* any other hashing algorithm, you would need to write a custom authentication
* adapter See Docs section.
* @param firstName
* @param lastName
* @param options optional arguments
* @return
*/
User createUser(String userName, String accountName, String email, String hashedPassword,
String firstName, String lastName, CreateUserOptions... options);
/**
* This command allows a user to register for the developer API, returning a
* secret key and an API key
*
* @param userId the ID of the user
* @return
*/
ApiKeyPair registerUserKeys(long userId);
/**
* Update an user
*
* @param id the user ID
* @param options optional arguments
* @return
*/
User updateUser(long id, UpdateUserOptions... options);
/**
* Delete an user with the specified ID
*
* @param id user ID
*/
Void deleteUser(long id);
}

View File

@ -29,6 +29,7 @@ import javax.inject.Named;
import javax.inject.Singleton;
import com.google.common.base.Strings;
import org.jclouds.cloudstack.domain.Account;
import org.jclouds.cloudstack.domain.AsyncJob;
import org.jclouds.cloudstack.domain.AsyncJob.Builder;
import org.jclouds.cloudstack.domain.AsyncJobError;
@ -39,6 +40,7 @@ import org.jclouds.cloudstack.domain.PublicIPAddress;
import org.jclouds.cloudstack.domain.SecurityGroup;
import org.jclouds.cloudstack.domain.Template;
import org.jclouds.cloudstack.domain.TemplateExtraction;
import org.jclouds.cloudstack.domain.User;
import org.jclouds.cloudstack.domain.VirtualMachine;
import org.jclouds.domain.JsonBall;
import org.jclouds.json.Json;
@ -62,6 +64,8 @@ public class ParseTypedAsyncJob implements Function<AsyncJob<Map<String, JsonBal
@VisibleForTesting
@Named("jclouds.cloudstack.jobresult-type-map")
Map<String, Class<?>> typeMap = ImmutableMap.<String, Class<?>>builder()
.put("user", User.class)
.put("account", Account.class)
.put("securitygroup", SecurityGroup.class)
.put("portforwardingrule", PortForwardingRule.class)
.put("ipforwardingrule", IPForwardingRule.class)

View File

@ -0,0 +1,87 @@
/**
* 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.cloudstack.options;
import com.google.common.collect.ImmutableSet;
import org.jclouds.http.options.BaseHttpRequestOptions;
/**
* Optional fields for account creation
*
* @author Adrian Cole
* @see <a
* href="http://download.cloud.com/releases/2.2.0/api_2.2.12/global_admin/createAccount.html"
* />
*/
public class CreateAccountOptions extends BaseHttpRequestOptions {
public static final CreateAccountOptions NONE = new CreateAccountOptions();
/**
* @param networkDomain network domain
*/
public CreateAccountOptions networkDomain(String networkDomain) {
this.queryParameters.replaceValues("networkdomain", ImmutableSet.of(networkDomain));
return this;
}
/**
* @param account an optional account for the resource
*/
public CreateAccountOptions account(String account) {
this.queryParameters.replaceValues("account", ImmutableSet.of(account));
return this;
}
/**
* @param domainId The domain for the resource
*/
public CreateAccountOptions domainId(long domainId) {
this.queryParameters.replaceValues("domainid", ImmutableSet.of(domainId + ""));
return this;
}
public static class Builder {
/**
* @see CreateAccountOptions#networkDomain
*/
public static CreateAccountOptions networkDomain(String networkDomain) {
CreateAccountOptions options = new CreateAccountOptions();
return options.networkDomain(networkDomain);
}
/**
* @see CreateAccountOptions#account
*/
public static CreateAccountOptions account(String account) {
CreateAccountOptions options = new CreateAccountOptions();
return options.account(account);
}
/**
* @see CreateAccountOptions#domainId
*/
public static CreateAccountOptions domainId(long domainId) {
CreateAccountOptions options = new CreateAccountOptions();
return options.domainId(domainId);
}
}
}

View File

@ -21,10 +21,10 @@ package org.jclouds.cloudstack.options;
import com.google.common.collect.ImmutableSet;
/**
* Options used to control what networks information is returned
* Optional fields for network creation
*
* @see <a
* href="http://download.cloud.com/releases/2.2.0/api/user/listNetworks.html"
* href="http://download.cloud.com/releases/2.2.0/api_2.2.12/user/createNetwork.html"
* />
* @author Adrian Cole
*/

View File

@ -0,0 +1,72 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.cloudstack.options;
import com.google.common.collect.ImmutableSet;
import org.jclouds.http.options.BaseHttpRequestOptions;
/**
* Optional fields for user creation
*
* @author Andrei Savu
* @see <a
* href="http://download.cloud.com/releases/2.2.0/api_2.2.12/global_admin/createUser.html"
* />
*/
public class CreateUserOptions extends BaseHttpRequestOptions {
public static final CreateUserOptions NONE = new CreateUserOptions();
/**
* @param domainId The domain for the resource
*/
public CreateUserOptions domainId(long domainId) {
this.queryParameters.replaceValues("domainid", ImmutableSet.of(domainId + ""));
return this;
}
/**
* @param timezone Specifies a timezone for this command. For more information
* on the timezone parameter, see Time Zone Format.
*/
public CreateUserOptions timezone(String timezone) {
this.queryParameters.replaceValues("timezone", ImmutableSet.of(timezone));
return this;
}
public static class Builder {
/**
* @see CreateUserOptions#domainId
*/
public static CreateUserOptions domainId(long domainId) {
CreateUserOptions options = new CreateUserOptions();
return options.domainId(domainId);
}
/**
* @see CreateUserOptions#timezone
*/
public static CreateUserOptions timezone(String timezone) {
CreateUserOptions options = new CreateUserOptions();
return options.timezone(timezone);
}
}
}

View File

@ -0,0 +1,189 @@
/**
* 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.cloudstack.options;
import com.google.common.collect.ImmutableSet;
/**
* Options used to control what user information is returned
*
* @see <a
* href="http://download.cloud.com/releases/2.2.0/api_2.2.12/domain_admin/listUsers.html"
* />
* @author Andrei Savu
*/
public class ListUsersOptions extends AccountInDomainOptions {
public static final ListUsersOptions NONE = new ListUsersOptions();
/**
* @param id
* list account by account ID
*/
public ListUsersOptions id(long id) {
this.queryParameters.replaceValues("id", ImmutableSet.of(id + ""));
return this;
}
/**
* @param userName
* retrieve user by name
*/
public ListUsersOptions userName(String userName) {
this.queryParameters.replaceValues("name", ImmutableSet.of(userName));
return this;
}
/**
* @param state
* list accounts by state. Valid states are enabled, disabled, and
* locked.
*/
public ListUsersOptions state(String state) {
this.queryParameters.replaceValues("state", ImmutableSet.of(state));
return this;
}
/**
* @param accountType
* List users by account type. Valid types include admin,
* domain-admin, read-only-admin, or user.
*/
public ListUsersOptions accountType(String accountType) {
this.queryParameters.replaceValues("accounttype", ImmutableSet.of(accountType));
return this;
}
/**
* @param keyword
*/
public ListUsersOptions keyword(String keyword) {
this.queryParameters.replaceValues("keyword", ImmutableSet.of(keyword));
return this;
}
/**
* @param page
* the page number
*/
public ListUsersOptions page(long page) {
this.queryParameters.replaceValues("page", ImmutableSet.of(page + ""));
return this;
}
/**
* @param pageSize
* the number of items per page
*/
public ListUsersOptions pageSize(long pageSize) {
this.queryParameters.replaceValues("pagesize", ImmutableSet.of(pageSize + ""));
return this;
}
public static class Builder {
/**
* @see ListUsersOptions#id
*/
public static ListUsersOptions id(long id) {
ListUsersOptions options = new ListUsersOptions();
return options.id(id);
}
/**
* @see ListUsersOptions#userName(String)
*/
public static ListUsersOptions userName(String name) {
ListUsersOptions options = new ListUsersOptions();
return options.userName(name);
}
/**
* @see ListUsersOptions#state
*/
public static ListUsersOptions state(String state) {
ListUsersOptions options = new ListUsersOptions();
return options.state(state);
}
/**
* @see ListUsersOptions#accountType
*/
public static ListUsersOptions accountType(String accountType) {
ListUsersOptions options = new ListUsersOptions();
return options.accountType(accountType);
}
/**
* @see ListUsersOptions#keyword
*/
public static ListUsersOptions keyword(String keyword) {
ListUsersOptions options = new ListUsersOptions();
return options.keyword(keyword);
}
/**
* @see ListUsersOptions#page
*/
public static ListUsersOptions page(long page) {
ListUsersOptions options = new ListUsersOptions();
return options.page(page);
}
/**
* @see ListUsersOptions#pageSize
*/
public static ListUsersOptions pageSize(long pageSize) {
ListUsersOptions options = new ListUsersOptions();
return options.pageSize(pageSize);
}
/**
* @see ListUsersOptions#accountInDomain
*/
public static ListUsersOptions accountInDomain(String account, long domain) {
ListUsersOptions options = new ListUsersOptions();
return options.accountInDomain(account, domain);
}
/**
* @see ListUsersOptions#domainId
*/
public static ListUsersOptions domainId(long id) {
ListUsersOptions options = new ListUsersOptions();
return options.domainId(id);
}
}
/**
* {@inheritDoc}
*/
@Override
public ListUsersOptions accountInDomain(String account, long domain) {
return ListUsersOptions.class.cast(super.accountInDomain(account, domain));
}
/**
* {@inheritDoc}
*/
@Override
public ListUsersOptions domainId(long domainId) {
return ListUsersOptions.class.cast(super.domainId(domainId));
}
}

View File

@ -0,0 +1,56 @@
/**
* 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.cloudstack.options;
import com.google.common.collect.ImmutableSet;
import org.jclouds.http.options.BaseHttpRequestOptions;
/**
* Optional arguments for updating an Account
*
* @see <a
* href="http://download.cloud.com/releases/2.2.0/api_2.2.12/global_admin/updateAccount.html"
* />
* @author Andrei Savu
*/
public class UpdateAccountOptions extends BaseHttpRequestOptions {
public static final UpdateAccountOptions NONE = new UpdateAccountOptions();
/**
* @param networkDomain
* network domain for the account's networks
*/
public UpdateAccountOptions networkDomain(String networkDomain) {
this.queryParameters.replaceValues("networkdomain", ImmutableSet.<String>of(networkDomain));
return this;
}
public static class Builder {
/**
* @see UpdateAccountOptions#networkDomain
*/
public static UpdateAccountOptions networkDomain(String networkDomain) {
UpdateAccountOptions options = new UpdateAccountOptions();
return options.networkDomain(networkDomain);
}
}
}

View File

@ -0,0 +1,169 @@
/**
* 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.cloudstack.options;
import com.google.common.collect.ImmutableSet;
import org.jclouds.http.options.BaseHttpRequestOptions;
/**
* Optional arguments for updating an User
*
* @author Andrei Savu
* @see <a
* href="http://download.cloud.com/releases/2.2.0/api_2.2.12/global_admin/updateUser.html"
* />
*/
public class UpdateUserOptions extends BaseHttpRequestOptions {
public static final UpdateUserOptions NONE = new UpdateUserOptions();
/**
* @param email user email address
*/
public UpdateUserOptions email(String email) {
this.queryParameters.replaceValues("email", ImmutableSet.of(email));
return this;
}
/**
* @param firstName user account first name
*/
public UpdateUserOptions firstName(String firstName) {
this.queryParameters.replaceValues("firstname", ImmutableSet.of(firstName));
return this;
}
/**
* @param lastName user account last name
*/
public UpdateUserOptions lastName(String lastName) {
this.queryParameters.replaceValues("lastname", ImmutableSet.of(lastName));
return this;
}
/**
* @param hashedPassword hashed password (default is MD5). If you wish to use any other
* hashing algorithm, you would need to write a custom authentication adapter
*/
public UpdateUserOptions hashedPassword(String hashedPassword) {
this.queryParameters.replaceValues("password", ImmutableSet.of(hashedPassword));
return this;
}
/**
* @param timezone specifies a timezone for this command. For more information on
* the timezone parameter, see Time Zone Format.
*/
public UpdateUserOptions timezone(String timezone) {
this.queryParameters.replaceValues("timezone", ImmutableSet.of(timezone));
return this;
}
/**
* @param userApiKey
*/
public UpdateUserOptions userApiKey(String userApiKey) {
this.queryParameters.replaceValues("userapikey", ImmutableSet.of(userApiKey));
return this;
}
/**
* @param userSecretKey
*/
public UpdateUserOptions userSecretKey(String userSecretKey) {
this.queryParameters.replaceValues("usersecretkey", ImmutableSet.of(userSecretKey));
return this;
}
/**
* @param userName unique user name
*/
public UpdateUserOptions userName(String userName) {
this.queryParameters.replaceValues("username", ImmutableSet.of(userName));
return this;
}
public static class Builder {
/**
* @see UpdateUserOptions#email
*/
public static UpdateUserOptions email(String email) {
UpdateUserOptions options = new UpdateUserOptions();
return options.email(email);
}
/**
* @see UpdateUserOptions#firstName
*/
public static UpdateUserOptions firstName(String firstName) {
UpdateUserOptions options = new UpdateUserOptions();
return options.firstName(firstName);
}
/**
* @see UpdateUserOptions#lastName
*/
public static UpdateUserOptions lastName(String lastName) {
UpdateUserOptions options = new UpdateUserOptions();
return options.lastName(lastName);
}
/**
* @see UpdateUserOptions#hashedPassword
*/
public static UpdateUserOptions hashedPassword(String hashedPassword) {
UpdateUserOptions options = new UpdateUserOptions();
return options.hashedPassword(hashedPassword);
}
/**
* @see UpdateUserOptions#timezone
*/
public static UpdateUserOptions timezone(String timezone) {
UpdateUserOptions options = new UpdateUserOptions();
return options.timezone(timezone);
}
/**
* @see UpdateUserOptions#userApiKey
*/
public static UpdateUserOptions userApiKey(String userApiKey) {
UpdateUserOptions options = new UpdateUserOptions();
return options.userApiKey(userApiKey);
}
/**
* @see UpdateUserOptions#userSecretKey
*/
public static UpdateUserOptions userSecretKey(String userSecretKey) {
UpdateUserOptions options = new UpdateUserOptions();
return options.userSecretKey(userSecretKey);
}
/**
* @see UpdateUserOptions#userName
*/
public static UpdateUserOptions userName(String userName) {
UpdateUserOptions options = new UpdateUserOptions();
return options.userName(userName);
}
}
}

View File

@ -170,7 +170,7 @@ public class BaseCloudStackClientLiveTest extends BaseVersionedServiceLiveTest {
protected boolean domainAdminEnabled;
protected CloudStackContext domainAdminComputeContext;
protected RestContext<CloudStackDomainClient, CloudStackDomainAsyncClient> domainAdminContext;
protected CloudStackClient domainAdminClient;
protected CloudStackDomainClient domainAdminClient;
protected User domainAdminUser;
protected boolean globalAdminEnabled;

View File

@ -18,11 +18,19 @@
*/
package org.jclouds.cloudstack.features;
import org.jclouds.cloudstack.options.ListAccountsOptions;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.functions.ParseFirstJsonValueNamed;
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.testng.annotations.Test;
import com.google.inject.TypeLiteral;
import java.io.IOException;
import java.lang.reflect.Method;
/**
* Tests behavior of {@code DomainAccountAsyncClient}
*
@ -31,6 +39,37 @@ import com.google.inject.TypeLiteral;
@Test(groups = "unit", testName = "DomainAccountAsyncClientTest")
public class DomainAccountAsyncClientTest extends BaseCloudStackAsyncClientTest<DomainAccountAsyncClient> {
public void testEnableAccount() throws Exception {
Method method = DomainAccountAsyncClient.class.getMethod("enableAccount", long.class, long.class);
HttpRequest httpRequest = processor.createRequest(method, 1L, 2L);
assertRequestLineEquals(httpRequest,
"GET http://localhost:8080/client/api?response=json&command=enableAccount&account=1&domainid=2 HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(httpRequest);
}
public void testDisableAccount() throws Exception {
Method method = DomainAccountAsyncClient.class.getMethod("disableAccount", long.class, long.class, boolean.class);
HttpRequest httpRequest = processor.createRequest(method, 1L, 2L, true);
assertRequestLineEquals(httpRequest,
"GET http://localhost:8080/client/api?response=json&command=disableAccount&account=1&lock=true&domainid=2 HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(httpRequest);
}
@Override
protected TypeLiteral<RestAnnotationProcessor<DomainAccountAsyncClient>> createTypeLiteral() {

View File

@ -18,8 +18,16 @@
*/
package org.jclouds.cloudstack.features;
import org.jclouds.cloudstack.domain.Account;
import org.jclouds.cloudstack.domain.AsyncCreateResponse;
import org.jclouds.cloudstack.domain.AsyncJob;
import org.testng.annotations.Test;
import static org.jclouds.cloudstack.features.GlobalAccountClientLiveTest.createTestAccount;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
/**
* Tests behavior of {@code DomainAccountClient}
*
@ -28,4 +36,32 @@ import org.testng.annotations.Test;
@Test(groups = "live", singleThreaded = true, testName = "DomainAccountClientLiveTest")
public class DomainAccountClientLiveTest extends BaseCloudStackClientLiveTest {
@Test
public void testEnableDisableAccount() {
assert globalAdminEnabled;
Account testAccount = null;
try {
testAccount = createTestAccount(globalAdminClient, prefix);
AsyncCreateResponse response = domainAdminClient.getAccountClient()
.disableAccount(testAccount.getName(), testAccount.getDomainId(), false);
assertNotNull(response);
assertTrue(jobComplete.apply(response.getJobId()));
AsyncJob<Account> job = domainAdminClient.getAsyncJobClient().getAsyncJob(response.getJobId());
assertEquals(job.getResult().getState(), Account.State.DISABLED);
Account updated = domainAdminClient.getAccountClient()
.enableAccount(testAccount.getName(), testAccount.getDomainId());
assertNotNull(updated);
assertEquals(updated.getState(), Account.State.ENABLED);
} finally {
if (testAccount != null) {
globalAdminClient.getAccountClient().deleteAccount(testAccount.getId());
}
}
}
}

View File

@ -0,0 +1,38 @@
/**
* 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.cloudstack.features;
import com.google.inject.TypeLiteral;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.testng.annotations.Test;
/**
* Tests behavior of {@code DomainUserAsyncClient}
*
* @author Andrei Savu
*/
@Test(groups = "unit", testName = "DomainUserAsyncClientTest")
public class DomainUserAsyncClientTest extends BaseCloudStackAsyncClientTest<DomainUserAsyncClient> {
@Override
protected TypeLiteral<RestAnnotationProcessor<DomainUserAsyncClient>> createTypeLiteral() {
return new TypeLiteral<RestAnnotationProcessor<DomainUserAsyncClient>>() {
};
}
}

View File

@ -0,0 +1,92 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.cloudstack.features;
import org.jclouds.cloudstack.domain.Account;
import org.jclouds.cloudstack.domain.AsyncCreateResponse;
import org.jclouds.cloudstack.domain.AsyncJob;
import org.jclouds.cloudstack.domain.User;
import org.testng.annotations.Test;
import java.util.Set;
import static org.jclouds.cloudstack.features.GlobalAccountClientLiveTest.createTestAccount;
import static org.jclouds.cloudstack.features.GlobalUserClientLiveTest.createTestUser;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
/**
* Tests behavior of {@code DomainUserClient}
*/
@Test(groups = "live", singleThreaded = true, testName = "DomainUserClientLiveTest")
public class DomainUserClientLiveTest extends BaseCloudStackClientLiveTest {
@Test
public void testListUsers() {
assert domainAdminEnabled;
Set<User> users = domainAdminClient.getUserClient().listUsers();
assert users.size() > 0;
assert users.contains(user); // contains the current user
for (User user : users) {
checkUser(user);
}
}
private void checkUser(User user) {
assert user.getId() > 0;
assert user.getAccount() != null;
assert user.getDomain() != null;
}
@Test
public void testEnableDisableUser() {
assert globalAdminEnabled && domainAdminEnabled;
Account testAccount = null;
User testUser = null;
try {
testAccount = createTestAccount(globalAdminClient, prefix);
testUser = createTestUser(globalAdminClient, testAccount, prefix);
AsyncCreateResponse response = domainAdminClient.getUserClient().disableUser(testUser.getId());
assertNotNull(response);
assertTrue(jobComplete.apply(response.getJobId()));
AsyncJob<User> job = domainAdminClient.getAsyncJobClient().getAsyncJob(response.getJobId());
assertNotNull(job);
assertEquals(job.getResult().getState(), User.State.DISABLED);
User updated = domainAdminClient.getUserClient().enableUser(testUser.getId());
assertNotNull(updated);
assertEquals(updated.getState(), User.State.ENABLED);
} finally {
if (testUser != null) {
globalAdminClient.getUserClient().deleteUser(testUser.getId());
}
if (testAccount != null) {
globalAdminClient.getAccountClient().deleteAccount(testAccount.getId());
}
}
}
}

View File

@ -18,11 +18,20 @@
*/
package org.jclouds.cloudstack.features;
import org.jclouds.cloudstack.domain.Account;
import org.jclouds.cloudstack.options.CreateAccountOptions;
import org.jclouds.cloudstack.options.UpdateAccountOptions;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.functions.ParseFirstJsonValueNamed;
import org.jclouds.http.functions.ReleasePayloadAndReturn;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.testng.annotations.Test;
import com.google.inject.TypeLiteral;
import java.lang.reflect.Method;
/**
* Tests behavior of {@code GlobalAccountAsyncClient}
*
@ -31,6 +40,59 @@ import com.google.inject.TypeLiteral;
@Test(groups = "unit", testName = "GlobalAccountAsyncClientTest")
public class GlobalAccountAsyncClientTest extends BaseCloudStackAsyncClientTest<GlobalAccountAsyncClient> {
public void testCreateAccount() throws Exception {
Method method = GlobalAccountAsyncClient.class.getMethod("createAccount", String.class, Account.Type.class,
String.class, String.class, String.class, String.class, CreateAccountOptions[].class);
HttpRequest httpRequest = processor.createRequest(method, "user", Account.Type.USER, "email@example.com",
"FirstName", "LastName", "hashed-password");
assertRequestLineEquals(httpRequest,
"GET http://localhost:8080/client/api?response=json&command=createAccount&password=hashed-password&" +
"username=user&email=email%40example.com&accounttype=0&firstname=FirstName&lastname=LastName HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(httpRequest);
}
public void testUpdateAccount() throws Exception {
Method method = GlobalAccountAsyncClient.class.getMethod("updateAccount", String.class, long.class,
String.class, UpdateAccountOptions[].class);
HttpRequest httpRequest = processor.createRequest(method, "account", 42L, "new-account-name");
assertRequestLineEquals(httpRequest,
"GET http://localhost:8080/client/api?response=json&command=updateAccount&account=account&" +
"newname=new-account-name&domainid=42 HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(httpRequest);
}
public void testDeleteAccount() throws Exception {
Method method = GlobalAccountAsyncClient.class.getMethod("deleteAccount", long.class);
HttpRequest httpRequest = processor.createRequest(method, 42L);
assertRequestLineEquals(httpRequest,
"GET http://localhost:8080/client/api?response=json&command=deleteAccount&id=42 HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, ReleasePayloadAndReturn.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(httpRequest);
}
@Override
protected TypeLiteral<RestAnnotationProcessor<GlobalAccountAsyncClient>> createTypeLiteral() {
return new TypeLiteral<RestAnnotationProcessor<GlobalAccountAsyncClient>>() {

View File

@ -18,14 +18,51 @@
*/
package org.jclouds.cloudstack.features;
import org.jclouds.cloudstack.CloudStackGlobalClient;
import org.jclouds.cloudstack.domain.Account;
import org.testng.annotations.Test;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
/**
* Tests behavior of {@code GlobalAccountClient}
*
* @author Adrian Cole
* @author Adrian Cole, Andrei Savu
*/
@Test(groups = "live", singleThreaded = true, testName = "GlobalAccountClientLiveTest")
public class GlobalAccountClientLiveTest extends BaseCloudStackClientLiveTest {
public static Account createTestAccount(CloudStackGlobalClient client, String prefix) {
return client.getAccountClient().createAccount(
prefix + "-account", Account.Type.USER, "dummy@example.com",
"First", "Last", "hashed-password");
}
@Test
public void testCreateAndRemoveAccount() {
assert globalAdminEnabled;
Account account = null;
try {
account = createTestAccount(globalAdminClient, prefix);
assertNotNull(account);
assertEquals(account.getName(), prefix + "-account");
assertEquals(account.getType(), Account.Type.USER);
Account updated = globalAdminClient.getAccountClient().updateAccount(
account.getName(), account.getDomainId(), prefix + "-account-2");
assertNotNull(updated);
assertEquals(updated.getName(), prefix + "-account-2");
} finally {
if (account != null) {
globalAdminClient.getAccountClient().deleteAccount(account.getId());
}
}
}
}

View File

@ -0,0 +1,96 @@
/**
* 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.cloudstack.features;
import com.google.inject.TypeLiteral;
import org.jclouds.cloudstack.options.CreateUserOptions;
import org.jclouds.cloudstack.options.UpdateAccountOptions;
import org.jclouds.cloudstack.options.UpdateUserOptions;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.functions.ParseFirstJsonValueNamed;
import org.jclouds.http.functions.ReleasePayloadAndReturn;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.testng.annotations.Test;
import java.lang.reflect.Method;
/**
* Tests behavior of {@code GlobalUserAsyncClient}
*/
@Test(groups = "unit", testName = "GlobalUserAsyncClientTest")
public class GlobalUserAsyncClientTest extends BaseCloudStackAsyncClientTest<GlobalUserAsyncClient> {
public void testCreateAccount() throws Exception {
Method method = GlobalUserAsyncClient.class.getMethod("createUser", String.class, String.class,
String.class, String.class, String.class, String.class, CreateUserOptions[].class);
HttpRequest httpRequest = processor.createRequest(method, "user", "account", "email@example.com",
"hashed-password", "FirstName", "LastName");
assertRequestLineEquals(httpRequest,
"GET http://localhost:8080/client/api?response=json&command=createUser&lastname=LastName&" +
"username=user&email=email%40example.com&account=account&password=hashed-password&firstname=FirstName HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(httpRequest);
}
public void testUpdateUser() throws Exception {
Method method = GlobalUserAsyncClient.class.getMethod("updateUser", long.class, UpdateUserOptions[].class);
HttpRequest httpRequest = processor.createRequest(method, 42L);
assertRequestLineEquals(httpRequest,
"GET http://localhost:8080/client/api?response=json&command=updateUser&id=42 HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(httpRequest);
}
public void testDeleteUser() throws Exception {
Method method = GlobalUserAsyncClient.class.getMethod("deleteUser", long.class);
HttpRequest httpRequest = processor.createRequest(method, 42L);
assertRequestLineEquals(httpRequest,
"GET http://localhost:8080/client/api?response=json&command=deleteUser&id=42 HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, ReleasePayloadAndReturn.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(httpRequest);
}
@Override
protected TypeLiteral<RestAnnotationProcessor<GlobalUserAsyncClient>> createTypeLiteral() {
return new TypeLiteral<RestAnnotationProcessor<GlobalUserAsyncClient>>() {
};
}
}

View File

@ -0,0 +1,109 @@
/**
* 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.cloudstack.features;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Module;
import org.jclouds.cloudstack.CloudStackClient;
import org.jclouds.cloudstack.CloudStackGlobalClient;
import org.jclouds.cloudstack.domain.Account;
import org.jclouds.cloudstack.domain.ApiKeyPair;
import org.jclouds.cloudstack.domain.User;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.annotations.Test;
import java.util.Properties;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.cloudstack.features.GlobalAccountClientLiveTest.createTestAccount;
import static org.jclouds.cloudstack.options.UpdateUserOptions.Builder.userName;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
/**
* Tests behavior of {@code GlobaUserClient}
*/
@Test(groups = "live", singleThreaded = true, testName = "GlobalUserClientLiveTest")
public class GlobalUserClientLiveTest extends BaseCloudStackClientLiveTest {
public static User createTestUser(CloudStackGlobalClient client, Account account, String prefix) {
return client.getUserClient().createUser(prefix + "-user",
account.getName(), "dummy2@example.com", "md5-password", "First", "Last");
}
@Test
public void testCreateUser() {
assert globalAdminEnabled;
Account testAccount = createTestAccount(globalAdminClient, prefix);
User testUser = null;
try {
testUser = createTestUser(globalAdminClient, testAccount, prefix);
assertNotNull(testUser);
assertEquals(testUser.getName(), prefix + "-user");
assertEquals(testUser.getAccount(), prefix + "-account");
User updatedUser = globalAdminClient.getUserClient()
.updateUser(testUser.getId(), userName(prefix + "-user-2"));
assertNotNull(updatedUser);
assertEquals(updatedUser.getName(), prefix + "-user-2");
ApiKeyPair apiKeys = globalAdminClient.getUserClient()
.registerUserKeys(updatedUser.getId());
assertNotNull(apiKeys.getApiKey());
assertNotNull(apiKeys.getSecretKey());
checkAuthAsUser(apiKeys);
} finally {
if (testUser != null) {
globalAdminClient.getUserClient().deleteUser(testUser.getId());
}
globalAdminClient.getAccountClient().deleteAccount(testAccount.getId());
}
}
private void checkAuthAsUser(ApiKeyPair keyPair) {
ComputeServiceContext context = new ComputeServiceContextFactory(setupRestProperties()).
createContext(provider, ImmutableSet.<Module>of(
new Log4JLoggingModule(), new SshjSshClientModule()), credentialsAsProperties(keyPair));
CloudStackClient client = CloudStackClient.class.cast(context.getProviderSpecificContext().getApi());
Set<Account> accounts = client.getAccountClient().listAccounts();
assert accounts.size() > 0;
context.close();
}
private Properties credentialsAsProperties(ApiKeyPair keyPair) {
Properties overrides = new Properties();
overrides.put(provider + ".identity", checkNotNull(keyPair.getApiKey()));
overrides.put(provider + ".credential", checkNotNull(keyPair.getSecretKey()));
return overrides;
}
}

View File

@ -96,7 +96,7 @@ public class ListAccountsResponseTest extends BaseSetParserTest<Account> {
ImmutableSet.of(User.builder().id(505).name("jclouds").firstName("Adrian").lastName("Cole")
.email("adrian@jclouds.org")
.created(new SimpleDateFormatDateService().iso8601SecondsDateParse("2011-04-19T01:57:24+0000"))
.state("enabled").account("jclouds").accountType(Type.USER).domainId(457)
.state(User.State.ENABLED).account("jclouds").accountType(Type.USER).domainId(457)
.domain("AA000062-jclouds-dev").apiKey("APIKEY").secretKey("SECRETKEY").build())).build());
}