Adds support for the Security Group extension to neutron

This commit is contained in:
Zack Shoylev 2014-08-15 16:17:39 -05:00
parent b5b3a91fa3
commit 39d7a96d49
31 changed files with 2766 additions and 12 deletions

View File

@ -25,6 +25,7 @@ import org.jclouds.Constants;
import org.jclouds.location.Region;
import org.jclouds.location.functions.RegionToEndpoint;
import org.jclouds.openstack.neutron.v2.extensions.RouterApi;
import org.jclouds.openstack.neutron.v2.extensions.SecurityGroupApi;
import org.jclouds.openstack.neutron.v2.features.NetworkApi;
import org.jclouds.openstack.neutron.v2.features.PortApi;
import org.jclouds.openstack.neutron.v2.features.SubnetApi;
@ -89,4 +90,13 @@ public interface NeutronApi extends Closeable {
@Delegate
Optional<? extends RouterApi> getRouterExtensionApi(@EndpointParam(parser = RegionToEndpoint.class) String region);
/**
* Provides access to SecurityGroup features.
*
* <h3>NOTE</h3>
* This API is an extension that may or may not be present in your OpenStack cloud. Use the Optional return type
* to determine if it is present.
*/
@Delegate
Optional<SecurityGroupApi> getSecurityGroupApi(@EndpointParam(parser = RegionToEndpoint.class) String region);
}

View File

@ -101,19 +101,10 @@ public class AddressPair {
* In this case, both parameters are required.
* @return the Builder for AddressPair
*/
public static Builder createOptions(String macAddress, String ipAddress) {
public static Builder builder(String macAddress, String ipAddress) {
return new Builder(macAddress, ipAddress);
}
/**
* Returns a builder, but requires the user to specify any parameters required when updating a resource.
* In this case, there are none.
* @return the Builder for AddressPair
*/
public static Builder updateOptions() {
return new Builder();
}
/**
* Gets a Builder configured as this object.
*/

View File

@ -0,0 +1,375 @@
/*
* 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.neutron.v2.domain;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import java.beans.ConstructorProperties;
import javax.inject.Named;
import org.jclouds.javax.annotation.Nullable;
import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
/**
* Contains a mapping between a MAC address and an IP address.
*/
public class Rule {
private String id;
@Named("tenant_id")
private String tenantId;
private RuleDirection direction;
@Named("security_group_id")
private String securityGroupId;
private RuleEthertype ethertype;
@Named("port_range_min")
private Integer portRangeMin;
@Named("port_range_max")
private Integer portRangeMax;
private RuleProtocol protocol;
@Named("remote_group_id")
private String remoteGroupId;
@Named("remote_ip_prefix")
private String remoteIpPrefix;
@ConstructorProperties({"id", "tenant_id", "direction", "security_group_id", "ethertype", "port_range_min",
"port_range_max", "protocol", "remote_group_id", "remote_ip_prefix"})
protected Rule(String id, String tenantId, RuleDirection direction, String securityGroupId,
RuleEthertype ethertype, Integer portRangeMin, Integer portRangeMax,
RuleProtocol protocol, String remoteGroupId, String remoteIpPrefix) {
this.id = id;
this.tenantId = tenantId;
this.direction = direction;
this.securityGroupId = securityGroupId;
this.ethertype = ethertype;
this.portRangeMin = portRangeMin;
this.portRangeMax = portRangeMax;
this.protocol = protocol;
this.remoteGroupId = remoteGroupId;
this.remoteIpPrefix = remoteIpPrefix;
}
private Rule(Rule rule) {
this(rule.id,
rule.tenantId,
rule.direction,
rule.securityGroupId,
rule.ethertype,
rule.portRangeMin,
rule.portRangeMax,
rule.protocol,
rule.remoteGroupId,
rule.remoteIpPrefix
);
}
private Rule() {}
/**
* @return The identifier for this rule.
*/
@Nullable
public String getId() {
return id;
}
/**
* @return The identifier of the tenant for this rule.
*/
@Nullable
public String getTenantId() {
return tenantId;
}
/**
* @return The direction in which the security group rule is applied.
*/
@Nullable
public RuleDirection getDirection() {
return direction;
}
/**
* @return The security group ID to associate with this security group rule.
*/
@Nullable
public String getSecurityGroupId() {
return securityGroupId;
}
/**
* @return The internet protocol version type of this rule.
*/
@Nullable
public RuleEthertype getEthertype() {
return ethertype;
}
/**
* @return The minimum port number in the range that is matched by the security group rule. If the protocol is TCP
* or UDP, this value must be less than or equal to the value of the port_range_max attribute. If the protocol is
* ICMP, this value must be an ICMP type.
*/
@Nullable
public Integer getPortRangeMin() {
return portRangeMin;
}
/**
* @return The maximum port number in the range that is matched by the security group rule. The port_range_min
* attribute constrains the port_range_max attribute. If the protocol is ICMP, this value must be an ICMP type.
*/
@Nullable
public Integer getPortRangeMax() {
return portRangeMax;
}
/**
* @return The protocol that is matched by the security group rule. Valid values are null, tcp, udp, and icmp.
*/
@Nullable
public RuleProtocol getProtocol() {
return protocol;
}
/**
* @return The remote group ID to be associated with this security group rule.
*/
@Nullable
public String getRemoteGroupId() {
return remoteGroupId;
}
/**
* @return The remote IP prefix to be associated with this security group rule. This attribute matches the specified
* IP prefix as the source IP address of the IP packet.
*/
@Nullable
public String getRemoteIpPrefix() {
return remoteIpPrefix;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
Rule that = (Rule) o;
return Objects.equal(this.id, that.id) &&
Objects.equal(this.tenantId, that.tenantId) &&
Objects.equal(this.direction, that.direction) &&
Objects.equal(this.securityGroupId, that.securityGroupId) &&
Objects.equal(this.ethertype, that.ethertype) &&
Objects.equal(this.portRangeMin, that.portRangeMin) &&
Objects.equal(this.portRangeMax, that.portRangeMax) &&
Objects.equal(this.protocol, that.protocol) &&
Objects.equal(this.remoteGroupId, that.remoteGroupId) &&
Objects.equal(this.remoteIpPrefix, that.remoteIpPrefix);
}
@Override
public int hashCode() {
return Objects.hashCode(id, tenantId, direction, securityGroupId, ethertype, portRangeMin,
portRangeMax, protocol, remoteGroupId, remoteIpPrefix);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("id", id)
.add("tenantId", tenantId)
.add("direction", direction)
.add("securityGroupId", securityGroupId)
.add("ethertype", ethertype)
.add("portRangeMin", portRangeMin)
.add("portRangeMax", portRangeMax)
.add("protocol", protocol)
.add("remoteGroupId", remoteGroupId)
.add("remoteIpPrefix", remoteIpPrefix)
.toString();
}
/*
* Methods to get the Create and Update builders follow
*/
/**
* @return the Builder for creating a new SecurityGroupRule
*/
public static CreateBuilder createOptions(RuleDirection direction, String securityGroupId) {
return new CreateBuilder(direction, securityGroupId);
}
public abstract static class Builder<ParameterizedBuilderType> {
// Keep track of the builder's state.
protected Rule rule;
private Builder() {
rule = new Rule();
}
protected abstract ParameterizedBuilderType self();
/**
* The tenant id for this rule. Usually can only be specified by administrators.
*
* @return the Builder.
* @see Rule#getTenantId()
*/
public ParameterizedBuilderType tenantId(String tenantId) {
rule.tenantId = tenantId;
return self();
}
/**
* The direction in which the security group rule is applied.
*
* @return the Builder.
* @see Rule#getDirection()
*/
public ParameterizedBuilderType direction(RuleDirection direction) {
rule.direction = direction;
return self();
}
/**
* The security group ID to associate with this security group rule.
*
* @return the Builder.
* @see Rule#getSecurityGroupId()
*/
public ParameterizedBuilderType securityGroupId(String securityGroupId) {
rule.securityGroupId = securityGroupId;
return self();
}
/**
* The internet protocol version for this rule.
*
* @return the Builder.
* @see Rule#getEthertype()
*/
public ParameterizedBuilderType ethertype(RuleEthertype ethertype) {
rule.ethertype = ethertype;
return self();
}
/**
* The minimum port number in the range that is matched by the security group rule.
*
* @return the Builder.
* @see Rule#getPortRangeMin()
*/
public ParameterizedBuilderType portRangeMin(Integer portRangeMin) {
rule.portRangeMin = portRangeMin;
return self();
}
/**
* The maximum port number in the range that is matched by the security group rule.
*
* @return the Builder.
* @see Rule#getPortRangeMax()
*/
public ParameterizedBuilderType portRangeMax(Integer portRangeMax) {
rule.portRangeMax = portRangeMax;
return self();
}
/**
* The protocol that is matched by the security group rule. Valid values are null, tcp, udp, and icmp.
*
* @return the Builder.
* @see Rule#getProtocol()
*/
public ParameterizedBuilderType protocol(RuleProtocol protocol) {
rule.protocol = protocol;
return self();
}
/**
* The remote group ID to be associated with this security group rule. You can specify either remote_group_id or
* remote_ip_prefix in the request body.
*
* @return the Builder.
* @see Rule#getRemoteGroupId()
*/
public ParameterizedBuilderType remoteGroupId(String remoteGroupId) {
rule.remoteGroupId = remoteGroupId;
return self();
}
/**
* The remote IP prefix to be associated with this security group rule. You can specify either remote_group_id
* or remote_ip_prefix in the request body. This attribute matches the specified IP prefix as the source IP
* address of the IP packet.
*
* @return the Builder.
* @see Rule#getRemoteIpPrefix()
*/
public ParameterizedBuilderType remoteIpPrefix(String remoteIpPrefix) {
rule.remoteIpPrefix = remoteIpPrefix;
return self();
}
}
/**
* This is used to build a CreateOptions object.
*/
public static class CreateBuilder extends Builder<CreateBuilder> {
/**
* Supply required properties for creating a Builder
*/
private CreateBuilder(RuleDirection direction, String securityGroupId) {
rule.direction = direction;
rule.securityGroupId = securityGroupId;
}
/**
* @return a CreateOptions constructed with this Builder.
*/
public CreateOptions build() {
return new CreateOptions(rule);
}
protected CreateBuilder self() {
return this;
}
}
/**
* Create and Update options - extend the domain class, passed to API update and create calls.
* Essentially the same as the domain class. Ensure validation and safe typing.
*/
public static class CreateOptions extends Rule {
private CreateOptions(Rule rule) {
super(rule);
checkNotNull(rule.getDirection(), "direction should not be null");
checkNotNull(rule.getSecurityGroupId(), "security group id should not be null");
checkState(rule.getPortRangeMax()>= rule.getPortRangeMin(),
"port range max should be greater than or equal to port range min");
checkState(rule.getRemoteGroupId()==null || rule.getRemoteIpPrefix()==null,
"You can specify either remote_group_id or remote_ip_prefix in the request body.");
}
}
}

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.openstack.neutron.v2.domain;
/**
* The direction in which the security group rule is applied.
*/
public enum RuleDirection {
/**
* For a compute instance, an ingress security group rule matches traffic that is incoming (ingress) for that instance.
*/
INGRESS("ingress"),
/**
* An egress rule is applied to traffic leaving the instance.
*/
EGRESS("egress"),
/**
* Used by jclouds when the service returns an unknown value other than null.
*/
UNRECOGNIZED("unrecognized");
private String name;
private RuleDirection(String name) {
this.name = name;
}
public String toString() {
return name;
}
/**
* This provides GSON enum support in jclouds.
* */
public static RuleDirection fromValue(String name){
if (name != null) {
for (RuleDirection value : RuleDirection.values()) {
if (name.equalsIgnoreCase(value.name)) {
return value;
}
}
return UNRECOGNIZED;
}
return null;
}
}

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.openstack.neutron.v2.domain;
/**
* The direction in which the security group rule is applied.
*/
public enum RuleEthertype {
/**
* Internet Protocol version 4
*/
IPV4("IPv4"),
/**
* Internet Protocol version 6
*/
IPV6("IPv6"),
/**
* Used by jclouds when the service returns an unknown value other than null.
*/
UNRECOGNIZED("unrecognized");
private String name;
private RuleEthertype(String name) {
this.name = name;
}
public String toString() {
return name;
}
/**
* This provides GSON enum support in jclouds.
* */
public static RuleEthertype fromValue(String name){
if (name != null) {
for (RuleEthertype value : RuleEthertype.values()) {
if (name.equalsIgnoreCase(value.name)) {
return value;
}
}
return UNRECOGNIZED;
}
return null;
}
}

View File

@ -0,0 +1,65 @@
/*
* 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.neutron.v2.domain;
/**
* The protocol that is matched by the security group rule. Valid values are null, tcp, udp, and icmp.
*/
public enum RuleProtocol {
/**
* Transmission Control Protocol
*/
TCP("tcp"),
/**
* User Datagram Protocol
*/
UDP("udp"),
/**
* Internet Control Message Protocol
*/
ICMP("icmp"),
/**
* Used by jclouds when the service returns an unknown value other than null.
*/
UNRECOGNIZED("unrecognized");
private String name;
private RuleProtocol(String name) {
this.name = name;
}
public String toString() {
return name;
}
/**
* This provides GSON enum support in jclouds.
* */
public static RuleProtocol fromValue(String name){
if (name != null) {
for (RuleProtocol value : RuleProtocol.values()) {
if (name.equalsIgnoreCase(value.name)) {
return value;
}
}
return UNRECOGNIZED;
}
return null;
}
}

View File

@ -0,0 +1,35 @@
/*
* 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.neutron.v2.domain;
import java.beans.ConstructorProperties;
import org.jclouds.openstack.v2_0.domain.Link;
import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
import com.google.common.collect.ImmutableSet;
/**
* A collection of Networks
*/
public class Rules extends PaginatedCollection<Rule> {
public static final Rules EMPTY = new Rules(ImmutableSet.<Rule> of(), ImmutableSet.<Link> of());
@ConstructorProperties({"security_group_rules", "security_group_rules_links"})
protected Rules(Iterable<Rule> securityGroups, Iterable<Link> securityGroupRulesLinks) {
super(securityGroups, securityGroupRulesLinks);
}
}

View File

@ -0,0 +1,219 @@
/*
* 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.neutron.v2.domain;
import java.beans.ConstructorProperties;
import javax.inject.Named;
import org.jclouds.javax.annotation.Nullable;
import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
/**
* Contains a mapping between a MAC address and an IP address.
*/
public class SecurityGroup {
private String id;
@Named("tenant_id")
private String tenantId;
private String name;
private String description;
@Named("security_group_rules")
private ImmutableList<Rule> rules;
@ConstructorProperties({"id", "tenant_id", "name", "description", "security_group_rules"})
protected SecurityGroup(String id, String tenantId, String name, String description,
ImmutableList<Rule> rules) {
this.id = id;
this.tenantId = tenantId;
this.name = name;
this.description = description;
this.rules = rules;
}
private SecurityGroup(SecurityGroup securityGroup) {
this(securityGroup.id,
securityGroup.tenantId,
securityGroup.name,
securityGroup.description,
securityGroup.rules
);
}
private SecurityGroup() {}
/**
* @return The identifier for this Security Group.
*/
@Nullable
public String getId() {
return id;
}
/**
* @return The identifier of the tenant for this Security Group.
*/
@Nullable
public String getTenantId() {
return tenantId;
}
/**
* @return The name of the Security Group.
*/
@Nullable
public String getName() {
return name;
}
/**
* @return The description of the Security Group.
*/
@Nullable
public String getDescription() {
return description;
}
/**
* @return The collection of rules for this Security Group.
*/
public ImmutableList<Rule> getRules() {
return rules!=null ? rules : ImmutableList.<Rule>of();
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
SecurityGroup that = (SecurityGroup) o;
return Objects.equal(this.id, that.id) &&
Objects.equal(this.tenantId, that.tenantId) &&
Objects.equal(this.name, that.name) &&
Objects.equal(this.description, that.description) &&
Objects.equal(this.rules, that.rules);
}
@Override
public int hashCode() {
return Objects.hashCode(id, tenantId, name, description, rules);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("id", id)
.add("tenantId", tenantId)
.add("name", name)
.add("description", description)
.add("securityGroupRules", rules)
.toString();
}
/*
* Methods to get the Create and Update builders follow
*/
/**
* @return the Builder for creating a new SecurityGroup
*/
public static CreateBuilder createOptions() {
return new CreateBuilder();
}
private abstract static class Builder<ParameterizedBuilderType> {
// Keep track of the builder's state.
protected SecurityGroup securityGroup;
private Builder() {
securityGroup = new SecurityGroup();
}
protected abstract ParameterizedBuilderType self();
/**
* The tenant id for this Security Group. Usually can only be specified by administrators.
*
* @return the Builder.
* @see SecurityGroup#getTenantId()
*/
public ParameterizedBuilderType tenantId(String tenantId) {
securityGroup.tenantId = tenantId;
return self();
}
/**
* The name for this Security Group.
*
* @return the Builder.
* @see SecurityGroup#getName()
*/
public ParameterizedBuilderType name(String name) {
securityGroup.name = name;
return self();
}
/**
* The description for this Security Group.
*
* @return the Builder.
* @see SecurityGroup#getDescription()
*/
public ParameterizedBuilderType description(String description) {
securityGroup.description = description;
return self();
}
}
/**
* Create and Update builders (inheriting from Builder)
*/
public static class CreateBuilder extends Builder<CreateBuilder> {
/**
* Supply required properties for creating a Builder
*/
private CreateBuilder() {
}
/**
* @return a CreateOptions constructed with this Builder.
*/
public CreateOptions build() {
return new CreateOptions(securityGroup);
}
protected CreateBuilder self() {
return this;
}
}
/**
* Create and Update options - extend the domain class, passed to API update and create calls.
* Essentially the same as the domain class. Ensure validation and safe typing.
*/
public static class CreateOptions extends SecurityGroup {
private CreateOptions(SecurityGroup securityGroup) {
super(securityGroup);
}
}
}

View File

@ -0,0 +1,36 @@
/*
* 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.neutron.v2.domain;
import java.beans.ConstructorProperties;
import org.jclouds.openstack.v2_0.domain.Link;
import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
import com.google.common.collect.ImmutableSet;
/**
* A collection of Networks
*/
public class SecurityGroups extends PaginatedCollection<SecurityGroup> {
public static final SecurityGroups EMPTY = new SecurityGroups(ImmutableSet.<SecurityGroup> of(), ImmutableSet.<Link> of());
@ConstructorProperties({"security_groups", "security_groups_links"})
protected SecurityGroups(Iterable<SecurityGroup> securityGroups, Iterable<Link> securityGroupsLinks) {
super(securityGroups, securityGroupsLinks);
}
}

View File

@ -0,0 +1,186 @@
/*
* 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.neutron.v2.extensions;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks;
import org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
import org.jclouds.collect.PagedIterable;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.neutron.v2.domain.Rule;
import org.jclouds.openstack.neutron.v2.domain.Rules;
import org.jclouds.openstack.neutron.v2.domain.SecurityGroup;
import org.jclouds.openstack.neutron.v2.domain.SecurityGroups;
import org.jclouds.openstack.neutron.v2.fallbacks.EmptyRulesFallback;
import org.jclouds.openstack.neutron.v2.fallbacks.EmptySecurityGroupsFallback;
import org.jclouds.openstack.neutron.v2.functions.ParseRules;
import org.jclouds.openstack.neutron.v2.functions.ParseSecurityGroups;
import org.jclouds.openstack.neutron.v2.functions.RulesToPagedIterable;
import org.jclouds.openstack.neutron.v2.functions.SecurityGroupsToPagedIterable;
import org.jclouds.openstack.v2_0.options.PaginationOptions;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.annotations.Transform;
import org.jclouds.rest.annotations.WrapWith;
import com.google.common.annotations.Beta;
/**
* Provides access to Security Group extension operations for the OpenStack Networking (Neutron) v2 API.
* <p/>
* Security groups and security group rules allows administrators and tenants the ability to specify the type of
* traffic and direction (ingress/egress) that is allowed to pass through a port. A security group is a container for
* security group rules.
*/
@Beta
@RequestFilters(AuthenticateRequest.class)
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public interface SecurityGroupApi {
/**
* Groups
*/
/**
* @return all security groups currently defined in Neutron for the current tenant.
*/
@Path("/security-groups")
@Named("security-group:list")
@GET
@ResponseParser(ParseSecurityGroups.class)
@Transform(SecurityGroupsToPagedIterable.class)
@Fallback(EmptyPagedIterableOnNotFoundOr404.class)
PagedIterable<SecurityGroup> listSecurityGroups();
/**
* @return all security groups currently defined in Neutron for the current tenant.
*/
@Path("/security-groups")
@Named("security-group:list")
@GET
@ResponseParser(ParseSecurityGroups.class)
@Fallback(EmptySecurityGroupsFallback.class)
SecurityGroups listSecurityGroups(PaginationOptions options);
/**
* @param id the id of the security group to return
* @return SecurityGroup or null if not found.
*/
@Path("/security-groups/{id}")
@Named("security-group:get")
@GET
@SelectJson("security_group")
@Fallback(Fallbacks.NullOnNotFoundOr404.class)
@Nullable
SecurityGroup getSecurityGroup(@PathParam("id") String id);
/**
* Create a new SecurityGroup.
*
* @param securityGroup Describes the security group to be created.
* @return a reference of the newly-created security group
*/
@Path("/security-groups")
@Named("secuity-group:create")
@POST
@SelectJson("security_group")
SecurityGroup create(@WrapWith("security_group") SecurityGroup.CreateOptions securityGroup);
/**
* Deletes the specified Security Group.
*
* @param id the id of the security group to delete
* @return true if delete was successful, false if not
*/
@Path("/security-groups/{id}")
@Named("security-group:delete")
@DELETE
@Fallback(Fallbacks.FalseOnNotFoundOr404.class)
boolean deleteSecurityGroup(@PathParam("id") String id);
/**
* Rules
*/
/**
* @return all security groups rules currently defined in Neutron for the current tenant.
*/
@Path("/security-group-rules")
@Named("security-group-rule:list")
@GET
@ResponseParser(ParseRules.class)
@Transform(RulesToPagedIterable.class)
@Fallback(EmptyPagedIterableOnNotFoundOr404.class)
PagedIterable<Rule> listRules();
/**
* @return all security groups rules currently defined in Neutron for the current tenant.
*/
@Path("/security-group-rules")
@Named("security-group-rule:list")
@GET
@ResponseParser(ParseRules.class)
@Fallback(EmptyRulesFallback.class)
Rules listRules(PaginationOptions options);
/**
* @param id the id of the security group rule to return.
* @return SecurityGroupRule or null if not found.
*/
@Path("/security-group-rules/{id}")
@Named("security-group-rule:get")
@GET
@SelectJson("security_group_rule")
@Fallback(Fallbacks.NullOnNotFoundOr404.class)
@Nullable
Rule get(@PathParam("id") String id);
/**
* Create a new Security Group Rule.
*
* @param securityGroupRule Describes the security group rule to be created.
* @return a reference of the newly-created security group rule.
*/
@Path("/security-group-rules")
@Named("security-group-rule:create")
@POST
@SelectJson("security_group_rule")
Rule create(@WrapWith("security_group_rule") Rule.CreateOptions securityGroupRule);
/**
* Deletes the specified Security Group Rule.
*
* @param id the id of the security group rule to delete.
* @return true if delete was successful, false if not.
*/
@Path("/security-group-rules/{id}")
@Named("security-group-rule:delete")
@DELETE
@Fallback(Fallbacks.FalseOnNotFoundOr404.class)
boolean deleteRule(@PathParam("id") String id);
}

View File

@ -0,0 +1,45 @@
/*
* 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.neutron.v2.fallbacks;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Throwables.propagate;
import static com.google.common.util.concurrent.Futures.immediateFuture;
import static org.jclouds.http.HttpUtils.contains404;
import static org.jclouds.util.Throwables2.getFirstThrowableOfType;
import org.jclouds.Fallback;
import org.jclouds.openstack.neutron.v2.domain.Rules;
import org.jclouds.rest.ResourceNotFoundException;
import com.google.common.util.concurrent.ListenableFuture;
public class EmptyRulesFallback implements Fallback<Rules> {
public ListenableFuture<Rules> create(Throwable t) throws Exception {
return immediateFuture(createOrPropagate(t));
}
@Override
public Rules createOrPropagate(Throwable t) throws Exception {
if ((getFirstThrowableOfType(checkNotNull(t, "throwable"), ResourceNotFoundException.class) != null)
|| contains404(t)) {
return Rules.EMPTY;
}
throw propagate(t);
}
}

View File

@ -0,0 +1,45 @@
/*
* 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.neutron.v2.fallbacks;
import com.google.common.util.concurrent.ListenableFuture;
import org.jclouds.Fallback;
import org.jclouds.openstack.neutron.v2.domain.SecurityGroups;
import org.jclouds.rest.ResourceNotFoundException;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Throwables.propagate;
import static com.google.common.util.concurrent.Futures.immediateFuture;
import static org.jclouds.http.HttpUtils.contains404;
import static org.jclouds.util.Throwables2.getFirstThrowableOfType;
public class EmptySecurityGroupsFallback implements Fallback<SecurityGroups> {
public ListenableFuture<SecurityGroups> create(Throwable t) throws Exception {
return immediateFuture(createOrPropagate(t));
}
@Override
public SecurityGroups createOrPropagate(Throwable t) throws Exception {
if ((getFirstThrowableOfType(checkNotNull(t, "throwable"), ResourceNotFoundException.class) != null)
|| contains404(t)) {
return SecurityGroups.EMPTY;
}
throw propagate(t);
}
}

View File

@ -0,0 +1,38 @@
/*
* 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.neutron.v2.functions;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.http.functions.ParseJson;
import org.jclouds.json.Json;
import org.jclouds.openstack.neutron.v2.domain.Rules;
import com.google.inject.TypeLiteral;
/**
* Used by jclouds to provide more specific collections and fallbacks.
*/
@Singleton
public class ParseRules extends ParseJson<Rules> {
@Inject
public ParseRules(Json json) {
super(json, TypeLiteral.get(Rules.class));
}
}

View File

@ -0,0 +1,38 @@
/*
* 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.neutron.v2.functions;
import com.google.inject.TypeLiteral;
import org.jclouds.http.functions.ParseJson;
import org.jclouds.json.Json;
import org.jclouds.openstack.neutron.v2.domain.SecurityGroup;
import org.jclouds.openstack.neutron.v2.domain.SecurityGroups;
import javax.inject.Inject;
import javax.inject.Singleton;
/**
* Used by jclouds to provide more specific collections and fallbacks.
*/
@Singleton
public class ParseSecurityGroups extends ParseJson<SecurityGroups> {
@Inject
public ParseSecurityGroups(Json json) {
super(json, TypeLiteral.get(SecurityGroups.class));
}
}

View File

@ -0,0 +1,66 @@
/*
* 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.neutron.v2.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Inject;
import org.jclouds.collect.IterableWithMarker;
import org.jclouds.collect.internal.Arg0ToPagedIterable;
import org.jclouds.openstack.neutron.v2.NeutronApi;
import org.jclouds.openstack.neutron.v2.domain.Rule;
import org.jclouds.openstack.neutron.v2.extensions.SecurityGroupApi;
import org.jclouds.openstack.v2_0.options.PaginationOptions;
import com.google.common.base.Function;
import com.google.common.base.Optional;
/**
* Ensures Routers works as PagedIterable.
*/
public class RulesToPagedIterable extends
Arg0ToPagedIterable.FromCaller<Rule, RulesToPagedIterable> {
private final NeutronApi api;
@Inject
protected RulesToPagedIterable(NeutronApi api) {
this.api = checkNotNull(api, "api");
}
@Override
protected Function<Object, IterableWithMarker<Rule>> markerToNextForArg0(Optional<Object> arg0) {
String region = arg0.isPresent() ? arg0.get().toString() : null;
final SecurityGroupApi securityGroupApi = api.getSecurityGroupApi(region).get();
return new Function<Object, IterableWithMarker<Rule>>() {
@SuppressWarnings("unchecked")
@Override
public IterableWithMarker<Rule> apply(Object input) {
PaginationOptions paginationOptions = PaginationOptions.class.cast(input);
return IterableWithMarker.class.cast(securityGroupApi.listRules(paginationOptions));
}
@Override
public String toString() {
return "listRules()";
}
};
}
}

View File

@ -0,0 +1,66 @@
/*
* 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.neutron.v2.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Inject;
import org.jclouds.collect.IterableWithMarker;
import org.jclouds.collect.internal.Arg0ToPagedIterable;
import org.jclouds.openstack.neutron.v2.NeutronApi;
import org.jclouds.openstack.neutron.v2.domain.SecurityGroup;
import org.jclouds.openstack.neutron.v2.extensions.SecurityGroupApi;
import org.jclouds.openstack.v2_0.options.PaginationOptions;
import com.google.common.base.Function;
import com.google.common.base.Optional;
/**
* Ensures Routers works as PagedIterable.
*/
public class SecurityGroupsToPagedIterable extends
Arg0ToPagedIterable.FromCaller<SecurityGroup, SecurityGroupsToPagedIterable> {
private final NeutronApi api;
@Inject
protected SecurityGroupsToPagedIterable(NeutronApi api) {
this.api = checkNotNull(api, "api");
}
@Override
protected Function<Object, IterableWithMarker<SecurityGroup>> markerToNextForArg0(Optional<Object> arg0) {
String region = arg0.isPresent() ? arg0.get().toString() : null;
final SecurityGroupApi securityGroupApi = api.getSecurityGroupApi(region).get();
return new Function<Object, IterableWithMarker<SecurityGroup>>() {
@SuppressWarnings("unchecked")
@Override
public IterableWithMarker<SecurityGroup> apply(Object input) {
PaginationOptions paginationOptions = PaginationOptions.class.cast(input);
return IterableWithMarker.class.cast(securityGroupApi.listSecurityGroups(paginationOptions));
}
@Override
public String toString() {
return "listSecurityGroups()";
}
};
}
}

View File

@ -0,0 +1,88 @@
/*
* 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.neutron.v2.extensions;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import org.jclouds.openstack.neutron.v2.domain.Rule;
import org.jclouds.openstack.neutron.v2.domain.RuleDirection;
import org.jclouds.openstack.neutron.v2.domain.RuleEthertype;
import org.jclouds.openstack.neutron.v2.domain.RuleProtocol;
import org.jclouds.openstack.neutron.v2.domain.SecurityGroup;
import org.jclouds.openstack.neutron.v2.internal.BaseNeutronApiLiveTest;
import org.testng.annotations.Test;
/**
* Tests parsing and Guice wiring of RouterApi
*/
@Test(groups = "live", testName = "SecurityGroupApiLiveTest")
public class SecurityGroupApiLiveTest extends BaseNeutronApiLiveTest {
/**
* Smoke test for the Security Group extension for Neutron
*/
public void testCreateUpdateAndDeleteSecurityGroup() {
for (String region : api.getConfiguredRegions()) {
SecurityGroupApi sgApi = api.getSecurityGroupApi(region).get();
SecurityGroup securityGroup = sgApi.create(
SecurityGroup.createOptions().name("jclouds-test").description("jclouds test security group").build());
assertNotNull(securityGroup);
Rule rule = sgApi.create(
Rule.createOptions(RuleDirection.EGRESS, securityGroup.getId())
.ethertype(RuleEthertype.IPV6)
.portRangeMax(90)
.portRangeMin(80)
.protocol(RuleProtocol.TCP)
.build());
assertNotNull(rule);
// Refresh
securityGroup = sgApi.getSecurityGroup(securityGroup.getId());
assertEquals(securityGroup.getName(), "jclouds-test");
assertEquals(securityGroup.getDescription(), "jclouds test security group");
assertEquals(securityGroup.getRules().size(), 3, "Expected 2 default rules");
Rule newSecGroupRule = null;
for(Rule sgr : securityGroup.getRules()) {
if(sgr.getId().equals(rule.getId())) {
newSecGroupRule = sgr;
break;
}
}
assertNotNull(newSecGroupRule, "Did not find the new rule in the group.");
assertEquals(rule, newSecGroupRule);
assertEquals(rule.getEthertype(), RuleEthertype.IPV6);
assertEquals(rule.getProtocol(), RuleProtocol.TCP);
assertEquals(rule.getPortRangeMax().intValue(), 90);
assertEquals(rule.getPortRangeMin().intValue(), 80);
assertEquals(rule.getDirection(), RuleDirection.EGRESS);
assertTrue(sgApi.deleteRule(rule.getId()));
assertTrue(sgApi.deleteSecurityGroup(securityGroup.getId()));
}
}
}

View File

@ -0,0 +1,655 @@
/*
* 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.neutron.v2.extensions;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.List;
import org.jclouds.openstack.neutron.v2.NeutronApi;
import org.jclouds.openstack.neutron.v2.domain.Rule;
import org.jclouds.openstack.neutron.v2.domain.RuleDirection;
import org.jclouds.openstack.neutron.v2.domain.RuleEthertype;
import org.jclouds.openstack.neutron.v2.domain.RuleProtocol;
import org.jclouds.openstack.neutron.v2.domain.Rules;
import org.jclouds.openstack.neutron.v2.domain.SecurityGroup;
import org.jclouds.openstack.neutron.v2.domain.SecurityGroups;
import org.jclouds.openstack.neutron.v2.internal.BaseNeutronApiMockTest;
import org.jclouds.openstack.v2_0.options.PaginationOptions;
import org.jclouds.rest.ResourceNotFoundException;
import org.testng.annotations.Test;
import com.squareup.okhttp.mockwebserver.MockResponse;
import com.squareup.okhttp.mockwebserver.MockWebServer;
/**
* Tests NetworkApi Guice wiring and parsing
*
*/
@Test
public class SecurityGroupApiMockTest extends BaseNeutronApiMockTest {
public void testCreateSecurityGroup() throws IOException, InterruptedException, URISyntaxException {
MockWebServer server = mockOpenStackServer();
server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
server.enqueue(addCommonHeaders(
new MockResponse().setResponseCode(201).setBody(stringFromResource("/security_group_create_response.json"))));
try {
NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
SecurityGroupApi api = neutronApi.getSecurityGroupApi("RegionOne").get();
SecurityGroup.CreateOptions createSecurityGroup = SecurityGroup.createOptions().name("new-webservers")
.description("security group for webservers")
.build();
SecurityGroup securityGroup = api.create(createSecurityGroup);
/*
* Check request
*/
assertAuthentication(server);
assertRequest(server.takeRequest(), "POST", "/v2.0/security-groups", "/security_group_create_request.json");
/*
* Check response
*/
assertNotNull(securityGroup);
assertEquals(securityGroup.getId(), "2076db17-a522-4506-91de-c6dd8e837028");
assertEquals(securityGroup.getTenantId(), "e4f50856753b4dc6afee5fa6b9b6c550");
assertEquals(securityGroup.getName(), "new-webservers");
assertEquals(securityGroup.getDescription(), "security group for webservers");
Rule sgr0 = securityGroup.getRules().get(0);
Rule sgr1 = securityGroup.getRules().get(1);
assertEquals(sgr0.getId(), "38ce2d8e-e8f1-48bd-83c2-d33cb9f50c3d");
assertEquals(sgr1.getId(), "565b9502-12de-4ffd-91e9-68885cff6ae1");
} finally {
server.shutdown();
}
}
@Test(expectedExceptions = ResourceNotFoundException.class)
public void testCreateSecurityGroupFail() throws IOException, InterruptedException, URISyntaxException {
MockWebServer server = mockOpenStackServer();
server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
server.enqueue(addCommonHeaders(
new MockResponse().setResponseCode(404)));
try {
NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
SecurityGroupApi api = neutronApi.getSecurityGroupApi("RegionOne").get();
SecurityGroup.CreateOptions createSecurityGroup = SecurityGroup.createOptions().name("new-webservers")
.description("security group for webservers")
.build();
SecurityGroup securityGroup = api.create(createSecurityGroup);
} finally {
server.shutdown();
}
}
public void testCreateSecurityGroupRule() throws IOException, InterruptedException, URISyntaxException {
MockWebServer server = mockOpenStackServer();
server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
server.enqueue(addCommonHeaders(
new MockResponse().setResponseCode(201).setBody(stringFromResource("/security_group_rule_create_response.json"))));
try {
NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
SecurityGroupApi api = neutronApi.getSecurityGroupApi("RegionOne").get();
Rule.CreateOptions createSecurityGroupRule = Rule.createOptions(
RuleDirection.INGRESS, "a7734e61-b545-452d-a3cd-0189cbd9747a")
.portRangeMin(80)
.portRangeMax(80)
.ethertype(RuleEthertype.IPV4)
.protocol(RuleProtocol.TCP)
.remoteGroupId("85cc3048-abc3-43cc-89b3-377341426ac5")
.build();
Rule rule = api.create(createSecurityGroupRule);
/*
* Check request
*/
assertAuthentication(server);
assertRequest(server.takeRequest(), "POST", "/v2.0/security-group-rules", "/security_group_rule_create_request.json");
/*
* Check response
*/
assertNotNull(rule);
assertEquals(rule.getId(), "2bc0accf-312e-429a-956e-e4407625eb62");
assertEquals(rule.getTenantId(), "e4f50856753b4dc6afee5fa6b9b6c550");
assertEquals(rule.getDirection(), RuleDirection.INGRESS);
assertEquals(rule.getPortRangeMax().intValue(), 80);
assertEquals(rule.getPortRangeMin().intValue(), 80);
assertEquals(rule.getEthertype(), RuleEthertype.IPV4);
assertEquals(rule.getProtocol(), RuleProtocol.TCP);
assertEquals(rule.getRemoteGroupId(), "85cc3048-abc3-43cc-89b3-377341426ac5");
assertEquals(rule.getSecurityGroupId(), "a7734e61-b545-452d-a3cd-0189cbd9747a");
} finally {
server.shutdown();
}
}
@Test(expectedExceptions = ResourceNotFoundException.class)
public void testCreateSecurityGroupRuleFail() throws IOException, InterruptedException, URISyntaxException {
MockWebServer server = mockOpenStackServer();
server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
server.enqueue(addCommonHeaders(
new MockResponse().setResponseCode(404)));
try {
NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
SecurityGroupApi api = neutronApi.getSecurityGroupApi("RegionOne").get();
Rule.CreateOptions createSecurityGroupRule = Rule.createOptions(
RuleDirection.INGRESS, "a7734e61-b545-452d-a3cd-0189cbd9747a")
.portRangeMin(80)
.portRangeMax(80)
.ethertype(RuleEthertype.IPV4)
.protocol(RuleProtocol.TCP)
.remoteGroupId("85cc3048-abc3-43cc-89b3-377341426ac5")
.build();
Rule rule = api.create(createSecurityGroupRule);
} finally {
server.shutdown();
}
}
public void testListSpecificPageSecurityGroup() throws IOException, InterruptedException, URISyntaxException {
MockWebServer server = mockOpenStackServer();
server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(200).setBody(stringFromResource("/security_group_list_response_paged1.json"))));
try {
NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
SecurityGroupApi api = neutronApi.getSecurityGroupApi("RegionOne").get();
SecurityGroups securityGroups = api.listSecurityGroups(PaginationOptions.Builder.limit(2).marker("abcdefg"));
/*
* Check request
*/
assertAuthentication(server);
assertRequest(server.takeRequest(), "GET", "/v2.0/security-groups?limit=2&marker=abcdefg");
/*
* Check response
*/
assertNotNull(securityGroups);
assertEquals(securityGroups.size(), 2);
assertEquals(securityGroups.first().get().getId(), "85cc3048-abc3-43cc-89b3-377341426ac5");
assertEquals(securityGroups.get(1).getId(), "85cc3048-abc3-43cc-89b3-377341426ac52");
} finally {
server.shutdown();
}
}
public void testListSpecificPageSecurityGroupFail() throws IOException, InterruptedException, URISyntaxException {
MockWebServer server = mockOpenStackServer();
server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(404)));
try {
NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
SecurityGroupApi api = neutronApi.getSecurityGroupApi("RegionOne").get();
SecurityGroups securityGroups = api.listSecurityGroups(PaginationOptions.Builder.limit(2).marker("abcdefg"));
/*
* Check request
*/
assertAuthentication(server);
assertRequest(server.takeRequest(), "GET", "/v2.0/security-groups?limit=2&marker=abcdefg");
/*
* Check response
*/
assertNotNull(securityGroups);
assertTrue(securityGroups.isEmpty());
} finally {
server.shutdown();
}
}
public void testListSpecificPageSecurityGroupRule() throws IOException, InterruptedException, URISyntaxException {
MockWebServer server = mockOpenStackServer();
server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(200).setBody(stringFromResource("/security_group_rule_list_response_paged1.json"))));
try {
NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
SecurityGroupApi api = neutronApi.getSecurityGroupApi("RegionOne").get();
Rules rules = api.listRules(PaginationOptions.Builder.limit(2).marker("abcdefg"));
/*
* Check request
*/
assertAuthentication(server);
assertRequest(server.takeRequest(), "GET", "/v2.0/security-group-rules?limit=2&marker=abcdefg");
/*
* Check response
*/
assertNotNull(rules);
assertEquals(rules.size(), 4);
assertEquals(rules.first().get().getId(), "3c0e45ff-adaf-4124-b083-bf390e5482ff");
assertEquals(rules.get(3).getId(), "f7d45c89-008e-4bab-88ad-d6811724c51c");
} finally {
server.shutdown();
}
}
public void testListSpecificPageSecurityGroupRuleFail() throws IOException, InterruptedException, URISyntaxException {
MockWebServer server = mockOpenStackServer();
server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(404)));
try {
NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
SecurityGroupApi api = neutronApi.getSecurityGroupApi("RegionOne").get();
Rules rules = api.listRules(PaginationOptions.Builder.limit(2).marker("abcdefg"));
/*
* Check request
*/
assertAuthentication(server);
assertRequest(server.takeRequest(), "GET", "/v2.0/security-group-rules?limit=2&marker=abcdefg");
/*
* Check response
*/
assertNotNull(rules);
assertTrue(rules.isEmpty());
} finally {
server.shutdown();
}
}
public void testListPagedSecurityGroups() throws IOException, InterruptedException, URISyntaxException {
MockWebServer server = mockOpenStackServer();
server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(200).setBody(stringFromResource("/security_group_list_response_paged1.json"))));
server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(200).setBody(stringFromResource("/security_group_list_response_paged2.json"))));
try {
NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
SecurityGroupApi api = neutronApi.getSecurityGroupApi("RegionOne").get();
// Note: Lazy! Have to actually look at the collection.
List<SecurityGroup> securityGroups = api.listSecurityGroups().concat().toList();
/*
* Check request
*/
assertEquals(server.getRequestCount(), 3);
assertAuthentication(server);
assertRequest(server.takeRequest(), "GET", "/v2.0/security-groups");
assertRequest(server.takeRequest(), "GET", "/v2.0/security-groups?marker=71c1e68c-171a-4aa2-aca5-50ea153a3718");
/*
* Check response
*/
assertNotNull(securityGroups);
assertEquals(securityGroups.size(), 4);
assertEquals(securityGroups.get(0).getId(), "85cc3048-abc3-43cc-89b3-377341426ac5");
assertEquals(securityGroups.get(3).getId(), "85cc3048-abc3-43cc-89b3-377341426ac524");
} finally {
server.shutdown();
}
}
public void testListPagedSecurityGroupsFail() throws IOException, InterruptedException, URISyntaxException {
MockWebServer server = mockOpenStackServer();
server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(404)));
try {
NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
SecurityGroupApi api = neutronApi.getSecurityGroupApi("RegionOne").get();
// Note: Lazy! Have to actually look at the collection.
List<SecurityGroup> securityGroups = api.listSecurityGroups().concat().toList();
/*
* Check request
*/
assertEquals(server.getRequestCount(), 2);
assertAuthentication(server);
assertRequest(server.takeRequest(), "GET", "/v2.0/security-groups");
/*
* Check response
*/
assertNotNull(securityGroups);
assertTrue(securityGroups.isEmpty());
} finally {
server.shutdown();
}
}
public void testListPagedSecurityGroupRules() throws IOException, InterruptedException, URISyntaxException {
MockWebServer server = mockOpenStackServer();
server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(200).setBody(stringFromResource("/security_group_rule_list_response_paged1.json"))));
server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(200).setBody(stringFromResource("/security_group_rule_list_response_paged2.json"))));
try {
NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
SecurityGroupApi api = neutronApi.getSecurityGroupApi("RegionOne").get();
// Note: Lazy! Have to actually look at the collection.
List<Rule> rules = api.listRules().concat().toList();
/*
* Check request
*/
assertEquals(server.getRequestCount(), 3);
assertAuthentication(server);
assertRequest(server.takeRequest(), "GET", "/v2.0/security-group-rules");
assertRequest(server.takeRequest(), "GET", "/v2.0/security-group-rules?marker=71c1e68c-171a-4aa2-aca5-50ea153a3718");
/*
* Check response
*/
assertNotNull(rules);
assertEquals(rules.size(), 8);
assertEquals(rules.get(0).getId(), "3c0e45ff-adaf-4124-b083-bf390e5482ff");
assertEquals(rules.get(7).getId(), "f7d45c89-008e-4bab-88ad-d6811724c51c2");
} finally {
server.shutdown();
}
}
public void testListPagedSecurityGroupRulesFail() throws IOException, InterruptedException, URISyntaxException {
MockWebServer server = mockOpenStackServer();
server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(404)));
try {
NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
SecurityGroupApi api = neutronApi.getSecurityGroupApi("RegionOne").get();
// Note: Lazy! Have to actually look at the collection.
List<Rule> rules = api.listRules().concat().toList();
/*
* Check request
*/
assertEquals(server.getRequestCount(), 2);
assertAuthentication(server);
assertRequest(server.takeRequest(), "GET", "/v2.0/security-group-rules");
/*
* Check response
*/
assertNotNull(rules);
assertTrue(rules.isEmpty());
} finally {
server.shutdown();
}
}
public void testGetSecurityGroup() throws IOException, InterruptedException, URISyntaxException {
MockWebServer server = mockOpenStackServer();
server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
server.enqueue(addCommonHeaders(
new MockResponse().setResponseCode(201).setBody(stringFromResource("/security_group_get_response.json"))));
try {
NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
SecurityGroupApi api = neutronApi.getSecurityGroupApi("RegionOne").get();
SecurityGroup securityGroup = api.getSecurityGroup("12345");
/*
* Check request
*/
assertAuthentication(server);
assertRequest(server.takeRequest(), "GET", "/v2.0/security-groups/12345");
/*
* Check response
*/
assertNotNull(securityGroup);
assertEquals(securityGroup.getName(), "default");
assertEquals(securityGroup.getDescription(), "default");
assertEquals(securityGroup.getId(), "85cc3048-abc3-43cc-89b3-377341426ac5");
assertEquals(securityGroup.getTenantId(), "e4f50856753b4dc6afee5fa6b9b6c550");
Rule sgr = securityGroup.getRules().get(0);
assertEquals(sgr.getId(), "3c0e45ff-adaf-4124-b083-bf390e5482ff");
} finally {
server.shutdown();
}
}
public void testGetSecurityGroupFail() throws IOException, InterruptedException, URISyntaxException {
MockWebServer server = mockOpenStackServer();
server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
server.enqueue(addCommonHeaders(
new MockResponse().setResponseCode(404)));
try {
NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
SecurityGroupApi api = neutronApi.getSecurityGroupApi("RegionOne").get();
SecurityGroup securityGroup = api.getSecurityGroup("12345");
/*
* Check request
*/
assertAuthentication(server);
assertRequest(server.takeRequest(), "GET", "/v2.0/security-groups/12345");
/*
* Check response
*/
assertNull(securityGroup);
} finally {
server.shutdown();
}
}
public void testGetSecurityGroupRule() throws IOException, InterruptedException, URISyntaxException {
MockWebServer server = mockOpenStackServer();
server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
server.enqueue(addCommonHeaders(
new MockResponse().setResponseCode(201).setBody(stringFromResource("/security_group_rule_get_response.json"))));
try {
NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
SecurityGroupApi api = neutronApi.getSecurityGroupApi("RegionOne").get();
Rule rule = api.get("12345");
/*
* Check request
*/
assertAuthentication(server);
assertRequest(server.takeRequest(), "GET", "/v2.0/security-group-rules/12345");
/*
* Check response
*/
assertNotNull(rule);
assertEquals(rule.getDirection(), RuleDirection.EGRESS);
assertEquals(rule.getEthertype(), RuleEthertype.IPV6);
assertEquals(rule.getId(), "3c0e45ff-adaf-4124-b083-bf390e5482ff");
assertEquals(rule.getTenantId(), "e4f50856753b4dc6afee5fa6b9b6c550");
assertEquals(rule.getSecurityGroupId(), "85cc3048-abc3-43cc-89b3-377341426ac5");
} finally {
server.shutdown();
}
}
public void testGetSecurityGroupRuleFail() throws IOException, InterruptedException, URISyntaxException {
MockWebServer server = mockOpenStackServer();
server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
server.enqueue(addCommonHeaders(
new MockResponse().setResponseCode(404)));
try {
NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
SecurityGroupApi api = neutronApi.getSecurityGroupApi("RegionOne").get();
Rule rule = api.get("12345");
/*
* Check request
*/
assertAuthentication(server);
assertRequest(server.takeRequest(), "GET", "/v2.0/security-group-rules/12345");
/*
* Check response
*/
assertNull(rule);
} finally {
server.shutdown();
}
}
public void testDeleteSecurityGroup() throws IOException, InterruptedException, URISyntaxException {
MockWebServer server = mockOpenStackServer();
server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
server.enqueue(addCommonHeaders(
new MockResponse().setResponseCode(201)));
try {
NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
SecurityGroupApi api = neutronApi.getSecurityGroupApi("RegionOne").get();
boolean result = api.deleteSecurityGroup("12345");
/*
* Check request
*/
assertAuthentication(server);
assertRequest(server.takeRequest(), "DELETE", "/v2.0/security-groups/12345");
/*
* Check response
*/
assertTrue(result);
} finally {
server.shutdown();
}
}
public void testDeleteSecurityGroupFail() throws IOException, InterruptedException, URISyntaxException {
MockWebServer server = mockOpenStackServer();
server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
server.enqueue(addCommonHeaders(
new MockResponse().setResponseCode(404)));
try {
NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
SecurityGroupApi api = neutronApi.getSecurityGroupApi("RegionOne").get();
boolean result = api.deleteSecurityGroup("12345");
/*
* Check request
*/
assertAuthentication(server);
assertRequest(server.takeRequest(), "DELETE", "/v2.0/security-groups/12345");
/*
* Check response
*/
assertFalse(result);
} finally {
server.shutdown();
}
}
public void testDeleteSecurityGroupRule() throws IOException, InterruptedException, URISyntaxException {
MockWebServer server = mockOpenStackServer();
server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
server.enqueue(addCommonHeaders(
new MockResponse().setResponseCode(201)));
try {
NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
SecurityGroupApi api = neutronApi.getSecurityGroupApi("RegionOne").get();
boolean result = api.deleteRule("12345");
/*
* Check request
*/
assertAuthentication(server);
assertRequest(server.takeRequest(), "DELETE", "/v2.0/security-group-rules/12345");
/*
* Check response
*/
assertTrue(result);
} finally {
server.shutdown();
}
}
public void testDeleteSecurityGroupRuleFail() throws IOException, InterruptedException, URISyntaxException {
MockWebServer server = mockOpenStackServer();
server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
server.enqueue(addCommonHeaders(
new MockResponse().setResponseCode(404)));
try {
NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
SecurityGroupApi api = neutronApi.getSecurityGroupApi("RegionOne").get();
boolean result = api.deleteRule("12345");
/*
* Check request
*/
assertAuthentication(server);
assertRequest(server.takeRequest(), "DELETE", "/v2.0/security-group-rules/12345");
/*
* Check response
*/
assertFalse(result);
} finally {
server.shutdown();
}
}
}

View File

@ -65,7 +65,7 @@ public class PortApiMockTest extends BaseNeutronApiMockTest {
.name("port1")
.adminStateUp(true)
.deviceId("d6b4d3a5-c700-476f-b609-1493dd9dadc0")
.allowedAddressPairs(ImmutableSet.of(AddressPair.createOptions("12", "111.222.333.444").build()))
.allowedAddressPairs(ImmutableSet.of(AddressPair.builder("12", "111.222.333.444").build()))
.build();
Port port = api.create(createPort);
@ -112,7 +112,7 @@ public class PortApiMockTest extends BaseNeutronApiMockTest {
.name("port1")
.adminStateUp(true)
.deviceId("d6b4d3a5-c700-476f-b609-1493dd9dadc0")
.allowedAddressPairs(ImmutableSet.of(AddressPair.createOptions("12", "111.222.333.444").build()))
.allowedAddressPairs(ImmutableSet.of(AddressPair.builder("12", "111.222.333.444").build()))
.build();
Port port = api.create(createPort);

View File

@ -0,0 +1,6 @@
{
"security_group": {
"name": "new-webservers",
"description": "security group for webservers"
}
}

View File

@ -0,0 +1,34 @@
{
"security_group": {
"description": "security group for webservers",
"id": "2076db17-a522-4506-91de-c6dd8e837028",
"name": "new-webservers",
"security_group_rules": [
{
"direction": "egress",
"ethertype": "IPv4",
"id": "38ce2d8e-e8f1-48bd-83c2-d33cb9f50c3d",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": null,
"remote_ip_prefix": null,
"security_group_id": "2076db17-a522-4506-91de-c6dd8e837028",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
},
{
"direction": "egress",
"ethertype": "IPv6",
"id": "565b9502-12de-4ffd-91e9-68885cff6ae1",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": null,
"remote_ip_prefix": null,
"security_group_id": "2076db17-a522-4506-91de-c6dd8e837028",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
}
],
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
}
}

View File

@ -0,0 +1,58 @@
{
"security_group": {
"description": "default",
"id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"name": "default",
"security_group_rules": [
{
"direction": "egress",
"ethertype": "IPv6",
"id": "3c0e45ff-adaf-4124-b083-bf390e5482ff",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": null,
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
},
{
"direction": "egress",
"ethertype": "IPv4",
"id": "93aa42e5-80db-4581-9391-3a608bd0e448",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": null,
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
},
{
"direction": "ingress",
"ethertype": "IPv6",
"id": "c0b09f00-1d49-4e64-a0a7-8a186d928138",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
},
{
"direction": "ingress",
"ethertype": "IPv4",
"id": "f7d45c89-008e-4bab-88ad-d6811724c51c",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
}
],
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
}
}

View File

@ -0,0 +1,116 @@
{
"security_groups": [
{
"description": "default",
"id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"name": "default",
"security_group_rules": [
{
"direction": "egress",
"ethertype": "IPv6",
"id": "3c0e45ff-adaf-4124-b083-bf390e5482ff",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": null,
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
},
{
"direction": "egress",
"ethertype": "IPv4",
"id": "93aa42e5-80db-4581-9391-3a608bd0e448",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": null,
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
},
{
"direction": "ingress",
"ethertype": "IPv6",
"id": "c0b09f00-1d49-4e64-a0a7-8a186d928138",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
},
{
"direction": "ingress",
"ethertype": "IPv4",
"id": "f7d45c89-008e-4bab-88ad-d6811724c51c",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
}
],
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
},
{
"description": "default",
"id": "85cc3048-abc3-43cc-89b3-377341426ac52",
"name": "default",
"security_group_rules": [
{
"direction": "egress",
"ethertype": "IPv6",
"id": "3c0e45ff-adaf-4124-b083-bf390e5482ff2",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": null,
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
},
{
"direction": "egress",
"ethertype": "IPv4",
"id": "93aa42e5-80db-4581-9391-3a608bd0e4482",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": null,
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
},
{
"direction": "ingress",
"ethertype": "IPv6",
"id": "c0b09f00-1d49-4e64-a0a7-8a186d9281382",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
},
{
"direction": "ingress",
"ethertype": "IPv4",
"id": "f7d45c89-008e-4bab-88ad-d6811724c51c2",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
}
],
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
}
]
}

View File

@ -0,0 +1,126 @@
{
"security_groups": [
{
"description": "default",
"id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"name": "default",
"security_group_rules": [
{
"direction": "egress",
"ethertype": "IPv6",
"id": "3c0e45ff-adaf-4124-b083-bf390e5482ff",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": null,
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
},
{
"direction": "egress",
"ethertype": "IPv4",
"id": "93aa42e5-80db-4581-9391-3a608bd0e448",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": null,
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
},
{
"direction": "ingress",
"ethertype": "IPv6",
"id": "c0b09f00-1d49-4e64-a0a7-8a186d928138",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
},
{
"direction": "ingress",
"ethertype": "IPv4",
"id": "f7d45c89-008e-4bab-88ad-d6811724c51c",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
}
],
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
},
{
"description": "default",
"id": "85cc3048-abc3-43cc-89b3-377341426ac52",
"name": "default",
"security_group_rules": [
{
"direction": "egress",
"ethertype": "IPv6",
"id": "3c0e45ff-adaf-4124-b083-bf390e5482ff2",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": null,
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
},
{
"direction": "egress",
"ethertype": "IPv4",
"id": "93aa42e5-80db-4581-9391-3a608bd0e4482",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": null,
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
},
{
"direction": "ingress",
"ethertype": "IPv6",
"id": "c0b09f00-1d49-4e64-a0a7-8a186d9281382",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
},
{
"direction": "ingress",
"ethertype": "IPv4",
"id": "f7d45c89-008e-4bab-88ad-d6811724c51c2",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
}
],
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
}
],
"security_groups_links": [
{
"href": "/v2.0/security-groups.json?marker=71c1e68c-171a-4aa2-aca5-50ea153a3718",
"rel": "next"
},
{
"href": "/v2.0/security-groups.json?marker=396f12f8-521e-4b91-8e21-2e003500433a&page_reverse=True",
"rel": "previous"
}
]
}

View File

@ -0,0 +1,122 @@
{
"security_groups": [
{
"description": "default",
"id": "85cc3048-abc3-43cc-89b3-377341426ac53",
"name": "default",
"security_group_rules": [
{
"direction": "egress",
"ethertype": "IPv6",
"id": "3c0e45ff-adaf-4124-b083-bf390e5482ff",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": null,
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
},
{
"direction": "egress",
"ethertype": "IPv4",
"id": "93aa42e5-80db-4581-9391-3a608bd0e448",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": null,
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
},
{
"direction": "ingress",
"ethertype": "IPv6",
"id": "c0b09f00-1d49-4e64-a0a7-8a186d928138",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
},
{
"direction": "ingress",
"ethertype": "IPv4",
"id": "f7d45c89-008e-4bab-88ad-d6811724c51c",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
}
],
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
},
{
"description": "default",
"id": "85cc3048-abc3-43cc-89b3-377341426ac524",
"name": "default",
"security_group_rules": [
{
"direction": "egress",
"ethertype": "IPv6",
"id": "3c0e45ff-adaf-4124-b083-bf390e5482ff2",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": null,
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
},
{
"direction": "egress",
"ethertype": "IPv4",
"id": "93aa42e5-80db-4581-9391-3a608bd0e4482",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": null,
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
},
{
"direction": "ingress",
"ethertype": "IPv6",
"id": "c0b09f00-1d49-4e64-a0a7-8a186d9281382",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
},
{
"direction": "ingress",
"ethertype": "IPv4",
"id": "f7d45c89-008e-4bab-88ad-d6811724c51c2",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
}
],
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
}
],
"security_groups_links": [
{
"href": "/v2.0/security-groups.json?marker=396f12f8-521e-4b91-8e21-2e003500433a&page_reverse=True",
"rel": "previous"
}
]
}

View File

@ -0,0 +1,11 @@
{
"security_group_rule": {
"direction": "ingress",
"port_range_min": 80,
"ethertype": "IPv4",
"port_range_max": 80,
"protocol": "tcp",
"remote_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"security_group_id": "a7734e61-b545-452d-a3cd-0189cbd9747a"
}
}

View File

@ -0,0 +1,15 @@
{
"security_group_rule": {
"direction": "ingress",
"ethertype": "IPv4",
"id": "2bc0accf-312e-429a-956e-e4407625eb62",
"port_range_max": 80,
"port_range_min": 80,
"protocol": "tcp",
"remote_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"remote_ip_prefix": null,
"security_group_id": "a7734e61-b545-452d-a3cd-0189cbd9747a",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
}
}

View File

@ -0,0 +1,14 @@
{
"security_group_rule": {
"direction": "egress",
"ethertype": "IPv6",
"id": "3c0e45ff-adaf-4124-b083-bf390e5482ff",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": null,
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
}
}

View File

@ -0,0 +1,52 @@
{
"security_group_rules": [
{
"direction": "egress",
"ethertype": "IPv6",
"id": "3c0e45ff-adaf-4124-b083-bf390e5482ff",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": null,
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
},
{
"direction": "egress",
"ethertype": "IPv4",
"id": "93aa42e5-80db-4581-9391-3a608bd0e448",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": null,
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
},
{
"direction": "ingress",
"ethertype": "IPv6",
"id": "c0b09f00-1d49-4e64-a0a7-8a186d928138",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
},
{
"direction": "ingress",
"ethertype": "IPv4",
"id": "f7d45c89-008e-4bab-88ad-d6811724c51c",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
}
]
}

View File

@ -0,0 +1,62 @@
{
"security_group_rules": [
{
"direction": "egress",
"ethertype": "IPv6",
"id": "3c0e45ff-adaf-4124-b083-bf390e5482ff",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": null,
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
},
{
"direction": "egress",
"ethertype": "IPv4",
"id": "93aa42e5-80db-4581-9391-3a608bd0e448",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": null,
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
},
{
"direction": "ingress",
"ethertype": "IPv6",
"id": "c0b09f00-1d49-4e64-a0a7-8a186d928138",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
},
{
"direction": "ingress",
"ethertype": "IPv4",
"id": "f7d45c89-008e-4bab-88ad-d6811724c51c",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
}
],
"security_group_rules_links": [
{
"href": "/v2.0/security-group-rules.json?marker=71c1e68c-171a-4aa2-aca5-50ea153a3718",
"rel": "next"
},
{
"href": "/v2.0/security-group-rules.json?marker=396f12f8-521e-4b91-8e21-2e003500433a&page_reverse=True",
"rel": "previous"
}
]
}

View File

@ -0,0 +1,58 @@
{
"security_group_rules": [
{
"direction": "egress",
"ethertype": "IPv6",
"id": "3c0e45ff-adaf-4124-b083-bf390e5482ff2",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": null,
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
},
{
"direction": "egress",
"ethertype": "IPv4",
"id": "93aa42e5-80db-4581-9391-3a608bd0e4482",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": null,
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
},
{
"direction": "ingress",
"ethertype": "IPv6",
"id": "c0b09f00-1d49-4e64-a0a7-8a186d9281382",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
},
{
"direction": "ingress",
"ethertype": "IPv4",
"id": "f7d45c89-008e-4bab-88ad-d6811724c51c2",
"port_range_max": null,
"port_range_min": null,
"protocol": null,
"remote_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"remote_ip_prefix": null,
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
}
],
"security_group_rules_links": [
{
"href": "/v2.0/security-group-rules.json?marker=396f12f8-521e-4b91-8e21-2e003500433a&page_reverse=True",
"rel": "previous"
}
]
}