mirror of https://github.com/apache/jclouds.git
Adds support for the Security Group extension to neutron
This commit is contained in:
parent
b5b3a91fa3
commit
39d7a96d49
|
@ -25,6 +25,7 @@ import org.jclouds.Constants;
|
||||||
import org.jclouds.location.Region;
|
import org.jclouds.location.Region;
|
||||||
import org.jclouds.location.functions.RegionToEndpoint;
|
import org.jclouds.location.functions.RegionToEndpoint;
|
||||||
import org.jclouds.openstack.neutron.v2.extensions.RouterApi;
|
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.NetworkApi;
|
||||||
import org.jclouds.openstack.neutron.v2.features.PortApi;
|
import org.jclouds.openstack.neutron.v2.features.PortApi;
|
||||||
import org.jclouds.openstack.neutron.v2.features.SubnetApi;
|
import org.jclouds.openstack.neutron.v2.features.SubnetApi;
|
||||||
|
@ -89,4 +90,13 @@ public interface NeutronApi extends Closeable {
|
||||||
@Delegate
|
@Delegate
|
||||||
Optional<? extends RouterApi> getRouterExtensionApi(@EndpointParam(parser = RegionToEndpoint.class) String region);
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,19 +101,10 @@ public class AddressPair {
|
||||||
* In this case, both parameters are required.
|
* In this case, both parameters are required.
|
||||||
* @return the Builder for AddressPair
|
* @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);
|
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.
|
* Gets a Builder configured as this object.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
|
@ -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()";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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()";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -65,7 +65,7 @@ public class PortApiMockTest extends BaseNeutronApiMockTest {
|
||||||
.name("port1")
|
.name("port1")
|
||||||
.adminStateUp(true)
|
.adminStateUp(true)
|
||||||
.deviceId("d6b4d3a5-c700-476f-b609-1493dd9dadc0")
|
.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();
|
.build();
|
||||||
|
|
||||||
Port port = api.create(createPort);
|
Port port = api.create(createPort);
|
||||||
|
@ -112,7 +112,7 @@ public class PortApiMockTest extends BaseNeutronApiMockTest {
|
||||||
.name("port1")
|
.name("port1")
|
||||||
.adminStateUp(true)
|
.adminStateUp(true)
|
||||||
.deviceId("d6b4d3a5-c700-476f-b609-1493dd9dadc0")
|
.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();
|
.build();
|
||||||
|
|
||||||
Port port = api.create(createPort);
|
Port port = api.create(createPort);
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"security_group": {
|
||||||
|
"name": "new-webservers",
|
||||||
|
"description": "security group for webservers"
|
||||||
|
}
|
||||||
|
}
|
|
@ -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"
|
||||||
|
}
|
||||||
|
}
|
|
@ -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"
|
||||||
|
}
|
||||||
|
}
|
|
@ -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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -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"
|
||||||
|
}
|
||||||
|
}
|
|
@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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"
|
||||||
|
}
|
||||||
|
}
|
|
@ -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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
Loading…
Reference in New Issue