You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by ab...@apache.org on 2013/06/26 23:59:08 UTC
[2/4] JCLOUDS-101 - Add SecurityGroupExtension for compute
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f524ee6/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/parse/ParseComputeServiceTypicalSecurityGroupTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/parse/ParseComputeServiceTypicalSecurityGroupTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/parse/ParseComputeServiceTypicalSecurityGroupTest.java
index 5da793f..9b056b9 100644
--- a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/parse/ParseComputeServiceTypicalSecurityGroupTest.java
+++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/parse/ParseComputeServiceTypicalSecurityGroupTest.java
@@ -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;
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f524ee6/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/parse/ParseSecurityGroupListTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/parse/ParseSecurityGroupListTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/parse/ParseSecurityGroupListTest.java
index 9f477ee..4e46ede 100644
--- a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/parse/ParseSecurityGroupListTest.java
+++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/parse/ParseSecurityGroupListTest.java
@@ -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;
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f524ee6/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/parse/ParseSecurityGroupTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/parse/ParseSecurityGroupTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/parse/ParseSecurityGroupTest.java
index a5c83f4..784a0bd 100644
--- a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/parse/ParseSecurityGroupTest.java
+++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/parse/ParseSecurityGroupTest.java
@@ -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;
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f524ee6/common/trmk/src/main/java/org/jclouds/trmk/vcloud_0_8/compute/TerremarkVCloudComputeService.java
----------------------------------------------------------------------
diff --git a/common/trmk/src/main/java/org/jclouds/trmk/vcloud_0_8/compute/TerremarkVCloudComputeService.java b/common/trmk/src/main/java/org/jclouds/trmk/vcloud_0_8/compute/TerremarkVCloudComputeService.java
index 1431d54..b37e85e 100644
--- a/common/trmk/src/main/java/org/jclouds/trmk/vcloud_0_8/compute/TerremarkVCloudComputeService.java
+++ b/common/trmk/src/main/java/org/jclouds/trmk/vcloud_0_8/compute/TerremarkVCloudComputeService.java
@@ -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;
}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f524ee6/compute/src/main/java/org/jclouds/compute/ComputeService.java
----------------------------------------------------------------------
diff --git a/compute/src/main/java/org/jclouds/compute/ComputeService.java b/compute/src/main/java/org/jclouds/compute/ComputeService.java
index 610090a..a7c2519 100644
--- a/compute/src/main/java/org/jclouds/compute/ComputeService.java
+++ b/compute/src/main/java/org/jclouds/compute/ComputeService.java
@@ -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();
}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f524ee6/compute/src/main/java/org/jclouds/compute/config/BaseComputeServiceContextModule.java
----------------------------------------------------------------------
diff --git a/compute/src/main/java/org/jclouds/compute/config/BaseComputeServiceContextModule.java b/compute/src/main/java/org/jclouds/compute/config/BaseComputeServiceContextModule.java
index 7581e86..7307196 100644
--- a/compute/src/main/java/org/jclouds/compute/config/BaseComputeServiceContextModule.java
+++ b/compute/src/main/java/org/jclouds/compute/config/BaseComputeServiceContextModule.java
@@ -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();
+ }
+
}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f524ee6/compute/src/main/java/org/jclouds/compute/domain/ComputeType.java
----------------------------------------------------------------------
diff --git a/compute/src/main/java/org/jclouds/compute/domain/ComputeType.java b/compute/src/main/java/org/jclouds/compute/domain/ComputeType.java
index 26df759..8e2c75c 100644
--- a/compute/src/main/java/org/jclouds/compute/domain/ComputeType.java
+++ b/compute/src/main/java/org/jclouds/compute/domain/ComputeType.java
@@ -22,6 +22,6 @@ package org.jclouds.compute.domain;
*/
public enum ComputeType {
- NODE, IMAGE, HARDWARE;
+ NODE, IMAGE, HARDWARE, SECURITYGROUP;
}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f524ee6/compute/src/main/java/org/jclouds/compute/domain/SecurityGroup.java
----------------------------------------------------------------------
diff --git a/compute/src/main/java/org/jclouds/compute/domain/SecurityGroup.java b/compute/src/main/java/org/jclouds/compute/domain/SecurityGroup.java
new file mode 100644
index 0000000..fecba5a
--- /dev/null
+++ b/compute/src/main/java/org/jclouds/compute/domain/SecurityGroup.java
@@ -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);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f524ee6/compute/src/main/java/org/jclouds/compute/domain/SecurityGroupBuilder.java
----------------------------------------------------------------------
diff --git a/compute/src/main/java/org/jclouds/compute/domain/SecurityGroupBuilder.java b/compute/src/main/java/org/jclouds/compute/domain/SecurityGroupBuilder.java
new file mode 100644
index 0000000..002116f
--- /dev/null
+++ b/compute/src/main/java/org/jclouds/compute/domain/SecurityGroupBuilder.java
@@ -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());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f524ee6/compute/src/main/java/org/jclouds/compute/extensions/SecurityGroupExtension.java
----------------------------------------------------------------------
diff --git a/compute/src/main/java/org/jclouds/compute/extensions/SecurityGroupExtension.java b/compute/src/main/java/org/jclouds/compute/extensions/SecurityGroupExtension.java
new file mode 100644
index 0000000..f07e72d
--- /dev/null
+++ b/compute/src/main/java/org/jclouds/compute/extensions/SecurityGroupExtension.java
@@ -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();
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f524ee6/compute/src/main/java/org/jclouds/compute/internal/BaseComputeService.java
----------------------------------------------------------------------
diff --git a/compute/src/main/java/org/jclouds/compute/internal/BaseComputeService.java b/compute/src/main/java/org/jclouds/compute/internal/BaseComputeService.java
index fd177ac..75ea787 100644
--- a/compute/src/main/java/org/jclouds/compute/internal/BaseComputeService.java
+++ b/compute/src/main/java/org/jclouds/compute/internal/BaseComputeService.java
@@ -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;
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f524ee6/compute/src/main/java/org/jclouds/compute/options/TemplateOptions.java
----------------------------------------------------------------------
diff --git a/compute/src/main/java/org/jclouds/compute/options/TemplateOptions.java b/compute/src/main/java/org/jclouds/compute/options/TemplateOptions.java
index 270633a..d17a6cd 100644
--- a/compute/src/main/java/org/jclouds/compute/options/TemplateOptions.java
+++ b/compute/src/main/java/org/jclouds/compute/options/TemplateOptions.java
@@ -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)
@@ -295,6 +297,21 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
}
@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;
}
@@ -451,6 +476,21 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
}
/**
+ * 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.
*/
public TemplateOptions inboundPorts(int... ports) {
@@ -522,6 +562,22 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
}
/**
+ * @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)
*/
public static TemplateOptions blockUntilRunning(boolean blockUntilRunning) {
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f524ee6/compute/src/main/java/org/jclouds/compute/stub/config/StubComputeServiceAdapter.java
----------------------------------------------------------------------
diff --git a/compute/src/main/java/org/jclouds/compute/stub/config/StubComputeServiceAdapter.java b/compute/src/main/java/org/jclouds/compute/stub/config/StubComputeServiceAdapter.java
index 925dc1a..22e7dcf 100644
--- a/compute/src/main/java/org/jclouds/compute/stub/config/StubComputeServiceAdapter.java
+++ b/compute/src/main/java/org/jclouds/compute/stub/config/StubComputeServiceAdapter.java
@@ -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
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f524ee6/compute/src/main/java/org/jclouds/compute/stub/config/StubComputeServiceContextModule.java
----------------------------------------------------------------------
diff --git a/compute/src/main/java/org/jclouds/compute/stub/config/StubComputeServiceContextModule.java b/compute/src/main/java/org/jclouds/compute/stub/config/StubComputeServiceContextModule.java
index 91e858a..ab381b3 100644
--- a/compute/src/main/java/org/jclouds/compute/stub/config/StubComputeServiceContextModule.java
+++ b/compute/src/main/java/org/jclouds/compute/stub/config/StubComputeServiceContextModule.java
@@ -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));
+ }
+
}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f524ee6/compute/src/main/java/org/jclouds/compute/stub/config/StubComputeServiceDependenciesModule.java
----------------------------------------------------------------------
diff --git a/compute/src/main/java/org/jclouds/compute/stub/config/StubComputeServiceDependenciesModule.java b/compute/src/main/java/org/jclouds/compute/stub/config/StubComputeServiceDependenciesModule.java
index de28ee1..0d07bbe 100644
--- a/compute/src/main/java/org/jclouds/compute/stub/config/StubComputeServiceDependenciesModule.java
+++ b/compute/src/main/java/org/jclouds/compute/stub/config/StubComputeServiceDependenciesModule.java
@@ -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")
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f524ee6/compute/src/main/java/org/jclouds/compute/stub/extensions/StubSecurityGroupExtension.java
----------------------------------------------------------------------
diff --git a/compute/src/main/java/org/jclouds/compute/stub/extensions/StubSecurityGroupExtension.java b/compute/src/main/java/org/jclouds/compute/stub/extensions/StubSecurityGroupExtension.java
new file mode 100644
index 0000000..5e8fdd9
--- /dev/null
+++ b/compute/src/main/java/org/jclouds/compute/stub/extensions/StubSecurityGroupExtension.java
@@ -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;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f524ee6/compute/src/main/java/org/jclouds/net/domain/IpPermission.java
----------------------------------------------------------------------
diff --git a/compute/src/main/java/org/jclouds/net/domain/IpPermission.java b/compute/src/main/java/org/jclouds/net/domain/IpPermission.java
index 895d9d3..d04af0c 100644
--- a/compute/src/main/java/org/jclouds/net/domain/IpPermission.java
+++ b/compute/src/main/java/org/jclouds/net/domain/IpPermission.java
@@ -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);
}
}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f524ee6/compute/src/main/java/org/jclouds/net/domain/IpProtocol.java
----------------------------------------------------------------------
diff --git a/compute/src/main/java/org/jclouds/net/domain/IpProtocol.java b/compute/src/main/java/org/jclouds/net/domain/IpProtocol.java
index 50d4422..203f0f9 100644
--- a/compute/src/main/java/org/jclouds/net/domain/IpProtocol.java
+++ b/compute/src/main/java/org/jclouds/net/domain/IpProtocol.java
@@ -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;
}
}
-
}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f524ee6/compute/src/test/java/org/jclouds/compute/extensions/internal/BaseSecurityGroupExtensionLiveTest.java
----------------------------------------------------------------------
diff --git a/compute/src/test/java/org/jclouds/compute/extensions/internal/BaseSecurityGroupExtensionLiveTest.java b/compute/src/test/java/org/jclouds/compute/extensions/internal/BaseSecurityGroupExtensionLiveTest.java
new file mode 100644
index 0000000..1a5c646
--- /dev/null
+++ b/compute/src/test/java/org/jclouds/compute/extensions/internal/BaseSecurityGroupExtensionLiveTest.java
@@ -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);
+ }
+ });
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f524ee6/compute/src/test/java/org/jclouds/compute/stub/extensions/StubSecurityGroupExtensionIntegrationTest.java
----------------------------------------------------------------------
diff --git a/compute/src/test/java/org/jclouds/compute/stub/extensions/StubSecurityGroupExtensionIntegrationTest.java b/compute/src/test/java/org/jclouds/compute/stub/extensions/StubSecurityGroupExtensionIntegrationTest.java
new file mode 100644
index 0000000..8c2b31c
--- /dev/null
+++ b/compute/src/test/java/org/jclouds/compute/stub/extensions/StubSecurityGroupExtensionIntegrationTest.java
@@ -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;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f524ee6/compute/src/test/java/org/jclouds/net/util/IpPermissionsTest.java
----------------------------------------------------------------------
diff --git a/compute/src/test/java/org/jclouds/net/util/IpPermissionsTest.java b/compute/src/test/java/org/jclouds/net/util/IpPermissionsTest.java
index 2c278f6..30f5453 100644
--- a/compute/src/test/java/org/jclouds/net/util/IpPermissionsTest.java
+++ b/compute/src/test/java/org/jclouds/net/util/IpPermissionsTest.java
@@ -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)
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f524ee6/core/src/main/java/org/jclouds/util/Strings2.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/jclouds/util/Strings2.java b/core/src/main/java/org/jclouds/util/Strings2.java
index 8b85b53..2a47286 100644
--- a/core/src/main/java/org/jclouds/util/Strings2.java
+++ b/core/src/main/java/org/jclouds/util/Strings2.java
@@ -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) {
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f524ee6/core/src/test/java/org/jclouds/util/Strings2Test.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/jclouds/util/Strings2Test.java b/core/src/test/java/org/jclouds/util/Strings2Test.java
index d7e3cd5..5b1c9a0 100644
--- a/core/src/test/java/org/jclouds/util/Strings2Test.java
+++ b/core/src/test/java/org/jclouds/util/Strings2Test.java
@@ -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");
+ }
+
}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f524ee6/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/AWSEC2ComputeService.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/AWSEC2ComputeService.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/AWSEC2ComputeService.java
index d9a15f3..8bcc4d5 100644
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/AWSEC2ComputeService.java
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/AWSEC2ComputeService.java
@@ -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;
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f524ee6/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/config/AWSEC2ComputeServiceContextModule.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/config/AWSEC2ComputeServiceContextModule.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/config/AWSEC2ComputeServiceContextModule.java
index 7d18968..5341d57 100644
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/config/AWSEC2ComputeServiceContextModule.java
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/config/AWSEC2ComputeServiceContextModule.java
@@ -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));
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f524ee6/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/config/AWSEC2ComputeServiceDependenciesModule.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/config/AWSEC2ComputeServiceDependenciesModule.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/config/AWSEC2ComputeServiceDependenciesModule.java
index f82216f..8102cb6 100644
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/config/AWSEC2ComputeServiceDependenciesModule.java
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/config/AWSEC2ComputeServiceDependenciesModule.java
@@ -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