diff --git a/o11nplugin-contrail-config/src/main/kotlin/net/juniper/contrail/vro/config/Actions.kt b/o11nplugin-contrail-config/src/main/kotlin/net/juniper/contrail/vro/config/Actions.kt index a27926b3..3c139a7d 100644 --- a/o11nplugin-contrail-config/src/main/kotlin/net/juniper/contrail/vro/config/Actions.kt +++ b/o11nplugin-contrail-config/src/main/kotlin/net/juniper/contrail/vro/config/Actions.kt @@ -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" @@ -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" diff --git a/o11nplugin-contrail-config/src/main/kotlin/net/juniper/contrail/vro/config/constants/Constants.kt b/o11nplugin-contrail-config/src/main/kotlin/net/juniper/contrail/vro/config/constants/Constants.kt index ab257a4b..949f9b02 100644 --- a/o11nplugin-contrail-config/src/main/kotlin/net/juniper/contrail/vro/config/constants/Constants.kt +++ b/o11nplugin-contrail-config/src/main/kotlin/net/juniper/contrail/vro/config/constants/Constants.kt @@ -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" } @@ -34,4 +41,6 @@ val supportedInterfaceNames = listOf( ) + supportedOtherInterfaces val maxInterfacesSupported = supportedInterfaceNames.size -val VxLANMaxID = 16777215 \ No newline at end of file +val VxLANMaxID = 16777215 +val minPort = 0 +val maxPort = 65535 \ No newline at end of file diff --git a/o11nplugin-contrail-core/src/main/kotlin/net/juniper/contrail/vro/model/Executor.kt b/o11nplugin-contrail-core/src/main/kotlin/net/juniper/contrail/vro/model/Executor.kt index 7182ba85..953f685d 100644 --- a/o11nplugin-contrail-core/src/main/kotlin/net/juniper/contrail/vro/model/Executor.kt +++ b/o11nplugin-contrail-core/src/main/kotlin/net/juniper/contrail/vro/model/Executor.kt @@ -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 @@ -48,4 +49,13 @@ NetworkPolicyRuleProperties by NetworkPolicyRulePropertyExecutor(connection) { fun Connection.listTagTypes(): List = list()?.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()) } \ No newline at end of file diff --git a/o11nplugin-contrail-core/src/main/kotlin/net/juniper/contrail/vro/model/NetworkPolicyRulePropertyExecutor.kt b/o11nplugin-contrail-core/src/main/kotlin/net/juniper/contrail/vro/model/NetworkPolicyRulePropertyExecutor.kt index d7d41cad..d6aa5954 100644 --- a/o11nplugin-contrail-core/src/main/kotlin/net/juniper/contrail/vro/model/NetworkPolicyRulePropertyExecutor.kt +++ b/o11nplugin-contrail-core/src/main/kotlin/net/juniper/contrail/vro/model/NetworkPolicyRulePropertyExecutor.kt @@ -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] } diff --git a/o11nplugin-contrail-core/src/main/kotlin/net/juniper/contrail/vro/model/SecurityGroupRulePropertyExecutor.kt b/o11nplugin-contrail-core/src/main/kotlin/net/juniper/contrail/vro/model/SecurityGroupRulePropertyExecutor.kt index 3fdd923c..f0026654 100644 --- a/o11nplugin-contrail-core/src/main/kotlin/net/juniper/contrail/vro/model/SecurityGroupRulePropertyExecutor.kt +++ b/o11nplugin-contrail-core/src/main/kotlin/net/juniper/contrail/vro/model/SecurityGroupRulePropertyExecutor.kt @@ -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] } } \ No newline at end of file diff --git a/o11nplugin-contrail-core/src/main/kotlin/net/juniper/contrail/vro/model/Utils.kt b/o11nplugin-contrail-core/src/main/kotlin/net/juniper/contrail/vro/model/Utils.kt index 8c55aa00..78310fad 100644 --- a/o11nplugin-contrail-core/src/main/kotlin/net/juniper/contrail/vro/model/Utils.kt +++ b/o11nplugin-contrail-core/src/main/kotlin/net/juniper/contrail/vro/model/Utils.kt @@ -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() @@ -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}" @@ -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} " + @@ -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() \ No newline at end of file diff --git a/o11nplugin-contrail-format/pom.xml b/o11nplugin-contrail-format/pom.xml index 1ad2e3ec..f7cd1941 100644 --- a/o11nplugin-contrail-format/pom.xml +++ b/o11nplugin-contrail-format/pom.xml @@ -30,6 +30,11 @@ com.vmware.o11n o11n-plugin-modeldriven-runtime + + net.juniper.contrail.vro + o11nplugin-contrail-config + compile + net.juniper.contrail juniper-contrail-api diff --git a/o11nplugin-contrail-format/src/main/kotlin/net/juniper/contrail/vro/format/PropertyFormatter.kt b/o11nplugin-contrail-format/src/main/kotlin/net/juniper/contrail/vro/format/PropertyFormatter.kt index 410f3eef..091cf0cc 100644 --- a/o11nplugin-contrail-format/src/main/kotlin/net/juniper/contrail/vro/format/PropertyFormatter.kt +++ b/o11nplugin-contrail-format/src/main/kotlin/net/juniper/contrail/vro/format/PropertyFormatter.kt @@ -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 @@ -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}" @@ -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 " diff --git a/o11nplugin-contrail-tests/src/test/groovy/net/juniper/contrail/vro/tests/actions/NetworkIpamSubnetsSpec.groovy b/o11nplugin-contrail-tests/src/test/groovy/net/juniper/contrail/vro/tests/actions/NetworkIpamSubnetsSpec.groovy index 0845659f..164420df 100644 --- a/o11nplugin-contrail-tests/src/test/groovy/net/juniper/contrail/vro/tests/actions/NetworkIpamSubnetsSpec.groovy +++ b/o11nplugin-contrail-tests/src/test/groovy/net/juniper/contrail/vro/tests/actions/NetworkIpamSubnetsSpec.groovy @@ -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 @@ -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" diff --git a/o11nplugin-contrail-tests/src/test/groovy/net/juniper/contrail/vro/tests/actions/NetworkPolicyRulesSpec.groovy b/o11nplugin-contrail-tests/src/test/groovy/net/juniper/contrail/vro/tests/actions/NetworkPolicyRulesSpec.groovy new file mode 100644 index 00000000..153a8bf8 --- /dev/null +++ b/o11nplugin-contrail-tests/src/test/groovy/net/juniper/contrail/vro/tests/actions/NetworkPolicyRulesSpec.groovy @@ -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 + + 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 + + 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 + + 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 + + then: "resulting list has one formatted element" + result.size() == 1 + result[0] == utils.ruleToString(rule, 0) + } +} diff --git a/o11nplugin-contrail-tests/src/test/groovy/net/juniper/contrail/vro/tests/actions/ServiceGroupServicesSpec.groovy b/o11nplugin-contrail-tests/src/test/groovy/net/juniper/contrail/vro/tests/actions/ServiceGroupServicesSpec.groovy new file mode 100644 index 00000000..0fcd6c3a --- /dev/null +++ b/o11nplugin-contrail-tests/src/test/groovy/net/juniper/contrail/vro/tests/actions/ServiceGroupServicesSpec.groovy @@ -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 + + 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 + + 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 + + then: + result.isEmpty() + } + + def "empty firewall service list results in empty list" () { + given: + def item = new ServiceGroup() + def listType = new FirewallServiceGroupType(new ArrayList()) + item.setFirewallServiceList(listType) + + when: + def result = invokeAction(actionScript, item) as List + + 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 + + then: + result.size() == 1 + result[0] == utils.firewallServiceToString(service, 0) + } +} diff --git a/o11nplugin-contrail-tests/src/test/groovy/net/juniper/contrail/vro/tests/workflows/AddServiceToServiceGroupSpec.groovy b/o11nplugin-contrail-tests/src/test/groovy/net/juniper/contrail/vro/tests/workflows/AddServiceToServiceGroupSpec.groovy new file mode 100644 index 00000000..bf5c694d --- /dev/null +++ b/o11nplugin-contrail-tests/src/test/groovy/net/juniper/contrail/vro/tests/workflows/AddServiceToServiceGroupSpec.groovy @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2018 Juniper Networks, Inc. All rights reserved. + */ + +package net.juniper.contrail.vro.tests.workflows + +import net.juniper.contrail.api.Status +import net.juniper.contrail.api.types.NetworkPolicy +import net.juniper.contrail.api.types.ServiceGroup + +class AddServiceToServiceGroupSpec extends WorkflowSpec { + + def workflowScript = workflowFromScript("Add service to service group") + + def someProtocol = "tcp" + def startPort = 157 + def endPort = 2391 + def somePorts = "$startPort-$endPort".toString() + + def "Adding service to a service group"() { + given: + def serviceGroup = dependencies.someServiceGroup() + + def initialSize = serviceGroup.getFirewallServiceList()?.getFirewallService()?.size() ?: 0 + connectorMock.read(_) >> Status.success() + + when: "workflow is executed" + invokeFunction( + workflowScript, + serviceGroup, + someProtocol, + somePorts + ) + + then: "the parent service group should be updated." + 1 * connectorMock.update({ + def _it = it as ServiceGroup + _it.uuid == serviceGroup.uuid && + _it.firewallServiceList.firewallService.size() == initialSize + 1 && + _it.firewallServiceList.firewallService.any{ + it.protocol == someProtocol && + it.dstPorts.startPort == startPort && + it.dstPorts.endPort == endPort + }}) >> Status.success() + } +} diff --git a/o11nplugin-contrail-tests/src/test/groovy/net/juniper/contrail/vro/tests/workflows/EditServiceOfServiceGroupSpec.groovy b/o11nplugin-contrail-tests/src/test/groovy/net/juniper/contrail/vro/tests/workflows/EditServiceOfServiceGroupSpec.groovy new file mode 100644 index 00000000..841feea3 --- /dev/null +++ b/o11nplugin-contrail-tests/src/test/groovy/net/juniper/contrail/vro/tests/workflows/EditServiceOfServiceGroupSpec.groovy @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018 Juniper Networks, Inc. All rights reserved. + */ + +package net.juniper.contrail.vro.tests.workflows + +import net.juniper.contrail.api.Status +import net.juniper.contrail.api.types.ServiceGroup + +class EditServiceOfServiceGroupSpec extends WorkflowSpec { + + def workflowScript = workflowFromScript("Edit service of service group") + def addServiceScript = workflowFromScript("Add service to service group") + + def someProtocol = "tcp" + def startPort = 157 + def endPort = 2391 + def somePorts = "$startPort-$endPort".toString() + + def someOtherProtocol = "udp" + def someOtherStartPort = 73 + def someOtherEndPort = 372 + def someOtherPorts = "$someOtherStartPort-$someOtherEndPort".toString() + + def "Editing service of service group"() { + given: + def serviceGroup = dependencies.someServiceGroup() + + connectorMock.read(_) >> Status.success() + connectorMock.update(_) >> Status.success() + def initialSize = serviceGroup.getFirewallServiceList()?.getFirewallService()?.size() ?: 0 + def serviceToEdit = "$initialSize: dummy representation" + //add service to service group + invokeFunction( + addServiceScript, + serviceGroup, + someProtocol, + somePorts + ) + def sizeBeforeEdit = serviceGroup.getFirewallServiceList().getFirewallService().size() + + when: "workflow is executed" + invokeFunction( + workflowScript, + serviceGroup, + serviceToEdit, + someOtherProtocol, + someOtherPorts + ) + + then: "the parent service group should be updated." + 1 * connectorMock.update({ + def _it = it as ServiceGroup + _it.uuid == serviceGroup.uuid && + _it.firewallServiceList.firewallService.size() == sizeBeforeEdit && + ! _it.firewallServiceList.firewallService.any{ + it.protocol == someProtocol && + it.dstPorts.startPort == startPort && + it.dstPorts.endPort == endPort + } && + _it.firewallServiceList.firewallService.any{ + it.protocol == someOtherProtocol && + it.dstPorts.startPort == someOtherStartPort && + it.dstPorts.endPort == someOtherEndPort + } + }) >> Status.success() + } +} diff --git a/o11nplugin-contrail-tests/src/test/groovy/net/juniper/contrail/vro/tests/workflows/RemoveServiceFromServiceGroupSpec.groovy b/o11nplugin-contrail-tests/src/test/groovy/net/juniper/contrail/vro/tests/workflows/RemoveServiceFromServiceGroupSpec.groovy new file mode 100644 index 00000000..e75b4c99 --- /dev/null +++ b/o11nplugin-contrail-tests/src/test/groovy/net/juniper/contrail/vro/tests/workflows/RemoveServiceFromServiceGroupSpec.groovy @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018 Juniper Networks, Inc. All rights reserved. + */ + +package net.juniper.contrail.vro.tests.workflows + +import net.juniper.contrail.api.Status +import net.juniper.contrail.api.types.ServiceGroup + +class RemoveServiceFromServiceGroupSpec extends WorkflowSpec { + + def workflowScript = workflowFromScript("Remove service from service group") + def addServiceScript = workflowFromScript("Add service to service group") + + def someProtocol = "tcp" + def startPort = 157 + def endPort = 2391 + def somePorts = "$startPort-$endPort".toString() + + def "Removing service from service group"() { + given: + def serviceGroup = dependencies.someServiceGroup() + + def initialSize = serviceGroup.getFirewallServiceList()?.getFirewallService()?.size() ?: 0 + connectorMock.read(_) >> Status.success() + connectorMock.update(_) >> Status.success() + //add service to service group + invokeFunction( + addServiceScript, + serviceGroup, + someProtocol, + somePorts + ) + def lastService = "$initialSize: dummy representation" + + when: "workflow is executed" + invokeFunction( + workflowScript, + serviceGroup, + lastService + ) + + then: "the parent service group should be updated." + 1 * connectorMock.update({ + def _it = it as ServiceGroup + _it.uuid == serviceGroup.uuid && + _it.firewallServiceList.firewallService.size() == initialSize && + ! _it.firewallServiceList.firewallService.any{ + it.protocol == someProtocol && + it.dstPorts.startPort == startPort && + it.dstPorts.endPort == endPort + }}) >> Status.success() + } +} diff --git a/o11nplugin-contrail-tests/src/test/groovy/net/juniper/contrail/vro/tests/workflows/WorkflowSpec.groovy b/o11nplugin-contrail-tests/src/test/groovy/net/juniper/contrail/vro/tests/workflows/WorkflowSpec.groovy index 65575f36..4c13065f 100644 --- a/o11nplugin-contrail-tests/src/test/groovy/net/juniper/contrail/vro/tests/workflows/WorkflowSpec.groovy +++ b/o11nplugin-contrail-tests/src/test/groovy/net/juniper/contrail/vro/tests/workflows/WorkflowSpec.groovy @@ -38,7 +38,7 @@ abstract class WorkflowSpec extends ScriptSpec { def setupSpec() { createContext() - loadWrapperTypes() + engine.engine.eval(setupScript) def ctx = AnonymousPluginContext.get() def utils = createUtils(ctx) def constants = createConstants(ctx) @@ -51,31 +51,6 @@ abstract class WorkflowSpec extends ScriptSpec { mockUtil.attachMock(connectorMock, this) } - private def loadWrapperTypes() { - loadWrapperType("ActionListType") - loadWrapperType("AllocationPoolType") - loadWrapperType("FloatingIp") - loadWrapperType("IpamSubnets") - loadWrapperType("IpamSubnetType") - loadWrapperType("PolicyEntriesType") - loadWrapperType("PolicyRuleType") - loadWrapperType("PortTuple") - loadWrapperType("SecurityGroup") - loadWrapperType("SequenceType") - loadWrapperType("ServiceInstance") - loadWrapperType("ServiceInstanceType") - loadWrapperType("ServiceInstanceInterfaceType") - loadWrapperType("ServiceInterfaceTag") - loadWrapperType("ServiceTemplate") - loadWrapperType("ServiceTemplateType") - loadWrapperType("ServiceTemplateInterfaceType") - loadWrapperType("SubnetType") - loadWrapperType("VirtualMachineInterfacePropertiesType") - loadWrapperType("VirtualNetworkPolicyType") - loadWrapperType("VnSubnetsType") - loadWrapperType("SubnetListType") - } - // We need the Spring Context to automatically load the converters for model- and plugin-objects private static def createContext() { def baseContext = new AnnotationConfigApplicationContext(WorkflowTestConfig.class) @@ -122,7 +97,39 @@ abstract class WorkflowSpec extends ScriptSpec { return new Dependencies(conn_wrap, utils) } - private def loadWrapperType(typeName) { - engine.engine.eval("var Contrail$typeName = Java.type('net.juniper.contrail.vro.gen.${typeName}_Wrapper');") + private final static String setupScript = buildWrapperDefinition( + "ActionListType", + "AllocationPoolType", + "FloatingIp", + "IpamSubnets", + "IpamSubnetType", + "PolicyEntriesType", + "PolicyRuleType", + "PortTuple", + "SecurityGroup", + "SequenceType", + "ServiceInstance", + "ServiceInstanceType", + "ServiceInstanceInterfaceType", + "ServiceInterfaceTag", + "ServiceTemplate", + "ServiceTemplateType", + "ServiceTemplateInterfaceType", + "SubnetType", + "VirtualMachineInterfacePropertiesType", + "VirtualNetworkPolicyType", + "VnSubnetsType", + "SubnetListType", + "FirewallServiceGroupType", + "FirewallServiceType" + ) + + private static String buildWrapperDefinition(String... types) { + return types.collect { toWrapperDefinitionScript(it) }.join("\n") } + + private static String toWrapperDefinitionScript(String type) { + return "var Contrail$type = Java.type('net.juniper.contrail.vro.gen.${type}_Wrapper');" + } + } diff --git a/o11nplugin-contrail-tests/src/test/kotlin/net/juniper/contrail/vro/tests/workflows/Dependencies.kt b/o11nplugin-contrail-tests/src/test/kotlin/net/juniper/contrail/vro/tests/workflows/Dependencies.kt index 4e446abd..681009d1 100644 --- a/o11nplugin-contrail-tests/src/test/kotlin/net/juniper/contrail/vro/tests/workflows/Dependencies.kt +++ b/o11nplugin-contrail-tests/src/test/kotlin/net/juniper/contrail/vro/tests/workflows/Dependencies.kt @@ -14,6 +14,7 @@ import net.juniper.contrail.vro.gen.NetworkPolicy_Wrapper import net.juniper.contrail.vro.gen.PortTuple_Wrapper import net.juniper.contrail.vro.gen.Project_Wrapper import net.juniper.contrail.vro.gen.SecurityGroup_Wrapper +import net.juniper.contrail.vro.gen.ServiceGroup_Wrapper import net.juniper.contrail.vro.gen.ServiceHealthCheck_Wrapper import net.juniper.contrail.vro.gen.ServiceInstance_Wrapper import net.juniper.contrail.vro.gen.ServiceTemplate_Wrapper @@ -116,6 +117,12 @@ class Dependencies(private val connection: Connection_Wrapper, private val utils setParentConnection(this@Dependencies.connection) } + fun someServiceGroup() = ServiceGroup_Wrapper().apply { + uuid = randomStringUuid() + name = "someServiceGroup$uuid" + setParentConnection(this@Dependencies.connection) + } + fun someIpamSubnetType() = IpamSubnetType_Wrapper() fun someSubnetType(ipPrefix: String = "1.2.3.4", ipPrefixLen: Int = 16) = SubnetType_Wrapper(ipPrefix, ipPrefixLen) diff --git a/o11nplugin-contrail-tests/src/test/kotlin/net/juniper/contrail/vro/tests/workflows/TestObjectFactory.kt b/o11nplugin-contrail-tests/src/test/kotlin/net/juniper/contrail/vro/tests/workflows/TestObjectFactory.kt new file mode 100644 index 00000000..f1108f27 --- /dev/null +++ b/o11nplugin-contrail-tests/src/test/kotlin/net/juniper/contrail/vro/tests/workflows/TestObjectFactory.kt @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018 Juniper Networks, Inc. All rights reserved. + */ + +package net.juniper.contrail.vro.tests.workflows + +import com.vmware.o11n.sdk.modeldriven.ObjectFactory +import com.vmware.o11n.sdk.modeldriven.PluginContext + +/** + * Class allows for customization of plugin objects created by default object factory. + */ +class TestObjectFactory(private val delegate: ObjectFactory) : ObjectFactory by delegate +{ + @Suppress("UNCHECKED_CAST") + override fun + createPluginObject(modelType: ModelType, ctx: PluginContext?, clazz: Class<*>?): PluginType? { + val result = delegate.createPluginObject(modelType, ctx, clazz) + return if (result is MutableList<*>) + ListAsArray(result as MutableList) as PluginType + else + result + } +} + +/** + * Class used to simulate JS Array inside test scripts. + */ +class ListAsArray(delegate: MutableList) : MutableList by delegate +{ + fun splice(index: Int, n: Int) { + repeat(n) { removeAt(index) } + } +} \ No newline at end of file diff --git a/o11nplugin-contrail-tests/src/test/kotlin/net/juniper/contrail/vro/tests/workflows/WorkflowTestConfig.kt b/o11nplugin-contrail-tests/src/test/kotlin/net/juniper/contrail/vro/tests/workflows/WorkflowTestConfig.kt index f60c2f7e..ce614462 100644 --- a/o11nplugin-contrail-tests/src/test/kotlin/net/juniper/contrail/vro/tests/workflows/WorkflowTestConfig.kt +++ b/o11nplugin-contrail-tests/src/test/kotlin/net/juniper/contrail/vro/tests/workflows/WorkflowTestConfig.kt @@ -5,9 +5,12 @@ package net.juniper.contrail.vro.tests.workflows import com.vmware.o11n.plugin.sdk.spring.platform.GlobalPluginNotificationHandler +import com.vmware.o11n.sdk.modeldriven.ObjectFactory +import com.vmware.o11n.sdk.modeldriven.impl.DefaultObjectFactory import net.juniper.contrail.vro.base.RepositoryInitializer import net.juniper.contrail.vro.model.Connection import net.juniper.contrail.vro.model.ConnectionInfo +import org.springframework.beans.factory.annotation.Autowired import org.springframework.context.annotation.Bean import org.springframework.context.annotation.ComponentScan import org.springframework.context.annotation.Configuration @@ -17,6 +20,13 @@ import org.springframework.context.annotation.Primary @ComponentScan("net.juniper.contrail.vro.base") class WorkflowTestConfig { + @Autowired lateinit var factoryDelegate: DefaultObjectFactory + + @Bean + @Primary + fun objectFactory() : ObjectFactory = + TestObjectFactory(factoryDelegate) + @Bean @Primary fun globalPluginNotificationHandler() : GlobalPluginNotificationHandler = diff --git a/o11nplugin-contrail-workflow-dsl/src/main/kotlin/net/juniper/contrail/vro/workflows/dsl/DataBinding.kt b/o11nplugin-contrail-workflow-dsl/src/main/kotlin/net/juniper/contrail/vro/workflows/dsl/DataBinding.kt index b71be6f1..70cb8e49 100644 --- a/o11nplugin-contrail-workflow-dsl/src/main/kotlin/net/juniper/contrail/vro/workflows/dsl/DataBinding.kt +++ b/o11nplugin-contrail-workflow-dsl/src/main/kotlin/net/juniper/contrail/vro/workflows/dsl/DataBinding.kt @@ -4,7 +4,7 @@ package net.juniper.contrail.vro.workflows.dsl -import net.juniper.contrail.vro.config.propertyOfObjectRule +import net.juniper.contrail.vro.config.listElementProperty import net.juniper.contrail.vro.workflows.model.ParameterQualifier import net.juniper.contrail.vro.workflows.model.ParameterType import net.juniper.contrail.vro.workflows.model.any @@ -54,13 +54,15 @@ class FromAction(val actionCall: ActionCall, val type: ParameterType fun fromAction(actionName: String, type: ParameterType, setup: ActionCallBuilder.() -> Unit): DataBinding = FromAction(actionCallTo(actionName).apply(setup).create(), type) -fun fromRuleProperty( +fun fromListElementProperty( parentItem: String, - ruleItem: String, - parameterName: String, + elementItem: String, + propertyPrefix: String, + propertyName: String, type: ParameterType -) = fromAction(propertyOfObjectRule, type) { - parameter(parentItem) - parameter(ruleItem) - string(parameterName) +) = fromAction(listElementProperty, type) { + parameter(parentItem) + parameter(elementItem) + string(propertyPrefix) + string(propertyName.capitalize()) } \ No newline at end of file diff --git a/o11nplugin-contrail-workflows/src/main/js/actions/isSingleAddressNetworkPolicyRule.js b/o11nplugin-contrail-workflows/src/main/js/actions/isSingleAddressNetworkPolicyRule.js index 93b3e946..17dba9a4 100644 --- a/o11nplugin-contrail-workflows/src/main/js/actions/isSingleAddressNetworkPolicyRule.js +++ b/o11nplugin-contrail-workflows/src/main/js/actions/isSingleAddressNetworkPolicyRule.js @@ -1,3 +1,4 @@ +if (!input) return null; var theRule = ContrailUtils.stringToRuleFromNetworkPolicy(input.trim(), networkPolicy); if (theRule.srcAddresses.length == 1 && theRule.dstAddresses.length == 1){ diff --git a/o11nplugin-contrail-workflows/src/main/js/actions/isSingleAddressSecurityGroupRule.js b/o11nplugin-contrail-workflows/src/main/js/actions/isSingleAddressSecurityGroupRule.js index 5fce2b2d..9316f7cb 100644 --- a/o11nplugin-contrail-workflows/src/main/js/actions/isSingleAddressSecurityGroupRule.js +++ b/o11nplugin-contrail-workflows/src/main/js/actions/isSingleAddressSecurityGroupRule.js @@ -1,3 +1,4 @@ +if (!input) return null; var theRule = ContrailUtils.stringToRuleFromSecurityGroup(input.trim(), securityGroup); if (theRule.srcAddresses.length == 1 && theRule.dstAddresses.length == 1){ diff --git a/o11nplugin-contrail-workflows/src/main/js/actions/listElementProperty.js b/o11nplugin-contrail-workflows/src/main/js/actions/listElementProperty.js new file mode 100644 index 00000000..522a7c90 --- /dev/null +++ b/o11nplugin-contrail-workflows/src/main/js/actions/listElementProperty.js @@ -0,0 +1,2 @@ +var methodName = propertyPrefix + propertyName; +return eval("item." + methodName + "(element)"); \ No newline at end of file diff --git a/o11nplugin-contrail-workflows/src/main/js/actions/networkPolicyRules.js b/o11nplugin-contrail-workflows/src/main/js/actions/networkPolicyRules.js index c08655a7..7be84a02 100644 --- a/o11nplugin-contrail-workflows/src/main/js/actions/networkPolicyRules.js +++ b/o11nplugin-contrail-workflows/src/main/js/actions/networkPolicyRules.js @@ -1,5 +1,12 @@ var actionResult = new Array(); -var rules = item.getEntries().getPolicyRule() + +if (!item) return actionResult; + +var entries = item.getEntries(); +if (!entries) return actionResult; + +var rules = entries.getPolicyRule(); +if (!rules) return actionResult; rules.forEach(function (value, index) { actionResult.push(ContrailUtils.ruleToString(value, index)); diff --git a/o11nplugin-contrail-workflows/src/main/js/actions/propertyOfObjectRule.js b/o11nplugin-contrail-workflows/src/main/js/actions/propertyOfObjectRule.js deleted file mode 100644 index 5b340660..00000000 --- a/o11nplugin-contrail-workflows/src/main/js/actions/propertyOfObjectRule.js +++ /dev/null @@ -1,2 +0,0 @@ -var methodName = "ruleProperty" + propertyName + "(rule)"; -return eval("parent." + methodName); \ No newline at end of file diff --git a/o11nplugin-contrail-workflows/src/main/js/actions/serviceGroupServices.js b/o11nplugin-contrail-workflows/src/main/js/actions/serviceGroupServices.js new file mode 100644 index 00000000..78d42cd3 --- /dev/null +++ b/o11nplugin-contrail-workflows/src/main/js/actions/serviceGroupServices.js @@ -0,0 +1,14 @@ +var actionResult = new Array(); + +if (!item) return actionResult; + +var serviceList = item.getFirewallServiceList(); +if (!serviceList) return actionResult; + +var services = serviceList.getFirewallService(); +if (! services) return actionResult; + +services.forEach(function (value, index) { + actionResult.push(ContrailUtils.firewallServiceToString(value, index)); +}); +return actionResult; \ No newline at end of file diff --git a/o11nplugin-contrail-workflows/src/main/js/workflows/addRuleToPolicy.js b/o11nplugin-contrail-workflows/src/main/js/workflows/addRuleToPolicy.js index f1a9ae42..72c701fd 100644 --- a/o11nplugin-contrail-workflows/src/main/js/workflows/addRuleToPolicy.js +++ b/o11nplugin-contrail-workflows/src/main/js/workflows/addRuleToPolicy.js @@ -48,11 +48,11 @@ if (services != null) { actions.setMirrorTo(mirrorAction); var rule = new ContrailPolicyRuleType(null, ruleUuid, direction, protocol, srcAddr, parsedSrcPorts, application, dstAddr, parsedDstPorts, actions); -var rules = parent.getEntries(); +var rules = item.getEntries(); if (!rules) { rules = new ContrailPolicyEntriesType(); - parent.setEntries(rules); + item.setEntries(rules); } rules.addPolicyRule(rule); -parent.update(); \ No newline at end of file +item.update(); \ No newline at end of file diff --git a/o11nplugin-contrail-workflows/src/main/js/workflows/addRuleToSecurityGroup.js b/o11nplugin-contrail-workflows/src/main/js/workflows/addRuleToSecurityGroup.js index 3a3dc883..6c077eb6 100644 --- a/o11nplugin-contrail-workflows/src/main/js/workflows/addRuleToSecurityGroup.js +++ b/o11nplugin-contrail-workflows/src/main/js/workflows/addRuleToSecurityGroup.js @@ -23,11 +23,11 @@ if (direction == "ingress") { } var rule = new ContrailPolicyRuleType(null, ruleUuid, trafficDirection, protocol, srcAddr, srcPorts, null, dstAddr, dstPorts, null, ethertype); -var rules = parent.getEntries(); +var rules = item.getEntries(); if (!rules) { rules = new ContrailPolicyEntriesType(); - parent.setEntries(rules); + item.setEntries(rules); } rules.addPolicyRule(rule); -parent.update(); \ No newline at end of file +item.update(); \ No newline at end of file diff --git a/o11nplugin-contrail-workflows/src/main/js/workflows/addServiceToServiceGroup.js b/o11nplugin-contrail-workflows/src/main/js/workflows/addServiceToServiceGroup.js new file mode 100644 index 00000000..705f4c54 --- /dev/null +++ b/o11nplugin-contrail-workflows/src/main/js/workflows/addServiceToServiceGroup.js @@ -0,0 +1,13 @@ +var service = new ContrailFirewallServiceType(); +service.protocol = protocol; +service.srcPorts = ContrailUtils.parseFirewallServicePorts("any"); +service.dstPorts = ContrailUtils.parseFirewallServicePorts(port); + +var services = item.getFirewallServiceList(); +if (!services) { + services = new ContrailFirewallServiceGroupType(); + item.setFirewallServiceList(services); +} +services.addFirewallService(service); + +item.update(); \ No newline at end of file diff --git a/o11nplugin-contrail-workflows/src/main/js/workflows/editPolicyRule.js b/o11nplugin-contrail-workflows/src/main/js/workflows/editPolicyRule.js index c4fdca63..6d8b0e22 100644 --- a/o11nplugin-contrail-workflows/src/main/js/workflows/editPolicyRule.js +++ b/o11nplugin-contrail-workflows/src/main/js/workflows/editPolicyRule.js @@ -1,5 +1,5 @@ -var index = ContrailUtils.ruleStringToIndex(rule); -var theRule = parent.entries.policyRule[index]; +var index = ContrailUtils.stringToIndex(rule); +var theRule = item.entries.policyRule[index]; theRule.protocol = protocol; theRule.direction = direction; @@ -61,4 +61,4 @@ actions.setMirrorTo(mirrorAction); theRule.setActionList(actions); -parent.update(); \ No newline at end of file +item.update(); \ No newline at end of file diff --git a/o11nplugin-contrail-workflows/src/main/js/workflows/editSecurityGroupRule.js b/o11nplugin-contrail-workflows/src/main/js/workflows/editSecurityGroupRule.js index fd9c84aa..e58acb59 100644 --- a/o11nplugin-contrail-workflows/src/main/js/workflows/editSecurityGroupRule.js +++ b/o11nplugin-contrail-workflows/src/main/js/workflows/editSecurityGroupRule.js @@ -1,5 +1,5 @@ -var index = ContrailUtils.ruleStringToIndex(rule); -var theRule = parent.entries.policyRule[index]; +var index = ContrailUtils.stringToIndex(rule); +var theRule = item.entries.policyRule[index]; var parsedPorts = ContrailUtils.parsePortsOfSecurityGroupRule(ports); var addr = ContrailUtils.createAddress(addressType, addressCidr, null, null, null, addressSecurityGroup); @@ -35,4 +35,4 @@ if (direction == "ingress") { theRule.protocol = protocol; theRule.ethertype = ethertype; -parent.update(); \ No newline at end of file +item.update(); \ No newline at end of file diff --git a/o11nplugin-contrail-workflows/src/main/js/workflows/editServiceOfServiceGroup.js b/o11nplugin-contrail-workflows/src/main/js/workflows/editServiceOfServiceGroup.js new file mode 100644 index 00000000..a2478b7a --- /dev/null +++ b/o11nplugin-contrail-workflows/src/main/js/workflows/editServiceOfServiceGroup.js @@ -0,0 +1,7 @@ +var index = ContrailUtils.stringToIndex(service); +var theService = item.firewallServiceList.firewallService[index]; + +theService.protocol = protocol; +theService.dstPorts = ContrailUtils.parseFirewallServicePorts(port); + +item.update(); \ No newline at end of file diff --git a/o11nplugin-contrail-workflows/src/main/js/workflows/removeRuleFromPolicy.js b/o11nplugin-contrail-workflows/src/main/js/workflows/removeRuleFromPolicy.js index d7ee2190..e0bc3982 100644 --- a/o11nplugin-contrail-workflows/src/main/js/workflows/removeRuleFromPolicy.js +++ b/o11nplugin-contrail-workflows/src/main/js/workflows/removeRuleFromPolicy.js @@ -1,7 +1,7 @@ -var index = ContrailUtils.ruleStringToIndex(rule); +var index = ContrailUtils.stringToIndex(rule); -var list = parent.getEntries().getPolicyRule(); -list.remove(list[index]); -parent.setEntries(new ContrailPolicyEntriesType(list)); +var list = item.getEntries().getPolicyRule(); +list.splice(index, 1); +item.setEntries(new ContrailPolicyEntriesType(list)); -parent.update(); \ No newline at end of file +item.update(); \ No newline at end of file diff --git a/o11nplugin-contrail-workflows/src/main/js/workflows/removeRuleFromSecurityGroup.js b/o11nplugin-contrail-workflows/src/main/js/workflows/removeRuleFromSecurityGroup.js index b1c03e60..e0bc3982 100644 --- a/o11nplugin-contrail-workflows/src/main/js/workflows/removeRuleFromSecurityGroup.js +++ b/o11nplugin-contrail-workflows/src/main/js/workflows/removeRuleFromSecurityGroup.js @@ -1,8 +1,7 @@ -var index = ContrailUtils.ruleStringToIndex(rule); +var index = ContrailUtils.stringToIndex(rule); -var list = parent.getEntries().getPolicyRule(); -list.remove(list[index]); +var list = item.getEntries().getPolicyRule(); +list.splice(index, 1); +item.setEntries(new ContrailPolicyEntriesType(list)); -parent.setEntries(new ContrailPolicyEntriesType(list)); - -parent.update(); \ No newline at end of file +item.update(); \ No newline at end of file diff --git a/o11nplugin-contrail-workflows/src/main/js/workflows/removeServiceFromServiceGroup.js b/o11nplugin-contrail-workflows/src/main/js/workflows/removeServiceFromServiceGroup.js new file mode 100644 index 00000000..61da6214 --- /dev/null +++ b/o11nplugin-contrail-workflows/src/main/js/workflows/removeServiceFromServiceGroup.js @@ -0,0 +1,7 @@ +var index = ContrailUtils.stringToIndex(service); + +var services = item.getFirewallServiceList().getFirewallService(); +services.splice(index, 1); +item.setFirewallServiceList(new ContrailFirewallServiceGroupType(services)); + +item.update(); \ No newline at end of file diff --git a/o11nplugin-contrail-workflows/src/main/kotlin/net/juniper/contrail/vro/workflows/custom/Binding.kt b/o11nplugin-contrail-workflows/src/main/kotlin/net/juniper/contrail/vro/workflows/custom/Binding.kt new file mode 100644 index 00000000..9b83f0ba --- /dev/null +++ b/o11nplugin-contrail-workflows/src/main/kotlin/net/juniper/contrail/vro/workflows/custom/Binding.kt @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2018 Juniper Networks, Inc. All rights reserved. + */ + +package net.juniper.contrail.vro.workflows.custom + +import net.juniper.contrail.vro.config.constants.item +import net.juniper.contrail.vro.workflows.dsl.BasicParameterBuilder +import net.juniper.contrail.vro.workflows.dsl.fromListElementProperty + +val rule = "rule" +val service = "service" + +fun BasicParameterBuilder.rulePropertyDataBinding() = + fromListElementProperty(item, rule, "ruleProperty", parameterName, type) + +fun BasicParameterBuilder.servicePropertyDataBinding() = + fromListElementProperty(item, service, "serviceProperty", parameterName, type) diff --git a/o11nplugin-contrail-workflows/src/main/kotlin/net/juniper/contrail/vro/workflows/custom/GeneralActions.kt b/o11nplugin-contrail-workflows/src/main/kotlin/net/juniper/contrail/vro/workflows/custom/GeneralActions.kt index 028b571b..5bef7b5b 100644 --- a/o11nplugin-contrail-workflows/src/main/kotlin/net/juniper/contrail/vro/workflows/custom/GeneralActions.kt +++ b/o11nplugin-contrail-workflows/src/main/kotlin/net/juniper/contrail/vro/workflows/custom/GeneralActions.kt @@ -4,10 +4,11 @@ package net.juniper.contrail.vro.workflows.custom +import net.juniper.contrail.vro.config.constants.element import net.juniper.contrail.vro.config.constants.item import net.juniper.contrail.vro.config.listTagTypes import net.juniper.contrail.vro.config.propertyNotNull -import net.juniper.contrail.vro.config.propertyOfObjectRule +import net.juniper.contrail.vro.config.listElementProperty import net.juniper.contrail.vro.config.propertyValue import net.juniper.contrail.vro.config.readSubnet import net.juniper.contrail.vro.workflows.dsl.ofType @@ -45,12 +46,13 @@ val readSubnetAction = ActionDefinition ( ) ) -val propertyOfObjectRule = ActionDefinition( - name = propertyOfObjectRule, +val listElementPropertyAction = ActionDefinition( + name = listElementProperty, resultType = any, parameters = listOf( - "parent" ofType any, - "rule" ofType string, + item ofType any, + element ofType string, + "propertyPrefix" ofType string, "propertyName" ofType string ) ) diff --git a/o11nplugin-contrail-workflows/src/main/kotlin/net/juniper/contrail/vro/workflows/custom/NetworkPolicyRules.kt b/o11nplugin-contrail-workflows/src/main/kotlin/net/juniper/contrail/vro/workflows/custom/NetworkPolicyRules.kt index 7d021588..36fa07f2 100644 --- a/o11nplugin-contrail-workflows/src/main/kotlin/net/juniper/contrail/vro/workflows/custom/NetworkPolicyRules.kt +++ b/o11nplugin-contrail-workflows/src/main/kotlin/net/juniper/contrail/vro/workflows/custom/NetworkPolicyRules.kt @@ -12,12 +12,11 @@ import net.juniper.contrail.api.types.Project import net.juniper.contrail.api.types.SecurityGroup import net.juniper.contrail.api.types.ServiceInstance import net.juniper.contrail.api.types.VirtualNetwork -import net.juniper.contrail.vro.config.constants.parent +import net.juniper.contrail.vro.config.constants.item import net.juniper.contrail.vro.config.networkPolicyRules import net.juniper.contrail.vro.schema.Schema import net.juniper.contrail.vro.schema.propertyDescription import net.juniper.contrail.vro.schema.simpleTypeConstraints -import net.juniper.contrail.vro.workflows.dsl.BasicParameterBuilder import net.juniper.contrail.vro.workflows.dsl.FromBooleanParameter import net.juniper.contrail.vro.workflows.dsl.FromStringParameter import net.juniper.contrail.vro.workflows.dsl.PresentationParametersBuilder @@ -25,7 +24,6 @@ import net.juniper.contrail.vro.workflows.dsl.WhenNonNull import net.juniper.contrail.vro.workflows.dsl.WorkflowDefinition import net.juniper.contrail.vro.workflows.dsl.actionCallTo import net.juniper.contrail.vro.workflows.dsl.and -import net.juniper.contrail.vro.workflows.dsl.fromRuleProperty import net.juniper.contrail.vro.workflows.dsl.or import net.juniper.contrail.vro.workflows.model.array import net.juniper.contrail.vro.workflows.model.boolean @@ -61,13 +59,13 @@ internal fun addRuleToPolicyWorkflow(schema: Schema): WorkflowDefinition { val workflowName = "Add rule to network policy" return customWorkflow(workflowName).withScriptFile("addRuleToPolicy") { - step("Parent policy") { - parameter(parent, reference()) { + step("Network Policy") { + parameter(item, reference()) { description = relationDescription(schema) mandatory = true } } - policyRuleParameters(schema, "parent", false) + policyRuleParameters(schema, item, false) } } @@ -75,43 +73,44 @@ internal fun editPolicyRuleWorkflow(schema: Schema): WorkflowDefinition { val workflowName = "Edit rule of network policy" return customWorkflow(workflowName).withScriptFile("editPolicyRule") { - step("Rule") { - parameter(parent, reference()) { + step("Network Policy Rule") { + parameter(item, reference()) { description = relationDescription(schema) mandatory = true } - parameter("rule", string) { - visibility = WhenNonNull(parent) + parameter(rule, string) { + visibility = WhenNonNull(item) description = "Rule to edit" - predefinedAnswersFrom = actionCallTo(networkPolicyRules).parameter(parent) - validWhen = isSingleAddressNetworkPolicyRuleOf(parent) + mandatory = true + predefinedAnswersFrom = actionCallTo(networkPolicyRules).parameter(item) + validWhen = isSingleAddressNetworkPolicyRuleOf(item) } } - policyRuleParameters(schema, "rule", true) + policyRuleParameters(schema, rule, true) } } private fun PresentationParametersBuilder.policyRuleParameters(schema: Schema, visibilityDependencyField: String, loadCurrentValues: Boolean) { - step("Basic attributes") { + step("Basic Properties") { visibility = WhenNonNull(visibilityDependencyField) parameter("simpleAction", string) { description = propertyDescription(schema) additionalQualifiers += schema.simpleTypeConstraints("simpleAction") - if (loadCurrentValues) dataBinding = networkPolicyRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } parameter("protocol", string) { description = propertyDescription(schema) mandatory = true defaultValue = defaultProtocol predefinedAnswers = allowedProtocols - if (loadCurrentValues) dataBinding = networkPolicyRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } parameter("direction", string) { // direction has no description in the schema description = "Direction" mandatory = true additionalQualifiers += schema.simpleTypeConstraints("direction") - if (loadCurrentValues) dataBinding = networkPolicyRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } } @@ -122,13 +121,13 @@ private fun PresentationParametersBuilder.policyRuleParameters(schema: Schema, v mandatory = true defaultValue = defaultAddressType predefinedAnswers = allowedAddressTypes - if (loadCurrentValues) dataBinding = networkPolicyRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } parameter("srcSubnet", string) { description = schema.propertyDescription("subnet") mandatory = true visibility = FromStringParameter(sourceAddressTypeParameterName, "CIDR") - if (loadCurrentValues) dataBinding = networkPolicyRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } parameter(sourceVirtualNetworkType, string) { description = "Type of source network address" @@ -136,44 +135,44 @@ private fun PresentationParametersBuilder.policyRuleParameters(schema: Schema, v visibility = FromStringParameter(sourceAddressTypeParameterName, "Network") defaultValue = defaultNetworkType predefinedAnswers = allowedNetworkTypes - if (loadCurrentValues) dataBinding = networkPolicyRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } parameter("srcVirtualNetwork", reference()) { description = schema.propertyDescription("virtual_network") mandatory = true visibility = FromStringParameter(sourceVirtualNetworkType, "reference") - if (loadCurrentValues) dataBinding = networkPolicyRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } parameter("srcNetworkPolicy", reference()) { description = schema.propertyDescription("network-policy") mandatory = true visibility = FromStringParameter(sourceAddressTypeParameterName, "Policy") - if (loadCurrentValues) dataBinding = networkPolicyRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } parameter("srcSecurityGroup", reference()) { description = schema.propertyDescription("security-group") mandatory = true visibility = FromStringParameter(sourceAddressTypeParameterName, "Security Group") - if (loadCurrentValues) dataBinding = networkPolicyRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } parameter("srcPorts", string) { description = propertyDescription(schema) mandatory = true defaultValue = defaultPort - if (loadCurrentValues) dataBinding = networkPolicyRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } parameter(destinationAddressTypeParameterName, string) { description = "Traffic Destination" mandatory = true defaultValue = defaultAddressType predefinedAnswers = allowedAddressTypes - if (loadCurrentValues) dataBinding = networkPolicyRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } parameter("dstSubnet", string) { description = schema.propertyDescription("subnet") mandatory = true visibility = FromStringParameter(destinationAddressTypeParameterName, "CIDR") - if (loadCurrentValues) dataBinding = networkPolicyRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } parameter(destinationVirtualNetworkType, string) { description = "Type of destination network address" @@ -181,31 +180,31 @@ private fun PresentationParametersBuilder.policyRuleParameters(schema: Schema, v visibility = FromStringParameter(destinationAddressTypeParameterName, "Network") defaultValue = defaultNetworkType predefinedAnswers = allowedNetworkTypes - if (loadCurrentValues) dataBinding = networkPolicyRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } parameter("dstVirtualNetwork", reference()) { description = schema.propertyDescription("virtual_network") mandatory = true visibility = FromStringParameter(destinationVirtualNetworkType, "reference") - if (loadCurrentValues) dataBinding = networkPolicyRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } parameter("dstNetworkPolicy", reference()) { description = schema.propertyDescription("network-policy") mandatory = true visibility = FromStringParameter(destinationAddressTypeParameterName, "Policy") - if (loadCurrentValues) dataBinding = networkPolicyRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } parameter("dstSecurityGroup", reference()) { description = schema.propertyDescription("security-group") mandatory = true visibility = FromStringParameter(destinationAddressTypeParameterName, "Security Group") - if (loadCurrentValues) dataBinding = networkPolicyRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } parameter("dstPorts", string) { description = propertyDescription(schema) mandatory = true defaultValue = defaultPort - if (loadCurrentValues) dataBinding = networkPolicyRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } } @@ -215,20 +214,20 @@ private fun PresentationParametersBuilder.policyRuleParameters(schema: Schema, v description = propertyDescription(schema) mandatory = true defaultValue = false - if (loadCurrentValues) dataBinding = networkPolicyRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } parameter(defineServicesParameterName, boolean) { description = "Services" mandatory = true defaultValue = false - if (loadCurrentValues) dataBinding = networkPolicyRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } parameter(defineMirrorParameterName, boolean) { description = "Mirror" mandatory = true defaultValue = false - if (loadCurrentValues) dataBinding = networkPolicyRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } } @@ -237,7 +236,7 @@ private fun PresentationParametersBuilder.policyRuleParameters(schema: Schema, v parameter("services", array(reference())) { description = "Service instances" mandatory = true - if (loadCurrentValues) dataBinding = networkPolicyRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } } @@ -255,19 +254,19 @@ private fun PresentationParametersBuilder.policyRuleParameters(schema: Schema, v mandatory = true defaultValue = defaultMirrorType predefinedAnswers = allowedMirrorTypes - if (loadCurrentValues) dataBinding = networkPolicyRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } parameter("mirrorAnalyzerInstance", reference()) { description = "Analyzer Instance" mandatory = true visibility = mirrorIsAnalyzerInstance - if (loadCurrentValues) dataBinding = networkPolicyRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } parameter("mirrorAnalyzerName", string) { description = "Analyzer Name" mandatory = true visibility = mirrorIsNicAssisted or mirrorIsAnalyzerIp - if (loadCurrentValues) dataBinding = networkPolicyRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } parameter("mirrorNicAssistedVlan", number) { description = "NIC Assisted VLAN" @@ -275,25 +274,25 @@ private fun PresentationParametersBuilder.policyRuleParameters(schema: Schema, v min = 1 max = 4094 visibility = mirrorIsNicAssisted - if (loadCurrentValues) dataBinding = networkPolicyRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } parameter("mirrorAnalyzerIP", string) { description = "Analyzer IP" mandatory = true visibility = mirrorIsAnalyzerIp - if (loadCurrentValues) dataBinding = networkPolicyRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } parameter("mirrorAnalyzerMac", string) { description = "Analyzer MAC" mandatory = true visibility = mirrorIsAnalyzerIp - if (loadCurrentValues) dataBinding = networkPolicyRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } parameter("mirrorUdpPort", number) { description = "UDP Port" mandatory = true visibility = mirrorIsAnalyzerIp - if (loadCurrentValues) dataBinding = networkPolicyRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } parameter("mirrorJuniperHeader", string) { description = "Juniper Header" @@ -301,13 +300,13 @@ private fun PresentationParametersBuilder.policyRuleParameters(schema: Schema, v defaultValue = defaultJuniperHeaderOption predefinedAnswers = allowedJuniperHeaderOptions visibility = mirrorIsAnalyzerIp - if (loadCurrentValues) dataBinding = networkPolicyRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } parameter("mirrorRoutingInstance", reference()) { description = "Routing Instance" mandatory = true visibility = mirrorIsAnalyzerIp and juniperHeaderIsDisabled - if (loadCurrentValues) dataBinding = networkPolicyRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } parameter("mirrorNexthopMode", string) { description = "Nexthop Mode" @@ -315,25 +314,25 @@ private fun PresentationParametersBuilder.policyRuleParameters(schema: Schema, v defaultValue = defaultNexthopMode predefinedAnswers = allowedNexthopModes visibility = mirrorIsAnalyzerIp - if (loadCurrentValues) dataBinding = networkPolicyRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } parameter("mirrorVtepDestIp", string) { description = "VTEP Dest IP" mandatory = true visibility = mirrorIsAnalyzerIp and nextHopModeIsStatic - if (loadCurrentValues) dataBinding = networkPolicyRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } parameter("mirrorVtepDestMac", string) { description = "VTEP Dest MAC" mandatory = true visibility = mirrorIsAnalyzerIp and nextHopModeIsStatic - if (loadCurrentValues) dataBinding = networkPolicyRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } parameter("mirrorVni", number) { description = "VxLAN ID" mandatory = true visibility = mirrorIsAnalyzerIp and nextHopModeIsStatic - if (loadCurrentValues) dataBinding = networkPolicyRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } } } @@ -342,20 +341,15 @@ internal fun removePolicyRuleWorkflow(schema: Schema): WorkflowDefinition { val workflowName = "Remove rule from network policy" return customWorkflow(workflowName).withScriptFile("removeRuleFromPolicy") { - parameter(parent, reference()) { + parameter(item, reference()) { description = relationDescription(schema) mandatory = true } - parameter("rule", string) { - visibility = WhenNonNull(parent) + parameter(rule, string) { + visibility = WhenNonNull(item) description = "Rule to remove" mandatory = true - predefinedAnswersFrom = actionCallTo(networkPolicyRules).parameter(parent) + predefinedAnswersFrom = actionCallTo(networkPolicyRules).parameter(item) } } -} - -// default is capitalized to fit the camelCase function name -// e.g. srcPorts -> rulePropertySrcPorts -private fun BasicParameterBuilder.networkPolicyRulePropertyDataBinding() = - fromRuleProperty(parent, "rule", parameterName.capitalize(), type) \ No newline at end of file +} \ No newline at end of file diff --git a/o11nplugin-contrail-workflows/src/main/kotlin/net/juniper/contrail/vro/workflows/custom/RelationActions.kt b/o11nplugin-contrail-workflows/src/main/kotlin/net/juniper/contrail/vro/workflows/custom/RelationActions.kt index 56f2643f..380caa76 100644 --- a/o11nplugin-contrail-workflows/src/main/kotlin/net/juniper/contrail/vro/workflows/custom/RelationActions.kt +++ b/o11nplugin-contrail-workflows/src/main/kotlin/net/juniper/contrail/vro/workflows/custom/RelationActions.kt @@ -6,6 +6,7 @@ package net.juniper.contrail.vro.workflows.custom import net.juniper.contrail.api.types.AddressGroup import net.juniper.contrail.api.types.NetworkIpam +import net.juniper.contrail.api.types.ServiceGroup import net.juniper.contrail.api.types.ServiceInstance import net.juniper.contrail.api.types.VirtualMachineInterface import net.juniper.contrail.api.types.VirtualNetwork @@ -18,6 +19,7 @@ import net.juniper.contrail.vro.config.virtualNetworkSubnets import net.juniper.contrail.vro.config.routeTableRoutes import net.juniper.contrail.vro.config.portsForServiceInterface import net.juniper.contrail.vro.config.networkIpamSubnets +import net.juniper.contrail.vro.config.serviceGroupServices import net.juniper.contrail.vro.workflows.dsl.ofType import net.juniper.contrail.vro.workflows.model.any import net.juniper.contrail.vro.workflows.model.array @@ -48,6 +50,12 @@ val addressGroupSubnetsAction = ActionDefinition( parameters = listOf(item ofType reference()) ) +val serviceGroupServicesAction = ActionDefinition( + name = serviceGroupServices, + resultType = array(string), + parameters = listOf(item ofType reference()) +) + val routeTableRoutesAction = ActionDefinition( name = routeTableRoutes, resultType = array(string), diff --git a/o11nplugin-contrail-workflows/src/main/kotlin/net/juniper/contrail/vro/workflows/custom/SecurityGroupRules.kt b/o11nplugin-contrail-workflows/src/main/kotlin/net/juniper/contrail/vro/workflows/custom/SecurityGroupRules.kt index c39b50af..4ef6b387 100644 --- a/o11nplugin-contrail-workflows/src/main/kotlin/net/juniper/contrail/vro/workflows/custom/SecurityGroupRules.kt +++ b/o11nplugin-contrail-workflows/src/main/kotlin/net/juniper/contrail/vro/workflows/custom/SecurityGroupRules.kt @@ -10,18 +10,16 @@ import net.juniper.contrail.api.types.Project import net.juniper.contrail.api.types.SecurityGroup import net.juniper.contrail.vro.config.constants.egress import net.juniper.contrail.vro.config.constants.ingress -import net.juniper.contrail.vro.config.constants.parent +import net.juniper.contrail.vro.config.constants.item import net.juniper.contrail.vro.config.networkPolicyRules import net.juniper.contrail.vro.schema.Schema import net.juniper.contrail.vro.schema.propertyDescription import net.juniper.contrail.vro.schema.simpleTypeConstraints -import net.juniper.contrail.vro.workflows.dsl.BasicParameterBuilder import net.juniper.contrail.vro.workflows.dsl.FromStringParameter import net.juniper.contrail.vro.workflows.dsl.PresentationParametersBuilder import net.juniper.contrail.vro.workflows.dsl.WhenNonNull import net.juniper.contrail.vro.workflows.dsl.WorkflowDefinition import net.juniper.contrail.vro.workflows.dsl.actionCallTo -import net.juniper.contrail.vro.workflows.dsl.fromRuleProperty import net.juniper.contrail.vro.workflows.model.reference import net.juniper.contrail.vro.workflows.model.string import net.juniper.contrail.vro.workflows.util.propertyDescription @@ -41,13 +39,13 @@ internal fun addRuleToSecurityGroupWorkflow(schema: Schema): WorkflowDefinition val workflowName = "Add rule to security group" return customWorkflow(workflowName).withScriptFile("addRuleToSecurityGroup") { - step("Parent security group") { - parameter(parent, reference()) { + step("Security Group") { + parameter(item, reference()) { description = relationDescription(schema) mandatory = true } } - securityGroupRuleParameters(schema, parent, false) + securityGroupRuleParameters(schema, item, false) } } @@ -55,24 +53,25 @@ internal fun editSecurityGroupRuleWorkflow(schema: Schema): WorkflowDefinition { val workflowName = "Edit rule of security group" return customWorkflow(workflowName).withScriptFile("editSecurityGroupRule") { - step("Rule") { - parameter(parent, reference()) { + step("Security Group Rule") { + parameter(item, reference()) { description = relationDescription(schema) mandatory = true } - parameter("rule", string) { - visibility = WhenNonNull(parent) + parameter(rule, string) { + visibility = WhenNonNull(item) description = "Rule to edit" - predefinedAnswersFrom = actionCallTo(networkPolicyRules).parameter(parent) - validWhen = isSingleAddressSecurityGroupRuleOf(parent) + mandatory = true + predefinedAnswersFrom = actionCallTo(networkPolicyRules).parameter(item) + validWhen = isSingleAddressSecurityGroupRuleOf(item) } } - securityGroupRuleParameters(schema, "rule", true) + securityGroupRuleParameters(schema, rule, true) } } private fun PresentationParametersBuilder.securityGroupRuleParameters(schema: Schema, visibilityDependencyField: String, loadCurrentValues: Boolean) { - step("Rule attributes") { + step("Rule properties") { visibility = WhenNonNull(visibilityDependencyField) parameter("direction", string) { // direction has no description in the schema @@ -80,46 +79,46 @@ private fun PresentationParametersBuilder.securityGroupRuleParameters(schema: Sc mandatory = true defaultValue = defaultDirection predefinedAnswers = allowedDirections - if (loadCurrentValues) dataBinding = securityGroupRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } parameter("ethertype", string) { // etherType has no description in the schema description = "Ether Type" additionalQualifiers += schema.simpleTypeConstraints("ethertype") - if (loadCurrentValues) dataBinding = securityGroupRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } parameter(addressTypeParameterName, string) { description = "Address Type" mandatory = true defaultValue = defaultAddressType predefinedAnswers = allowedAddressTypes - if (loadCurrentValues) dataBinding = securityGroupRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } parameter("addressCidr", string) { description = schema.propertyDescription("subnet") mandatory = true visibility = FromStringParameter(addressTypeParameterName, "CIDR") validWhen = isCidr() - if (loadCurrentValues) dataBinding = securityGroupRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } parameter("addressSecurityGroup", reference()) { description = schema.propertyDescription("security-group") mandatory = true visibility = FromStringParameter(addressTypeParameterName, "Security Group") - if (loadCurrentValues) dataBinding = securityGroupRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } parameter("protocol", string) { description = propertyDescription(schema) mandatory = true defaultValue = defaultProtocol predefinedAnswers = allowedProtocols - if (loadCurrentValues) dataBinding = securityGroupRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } parameter("ports", string) { description = "Port Range" mandatory = true defaultValue = defaultPort - if (loadCurrentValues) dataBinding = securityGroupRulePropertyDataBinding() + if (loadCurrentValues) dataBinding = rulePropertyDataBinding() } } } @@ -128,20 +127,15 @@ internal fun removeSecurityGroupRuleWorkflow(schema: Schema): WorkflowDefinition val workflowName = "Remove rule from security group" return customWorkflow(workflowName).withScriptFile("removeRuleFromSecurityGroup") { - parameter(parent, reference()) { + parameter(item, reference()) { description = relationDescription(schema) mandatory = true } - parameter("rule", string) { - visibility = WhenNonNull(parent) + parameter(rule, string) { + visibility = WhenNonNull(item) description = "Rule to remove" mandatory = true - predefinedAnswersFrom = actionCallTo(networkPolicyRules).parameter(parent) + predefinedAnswersFrom = actionCallTo(networkPolicyRules).parameter(item) } } -} - -// default is capitalized to fit the camelCase function name -// e.g. ports -> rulePropertyPorts -private fun BasicParameterBuilder.securityGroupRulePropertyDataBinding() = - fromRuleProperty(parent, "rule", parameterName.capitalize(), type) \ No newline at end of file +} \ No newline at end of file diff --git a/o11nplugin-contrail-workflows/src/main/kotlin/net/juniper/contrail/vro/workflows/custom/ServiceGroup.kt b/o11nplugin-contrail-workflows/src/main/kotlin/net/juniper/contrail/vro/workflows/custom/ServiceGroup.kt new file mode 100644 index 00000000..f9479780 --- /dev/null +++ b/o11nplugin-contrail-workflows/src/main/kotlin/net/juniper/contrail/vro/workflows/custom/ServiceGroup.kt @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2018 Juniper Networks, Inc. All rights reserved. + */ + +package net.juniper.contrail.vro.workflows.custom + +import net.juniper.contrail.api.types.ServiceGroup +import net.juniper.contrail.vro.config.constants.any +import net.juniper.contrail.vro.config.constants.icmp +import net.juniper.contrail.vro.config.constants.item +import net.juniper.contrail.vro.config.constants.tcp +import net.juniper.contrail.vro.config.constants.udp +import net.juniper.contrail.vro.config.serviceGroupServices +import net.juniper.contrail.vro.schema.Schema +import net.juniper.contrail.vro.workflows.dsl.PresentationParametersBuilder +import net.juniper.contrail.vro.workflows.dsl.WhenNonNull +import net.juniper.contrail.vro.workflows.dsl.WorkflowDefinition +import net.juniper.contrail.vro.workflows.dsl.actionCallTo +import net.juniper.contrail.vro.workflows.model.reference +import net.juniper.contrail.vro.workflows.model.string + +internal fun addServiceToServiceGroupWorkflow(): WorkflowDefinition { + val workflowName = "Add service to service group" + + return customWorkflow(workflowName).withScriptFile("addServiceToServiceGroup") { + step("Service Group") { + parameter(item, reference()) { + description = "Service Group to add service to" + mandatory = true + } + } + serviceGroupParameters(item, false) + } +} + +internal fun editServiceGroupServiceWorkflow(): WorkflowDefinition { + val workflowName = "Edit service of service group" + + return customWorkflow(workflowName).withScriptFile("editServiceOfServiceGroup") { + step("Service Group") { + parameter(item, reference()) { + description = "Service Group to edit service" + mandatory = true + } + parameter(service, string) { + visibility = WhenNonNull(item) + description = "Service to edit" + predefinedAnswersFrom = actionCallTo(serviceGroupServices).parameter(item) + } + } + serviceGroupParameters(service, true) + } +} + +private fun PresentationParametersBuilder.serviceGroupParameters(visibilityParameter: String, editing: Boolean) { + step("Service Properties") { + visibility = WhenNonNull(visibilityParameter) + parameter("protocol", string) { + mandatory = true + // There is no information about protocols in the schema, values were taken from the UI + defaultValue = tcp + predefinedAnswers = listOf(tcp, udp, icmp) + if (editing) dataBinding = servicePropertyDataBinding() + } + parameter("port", string) { + mandatory = true + defaultValue = any + if (editing) dataBinding = servicePropertyDataBinding() + } + } +} + +internal fun removeServiceGroupServiceWorkflow(schema: Schema): WorkflowDefinition { + val workflowName = "Remove service from service group" + + return customWorkflow(workflowName).withScriptFile("removeServiceFromServiceGroup") { + parameter(item, reference()) { + description = "Service Group to remove service from" + mandatory = true + } + parameter(service, string) { + visibility = WhenNonNull(item) + description = "Service to remove" + mandatory = true + predefinedAnswersFrom = actionCallTo(serviceGroupServices).parameter(item) + } + } +} \ No newline at end of file