Skip to content

Commit

Permalink
Add workflows for managing ServiceGroup services.
Browse files Browse the repository at this point in the history
Change-Id: I978f64b431ba7d7c6b7e8fabd6b6d950ac8b3180
Partial-Bug: #1772594
  • Loading branch information
danieljasinski committed Jun 5, 2018
1 parent dfc37d6 commit 020779b
Show file tree
Hide file tree
Showing 40 changed files with 762 additions and 175 deletions.
Expand Up @@ -22,6 +22,7 @@ val isSingleAddressNetworkPolicyRule = "isSingleAddressNetworkPolicyRule"
val isSingleAddressSecurityGroupRule = "isSingleAddressSecurityGroupRule"
val networkOfServiceInterface = "networkOfServiceInterface"
val networkPolicyRules = "networkPolicyRules"
val serviceGroupServices = "serviceGroupServices"
val virtualNetworkSubnets = "virtualNetworkSubnets"
val networkIpamSubnets = "networkIpamSubnets"
val addressGroupSubnets = "addressGroupSubnets"
Expand All @@ -39,7 +40,7 @@ val serviceInstanceInterfaceNames = "serviceInstanceInterfaceNames"
val ipamHasAllocationMode = "ipamHasAllocationMode"
val ipamHasNotAllocationMode = "ipamHasNotAllocationMode"
val networkHasNotAllcationMode = "networkHasNotAllocationMode"
val propertyOfObjectRule = "propertyOfObjectRule"
val listElementProperty = "listElementProperty"
val listTagTypes = "listTagTypes"

val portOfVCVirtualMachine = "portOfVCVirtualMachine"
Expand Down
Expand Up @@ -20,10 +20,17 @@ val parent = "parent"
val child = "child"
val item = "item"
val name = "name"
val element = "element"
val id = "id"
val ingress = "ingress"
val egress = "egress"
val subnet = "subnet"
val any = "any"

val tcp = "tcp"
val udp = "udp"
val icmp = "icmp"
val icmp6 = "icmp6"

val maxOtherInterfacesSupported = 8
val supportedOtherInterfaces = (0 until maxOtherInterfacesSupported).map { "other$it" }
Expand All @@ -34,4 +41,6 @@ val supportedInterfaceNames = listOf(
) + supportedOtherInterfaces
val maxInterfacesSupported = supportedInterfaceNames.size

val VxLANMaxID = 16777215
val VxLANMaxID = 16777215
val minPort = 0
val maxPort = 65535
Expand Up @@ -7,6 +7,7 @@ package net.juniper.contrail.vro.model
import net.juniper.contrail.api.types.IpamSubnetType
import net.juniper.contrail.api.types.VirtualNetwork
import net.juniper.contrail.api.types.InstanceIp
import net.juniper.contrail.api.types.ServiceGroup
import net.juniper.contrail.api.types.VirtualMachineInterface
import net.juniper.contrail.api.types.ServiceTemplate
import net.juniper.contrail.api.types.ServiceInstance
Expand Down Expand Up @@ -48,4 +49,13 @@ NetworkPolicyRuleProperties by NetworkPolicyRulePropertyExecutor(connection) {

fun Connection.listTagTypes(): List<String> =
list<TagType>()?.asSequence()?.map { it.name }?.sorted()?.toList() ?: emptyList()

fun ServiceGroup.servicePropertyProtocol(ruleString: String): String? =
findService(ruleString)?.protocol

fun ServiceGroup.servicePropertyPort(ruleString: String): String? =
findService(ruleString)?.dstPorts?.let { utils.formatPort(it) }

private fun ServiceGroup.findService(ruleString: String) =
firewallServiceList?.firewallService?.getOrNull(ruleString.toIndex())
}
Expand Up @@ -421,7 +421,7 @@ open class NetworkPolicyRulePropertyExecutor(private val connection: Connection)
private fun NetworkPolicy.extractRule(
ruleString: String
): PolicyRuleType {
val ruleIndex = utils.ruleStringToIndex(ruleString)
val ruleIndex = utils.stringToIndex(ruleString)
return entries.policyRule[ruleIndex]
}

Expand Down
Expand Up @@ -116,7 +116,7 @@ class SecurityGroupRulePropertyExecutor(private val connection: Connection) : Se
private fun SecurityGroup.extractRule(
ruleString: String
): PolicyRuleType {
val ruleIndex = utils.ruleStringToIndex(ruleString)
val ruleIndex = utils.stringToIndex(ruleString)
return entries.policyRule[ruleIndex]
}
}
Expand Up @@ -16,16 +16,17 @@ import net.juniper.contrail.api.types.SubnetType
import net.juniper.contrail.api.types.VirtualNetwork
import net.juniper.contrail.api.types.VnSubnetsType
import net.juniper.contrail.api.types.AllowedAddressPair
import net.juniper.contrail.api.types.FirewallServiceType
import net.juniper.contrail.api.types.IpamSubnetType
import net.juniper.contrail.api.types.ServiceGroup
import net.juniper.contrail.vro.base.Description
import net.juniper.contrail.vro.config.constants.minPort
import net.juniper.contrail.vro.config.constants.maxPort
import net.juniper.contrail.vro.format.PropertyFormatter
import java.util.UUID

@Description("Object containing miscellaneous utility functions used by workflows and actions, e.g. IP address validation.")
class Utils {
private val minPort = 0
private val maxPort = 65535

private val macPattern =
"^(?:[\\p{XDigit}]{1,2}([-:]))(?:[\\p{XDigit}]{1,2}\\1){4}[\\p{XDigit}]{1,2}$".toRegex()

Expand Down Expand Up @@ -154,6 +155,8 @@ class Utils {
fun formatPort(port: PortType): String =
if (port.startPort == port.endPort)
if (port.startPort == -1) "any" else "${port.startPort}"
else if (port.startPort == minPort && port.endPort == maxPort)
"any"
else
"${port.startPort}-${port.endPort}"

Expand Down Expand Up @@ -258,18 +261,23 @@ class Utils {
"${rule.direction} ${PropertyFormatter.format(rule.dstAddresses[0])} ports ${rule.dstPorts.joinToString(", "){PropertyFormatter.format(it)}}"
}

fun stringToRuleFromNetworkPolicy(ruleString: String, policy: NetworkPolicy): PolicyRuleType {
val index = ruleString.split(":")[0].toInt()
return policy.entries.policyRule[index]
}
fun stringToRuleFromNetworkPolicy(ruleString: String, policy: NetworkPolicy): PolicyRuleType =
policy.entries.policyRule[ruleString.toIndex()]

fun stringToRuleFromSecurityGroup(ruleString: String, group: SecurityGroup): PolicyRuleType {
val index = ruleString.split(":")[0].toInt()
return group.entries.policyRule[index]
}
fun stringToRuleFromSecurityGroup(ruleString: String, group: SecurityGroup): PolicyRuleType =
group.entries.policyRule[ruleString.toIndex()]

fun stringToIndex(ruleString: String): Int =
ruleString.toIndex()

fun ruleStringToIndex(ruleString: String): Int =
ruleString.split(":")[0].toInt()
fun firewallServiceToString(service: FirewallServiceType, index: Int) =
"$index: ${PropertyFormatter.format(service)}"

fun stringToFirewallService(serviceString: String, serviceGroup: ServiceGroup): FirewallServiceType =
serviceGroup.firewallServiceList.firewallService[serviceString.toIndex()]

fun parseFirewallServicePorts(ports: String): PortType =
parsePortRange(ports, anyAsFullRange = true)

fun routeToString(route: RouteType, index: Int): String {
return "$index: prefix ${route.prefix} next-hop-type ${route.nextHopType} next-hop ${route.nextHop} " +
Expand Down Expand Up @@ -322,5 +330,8 @@ class Utils {
}
}

fun String.toIndex() =
split(":")[0].toInt()

// Utils is not an object due to model-driven archetype constraints
val utils = Utils()
5 changes: 5 additions & 0 deletions o11nplugin-contrail-format/pom.xml
Expand Up @@ -30,6 +30,11 @@
<groupId>com.vmware.o11n</groupId>
<artifactId>o11n-plugin-modeldriven-runtime</artifactId>
</dependency>
<dependency>
<groupId>net.juniper.contrail.vro</groupId>
<artifactId>o11nplugin-contrail-config</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.juniper.contrail</groupId>
<artifactId>juniper-contrail-api</artifactId>
Expand Down
Expand Up @@ -6,6 +6,9 @@ package net.juniper.contrail.vro.format

import net.juniper.contrail.api.ApiPropertyBase
import net.juniper.contrail.api.types.* // ktlint-disable no-wildcard-imports
import net.juniper.contrail.vro.config.constants.any
import net.juniper.contrail.vro.config.constants.maxPort
import net.juniper.contrail.vro.config.constants.minPort
import java.lang.reflect.Field
import java.lang.reflect.Method
import java.lang.reflect.ParameterizedType
Expand All @@ -29,7 +32,9 @@ object PropertyFormatter {

fun format(prop: PortType) =
if (prop.startPort == prop.endPort)
if (prop.startPort == -1) "any" else "${prop.startPort}"
if (prop.startPort == -1) any else "${prop.startPort}"
else if (prop.startPort == minPort && prop.endPort == maxPort)
any
else
"${prop.startPort}-${prop.endPort}"

Expand Down Expand Up @@ -70,6 +75,10 @@ object PropertyFormatter {
"${actionList.safeSimpleAction}$protocol ${srcAddresses.inline} ${srcPorts.inline} $direction ${dstAddresses.inline} ${dstPorts.inline}"
}

fun format(prop: FirewallServiceType) = prop.run {
"$protocol:${format(srcPorts)}:${format(dstPorts)}"
}

private val ActionListType?.safeSimpleAction get() =
if (this == null) "" else "$simpleAction "

Expand Down
@@ -1,3 +1,7 @@
/*
* Copyright (c) 2018 Juniper Networks, Inc. All rights reserved.
*/

package net.juniper.contrail.vro.tests.actions

import net.juniper.contrail.api.types.IpamSubnetType
Expand All @@ -12,7 +16,7 @@ class NetworkIpamSubnetsSpec extends ActionSpec {
def action = actionFromScript(networkIpamSubnets)

def "null network IPAM results in null" () {
given: "null address group"
given: "null IPAM"
def ipam = null

when: "retrieved subnet list"
Expand Down
@@ -0,0 +1,75 @@
/*
* Copyright (c) 2018 Juniper Networks, Inc. All rights reserved.
*/

package net.juniper.contrail.vro.tests.actions

import net.juniper.contrail.api.types.ActionListType
import net.juniper.contrail.api.types.AddressType
import net.juniper.contrail.api.types.NetworkPolicy
import net.juniper.contrail.api.types.PolicyEntriesType
import net.juniper.contrail.api.types.PolicyRuleType
import net.juniper.contrail.api.types.PortType

import static net.juniper.contrail.vro.config.Actions.networkPolicyRules
import static net.juniper.contrail.vro.model.UtilsKt.utils

class NetworkPolicyRulesSpec extends ActionSpec {
def action = actionFromScript(networkPolicyRules)

def "null network policy results in empty list" () {
given: "null network policy"
def policy = null

when: "retrieved list of rules"
def result = invokeAction(action, policy) as List<String>

then:
result.isEmpty()
}

def "empty network policy results in empty list" () {
given: "empty policy"
def policy = new NetworkPolicy()

when: "retrieved list of rules"
def result = invokeAction(action, policy) as List<String>

then:
result.isEmpty()
}

def "network policy with empty rule list list results in empty list" () {
given: "network policy with empty list of rules"
def policy = new NetworkPolicy()
def rules = new PolicyEntriesType()
policy.entries = rules

when: "retrieved list of rules"
def result = invokeAction(action, policy) as List<String>

then:
result.isEmpty()
}

def "network policy with single rule results in list with single formatted rule" () {
given: "network policy with single rule"
def policy = new NetworkPolicy()
def rules = new PolicyEntriesType()
policy.entries = rules
def rule = new PolicyRuleType()
rules.addPolicyRule(rule)
rule.actionList = new ActionListType("deny")
rule.addSrcAddresses(new AddressType())
rule.addDstAddresses(new AddressType())
rule.addSrcPorts(new PortType())
rule.addDstPorts(new PortType())

when: "retrieved list of rules"
def result = invokeAction(action, policy) as List<String>

then: "resulting list has one formatted element"
result.size() == 1
result[0] == utils.ruleToString(rule, 0)
}
}
@@ -0,0 +1,82 @@
/*
* Copyright (c) 2018 Juniper Networks, Inc. All rights reserved.
*/

package net.juniper.contrail.vro.tests.actions

import net.juniper.contrail.api.types.FirewallServiceGroupType
import net.juniper.contrail.api.types.FirewallServiceType
import net.juniper.contrail.api.types.PortType
import net.juniper.contrail.api.types.ServiceGroup

import static net.juniper.contrail.vro.config.Actions.serviceGroupServices
import static net.juniper.contrail.vro.model.UtilsKt.utils

class ServiceGroupServicesSpec extends ActionSpec implements ValidationAsserts {
def actionScript = actionFromScript(serviceGroupServices)

def "null service group results in empty list" () {
given:
def item = null

when:
def result = invokeAction(actionScript, item) as List<String>

then:
result.isEmpty()
}

def "null FirewallServiceGroupType object results in empty list" () {
given:
def item = new ServiceGroup()
item.setFirewallServiceList(null)

when:
def result = invokeAction(actionScript, item) as List<String>

then:
result.isEmpty()
}

def "null firewall service list results in empty list" () {
given:
def item = new ServiceGroup()
def listType = new FirewallServiceGroupType(null)
item.setFirewallServiceList(listType)

when:
def result = invokeAction(actionScript, item) as List<String>

then:
result.isEmpty()
}

def "empty firewall service list results in empty list" () {
given:
def item = new ServiceGroup()
def listType = new FirewallServiceGroupType(new ArrayList<FirewallServiceType>())
item.setFirewallServiceList(listType)

when:
def result = invokeAction(actionScript, item) as List<String>

then:
result.isEmpty()
}

def "single service in the list results in list with single element formatted using Utils" () {
given:
def item = new ServiceGroup()
def listType = new FirewallServiceGroupType()
item.setFirewallServiceList(listType)
def service = new FirewallServiceType("tcp", null, new PortType(0, 65535), new PortType(7, 131))
listType.addFirewallService(service)

when:
def result = invokeAction(actionScript, item) as List<String>

then:
result.size() == 1
result[0] == utils.firewallServiceToString(service, 0)
}
}

0 comments on commit 020779b

Please sign in to comment.