JCLOUDS-218. List templates in all known projects for CloudStack.

This commit is contained in:
Andrew Bayer 2013-11-25 16:43:46 -08:00
parent 981db34655
commit 8b94ee589b
13 changed files with 911 additions and 79 deletions

View File

@ -32,6 +32,7 @@ import org.jclouds.cloudstack.features.LoadBalancerApi;
import org.jclouds.cloudstack.features.NATApi;
import org.jclouds.cloudstack.features.NetworkApi;
import org.jclouds.cloudstack.features.OfferingApi;
import org.jclouds.cloudstack.features.ProjectApi;
import org.jclouds.cloudstack.features.SSHKeyPairApi;
import org.jclouds.cloudstack.features.SecurityGroupApi;
import org.jclouds.cloudstack.features.SessionApi;
@ -189,4 +190,10 @@ public interface CloudStackApi extends Closeable {
*/
@Delegate
SessionApi getSessionApi();
/**
* Provides synchronous access to Projects
*/
@Delegate
ProjectApi getProjectApi();
}

View File

@ -53,6 +53,7 @@ import org.jclouds.cloudstack.domain.IngressRule;
import org.jclouds.cloudstack.domain.Network;
import org.jclouds.cloudstack.domain.NetworkType;
import org.jclouds.cloudstack.domain.OSType;
import org.jclouds.cloudstack.domain.Project;
import org.jclouds.cloudstack.domain.SecurityGroup;
import org.jclouds.cloudstack.domain.ServiceOffering;
import org.jclouds.cloudstack.domain.SshKeyPair;
@ -71,6 +72,7 @@ import org.jclouds.cloudstack.functions.ZoneIdToZone;
import org.jclouds.cloudstack.predicates.JobComplete;
import org.jclouds.cloudstack.suppliers.GetCurrentUser;
import org.jclouds.cloudstack.suppliers.NetworksForCurrentUser;
import org.jclouds.cloudstack.suppliers.ProjectsForCurrentUser;
import org.jclouds.cloudstack.suppliers.ZoneIdToZoneSupplier;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.ComputeServiceAdapter;
@ -220,6 +222,15 @@ public class CloudStackComputeServiceContextModule extends
seconds, TimeUnit.SECONDS);
}
@Provides
@Singleton
@Memoized
public Supplier<Map<String, Project>> listProjects(AtomicReference<AuthorizationException> authException, @Named(PROPERTY_SESSION_INTERVAL) long seconds,
final ProjectsForCurrentUser projectsForCurrentUser) {
return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException, projectsForCurrentUser,
seconds, TimeUnit.SECONDS);
}
@Provides
@Singleton
@Memoized

View File

@ -19,9 +19,11 @@ package org.jclouds.cloudstack.compute.strategy;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.contains;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.get;
import static com.google.common.collect.Iterables.transform;
import static org.jclouds.cloudstack.options.DeployVirtualMachineOptions.Builder.displayName;
import static org.jclouds.cloudstack.options.ListTemplatesOptions.Builder.id;
import static org.jclouds.cloudstack.predicates.TemplatePredicates.isReady;
@ -31,7 +33,6 @@ import static org.jclouds.ssh.SshKeys.fingerprintPrivateKey;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import javax.annotation.Resource;
import javax.inject.Inject;
@ -46,6 +47,7 @@ import org.jclouds.cloudstack.domain.FirewallRule;
import org.jclouds.cloudstack.domain.IPForwardingRule;
import org.jclouds.cloudstack.domain.Network;
import org.jclouds.cloudstack.domain.NetworkType;
import org.jclouds.cloudstack.domain.Project;
import org.jclouds.cloudstack.domain.PublicIPAddress;
import org.jclouds.cloudstack.domain.SecurityGroup;
import org.jclouds.cloudstack.domain.ServiceOffering;
@ -55,12 +57,14 @@ import org.jclouds.cloudstack.domain.VirtualMachine;
import org.jclouds.cloudstack.domain.Zone;
import org.jclouds.cloudstack.domain.ZoneAndName;
import org.jclouds.cloudstack.domain.ZoneSecurityGroupNamePortsCidrs;
import org.jclouds.cloudstack.features.TemplateApi;
import org.jclouds.cloudstack.functions.CreateFirewallRulesForIP;
import org.jclouds.cloudstack.functions.CreatePortForwardingRulesForIP;
import org.jclouds.cloudstack.functions.StaticNATVirtualMachineInNetwork;
import org.jclouds.cloudstack.functions.StaticNATVirtualMachineInNetwork.Factory;
import org.jclouds.cloudstack.options.DeployVirtualMachineOptions;
import org.jclouds.cloudstack.options.ListFirewallRulesOptions;
import org.jclouds.cloudstack.options.ListTemplatesOptions;
import org.jclouds.cloudstack.strategy.BlockUntilJobCompletesAndReturnResult;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.ComputeServiceAdapter;
@ -70,14 +74,13 @@ import org.jclouds.domain.Credentials;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.logging.Logger;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.base.Throwables;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.google.common.collect.ImmutableSet.Builder;
import com.google.common.collect.Sets;
import com.google.common.primitives.Ints;
/**
@ -95,6 +98,7 @@ public class CloudStackComputeServiceAdapter implements
private final CloudStackApi client;
private final Predicate<String> jobComplete;
private final Supplier<Map<String, Network>> networkSupplier;
private final Supplier<Map<String, Project>> projectSupplier;
private final BlockUntilJobCompletesAndReturnResult blockUntilJobCompletesAndReturnResult;
private final Factory staticNATVMInNetwork;
private final CreatePortForwardingRulesForIP setupPortForwardingRulesForIP;
@ -110,6 +114,7 @@ public class CloudStackComputeServiceAdapter implements
@Inject
public CloudStackComputeServiceAdapter(CloudStackApi client, Predicate<String> jobComplete,
@Memoized Supplier<Map<String, Network>> networkSupplier,
@Memoized Supplier<Map<String, Project>> projectSupplier,
BlockUntilJobCompletesAndReturnResult blockUntilJobCompletesAndReturnResult,
StaticNATVirtualMachineInNetwork.Factory staticNATVMInNetwork,
CreatePortForwardingRulesForIP setupPortForwardingRulesForIP,
@ -124,6 +129,7 @@ public class CloudStackComputeServiceAdapter implements
this.client = checkNotNull(client, "client");
this.jobComplete = checkNotNull(jobComplete, "jobComplete");
this.networkSupplier = checkNotNull(networkSupplier, "networkSupplier");
this.projectSupplier = checkNotNull(projectSupplier, "projectSupplier");
this.blockUntilJobCompletesAndReturnResult = checkNotNull(blockUntilJobCompletesAndReturnResult,
"blockUntilJobCompletesAndReturnResult");
this.staticNATVMInNetwork = checkNotNull(staticNATVMInNetwork, "staticNATVMInNetwork");
@ -270,9 +276,14 @@ public class CloudStackComputeServiceAdapter implements
@Override
public Iterable<Template> listImages() {
// TODO: we may need to filter these further
// we may also want to see if we can work with ssh keys
return filter(client.getTemplateApi().listTemplates(), isReady());
TemplateApi templateApi = client.getTemplateApi();
ImmutableSet.Builder<Template> templates = ImmutableSet.builder();
templates.addAll(templateApi.listTemplates());
for (String project : projectSupplier.get().keySet()) {
templates.addAll(templateApi.listTemplates(ListTemplatesOptions.Builder.projectId(project)));
}
return filter(templates.build(), isReady());
}
@Override

View File

@ -0,0 +1,243 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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 static com.google.common.base.Preconditions.checkNotNull;
import java.beans.ConstructorProperties;
import org.jclouds.javax.annotation.Nullable;
import com.google.common.base.CaseFormat;
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
/**
* Representation of the API project response
*
* @author Andrew Bayer
*/
public class Project implements Comparable<Project> {
public static enum State {
ACTIVE, DISABLED, SUSPENDED, UNRECOGNIZED;
@Override
public String toString() {
return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_HYPHEN, name());
}
public static State fromValue(String state) {
try {
return valueOf(CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(state, "state")));
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}
public static Builder<?> builder() {
return new ConcreteBuilder();
}
public Builder<?> toBuilder() {
return new ConcreteBuilder().fromDomain(this);
}
public abstract static class Builder<T extends Builder<T>> {
protected abstract T self();
protected String id;
protected String account;
protected String displayText;
protected String domain;
protected String domainId;
protected String name;
protected State state;
/**
* @see org.jclouds.cloudstack.domain.Project#getId()
*/
public T id(String id) {
this.id = id;
return self();
}
/**
* @see org.jclouds.cloudstack.domain.Project#getName()
*/
public T name(String name) {
this.name = name;
return self();
}
/**
* @see org.jclouds.cloudstack.domain.Project#getDomainId()
*/
public T domainId(String domainId) {
this.domainId = domainId;
return self();
}
/**
* @see org.jclouds.cloudstack.domain.Project#getDomain()
*/
public T domain(String domain) {
this.domain = domain;
return self();
}
/**
* @see org.jclouds.cloudstack.domain.Project#getAccount()
*/
public T account(String account) {
this.account = account;
return self();
}
/**
* @see org.jclouds.cloudstack.domain.Project#getDisplayText()
*/
public T displayText(String displayText) {
this.displayText = displayText;
return self();
}
/**
* @see org.jclouds.cloudstack.domain.Project#getState()
*/
public T state(State state) {
this.state = state;
return self();
}
public Project build() {
return new Project(id, account, displayText, domain, domainId, name, state);
}
public T fromDomain(Project in) {
return this
.id(in.getId())
.account(in.getAccount())
.displayText(in.getDisplayText())
.domain(in.getDomain())
.domainId(in.getDomainId())
.name(in.getName())
.state(in.getState());
}
}
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
@Override
protected ConcreteBuilder self() {
return this;
}
}
private final String id;
private final String account;
private final String displayText;
private final String domain;
private final String domainId;
private final String name;
private final State state;
@ConstructorProperties({
"id", "account", "displaytext", "domain", "domainid", "name", "state"
})
protected Project(String id, String account, String displayText, String domain, String domainId,
String name, State state) {
this.id = checkNotNull(id, "id");
this.account = account;
this.displayText = displayText;
this.domain = domain;
this.domainId = domainId;
this.name = name;
this.state = checkNotNull(state, "state");
}
public String getId() {
return this.id;
}
@Nullable
public String getAccount() {
return this.account;
}
@Nullable
public String getDisplayText() {
return this.displayText;
}
@Nullable
public String getDomain() {
return this.domain;
}
@Nullable
public String getDomainId() {
return this.domainId;
}
@Nullable
public String getName() {
return this.name;
}
public State getState() {
return this.state;
}
@Override
public int hashCode() {
return Objects.hashCode(id, account, displayText, domain, domainId, name, state);
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Project that = Project.class.cast(obj);
return Objects.equal(this.id, that.id)
&& Objects.equal(this.account, that.account)
&& Objects.equal(this.displayText, that.displayText)
&& Objects.equal(this.domain, that.domain)
&& Objects.equal(this.domainId, that.domainId)
&& Objects.equal(this.name, that.name)
&& Objects.equal(this.state, that.state);
}
protected ToStringHelper string() {
return Objects.toStringHelper(this).omitNullValues()
.add("id", id).add("account", account).add("displayText", displayText)
.add("domain", domain).add("domainId", domainId).add("name", name).add("state", state);
}
@Override
public String toString() {
return string().toString();
}
@Override
public int compareTo(Project other) {
return id.compareTo(other.getId());
}
}

View File

@ -0,0 +1,77 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.Set;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.cloudstack.domain.Project;
import org.jclouds.cloudstack.filters.AuthenticationFilter;
import org.jclouds.cloudstack.options.ListProjectsOptions;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.OnlyElement;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
/**
* Provides synchronous access to CloudStack project features.
*
* @author Andrew Bayer
* @see <a
* href="http://download.cloud.com/releases/3.0.6/api_3.0.6/TOC_Root_Admin.html"
* />
*/
@RequestFilters(AuthenticationFilter.class)
@QueryParams(keys = "response", values = "json")
public interface ProjectApi {
/**
* Lists the projects this account has access to.
*
* @param options if present, how to constrain the list
*/
@Named("listProjects")
@GET
@QueryParams(keys = { "command", "listAll" }, values = { "listProjects", "true" })
@SelectJson("project")
@Consumes(MediaType.APPLICATION_JSON)
@Fallback(EmptySetOnNotFoundOr404.class)
Set<Project> listProjects(ListProjectsOptions... options);
/**
* gets a specific Project by id
*
* @param id
* Project to get
* @return Project or null if not found */
@Named("listProjects")
@GET
@QueryParams(keys = { "command", "listAll" }, values = { "listProjects", "true" })
@SelectJson("project")
@OnlyElement
@Consumes(MediaType.APPLICATION_JSON)
@Fallback(NullOnNotFoundOr404.class)
Project getProject(@QueryParam("id") String id);
}

View File

@ -0,0 +1,171 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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 account information is returned
*
* @see <a
* href="http://download.cloud.com/releases/3.0.6/api_3.0.6/root_admin/listProjects.html"
* />
* @author Andrew Bayer
*/
public class ListProjectsOptions extends AccountInDomainOptions {
public static final ListProjectsOptions NONE = new ListProjectsOptions();
/**
* @param id
* list projects by project ID
*/
public ListProjectsOptions id(String id) {
this.queryParameters.replaceValues("id", ImmutableSet.of(id));
return this;
}
/**
* @param name
* list project by project name
*/
public ListProjectsOptions name(String name) {
this.queryParameters.replaceValues("name", ImmutableSet.of(name));
return this;
}
/**
* @param state
* list projects by state. Valid states are enabled, disabled, and
* locked.
*/
public ListProjectsOptions state(String state) {
this.queryParameters.replaceValues("state", ImmutableSet.of(state));
return this;
}
/**
* @param displayText
* list projects by displayText.
*/
public ListProjectsOptions displayText(String displayText) {
this.queryParameters.replaceValues("displaytext", ImmutableSet.of(displayText));
return this;
}
/**
* @param keyword
* list projects by keyword.
*/
public ListProjectsOptions keyword(String keyword) {
this.queryParameters.replaceValues("keyword", ImmutableSet.of(keyword));
return this;
}
/**
* @param recursive
* defaults to false, but if true, lists all projects from the
* parent specified by the domain id till leaves.
*/
public ListProjectsOptions recursive(boolean recursive) {
this.queryParameters.replaceValues("isrecursive", ImmutableSet.of(recursive + ""));
return this;
}
public static class Builder {
/**
* @see org.jclouds.cloudstack.options.ListProjectsOptions#accountInDomain(String, String)
*/
public static ListProjectsOptions accountInDomain(String project, String domain) {
ListProjectsOptions options = new ListProjectsOptions();
return options.accountInDomain(project, domain);
}
/**
* @see org.jclouds.cloudstack.options.ListProjectsOptions#domainId
*/
public static ListProjectsOptions domainId(String domainId) {
ListProjectsOptions options = new ListProjectsOptions();
return options.domainId(domainId);
}
/**
* @see org.jclouds.cloudstack.options.ListProjectsOptions#id
*/
public static ListProjectsOptions id(String id) {
ListProjectsOptions options = new ListProjectsOptions();
return options.id(id);
}
/**
* @see org.jclouds.cloudstack.options.ListProjectsOptions#name
*/
public static ListProjectsOptions name(String name) {
ListProjectsOptions options = new ListProjectsOptions();
return options.name(name);
}
/**
* @see org.jclouds.cloudstack.options.ListProjectsOptions#state
*/
public static ListProjectsOptions state(String state) {
ListProjectsOptions options = new ListProjectsOptions();
return options.state(state);
}
/**
* @see org.jclouds.cloudstack.options.ListProjectsOptions#displayText(String)
*/
public static ListProjectsOptions displayText(String displayText) {
ListProjectsOptions options = new ListProjectsOptions();
return options.displayText(displayText);
}
/**
* @see org.jclouds.cloudstack.options.ListProjectsOptions#keyword(String)
*/
public static ListProjectsOptions keyword(String keyword) {
ListProjectsOptions options = new ListProjectsOptions();
return options.keyword(keyword);
}
/**
* @see org.jclouds.cloudstack.options.ListProjectsOptions#recursive
*/
public static ListProjectsOptions recursive(boolean recursive) {
ListProjectsOptions options = new ListProjectsOptions();
return options.recursive(recursive);
}
}
/**
* {@inheritDoc}
*/
@Override
public ListProjectsOptions accountInDomain(String account, String domain) {
return ListProjectsOptions.class.cast(super.accountInDomain(account, domain));
}
/**
* {@inheritDoc}
*/
@Override
public ListProjectsOptions domainId(String domainId) {
return ListProjectsOptions.class.cast(super.domainId(domainId));
}
}

View File

@ -0,0 +1,64 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.suppliers;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.cloudstack.options.ListProjectsOptions.Builder.accountInDomain;
import java.util.Map;
import javax.inject.Inject;
import org.jclouds.cloudstack.CloudStackApi;
import org.jclouds.cloudstack.domain.Project;
import org.jclouds.cloudstack.domain.User;
import org.jclouds.cloudstack.features.ProjectApi;
import org.jclouds.collect.Memoized;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.collect.Maps;
/**
*
* @author Andrew Bayer
*/
public class ProjectsForCurrentUser implements Supplier<Map<String, Project>> {
private final CloudStackApi api;
private final Supplier<User> currentUserSupplier;
@Inject
public ProjectsForCurrentUser(CloudStackApi api, @Memoized Supplier<User> currentUserSupplier) {
this.api = checkNotNull(api, "api");
this.currentUserSupplier = checkNotNull(currentUserSupplier, "currentUserSupplier");
}
@Override
public Map<String, Project> get() {
User currentUser = currentUserSupplier.get();
ProjectApi projectApi = api.getProjectApi();
return Maps.uniqueIndex(
projectApi.listProjects(accountInDomain(currentUser.getAccount(), currentUser.getDomainId())),
new Function<Project, String>() {
@Override
public String apply(Project arg0) {
return arg0.getId();
}
});
}
}

View File

@ -110,17 +110,18 @@ public class CloudStackComputeServiceAdapterExpectTest extends BaseCloudStackCom
.build();
Map<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder()
.put(listTemplates, listTemplatesResponse)
.put(listOsTypes, listOsTypesResponse)
.put(listOsCategories, listOsCategoriesResponse)
.put(listZones, listZonesResponse)
.put(listServiceOfferings, listServiceOfferingsResponse)
.put(listAccounts, listAccountsResponse)
.put(listNetworks, listNetworksResponse)
.put(getZone, getZoneResponse)
.put(deployVM, deployVMResponse)
.put(queryAsyncJobResult, queryAsyncJobResultResponse)
.build();
.put(listProjects, listProjectsResponse)
.put(listTemplates, listTemplatesResponse)
.put(listOsTypes, listOsTypesResponse)
.put(listOsCategories, listOsCategoriesResponse)
.put(listZones, listZonesResponse)
.put(listServiceOfferings, listServiceOfferingsResponse)
.put(listAccounts, listAccountsResponse)
.put(listNetworks, listNetworksResponse)
.put(getZone, getZoneResponse)
.put(deployVM, deployVMResponse)
.put(queryAsyncJobResult, queryAsyncJobResultResponse)
.build();
Injector forNode = requestsSendResponses(requestResponseMap);
@ -154,17 +155,18 @@ public class CloudStackComputeServiceAdapterExpectTest extends BaseCloudStackCom
.build();
Map<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder()
.put(listTemplates, listTemplatesResponse)
.put(listOsTypes, listOsTypesResponse)
.put(listOsCategories, listOsCategoriesResponse)
.put(listZones, listZonesResponse)
.put(listServiceOfferings, listServiceOfferingsResponse)
.put(listAccounts, listAccountsResponse)
.put(listNetworks, listNetworksResponse)
.put(getZone, getZoneResponse)
.put(deployVM, deployVMResponse)
.put(queryAsyncJobResult, queryAsyncJobResultResponse)
.build();
.put(listProjects, listProjectsResponse)
.put(listTemplates, listTemplatesResponse)
.put(listOsTypes, listOsTypesResponse)
.put(listOsCategories, listOsCategoriesResponse)
.put(listZones, listZonesResponse)
.put(listServiceOfferings, listServiceOfferingsResponse)
.put(listAccounts, listAccountsResponse)
.put(listNetworks, listNetworksResponse)
.put(getZone, getZoneResponse)
.put(deployVM, deployVMResponse)
.put(queryAsyncJobResult, queryAsyncJobResultResponse)
.build();
Injector forKeyPair = requestsSendResponses(requestResponseMap);
@ -201,18 +203,19 @@ public class CloudStackComputeServiceAdapterExpectTest extends BaseCloudStackCom
.build();
Map<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder()
.put(listTemplates, listTemplatesResponse)
.put(listOsTypes, listOsTypesResponse)
.put(listOsCategories, listOsCategoriesResponse)
.put(listZones, listZonesResponse)
.put(listServiceOfferings, listServiceOfferingsResponse)
.put(listAccounts, listAccountsResponse)
.put(listNetworks, listNetworksResponse)
.put(getZone, getZoneResponse)
.put(deployVM, deployVMResponse)
.put(createSSHKeyPair, createSSHKeyPairResponse)
.put(queryAsyncJobResult, queryAsyncJobResultResponse)
.build();
.put(listProjects, listProjectsResponse)
.put(listTemplates, listTemplatesResponse)
.put(listOsTypes, listOsTypesResponse)
.put(listOsCategories, listOsCategoriesResponse)
.put(listZones, listZonesResponse)
.put(listServiceOfferings, listServiceOfferingsResponse)
.put(listAccounts, listAccountsResponse)
.put(listNetworks, listNetworksResponse)
.put(getZone, getZoneResponse)
.put(deployVM, deployVMResponse)
.put(createSSHKeyPair, createSSHKeyPairResponse)
.put(queryAsyncJobResult, queryAsyncJobResultResponse)
.build();
Injector forKeyPair = requestsSendResponses(requestResponseMap);
@ -247,17 +250,18 @@ public class CloudStackComputeServiceAdapterExpectTest extends BaseCloudStackCom
.build();
Map<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder()
.put(listTemplates, listTemplatesResponse)
.put(listOsTypes, listOsTypesResponse)
.put(listOsCategories, listOsCategoriesResponse)
.put(listZones, listZonesResponse)
.put(listServiceOfferings, listServiceOfferingsResponse)
.put(listAccounts, listAccountsResponse)
.put(listNetworks, listNetworksWithSecurityGroupsResponse)
.put(getZoneWithSecurityGroups, getZoneWithSecurityGroupsResponse)
.put(deployVM, deployVMResponse)
.put(queryAsyncJobResult, queryAsyncJobResultResponse)
.build();
.put(listProjects, listProjectsResponse)
.put(listTemplates, listTemplatesResponse)
.put(listOsTypes, listOsTypesResponse)
.put(listOsCategories, listOsCategoriesResponse)
.put(listZones, listZonesResponse)
.put(listServiceOfferings, listServiceOfferingsResponse)
.put(listAccounts, listAccountsResponse)
.put(listNetworks, listNetworksWithSecurityGroupsResponse)
.put(getZoneWithSecurityGroups, getZoneWithSecurityGroupsResponse)
.put(deployVM, deployVMResponse)
.put(queryAsyncJobResult, queryAsyncJobResultResponse)
.build();
Injector forKeyPair = requestsSendResponses(requestResponseMap);
@ -299,6 +303,7 @@ public class CloudStackComputeServiceAdapterExpectTest extends BaseCloudStackCom
.build();
Map<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder()
.put(listProjects, listProjectsResponse)
.put(listTemplates, listTemplatesResponse)
.put(listOsTypes, listOsTypesResponse)
.put(listOsCategories, listOsCategoriesResponse)
@ -353,21 +358,22 @@ public class CloudStackComputeServiceAdapterExpectTest extends BaseCloudStackCom
.build();
Map<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder()
.put(listTemplates, listTemplatesResponse)
.put(listOsTypes, listOsTypesResponse)
.put(listOsCategories, listOsCategoriesResponse)
.put(listZones, listZonesResponse)
.put(listServiceOfferings, listServiceOfferingsResponse)
.put(listAccounts, listAccountsResponse)
.put(listNetworks, listNetworksWithSecurityGroupsResponse)
.put(getZoneWithSecurityGroups, getZoneWithSecurityGroupsResponse)
.put(deployVM, deployVMResponse)
.put(queryAsyncJobResult, queryAsyncJobResultSecurityGroupResponse)
.put(queryAsyncJobResultAuthorizeIngress, queryAsyncJobResultAuthorizeIngressResponse)
.put(getSecurityGroup, getSecurityGroupResponse)
.put(createSecurityGroup, createSecurityGroupResponse)
.put(authorizeIngress, authorizeIngressResponse)
.build();
.put(listProjects, listProjectsResponse)
.put(listTemplates, listTemplatesResponse)
.put(listOsTypes, listOsTypesResponse)
.put(listOsCategories, listOsCategoriesResponse)
.put(listZones, listZonesResponse)
.put(listServiceOfferings, listServiceOfferingsResponse)
.put(listAccounts, listAccountsResponse)
.put(listNetworks, listNetworksWithSecurityGroupsResponse)
.put(getZoneWithSecurityGroups, getZoneWithSecurityGroupsResponse)
.put(deployVM, deployVMResponse)
.put(queryAsyncJobResult, queryAsyncJobResultSecurityGroupResponse)
.put(queryAsyncJobResultAuthorizeIngress, queryAsyncJobResultAuthorizeIngressResponse)
.put(getSecurityGroup, getSecurityGroupResponse)
.put(createSecurityGroup, createSecurityGroupResponse)
.put(authorizeIngress, authorizeIngressResponse)
.build();
Injector forKeyPair = requestsSendResponses(requestResponseMap);
@ -411,17 +417,18 @@ public class CloudStackComputeServiceAdapterExpectTest extends BaseCloudStackCom
.build();
Map<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder()
.put(listTemplates, listTemplatesResponse)
.put(listOsTypes, listOsTypesResponse)
.put(listOsCategories, listOsCategoriesResponse)
.put(listZones, listZonesResponse)
.put(listServiceOfferings, listServiceOfferingsResponse)
.put(listAccounts, listAccountsResponse)
.put(listNetworks, listNetworksResponse)
.put(getZone, getZoneResponse)
.put(deployVM, deployVMResponse)
.put(queryAsyncJobResult, queryAsyncJobResultResponse)
.build();
.put(listProjects, listProjectsResponse)
.put(listTemplates, listTemplatesResponse)
.put(listOsTypes, listOsTypesResponse)
.put(listOsCategories, listOsCategoriesResponse)
.put(listZones, listZonesResponse)
.put(listServiceOfferings, listServiceOfferingsResponse)
.put(listAccounts, listAccountsResponse)
.put(listNetworks, listNetworksResponse)
.put(getZone, getZoneResponse)
.put(deployVM, deployVMResponse)
.put(queryAsyncJobResult, queryAsyncJobResultResponse)
.build();
Injector forKeyPair = requestsSendResponses(requestResponseMap);

View File

@ -0,0 +1,79 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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 static org.testng.Assert.assertEquals;
import java.util.Set;
import org.jclouds.cloudstack.CloudStackContext;
import org.jclouds.cloudstack.domain.Project;
import org.jclouds.cloudstack.internal.BaseCloudStackExpectTest;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
/**
* Test the CloudStack ProjectApi
*
* @author Andrew Bayer
*/
@Test(groups = "unit", testName = "ProjectApiExpectTest")
public class ProjectApiExpectTest extends BaseCloudStackExpectTest<ProjectApi> {
public void testListProjectsWhenResponseIs2xx() {
ProjectApi client = requestSendsResponse(
HttpRequest.builder()
.method("GET")
.endpoint("http://localhost:8080/client/api?response=json&command=listProjects&listAll=true&apiKey=identity&signature=vtCqaYXfXttr6mD18Es0e22QBIQ%3D")
.addHeader("Accept", "application/json")
.build(),
HttpResponse.builder()
.statusCode(200)
.payload(payloadFromResource("/listprojectsresponse.json"))
.build());
Set<Project> projects = ImmutableSet.of(
Project.builder()
.id("489da162-0b77-489d-b044-ce39aa018b1f")
.account("thyde")
.displayText("")
.domain("ROOT")
.domainId("41a4917b-7952-499d-ba7f-4c57464d3dc8")
.name("NN-HA-T1")
.state(Project.State.ACTIVE).build(),
Project.builder()
.id("1c11f22c-15ac-4fa7-b833-4d748df317b7")
.account("prasadm")
.displayText("Hive")
.domain("ROOT")
.domainId("41a4917b-7952-499d-ba7f-4c57464d3dc8")
.name("hive")
.state(Project.State.ACTIVE).build());
assertEquals(client.listProjects(), projects);
}
@Override
protected ProjectApi clientFrom(CloudStackContext context) {
return context.getApi().getProjectApi();
}
}

View File

@ -0,0 +1,48 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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 static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import org.jclouds.cloudstack.domain.Project;
import org.jclouds.cloudstack.internal.BaseCloudStackApiLiveTest;
import org.testng.annotations.Test;
/**
* Tests behavior of {@code ProjectApi}
*
* @author Andrew Bayer
*/
@Test(groups = "live", singleThreaded = true, testName = "ProjectApiLiveTest")
public class ProjectApiLiveTest extends BaseCloudStackApiLiveTest {
@Test
public void testListAccounts() throws Exception {
for (Project project : client.getProjectApi().listProjects())
checkProject(project);
}
protected void checkProject(Project project) {
assertNotNull(project.getId());
assertEquals(project.toString(), client.getProjectApi().getProject(project.getId()).toString());
assertTrue(project.getState() != null);
assertTrue(project.getState() != Project.State.UNRECOGNIZED);
}
}

View File

@ -0,0 +1,98 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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 static org.jclouds.reflect.Reflection2.method;
import java.io.IOException;
import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.cloudstack.internal.BaseCloudStackApiTest;
import org.jclouds.cloudstack.options.ListProjectsOptions;
import org.jclouds.functions.IdentityFunction;
import org.jclouds.http.functions.ParseFirstJsonValueNamed;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.testng.annotations.Test;
import com.google.common.base.Functions;
import com.google.common.collect.ImmutableList;
import com.google.common.reflect.Invokable;
/**
* Tests behavior of {@code ProjectApi}
*
* @author Andrew Bayer
*/
// NOTE:without testName, this will not call @Before* and fail w/NPE during
// surefire
@Test(groups = "unit", testName = "ProjectApiTest")
public class ProjectApiTest extends BaseCloudStackApiTest<ProjectApi> {
public void testListProjects() throws SecurityException, NoSuchMethodException, IOException {
Invokable<?, ?> method = method(ProjectApi.class, "listProjects", ListProjectsOptions[].class);
GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.of());
assertRequestLineEquals(httpRequest,
"GET http://localhost:8080/client/api?response=json&command=listProjects&listAll=true HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class);
assertSaxResponseParserClassEquals(method, null);
assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
checkFilters(httpRequest);
}
public void testListProjectsOptions() throws SecurityException, NoSuchMethodException, IOException {
Invokable<?, ?> method = method(ProjectApi.class, "listProjects", ListProjectsOptions[].class);
GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(
ListProjectsOptions.Builder.accountInDomain("jclouds", "123")));
assertRequestLineEquals(httpRequest,
"GET http://localhost:8080/client/api?response=json&command=listProjects&listAll=true&account=jclouds&domainid=123 HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class);
assertSaxResponseParserClassEquals(method, null);
assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
checkFilters(httpRequest);
}
public void testGetAccount() throws SecurityException, NoSuchMethodException, IOException {
Invokable<?, ?> method = method(ProjectApi.class, "getProject", String.class);
GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of("3"));
assertRequestLineEquals(httpRequest,
"GET http://localhost:8080/client/api?response=json&command=listProjects&listAll=true&id=3 HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest,
Functions.compose(IdentityFunction.INSTANCE, IdentityFunction.INSTANCE).getClass());
assertSaxResponseParserClassEquals(method, null);
assertFallbackClassEquals(method, NullOnNotFoundOr404.class);
checkFilters(httpRequest);
}
}

View File

@ -47,7 +47,22 @@ public abstract class BaseCloudStackComputeServiceContextExpectTest<T> extends B
protected final HttpResponse listTemplatesResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/listtemplatesresponse.json"))
.build();
protected final HttpRequest listProjects = HttpRequest.builder().method("GET")
.endpoint("http://localhost:8080/client/api")
.addQueryParam("response", "json")
.addQueryParam("command", "listProjects")
.addQueryParam("listAll", "true")
.addQueryParam("account", "jclouds")
.addQueryParam("domainid", "457")
.addQueryParam("apiKey", "APIKEY")
.addQueryParam("signature", "yAx1XbtjeEhdBQCNP0OLyWWAFCw%3D")
.addHeader("Accept", "application/json")
.build();
protected final HttpResponse listProjectsResponse = HttpResponse.builder().statusCode(200)
.build();
protected final HttpRequest listOsTypes = HttpRequest.builder().method("GET")
.endpoint("http://localhost:8080/client/api")
.addQueryParam("response", "json")

View File

@ -0,0 +1 @@
{ "listprojectsresponse" : { "count":2 ,"project" : [ {"id":"489da162-0b77-489d-b044-ce39aa018b1f","name":"NN-HA-T1","displaytext":"","domainid":"41a4917b-7952-499d-ba7f-4c57464d3dc8","domain":"ROOT","account":"thyde","state":"Active"}, {"id":"1c11f22c-15ac-4fa7-b833-4d748df317b7","name":"hive","displaytext":"Hive","domainid":"41a4917b-7952-499d-ba7f-4c57464d3dc8","domain":"ROOT","account":"prasadm","state":"Active"} ] } }