Allow users to assign a security group to an app
This patch allows users to supply a list* of their own security groups to an instance, rather than using the application defined one (built via the SecurityGroupManager). * Note, while we can support multiple security groups, murano-dashboard currently has no UI element to select multiple items. This means that currently users are restricted to selecting one group. If/when the UI is improved this change can easily support multiple groups. Example ======= Application authors can make this available in their apps as follows: UI.yaml ------- Forms: - instanceConfiguration: fields: ... - name: securityGroups type: securitygroup label: Security Group required: false Class.yaml: ---------- Application: ?: type: com.paul.HelloWorld instance: ?: type: io.murano.resources.LinuxMuranoInstance name: $.instanceConfiguration.hostname securityGroups: $.instanceConfiguration.securityGroups ... DocImpact Change-Id: I60d37cfe034c467e894ee93cf3718e463bf49337 Partially-Implements: blueprint app-use-existing-security-group
This commit is contained in:
parent
580b09d1d4
commit
103f67815a
@ -362,6 +362,8 @@ Currently supported options for **type** attribute are:
|
||||
a list
|
||||
* *network* - specific field, used to select a network and subnet from a list
|
||||
of the ones available to the current user
|
||||
* *securitygroup* - specific field, used for selecting a custom security group
|
||||
to assign to the instance
|
||||
* any other value is considered to be a fully qualified name for some
|
||||
Application package and is rendered as a pair of controls: one for selecting
|
||||
already existing Applications of that type in an Environment, second - for
|
||||
|
@ -131,6 +131,8 @@ Workflow:
|
||||
Contract: $.class(Instance).notNull()
|
||||
- securityGroupName:
|
||||
Contract: $.string()
|
||||
- securityGroups:
|
||||
Contract: [$.string()]
|
||||
- assignFloatingIp:
|
||||
Contract: $.bool().notNull()
|
||||
- sharedIps:
|
||||
|
@ -64,6 +64,9 @@ Properties:
|
||||
securityGroupName:
|
||||
Contract: $.string()
|
||||
Default: null
|
||||
securityGroups:
|
||||
Contract: [$.string()]
|
||||
Default: []
|
||||
sharedIps:
|
||||
Contract:
|
||||
- $.class(std:SharedIp)
|
||||
@ -135,11 +138,11 @@ Methods:
|
||||
- $.ensureNetworksDeployed()
|
||||
- If: $.networks.useEnvironmentNetwork and $region.defaultNetworks.environment!=null
|
||||
Then:
|
||||
$.joinNet($region.defaultNetworks.environment, $securityGroupName)
|
||||
$.joinNet($region.defaultNetworks.environment, $securityGroupName, $this.securityGroups)
|
||||
- If: $.networks.useFlatNetwork and $region.defaultNetworks.flat!=null
|
||||
Then:
|
||||
$.joinNet($region.defaultNetworks.flat, $securityGroupName)
|
||||
- $.networks.customNetworks.select($this.joinNet($, $securityGroupName))
|
||||
$.joinNet($region.defaultNetworks.flat, $securityGroupName, $this.securityGroups)
|
||||
- $.networks.customNetworks.select($this.joinNet($, $securityGroupName, $this.securityGroups))
|
||||
|
||||
- $preparedUserData: $.prepareUserData()
|
||||
- $properties:
|
||||
@ -251,6 +254,8 @@ Methods:
|
||||
Contract: $.class(Network).notNull()
|
||||
- securityGroupName:
|
||||
Contract: $.string()
|
||||
- securityGroups:
|
||||
Contract: [$.string()]
|
||||
Body:
|
||||
- $primary: $net = $._primaryNetwork
|
||||
- $assignFip: $primary and $.assignFloatingIp and not $.getAttr(fipAssigned, false)
|
||||
@ -261,6 +266,7 @@ Methods:
|
||||
- $joinResult: $net.joinInstance(
|
||||
instance => $this,
|
||||
securityGroupName => $securityGroupName,
|
||||
securityGroups => $securityGroups,
|
||||
assignFloatingIp => $assignFip,
|
||||
sharedIps => $sharedIps
|
||||
)
|
||||
|
@ -127,6 +127,8 @@ Methods:
|
||||
Contract: $.class(Instance).notNull()
|
||||
- securityGroupName:
|
||||
Contract: $.string()
|
||||
- securityGroups:
|
||||
Contract: [$.string()]
|
||||
- assignFloatingIp:
|
||||
Contract: $.bool().notNull()
|
||||
- sharedIps:
|
||||
@ -146,6 +148,7 @@ Methods:
|
||||
- $result: $.joinInstanceToNetwork(
|
||||
instance => $instance,
|
||||
securityGroupName => $securityGroupName,
|
||||
securityGroups => $securityGroups,
|
||||
sharedIps => $sharedIps,
|
||||
netRef => $netRef,
|
||||
subnetRef => $subnetRef,
|
||||
|
@ -38,6 +38,8 @@ Methods:
|
||||
Contract: $.class(Instance).notNull()
|
||||
- securityGroupName:
|
||||
Contract: $.string()
|
||||
- securityGroups:
|
||||
Contract: [$.string()]
|
||||
- sharedIps:
|
||||
Contract:
|
||||
- $.class(std:SharedIp)
|
||||
@ -80,7 +82,22 @@ Methods:
|
||||
- subnet: $subnetRef
|
||||
- $patchTemplate: $patchTemplate.mergeWith($template)
|
||||
|
||||
- If: bool($securityGroupName) and $securityGroupsEnabled
|
||||
- If: $securityGroupsEnabled
|
||||
Then:
|
||||
- If: len($securityGroups) > 0 and $securityGroups[0] != ""
|
||||
Then:
|
||||
- For: securityGroup
|
||||
In: $securityGroups
|
||||
Do:
|
||||
- $template:
|
||||
resources:
|
||||
$portName:
|
||||
properties:
|
||||
security_groups:
|
||||
- $securityGroup
|
||||
- $patchTemplate: $patchTemplate.mergeWith($template)
|
||||
Else:
|
||||
- If: bool($securityGroupName)
|
||||
Then:
|
||||
- $template:
|
||||
resources:
|
||||
|
@ -212,6 +212,32 @@ class BaseApplicationCatalogScenarioTest(base.BaseTestCase):
|
||||
}
|
||||
return post_body
|
||||
|
||||
def vm_test(self, **kwargs):
|
||||
instance = {
|
||||
"flavor": "m1.small",
|
||||
"image": self.cirros_image,
|
||||
"assignFloatingIp": True,
|
||||
"availabilityZone": "nova",
|
||||
"?": {
|
||||
"type": "io.murano.resources.LinuxMuranoInstance",
|
||||
"id": utils.generate_uuid()
|
||||
},
|
||||
"name": utils.generate_name("testMurano")
|
||||
}
|
||||
if kwargs.get('securityGroups'):
|
||||
instance['securityGroups'] = kwargs.get('securityGroups')
|
||||
return {
|
||||
"instance": instance,
|
||||
"name": utils.generate_name("VM"),
|
||||
"?": {
|
||||
"_{id}".format(id=utils.generate_uuid()): {
|
||||
"name": "VM"
|
||||
},
|
||||
"type": "io.murano.apps.test.VM",
|
||||
"id": utils.generate_uuid()
|
||||
}
|
||||
}
|
||||
|
||||
def update_executor(self, flavor='m1.small'):
|
||||
post_body = {
|
||||
"instance": {
|
||||
@ -365,7 +391,7 @@ class BaseApplicationCatalogScenarioTest(base.BaseTestCase):
|
||||
instance_id = self.get_instance_id(name)
|
||||
attached_volumes = self.servers_client.\
|
||||
list_volume_attachments(instance_id)['volumeAttachments']
|
||||
assert attached_volumes[0]['id'] == volume_id
|
||||
self.assertEqual(attached_volumes[0]['id'], volume_id)
|
||||
|
||||
|
||||
class BaseApplicationCatalogScenarioIsolatedAdminTest(
|
||||
|
@ -0,0 +1,82 @@
|
||||
#
|
||||
# Licensed 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.
|
||||
|
||||
import os
|
||||
import testtools
|
||||
|
||||
from tempest import config
|
||||
|
||||
from murano_tempest_tests.tests.scenario.application_catalog import base
|
||||
from murano_tempest_tests import utils
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class TestSecurityGroups(base.BaseApplicationCatalogScenarioTest):
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
super(TestSecurityGroups, cls).resource_setup()
|
||||
cls.linux = CONF.application_catalog.linux_image
|
||||
application_name = utils.generate_name('VM')
|
||||
cls.abs_archive_path, dir_with_archive, archive_name = \
|
||||
utils.prepare_package(
|
||||
application_name,
|
||||
app='io.murano.apps.test.VM',
|
||||
manifest_required=False)
|
||||
if CONF.application_catalog.glare_backend:
|
||||
cls.client = cls.artifacts_client
|
||||
else:
|
||||
cls.client = cls.application_catalog_client
|
||||
cls.package = cls.client.upload_package(
|
||||
application_name, archive_name, dir_with_archive,
|
||||
{"categories": ["Web"], "tags": ["test"]})
|
||||
|
||||
@classmethod
|
||||
def resource_cleanup(cls):
|
||||
cls.client.delete_package(cls.package['id'])
|
||||
os.remove(cls.abs_archive_path)
|
||||
super(TestSecurityGroups, cls).resource_cleanup()
|
||||
|
||||
@testtools.testcase.attr('smoke')
|
||||
@testtools.testcase.attr('scenario')
|
||||
def test_deploy_app_with_murano_defined_security_group(self):
|
||||
name = utils.generate_name('testMurano')
|
||||
environment = self.application_catalog_client.create_environment(name)
|
||||
session = self.application_catalog_client.create_session(
|
||||
environment['id'])
|
||||
self.application_catalog_client.create_service(
|
||||
environment['id'], session['id'], self.vm_test())
|
||||
self.deploy_environment(environment, session)
|
||||
instance_id = self.get_instance_id('testMurano')
|
||||
security_groups = self.servers_client.list_security_groups_by_server(
|
||||
instance_id).get('security_groups')
|
||||
self.assertEqual(len(security_groups), 1)
|
||||
self.assertEqual(len(security_groups[0].get('rules')), 4)
|
||||
|
||||
@testtools.testcase.attr('smoke')
|
||||
@testtools.testcase.attr('scenario')
|
||||
def test_deploy_app_with_user_defined_security_group(self):
|
||||
name = utils.generate_name('testMurano')
|
||||
environment = self.application_catalog_client.create_environment(name)
|
||||
session = self.application_catalog_client.create_session(
|
||||
environment['id'])
|
||||
self.application_catalog_client.create_service(
|
||||
environment['id'], session['id'],
|
||||
self.vm_test(securityGroups=['default']))
|
||||
self.deploy_environment(environment, session)
|
||||
instance_id = self.get_instance_id('testMurano')
|
||||
security_groups = self.servers_client.list_security_groups_by_server(
|
||||
instance_id).get('security_groups')
|
||||
self.assertEqual(len(security_groups), 1)
|
||||
self.assertEqual('default', security_groups[0].get('name'))
|
@ -0,0 +1,5 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Users can now assign an existing security group to an application as
|
||||
an alternative to using the one created by Murano's ``SecurityGroupManager``.
|
Loading…
Reference in New Issue
Block a user