made new cloudstackcontext with visibility to domainAdmin and also globalAdmin clients

This commit is contained in:
Adrian Cole 2011-11-21 19:57:19 +02:00
parent db54e0c426
commit 009c1e30f6
28 changed files with 928 additions and 40 deletions

View File

@ -0,0 +1,22 @@
package org.jclouds.cloudstack;
import org.jclouds.cloudstack.internal.CloudStackContextImpl;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.rest.RestContext;
import com.google.inject.ImplementedBy;
/**
*
*
* @author Adrian Cole
*
*/
@ImplementedBy(CloudStackContextImpl.class)
public interface CloudStackContext extends ComputeServiceContext {
RestContext<CloudStackDomainClient, CloudStackDomainAsyncClient> getDomainContext();
RestContext<CloudStackGlobalClient, CloudStackGlobalAsyncClient> getGlobalContext();
}

View File

@ -23,6 +23,7 @@ import java.util.Properties;
import org.jclouds.cloudstack.compute.config.CloudStackComputeServiceContextModule;
import org.jclouds.cloudstack.config.CloudStackRestClientModule;
import org.jclouds.cloudstack.internal.CloudStackContextImpl;
import org.jclouds.compute.ComputeServiceContextBuilder;
import com.google.inject.Module;
@ -47,4 +48,8 @@ public class CloudStackContextBuilder extends ComputeServiceContextBuilder<Cloud
modules.add(new CloudStackRestClientModule());
}
@Override
public CloudStackContext buildComputeServiceContext() {
return buildInjector().getInstance(CloudStackContextImpl.class);
}
}

View File

@ -0,0 +1,51 @@
/**
* 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;
import org.jclouds.cloudstack.features.DomainAccountAsyncClient;
import org.jclouds.cloudstack.features.DomainLimitAsyncClient;
import org.jclouds.rest.annotations.Delegate;
/**
* Provides asynchronous access to CloudStack via their REST API.
* <p/>
*
* @author Adrian Cole
* @see CloudStackDomainClient
* @see <a href=
* "http://download.cloud.com/releases/2.2.0/api_2.2.12/TOC_Domain_Admin.html"
* />
*/
public interface CloudStackDomainAsyncClient extends CloudStackAsyncClient {
/**
* Provides synchronous access to Resource Limits
*/
@Delegate
@Override
DomainLimitAsyncClient getLimitClient();
/**
* Provides synchronous access to Accounts
*/
@Delegate
@Override
DomainAccountAsyncClient getAccountClient();
}

View File

@ -0,0 +1,54 @@
/**
* 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;
import java.util.concurrent.TimeUnit;
import org.jclouds.cloudstack.features.DomainAccountClient;
import org.jclouds.cloudstack.features.DomainLimitClient;
import org.jclouds.concurrent.Timeout;
import org.jclouds.rest.annotations.Delegate;
/**
* Provides synchronous access to CloudStack.
* <p/>
*
* @author Adrian Cole
* @see CloudStackDomainAsyncClient
* @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 CloudStackDomainClient extends CloudStackClient {
/**
* Provides synchronous access to Resource Limits
*/
@Delegate
@Override
DomainLimitClient getLimitClient();
/**
* Provides synchronous access to Accounts
*/
@Delegate
@Override
DomainAccountClient getAccountClient();
}

View File

@ -0,0 +1,43 @@
/**
* 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;
import org.jclouds.cloudstack.features.GlobalAccountAsyncClient;
import org.jclouds.rest.annotations.Delegate;
/**
* Provides asynchronous access to CloudStack via their REST API.
* <p/>
*
* @author Adrian Cole
* @see CloudStackDomainClient
* @see <a href=
* "http://download.cloud.com/releases/2.2.0/api_2.2.12/TOC_Global_Admin.html"
* />
*/
public interface CloudStackGlobalAsyncClient extends CloudStackDomainAsyncClient {
/**
* Provides synchronous access to Accounts
*/
@Delegate
@Override
GlobalAccountAsyncClient getAccountClient();
}

View File

@ -0,0 +1,46 @@
/**
* 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;
import java.util.concurrent.TimeUnit;
import org.jclouds.cloudstack.features.GlobalAccountClient;
import org.jclouds.concurrent.Timeout;
import org.jclouds.rest.annotations.Delegate;
/**
* Provides synchronous access to CloudStack.
* <p/>
*
* @author Adrian Cole
* @see CloudStackDomainAsyncClient
* @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 CloudStackGlobalClient extends CloudStackDomainClient {
/**
* Provides synchronous access to Accounts
*/
@Delegate
@Override
GlobalAccountClient getAccountClient();
}

View File

@ -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.cloudstack.binders;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.ws.rs.core.UriBuilder;
import org.jclouds.cloudstack.domain.ResourceLimit;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.utils.ModifyRequest;
import org.jclouds.rest.Binder;
/**
* @author Adrian Cole
*
* @see <a href=
* "http://download.cloud.com/releases/2.2.0/api_2.2.12/domain_admin/updateResourceLimit.html"
* />
*/
public class ResourceLimitToQueryParams implements Binder {
private final Provider<UriBuilder> uriBuilderProvider;
@Inject
public ResourceLimitToQueryParams(Provider<UriBuilder> uriBuilderProvider) {
this.uriBuilderProvider = checkNotNull(uriBuilderProvider, "uriBuilderProvider");
}
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
checkArgument(input instanceof ResourceLimit, "this binder is only valid for ResourceLimit");
ResourceLimit limit = (ResourceLimit) input;
request = ModifyRequest.addQueryParam(request, "resourcetype", limit.getResourceType().getCode(),
uriBuilderProvider.get());
request = ModifyRequest.addQueryParam(request, "account", limit.getAccount(), uriBuilderProvider.get());
request = ModifyRequest.addQueryParam(request, "domainid", limit.getDomainId(), uriBuilderProvider.get());
request = ModifyRequest.addQueryParam(request, "max", limit.getMax(), uriBuilderProvider.get());
return request;
}
}

View File

@ -20,9 +20,12 @@ package org.jclouds.cloudstack.config;
import java.util.Map;
import com.google.common.collect.ImmutableMap;
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.features.AccountAsyncClient;
import org.jclouds.cloudstack.features.AccountClient;
import org.jclouds.cloudstack.features.AddressAsyncClient;
@ -31,10 +34,16 @@ import org.jclouds.cloudstack.features.AsyncJobAsyncClient;
import org.jclouds.cloudstack.features.AsyncJobClient;
import org.jclouds.cloudstack.features.ConfigurationAsyncClient;
import org.jclouds.cloudstack.features.ConfigurationClient;
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.EventAsyncClient;
import org.jclouds.cloudstack.features.EventClient;
import org.jclouds.cloudstack.features.FirewallAsyncClient;
import org.jclouds.cloudstack.features.FirewallClient;
import org.jclouds.cloudstack.features.GlobalAccountAsyncClient;
import org.jclouds.cloudstack.features.GlobalAccountClient;
import org.jclouds.cloudstack.features.GuestOSAsyncClient;
import org.jclouds.cloudstack.features.GuestOSClient;
import org.jclouds.cloudstack.features.HypervisorAsyncClient;
@ -76,18 +85,24 @@ import org.jclouds.http.annotation.ServerError;
import org.jclouds.json.config.GsonModule.DateAdapter;
import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
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 com.google.common.collect.ImmutableMap;
import com.google.inject.TypeLiteral;
/**
* Configures the cloudstack connection.
*
*
* @author Adrian Cole
*/
@RequiresHttp
@ConfiguresRestClient
public class CloudStackRestClientModule extends RestClientModule<CloudStackClient, CloudStackAsyncClient> {
public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>>builder()//
public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>> builder()//
.put(ZoneClient.class, ZoneAsyncClient.class)//
.put(TemplateClient.class, TemplateAsyncClient.class)//
.put(OfferingClient.class, OfferingAsyncClient.class)//
@ -103,8 +118,11 @@ public class CloudStackRestClientModule extends RestClientModule<CloudStackClien
.put(HypervisorClient.class, HypervisorAsyncClient.class)//
.put(ConfigurationClient.class, ConfigurationAsyncClient.class)//
.put(AccountClient.class, AccountAsyncClient.class)//
.put(DomainAccountClient.class, DomainAccountAsyncClient.class)//
.put(GlobalAccountClient.class, GlobalAccountAsyncClient.class)//
.put(EventClient.class, EventAsyncClient.class)//
.put(LimitClient.class, LimitAsyncClient.class)//
.put(DomainLimitClient.class, DomainLimitAsyncClient.class)//
.put(SSHKeyPairClient.class, SSHKeyPairAsyncClient.class)//
.put(VMGroupClient.class, VMGroupAsyncClient.class)//
.put(ISOClient.class, ISOAsyncClient.class)//
@ -112,6 +130,26 @@ public class CloudStackRestClientModule extends RestClientModule<CloudStackClien
.put(SnapshotClient.class, SnapshotAsyncClient.class)//
.build();
@Override
protected void bindAsyncClient() {
// bind the user client (default)
super.bindAsyncClient();
// bind the domain admin client
BinderUtils.bindAsyncClient(binder(), CloudStackDomainAsyncClient.class);
// bind the global admin client
BinderUtils.bindAsyncClient(binder(), CloudStackGlobalAsyncClient.class);
}
@Override
protected void bindClient() {
// bind the user client (default)
super.bindClient();
// bind the domain admin client
BinderUtils.bindClient(binder(), CloudStackDomainClient.class, CloudStackDomainAsyncClient.class, DELEGATE_MAP);
// bind the domain admin client
BinderUtils.bindClient(binder(), CloudStackGlobalClient.class, CloudStackGlobalAsyncClient.class, DELEGATE_MAP);
}
public CloudStackRestClientModule() {
super(CloudStackClient.class, CloudStackAsyncClient.class, DELEGATE_MAP);
}
@ -119,6 +157,12 @@ public class CloudStackRestClientModule extends RestClientModule<CloudStackClien
@Override
protected void configure() {
bind(DateAdapter.class).to(Iso8601DateAdapter.class);
bind(new TypeLiteral<RestContext<CloudStackDomainClient, CloudStackDomainAsyncClient>>() {
}).to(new TypeLiteral<RestContextImpl<CloudStackDomainClient, CloudStackDomainAsyncClient>>() {
});
bind(new TypeLiteral<RestContext<CloudStackGlobalClient, CloudStackGlobalAsyncClient>>() {
}).to(new TypeLiteral<RestContextImpl<CloudStackGlobalClient, CloudStackGlobalAsyncClient>>() {
});
install(new CloudStackParserModule());
super.configure();
}

View File

@ -195,6 +195,10 @@ public class ResourceLimit implements Comparable<ResourceLimit> {
this.code = code;
}
public int getCode(){
return code;
}
@Override
public String toString() {
return name();

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 org.jclouds.cloudstack.filters.QuerySigner;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
/**
* Provides asynchronous access to CloudStack Account features available to Domain
* Admin users.
*
* @author Adrian Cole
* @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 DomainAccountAsyncClient extends AccountAsyncClient {
}

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 java.util.concurrent.TimeUnit;
import org.jclouds.concurrent.Timeout;
/**
* Provides synchronous access to CloudStack Account features available to Domain
* Admin users.
*
* @author Adrian Cole
* @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 DomainAccountClient extends AccountClient {
}

View File

@ -0,0 +1,57 @@
/**
* 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 javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.core.MediaType;
import org.jclouds.cloudstack.binders.ResourceLimitToQueryParams;
import org.jclouds.cloudstack.domain.ResourceLimit;
import org.jclouds.cloudstack.filters.QuerySigner;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Provides asynchronous access to CloudStack Limit features available to Domain
* Admin users.
*
* @author Adrian Cole
* @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 DomainLimitAsyncClient extends LimitAsyncClient {
/**
* @see DomainLimitClient#updateResourceLimit
*/
@GET
@QueryParams(keys = "command", values = "updateResourceLimit")
@SelectJson("resourcelimit")
@Consumes(MediaType.APPLICATION_JSON)
ListenableFuture<ResourceLimit> updateResourceLimit(
@BinderParam(ResourceLimitToQueryParams.class) ResourceLimit limit);
}

View File

@ -0,0 +1,45 @@
/**
* 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.ResourceLimit;
import org.jclouds.concurrent.Timeout;
/**
* Provides synchronous access to CloudStack Limit features available to Domain
* Admin users.
*
* @author Adrian Cole
* @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 DomainLimitClient extends LimitClient {
/**
* Updates resource limits for an account in a domain.
*
* @param limit
* what you are updating
*/
ResourceLimit updateResourceLimit(ResourceLimit limit);
}

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 org.jclouds.cloudstack.filters.QuerySigner;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
/**
* Provides asynchronous access to CloudStack Account features available to Global
* Admin users.
*
* @author Adrian Cole
* @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 GlobalAccountAsyncClient extends DomainAccountAsyncClient {
}

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 java.util.concurrent.TimeUnit;
import org.jclouds.concurrent.Timeout;
/**
* Provides synchronous access to CloudStack Account features available to Global
* Admin users.
*
* @author Adrian Cole
* @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 GlobalAccountClient extends DomainAccountClient {
}

View File

@ -18,14 +18,13 @@
*/
package org.jclouds.cloudstack.features;
import java.util.Set;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.core.MediaType;
import java.util.Set;
import com.google.common.util.concurrent.ListenableFuture;
import org.jclouds.cloudstack.domain.ResourceLimit;
import org.jclouds.cloudstack.domain.SshKeyPair;
import org.jclouds.cloudstack.filters.QuerySigner;
import org.jclouds.cloudstack.options.ListResourceLimitsOptions;
import org.jclouds.rest.annotations.ExceptionParser;
@ -34,6 +33,8 @@ import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Provides asynchronous access to CloudStack SSHKeyPair features.
*

View File

@ -18,6 +18,9 @@
*/
package org.jclouds.cloudstack.features;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.jclouds.cloudstack.domain.AsyncCreateResponse;
import org.jclouds.cloudstack.domain.Snapshot;
import org.jclouds.cloudstack.domain.SnapshotPolicy;
@ -27,10 +30,6 @@ import org.jclouds.cloudstack.options.ListSnapshotPoliciesOptions;
import org.jclouds.cloudstack.options.ListSnapshotsOptions;
import org.jclouds.concurrent.Timeout;
import javax.ws.rs.QueryParam;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* Provides synchronous access to CloudStack Snapshot features.
* <p/>

View File

@ -0,0 +1,49 @@
package org.jclouds.cloudstack.internal;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.cloudstack.CloudStackAsyncClient;
import org.jclouds.cloudstack.CloudStackClient;
import org.jclouds.cloudstack.CloudStackContext;
import org.jclouds.cloudstack.CloudStackDomainAsyncClient;
import org.jclouds.cloudstack.CloudStackDomainClient;
import org.jclouds.cloudstack.CloudStackGlobalAsyncClient;
import org.jclouds.cloudstack.CloudStackGlobalClient;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.Utils;
import org.jclouds.compute.internal.ComputeServiceContextImpl;
import org.jclouds.domain.Credentials;
import org.jclouds.rest.RestContext;
/**
* @author Adrian Cole
*/
@Singleton
public class CloudStackContextImpl extends ComputeServiceContextImpl<CloudStackClient, CloudStackAsyncClient> implements
CloudStackContext {
private final RestContext<CloudStackDomainClient, CloudStackDomainAsyncClient> domainContext;
private final RestContext<CloudStackGlobalClient, CloudStackGlobalAsyncClient> globalContext;
@Inject
public CloudStackContextImpl(ComputeService computeService, Map<String, Credentials> credentialStore, Utils utils,
@SuppressWarnings("rawtypes") RestContext providerSpecificContext,
RestContext<CloudStackDomainClient, CloudStackDomainAsyncClient> domainContext,
RestContext<CloudStackGlobalClient, CloudStackGlobalAsyncClient> globalContext) {
super(computeService, credentialStore, utils, providerSpecificContext);
this.domainContext = domainContext;
this.globalContext = globalContext;
}
@Override
public RestContext<CloudStackDomainClient, CloudStackDomainAsyncClient> getDomainContext() {
return domainContext;
}
@Override
public RestContext<CloudStackGlobalClient, CloudStackGlobalAsyncClient> getGlobalContext() {
return globalContext;
}
}

View File

@ -21,16 +21,17 @@ package org.jclouds.cloudstack;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import com.google.inject.TypeLiteral;
import org.jclouds.cloudstack.features.BaseCloudStackAsyncClientTest;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.google.inject.TypeLiteral;
/**
* Tests behavior of {@code CloudStackAsyncClient}
*
*
* @author Adrian Cole
*/
// NOTE:without testName, this will not call @Before* and fail w/NPE during
@ -40,6 +41,10 @@ public class CloudStackAsyncClientTest extends BaseCloudStackAsyncClientTest<Clo
private CloudStackAsyncClient asyncClient;
private CloudStackClient syncClient;
private CloudStackDomainAsyncClient domainAsyncClient;
private CloudStackDomainClient domainSyncClient;
private CloudStackGlobalAsyncClient globalAsyncClient;
private CloudStackGlobalClient globalSyncClient;
public void testSync() throws SecurityException, NoSuchMethodException, InterruptedException, ExecutionException {
assert syncClient.getZoneClient() != null;
@ -64,6 +69,11 @@ public class CloudStackAsyncClientTest extends BaseCloudStackAsyncClientTest<Clo
assert syncClient.getISOClient() != null;
assert syncClient.getVolumeClient() != null;
assert syncClient.getSnapshotClient() != null;
assert domainSyncClient.getLimitClient() != null;
assert domainSyncClient.getAccountClient() != null;
assert globalSyncClient.getAccountClient() != null;
}
public void testAsync() throws SecurityException, NoSuchMethodException, InterruptedException, ExecutionException {
@ -90,6 +100,10 @@ public class CloudStackAsyncClientTest extends BaseCloudStackAsyncClientTest<Clo
assert asyncClient.getVolumeClient() != null;
assert asyncClient.getSnapshotClient() != null;
assert domainAsyncClient.getLimitClient() != null;
assert domainAsyncClient.getAccountClient() != null;
assert globalAsyncClient.getAccountClient() != null;
}
@Override
@ -104,6 +118,10 @@ public class CloudStackAsyncClientTest extends BaseCloudStackAsyncClientTest<Clo
super.setupFactory();
asyncClient = injector.getInstance(CloudStackAsyncClient.class);
syncClient = injector.getInstance(CloudStackClient.class);
domainAsyncClient = injector.getInstance(CloudStackDomainAsyncClient.class);
domainSyncClient = injector.getInstance(CloudStackDomainClient.class);
globalAsyncClient = injector.getInstance(CloudStackGlobalAsyncClient.class);
globalSyncClient = injector.getInstance(CloudStackGlobalClient.class);
}
@Override

View File

@ -31,6 +31,9 @@ import java.util.logging.Logger;
import org.jclouds.cloudstack.CloudStackAsyncClient;
import org.jclouds.cloudstack.CloudStackClient;
import org.jclouds.cloudstack.CloudStackContext;
import org.jclouds.cloudstack.CloudStackDomainAsyncClient;
import org.jclouds.cloudstack.CloudStackDomainClient;
import org.jclouds.cloudstack.domain.Account;
import org.jclouds.cloudstack.domain.Template;
import org.jclouds.cloudstack.domain.User;
@ -45,7 +48,6 @@ import org.jclouds.cloudstack.predicates.UserPredicates;
import org.jclouds.cloudstack.predicates.VirtualMachineDestroyed;
import org.jclouds.cloudstack.predicates.VirtualMachineRunning;
import org.jclouds.compute.BaseVersionedServiceLiveTest;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.domain.Credentials;
@ -126,7 +128,7 @@ public class BaseCloudStackClientLiveTest extends BaseVersionedServiceLiveTest {
protected String prefix = System.getProperty("user.name");
protected ComputeServiceContext computeContext;
protected CloudStackContext computeContext;
protected RestContext<CloudStackClient, CloudStackAsyncClient> context;
protected CloudStackClient client;
protected CloudStackClient adminClient;
@ -139,7 +141,7 @@ public class BaseCloudStackClientLiveTest extends BaseVersionedServiceLiveTest {
protected RetryablePredicate<VirtualMachine> adminVirtualMachineRunning;
protected RetryablePredicate<VirtualMachine> virtualMachineDestroyed;
protected RetryablePredicate<VirtualMachine> adminVirtualMachineDestroyed;
protected SshClient.Factory sshFactory;
protected SshClient.Factory sshFactory;
protected String password = "password";
protected Injector injector;
@ -147,8 +149,8 @@ public class BaseCloudStackClientLiveTest extends BaseVersionedServiceLiveTest {
protected ReuseOrAssociateNewPublicIPAddress reuseOrAssociate;
protected boolean domainAdminEnabled;
protected ComputeServiceContext domainAdminComputeContext;
protected RestContext<CloudStackClient, CloudStackAsyncClient> domainAdminContext;
protected CloudStackContext domainAdminComputeContext;
protected RestContext<CloudStackDomainClient, CloudStackDomainAsyncClient> domainAdminContext;
protected CloudStackClient domainAdminClient;
protected User domainAdminUser;
@ -170,8 +172,8 @@ public class BaseCloudStackClientLiveTest extends BaseVersionedServiceLiveTest {
public void setupClient() {
setupCredentials();
computeContext = new ComputeServiceContextFactory().createContext(provider,
ImmutableSet.<Module> of(new Log4JLoggingModule(), new SshjSshClientModule()), setupProperties());
computeContext = CloudStackContext.class.cast(new ComputeServiceContextFactory().createContext(provider,
ImmutableSet.<Module> of(new Log4JLoggingModule(), new SshjSshClientModule()), setupProperties()));
context = computeContext.getProviderSpecificContext();
client = context.getApi();
user = verifyCurrentUserIsOfType(context, Account.Type.USER);
@ -179,9 +181,10 @@ public class BaseCloudStackClientLiveTest extends BaseVersionedServiceLiveTest {
domainAdminEnabled = setupAdminProperties() != null;
if (domainAdminEnabled) {
domainAdminComputeContext = new ComputeServiceContextFactory().createContext(provider,
ImmutableSet.<Module> of(new Log4JLoggingModule(), new SshjSshClientModule()), setupAdminProperties());
domainAdminContext = domainAdminComputeContext.getProviderSpecificContext();
domainAdminComputeContext = CloudStackContext.class.cast(new ComputeServiceContextFactory().createContext(
provider, ImmutableSet.<Module> of(new Log4JLoggingModule(), new SshjSshClientModule()),
setupAdminProperties()));
domainAdminContext = domainAdminComputeContext.getDomainContext();
domainAdminClient = domainAdminContext.getApi();
domainAdminUser = verifyCurrentUserIsOfType(domainAdminContext, Account.Type.DOMAIN_ADMIN);
adminClient = domainAdminContext.getApi();
@ -198,21 +201,21 @@ public class BaseCloudStackClientLiveTest extends BaseVersionedServiceLiveTest {
virtualMachineRunning = new RetryablePredicate<VirtualMachine>(new VirtualMachineRunning(client), 600, 5, 5,
TimeUnit.SECONDS);
injector.injectMembers(virtualMachineRunning);
adminVirtualMachineRunning = new RetryablePredicate<VirtualMachine>(new VirtualMachineRunning(adminClient), 600, 5, 5,
TimeUnit.SECONDS);
adminVirtualMachineRunning = new RetryablePredicate<VirtualMachine>(new VirtualMachineRunning(adminClient), 600,
5, 5, TimeUnit.SECONDS);
injector.injectMembers(adminVirtualMachineRunning);
virtualMachineDestroyed = new RetryablePredicate<VirtualMachine>(new VirtualMachineDestroyed(client), 600, 5, 5,
TimeUnit.SECONDS);
injector.injectMembers(virtualMachineDestroyed);
adminVirtualMachineDestroyed = new RetryablePredicate<VirtualMachine>(new VirtualMachineDestroyed(adminClient), 600, 5, 5,
TimeUnit.SECONDS);
adminVirtualMachineDestroyed = new RetryablePredicate<VirtualMachine>(new VirtualMachineDestroyed(adminClient),
600, 5, 5, TimeUnit.SECONDS);
injector.injectMembers(adminVirtualMachineDestroyed);
reuseOrAssociate = new ReuseOrAssociateNewPublicIPAddress(client, jobComplete);
injector.injectMembers(reuseOrAssociate);
}
protected static User verifyCurrentUserIsOfType(RestContext<CloudStackClient, CloudStackAsyncClient> context,
Account.Type type) {
protected static User verifyCurrentUserIsOfType(
RestContext<? extends CloudStackClient, ? extends CloudStackAsyncClient> context, Account.Type type) {
Iterable<User> users = Iterables.concat(context.getApi().getAccountClient().listAccounts());
Predicate<User> apiKeyMatches = UserPredicates.apiKeyEquals(context.getIdentity());
User currentUser;
@ -225,7 +228,7 @@ public class BaseCloudStackClientLiveTest extends BaseVersionedServiceLiveTest {
if (currentUser.getAccountType() != type) {
Logger.getAnonymousLogger().warning(
String.format("Expecting an user with type %s. Got: %s", type.toString(), currentUser.toString()));
String.format("Expecting an user with type %s. Got: %s", type.toString(), currentUser.toString()));
}
return currentUser;
}

View File

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

View File

@ -0,0 +1,31 @@
/**
* 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.testng.annotations.Test;
/**
* Tests behavior of {@code DomainAccountClient}
*
* @author Adrian Cole
*/
@Test(groups = "live", singleThreaded = true, testName = "DomainAccountClientLiveTest")
public class DomainAccountClientLiveTest extends BaseCloudStackClientLiveTest {
}

View File

@ -0,0 +1,66 @@
/**
* 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.io.IOException;
import java.lang.reflect.Method;
import org.jclouds.cloudstack.domain.ResourceLimit;
import org.jclouds.cloudstack.domain.ResourceLimit.ResourceType;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.functions.ParseFirstJsonValueNamed;
import org.jclouds.rest.functions.MapHttp4xxCodesToExceptions;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.testng.annotations.Test;
import com.google.inject.TypeLiteral;
/**
* Tests behavior of {@code DomainLimitAsyncClient}
*
* @author Adrian
*/
@Test(groups = "unit", testName = "DomainLimitAsyncClientTest")
public class DomainLimitAsyncClientTest extends BaseCloudStackAsyncClientTest<DomainLimitAsyncClient> {
public void testUpdateResourceLimit() throws SecurityException, NoSuchMethodException, IOException {
Method method = DomainLimitAsyncClient.class.getMethod("updateResourceLimit", ResourceLimit.class);
HttpRequest httpRequest = processor.createRequest(method,
ResourceLimit.builder().resourceType(ResourceType.SNAPSHOT).account("foo").domainId(100l).max(101).build());
assertRequestLineEquals(
httpRequest,
"GET http://localhost:8080/client/api?response=json&command=updateResourceLimit&resourcetype=3&account=foo&domainid=100&max=101 HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, MapHttp4xxCodesToExceptions.class);
checkFilters(httpRequest);
}
@Override
protected TypeLiteral<RestAnnotationProcessor<DomainLimitAsyncClient>> createTypeLiteral() {
return new TypeLiteral<RestAnnotationProcessor<DomainLimitAsyncClient>>() {
};
}
}

View File

@ -0,0 +1,31 @@
/**
* 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.testng.annotations.Test;
/**
* Tests behavior of {@code DomainLimitClient}
*
* @author Adrian Cole
*/
@Test(groups = "live", singleThreaded = true, testName = "DomainLimitClientLiveTest")
public class DomainLimitClientLiveTest extends BaseCloudStackClientLiveTest {
}

View File

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

View File

@ -0,0 +1,31 @@
/**
* 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.testng.annotations.Test;
/**
* Tests behavior of {@code GlobalAccountClient}
*
* @author Adrian Cole
*/
@Test(groups = "live", singleThreaded = true, testName = "GlobalAccountClientLiveTest")
public class GlobalAccountClientLiveTest extends BaseCloudStackClientLiveTest {
}

View File

@ -20,7 +20,6 @@ package org.jclouds.cloudstack.features;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.in;
import static com.google.common.base.Predicates.or;
import static com.google.common.collect.Iterables.find;
import static com.google.common.collect.Iterables.get;
import static com.google.common.collect.Iterables.getFirst;
@ -28,17 +27,14 @@ import static com.google.common.collect.Iterables.getOnlyElement;
import static com.google.common.collect.Sets.filter;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.logging.Logger;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import javax.annotation.Nullable;
import org.jclouds.cloudstack.CloudStackClient;
import org.jclouds.cloudstack.domain.AsyncCreateResponse;
import org.jclouds.cloudstack.domain.AsyncJob;
@ -62,14 +58,16 @@ import org.jclouds.util.InetAddresses2;
import org.testng.annotations.AfterGroups;
import org.testng.annotations.Test;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Throwables;
import com.google.common.collect.ComparisonChain;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Ordering;
import com.google.common.net.HostSpecifier;
import javax.annotation.Nullable;
/**
* Tests behavior of {@code VirtualMachineClientLiveTest}
*
@ -175,7 +173,6 @@ public class VirtualMachineClientLiveTest extends BaseCloudStackClientLiveTest {
return vm;
}
@SuppressWarnings("unchecked")
public void testCreateVirtualMachine() throws Exception {
Long templateId = (imageId != null && !"".equals(imageId)) ? new Long(imageId) : null;
vm = createVirtualMachine(client, templateId, jobComplete, virtualMachineRunning);

View File

@ -24,12 +24,13 @@ import static org.testng.AssertJUnit.assertNotSame;
import java.util.Set;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import org.jclouds.cloudstack.domain.AsyncCreateResponse;
import org.jclouds.cloudstack.domain.Volume;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
/**
* Tests behavior of {@code SSHKeyPairClient}
*