JCLOUDS-101 - Add SecurityGroupExtension for compute

- Adds the SecurityGroupExtension to compute, with tests and stub
support.
- Gets everything else to actually build against this.
- Unifies on compute's IpPermission/IpProtocol, eliminating EC2's.
- Converters from EC2/Nova/CloudStack SecurityGroup (and rules, for
the latter two) to the compute SecurityGroup (and rules, etc).
- EC2SecurityGroupExtension and tests.
- AWSEC2SecurityGroupExtension and tests - depends on JCLOUDS-99.
This commit is contained in:
Andrew Bayer 2013-06-26 13:48:17 -07:00
parent a906f9f4ec
commit 5f524ee6c9
89 changed files with 3935 additions and 317 deletions

View File

@ -43,6 +43,7 @@ import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.compute.internal.BaseComputeService;
import org.jclouds.compute.internal.PersistNodeCredentials;
@ -113,12 +114,13 @@ public class CloudStackComputeService extends BaseComputeService {
Function<Set<? extends NodeMetadata>, Multimap<String, String>> orphanedGroupsByZoneId,
GroupNamingConvention.Factory namingConvention,
Supplier<LoadingCache<String, Zone>> zoneIdToZone,
Optional<ImageExtension> imageExtension) {
Optional<ImageExtension> imageExtension,
Optional<SecurityGroupExtension> securityGroupExtension) {
super(context, credentialStore, images, sizes, locations, listNodesStrategy, getImageStrategy,
getNodeMetadataStrategy, runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy,
startNodeStrategy, stopNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning,
nodeTerminated, nodeSuspended, initScriptRunnerFactory, initAdminAccess, runScriptOnNodeFactory,
persistNodeCredentials, timeouts, userExecutor, imageExtension);
persistNodeCredentials, timeouts, userExecutor, imageExtension, securityGroupExtension);
this.zoneIdToZone = checkNotNull(zoneIdToZone, "zoneIdToZone");
this.client = checkNotNull(client, "client");
this.securityGroupMap = checkNotNull(securityGroupMap, "securityGroupMap");

View File

@ -32,6 +32,8 @@ import javax.inject.Singleton;
import org.jclouds.cloudstack.CloudStackClient;
import org.jclouds.cloudstack.compute.CloudStackComputeService;
import org.jclouds.cloudstack.compute.extensions.CloudStackImageExtension;
import org.jclouds.cloudstack.compute.functions.CloudStackSecurityGroupToSecurityGroup;
import org.jclouds.cloudstack.compute.functions.IngressRuleToIpPermission;
import org.jclouds.cloudstack.compute.functions.OrphanedGroupsByZoneId;
import org.jclouds.cloudstack.compute.functions.ServiceOfferingToHardware;
import org.jclouds.cloudstack.compute.functions.TemplateToImage;
@ -46,6 +48,7 @@ import org.jclouds.cloudstack.compute.strategy.BasicNetworkOptionsConverter;
import org.jclouds.cloudstack.compute.strategy.CloudStackComputeServiceAdapter;
import org.jclouds.cloudstack.compute.strategy.OptionsConverter;
import org.jclouds.cloudstack.domain.FirewallRule;
import org.jclouds.cloudstack.domain.IngressRule;
import org.jclouds.cloudstack.domain.IPForwardingRule;
import org.jclouds.cloudstack.domain.Network;
import org.jclouds.cloudstack.domain.NetworkType;
@ -77,6 +80,7 @@ import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.domain.Location;
import org.jclouds.net.domain.IpPermission;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.suppliers.MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier;
@ -112,6 +116,10 @@ public class CloudStackComputeServiceContextModule extends
}).to(CloudStackComputeServiceAdapter.class);
bind(new TypeLiteral<Function<VirtualMachine, NodeMetadata>>() {
}).to(VirtualMachineToNodeMetadata.class);
bind(new TypeLiteral<Function<SecurityGroup, org.jclouds.compute.domain.SecurityGroup>>() {
}).to(CloudStackSecurityGroupToSecurityGroup.class);
bind(new TypeLiteral<Function<IngressRule, IpPermission>>() {
}).to(IngressRuleToIpPermission.class);
bind(new TypeLiteral<Function<Template, org.jclouds.compute.domain.Image>>() {
}).to(TemplateToImage.class);
bind(new TypeLiteral<Function<ServiceOffering, org.jclouds.compute.domain.Hardware>>() {

View File

@ -0,0 +1,74 @@
/*
* 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.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.transform;
import java.util.NoSuchElementException;
import java.util.Set;
import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.domain.SecurityGroup;
import org.jclouds.compute.domain.SecurityGroupBuilder;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import org.jclouds.net.domain.IpPermission;
import org.jclouds.cloudstack.domain.IngressRule;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.collect.Iterables;
import com.google.inject.Inject;
/**
* A function for transforming a CloudStack-specific SecurityGroup into a generic
* SecurityGroup object.
*
* @author Andrew Bayer
*/
@Singleton
public class CloudStackSecurityGroupToSecurityGroup implements Function<org.jclouds.cloudstack.domain.SecurityGroup, SecurityGroup> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
protected final Function<IngressRule,IpPermission> ruleToPermission;
@Inject
public CloudStackSecurityGroupToSecurityGroup(Function<IngressRule,IpPermission> ruleToPermission) {
this.ruleToPermission = ruleToPermission;
}
@Override
public SecurityGroup apply(org.jclouds.cloudstack.domain.SecurityGroup group) {
SecurityGroupBuilder builder = new SecurityGroupBuilder();
builder.id(group.getId());
builder.providerId(group.getId());
builder.name(group.getName());
builder.ownerId(group.getAccount());
builder.ipPermissions(transform(group.getIngressRules(), ruleToPermission));
return builder.build();
}
}

View File

@ -0,0 +1,55 @@
/*
* 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.compute.functions;
import javax.annotation.Resource;
import javax.inject.Named;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.cloudstack.domain.IngressRule;
import org.jclouds.logging.Logger;
import org.jclouds.net.domain.IpPermission;
import org.jclouds.net.domain.IpProtocol;
import com.google.common.base.Function;
/**
* A function for transforming a CloudStack-specific IngressRule into a generic
* IpPermission object.
*
* @author Andrew Bayer
*/
public class IngressRuleToIpPermission implements Function<IngressRule, IpPermission> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
public IngressRuleToIpPermission() {
}
@Override
public IpPermission apply(IngressRule rule) {
IpPermission.Builder builder = IpPermission.builder();
builder.ipProtocol(IpProtocol.fromValue(rule.getProtocol()));
builder.fromPort(rule.getStartPort());
builder.toPort(rule.getEndPort());
builder.cidrBlock(rule.getCIDR());
return builder.build();
}
}

View File

@ -0,0 +1,80 @@
/*
* 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.compute.functions;
import static com.google.common.collect.Iterables.transform;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import java.util.Set;
import org.jclouds.compute.domain.SecurityGroup;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.net.domain.IpPermission;
import org.jclouds.net.domain.IpProtocol;
import org.jclouds.cloudstack.domain.IngressRule;
import org.testng.annotations.Test;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableSet;
/**
* @author Andrew Bayer
*/
@Test(groups = "unit", testName = "CloudStackSecurityGroupToSecurityGroupTest")
public class CloudStackSecurityGroupToSecurityGroupTest {
private static final IngressRuleToIpPermission ruleConverter = new IngressRuleToIpPermission();
@Test
public void testApply() {
IngressRule ruleToConvert = IngressRule.builder()
.id("some-id")
.account("some-account")
.securityGroupName("some-group-name")
.protocol(IpProtocol.TCP.toString())
.startPort(10)
.endPort(20)
.CIDR("0.0.0.0/0")
.build();
org.jclouds.cloudstack.domain.SecurityGroup origGroup = org.jclouds.cloudstack.domain.SecurityGroup.builder()
.id("some-id")
.name("some-group")
.description("some-description")
.account("some-account")
.ingressRules(ImmutableSet.of(ruleToConvert))
.build();
CloudStackSecurityGroupToSecurityGroup parser = createGroupParser();
SecurityGroup group = parser.apply(origGroup);
assertEquals(group.getId(), origGroup.getId());
assertEquals(group.getProviderId(), origGroup.getId());
assertEquals(group.getName(), origGroup.getName());
assertEquals(group.getOwnerId(), origGroup.getAccount());
assertEquals(group.getIpPermissions(), ImmutableSet.copyOf(transform(origGroup.getIngressRules(), ruleConverter)));
}
private CloudStackSecurityGroupToSecurityGroup createGroupParser() {
CloudStackSecurityGroupToSecurityGroup parser = new CloudStackSecurityGroupToSecurityGroup(ruleConverter);
return parser;
}
}

View File

@ -0,0 +1,61 @@
/*
* 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.compute.functions;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import org.jclouds.cloudstack.domain.IngressRule;
import org.jclouds.net.domain.IpPermission;
import org.jclouds.net.domain.IpProtocol;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
/**
* Tests for the function for transforming a cloudstack specific IngressRule into a generic
* IpPermission object.
*
* @author Andrew Bayer
*/
public class IngressRuleToIpPermissionTest {
@Test
public void testApplyWithTCP() {
IngressRule ruleToConvert = IngressRule.builder()
.id("some-id")
.account("some-account")
.securityGroupName("some-group-name")
.protocol(IpProtocol.TCP.toString())
.startPort(10)
.endPort(20)
.CIDR("0.0.0.0/0")
.build();
IngressRuleToIpPermission converter = new IngressRuleToIpPermission();
IpPermission convertedPerm = converter.apply(ruleToConvert);
assertEquals(convertedPerm.getIpProtocol(), IpProtocol.fromValue(ruleToConvert.getProtocol()));
assertEquals(convertedPerm.getFromPort(), ruleToConvert.getStartPort());
assertEquals(convertedPerm.getToPort(), ruleToConvert.getEndPort());
assertEquals(convertedPerm.getCidrBlocks(), ImmutableSet.of("0.0.0.0/0"));
assertTrue(convertedPerm.getTenantIdGroupNamePairs().size() == 0);
assertTrue(convertedPerm.getGroupIds().size() == 0);
}
}

View File

@ -21,9 +21,9 @@
org.jclouds.ec2.security-group2
(:require (org.jclouds [compute2 :as compute])
[org.jclouds.ec2.ebs2 :as ebs])
(:import org.jclouds.ec2.domain.IpProtocol
org.jclouds.ec2.domain.SecurityGroup
org.jclouds.ec2.services.SecurityGroupClient))
(:import org.jclouds.ec2.domain.SecurityGroup
org.jclouds.ec2.services.SecurityGroupClient
org.jclouds.net.domain.IpProtocol))
(defn #^SecurityGroupClient
sg-service

View File

@ -19,9 +19,9 @@ package org.jclouds.ec2.binders;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.ec2.domain.IpPermission;
import org.jclouds.ec2.util.IpPermissions;
import org.jclouds.http.HttpRequest;
import org.jclouds.net.domain.IpPermission;
import org.jclouds.rest.Binder;
/**

View File

@ -19,9 +19,9 @@ package org.jclouds.ec2.binders;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.ec2.domain.IpPermission;
import org.jclouds.ec2.util.IpPermissions;
import org.jclouds.http.HttpRequest;
import org.jclouds.net.domain.IpPermission;
import org.jclouds.rest.Binder;
import com.google.common.collect.ImmutableMultimap;

View File

@ -55,6 +55,7 @@ import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.compute.functions.GroupNamingConvention.Factory;
import org.jclouds.compute.internal.BaseComputeService;
@ -128,12 +129,13 @@ public class EC2ComputeService extends BaseComputeService {
ConcurrentMap<RegionAndName, KeyPair> credentialsMap,
@Named("SECURITY") LoadingCache<RegionAndName, String> securityGroupMap,
Optional<ImageExtension> imageExtension, GroupNamingConvention.Factory namingConvention,
@Named(PROPERTY_EC2_GENERATE_INSTANCE_NAMES) boolean generateInstanceNames) {
@Named(PROPERTY_EC2_GENERATE_INSTANCE_NAMES) boolean generateInstanceNames,
Optional<SecurityGroupExtension> securityGroupExtension) {
super(context, credentialStore, images, sizes, locations, listNodesStrategy, getImageStrategy,
getNodeMetadataStrategy, runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy,
startNodeStrategy, stopNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning,
nodeTerminated, nodeSuspended, initScriptRunnerFactory, initAdminAccess, runScriptOnNodeFactory,
persistNodeCredentials, timeouts, userExecutor, imageExtension);
persistNodeCredentials, timeouts, userExecutor, imageExtension, securityGroupExtension);
this.client = client;
this.credentialsMap = credentialsMap;
this.securityGroupMap = securityGroupMap;

View File

@ -31,6 +31,7 @@ import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.config.BaseComputeServiceContextModule;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.ec2.compute.EC2ComputeService;
import org.jclouds.ec2.compute.domain.RegionAndName;
import org.jclouds.ec2.compute.loaders.RegionAndIdToImage;
@ -137,5 +138,9 @@ public class EC2ComputeServiceContextModule extends BaseComputeServiceContextMod
return Optional.of(i.getInstance(ImageExtension.class));
}
@Override
protected Optional<SecurityGroupExtension> provideSecurityGroupExtension(Injector i) {
return Optional.of(i.getInstance(SecurityGroupExtension.class));
}
}

View File

@ -29,18 +29,22 @@ import org.jclouds.compute.ComputeService;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadata.Status;
import org.jclouds.compute.domain.SecurityGroup;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.ec2.compute.EC2ComputeService;
import org.jclouds.ec2.compute.domain.PasswordDataAndPrivateKey;
import org.jclouds.ec2.compute.domain.RegionAndName;
import org.jclouds.ec2.compute.extensions.EC2ImageExtension;
import org.jclouds.ec2.compute.extensions.EC2SecurityGroupExtension;
import org.jclouds.ec2.compute.functions.AddElasticIpsToNodemetadata;
import org.jclouds.ec2.compute.functions.CreateUniqueKeyPair;
import org.jclouds.ec2.compute.functions.CredentialsForInstance;
import org.jclouds.ec2.compute.functions.EC2ImageParser;
import org.jclouds.ec2.compute.functions.EC2SecurityGroupToSecurityGroup;
import org.jclouds.ec2.compute.functions.PasswordCredentialsFromWindowsInstance;
import org.jclouds.ec2.compute.functions.RunningInstanceToNodeMetadata;
import org.jclouds.ec2.compute.functions.WindowsLoginCredentialsFromEncryptedData;
@ -129,8 +133,12 @@ public class EC2ComputeServiceDependenciesModule extends AbstractModule {
}).to(PasswordCredentialsFromWindowsInstance.class);
bind(new TypeLiteral<Function<org.jclouds.ec2.domain.Image, Image>>() {
}).to(EC2ImageParser.class);
bind(new TypeLiteral<Function<org.jclouds.ec2.domain.SecurityGroup, SecurityGroup>>() {
}).to(EC2SecurityGroupToSecurityGroup.class);
bind(new TypeLiteral<ImageExtension>() {
}).to(EC2ImageExtension.class);
bind(new TypeLiteral<SecurityGroupExtension>() {
}).to(EC2SecurityGroupExtension.class);
}
/**

View File

@ -0,0 +1,384 @@
/*
* 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.ec2.compute.extensions;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.equalTo;
import static com.google.common.base.Predicates.not;
import static com.google.common.base.Predicates.notNull;
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.getOnlyElement;
import static com.google.common.collect.Iterables.toArray;
import static com.google.common.collect.Iterables.transform;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider;
import org.jclouds.Constants;
import org.jclouds.aws.util.AWSUtils;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.domain.SecurityGroup;
import org.jclouds.compute.domain.SecurityGroupBuilder;
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.compute.functions.GroupNamingConvention.Factory;
import org.jclouds.domain.Location;
import org.jclouds.ec2.EC2Client;
import org.jclouds.ec2.compute.domain.RegionAndName;
import org.jclouds.ec2.compute.domain.RegionNameAndIngressRules;
import org.jclouds.ec2.domain.RunningInstance;
import org.jclouds.ec2.domain.UserIdGroupPair;
import org.jclouds.location.Region;
import org.jclouds.net.domain.IpPermission;
import org.jclouds.net.domain.IpProtocol;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.UncheckedTimeoutException;
/**
* An extension to compute service to allow for the manipulation of {@link SecurityGroup}s. Implementation
* is optional by providers.
*
* @author Andrew Bayer
*/
public class EC2SecurityGroupExtension implements SecurityGroupExtension {
protected final EC2Client client;
protected final ListeningExecutorService userExecutor;
protected final Supplier<Set<String>> regions;
protected final Function<org.jclouds.ec2.domain.SecurityGroup, SecurityGroup> groupConverter;
protected final Supplier<Set<? extends Location>> locations;
protected final LoadingCache<RegionAndName, String> groupCreator;
protected final Factory namingConvention;
@Inject
public EC2SecurityGroupExtension(EC2Client client,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
@Region Supplier<Set<String>> regions,
Function<org.jclouds.ec2.domain.SecurityGroup, SecurityGroup> groupConverter,
@Memoized Supplier<Set<? extends Location>> locations,
@Named("SECURITY") LoadingCache<RegionAndName, String> groupCreator,
GroupNamingConvention.Factory namingConvention) {
this.client = checkNotNull(client, "client");
this.userExecutor = checkNotNull(userExecutor, "userExecutor");
this.regions = checkNotNull(regions, "regions");
this.groupConverter = checkNotNull(groupConverter, "groupConverter");
this.locations = checkNotNull(locations, "locations");
this.groupCreator = checkNotNull(groupCreator, "groupCreator");
this.namingConvention = checkNotNull(namingConvention, "namingConvention");
}
@Override
public Set<SecurityGroup> listSecurityGroups() {
Iterable<? extends org.jclouds.ec2.domain.SecurityGroup> rawGroups = pollSecurityGroups();
Iterable<SecurityGroup> groups = transform(filter(rawGroups, notNull()),
groupConverter);
return ImmutableSet.copyOf(groups);
}
@Override
public Set<SecurityGroup> listSecurityGroupsInLocation(final Location location) {
String region = AWSUtils.getRegionFromLocationOrNull(location);
if (region == null) {
return ImmutableSet.of();
}
return listSecurityGroupsInLocation(region);
}
public Set<SecurityGroup> listSecurityGroupsInLocation(String region) {
Iterable<? extends org.jclouds.ec2.domain.SecurityGroup> rawGroups = pollSecurityGroupsByRegion(region);
Iterable<SecurityGroup> groups = transform(filter(rawGroups, notNull()),
groupConverter);
return ImmutableSet.copyOf(groups);
}
@Override
public Set<SecurityGroup> listSecurityGroupsForNode(String id) {
checkNotNull(id, "id");
String[] parts = AWSUtils.parseHandle(id);
String region = parts[0];
String instanceId = parts[1];
RunningInstance instance = getOnlyElement(Iterables.concat(client.getInstanceServices().describeInstancesInRegion(region, instanceId)));
if (instance == null) {
return ImmutableSet.of();
}
Set<String> groupNames = instance.getGroupNames();
Set<? extends org.jclouds.ec2.domain.SecurityGroup> rawGroups =
client.getSecurityGroupServices().describeSecurityGroupsInRegion(region, Iterables.toArray(groupNames, String.class));
return ImmutableSet.copyOf(transform(filter(rawGroups, notNull()), groupConverter));
}
@Override
public SecurityGroup getSecurityGroupById(String id) {
checkNotNull(id, "id");
String[] parts = AWSUtils.parseHandle(id);
String region = parts[0];
String groupId = parts[1];
Set<? extends org.jclouds.ec2.domain.SecurityGroup> rawGroups =
client.getSecurityGroupServices().describeSecurityGroupsInRegion(region, groupId);
return getOnlyElement(transform(filter(rawGroups, notNull()), groupConverter));
}
@Override
public SecurityGroup createSecurityGroup(String name, Location location) {
String region = AWSUtils.getRegionFromLocationOrNull(location);
if (region != null) {
return createSecurityGroup(name, region);
} else {
return null;
}
}
public SecurityGroup createSecurityGroup(String name, String region) {
String markerGroup = namingConvention.create().sharedNameForGroup(name);
RegionNameAndIngressRules regionAndName = new RegionNameAndIngressRules(region, markerGroup, new int[] {},
false);
groupCreator.getUnchecked(regionAndName);
return getSecurityGroupById(regionAndName.slashEncode());
}
@Override
public boolean removeSecurityGroup(String id) {
checkNotNull(id, "id");
String[] parts = AWSUtils.parseHandle(id);
String region = parts[0];
String groupName = parts[1];
if (client.getSecurityGroupServices().describeSecurityGroupsInRegion(region, groupName).size() > 0) {
client.getSecurityGroupServices().deleteSecurityGroupInRegion(region, groupName);
// TODO: test this clear happens
groupCreator.invalidate(new RegionNameAndIngressRules(region, groupName, null, false));
return true;
}
return false;
}
@Override
public SecurityGroup addIpPermission(IpPermission ipPermission, SecurityGroup group) {
String region = AWSUtils.getRegionFromLocationOrNull(group.getLocation());
String name = group.getName();
if (ipPermission.getCidrBlocks().size() > 0) {
for (String cidr : ipPermission.getCidrBlocks()) {
client.getSecurityGroupServices().
authorizeSecurityGroupIngressInRegion(region,
name,
ipPermission.getIpProtocol(),
ipPermission.getFromPort(),
ipPermission.getToPort(),
cidr);
}
}
if (ipPermission.getTenantIdGroupNamePairs().size() > 0) {
for (String userId : ipPermission.getTenantIdGroupNamePairs().keySet()) {
for (String groupName : ipPermission.getTenantIdGroupNamePairs().get(userId)) {
client.getSecurityGroupServices().
authorizeSecurityGroupIngressInRegion(region,
name,
new UserIdGroupPair(userId, groupName));
}
}
}
System.out.println("group: " + group);
return getSecurityGroupById(new RegionAndName(region, group.getName()).slashEncode());
}
@Override
public SecurityGroup addIpPermission(IpProtocol protocol, int startPort, int endPort,
Multimap<String, String> tenantIdGroupNamePairs,
Iterable<String> ipRanges,
Iterable<String> groupIds, SecurityGroup group) {
String region = AWSUtils.getRegionFromLocationOrNull(group.getLocation());
String name = group.getName();
if (Iterables.size(ipRanges) > 0) {
for (String cidr : ipRanges) {
client.getSecurityGroupServices().
authorizeSecurityGroupIngressInRegion(region,
name,
protocol,
startPort,
endPort,
cidr);
}
}
if (tenantIdGroupNamePairs.size() > 0) {
for (String userId : tenantIdGroupNamePairs.keySet()) {
for (String groupName : tenantIdGroupNamePairs.get(userId)) {
client.getSecurityGroupServices().
authorizeSecurityGroupIngressInRegion(region,
name,
new UserIdGroupPair(userId, groupName));
}
}
}
return getSecurityGroupById(new RegionAndName(region, group.getName()).slashEncode());
}
@Override
public SecurityGroup removeIpPermission(IpPermission ipPermission, SecurityGroup group) {
String region = AWSUtils.getRegionFromLocationOrNull(group.getLocation());
String name = group.getName();
if (ipPermission.getCidrBlocks().size() > 0) {
for (String cidr : ipPermission.getCidrBlocks()) {
client.getSecurityGroupServices().
revokeSecurityGroupIngressInRegion(region,
name,
ipPermission.getIpProtocol(),
ipPermission.getFromPort(),
ipPermission.getToPort(),
cidr);
}
}
if (ipPermission.getTenantIdGroupNamePairs().size() > 0) {
for (String userId : ipPermission.getTenantIdGroupNamePairs().keySet()) {
for (String groupName : ipPermission.getTenantIdGroupNamePairs().get(userId)) {
client.getSecurityGroupServices().
revokeSecurityGroupIngressInRegion(region,
name,
new UserIdGroupPair(userId, groupName));
}
}
}
return getSecurityGroupById(new RegionAndName(region, group.getName()).slashEncode());
}
@Override
public SecurityGroup removeIpPermission(IpProtocol protocol, int startPort, int endPort,
Multimap<String, String> tenantIdGroupNamePairs,
Iterable<String> ipRanges,
Iterable<String> groupIds, SecurityGroup group) {
String region = AWSUtils.getRegionFromLocationOrNull(group.getLocation());
String name = group.getName();
if (Iterables.size(ipRanges) > 0) {
for (String cidr : ipRanges) {
client.getSecurityGroupServices().
revokeSecurityGroupIngressInRegion(region,
name,
protocol,
startPort,
endPort,
cidr);
}
}
if (tenantIdGroupNamePairs.size() > 0) {
for (String userId : tenantIdGroupNamePairs.keySet()) {
for (String groupName : tenantIdGroupNamePairs.get(userId)) {
client.getSecurityGroupServices().
revokeSecurityGroupIngressInRegion(region,
name,
new UserIdGroupPair(userId, groupName));
}
}
}
return getSecurityGroupById(new RegionAndName(region, group.getName()).slashEncode());
}
@Override
public boolean supportsTenantIdGroupNamePairs() {
return true;
}
@Override
public boolean supportsGroupIds() {
return false;
}
@Override
public boolean supportsPortRangesForGroups() {
return false;
}
protected Iterable<? extends org.jclouds.ec2.domain.SecurityGroup> pollSecurityGroups() {
Iterable<? extends Set<? extends org.jclouds.ec2.domain.SecurityGroup>> groups
= transform(regions.get(), allSecurityGroupsInRegion());
return concat(groups);
}
protected Iterable<? extends org.jclouds.ec2.domain.SecurityGroup> pollSecurityGroupsByRegion(String region) {
return allSecurityGroupsInRegion().apply(region);
}
protected Function<String, Set<? extends org.jclouds.ec2.domain.SecurityGroup>> allSecurityGroupsInRegion() {
return new Function<String, Set<? extends org.jclouds.ec2.domain.SecurityGroup>>() {
@Override
public Set<? extends org.jclouds.ec2.domain.SecurityGroup> apply(String from) {
return client.getSecurityGroupServices().describeSecurityGroupsInRegion(from);
}
};
}
protected Location findLocationWithId(final String locationId) {
if (locationId == null)
return null;
try {
Location location = Iterables.find(locations.get(), new Predicate<Location>() {
@Override
public boolean apply(Location input) {
return input.getId().equals(locationId);
}
});
return location;
} catch (NoSuchElementException e) {
return null;
}
}
}

View File

@ -0,0 +1,95 @@
/*
* 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.ec2.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.NoSuchElementException;
import java.util.Set;
import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.domain.SecurityGroup;
import org.jclouds.compute.domain.SecurityGroupBuilder;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.Location;
import org.jclouds.logging.Logger;
import org.jclouds.net.domain.IpPermission;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.collect.Iterables;
import com.google.inject.Inject;
/**
* A function for transforming an EC2-specific SecurityGroup into a generic
* SecurityGroup object.
*
* @author Andrew Bayer
*/
@Singleton
public class EC2SecurityGroupToSecurityGroup implements Function<org.jclouds.ec2.domain.SecurityGroup, SecurityGroup> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
protected final Supplier<Set<? extends Location>> locations;
@Inject
public EC2SecurityGroupToSecurityGroup(@Memoized Supplier<Set<? extends Location>> locations) {
this.locations = checkNotNull(locations, "locations");
}
@Override
public SecurityGroup apply(org.jclouds.ec2.domain.SecurityGroup group) {
SecurityGroupBuilder builder = new SecurityGroupBuilder();
Location location = findLocationWithId(group.getRegion());
builder.location(location);
builder.id(group.getName());
builder.providerId(group.getId());
builder.name(group.getName());
builder.ipPermissions(group);
builder.ownerId(group.getOwnerId());
return builder.build();
}
private Location findLocationWithId(final String locationId) {
if (locationId == null)
return null;
try {
Location location = Iterables.find(locations.get(), new Predicate<Location>() {
@Override
public boolean apply(Location input) {
return input.getId().equals(locationId);
}
});
return location;
} catch (NoSuchElementException e) {
logger.debug("couldn't match instance location %s in: %s", locationId, locations.get());
return null;
}
}
}

View File

@ -27,10 +27,10 @@ import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.ec2.EC2Client;
import org.jclouds.ec2.compute.domain.RegionAndName;
import org.jclouds.ec2.compute.domain.RegionNameAndIngressRules;
import org.jclouds.ec2.domain.IpProtocol;
import org.jclouds.ec2.domain.UserIdGroupPair;
import org.jclouds.ec2.services.SecurityGroupClient;
import org.jclouds.logging.Logger;
import org.jclouds.net.domain.IpProtocol;
import com.google.common.base.Predicate;
import com.google.common.cache.CacheLoader;

View File

@ -1,189 +0,0 @@
/*
* 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.ec2.domain;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Set;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
/**
*
* @see <a href=
* "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-ItemType-IpPermissionType.html"
* />
* @author Adrian Cole
*/
public class IpPermission {
public static Builder builder() {
return new Builder();
}
public static class Builder {
private int fromPort;
private int toPort;
private IpProtocol ipProtocol;
private Multimap<String, String> userIdGroupPairs = LinkedHashMultimap.create();
private Set<String> groupIds = Sets.newLinkedHashSet();
private Set<String> ipRanges = Sets.newLinkedHashSet();
public Builder fromPort(int fromPort) {
this.fromPort = fromPort;
return this;
}
public Builder toPort(int toPort) {
this.toPort = toPort;
return this;
}
public Builder ipProtocol(IpProtocol ipProtocol) {
this.ipProtocol = checkNotNull(ipProtocol, "ipProtocol");
return this;
}
public Builder userIdGroupPair(String userId, String groupNameOrId) {
this.userIdGroupPairs.put(checkNotNull(userId, "userId"), checkNotNull(groupNameOrId, "groupNameOrId of %s", userId));
return this;
}
public Builder userIdGroupPairs(Multimap<String, String> userIdGroupPairs) {
this.userIdGroupPairs.putAll(checkNotNull(userIdGroupPairs, "userIdGroupPairs"));
return this;
}
public Builder ipRange(String ipRange) {
this.ipRanges.add(ipRange);
return this;
}
public Builder ipRanges(Iterable<String> ipRanges) {
Iterables.addAll(this.ipRanges, checkNotNull(ipRanges, "ipRanges"));
return this;
}
public Builder groupId(String groupId) {
this.groupIds.add(checkNotNull(groupId, "groupId"));
return this;
}
public Builder groupIds(Iterable<String> groupIds) {
Iterables.addAll(this.groupIds, checkNotNull(groupIds, "groupIds"));
return this;
}
public IpPermission build() {
return new IpPermission(ipProtocol, fromPort, toPort, userIdGroupPairs, groupIds, ipRanges);
}
}
private final int fromPort;
private final int toPort;
private final Multimap<String, String> userIdGroupPairs;
private final Set<String> groupIds;
private final IpProtocol ipProtocol;
private final Set<String> ipRanges;
public IpPermission(IpProtocol ipProtocol, int fromPort, int toPort, Multimap<String, String> userIdGroupPairs,
Iterable<String> groupIds, Iterable<String> ipRanges) {
this.fromPort = fromPort;
this.toPort = toPort;
this.userIdGroupPairs = ImmutableMultimap.copyOf(checkNotNull(userIdGroupPairs, "userIdGroupPairs"));
this.ipProtocol = checkNotNull(ipProtocol, "ipProtocol");
this.groupIds = ImmutableSet.copyOf(checkNotNull(groupIds, "groupIds"));
this.ipRanges = ImmutableSet.copyOf(checkNotNull(ipRanges, "ipRanges"));
}
/**
* Start of port range for the TCP and UDP protocols, or an ICMP type number.
* An ICMP type number of -1 indicates a wildcard (i.e., any ICMP type
* number).
*/
public int getFromPort() {
return fromPort;
}
/**
* End of port range for the TCP and UDP protocols, or an ICMP code. An ICMP
* code of -1 indicates a wildcard (i.e., any ICMP code).
*/
public int getToPort() {
return toPort;
}
/**
* List of security group and user ID pairs.
*/
public Multimap<String, String> getUserIdGroupPairs() {
return userIdGroupPairs;
}
/**
* List of security group Ids
*/
public Set<String> getGroupIds() {
return groupIds;
}
/**
* IP protocol
*/
public IpProtocol getIpProtocol() {
return ipProtocol;
}
/**
* IP ranges.
*/
public Set<String> getIpRanges() {
return ipRanges;
}
@Override
public int hashCode() {
return Objects.hashCode(fromPort, toPort, groupIds, ipProtocol, ipRanges, userIdGroupPairs);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null || getClass() != obj.getClass())
return false;
IpPermission that = IpPermission.class.cast(obj);
return Objects.equal(this.fromPort, that.fromPort) && Objects.equal(this.toPort, that.toPort)
&& Objects.equal(this.groupIds, that.groupIds) && Objects.equal(this.ipProtocol, that.ipProtocol)
&& Objects.equal(this.ipRanges, that.ipRanges)
&& Objects.equal(this.userIdGroupPairs, that.userIdGroupPairs);
}
@Override
public String toString() {
return Objects.toStringHelper(this).omitNullValues().add("fromPort", fromPort == -1 ? null : fromPort)
.add("toPort", toPort == -1 ? null : toPort).add("groupIds", groupIds.size() == 0 ? null : groupIds)
.add("ipProtocol", ipProtocol).add("ipRanges", ipRanges.size() == 0 ? null : ipRanges)
.add("userIdGroupPairs", userIdGroupPairs.size() == 0 ? null : userIdGroupPairs).toString();
}
}

View File

@ -21,6 +21,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Set;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.net.domain.IpPermission;
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;

View File

@ -30,12 +30,12 @@ import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
import org.jclouds.aws.filters.FormSigner;
import org.jclouds.ec2.binders.BindGroupNamesToIndexedFormParams;
import org.jclouds.ec2.binders.BindUserIdGroupPairToSourceSecurityGroupFormParams;
import org.jclouds.ec2.domain.IpProtocol;
import org.jclouds.ec2.domain.SecurityGroup;
import org.jclouds.ec2.domain.UserIdGroupPair;
import org.jclouds.ec2.xml.DescribeSecurityGroupsResponseHandler;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
import org.jclouds.net.domain.IpProtocol;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.EndpointParam;
import org.jclouds.rest.annotations.Fallback;

View File

@ -17,10 +17,10 @@
package org.jclouds.ec2.services;
import java.util.Set;
import org.jclouds.ec2.domain.IpProtocol;
import org.jclouds.ec2.domain.SecurityGroup;
import org.jclouds.ec2.domain.UserIdGroupPair;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.net.domain.IpProtocol;
/**
* Provides access to EC2 via their REST API.

View File

@ -21,8 +21,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map;
import java.util.Map.Entry;
import org.jclouds.ec2.domain.IpPermission;
import org.jclouds.ec2.domain.IpProtocol;
import org.jclouds.net.domain.IpPermission;
import org.jclouds.net.domain.IpProtocol;
import org.jclouds.util.Maps2;
import com.google.common.annotations.Beta;
@ -58,7 +58,7 @@ public class IpPermissions extends IpPermission {
headers.put("IpPermissions.%d.ToPort", permission.getToPort() + "");
String prefix = "IpPermissions.%d.IpRanges.";
int i = 0;
for (String cidrIp : checkNotNull(permission.getIpRanges(), "cidrIps")) {
for (String cidrIp : checkNotNull(permission.getCidrBlocks(), "cidrIps")) {
headers.put(prefix + i++ + ".CidrIp", cidrIp);
}
prefix = "IpPermissions.%d.Groups.";
@ -68,15 +68,15 @@ public class IpPermissions extends IpPermission {
}
prefix = "IpPermissions.%d.Groups.";
i = 0;
for (Entry<String, String> userIdGroupNamePair : checkNotNull(permission.getUserIdGroupPairs(),
"userIdGroupNamePairs").entries()) {
headers.put(prefix + i + ".UserId", userIdGroupNamePair.getKey());
headers.put(prefix + i + ".GroupName", userIdGroupNamePair.getValue());
for (Entry<String, String> tenantIdGroupNamePair : checkNotNull(permission.getTenantIdGroupNamePairs(),
"tenantIdGroupNamePairs").entries()) {
headers.put(prefix + i + ".UserId", tenantIdGroupNamePair.getKey());
headers.put(prefix + i + ".GroupName", tenantIdGroupNamePair.getValue());
i++;
}
prefix = "IpPermissions.%d.IpRanges.";
i = 0;
for (String cidrIp : checkNotNull(permission.getIpRanges(), "cidrIps")) {
for (String cidrIp : checkNotNull(permission.getCidrBlocks(), "cidrIps")) {
headers.put(prefix + i++ + ".CidrIp", cidrIp);
}
return Multimaps.forMap(Maps2.transformKeys(headers, new Function<String, String>() {
@ -165,7 +165,7 @@ public class IpPermissions extends IpPermission {
}
public IpPermissions toVPCSecurityGroups(Iterable<String> groupIds) {
return new IpPermissions(getIpProtocol(), getFromPort(), getToPort(), getUserIdGroupPairs(), groupIds,
return new IpPermissions(getIpProtocol(), getFromPort(), getToPort(), getTenantIdGroupNamePairs(), groupIds,
ImmutableSet.<String> of());
}
}
@ -189,8 +189,8 @@ public class IpPermissions extends IpPermission {
checkNotNull(groupName, "groupName")));
}
public IpPermissions toEC2SecurityGroups(Multimap<String, String> userIdGroupNamePairs) {
return new IpPermissions(getIpProtocol(), getFromPort(), getToPort(), userIdGroupNamePairs, getGroupIds(),
public IpPermissions toEC2SecurityGroups(Multimap<String, String> tenantIdGroupNamePairs) {
return new IpPermissions(getIpProtocol(), getFromPort(), getToPort(), tenantIdGroupNamePairs, getGroupIds(),
ImmutableSet.<String> of());
}
}

View File

@ -19,9 +19,9 @@ package org.jclouds.ec2.xml;
import static org.jclouds.util.SaxUtils.currentOrNull;
import static org.jclouds.util.SaxUtils.equalsOrSuffix;
import org.jclouds.ec2.domain.IpPermission;
import org.jclouds.ec2.domain.IpProtocol;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.net.domain.IpPermission;
import org.jclouds.net.domain.IpProtocol;
import org.xml.sax.SAXException;
/**
@ -66,14 +66,14 @@ public class IpPermissionHandler extends ParseSax.HandlerForGeneratedRequestWith
// EC2)
builder.toPort(Integer.parseInt(currentOrNegative(currentText)));
} else if (equalsOrSuffix(qName, "cidrIp")) {
builder.ipRange(currentOrNull(currentText));
builder.cidrBlock(currentOrNull(currentText));
} else if (equalsOrSuffix(qName, "userId")) {
this.userId = currentOrNull(currentText);
} else if (equalsOrSuffix(qName, "groupName") || equalsOrSuffix(qName, "groupId")) {
this.groupId = currentOrNull(currentText);
} else if (equalsOrSuffix(qName, "item")) {
if (userId != null && groupId != null)
builder.userIdGroupPair(userId, groupId);
builder.tenantIdGroupNamePair(userId, groupId);
userId = groupId = null;
}
currentText = new StringBuilder();

View File

@ -40,7 +40,6 @@ import org.jclouds.ec2.domain.BlockDevice;
import org.jclouds.ec2.domain.Image.EbsBlockDevice;
import org.jclouds.ec2.domain.InstanceState;
import org.jclouds.ec2.domain.InstanceType;
import org.jclouds.ec2.domain.IpProtocol;
import org.jclouds.ec2.domain.KeyPair;
import org.jclouds.ec2.domain.PublicIpInstanceIdPair;
import org.jclouds.ec2.domain.Reservation;
@ -49,6 +48,7 @@ import org.jclouds.ec2.domain.Volume.InstanceInitiatedShutdownBehavior;
import org.jclouds.ec2.predicates.InstanceHasIpAddress;
import org.jclouds.ec2.predicates.InstanceStateRunning;
import org.jclouds.http.HttpResponseException;
import org.jclouds.net.domain.IpProtocol;
import org.jclouds.predicates.SocketOpen;
import org.jclouds.scriptbuilder.ScriptBuilder;
import org.jclouds.scriptbuilder.domain.OsFamily;

View File

@ -42,7 +42,6 @@ import org.jclouds.ec2.domain.Image.Architecture;
import org.jclouds.ec2.domain.Image.ImageType;
import org.jclouds.ec2.domain.InstanceState;
import org.jclouds.ec2.domain.InstanceType;
import org.jclouds.ec2.domain.IpProtocol;
import org.jclouds.ec2.domain.KeyPair;
import org.jclouds.ec2.domain.Reservation;
import org.jclouds.ec2.domain.RootDeviceType;
@ -58,6 +57,7 @@ import org.jclouds.ec2.predicates.VolumeAttached;
import org.jclouds.ec2.predicates.VolumeAvailable;
import org.jclouds.http.HttpResponseException;
import org.jclouds.io.Payloads;
import org.jclouds.net.domain.IpProtocol;
import org.jclouds.predicates.SocketOpen;
import org.jclouds.scriptbuilder.InitScript;
import org.jclouds.scriptbuilder.domain.OsFamily;

View File

@ -39,7 +39,6 @@ import org.jclouds.ec2.EC2ApiMetadata;
import org.jclouds.ec2.EC2Client;
import org.jclouds.ec2.compute.options.EC2TemplateOptions;
import org.jclouds.ec2.domain.BlockDevice;
import org.jclouds.ec2.domain.IpProtocol;
import org.jclouds.ec2.domain.KeyPair;
import org.jclouds.ec2.domain.PublicIpInstanceIdPair;
import org.jclouds.ec2.domain.RunningInstance;
@ -51,6 +50,7 @@ import org.jclouds.ec2.services.ElasticBlockStoreClient;
import org.jclouds.ec2.services.InstanceClient;
import org.jclouds.ec2.services.KeyPairClient;
import org.jclouds.ec2.services.SecurityGroupClient;
import org.jclouds.net.domain.IpProtocol;
import org.jclouds.scriptbuilder.domain.Statements;
import org.jclouds.sshj.config.SshjSshClientModule;
import org.jclouds.util.InetAddresses2;

View File

@ -0,0 +1,585 @@
/*
* 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.ec2.compute.extensions;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import java.util.Set;
import javax.ws.rs.core.MediaType;
import org.jclouds.compute.domain.SecurityGroup;
import org.jclouds.compute.domain.SecurityGroupBuilder;
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
import org.jclouds.ec2.compute.domain.RegionAndName;
import org.jclouds.ec2.compute.internal.BaseEC2ComputeServiceExpectTest;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.net.domain.IpPermission;
import org.jclouds.net.domain.IpProtocol;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.Futures;
/**
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "EC2SecurityGroupExtensionExpectTest")
public class EC2SecurityGroupExtensionExpectTest extends BaseEC2ComputeServiceExpectTest {
public void testListSecurityGroups() {
HttpRequest describeSecurityGroupsAllRequest =
formSigner.filter(HttpRequest.builder()
.method("POST")
.endpoint("https://ec2." + region + ".amazonaws.com/")
.addHeader("Host", "ec2." + region + ".amazonaws.com")
.addFormParam("Action", "DescribeSecurityGroups").build());
HttpResponse describeSecurityGroupsAllResponse =
HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType(
"/describe_securitygroups_extension_new.xml", MediaType.APPLICATION_XML)).build();
Builder<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder();
requestResponseMap.put(describeRegionsRequest, describeRegionsResponse);
requestResponseMap.put(describeAvailabilityZonesRequest, describeAvailabilityZonesResponse);
requestResponseMap.put(describeSecurityGroupsAllRequest, describeSecurityGroupsAllResponse);
requestResponseMap.put(createKeyPairRequest, createKeyPairResponse);
requestResponseMap.put(createSecurityGroupRequest, createSecurityGroupResponse);
requestResponseMap.put(authorizeSecurityGroupIngressRequest22, authorizeSecurityGroupIngressResponse);
requestResponseMap.put(authorizeSecurityGroupIngressRequestGroup, authorizeSecurityGroupIngressResponse);
requestResponseMap.put(describeInstanceRequest, describeInstanceResponse);
SecurityGroupExtension extension = requestsSendResponses(requestResponseMap.build()).getSecurityGroupExtension().get();
Set<SecurityGroup> groups = extension.listSecurityGroups();
assertEquals(2, groups.size());
}
public void testListSecurityGroupsInLocation() {
HttpRequest describeSecurityGroupsAllRequest =
formSigner.filter(HttpRequest.builder()
.method("POST")
.endpoint("https://ec2." + region + ".amazonaws.com/")
.addHeader("Host", "ec2." + region + ".amazonaws.com")
.addFormParam("Action", "DescribeSecurityGroups").build());
HttpResponse describeSecurityGroupsAllResponse =
HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType(
"/describe_securitygroups_extension_new.xml", MediaType.APPLICATION_XML)).build();
Builder<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder();
requestResponseMap.put(describeRegionsRequest, describeRegionsResponse);
requestResponseMap.put(describeAvailabilityZonesRequest, describeAvailabilityZonesResponse);
requestResponseMap.put(describeSecurityGroupsAllRequest, describeSecurityGroupsAllResponse);
requestResponseMap.put(createKeyPairRequest, createKeyPairResponse);
requestResponseMap.put(createSecurityGroupRequest, createSecurityGroupResponse);
requestResponseMap.put(authorizeSecurityGroupIngressRequest22, authorizeSecurityGroupIngressResponse);
requestResponseMap.put(authorizeSecurityGroupIngressRequestGroup, authorizeSecurityGroupIngressResponse);
requestResponseMap.put(describeInstanceRequest, describeInstanceResponse);
SecurityGroupExtension extension = requestsSendResponses(requestResponseMap.build()).getSecurityGroupExtension().get();
Set<SecurityGroup> groups = extension.listSecurityGroupsInLocation(new LocationBuilder()
.scope(LocationScope.REGION)
.id(region)
.description("region")
.build());
assertEquals(2, groups.size());
}
public void testListSecurityGroupsForNode() {
HttpRequest describeSecurityGroupsSingleRequest =
formSigner.filter(HttpRequest.builder()
.method("POST")
.endpoint("https://ec2." + region + ".amazonaws.com/")
.addHeader("Host", "ec2." + region + ".amazonaws.com")
.addFormParam("Action", "DescribeSecurityGroups")
.addFormParam("GroupName.1", "sg-3c6ef654").build());
HttpResponse describeSecurityGroupsSingleResponse =
HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType(
"/describe_securitygroups_extension_single.xml", MediaType.APPLICATION_XML)).build();
HttpResponse describeInstanceWithSGResponse =
HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType(
"/describe_instances_running_securitygroups.xml", MediaType.APPLICATION_XML)).build();
Builder<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder();
requestResponseMap.put(describeRegionsRequest, describeRegionsResponse);
requestResponseMap.put(describeAvailabilityZonesRequest, describeAvailabilityZonesResponse);
requestResponseMap.put(describeSecurityGroupsSingleRequest, describeSecurityGroupsSingleResponse);
requestResponseMap.put(createKeyPairRequest, createKeyPairResponse);
requestResponseMap.put(createSecurityGroupRequest, createSecurityGroupResponse);
requestResponseMap.put(authorizeSecurityGroupIngressRequest22, authorizeSecurityGroupIngressResponse);
requestResponseMap.put(authorizeSecurityGroupIngressRequestGroup, authorizeSecurityGroupIngressResponse);
requestResponseMap.put(describeInstanceRequest, describeInstanceWithSGResponse);
SecurityGroupExtension extension = requestsSendResponses(requestResponseMap.build()).getSecurityGroupExtension().get();
Set<SecurityGroup> groups = extension.listSecurityGroupsForNode(new RegionAndName(region, "i-2baa5550").slashEncode());
assertEquals(1, groups.size());
}
public void testGetSecurityGroupById() {
HttpRequest describeSecurityGroupsSingleRequest =
formSigner.filter(HttpRequest.builder()
.method("POST")
.endpoint("https://ec2." + region + ".amazonaws.com/")
.addHeader("Host", "ec2." + region + ".amazonaws.com")
.addFormParam("Action", "DescribeSecurityGroups")
.addFormParam("GroupName.1", "jclouds#some-group").build());
HttpResponse describeSecurityGroupsSingleResponse =
HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType(
"/describe_securitygroups_extension_single.xml", MediaType.APPLICATION_XML)).build();
Builder<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder();
requestResponseMap.put(describeRegionsRequest, describeRegionsResponse);
requestResponseMap.put(describeAvailabilityZonesRequest, describeAvailabilityZonesResponse);
requestResponseMap.put(describeSecurityGroupsSingleRequest, describeSecurityGroupsSingleResponse);
requestResponseMap.put(createKeyPairRequest, createKeyPairResponse);
requestResponseMap.put(createSecurityGroupRequest, createSecurityGroupResponse);
requestResponseMap.put(authorizeSecurityGroupIngressRequest22, authorizeSecurityGroupIngressResponse);
requestResponseMap.put(authorizeSecurityGroupIngressRequestGroup, authorizeSecurityGroupIngressResponse);
SecurityGroupExtension extension = requestsSendResponses(requestResponseMap.build()).getSecurityGroupExtension().get();
SecurityGroup group = extension.getSecurityGroupById(new RegionAndName(region, "jclouds#some-group").slashEncode());
assertEquals("sg-3c6ef654", group.getProviderId());
assertEquals("jclouds#some-group", group.getId());
}
public void testCreateSecurityGroup() {
HttpRequest createSecurityGroupExtRequest =
formSigner.filter(HttpRequest.builder()
.method("POST")
.endpoint("https://ec2." + region + ".amazonaws.com/")
.addHeader("Host", "ec2." + region + ".amazonaws.com")
.addFormParam("Action", "CreateSecurityGroup")
.addFormParam("GroupDescription", "jclouds#some-group")
.addFormParam("GroupName", "jclouds#some-group").build());
HttpRequest describeSecurityGroupsSingleRequest =
formSigner.filter(HttpRequest.builder()
.method("POST")
.endpoint("https://ec2." + region + ".amazonaws.com/")
.addHeader("Host", "ec2." + region + ".amazonaws.com")
.addFormParam("Action", "DescribeSecurityGroups")
.addFormParam("GroupName.1", "jclouds#some-group").build());
HttpResponse describeSecurityGroupsSingleResponse =
HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType(
"/describe_securitygroups_extension_single.xml", MediaType.APPLICATION_XML)).build();
Builder<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder();
requestResponseMap.put(describeRegionsRequest, describeRegionsResponse);
requestResponseMap.put(describeAvailabilityZonesRequest, describeAvailabilityZonesResponse);
requestResponseMap.put(describeSecurityGroupsSingleRequest, describeSecurityGroupsSingleResponse);
requestResponseMap.put(createKeyPairRequest, createKeyPairResponse);
requestResponseMap.put(createSecurityGroupExtRequest, createSecurityGroupResponse);
requestResponseMap.put(authorizeSecurityGroupIngressRequest22, authorizeSecurityGroupIngressResponse);
requestResponseMap.put(authorizeSecurityGroupIngressRequestGroup, authorizeSecurityGroupIngressResponse);
SecurityGroupExtension extension = requestsSendResponses(requestResponseMap.build()).getSecurityGroupExtension().get();
SecurityGroup group = extension.createSecurityGroup("some-group", new LocationBuilder()
.scope(LocationScope.REGION)
.id(region)
.description("region")
.build());
assertEquals("sg-3c6ef654", group.getProviderId());
assertEquals("jclouds#some-group", group.getId());
}
public void testRemoveSecurityGroup() {
HttpRequest describeSecurityGroupsSingleRequest =
formSigner.filter(HttpRequest.builder()
.method("POST")
.endpoint("https://ec2." + region + ".amazonaws.com/")
.addHeader("Host", "ec2." + region + ".amazonaws.com")
.addFormParam("Action", "DescribeSecurityGroups")
.addFormParam("GroupName.1", "jclouds#some-group").build());
HttpResponse describeSecurityGroupsSingleResponse =
HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType(
"/describe_securitygroups_extension_single.xml", MediaType.APPLICATION_XML)).build();
HttpRequest deleteSecurityGroupRequest =
formSigner.filter(HttpRequest.builder()
.method("POST")
.endpoint("https://ec2." + region + ".amazonaws.com/")
.addHeader("Host", "ec2." + region + ".amazonaws.com")
.addFormParam("Action", "DeleteSecurityGroup")
.addFormParam("GroupName", "jclouds#some-group").build());
HttpResponse deleteSecurityGroupResponse =
HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType(
"/delete_securitygroup.xml", MediaType.APPLICATION_XML)).build();
Builder<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder();
requestResponseMap.put(describeRegionsRequest, describeRegionsResponse);
requestResponseMap.put(describeAvailabilityZonesRequest, describeAvailabilityZonesResponse);
requestResponseMap.put(describeSecurityGroupsSingleRequest, describeSecurityGroupsSingleResponse);
requestResponseMap.put(deleteSecurityGroupRequest, deleteSecurityGroupResponse);
requestResponseMap.put(createKeyPairRequest, createKeyPairResponse);
requestResponseMap.put(createSecurityGroupRequest, createSecurityGroupResponse);
requestResponseMap.put(authorizeSecurityGroupIngressRequest22, authorizeSecurityGroupIngressResponse);
requestResponseMap.put(authorizeSecurityGroupIngressRequestGroup, authorizeSecurityGroupIngressResponse);
SecurityGroupExtension extension = requestsSendResponses(requestResponseMap.build()).getSecurityGroupExtension().get();
assertTrue(extension.removeSecurityGroup(new RegionAndName(region, "jclouds#some-group").slashEncode()));
}
public void testAddIpPermissionCidrFromIpPermission() {
HttpRequest describeSecurityGroupsSingleRequest =
formSigner.filter(HttpRequest.builder()
.method("POST")
.endpoint("https://ec2." + region + ".amazonaws.com/")
.addHeader("Host", "ec2." + region + ".amazonaws.com")
.addFormParam("Action", "DescribeSecurityGroups")
.addFormParam("GroupName.1", "jclouds#some-group").build());
HttpResponse describeSecurityGroupsSingleResponse =
HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType(
"/describe_securitygroups_extension_cidr.xml", MediaType.APPLICATION_XML)).build();
HttpRequest authorizeSecurityGroupIngressRequestRange =
formSigner.filter(HttpRequest.builder()
.method("POST")
.endpoint("https://ec2." + region + ".amazonaws.com/")
.addHeader("Host", "ec2." + region + ".amazonaws.com")
.addFormParam("Action", "AuthorizeSecurityGroupIngress")
.addFormParam("CidrIp", "0.0.0.0/0")
.addFormParam("FromPort", "22")
.addFormParam("ToPort", "40")
.addFormParam("GroupName", "jclouds#some-group")
.addFormParam("IpProtocol", "tcp").build());
Builder<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder();
requestResponseMap.put(describeRegionsRequest, describeRegionsResponse);
requestResponseMap.put(describeAvailabilityZonesRequest, describeAvailabilityZonesResponse);
requestResponseMap.put(describeSecurityGroupsSingleRequest, describeSecurityGroupsSingleResponse);
requestResponseMap.put(createKeyPairRequest, createKeyPairResponse);
requestResponseMap.put(createSecurityGroupRequest, createSecurityGroupResponse);
requestResponseMap.put(authorizeSecurityGroupIngressRequestRange, authorizeSecurityGroupIngressResponse);
IpPermission.Builder builder = IpPermission.builder();
builder.ipProtocol(IpProtocol.TCP);
builder.fromPort(22);
builder.toPort(40);
builder.cidrBlock("0.0.0.0/0");
IpPermission perm = builder.build();
SecurityGroupExtension extension = requestsSendResponses(requestResponseMap.build()).getSecurityGroupExtension().get();
SecurityGroupBuilder groupBuilder = new SecurityGroupBuilder();
groupBuilder.id("jclouds#some-group");
groupBuilder.providerId("sg-3c6ef654");
groupBuilder.name("jclouds#some-group");
groupBuilder.location(new LocationBuilder()
.scope(LocationScope.REGION)
.id(region)
.description("region")
.build());
SecurityGroup origGroup = groupBuilder.build();
SecurityGroup newGroup = extension.addIpPermission(perm, origGroup);
assertEquals(1, newGroup.getIpPermissions().size());
IpPermission newPerm = Iterables.getOnlyElement(newGroup.getIpPermissions());
assertNotNull(newPerm);
assertEquals(IpProtocol.TCP, newPerm.getIpProtocol());
assertEquals(22, newPerm.getFromPort());
assertEquals(40, newPerm.getToPort());
assertEquals(1, newPerm.getCidrBlocks().size());
assertTrue(newPerm.getCidrBlocks().contains("0.0.0.0/0"));
}
public void testAddIpPermissionCidrFromParams() {
HttpRequest describeSecurityGroupsSingleRequest =
formSigner.filter(HttpRequest.builder()
.method("POST")
.endpoint("https://ec2." + region + ".amazonaws.com/")
.addHeader("Host", "ec2." + region + ".amazonaws.com")
.addFormParam("Action", "DescribeSecurityGroups")
.addFormParam("GroupName.1", "jclouds#some-group").build());
HttpResponse describeSecurityGroupsSingleResponse =
HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType(
"/describe_securitygroups_extension_cidr.xml", MediaType.APPLICATION_XML)).build();
HttpRequest authorizeSecurityGroupIngressRequestRange =
formSigner.filter(HttpRequest.builder()
.method("POST")
.endpoint("https://ec2." + region + ".amazonaws.com/")
.addHeader("Host", "ec2." + region + ".amazonaws.com")
.addFormParam("Action", "AuthorizeSecurityGroupIngress")
.addFormParam("CidrIp", "0.0.0.0/0")
.addFormParam("FromPort", "22")
.addFormParam("ToPort", "40")
.addFormParam("GroupName", "jclouds#some-group")
.addFormParam("IpProtocol", "tcp").build());
Builder<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder();
requestResponseMap.put(describeRegionsRequest, describeRegionsResponse);
requestResponseMap.put(describeAvailabilityZonesRequest, describeAvailabilityZonesResponse);
requestResponseMap.put(describeSecurityGroupsSingleRequest, describeSecurityGroupsSingleResponse);
requestResponseMap.put(createKeyPairRequest, createKeyPairResponse);
requestResponseMap.put(createSecurityGroupRequest, createSecurityGroupResponse);
requestResponseMap.put(authorizeSecurityGroupIngressRequestRange, authorizeSecurityGroupIngressResponse);
SecurityGroupExtension extension = requestsSendResponses(requestResponseMap.build()).getSecurityGroupExtension().get();
SecurityGroupBuilder groupBuilder = new SecurityGroupBuilder();
groupBuilder.id("jclouds#some-group");
groupBuilder.providerId("sg-3c6ef654");
groupBuilder.name("jclouds#some-group");
groupBuilder.location(new LocationBuilder()
.scope(LocationScope.REGION)
.id(region)
.description("region")
.build());
SecurityGroup origGroup = groupBuilder.build();
SecurityGroup newGroup = extension.addIpPermission(IpProtocol.TCP,
22,
40,
emptyMultimap(),
ImmutableSet.of("0.0.0.0/0"),
emptyStringSet(),
origGroup);
assertEquals(1, newGroup.getIpPermissions().size());
IpPermission newPerm = Iterables.getOnlyElement(newGroup.getIpPermissions());
assertNotNull(newPerm);
assertEquals(IpProtocol.TCP, newPerm.getIpProtocol());
assertEquals(22, newPerm.getFromPort());
assertEquals(40, newPerm.getToPort());
assertEquals(1, newPerm.getCidrBlocks().size());
assertTrue(newPerm.getCidrBlocks().contains("0.0.0.0/0"));
}
public void testAddIpPermissionGroupFromIpPermission() {
HttpRequest describeSecurityGroupsSingleRequest =
formSigner.filter(HttpRequest.builder()
.method("POST")
.endpoint("https://ec2." + region + ".amazonaws.com/")
.addHeader("Host", "ec2." + region + ".amazonaws.com")
.addFormParam("Action", "DescribeSecurityGroups")
.addFormParam("GroupName.1", "jclouds#some-group").build());
HttpResponse describeSecurityGroupsSingleResponse =
HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType(
"/describe_securitygroups_extension_group.xml", MediaType.APPLICATION_XML)).build();
HttpRequest authorizeSecurityGroupIngressRequestGroupTenant =
formSigner.filter(HttpRequest.builder()
.method("POST")
.endpoint("https://ec2." + region + ".amazonaws.com/")
.addHeader("Host", "ec2." + region + ".amazonaws.com")
.addFormParam("Action", "AuthorizeSecurityGroupIngress")
.addFormParam("SourceSecurityGroupName", "jclouds#some-group")
.addFormParam("SourceSecurityGroupOwnerId", "993194456877")
.addFormParam("GroupName", "jclouds#some-group").build());
Builder<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder();
requestResponseMap.put(describeRegionsRequest, describeRegionsResponse);
requestResponseMap.put(describeAvailabilityZonesRequest, describeAvailabilityZonesResponse);
requestResponseMap.put(describeSecurityGroupsSingleRequest, describeSecurityGroupsSingleResponse);
requestResponseMap.put(createKeyPairRequest, createKeyPairResponse);
requestResponseMap.put(createSecurityGroupRequest, createSecurityGroupResponse);
requestResponseMap.put(authorizeSecurityGroupIngressRequestGroupTenant, authorizeSecurityGroupIngressResponse);
IpPermission.Builder builder = IpPermission.builder();
builder.ipProtocol(IpProtocol.TCP);
builder.fromPort(22);
builder.toPort(40);
builder.tenantIdGroupNamePair("993194456877", "jclouds#some-group");
IpPermission perm = builder.build();
SecurityGroupExtension extension = requestsSendResponses(requestResponseMap.build()).getSecurityGroupExtension().get();
SecurityGroupBuilder groupBuilder = new SecurityGroupBuilder();
groupBuilder.id("jclouds#some-group");
groupBuilder.providerId("sg-3c6ef654");
groupBuilder.name("jclouds#some-group");
groupBuilder.location(new LocationBuilder()
.scope(LocationScope.REGION)
.id(region)
.description("region")
.build());
groupBuilder.ownerId("993194456877");
SecurityGroup origGroup = groupBuilder.build();
SecurityGroup newGroup = extension.addIpPermission(perm, origGroup);
assertEquals(1, newGroup.getIpPermissions().size());
IpPermission newPerm = Iterables.getOnlyElement(newGroup.getIpPermissions());
assertNotNull(newPerm);
assertEquals(IpProtocol.TCP, newPerm.getIpProtocol());
assertEquals(22, newPerm.getFromPort());
assertEquals(40, newPerm.getToPort());
assertEquals(0, newPerm.getCidrBlocks().size());
assertEquals(1, newPerm.getTenantIdGroupNamePairs().size());
assertTrue(newPerm.getTenantIdGroupNamePairs().keySet().contains(origGroup.getOwnerId()));
assertTrue(newPerm.getTenantIdGroupNamePairs().values().contains(origGroup.getName()));
}
public void testAddIpPermissionGroupFromParams() {
HttpRequest describeSecurityGroupsSingleRequest =
formSigner.filter(HttpRequest.builder()
.method("POST")
.endpoint("https://ec2." + region + ".amazonaws.com/")
.addHeader("Host", "ec2." + region + ".amazonaws.com")
.addFormParam("Action", "DescribeSecurityGroups")
.addFormParam("GroupName.1", "jclouds#some-group").build());
HttpResponse describeSecurityGroupsSingleResponse =
HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType(
"/describe_securitygroups_extension_group.xml", MediaType.APPLICATION_XML)).build();
HttpRequest authorizeSecurityGroupIngressRequestGroupTenant =
formSigner.filter(HttpRequest.builder()
.method("POST")
.endpoint("https://ec2." + region + ".amazonaws.com/")
.addHeader("Host", "ec2." + region + ".amazonaws.com")
.addFormParam("Action", "AuthorizeSecurityGroupIngress")
.addFormParam("SourceSecurityGroupName", "jclouds#some-group")
.addFormParam("SourceSecurityGroupOwnerId", "993194456877")
.addFormParam("GroupName", "jclouds#some-group").build());
Builder<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder();
requestResponseMap.put(describeRegionsRequest, describeRegionsResponse);
requestResponseMap.put(describeAvailabilityZonesRequest, describeAvailabilityZonesResponse);
requestResponseMap.put(describeSecurityGroupsSingleRequest, describeSecurityGroupsSingleResponse);
requestResponseMap.put(createKeyPairRequest, createKeyPairResponse);
requestResponseMap.put(createSecurityGroupRequest, createSecurityGroupResponse);
requestResponseMap.put(authorizeSecurityGroupIngressRequestGroupTenant, authorizeSecurityGroupIngressResponse);
SecurityGroupExtension extension = requestsSendResponses(requestResponseMap.build()).getSecurityGroupExtension().get();
SecurityGroupBuilder groupBuilder = new SecurityGroupBuilder();
groupBuilder.id("jclouds#some-group");
groupBuilder.providerId("sg-3c6ef654");
groupBuilder.name("jclouds#some-group");
groupBuilder.ownerId("993194456877");
groupBuilder.location(new LocationBuilder()
.scope(LocationScope.REGION)
.id(region)
.description("region")
.build());
SecurityGroup origGroup = groupBuilder.build();
ImmutableMultimap.Builder<String, String> permBuilder = ImmutableMultimap.builder();
permBuilder.put(origGroup.getOwnerId(), origGroup.getName());
SecurityGroup newGroup = extension.addIpPermission(IpProtocol.TCP,
22,
40,
permBuilder.build(),
emptyStringSet(),
emptyStringSet(),
origGroup);
assertEquals(1, newGroup.getIpPermissions().size());
IpPermission newPerm = Iterables.getOnlyElement(newGroup.getIpPermissions());
assertNotNull(newPerm);
assertEquals(IpProtocol.TCP, newPerm.getIpProtocol());
assertEquals(22, newPerm.getFromPort());
assertEquals(40, newPerm.getToPort());
assertEquals(0, newPerm.getCidrBlocks().size());
assertEquals(1, newPerm.getTenantIdGroupNamePairs().size());
assertTrue(newPerm.getTenantIdGroupNamePairs().keySet().contains(origGroup.getOwnerId()));
assertTrue(newPerm.getTenantIdGroupNamePairs().values().contains(origGroup.getName()));
}
private Multimap<String, String> emptyMultimap() {
return LinkedHashMultimap.create();
}
private Set<String> emptyStringSet() {
return Sets.newLinkedHashSet();
}
}

View File

@ -14,35 +14,26 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.ec2.domain;
package org.jclouds.ec2.compute.extensions;
import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.compute.extensions.internal.BaseSecurityGroupExtensionLiveTest;
import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.annotations.Test;
import com.google.inject.Module;
/**
* @author Adrian Cole
* Live test for ec2 {@link SecurityGroupExtension} implementation
*
* @author Andrew Bayer
*
*/
public enum IpProtocol {
@Test(groups = "live", singleThreaded = true, testName = "EC2SecurityGroupExtensionLiveTest")
public class EC2SecurityGroupExtensionLiveTest extends BaseSecurityGroupExtensionLiveTest {
TCP, UDP, ICMP, ALL, UNRECOGNIZED;
public String value() {
return this == ALL ? "-1" : name().toLowerCase();
}
@Override
public String toString() {
return value();
}
public static IpProtocol fromValue(String protocol) {
try {
if (protocol.equalsIgnoreCase("-1"))
return ALL;
return valueOf(checkNotNull(protocol, "protocol").toUpperCase());
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
public EC2SecurityGroupExtensionLiveTest() {
provider = "ec2";
}
}

View File

@ -0,0 +1,85 @@
/*
* 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.ec2.compute.functions;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import java.util.Set;
import org.jclouds.compute.domain.SecurityGroup;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
import org.jclouds.ec2.util.IpPermissions;
import org.jclouds.net.domain.IpPermission;
import org.testng.annotations.Test;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableSet;
/**
* @author Andrew Bayer
*/
@Test(groups = "unit", testName = "EC2SecurityGroupToSecurityGroupTest")
public class EC2SecurityGroupToSecurityGroupTest {
static Location provider = new LocationBuilder().scope(LocationScope.REGION).id("us-east-1")
.description("us-east-1").build();
@Test
public void testApply() {
IpPermissions authorization = IpPermissions.permitAnyProtocol();
org.jclouds.ec2.domain.SecurityGroup origGroup = org.jclouds.ec2.domain.SecurityGroup.builder()
.region("us-east-1")
.id("some-id")
.name("some-group")
.ownerId("some-owner")
.description("some-description")
.ipPermission(authorization)
.build();
EC2SecurityGroupToSecurityGroup parser = createGroupParser(ImmutableSet.of(provider));
SecurityGroup group = parser.apply(origGroup);
assertEquals(group.getLocation(), provider);
assertEquals(group.getId(), origGroup.getName());
assertEquals(group.getProviderId(), origGroup.getId());
assertEquals(group.getName(), origGroup.getName());
assertEquals(group.getIpPermissions(), (Set<IpPermission>)origGroup);
assertEquals(group.getOwnerId(), origGroup.getOwnerId());
}
private EC2SecurityGroupToSecurityGroup createGroupParser(final ImmutableSet<Location> locations) {
Supplier<Set<? extends Location>> locationSupplier = new Supplier<Set<? extends Location>>() {
@Override
public Set<? extends Location> get() {
return locations;
}
};
EC2SecurityGroupToSecurityGroup parser = new EC2SecurityGroupToSecurityGroup(locationSupplier);
return parser;
}
}

View File

@ -29,10 +29,10 @@ import java.util.concurrent.ExecutionException;
import org.jclouds.ec2.compute.domain.RegionAndName;
import org.jclouds.ec2.compute.domain.RegionNameAndIngressRules;
import org.jclouds.ec2.domain.IpProtocol;
import org.jclouds.ec2.domain.SecurityGroup;
import org.jclouds.ec2.domain.UserIdGroupPair;
import org.jclouds.ec2.services.SecurityGroupClient;
import org.jclouds.net.domain.IpProtocol;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;

View File

@ -22,12 +22,12 @@ import java.io.IOException;
import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
import org.jclouds.ec2.domain.IpProtocol;
import org.jclouds.ec2.domain.UserIdGroupPair;
import org.jclouds.ec2.xml.DescribeSecurityGroupsResponseHandler;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.http.functions.ReleasePayloadAndReturn;
import org.jclouds.net.domain.IpProtocol;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.testng.annotations.Test;

View File

@ -30,10 +30,10 @@ import java.util.Set;
import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
import org.jclouds.ec2.EC2ApiMetadata;
import org.jclouds.ec2.EC2Client;
import org.jclouds.ec2.domain.IpPermission;
import org.jclouds.ec2.domain.IpProtocol;
import org.jclouds.ec2.domain.SecurityGroup;
import org.jclouds.ec2.domain.UserIdGroupPair;
import org.jclouds.net.domain.IpPermission;
import org.jclouds.net.domain.IpProtocol;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
@ -174,7 +174,7 @@ public class SecurityGroupClientLiveTest extends BaseComputeServiceContextLiveTe
assertEventually(new GroupHasPermission(client, group2Name, new Predicate<IpPermission>() {
@Override
public boolean apply(IpPermission arg0) {
return arg0.getUserIdGroupPairs().equals(ImmutableMultimap.of(group.getOwnerId(), group1Name));
return arg0.getTenantIdGroupNamePairs().equals(ImmutableMultimap.of(group.getOwnerId(), group1Name));
}
}));
@ -191,7 +191,7 @@ public class SecurityGroupClientLiveTest extends BaseComputeServiceContextLiveTe
@Override
public boolean apply(IpPermission arg0) {
return arg0.getIpProtocol() == IpProtocol.TCP && arg0.getFromPort() == 80 && arg0.getToPort() == 80
&& arg0.getIpRanges().equals(ImmutableSet.of("0.0.0.0/0"));
&& arg0.getCidrBlocks().equals(ImmutableSet.of("0.0.0.0/0"));
}
}

View File

@ -18,7 +18,7 @@ package org.jclouds.ec2.util;
import static org.testng.Assert.assertEquals;
import org.jclouds.ec2.domain.IpProtocol;
import org.jclouds.net.domain.IpProtocol;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;

View File

@ -21,10 +21,10 @@ import static org.testng.Assert.assertEquals;
import java.io.InputStream;
import java.util.Set;
import org.jclouds.ec2.domain.IpPermission;
import org.jclouds.ec2.domain.IpProtocol;
import org.jclouds.ec2.domain.SecurityGroup;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.net.domain.IpPermission;
import org.jclouds.net.domain.IpProtocol;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMultimap;
@ -46,10 +46,10 @@ public class DescribeSecurityGroupsResponseHandlerTest extends BaseEC2HandlerTes
InputStream is = getClass().getResourceAsStream("/describe_securitygroups.xml");
Set<SecurityGroup> expected = ImmutableSet.of(
new SecurityGroup(defaultRegion, null, "WebServers", "UYY3TLBUXIEON5NQVUUX6OMPWBZIQNFM", "Web Servers",
new SecurityGroup(defaultRegion, "sg-3c6ef654", "WebServers", "UYY3TLBUXIEON5NQVUUX6OMPWBZIQNFM", "Web Servers",
ImmutableSet.of(new IpPermission(IpProtocol.TCP, 80, 80, ImmutableMultimap.<String, String> of(),
ImmutableSet.<String> of(), ImmutableSet.of("0.0.0.0/0")))),
new SecurityGroup(defaultRegion, null, "RangedPortsBySource", "UYY3TLBUXIEON5NQVUUX6OMPWBZIQNFM", "Group A",
new SecurityGroup(defaultRegion, "sg-867309ab", "RangedPortsBySource", "UYY3TLBUXIEON5NQVUUX6OMPWBZIQNFM", "Group A",
ImmutableSet.of(new IpPermission(IpProtocol.TCP, 6000, 7000, ImmutableMultimap
.<String, String> of(), ImmutableSet.<String> of(), ImmutableSet.<String> of()))));
@ -69,7 +69,7 @@ public class DescribeSecurityGroupsResponseHandlerTest extends BaseEC2HandlerTes
userIdGroupPairs.put("UYY3TLBUXIEON5NQVUUX6OMPWBZIQNFM", "jclouds#cluster#world");
Set<SecurityGroup> expected = ImmutableSet.of(
new SecurityGroup(defaultRegion, null, "jclouds#cluster#world", "UYY3TLBUXIEON5NQVUUX6OMPWBZIQNFM", "Cluster",
new SecurityGroup(defaultRegion, "sg-3c6ef654", "jclouds#cluster#world", "UYY3TLBUXIEON5NQVUUX6OMPWBZIQNFM", "Cluster",
ImmutableSet.of(
new IpPermission(IpProtocol.TCP, 22, 22, ImmutableMultimap.<String, String> of(),
ImmutableSet.<String> of(), ImmutableSet.of("0.0.0.0/0")),

View File

@ -0,0 +1,4 @@
<DeleteSecurityGroupResponse xmlns="http://ec2.amazonaws.com/doc/2013-02-01/">
<requestId>59dbff89-35bd-4eac-99ed-be587EXAMPLE</requestId>
<return>true</return>
</DeleteSecurityGroupResponse>

View File

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<DescribeInstancesResponse xmlns="http://ec2.amazonaws.com/doc/2011-05-15/">
<requestId>f6d3252e-35e5-4ef5-b2c5-62da95dd829b</requestId>
<reservationSet>
<item>
<reservationId>r-205ad944</reservationId>
<ownerId>993194456877</ownerId>
<groupSet>
<item>
<groupId>sg-3c6ef654</groupId>
<groupName>jclouds#some-group</groupName>
</item>
</groupSet>
<instancesSet>
<item>
<instanceId>i-2baa5550</instanceId>
<imageId>ami-aecd60c7</imageId>
<instanceState>
<code>16</code>
<name>running</name>
</instanceState>
<privateDnsName>ip-10-28-89-195.ec2.internal</privateDnsName>
<dnsName>ec2-50-16-1-166.compute-1.amazonaws.com</dnsName>
<reason/>
<keyName>jclouds#mygroup2#81</keyName>
<amiLaunchIndex>0</amiLaunchIndex>
<productCodes/>
<instanceType>t1.micro</instanceType>
<launchTime>2012-08-02T04:28:30.000Z</launchTime>
<placement>
<availabilityZone>us-east-1e</availabilityZone>
<groupName/>
<tenancy>default</tenancy>
</placement>
<kernelId>aki-88aa75e1</kernelId>
<monitoring>
<state>disabled</state>
</monitoring>
<privateIpAddress>10.28.89.195</privateIpAddress>
<ipAddress>50.16.1.166</ipAddress>
<groupSet>
<item>
<groupId>sg-3c6ef654</groupId>
<groupName>jclouds#some-group</groupName>
</item>
</groupSet>
<architecture>x86_64</architecture>
<rootDeviceType>ebs</rootDeviceType>
<rootDeviceName>/dev/sda1</rootDeviceName>
<blockDeviceMapping>
<item>
<deviceName>/dev/sda1</deviceName>
<ebs>
<volumeId>vol-f2d7c993</volumeId>
<status>attached</status>
<attachTime>2012-08-02T04:28:56.000Z</attachTime>
<deleteOnTermination>true</deleteOnTermination>
</ebs>
</item>
</blockDeviceMapping>
<virtualizationType>paravirtual</virtualizationType>
<clientToken/>
<tagSet>
<item>
<key>Name</key>
<value>mygroup2-2baa5550</value>
</item>
</tagSet>
<hypervisor>xen</hypervisor>
</item>
</instancesSet>
</item>
</reservationSet>
</DescribeInstancesResponse>

View File

@ -3,6 +3,7 @@
<securityGroupInfo>
<item>
<ownerId>UYY3TLBUXIEON5NQVUUX6OMPWBZIQNFM</ownerId>
<groupId>sg-3c6ef654</groupId>
<groupName>WebServers</groupName>
<groupDescription>Web Servers</groupDescription>
<ipPermissions>
@ -21,7 +22,8 @@
</item>
<item>
<ownerId>UYY3TLBUXIEON5NQVUUX6OMPWBZIQNFM</ownerId>
<groupName>RangedPortsBySource</groupName>
<groupId>sg-867309ab</groupId>
<groupName>RangedPortsBySource</groupName>
<groupDescription>Group A</groupDescription>
<ipPermissions>
<item>

View File

@ -23,6 +23,7 @@
<ipRanges />
<groups>
<item>
<groupId>sg-3c6ef654</groupId>
<groupName>jclouds#cluster#world</groupName>
<userId>UYY3TLBUXIEON5NQVUUX6OMPWBZIQNFM</userId>
</item>
@ -31,6 +32,7 @@
</item>
</ipPermissions>
<groupName>jclouds#cluster#world</groupName>
<groupId>sg-3c6ef654</groupId>
<groupDescription>Cluster</groupDescription>
<ownerId>UYY3TLBUXIEON5NQVUUX6OMPWBZIQNFM</ownerId>
</item>

View File

@ -0,0 +1,24 @@
<DescribeSecurityGroupsResponse
xmlns="http://ec2.amazonaws.com/doc/2009-11-30/">
<securityGroupInfo>
<item>
<ownerId>993194456877</ownerId>
<groupId>sg-3c6ef654</groupId>
<groupName>jclouds#some-group</groupName>
<groupDescription>jclouds#some-group</groupDescription>
<ipPermissions>
<item>
<ipProtocol>tcp</ipProtocol>
<fromPort>22</fromPort>
<toPort>40</toPort>
<groups />
<ipRanges>
<item>
<cidrIp>0.0.0.0/0</cidrIp>
</item>
</ipRanges>
</item>
</ipPermissions>
</item>
</securityGroupInfo>
</DescribeSecurityGroupsResponse>

View File

@ -0,0 +1,26 @@
<DescribeSecurityGroupsResponse
xmlns="http://ec2.amazonaws.com/doc/2009-11-30/">
<securityGroupInfo>
<item>
<ownerId>993194456877</ownerId>
<groupName>jclouds#some-group</groupName>
<groupDescription>jclouds#some-group</groupDescription>
<groupId>sg-3c6ef654</groupId>
<ipPermissions>
<item>
<ipProtocol>tcp</ipProtocol>
<fromPort>22</fromPort>
<toPort>40</toPort>
<groups>
<item>
<userId>993194456877</userId>
<groupId>sg-3c6ef654</groupId>
<groupName>jclouds#some-group</groupName>
</item>
</groups>
<ipRanges/>
</item>
</ipPermissions>
</item>
</securityGroupInfo>
</DescribeSecurityGroupsResponse>

View File

@ -0,0 +1,27 @@
<DescribeSecurityGroupsResponse
xmlns="http://ec2.amazonaws.com/doc/2009-11-30/">
<securityGroupInfo>
<item>
<ownerId>993194456877</ownerId>
<groupName>jclouds#some-group</groupName>
<groupDescription>jclouds#some-group</groupDescription>
<groupId>sg-3c6ef654</groupId>
<ipPermissions/>
</item>
<item>
<ownerId>993194456877</ownerId>
<groupId>sg-3a2b3c4d</groupId>
<groupName>group-a</groupName>
<groupDescription>Group A</groupDescription>
<ipPermissions>
<item>
<ipProtocol>tcp</ipProtocol>
<fromPort>6000</fromPort>
<toPort>7000</toPort>
<groups />
<ipRanges />
</item>
</ipPermissions>
</item>
</securityGroupInfo>
</DescribeSecurityGroupsResponse>

View File

@ -0,0 +1,12 @@
<DescribeSecurityGroupsResponse
xmlns="http://ec2.amazonaws.com/doc/2009-11-30/">
<securityGroupInfo>
<item>
<ownerId>993194456877</ownerId>
<groupName>jclouds#some-group</groupName>
<groupDescription>jclouds#some-group</groupDescription>
<groupId>sg-3c6ef654</groupId>
<ipPermissions/>
</item>
</securityGroupInfo>
</DescribeSecurityGroupsResponse>

View File

@ -40,6 +40,7 @@ import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.compute.internal.BaseComputeService;
import org.jclouds.compute.internal.PersistNodeCredentials;
@ -107,12 +108,13 @@ public class NovaComputeService extends BaseComputeService {
LoadingCache<ZoneAndName, SecurityGroupInZone> securityGroupMap,
LoadingCache<ZoneAndName, KeyPair> keyPairCache,
Function<Set<? extends NodeMetadata>, Multimap<String, String>> orphanedGroupsByZoneId,
GroupNamingConvention.Factory namingConvention, Optional<ImageExtension> imageExtension) {
GroupNamingConvention.Factory namingConvention, Optional<ImageExtension> imageExtension,
Optional<SecurityGroupExtension> securityGroupExtension) {
super(context, credentialStore, images, sizes, locations, listNodesStrategy, getImageStrategy,
getNodeMetadataStrategy, runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy,
startNodeStrategy, stopNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning,
nodeTerminated, nodeSuspended, initScriptRunnerFactory, initAdminAccess, runScriptOnNodeFactory,
persistNodeCredentials, timeouts, userExecutor, imageExtension);
persistNodeCredentials, timeouts, userExecutor, imageExtension, securityGroupExtension);
this.novaApi = checkNotNull(novaApi, "novaApi");
this.securityGroupMap = checkNotNull(securityGroupMap, "securityGroupMap");
this.keyPairCache = checkNotNull(keyPairCache, "keyPairCache");

View File

@ -38,12 +38,14 @@ import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.SecurityGroup;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThenAddToSet;
import org.jclouds.domain.Location;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.functions.IdentityFunction;
import org.jclouds.net.domain.IpPermission;
import org.jclouds.openstack.nova.v2_0.compute.NovaComputeService;
import org.jclouds.openstack.nova.v2_0.compute.NovaComputeServiceAdapter;
import org.jclouds.openstack.nova.v2_0.compute.extensions.NovaImageExtension;
@ -51,7 +53,9 @@ import org.jclouds.openstack.nova.v2_0.compute.functions.CreateSecurityGroupIfNe
import org.jclouds.openstack.nova.v2_0.compute.functions.FlavorInZoneToHardware;
import org.jclouds.openstack.nova.v2_0.compute.functions.ImageInZoneToImage;
import org.jclouds.openstack.nova.v2_0.compute.functions.ImageToOperatingSystem;
import org.jclouds.openstack.nova.v2_0.compute.functions.NovaSecurityGroupToSecurityGroup;
import org.jclouds.openstack.nova.v2_0.compute.functions.OrphanedGroupsByZoneId;
import org.jclouds.openstack.nova.v2_0.compute.functions.SecurityGroupRuleToIpPermission;
import org.jclouds.openstack.nova.v2_0.compute.functions.ServerInZoneToNodeMetadata;
import org.jclouds.openstack.nova.v2_0.compute.loaders.CreateUniqueKeyPair;
import org.jclouds.openstack.nova.v2_0.compute.loaders.FindSecurityGroupOrCreate;
@ -60,6 +64,7 @@ import org.jclouds.openstack.nova.v2_0.compute.options.NovaTemplateOptions;
import org.jclouds.openstack.nova.v2_0.compute.strategy.ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet;
import org.jclouds.openstack.nova.v2_0.domain.FloatingIP;
import org.jclouds.openstack.nova.v2_0.domain.KeyPair;
import org.jclouds.openstack.nova.v2_0.domain.SecurityGroupRule;
import org.jclouds.openstack.nova.v2_0.domain.Server;
import org.jclouds.openstack.nova.v2_0.domain.zonescoped.FlavorInZone;
import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ImageInZone;
@ -108,6 +113,12 @@ public class NovaComputeServiceContextModule extends
bind(new TypeLiteral<Function<ServerInZone, NodeMetadata>>() {
}).to(ServerInZoneToNodeMetadata.class);
bind(new TypeLiteral<Function<SecurityGroupRule, IpPermission>>() {
}).to(SecurityGroupRuleToIpPermission.class);
bind(new TypeLiteral<Function<org.jclouds.openstack.nova.v2_0.domain.SecurityGroup, SecurityGroup>>() {
}).to(NovaSecurityGroupToSecurityGroup.class);
bind(new TypeLiteral<Function<Set<? extends NodeMetadata>, Multimap<String, String>>>() {
}).to(OrphanedGroupsByZoneId.class);

View File

@ -28,9 +28,9 @@ import javax.inject.Singleton;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import org.jclouds.net.domain.IpProtocol;
import org.jclouds.openstack.nova.v2_0.NovaApi;
import org.jclouds.openstack.nova.v2_0.domain.Ingress;
import org.jclouds.openstack.nova.v2_0.domain.IpProtocol;
import org.jclouds.openstack.nova.v2_0.domain.SecurityGroup;
import org.jclouds.openstack.nova.v2_0.domain.zonescoped.SecurityGroupInZone;
import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ZoneSecurityGroupNameAndPorts;

View File

@ -0,0 +1,74 @@
/*
* 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.openstack.nova.v2_0.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.transform;
import java.util.NoSuchElementException;
import java.util.Set;
import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.domain.SecurityGroup;
import org.jclouds.compute.domain.SecurityGroupBuilder;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import org.jclouds.net.domain.IpPermission;
import org.jclouds.openstack.nova.v2_0.domain.SecurityGroupRule;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.collect.Iterables;
import com.google.inject.Inject;
/**
* A function for transforming a Nova-specific SecurityGroup into a generic
* SecurityGroup object.
*
* @author Andrew Bayer
*/
@Singleton
public class NovaSecurityGroupToSecurityGroup implements Function<org.jclouds.openstack.nova.v2_0.domain.SecurityGroup, SecurityGroup> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
protected Function<SecurityGroupRule,IpPermission> ruleToPermission;
@Inject
public NovaSecurityGroupToSecurityGroup(Function<SecurityGroupRule,IpPermission> ruleToPermission) {
this.ruleToPermission = ruleToPermission;
}
@Override
public SecurityGroup apply(org.jclouds.openstack.nova.v2_0.domain.SecurityGroup group) {
SecurityGroupBuilder builder = new SecurityGroupBuilder();
builder.id(group.getId());
builder.providerId(group.getId());
builder.ownerId(group.getTenantId());
builder.name(group.getName());
builder.ipPermissions(transform(group.getRules(), ruleToPermission));
return builder.build();
}
}

View File

@ -0,0 +1,57 @@
/*
* 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.openstack.nova.v2_0.compute.functions;
import javax.annotation.Resource;
import javax.inject.Named;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import org.jclouds.net.domain.IpPermission;
import org.jclouds.openstack.nova.v2_0.domain.SecurityGroupRule;
import com.google.common.base.Function;
/**
* A function for transforming a nova-specific SecurityGroupRule into a generic
* IpPermission object.
*
* @author Andrew Bayer
*/
public class SecurityGroupRuleToIpPermission implements Function<SecurityGroupRule, IpPermission> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
public SecurityGroupRuleToIpPermission() {
}
@Override
public IpPermission apply(SecurityGroupRule rule) {
IpPermission.Builder builder = IpPermission.builder();
builder.ipProtocol(rule.getIpProtocol());
builder.fromPort(rule.getFromPort());
builder.toPort(rule.getToPort());
if (rule.getGroup() != null)
builder.tenantIdGroupNamePair(rule.getGroup().getTenantId(), rule.getGroup().getName());
if (rule.getIpRange() != null)
builder.cidrBlock(rule.getIpRange());
return builder.build();
}
}

View File

@ -21,6 +21,7 @@ import java.beans.ConstructorProperties;
import javax.inject.Named;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.net.domain.IpProtocol;
import com.google.common.annotations.Beta;
import com.google.common.base.Objects;

View File

@ -23,6 +23,7 @@ import java.beans.ConstructorProperties;
import javax.inject.Named;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.net.domain.IpProtocol;
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;

View File

@ -0,0 +1,112 @@
/*
* 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.openstack.nova.v2_0.compute.functions;
import static com.google.common.collect.Iterables.transform;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import java.util.Set;
import org.jclouds.compute.domain.SecurityGroup;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.net.domain.IpPermission;
import org.jclouds.net.domain.IpProtocol;
import org.jclouds.openstack.nova.v2_0.domain.SecurityGroupRule;
import org.jclouds.openstack.nova.v2_0.domain.TenantIdAndName;
import org.testng.annotations.Test;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableSet;
/**
* @author Andrew Bayer
*/
@Test(groups = "unit", testName = "NovaSecurityGroupToSecurityGroupTest")
public class NovaSecurityGroupToSecurityGroupTest {
private static final SecurityGroupRuleToIpPermission ruleConverter = new SecurityGroupRuleToIpPermission();
@Test
public void testApplyWithGroup() {
TenantIdAndName group = TenantIdAndName.builder().tenantId("tenant").name("name").build();
SecurityGroupRule ruleToConvert = SecurityGroupRule.builder()
.id("some-id")
.ipProtocol(IpProtocol.TCP)
.fromPort(10)
.toPort(20)
.group(group)
.parentGroupId("some-other-id")
.build();
org.jclouds.openstack.nova.v2_0.domain.SecurityGroup origGroup = org.jclouds.openstack.nova.v2_0.domain.SecurityGroup.builder()
.tenantId("tenant")
.id("some-id")
.name("some-group")
.description("some-description")
.rules(ruleToConvert)
.build();
NovaSecurityGroupToSecurityGroup parser = createGroupParser();
SecurityGroup newGroup = parser.apply(origGroup);
assertEquals(newGroup.getId(), origGroup.getId());
assertEquals(newGroup.getProviderId(), origGroup.getId());
assertEquals(newGroup.getName(), origGroup.getName());
assertEquals(newGroup.getOwnerId(), origGroup.getTenantId());
assertEquals(newGroup.getIpPermissions(), ImmutableSet.copyOf(transform(origGroup.getRules(), ruleConverter)));
}
@Test
public void testApplyWithCidr() {
SecurityGroupRule ruleToConvert = SecurityGroupRule.builder()
.id("some-id")
.ipProtocol(IpProtocol.TCP)
.fromPort(10)
.toPort(20)
.ipRange("0.0.0.0/0")
.parentGroupId("some-other-id")
.build();
org.jclouds.openstack.nova.v2_0.domain.SecurityGroup origGroup = org.jclouds.openstack.nova.v2_0.domain.SecurityGroup.builder()
.tenantId("tenant")
.id("some-id")
.name("some-group")
.description("some-description")
.rules(ruleToConvert)
.build();
NovaSecurityGroupToSecurityGroup parser = createGroupParser();
SecurityGroup group = parser.apply(origGroup);
assertEquals(group.getId(), origGroup.getId());
assertEquals(group.getProviderId(), origGroup.getId());
assertEquals(group.getName(), origGroup.getName());
assertEquals(group.getOwnerId(), origGroup.getTenantId());
assertEquals(group.getIpPermissions(), ImmutableSet.copyOf(transform(origGroup.getRules(), ruleConverter)));
}
private NovaSecurityGroupToSecurityGroup createGroupParser() {
NovaSecurityGroupToSecurityGroup parser = new NovaSecurityGroupToSecurityGroup(ruleConverter);
return parser;
}
}

View File

@ -0,0 +1,86 @@
/*
* 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.openstack.nova.v2_0.compute.functions;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import org.jclouds.net.domain.IpPermission;
import org.jclouds.net.domain.IpProtocol;
import org.jclouds.openstack.nova.v2_0.domain.SecurityGroupRule;
import org.jclouds.openstack.nova.v2_0.domain.TenantIdAndName;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
/**
* Tests for the function for transforming a nova specific SecurityGroupRule into a generic
* IpPermission object.
*
* @author Andrew Bayer
*/
public class SecurityGroupRuleToIpPermissionTest {
@Test
public void testApplyWithGroup() {
TenantIdAndName group = TenantIdAndName.builder().tenantId("tenant").name("name").build();
SecurityGroupRule ruleToConvert = SecurityGroupRule.builder()
.id("some-id")
.ipProtocol(IpProtocol.TCP)
.fromPort(10)
.toPort(20)
.group(group)
.parentGroupId("some-other-id")
.build();
SecurityGroupRuleToIpPermission converter = new SecurityGroupRuleToIpPermission();
IpPermission convertedPerm = converter.apply(ruleToConvert);
assertEquals(convertedPerm.getIpProtocol(), ruleToConvert.getIpProtocol());
assertEquals(convertedPerm.getFromPort(), ruleToConvert.getFromPort());
assertEquals(convertedPerm.getToPort(), ruleToConvert.getToPort());
assertTrue(convertedPerm.getTenantIdGroupNamePairs().containsKey(group.getTenantId()));
assertTrue(convertedPerm.getTenantIdGroupNamePairs().containsValue(group.getName()));
assertTrue(convertedPerm.getCidrBlocks().size() == 0);
}
@Test
public void testApplyWithCidr() {
SecurityGroupRule ruleToConvert = SecurityGroupRule.builder()
.id("some-id")
.ipProtocol(IpProtocol.TCP)
.fromPort(10)
.toPort(20)
.ipRange("0.0.0.0/0")
.parentGroupId("some-other-id")
.build();
SecurityGroupRuleToIpPermission converter = new SecurityGroupRuleToIpPermission();
IpPermission convertedPerm = converter.apply(ruleToConvert);
assertEquals(convertedPerm.getIpProtocol(), ruleToConvert.getIpProtocol());
assertEquals(convertedPerm.getFromPort(), ruleToConvert.getFromPort());
assertEquals(convertedPerm.getToPort(), ruleToConvert.getToPort());
assertEquals(convertedPerm.getCidrBlocks(), ImmutableSet.of("0.0.0.0/0"));
assertTrue(convertedPerm.getTenantIdGroupNamePairs().size() == 0);
}
}

View File

@ -24,9 +24,9 @@ import java.net.URI;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.net.domain.IpProtocol;
import org.jclouds.openstack.nova.v2_0.NovaApi;
import org.jclouds.openstack.nova.v2_0.domain.Ingress;
import org.jclouds.openstack.nova.v2_0.domain.IpProtocol;
import org.jclouds.openstack.nova.v2_0.domain.SecurityGroup;
import org.jclouds.openstack.nova.v2_0.domain.SecurityGroupRule;
import org.jclouds.openstack.nova.v2_0.internal.BaseNovaApiExpectTest;

View File

@ -20,8 +20,8 @@ import static org.testng.Assert.assertNotNull;
import java.util.Set;
import org.jclouds.net.domain.IpProtocol;
import org.jclouds.openstack.nova.v2_0.domain.Ingress;
import org.jclouds.openstack.nova.v2_0.domain.IpProtocol;
import org.jclouds.openstack.nova.v2_0.domain.SecurityGroup;
import org.jclouds.openstack.nova.v2_0.domain.SecurityGroupRule;
import org.jclouds.openstack.nova.v2_0.internal.BaseNovaApiLiveTest;

View File

@ -23,8 +23,8 @@ import javax.ws.rs.core.MediaType;
import org.jclouds.json.BaseItemParserTest;
import org.jclouds.json.config.GsonModule;
import org.jclouds.net.domain.IpProtocol;
import org.jclouds.openstack.nova.v2_0.config.NovaParserModule;
import org.jclouds.openstack.nova.v2_0.domain.IpProtocol;
import org.jclouds.openstack.nova.v2_0.domain.SecurityGroup;
import org.jclouds.openstack.nova.v2_0.domain.SecurityGroupRule;
import org.jclouds.openstack.nova.v2_0.domain.TenantIdAndName;

View File

@ -23,8 +23,8 @@ import javax.ws.rs.core.MediaType;
import org.jclouds.json.BaseSetParserTest;
import org.jclouds.json.config.GsonModule;
import org.jclouds.net.domain.IpProtocol;
import org.jclouds.openstack.nova.v2_0.config.NovaParserModule;
import org.jclouds.openstack.nova.v2_0.domain.IpProtocol;
import org.jclouds.openstack.nova.v2_0.domain.SecurityGroup;
import org.jclouds.openstack.nova.v2_0.domain.SecurityGroupRule;
import org.jclouds.rest.annotations.SelectJson;

View File

@ -23,8 +23,8 @@ import javax.ws.rs.core.MediaType;
import org.jclouds.json.BaseItemParserTest;
import org.jclouds.json.config.GsonModule;
import org.jclouds.net.domain.IpProtocol;
import org.jclouds.openstack.nova.v2_0.config.NovaParserModule;
import org.jclouds.openstack.nova.v2_0.domain.IpProtocol;
import org.jclouds.openstack.nova.v2_0.domain.SecurityGroup;
import org.jclouds.openstack.nova.v2_0.domain.SecurityGroupRule;
import org.jclouds.openstack.nova.v2_0.domain.TenantIdAndName;

View File

@ -37,6 +37,7 @@ import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.compute.internal.BaseComputeService;
import org.jclouds.compute.internal.PersistNodeCredentials;
import org.jclouds.compute.options.TemplateOptions;
@ -84,12 +85,12 @@ public class TerremarkVCloudComputeService extends BaseComputeService {
RunScriptOnNode.Factory runScriptOnNodeFactory, InitAdminAccess initAdminAccess,
PersistNodeCredentials persistNodeCredentials, Timeouts timeouts,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, CleanupOrphanKeys cleanupOrphanKeys,
Optional<ImageExtension> imageExtension) {
Optional<ImageExtension> imageExtension, Optional<SecurityGroupExtension> securityGroupExtension) {
super(context, credentialStore, images, sizes, locations, listNodesStrategy, getImageStrategy,
getNodeMetadataStrategy, runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy,
resumeNodeStrategy, suspendNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning,
nodeTerminated, nodeSuspended, initScriptRunnerFactory, initAdminAccess, runScriptOnNodeFactory,
persistNodeCredentials, timeouts, userExecutor, imageExtension);
persistNodeCredentials, timeouts, userExecutor, imageExtension, securityGroupExtension);
this.cleanupOrphanKeys = cleanupOrphanKeys;
}

View File

@ -27,6 +27,7 @@ import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.compute.internal.BaseComputeService;
import org.jclouds.compute.options.RunScriptOptions;
import org.jclouds.compute.options.TemplateOptions;
@ -383,5 +384,13 @@ public interface ComputeService {
@Beta
Optional<ImageExtension> getImageExtension();
/**
* Returns the {@link SecurityGroupExtension} for this provider if it implements it.
*
* @return an optional of the {@link SecurityGroupExtension} or {@link Optional#absent()} if not
* implemented
*/
@Beta
Optional<SecurityGroupExtension> getSecurityGroupExtension();
}

View File

@ -44,6 +44,7 @@ import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.compute.functions.CreateSshClientOncePortIsListeningOnNode;
import org.jclouds.compute.functions.DefaultCredentialsFromImageOrOverridingCredentials;
import org.jclouds.compute.functions.TemplateOptionsToStatement;
@ -306,5 +307,11 @@ public abstract class BaseComputeServiceContextModule extends AbstractModule {
return Optional.absent();
}
@Provides
@Singleton
protected Optional<SecurityGroupExtension> provideSecurityGroupExtension(Injector i){
return Optional.absent();
}
}

View File

@ -22,6 +22,6 @@ package org.jclouds.compute.domain;
*/
public enum ComputeType {
NODE, IMAGE, HARDWARE;
NODE, IMAGE, HARDWARE, SECURITYGROUP;
}

View File

@ -0,0 +1,80 @@
/*
* 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.compute.domain;
import static com.google.common.base.Preconditions.checkNotNull;
import java.net.URI;
import java.util.Map;
import java.util.Set;
import org.jclouds.compute.domain.ComputeType;
import org.jclouds.compute.domain.internal.ComputeMetadataImpl;
import org.jclouds.domain.Location;
import org.jclouds.domain.ResourceMetadata;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.net.domain.IpPermission;
import com.google.common.base.Objects.ToStringHelper;
import com.google.common.base.Predicate;
import com.google.common.collect.ComparisonChain;
import com.google.common.collect.ImmutableSet;
/**
* Describes a security group containing a set of @{link IpPermission}s
*
* @author Andrew Bayer
*/
public class SecurityGroup extends ComputeMetadataImpl {
private final Set<IpPermission> ipPermissions;
private final String ownerId;
public SecurityGroup(String providerId, String name, String id, @Nullable Location location, URI uri,
Map<String, String> userMetadata, Set<String> tags,
Iterable<IpPermission> ipPermissions,
@Nullable String ownerId) {
super(ComputeType.SECURITYGROUP, providerId, name, id, location, uri, userMetadata, tags);
this.ipPermissions = ImmutableSet.copyOf(checkNotNull(ipPermissions, "ipPermissions"));
this.ownerId = ownerId;
}
/**
*
* @return The set of @{link IpPermission}s for this security group
*/
public Set<IpPermission> getIpPermissions() {
return ipPermissions;
}
/**
*
* @return the owner ID. Can be null.
*/
public String getOwnerId() {
return ownerId;
}
@Override
protected ToStringHelper string() {
ToStringHelper helper = computeToStringPrefix();
if (ipPermissions.size() > 0)
helper.add("ipPermissions", ipPermissions);
return addComputeToStringSuffix(helper);
}
}

View File

@ -0,0 +1,122 @@
/*
* 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.compute.domain;
import static com.google.common.base.Preconditions.checkNotNull;
import java.net.URI;
import java.util.Map;
import java.util.Set;
import org.jclouds.domain.Location;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.net.domain.IpPermission;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
/**
* @author Andrew Bayer
*/
public class SecurityGroupBuilder extends ComputeMetadataBuilder {
private ImmutableSet.Builder<IpPermission> ipPermissions = ImmutableSet.<IpPermission> builder();
private String ownerId;
public SecurityGroupBuilder() {
super(ComputeType.SECURITYGROUP);
}
public SecurityGroupBuilder ipPermissions() {
this.ipPermissions = ImmutableSet.<IpPermission> builder();
return this;
}
public SecurityGroupBuilder ipPermissions(Iterable<IpPermission> ipPermissions) {
this.ipPermissions.addAll(checkNotNull(ipPermissions, "ipPermissions"));
return this;
}
public SecurityGroupBuilder ipPermission(IpPermission ipPermission) {
this.ipPermissions.add(checkNotNull(ipPermission, "ipPermission"));
return this;
}
public SecurityGroupBuilder ownerId(String ownerId) {
this.ownerId = ownerId;
return this;
}
@Override
public SecurityGroupBuilder id(String id) {
return SecurityGroupBuilder.class.cast(super.id(id));
}
@Override
public SecurityGroupBuilder tags(Iterable<String> tags) {
return SecurityGroupBuilder.class.cast(super.tags(tags));
}
@Override
public SecurityGroupBuilder ids(String id) {
return SecurityGroupBuilder.class.cast(super.ids(id));
}
@Override
public SecurityGroupBuilder providerId(String providerId) {
return SecurityGroupBuilder.class.cast(super.providerId(providerId));
}
@Override
public SecurityGroupBuilder name(String name) {
return SecurityGroupBuilder.class.cast(super.name(name));
}
@Override
public SecurityGroupBuilder location(Location location) {
return SecurityGroupBuilder.class.cast(super.location(location));
}
@Override
public SecurityGroupBuilder uri(URI uri) {
return SecurityGroupBuilder.class.cast(super.uri(uri));
}
@Override
public SecurityGroupBuilder userMetadata(Map<String, String> userMetadata) {
return SecurityGroupBuilder.class.cast(super.userMetadata(userMetadata));
}
@Override
public SecurityGroup build() {
return new SecurityGroup(providerId, name, id, location, uri, userMetadata, tags,
ipPermissions.build(), ownerId);
}
public static SecurityGroupBuilder fromSecurityGroup(SecurityGroup group) {
return new SecurityGroupBuilder().providerId(group.getProviderId())
.name(group.getName())
.id(group.getId())
.location(group.getLocation())
.uri(group.getUri())
.userMetadata(group.getUserMetadata())
.tags(group.getTags())
.ipPermissions(group.getIpPermissions())
.ownerId(group.getOwnerId());
}
}

View File

@ -0,0 +1,180 @@
/*
* 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.compute.extensions;
import java.util.Set;
import org.jclouds.compute.domain.SecurityGroup;
import org.jclouds.domain.Location;
import org.jclouds.net.domain.IpPermission;
import org.jclouds.net.domain.IpProtocol;
import com.google.common.collect.Multimap;
import com.google.common.util.concurrent.ListenableFuture;
/**
* An extension to compute service to allow for the manipulation of {@link SecurityGroup}s. Implementation
* is optional by providers.
*
* @author Andrew Bayer
*/
public interface SecurityGroupExtension {
/**
* List security groups.
*
* @return The set of @{link SecurityGroup}s we have access to.
*/
Set<SecurityGroup> listSecurityGroups();
/**
* List security groups in a given @{link Location}.
*
* @return The set of @{link SecurityGroup}s we have access to in the given location.
*/
Set<SecurityGroup> listSecurityGroupsInLocation(Location location);
/**
* List security groups for a given instance given the instance's ID.
*
* @return The set of @{link SecurityGroup}s for the given instance..
*/
Set<SecurityGroup> listSecurityGroupsForNode(String id);
/**
* Get a security group by id.
*
* @return The @{link SecurityGroup}, if it exists.
*/
SecurityGroup getSecurityGroupById(String id);
/**
* Create a new @{link SecurityGroup} from the parameters given.
*
* @param name
* The name of the security group
* @param location
* The @{link Location} of the security group
*
* @return The SecurityGroup that has been created.
*/
SecurityGroup createSecurityGroup(String name, Location location);
/**
* Remove an existing @{link SecurityGroup}, and its permissions.
*
* @param id
* The id of the SecurityGroup to delete.
*
* @return true if we were able to remove the group, false otherwise.
*/
boolean removeSecurityGroup(String id);
/**
* Add a @{link IpPermission} to an existing @{link SecurityGroup}. Applies the permission to the
* security group on the provider.
*
* @param rule
* The IpPermission to add.
* @param group
* The SecurityGroup to add the permission to.
*
* @return The SecurityGroup with the new permission added, after the permission has been applied on the provider.
*/
SecurityGroup addIpPermission(IpPermission ipPermission, SecurityGroup group);
/**
* Remove a @{link IpPermission} from an existing @{link SecurityGroup}. Removes the permission from the
* security group on the provider.
*
* @param rule
* The IpPermission to remove.
* @param group
* The SecurityGroup to remove the permission from.
*
* @return The SecurityGroup with the permission removed, after the permission has been removed on the provider.
*/
SecurityGroup removeIpPermission(IpPermission ipPermission, SecurityGroup group);
/**
* Add a @{link IpPermission} to an existing @{link SecurityGroup}, based on the parameters given.
* Applies the permission to the security group on the provider.
*
* @param protocol
* The @{link IpProtocol} for the permission.
* @param startPort
* The first port in the range to be opened, or -1 for ICMP.
* @param endPort
* The last port in the range to be opened, or -1 for ICMP.
* @param tenantIdGroupNamePairs
* source of traffic allowed is on basis of another group in a tenant, as opposed to by cidr
* @param ipRanges
* An Iterable of Strings representing the IP range(s) the permission should allow.
* @param groupIds
* An Iterable of @{link SecurityGroup} IDs this permission should allow.
* @param group
* The SecurityGroup to add the permission to.
*
* @return The SecurityGroup with the new permission added, after the permission has been applied on the provider.
*/
SecurityGroup addIpPermission(IpProtocol protocol, int startPort, int endPort,
Multimap<String, String> tenantIdGroupNamePairs,
Iterable<String> ipRanges,
Iterable<String> groupIds, SecurityGroup group);
/**
* Remove a @{link IpPermission} from an existing @{link SecurityGroup}, based on the parameters given.
* Removes the permission from the security group on the provider.
*
* @param protocol
* The @{link IpProtocol} for the permission.
* @param startPort
* The first port in the range to be opened, or -1 for ICMP.
* @param endPort
* The last port in the range to be opened, or -1 for ICMP.
* @param tenantIdGroupNamePairs
* source of traffic allowed is on basis of another group in a tenant, as opposed to by cidr
* @param ipRanges
* An Iterable of Strings representing the IP range(s) the permission should allow.
* @param groupIds
* An Iterable of @{link SecurityGroup} IDs this permission should allow.
* @param group
* The SecurityGroup to remove the permission from.
*
* @return The SecurityGroup with the permission removed, after the permission has been removed from the provider.
*/
SecurityGroup removeIpPermission(IpProtocol protocol, int startPort, int endPort,
Multimap<String, String> tenantIdGroupNamePairs,
Iterable<String> ipRanges,
Iterable<String> groupIds, SecurityGroup group);
/**
* Returns true if this SecurityGroupExtension supports tenant ID + group name pairs.
*/
boolean supportsTenantIdGroupNamePairs();
/**
* Returns true if this SecurityGroupExtension supports group IDs.
*/
boolean supportsGroupIds();
/**
* Returns true if this SecurityGroupExtension supports port ranges for group authorization.
*/
boolean supportsPortRangesForGroups();
}

View File

@ -66,6 +66,7 @@ import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.compute.options.RunScriptOptions;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.reference.ComputeServiceConstants;
@ -141,6 +142,7 @@ public class BaseComputeService implements ComputeService {
private final RunScriptOnNode.Factory runScriptOnNodeFactory;
private final ListeningExecutorService userExecutor;
private final Optional<ImageExtension> imageExtension;
private final Optional<SecurityGroupExtension> securityGroupExtension;
@Inject
protected BaseComputeService(ComputeServiceContext context, Map<String, Credentials> credentialStore,
@ -158,7 +160,7 @@ public class BaseComputeService implements ComputeService {
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory, InitAdminAccess initAdminAccess,
RunScriptOnNode.Factory runScriptOnNodeFactory, PersistNodeCredentials persistNodeCredentials,
Timeouts timeouts, @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
Optional<ImageExtension> imageExtension) {
Optional<ImageExtension> imageExtension, Optional<SecurityGroupExtension> securityGroupExtension) {
this.context = checkNotNull(context, "context");
this.credentialStore = checkNotNull(credentialStore, "credentialStore");
this.images = checkNotNull(images, "images");
@ -184,6 +186,7 @@ public class BaseComputeService implements ComputeService {
this.persistNodeCredentials = checkNotNull(persistNodeCredentials, "persistNodeCredentials");
this.userExecutor = checkNotNull(userExecutor, "userExecutor");
this.imageExtension = checkNotNull(imageExtension, "imageExtension");
this.securityGroupExtension = checkNotNull(securityGroupExtension, "securityGroupExtension");
}
/**
@ -714,4 +717,11 @@ public class BaseComputeService implements ComputeService {
return imageExtension;
}
/**
* {@inheritDoc}
*/
@Override
public Optional<SecurityGroupExtension> getSecurityGroupExtension() {
return securityGroupExtension;
}
}

View File

@ -70,6 +70,8 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
to.inboundPorts(this.getInboundPorts());
if (this.getRunScript() != null)
to.runScript(this.getRunScript());
if (this.getGroups().size() > 0)
to.securityGroups(this.getGroups());
if (this.getPrivateKey() != null)
to.installPrivateKey(this.getPrivateKey());
if (this.getPublicKey() != null)
@ -294,6 +296,21 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
throw new IllegalArgumentException("tags are immutable");
}
@Override
public Set<String> getGroups() {
return delegate.getGroups();
}
@Override
public TemplateOptions securityGroups(Iterable<String> securityGroups) {
throw new IllegalArgumentException("tags are immutable");
}
@Override
public TemplateOptions securityGroups(String... securityGroups) {
throw new IllegalArgumentException("tags are immutable");
}
@Override
public TemplateOptions userMetadata(Map<String, String> userMetadata) {
throw new IllegalArgumentException("userMetadata is immutable");
@ -321,6 +338,8 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
protected Set<String> tags = ImmutableSet.of();
protected Set<String> securityGroups = ImmutableSet.of();
protected String privateKey;
protected String publicKey;
@ -339,13 +358,13 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
return super.equals(that) && equal(this.inboundPorts, that.inboundPorts) && equal(this.script, that.script)
&& equal(this.publicKey, that.publicKey) && equal(this.privateKey, that.privateKey)
&& equal(this.blockUntilRunning, that.blockUntilRunning) && equal(this.tags, that.tags)
&& equal(this.userMetadata, that.userMetadata);
&& equal(this.securityGroups, that.securityGroups) && equal(this.userMetadata, that.userMetadata);
}
@Override
public int hashCode() {
return Objects.hashCode(super.hashCode(), inboundPorts, script, publicKey, privateKey, blockUntilRunning, tags,
userMetadata);
securityGroups, userMetadata);
}
@Override
@ -363,6 +382,8 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
toString.add("blockUntilRunning", blockUntilRunning);
if (tags.size() != 0)
toString.add("tags", tags);
if (securityGroups.size() != 0)
toString.add("securityGroups", securityGroups);
if (userMetadata.size() != 0)
toString.add("userMetadata", userMetadata);
return toString;
@ -380,6 +401,10 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
return tags;
}
public Set<String> getGroups() {
return securityGroups;
}
public String getPrivateKey() {
return privateKey;
}
@ -450,6 +475,21 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
return this;
}
/**
* assigns the created nodes to these security groups
*/
public TemplateOptions securityGroups(Iterable<String> securityGroups) {
this.securityGroups = ImmutableSet.copyOf(checkNotNull(securityGroups, "securityGroups"));
return this;
}
/**
* @see TemplateOptions#securityGroups(Iterable<String>)
*/
public TemplateOptions securityGroups(String... securityGroups) {
return securityGroups(ImmutableSet.copyOf(securityGroups));
}
/**
* Opens the set of ports to public access.
*/
@ -521,6 +561,22 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
return options.tags(tags);
}
/**
* @see TemplateOptions#securityGroups
*/
public static TemplateOptions securityGroups(Iterable<String> securityGroups) {
TemplateOptions options = new TemplateOptions();
return options.securityGroups(securityGroups);
}
/**
* @see TemplateOptions#securityGroups
*/
public static TemplateOptions securityGroups(String... securityGroups) {
TemplateOptions options = new TemplateOptions();
return options.securityGroups(securityGroups);
}
/**
* @see TemplateOptions#blockUntilRunning(boolean)
*/

View File

@ -41,13 +41,18 @@ import org.jclouds.compute.domain.NodeMetadata.Status;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.SecurityGroup;
import org.jclouds.compute.domain.SecurityGroupBuilder;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.compute.predicates.ImagePredicates;
import org.jclouds.domain.Location;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.location.suppliers.all.JustProvider;
import org.jclouds.rest.ResourceNotFoundException;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
@ -55,6 +60,7 @@ import com.google.common.collect.ImmutableList.Builder;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.ListeningExecutorService;
@ -66,20 +72,25 @@ import com.google.common.util.concurrent.ListeningExecutorService;
public class StubComputeServiceAdapter implements JCloudsNativeComputeServiceAdapter {
private final Supplier<Location> location;
private final ConcurrentMap<String, NodeMetadata> nodes;
private final Multimap<String, SecurityGroup> groupsForNodes;
private final ListeningExecutorService ioExecutor;
private final Provider<Integer> idProvider;
private final Provider<Integer> groupIdProvider;
private final String publicIpPrefix;
private final String privateIpPrefix;
private final String passwordPrefix;
private final Supplier<Set<? extends Location>> locationSupplier;
private final Map<OsFamily, Map<String, String>> osToVersionMap;
private final Optional<SecurityGroupExtension> securityGroupExtension;
@Inject
public StubComputeServiceAdapter(ConcurrentMap<String, NodeMetadata> nodes,
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ListeningExecutorService ioExecutor, Supplier<Location> location,
@Named("NODE_ID") Provider<Integer> idProvider, @Named("PUBLIC_IP_PREFIX") String publicIpPrefix,
@Named("PRIVATE_IP_PREFIX") String privateIpPrefix, @Named("PASSWORD_PREFIX") String passwordPrefix,
JustProvider locationSupplier, Map<OsFamily, Map<String, String>> osToVersionMap) {
JustProvider locationSupplier, Map<OsFamily, Map<String, String>> osToVersionMap,
Multimap<String, SecurityGroup> groupsForNodes, @Named("GROUP_ID") Provider<Integer> groupIdProvider,
Optional<SecurityGroupExtension> securityGroupExtension) {
this.nodes = nodes;
this.ioExecutor = ioExecutor;
this.location = location;
@ -89,6 +100,9 @@ public class StubComputeServiceAdapter implements JCloudsNativeComputeServiceAda
this.passwordPrefix = passwordPrefix;
this.locationSupplier = locationSupplier;
this.osToVersionMap = osToVersionMap;
this.groupsForNodes = groupsForNodes;
this.groupIdProvider = groupIdProvider;
this.securityGroupExtension = securityGroupExtension;
}
protected void setStateOnNode(Status status, NodeMetadata node) {
@ -133,6 +147,22 @@ public class StubComputeServiceAdapter implements JCloudsNativeComputeServiceAda
builder.credentials(LoginCredentials.builder().user("root").password(passwordPrefix + id).build());
NodeMetadata node = builder.build();
nodes.put(node.getId(), node);
if (template.getOptions().getGroups().size() > 0) {
final String groupId = Iterables.getFirst(template.getOptions().getGroups(), "0");
Optional<SecurityGroup> secGroup = Iterables.tryFind(securityGroupExtension.get().listSecurityGroups(),
new Predicate<SecurityGroup>() {
@Override
public boolean apply(SecurityGroup input) {
return input.getId().equals(groupId);
}
});
if (secGroup.isPresent()) {
groupsForNodes.put(node.getId(), secGroup.get());
}
}
setStateOnNodeAfterDelay(Status.RUNNING, node, 100);
return new NodeWithInitialCredentials(node);
}
@ -195,6 +225,8 @@ public class StubComputeServiceAdapter implements JCloudsNativeComputeServiceAda
return;
setStateOnNodeAfterDelay(Status.PENDING, node, 0);
setStateOnNodeAfterDelay(Status.TERMINATED, node, 50);
groupsForNodes.removeAll(id);
ioExecutor.execute(new Runnable() {
@Override

View File

@ -17,8 +17,12 @@
package org.jclouds.compute.stub.config;
import org.jclouds.compute.config.JCloudsNativeComputeServiceAdapterContextModule;
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.concurrent.SingleThreaded;
import com.google.common.base.Optional;
import com.google.inject.Injector;
/**
*
* @author Adrian Cole
@ -35,4 +39,10 @@ public class StubComputeServiceContextModule extends JCloudsNativeComputeService
install(new StubComputeServiceDependenciesModule());
super.configure();
}
@Override
protected Optional<SecurityGroupExtension> provideSecurityGroupExtension(Injector i) {
return Optional.of(i.getInstance(SecurityGroupExtension.class));
}
}

View File

@ -29,8 +29,11 @@ import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadata.Status;
import org.jclouds.compute.domain.Processor;
import org.jclouds.compute.domain.SecurityGroup;
import org.jclouds.compute.domain.Volume;
import org.jclouds.compute.domain.internal.VolumeImpl;
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.compute.stub.extensions.StubSecurityGroupExtension;
import org.jclouds.domain.Credentials;
import org.jclouds.location.Provider;
import org.jclouds.predicates.SocketOpen;
@ -40,9 +43,12 @@ import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.net.HostAndPort;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
/**
*
@ -52,6 +58,8 @@ public class StubComputeServiceDependenciesModule extends AbstractModule {
@Override
protected void configure() {
bind(new TypeLiteral<SecurityGroupExtension>() {
}).to(StubSecurityGroupExtension.class);
}
@ -73,6 +81,40 @@ public class StubComputeServiceDependenciesModule extends AbstractModule {
return backing.get(creds.get().identity);
}
protected static final LoadingCache<String, ConcurrentMap<String, SecurityGroup>> groupBacking = CacheBuilder.newBuilder()
.build(new CacheLoader<String, ConcurrentMap<String, SecurityGroup>>() {
@Override
public ConcurrentMap<String, SecurityGroup> load(String arg0) throws Exception {
return new ConcurrentHashMap<String, SecurityGroup>();
}
});
@Provides
@Singleton
protected ConcurrentMap<String, SecurityGroup> provideGroups(@Provider Supplier<Credentials> creds)
throws ExecutionException {
return groupBacking.get(creds.get().identity);
}
protected static final LoadingCache<String, Multimap<String, SecurityGroup>> groupsForNodeBacking = CacheBuilder.newBuilder()
.build(new CacheLoader<String, Multimap<String, SecurityGroup>>() {
@Override
public Multimap<String, SecurityGroup> load(String arg0) throws Exception {
return LinkedHashMultimap.create();
}
});
@Provides
@Singleton
protected Multimap<String, SecurityGroup> provideGroupsForNode(@Provider Supplier<Credentials> creds)
throws ExecutionException {
return groupsForNodeBacking.get(creds.get().identity);
}
protected static final LoadingCache<String, AtomicInteger> nodeIds = CacheBuilder.newBuilder().build(
new CacheLoader<String, AtomicInteger>() {
@ -89,6 +131,22 @@ public class StubComputeServiceDependenciesModule extends AbstractModule {
return nodeIds.get(creds.get().identity).incrementAndGet();
}
protected static final LoadingCache<String, AtomicInteger> groupIds = CacheBuilder.newBuilder().build(
new CacheLoader<String, AtomicInteger>() {
@Override
public AtomicInteger load(String arg0) throws Exception {
return new AtomicInteger(0);
}
});
@Provides
@Named("GROUP_ID")
protected Integer provideGroupIdForIdentity(@Provider Supplier<Credentials> creds) throws ExecutionException {
return groupIds.get(creds.get().identity).incrementAndGet();
}
@Singleton
@Provides
@Named("PUBLIC_IP_PREFIX")

View File

@ -0,0 +1,256 @@
/*
* 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.compute.stub.extensions;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.equalTo;
import static com.google.common.base.Predicates.not;
import static com.google.common.collect.Iterables.filter;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider;
import org.jclouds.Constants;
import org.jclouds.compute.domain.SecurityGroup;
import org.jclouds.compute.domain.SecurityGroupBuilder;
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.domain.Location;
import org.jclouds.location.suppliers.all.JustProvider;
import org.jclouds.net.domain.IpPermission;
import org.jclouds.net.domain.IpProtocol;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
* An extension to compute service to allow for the manipulation of {@link SecurityGroup}s. Implementation
* is optional by providers.
*
* @author Andrew Bayer
*/
public class StubSecurityGroupExtension implements SecurityGroupExtension {
private final Supplier<Location> location;
private final Provider<Integer> groupIdProvider;
private final Supplier<Set<? extends Location>> locationSupplier;
private final ListeningExecutorService ioExecutor;
private final ConcurrentMap<String, SecurityGroup> groups;
private final Multimap<String, SecurityGroup> groupsForNodes;
@Inject
public StubSecurityGroupExtension(ConcurrentMap<String, SecurityGroup> groups,
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ListeningExecutorService ioExecutor,
Supplier<Location> location,
@Named("GROUP_ID") Provider<Integer> groupIdProvider,
JustProvider locationSupplier,
Multimap<String, SecurityGroup> groupsForNodes) {
this.groups = groups;
this.ioExecutor = ioExecutor;
this.location = location;
this.groupIdProvider = groupIdProvider;
this.locationSupplier = locationSupplier;
this.groupsForNodes = groupsForNodes;
}
@Override
public Set<SecurityGroup> listSecurityGroups() {
return ImmutableSet.copyOf(groups.values());
}
@Override
public Set<SecurityGroup> listSecurityGroupsInLocation(final Location location) {
return ImmutableSet.copyOf(filter(groups.values(), new Predicate<SecurityGroup>() {
@Override
public boolean apply(SecurityGroup group) {
return group.getLocation().equals(location);
}
}));
}
@Override
public Set<SecurityGroup> listSecurityGroupsForNode(String nodeId) {
return ImmutableSet.copyOf(groupsForNodes.get(nodeId));
}
@Override
public SecurityGroup getSecurityGroupById(String id) {
return groups.get(id);
}
@Override
public SecurityGroup createSecurityGroup(String name, Location location) {
SecurityGroupBuilder builder = new SecurityGroupBuilder();
String id = groupIdProvider.get() + "";
builder.ids(id);
builder.name(name);
builder.location(location);
SecurityGroup group = builder.build();
groups.put(group.getId(), group);
return group;
}
@Override
public boolean removeSecurityGroup(String id) {
if (groups.containsKey(id)) {
groups.remove(id);
return true;
}
return false;
}
@Override
public SecurityGroup addIpPermission(IpPermission ipPermission, SecurityGroup group) {
SecurityGroupBuilder builder = SecurityGroupBuilder.fromSecurityGroup(checkNotNull(group, "group"));
builder.ipPermission(checkNotNull(ipPermission, "ipPermission"));
SecurityGroup newGroup = builder.build();
if (groups.containsKey(newGroup.getId())) {
groups.remove(newGroup.getId());
}
groups.put(newGroup.getId(), newGroup);
return newGroup;
}
@Override
public SecurityGroup addIpPermission(IpProtocol protocol, int startPort, int endPort,
Multimap<String, String> tenantIdGroupNamePairs,
Iterable<String> ipRanges,
Iterable<String> groupIds, SecurityGroup group) {
IpPermission.Builder ipBuilder = IpPermission.builder();
ipBuilder.ipProtocol(protocol);
ipBuilder.fromPort(startPort);
ipBuilder.toPort(endPort);
if (tenantIdGroupNamePairs.size() > 0) {
ipBuilder.tenantIdGroupNamePairs(tenantIdGroupNamePairs);
}
if (Iterables.size(ipRanges) > 0) {
ipBuilder.cidrBlocks(ipRanges);
}
if (Iterables.size(groupIds) > 0) {
ipBuilder.groupIds(groupIds);
}
IpPermission perm = ipBuilder.build();
SecurityGroupBuilder builder = SecurityGroupBuilder.fromSecurityGroup(checkNotNull(group, "group"));
builder.ipPermission(perm);
SecurityGroup newGroup = builder.build();
if (groups.containsKey(newGroup.getId())) {
groups.remove(newGroup.getId());
}
groups.put(newGroup.getId(), newGroup);
return newGroup;
}
@Override
public SecurityGroup removeIpPermission(IpPermission ipPermission, SecurityGroup group) {
SecurityGroupBuilder builder = SecurityGroupBuilder.fromSecurityGroup(checkNotNull(group, "group"));
builder.ipPermissions();
builder.ipPermissions(filter(group.getIpPermissions(), not(equalTo(ipPermission))));
SecurityGroup newGroup = builder.build();
if (groups.containsKey(newGroup.getId())) {
groups.remove(newGroup.getId());
}
groups.put(newGroup.getId(), newGroup);
return newGroup;
}
@Override
public SecurityGroup removeIpPermission(IpProtocol protocol, int startPort, int endPort,
Multimap<String, String> tenantIdGroupNamePairs,
Iterable<String> ipRanges,
Iterable<String> groupIds, SecurityGroup group) {
IpPermission.Builder ipBuilder = IpPermission.builder();
ipBuilder.ipProtocol(protocol);
ipBuilder.fromPort(startPort);
ipBuilder.toPort(endPort);
if (tenantIdGroupNamePairs.size() > 0) {
ipBuilder.tenantIdGroupNamePairs(tenantIdGroupNamePairs);
}
if (Iterables.size(ipRanges) > 0) {
ipBuilder.cidrBlocks(ipRanges);
}
if (Iterables.size(groupIds) > 0) {
ipBuilder.groupIds(groupIds);
}
IpPermission perm = ipBuilder.build();
SecurityGroupBuilder builder = SecurityGroupBuilder.fromSecurityGroup(checkNotNull(group, "group"));
builder.ipPermissions();
builder.ipPermissions(filter(group.getIpPermissions(), not(equalTo(perm))));
SecurityGroup newGroup = builder.build();
if (groups.containsKey(newGroup.getId())) {
groups.remove(newGroup.getId());
}
groups.put(newGroup.getId(), newGroup);
return newGroup;
}
@Override
public boolean supportsTenantIdGroupNamePairs() {
return false;
}
@Override
public boolean supportsGroupIds() {
return true;
}
@Override
public boolean supportsPortRangesForGroups() {
return true;
}
}

View File

@ -17,11 +17,15 @@
package org.jclouds.net.domain;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.transform;
import static org.jclouds.util.Strings2.isCidrFormat;
import java.util.Set;
import com.google.common.annotations.Beta;
import com.google.common.base.Function;
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
import com.google.common.collect.ImmutableMultimap;
@ -100,6 +104,7 @@ public class IpPermission implements Comparable<IpPermission> {
* @see IpPermission#getCidrBlocks()
*/
public Builder cidrBlock(String cidrBlock) {
checkArgument(isCidrFormat(cidrBlock), "cidrBlock %s is not a valid CIDR", cidrBlock);
this.cidrBlocks.add(cidrBlock);
return this;
}
@ -108,7 +113,16 @@ public class IpPermission implements Comparable<IpPermission> {
* @see IpPermission#getCidrBlocks()
*/
public Builder cidrBlocks(Iterable<String> cidrBlocks) {
Iterables.addAll(this.cidrBlocks, cidrBlocks);
Iterables.addAll(this.cidrBlocks, transform(cidrBlocks,
new Function<String, String>() {
@Override
public String apply(String input) {
checkArgument(isCidrFormat(input),
"input %s is not a valid CIDR",
input);
return input;
}
}));
return this;
}
@ -140,7 +154,7 @@ public class IpPermission implements Comparable<IpPermission> {
private final IpProtocol ipProtocol;
private final Set<String> cidrBlocks;
protected IpPermission(IpProtocol ipProtocol, int fromPort, int toPort,
public IpPermission(IpProtocol ipProtocol, int fromPort, int toPort,
Multimap<String, String> tenantIdGroupNamePairs, Iterable<String> groupIds, Iterable<String> cidrBlocks) {
this.fromPort = fromPort;
this.toPort = toPort;
@ -227,8 +241,8 @@ public class IpPermission implements Comparable<IpPermission> {
protected ToStringHelper string() {
return Objects.toStringHelper("").add("ipProtocol", ipProtocol).add("fromPort", fromPort).add("toPort", toPort)
.add("tenantIdGroupNamePairs", tenantIdGroupNamePairs).add("groupIds", groupIds).add("groupIds",
groupIds);
.add("tenantIdGroupNamePairs", tenantIdGroupNamePairs).add("groupIds", groupIds).add("cidrBlocks",
cidrBlocks);
}
}

View File

@ -29,12 +29,22 @@ public enum IpProtocol {
TCP, UDP, ICMP, ALL, UNRECOGNIZED;
public String value() {
return this == ALL ? "-1" : name().toLowerCase();
}
@Override
public String toString() {
return value();
}
public static IpProtocol fromValue(String protocol) {
try {
if (protocol.equalsIgnoreCase("-1"))
return ALL;
return valueOf(checkNotNull(protocol, "protocol").toUpperCase());
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}

View File

@ -0,0 +1,348 @@
/*
* 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.compute.extensions.internal;
import static java.util.concurrent.TimeUnit.SECONDS;
import static com.google.common.base.Predicates.equalTo;
import static com.google.common.base.Predicates.not;
import static com.google.common.collect.Iterables.filter;
import static org.jclouds.compute.predicates.NodePredicates.inGroup;
import static org.jclouds.util.Predicates2.retry;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import javax.annotation.Resource;
import javax.inject.Named;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.RunNodesException;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.SecurityGroup;
import org.jclouds.compute.domain.SecurityGroupBuilder;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.Location;
import org.jclouds.logging.Logger;
import org.jclouds.net.domain.IpPermission;
import org.jclouds.net.domain.IpProtocol;
import org.jclouds.ssh.SshClient;
import org.testng.annotations.Test;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
/**
* Base test for {@link SecurityGroupExtension} implementations.
*
* @author David Alves
*
*/
public abstract class BaseSecurityGroupExtensionLiveTest extends BaseComputeServiceContextLiveTest {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
protected String groupId;
/**
* Returns the template for the base node, override to test different templates.
*
* @return
*/
public Template getNodeTemplate() {
return view.getComputeService().templateBuilder().build();
}
@Test(groups = { "integration", "live" }, singleThreaded = true)
public void testCreateSecurityGroup() throws RunNodesException, InterruptedException, ExecutionException {
ComputeService computeService = view.getComputeService();
Location location = getNodeTemplate().getLocation();
Optional<SecurityGroupExtension> securityGroupExtension = computeService.getSecurityGroupExtension();
assertTrue(securityGroupExtension.isPresent(), "security extension was not present");
SecurityGroup group = securityGroupExtension.get().createSecurityGroup("test-create-security-group", location);
logger.info("Group created: %s", group);
assertTrue(group.getName().contains("test-create-security-group"));
groupId = group.getId();
}
@Test(groups = { "integration", "live" }, singleThreaded = true, dependsOnMethods = "testCreateSecurityGroup")
public void testGetSecurityGroupById() throws RunNodesException, InterruptedException, ExecutionException {
ComputeService computeService = view.getComputeService();
Location location = getNodeTemplate().getLocation();
Optional<SecurityGroupExtension> securityGroupExtension = computeService.getSecurityGroupExtension();
assertTrue(securityGroupExtension.isPresent(), "security extension was not present");
SecurityGroup group = securityGroupExtension.get().getSecurityGroupById(groupId);
logger.info("Group found: %s", group);
assertTrue(group.getName().contains("test-create-security-group"));
}
@Test(groups = { "integration", "live" }, singleThreaded = true, dependsOnMethods = "testGetSecurityGroupById")
public void testAddIpPermission() {
ComputeService computeService = view.getComputeService();
Optional<SecurityGroupExtension> securityGroupExtension = computeService.getSecurityGroupExtension();
assertTrue(securityGroupExtension.isPresent(), "security group extension was not present");
Optional<SecurityGroup> optGroup = getGroup(securityGroupExtension.get());
assertTrue(optGroup.isPresent());
SecurityGroup group = optGroup.get();
IpPermission.Builder builder = IpPermission.builder();
builder.ipProtocol(IpProtocol.TCP);
builder.fromPort(10);
builder.toPort(20);
builder.cidrBlock("0.0.0.0/0");
IpPermission perm = builder.build();
SecurityGroup newGroup = securityGroupExtension.get().addIpPermission(perm, group);
assertEquals(perm, Iterables.getOnlyElement(newGroup.getIpPermissions()));
}
@Test(groups = { "integration", "live" }, singleThreaded = true, dependsOnMethods = "testAddIpPermission")
public void testRemoveIpPermission() {
ComputeService computeService = view.getComputeService();
Optional<SecurityGroupExtension> securityGroupExtension = computeService.getSecurityGroupExtension();
assertTrue(securityGroupExtension.isPresent(), "security group extension was not present");
Optional<SecurityGroup> optGroup = getGroup(securityGroupExtension.get());
assertTrue(optGroup.isPresent());
SecurityGroup group = optGroup.get();
IpPermission.Builder builder = IpPermission.builder();
builder.ipProtocol(IpProtocol.TCP);
builder.fromPort(10);
builder.toPort(20);
builder.cidrBlock("0.0.0.0/0");
IpPermission perm = builder.build();
SecurityGroup newGroup = securityGroupExtension.get().removeIpPermission(perm, group);
assertEquals(0, Iterables.size(newGroup.getIpPermissions()));
}
@Test(groups = { "integration", "live" }, singleThreaded = true, dependsOnMethods = "testRemoveIpPermission")
public void testAddIpPermissionsFromSpec() {
ComputeService computeService = view.getComputeService();
Optional<SecurityGroupExtension> securityGroupExtension = computeService.getSecurityGroupExtension();
assertTrue(securityGroupExtension.isPresent(), "security group extension was not present");
Optional<SecurityGroup> optGroup = getGroup(securityGroupExtension.get());
assertTrue(optGroup.isPresent());
SecurityGroup group = optGroup.get();
IpPermission.Builder builder = IpPermission.builder();
builder.ipProtocol(IpProtocol.TCP);
builder.fromPort(50);
builder.toPort(60);
builder.cidrBlock("0.0.0.0/0");
IpPermission perm = builder.build();
SecurityGroup newGroup = securityGroupExtension.get().addIpPermission(IpProtocol.TCP,
50,
60,
emptyMultimap(),
ImmutableSet.of("0.0.0.0/0"),
emptyStringSet(),
group);
assertTrue(newGroup.getIpPermissions().contains(perm));
if (securityGroupExtension.get().supportsGroupIds()) {
IpPermission.Builder secondBuilder = IpPermission.builder();
int fromPort;
int toPort;
if (securityGroupExtension.get().supportsPortRangesForGroups()) {
fromPort = 70;
toPort = 80;
} else {
fromPort = 1;
toPort = 65535;
}
secondBuilder.ipProtocol(IpProtocol.TCP);
secondBuilder.fromPort(fromPort);
secondBuilder.toPort(toPort);
secondBuilder.groupId(group.getId());
IpPermission secondPerm = secondBuilder.build();
SecurityGroup secondNewGroup = securityGroupExtension.get().addIpPermission(IpProtocol.TCP,
fromPort,
toPort,
emptyMultimap(),
emptyStringSet(),
ImmutableSet.of(group.getId()),
newGroup);
assertTrue(secondNewGroup.getIpPermissions().contains(secondPerm));
}
if (securityGroupExtension.get().supportsTenantIdGroupNamePairs()) {
IpPermission.Builder thirdBuilder = IpPermission.builder();
int fromPort;
int toPort;
if (securityGroupExtension.get().supportsPortRangesForGroups()) {
fromPort = 90;
toPort = 100;
} else {
fromPort = 1;
toPort = 65535;
}
thirdBuilder.ipProtocol(IpProtocol.TCP);
thirdBuilder.fromPort(fromPort);
thirdBuilder.toPort(toPort);
thirdBuilder.tenantIdGroupNamePair(group.getOwnerId(), group.getId());
IpPermission thirdPerm = thirdBuilder.build();
SecurityGroup thirdNewGroup = securityGroupExtension.get().addIpPermission(IpProtocol.TCP,
fromPort,
toPort,
thirdPerm.getTenantIdGroupNamePairs(),
emptyStringSet(),
emptyStringSet(),
newGroup);
assertTrue(thirdNewGroup.getIpPermissions().contains(thirdPerm));
}
}
@Test(groups = { "integration", "live" }, singleThreaded = true, dependsOnMethods = "testAddIpPermissionsFromSpec")
public void testCreateNodeWithSecurityGroup() throws RunNodesException, InterruptedException, ExecutionException {
ComputeService computeService = view.getComputeService();
Optional<SecurityGroupExtension> securityGroupExtension = computeService.getSecurityGroupExtension();
assertTrue(securityGroupExtension.isPresent(), "security group extension was not present");
Template template = view.getComputeService().templateBuilder()
.options(TemplateOptions.Builder.securityGroups(groupId))
.build();
NodeMetadata node = Iterables.getOnlyElement(computeService.createNodesInGroup("test-create-node-with-group", 1, template));
Set<SecurityGroup> groups = securityGroupExtension.get().listSecurityGroupsForNode(node.getId());
assertTrue(groups.size() > 0, "node has no groups");
Optional<SecurityGroup> secGroup = Iterables.tryFind(securityGroupExtension.get().listSecurityGroupsForNode(node.getId()),
new Predicate<SecurityGroup>() {
@Override
public boolean apply(SecurityGroup input) {
return input.getId().equals(groupId);
}
});
assertTrue(secGroup.isPresent());
computeService.destroyNodesMatching(inGroup(node.getGroup()));
}
// testDeleteSecurityGroup currently disabled until I can find a way to get it to delete the security group while a terminated
// instance is still floating around in EC2. - abayer, 6/14/13
/*
@Test(groups = { "integration", "live" }, singleThreaded = true, dependsOnMethods = "testCreateNodeWithSecurityGroup")
public void testDeleteSecurityGroup() {
ComputeService computeService = view.getComputeService();
Optional<SecurityGroupExtension> securityGroupExtension = computeService.getSecurityGroupExtension();
assertTrue(securityGroupExtension.isPresent(), "security group extension was not present");
Optional<SecurityGroup> optGroup = getGroup(securityGroupExtension.get());
assertTrue(optGroup.isPresent());
SecurityGroup group = optGroup.get();
assertTrue(securityGroupExtension.get().removeSecurityGroup(group.getId()));
}
*/
private Multimap<String, String> emptyMultimap() {
return LinkedHashMultimap.create();
}
private Set<String> emptyStringSet() {
return Sets.newLinkedHashSet();
}
private Optional<SecurityGroup> getGroup(SecurityGroupExtension ext) {
return Iterables.tryFind(ext.listSecurityGroups(), new Predicate<SecurityGroup>() {
@Override
public boolean apply(SecurityGroup input) {
return input.getId().equals(groupId);
}
});
}
}

View File

@ -0,0 +1,70 @@
/*
* 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.compute.extensions.internal;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.jclouds.util.Predicates2.retry;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import java.util.Properties;
import java.util.concurrent.ExecutionException;
import javax.annotation.Resource;
import javax.inject.Named;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.RunNodesException;
import org.jclouds.compute.domain.SecurityGroup;
import org.jclouds.compute.domain.SecurityGroupBuilder;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.Location;
import org.jclouds.logging.Logger;
import org.jclouds.net.domain.IpPermission;
import org.jclouds.ssh.SshClient;
import org.testng.annotations.Test;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
/**
* Base test for {@link SecurityGroupExtension} implementations.
*
* @author Andrew Bayer
*
*/
@Test(groups = { "integration", "live" }, singleThreaded = true, testName="StubSecurityGroupExtensionIntegrationTest")
public class StubSecurityGroupExtensionIntegrationTest extends BaseSecurityGroupExtensionLiveTest {
public StubSecurityGroupExtensionIntegrationTest() {
provider = "stub";
}
@Override
protected Properties setupProperties() {
Properties overrides = super.setupProperties();
// This is a hack to make sure we get a different set of node IDs, nodes, groups, etc from StubComputeServiceIntegrationTest.
overrides.setProperty(provider + ".identity", "sec-stub");
return overrides;
}
}

View File

@ -37,6 +37,20 @@ public class IpPermissionsTest {
.cidrBlock("0.0.0.0/0").build());
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testAllProtocolInvalidCidr() {
IpPermissions authorization = IpPermissions.permitAnyProtocol();
assertEquals(authorization, IpPermission.builder().ipProtocol(IpProtocol.ALL).fromPort(1).toPort(65535)
.cidrBlock("a.0.0.0/0").build());
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testAllProtocolInvalidCidrMultiple() {
IpPermissions authorization = IpPermissions.permitAnyProtocol();
assertEquals(authorization, IpPermission.builder().ipProtocol(IpProtocol.ALL).fromPort(1).toPort(65535)
.cidrBlocks(ImmutableSet.of("a.0.0.0/0", "0.0.0.0/0")).build());
}
public void testAllProtocolCidrBound() {
IpPermissions authorization = IpPermissions.permit(IpProtocol.ALL).originatingFromCidrBlock("1.1.1.1/32");
assertEquals(authorization, IpPermission.builder().ipProtocol(IpProtocol.ALL).fromPort(1).toPort(65535)

View File

@ -87,7 +87,16 @@ public class Strings2 {
}
}
});
private static final String IP_ADDRESS = "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})";
private static final String SLASH_FORMAT = IP_ADDRESS + "/(\\d{1,3})";
private static final Pattern ADDRESS_PATTERN = Pattern.compile(IP_ADDRESS);
private static final Pattern CIDR_PATTERN = Pattern.compile(SLASH_FORMAT);
public static boolean isCidrFormat(String in) {
return CIDR_PATTERN.matcher(in).matches();
}
private static final Pattern URL_ENCODED_PATTERN = Pattern.compile(".*%[a-fA-F0-9][a-fA-F0-9].*");
public static boolean isUrlEncoded(String in) {

View File

@ -53,4 +53,12 @@ public class Strings2Test {
assertEquals(actual, urlDecode(urlEncode(actual)));
}
public void testIsCidrFormat() {
assert Strings2.isCidrFormat("1.2.3.4/5");
assert Strings2.isCidrFormat("0.0.0.0/0");
assert !Strings2.isCidrFormat("banana");
assert !Strings2.isCidrFormat("1.2.3.4");
assert !Strings2.isCidrFormat("500.500.500.500/2423");
}
}

View File

@ -46,6 +46,7 @@ import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.compute.internal.PersistNodeCredentials;
import org.jclouds.compute.options.TemplateOptions;
@ -104,13 +105,14 @@ public class AWSEC2ComputeService extends EC2ComputeService {
@Named("PLACEMENT") LoadingCache<RegionAndName, String> placementGroupMap,
@Named("DELETED") Predicate<PlacementGroup> placementGroupDeleted, Optional<ImageExtension> imageExtension,
GroupNamingConvention.Factory namingConvention,
@Named(PROPERTY_EC2_GENERATE_INSTANCE_NAMES) boolean generateInstanceNames) {
@Named(PROPERTY_EC2_GENERATE_INSTANCE_NAMES) boolean generateInstanceNames,
Optional<SecurityGroupExtension> securityGroupExtension) {
super(context, credentialStore, images, sizes, locations, listNodesStrategy, getImageStrategy,
getNodeMetadataStrategy, runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy,
startNodeStrategy, stopNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning,
nodeTerminated, nodeSuspended, initScriptRunnerFactory, runScriptOnNodeFactory, initAdminAccess,
persistNodeCredentials, timeouts, userExecutor, client, credentialsMap, securityGroupMap, imageExtension,
namingConvention, generateInstanceNames);
namingConvention, generateInstanceNames, securityGroupExtension);
this.client = client;
this.placementGroupMap = placementGroupMap;
this.placementGroupDeleted = placementGroupDeleted;

View File

@ -39,6 +39,7 @@ import org.jclouds.aws.ec2.compute.suppliers.AWSEC2HardwareSupplier;
import org.jclouds.compute.config.BaseComputeServiceContextModule;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.ec2.compute.config.EC2BindComputeStrategiesByClass;
import org.jclouds.ec2.compute.domain.RegionAndName;
@ -173,4 +174,9 @@ public class AWSEC2ComputeServiceContextModule extends BaseComputeServiceContext
protected Optional<ImageExtension> provideImageExtension(Injector i) {
return Optional.of(i.getInstance(ImageExtension.class));
}
@Override
protected Optional<SecurityGroupExtension> provideSecurityGroupExtension(Injector i) {
return Optional.of(i.getInstance(SecurityGroupExtension.class));
}
}

View File

@ -31,6 +31,7 @@ import javax.inject.Singleton;
import org.jclouds.aws.ec2.compute.AWSEC2ComputeService;
import org.jclouds.aws.ec2.compute.AWSEC2TemplateOptions;
import org.jclouds.aws.ec2.compute.extensions.AWSEC2SecurityGroupExtension;
import org.jclouds.aws.ec2.compute.loaders.AWSEC2CreateSecurityGroupIfNeeded;
import org.jclouds.aws.ec2.compute.suppliers.CallForImages;
import org.jclouds.aws.ec2.domain.PlacementGroup;
@ -41,8 +42,10 @@ import org.jclouds.aws.ec2.predicates.PlacementGroupAvailable;
import org.jclouds.aws.ec2.predicates.PlacementGroupDeleted;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.SecurityGroup;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.config.ValueOfConfigurationKeyOrNull;
import org.jclouds.domain.LoginCredentials;
@ -50,9 +53,11 @@ import org.jclouds.ec2.compute.config.EC2ComputeServiceDependenciesModule;
import org.jclouds.ec2.compute.domain.PasswordDataAndPrivateKey;
import org.jclouds.ec2.compute.domain.RegionAndName;
import org.jclouds.ec2.compute.extensions.EC2ImageExtension;
import org.jclouds.ec2.compute.extensions.EC2SecurityGroupExtension;
import org.jclouds.ec2.compute.functions.CreateUniqueKeyPair;
import org.jclouds.ec2.compute.functions.CredentialsForInstance;
import org.jclouds.ec2.compute.functions.EC2ImageParser;
import org.jclouds.ec2.compute.functions.EC2SecurityGroupToSecurityGroup;
import org.jclouds.ec2.compute.functions.PasswordCredentialsFromWindowsInstance;
import org.jclouds.ec2.compute.functions.WindowsLoginCredentialsFromEncryptedData;
import org.jclouds.ec2.compute.internal.EC2TemplateBuilderImpl;
@ -105,8 +110,12 @@ public class AWSEC2ComputeServiceDependenciesModule extends EC2ComputeServiceDep
install(new FactoryModuleBuilder().build(CallForImages.Factory.class));
bind(new TypeLiteral<Function<org.jclouds.ec2.domain.Image, Image>>() {
}).to(EC2ImageParser.class);
bind(new TypeLiteral<Function<org.jclouds.ec2.domain.SecurityGroup, SecurityGroup>>() {
}).to(EC2SecurityGroupToSecurityGroup.class);
bind(new TypeLiteral<ImageExtension>() {
}).to(EC2ImageExtension.class);
bind(new TypeLiteral<SecurityGroupExtension>() {
}).to(AWSEC2SecurityGroupExtension.class);
}
@Provides

View File

@ -0,0 +1,177 @@
/*
* 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.aws.ec2.compute.extensions;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.equalTo;
import static com.google.common.base.Predicates.not;
import static com.google.common.base.Predicates.notNull;
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.getOnlyElement;
import static com.google.common.collect.Iterables.toArray;
import static com.google.common.collect.Iterables.transform;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider;
import org.jclouds.Constants;
import org.jclouds.aws.ec2.AWSEC2Client;
import org.jclouds.aws.util.AWSUtils;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.domain.SecurityGroup;
import org.jclouds.compute.domain.SecurityGroupBuilder;
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.compute.functions.GroupNamingConvention.Factory;
import org.jclouds.domain.Location;
import org.jclouds.ec2.compute.domain.RegionAndName;
import org.jclouds.ec2.compute.domain.RegionNameAndIngressRules;
import org.jclouds.ec2.compute.extensions.EC2SecurityGroupExtension;
import org.jclouds.ec2.domain.RunningInstance;
import org.jclouds.ec2.domain.UserIdGroupPair;
import org.jclouds.location.Region;
import org.jclouds.net.domain.IpPermission;
import org.jclouds.net.domain.IpProtocol;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.UncheckedTimeoutException;
/**
* An extension to compute service to allow for the manipulation of {@link SecurityGroup}s. Implementation
* is optional by providers.
*
* @author Andrew Bayer
*/
public class AWSEC2SecurityGroupExtension extends EC2SecurityGroupExtension {
protected final AWSEC2Client client;
@Inject
public AWSEC2SecurityGroupExtension(AWSEC2Client client,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
@Region Supplier<Set<String>> regions,
Function<org.jclouds.ec2.domain.SecurityGroup, SecurityGroup> groupConverter,
@Memoized Supplier<Set<? extends Location>> locations,
@Named("SECURITY") LoadingCache<RegionAndName, String> groupCreator,
GroupNamingConvention.Factory namingConvention) {
super(client, userExecutor, regions, groupConverter, locations, groupCreator, namingConvention);
this.client = checkNotNull(client, "client");
}
@Override
public SecurityGroup addIpPermission(IpPermission ipPermission, SecurityGroup group) {
String region = AWSUtils.getRegionFromLocationOrNull(group.getLocation());
String name = group.getName();
client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(region, name, ipPermission);
return getSecurityGroupById(new RegionAndName(region, group.getName()).slashEncode());
}
@Override
public SecurityGroup addIpPermission(IpProtocol protocol, int startPort, int endPort,
Multimap<String, String> tenantIdGroupNamePairs,
Iterable<String> ipRanges,
Iterable<String> groupIds, SecurityGroup group) {
String region = AWSUtils.getRegionFromLocationOrNull(group.getLocation());
String name = group.getName();
IpPermission.Builder builder = IpPermission.builder();
builder.ipProtocol(protocol);
builder.fromPort(startPort);
builder.toPort(endPort);
if (Iterables.size(ipRanges) > 0) {
for (String cidr : ipRanges) {
builder.cidrBlock(cidr);
}
}
if (tenantIdGroupNamePairs.size() > 0) {
for (String userId : tenantIdGroupNamePairs.keySet()) {
for (String groupName : tenantIdGroupNamePairs.get(userId)) {
builder.tenantIdGroupNamePair(userId, groupName);
}
}
}
client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(region, name, builder.build());
return getSecurityGroupById(new RegionAndName(region, group.getName()).slashEncode());
}
@Override
public SecurityGroup removeIpPermission(IpPermission ipPermission, SecurityGroup group) {
String region = AWSUtils.getRegionFromLocationOrNull(group.getLocation());
String name = group.getName();
client.getSecurityGroupServices().revokeSecurityGroupIngressInRegion(region, name, ipPermission);
return getSecurityGroupById(new RegionAndName(region, group.getName()).slashEncode());
}
@Override
public SecurityGroup removeIpPermission(IpProtocol protocol, int startPort, int endPort,
Multimap<String, String> tenantIdGroupNamePairs,
Iterable<String> ipRanges,
Iterable<String> groupIds, SecurityGroup group) {
String region = AWSUtils.getRegionFromLocationOrNull(group.getLocation());
String name = group.getName();
IpPermission.Builder builder = IpPermission.builder();
builder.ipProtocol(protocol);
builder.fromPort(startPort);
builder.toPort(endPort);
if (Iterables.size(ipRanges) > 0) {
for (String cidr : ipRanges) {
builder.cidrBlock(cidr);
}
}
if (tenantIdGroupNamePairs.size() > 0) {
for (String userId : tenantIdGroupNamePairs.keySet()) {
for (String groupName : tenantIdGroupNamePairs.get(userId)) {
builder.tenantIdGroupNamePair(userId, groupName);
}
}
}
client.getSecurityGroupServices().revokeSecurityGroupIngressInRegion(region, name, builder.build());
return getSecurityGroupById(new RegionAndName(region, group.getName()).slashEncode());
}
}

View File

@ -32,10 +32,10 @@ import org.jclouds.aws.ec2.services.AWSSecurityGroupClient;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.ec2.compute.domain.RegionAndName;
import org.jclouds.ec2.compute.domain.RegionNameAndIngressRules;
import org.jclouds.ec2.domain.IpPermission;
import org.jclouds.ec2.domain.IpProtocol;
import org.jclouds.ec2.domain.UserIdGroupPair;
import org.jclouds.logging.Logger;
import org.jclouds.net.domain.IpPermission;
import org.jclouds.net.domain.IpProtocol;
import com.google.common.base.Predicate;
import com.google.common.cache.CacheLoader;
@ -95,7 +95,7 @@ public class AWSEC2CreateSecurityGroupIfNeeded extends CacheLoader<RegionAndName
.fromPort(range.getKey())
.toPort(range.getValue())
.ipProtocol(IpProtocol.TCP)
.ipRange("0.0.0.0/0")
.cidrBlock("0.0.0.0/0")
.build());
}
@ -104,13 +104,13 @@ public class AWSEC2CreateSecurityGroupIfNeeded extends CacheLoader<RegionAndName
.fromPort(0)
.toPort(65535)
.ipProtocol(IpProtocol.TCP)
.userIdGroupPair(myOwnerId, name)
.tenantIdGroupNamePair(myOwnerId, name)
.build());
permissions.add(IpPermission.builder()
.fromPort(0)
.toPort(65535)
.ipProtocol(IpProtocol.UDP)
.userIdGroupPair(myOwnerId, name)
.tenantIdGroupNamePair(myOwnerId, name)
.build());
}

View File

@ -33,12 +33,12 @@ import org.jclouds.aws.filters.FormSigner;
import org.jclouds.ec2.binders.BindGroupIdsToIndexedFormParams;
import org.jclouds.ec2.binders.BindIpPermissionToIndexedFormParams;
import org.jclouds.ec2.binders.BindIpPermissionsToIndexedFormParams;
import org.jclouds.ec2.domain.IpPermission;
import org.jclouds.ec2.domain.SecurityGroup;
import org.jclouds.ec2.services.SecurityGroupAsyncClient;
import org.jclouds.ec2.xml.DescribeSecurityGroupsResponseHandler;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
import org.jclouds.net.domain.IpPermission;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.EndpointParam;
import org.jclouds.rest.annotations.Fallback;

View File

@ -18,10 +18,10 @@ package org.jclouds.aws.ec2.services;
import java.util.Set;
import org.jclouds.aws.ec2.options.CreateSecurityGroupOptions;
import org.jclouds.ec2.domain.IpPermission;
import org.jclouds.ec2.domain.SecurityGroup;
import org.jclouds.ec2.services.SecurityGroupClient;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.net.domain.IpPermission;
import com.google.common.annotations.Beta;

View File

@ -48,11 +48,11 @@ import org.jclouds.compute.predicates.NodePredicates;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.ec2.EC2Client;
import org.jclouds.ec2.compute.EC2ComputeServiceLiveTest;
import org.jclouds.ec2.domain.IpProtocol;
import org.jclouds.ec2.domain.KeyPair;
import org.jclouds.ec2.domain.SecurityGroup;
import org.jclouds.ec2.services.InstanceClient;
import org.jclouds.ec2.services.KeyPairClient;
import org.jclouds.net.domain.IpProtocol;
import org.jclouds.scriptbuilder.domain.Statements;
import org.testng.annotations.Test;

View File

@ -0,0 +1,367 @@
/*
* 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.aws.ec2.compute.extensions;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import java.util.Set;
import javax.ws.rs.core.MediaType;
import org.jclouds.aws.ec2.compute.internal.BaseAWSEC2ComputeServiceExpectTest;
import org.jclouds.compute.domain.SecurityGroup;
import org.jclouds.compute.domain.SecurityGroupBuilder;
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
import org.jclouds.ec2.compute.domain.RegionAndName;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.net.domain.IpPermission;
import org.jclouds.net.domain.IpProtocol;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.Futures;
/**
*
* @author Andrew Bayer
*/
@Test(groups = "unit", testName = "AWSEC2SecurityGroupExtensionExpectTest")
public class AWSEC2SecurityGroupExtensionExpectTest extends BaseAWSEC2ComputeServiceExpectTest {
public void testAddIpPermissionCidrFromIpPermission() {
HttpRequest describeSecurityGroupsSingleRequest =
formSigner.filter(HttpRequest.builder()
.method("POST")
.endpoint("https://ec2." + region + ".amazonaws.com/")
.addHeader("Host", "ec2." + region + ".amazonaws.com")
.addFormParam("Action", "DescribeSecurityGroups")
.addFormParam("GroupName.1", "jclouds#some-group").build());
HttpResponse describeSecurityGroupsSingleResponse =
HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType(
"/describe_securitygroups_extension_cidr.xml", MediaType.APPLICATION_XML)).build();
HttpRequest authorizeSecurityGroupIngressRequestRange =
formSigner.filter(HttpRequest.builder()
.method("POST")
.endpoint("https://ec2." + region + ".amazonaws.com/")
.addHeader("Host", "ec2." + region + ".amazonaws.com")
.addFormParam("Action", "AuthorizeSecurityGroupIngress")
.addFormParam("GroupId", "jclouds#some-group")
.addFormParam("IpPermissions.0.FromPort", "22")
.addFormParam("IpPermissions.0.IpProtocol", "tcp")
.addFormParam("IpPermissions.0.IpRanges.0.CidrIp", "0.0.0.0/0")
.addFormParam("IpPermissions.0.ToPort", "40")
.build());
Builder<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder();
requestResponseMap.put(describeRegionsRequest, describeRegionsResponse);
requestResponseMap.put(describeAvailabilityZonesRequest, describeAvailabilityZonesResponse);
requestResponseMap.put(describeSecurityGroupsSingleRequest, describeSecurityGroupsSingleResponse);
requestResponseMap.put(createKeyPairRequest, createKeyPairResponse);
requestResponseMap.put(createSecurityGroupRequest, createSecurityGroupResponse);
requestResponseMap.put(authorizeSecurityGroupIngressRequestRange, authorizeSecurityGroupIngressResponse);
IpPermission.Builder builder = IpPermission.builder();
builder.ipProtocol(IpProtocol.TCP);
builder.fromPort(22);
builder.toPort(40);
builder.cidrBlock("0.0.0.0/0");
IpPermission perm = builder.build();
SecurityGroupExtension extension = requestsSendResponses(requestResponseMap.build()).getSecurityGroupExtension().get();
SecurityGroupBuilder groupBuilder = new SecurityGroupBuilder();
groupBuilder.id("jclouds#some-group");
groupBuilder.providerId("sg-3c6ef654");
groupBuilder.name("jclouds#some-group");
groupBuilder.location(new LocationBuilder()
.scope(LocationScope.REGION)
.id(region)
.description("region")
.build());
SecurityGroup origGroup = groupBuilder.build();
SecurityGroup newGroup = extension.addIpPermission(perm, origGroup);
assertEquals(1, newGroup.getIpPermissions().size());
IpPermission newPerm = Iterables.getOnlyElement(newGroup.getIpPermissions());
assertNotNull(newPerm);
assertEquals(IpProtocol.TCP, newPerm.getIpProtocol());
assertEquals(22, newPerm.getFromPort());
assertEquals(40, newPerm.getToPort());
assertEquals(1, newPerm.getCidrBlocks().size());
assertTrue(newPerm.getCidrBlocks().contains("0.0.0.0/0"));
}
public void testAddIpPermissionCidrFromParams() {
HttpRequest describeSecurityGroupsSingleRequest =
formSigner.filter(HttpRequest.builder()
.method("POST")
.endpoint("https://ec2." + region + ".amazonaws.com/")
.addHeader("Host", "ec2." + region + ".amazonaws.com")
.addFormParam("Action", "DescribeSecurityGroups")
.addFormParam("GroupName.1", "jclouds#some-group").build());
HttpResponse describeSecurityGroupsSingleResponse =
HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType(
"/describe_securitygroups_extension_cidr.xml", MediaType.APPLICATION_XML)).build();
HttpRequest authorizeSecurityGroupIngressRequestRange =
formSigner.filter(HttpRequest.builder()
.method("POST")
.endpoint("https://ec2." + region + ".amazonaws.com/")
.addHeader("Host", "ec2." + region + ".amazonaws.com")
.addFormParam("Action", "AuthorizeSecurityGroupIngress")
.addFormParam("GroupId", "jclouds#some-group")
.addFormParam("IpPermissions.0.FromPort", "22")
.addFormParam("IpPermissions.0.IpProtocol", "tcp")
.addFormParam("IpPermissions.0.IpRanges.0.CidrIp", "0.0.0.0/0")
.addFormParam("IpPermissions.0.ToPort", "40")
.build());
Builder<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder();
requestResponseMap.put(describeRegionsRequest, describeRegionsResponse);
requestResponseMap.put(describeAvailabilityZonesRequest, describeAvailabilityZonesResponse);
requestResponseMap.put(describeSecurityGroupsSingleRequest, describeSecurityGroupsSingleResponse);
requestResponseMap.put(createKeyPairRequest, createKeyPairResponse);
requestResponseMap.put(createSecurityGroupRequest, createSecurityGroupResponse);
requestResponseMap.put(authorizeSecurityGroupIngressRequestRange, authorizeSecurityGroupIngressResponse);
SecurityGroupExtension extension = requestsSendResponses(requestResponseMap.build()).getSecurityGroupExtension().get();
SecurityGroupBuilder groupBuilder = new SecurityGroupBuilder();
groupBuilder.id("jclouds#some-group");
groupBuilder.providerId("sg-3c6ef654");
groupBuilder.name("jclouds#some-group");
groupBuilder.location(new LocationBuilder()
.scope(LocationScope.REGION)
.id(region)
.description("region")
.build());
SecurityGroup origGroup = groupBuilder.build();
SecurityGroup newGroup = extension.addIpPermission(IpProtocol.TCP,
22,
40,
emptyMultimap(),
ImmutableSet.of("0.0.0.0/0"),
emptyStringSet(),
origGroup);
assertEquals(1, newGroup.getIpPermissions().size());
IpPermission newPerm = Iterables.getOnlyElement(newGroup.getIpPermissions());
assertNotNull(newPerm);
assertEquals(IpProtocol.TCP, newPerm.getIpProtocol());
assertEquals(22, newPerm.getFromPort());
assertEquals(40, newPerm.getToPort());
assertEquals(1, newPerm.getCidrBlocks().size());
assertTrue(newPerm.getCidrBlocks().contains("0.0.0.0/0"));
}
public void testAddIpPermissionGroupFromIpPermission() {
HttpRequest describeSecurityGroupsSingleRequest =
formSigner.filter(HttpRequest.builder()
.method("POST")
.endpoint("https://ec2." + region + ".amazonaws.com/")
.addHeader("Host", "ec2." + region + ".amazonaws.com")
.addFormParam("Action", "DescribeSecurityGroups")
.addFormParam("GroupName.1", "jclouds#some-group").build());
HttpResponse describeSecurityGroupsSingleResponse =
HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType(
"/describe_securitygroups_extension_group.xml", MediaType.APPLICATION_XML)).build();
HttpRequest authorizeSecurityGroupIngressRequestGroupTenant =
formSigner.filter(HttpRequest.builder()
.method("POST")
.endpoint("https://ec2." + region + ".amazonaws.com/")
.addHeader("Host", "ec2." + region + ".amazonaws.com")
.addFormParam("Action", "AuthorizeSecurityGroupIngress")
.addFormParam("GroupId", "jclouds#some-group")
.addFormParam("IpPermissions.0.FromPort", "22")
.addFormParam("IpPermissions.0.Groups.0.GroupName", "jclouds#some-group")
.addFormParam("IpPermissions.0.Groups.0.UserId", "993194456877")
.addFormParam("IpPermissions.0.IpProtocol", "tcp")
.addFormParam("IpPermissions.0.ToPort", "40")
.build());
Builder<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder();
requestResponseMap.put(describeRegionsRequest, describeRegionsResponse);
requestResponseMap.put(describeAvailabilityZonesRequest, describeAvailabilityZonesResponse);
requestResponseMap.put(describeSecurityGroupsSingleRequest, describeSecurityGroupsSingleResponse);
requestResponseMap.put(createKeyPairRequest, createKeyPairResponse);
requestResponseMap.put(createSecurityGroupRequest, createSecurityGroupResponse);
requestResponseMap.put(authorizeSecurityGroupIngressRequestGroupTenant, authorizeSecurityGroupIngressResponse);
IpPermission.Builder builder = IpPermission.builder();
builder.ipProtocol(IpProtocol.TCP);
builder.fromPort(22);
builder.toPort(40);
builder.tenantIdGroupNamePair("993194456877", "jclouds#some-group");
IpPermission perm = builder.build();
SecurityGroupExtension extension = requestsSendResponses(requestResponseMap.build()).getSecurityGroupExtension().get();
SecurityGroupBuilder groupBuilder = new SecurityGroupBuilder();
groupBuilder.id("jclouds#some-group");
groupBuilder.providerId("sg-3c6ef654");
groupBuilder.name("jclouds#some-group");
groupBuilder.location(new LocationBuilder()
.scope(LocationScope.REGION)
.id(region)
.description("region")
.build());
groupBuilder.ownerId("993194456877");
SecurityGroup origGroup = groupBuilder.build();
SecurityGroup newGroup = extension.addIpPermission(perm, origGroup);
assertEquals(1, newGroup.getIpPermissions().size());
IpPermission newPerm = Iterables.getOnlyElement(newGroup.getIpPermissions());
assertNotNull(newPerm);
assertEquals(IpProtocol.TCP, newPerm.getIpProtocol());
assertEquals(22, newPerm.getFromPort());
assertEquals(40, newPerm.getToPort());
assertEquals(0, newPerm.getCidrBlocks().size());
assertEquals(1, newPerm.getTenantIdGroupNamePairs().size());
assertTrue(newPerm.getTenantIdGroupNamePairs().keySet().contains(origGroup.getOwnerId()));
assertTrue(newPerm.getTenantIdGroupNamePairs().values().contains(origGroup.getName()));
}
public void testAddIpPermissionGroupFromParams() {
HttpRequest describeSecurityGroupsSingleRequest =
formSigner.filter(HttpRequest.builder()
.method("POST")
.endpoint("https://ec2." + region + ".amazonaws.com/")
.addHeader("Host", "ec2." + region + ".amazonaws.com")
.addFormParam("Action", "DescribeSecurityGroups")
.addFormParam("GroupName.1", "jclouds#some-group").build());
HttpResponse describeSecurityGroupsSingleResponse =
HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType(
"/describe_securitygroups_extension_group.xml", MediaType.APPLICATION_XML)).build();
HttpRequest authorizeSecurityGroupIngressRequestGroupTenant =
formSigner.filter(HttpRequest.builder()
.method("POST")
.endpoint("https://ec2." + region + ".amazonaws.com/")
.addHeader("Host", "ec2." + region + ".amazonaws.com")
.addFormParam("Action", "AuthorizeSecurityGroupIngress")
.addFormParam("GroupId", "jclouds#some-group")
.addFormParam("IpPermissions.0.FromPort", "22")
.addFormParam("IpPermissions.0.Groups.0.GroupName", "jclouds#some-group")
.addFormParam("IpPermissions.0.Groups.0.UserId", "993194456877")
.addFormParam("IpPermissions.0.IpProtocol", "tcp")
.addFormParam("IpPermissions.0.ToPort", "40")
.build());
Builder<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder();
requestResponseMap.put(describeRegionsRequest, describeRegionsResponse);
requestResponseMap.put(describeAvailabilityZonesRequest, describeAvailabilityZonesResponse);
requestResponseMap.put(describeSecurityGroupsSingleRequest, describeSecurityGroupsSingleResponse);
requestResponseMap.put(createKeyPairRequest, createKeyPairResponse);
requestResponseMap.put(createSecurityGroupRequest, createSecurityGroupResponse);
requestResponseMap.put(authorizeSecurityGroupIngressRequestGroupTenant, authorizeSecurityGroupIngressResponse);
SecurityGroupExtension extension = requestsSendResponses(requestResponseMap.build()).getSecurityGroupExtension().get();
SecurityGroupBuilder groupBuilder = new SecurityGroupBuilder();
groupBuilder.id("jclouds#some-group");
groupBuilder.providerId("sg-3c6ef654");
groupBuilder.name("jclouds#some-group");
groupBuilder.ownerId("993194456877");
groupBuilder.location(new LocationBuilder()
.scope(LocationScope.REGION)
.id(region)
.description("region")
.build());
SecurityGroup origGroup = groupBuilder.build();
ImmutableMultimap.Builder<String, String> permBuilder = ImmutableMultimap.builder();
permBuilder.put(origGroup.getOwnerId(), origGroup.getName());
SecurityGroup newGroup = extension.addIpPermission(IpProtocol.TCP,
22,
40,
permBuilder.build(),
emptyStringSet(),
emptyStringSet(),
origGroup);
assertEquals(1, newGroup.getIpPermissions().size());
IpPermission newPerm = Iterables.getOnlyElement(newGroup.getIpPermissions());
assertNotNull(newPerm);
assertEquals(IpProtocol.TCP, newPerm.getIpProtocol());
assertEquals(22, newPerm.getFromPort());
assertEquals(40, newPerm.getToPort());
assertEquals(0, newPerm.getCidrBlocks().size());
assertEquals(1, newPerm.getTenantIdGroupNamePairs().size());
assertTrue(newPerm.getTenantIdGroupNamePairs().keySet().contains(origGroup.getOwnerId()));
assertTrue(newPerm.getTenantIdGroupNamePairs().values().contains(origGroup.getName()));
}
private Multimap<String, String> emptyMultimap() {
return LinkedHashMultimap.create();
}
private Set<String> emptyStringSet() {
return Sets.newLinkedHashSet();
}
}

View File

@ -14,26 +14,26 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.openstack.nova.v2_0.domain;
package org.jclouds.aws.ec2.compute.extensions;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.transform;
public enum IpProtocol {
TCP, UDP, ICMP, UNRECOGNIZED;
public String value() {
return name().toLowerCase();
}
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.compute.extensions.internal.BaseSecurityGroupExtensionLiveTest;
import org.testng.annotations.Test;
@Override
public String toString() {
return value();
}
import com.google.inject.Module;
public static IpProtocol fromValue(String protocol) {
try {
return valueOf(checkNotNull(protocol, "protocol").toUpperCase());
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
/**
* Live test for aws-ec2 {@link SecurityGroupExtension} implementation
*
* @author Andrew Bayer
*
*/
@Test(groups = "live", singleThreaded = true, testName = "AWSEC2SecurityGroupExtensionLiveTest")
public class AWSEC2SecurityGroupExtensionLiveTest extends BaseSecurityGroupExtensionLiveTest {
public AWSEC2SecurityGroupExtensionLiveTest() {
provider = "aws-ec2";
}
}

View File

@ -30,10 +30,10 @@ import java.util.concurrent.ExecutionException;
import org.jclouds.aws.ec2.services.AWSSecurityGroupClient;
import org.jclouds.ec2.compute.domain.RegionAndName;
import org.jclouds.ec2.compute.domain.RegionNameAndIngressRules;
import org.jclouds.ec2.domain.IpPermission;
import org.jclouds.ec2.domain.IpProtocol;
import org.jclouds.ec2.domain.SecurityGroup;
import org.jclouds.ec2.domain.UserIdGroupPair;
import org.jclouds.net.domain.IpPermission;
import org.jclouds.net.domain.IpProtocol;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
@ -63,20 +63,20 @@ public class AWSEC2CreateSecurityGroupIfNeededTest {
.fromPort(22)
.toPort(22)
.ipProtocol(IpProtocol.TCP)
.ipRange("0.0.0.0/0")
.cidrBlock("0.0.0.0/0")
.build());
permissions.add(IpPermission.builder()
.fromPort(0)
.toPort(65535)
.ipProtocol(IpProtocol.TCP)
.userIdGroupPair("ownerId", "group")
.tenantIdGroupNamePair("ownerId", "group")
.build());
permissions.add(IpPermission.builder()
.fromPort(0)
.toPort(65535)
.ipProtocol(IpProtocol.UDP)
.userIdGroupPair("ownerId", "group")
.tenantIdGroupNamePair("ownerId", "group")
.build());
client.createSecurityGroupInRegion("region", "group", "group");

View File

@ -25,12 +25,12 @@ import static org.testng.Assert.assertEquals;
import java.io.InputStream;
import java.util.Set;
import org.jclouds.ec2.domain.IpPermission;
import org.jclouds.ec2.domain.IpProtocol;
import org.jclouds.ec2.domain.SecurityGroup;
import org.jclouds.ec2.xml.BaseEC2HandlerTest;
import org.jclouds.ec2.xml.DescribeSecurityGroupsResponseHandler;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.net.domain.IpPermission;
import org.jclouds.net.domain.IpProtocol;
import org.jclouds.reflect.Invocation;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.testng.annotations.Test;
@ -69,7 +69,7 @@ public class DescribeSecurityGroupsResponseTest extends BaseEC2HandlerTest {
// .vpcId("vpc-99999999")
.ipPermission(IpPermission.builder()
.ipProtocol(IpProtocol.ALL)
.userIdGroupPair("123123123123","sg-11111111").build())
.tenantIdGroupNamePair("123123123123","sg-11111111").build())
// .ipPermissionEgress(IpPermission.builder()
// .ipProtocol(IpProtocol.ALL)
// .ipRange("0.0.0.0/0").build())

View File

@ -22,13 +22,13 @@ import java.io.IOException;
import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
import org.jclouds.ec2.domain.IpPermission;
import org.jclouds.ec2.domain.IpProtocol;
import org.jclouds.ec2.util.IpPermissions;
import org.jclouds.ec2.xml.DescribeSecurityGroupsResponseHandler;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.http.functions.ReleasePayloadAndReturn;
import org.jclouds.net.domain.IpPermission;
import org.jclouds.net.domain.IpProtocol;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.testng.annotations.Test;

View File

@ -21,11 +21,11 @@ import static org.testng.Assert.assertNotNull;
import java.util.Set;
import org.jclouds.ec2.domain.IpPermission;
import org.jclouds.ec2.domain.IpProtocol;
import org.jclouds.ec2.domain.SecurityGroup;
import org.jclouds.ec2.services.SecurityGroupClientLiveTest;
import org.jclouds.ec2.util.IpPermissions;
import org.jclouds.net.domain.IpPermission;
import org.jclouds.net.domain.IpProtocol;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
@ -69,7 +69,7 @@ public class AWSSecurityGroupClientLiveTest extends SecurityGroupClientLiveTest
assertEventually(new GroupHasPermission(client, group2Name, new Predicate<IpPermission>() {
@Override
public boolean apply(IpPermission arg0) {
return arg0.getUserIdGroupPairs().equals(ImmutableMultimap.of(group.getOwnerId(), group1Name))
return arg0.getTenantIdGroupNamePairs().equals(ImmutableMultimap.of(group.getOwnerId(), group1Name))
&& arg0.getFromPort() == 80 && arg0.getToPort() == 80 && arg0.getIpProtocol() == IpProtocol.TCP;
}
}));

View File

@ -37,6 +37,7 @@ import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.compute.internal.BaseComputeService;
import org.jclouds.compute.internal.PersistNodeCredentials;
import org.jclouds.compute.options.TemplateOptions;
@ -81,12 +82,12 @@ public class GoGridComputeService extends BaseComputeService {
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory, InitAdminAccess initAdminAccess,
RunScriptOnNode.Factory runScriptOnNodeFactory, PersistNodeCredentials persistNodeCredentials,
Timeouts timeouts, @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
Optional<ImageExtension> imageExtension) {
Optional<ImageExtension> imageExtension, Optional<SecurityGroupExtension> securityGroupExtension) {
super(context, credentialStore, images, hardwareProfiles, locations, listNodesStrategy, getImageStrategy,
getNodeMetadataStrategy, runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy,
resumeNodeStrategy, suspendNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning,
nodeTerminated, nodeSuspended, initScriptRunnerFactory, initAdminAccess, runScriptOnNodeFactory,
persistNodeCredentials, timeouts, userExecutor, imageExtension);
persistNodeCredentials, timeouts, userExecutor, imageExtension, securityGroupExtension);
}
/**