Add OS::Sahara::DataSource resource
blueprint sahara-edp Change-Id: Ie9b0ae5e396b37f5aff286fb94c12b9e15bf4198
This commit is contained in:
parent
bf4ec9f1ae
commit
123404f801
133
heat/engine/resources/openstack/sahara/data_source.py
Normal file
133
heat/engine/resources/openstack/sahara/data_source.py
Normal file
@ -0,0 +1,133 @@
|
||||
#
|
||||
# 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.
|
||||
|
||||
from heat.common.i18n import _
|
||||
from heat.engine import constraints
|
||||
from heat.engine import properties
|
||||
from heat.engine import resource
|
||||
from heat.engine import support
|
||||
|
||||
|
||||
class DataSource(resource.Resource):
|
||||
"""A resource for creating sahara data source.
|
||||
|
||||
A data source stores an URL which designates the location of input
|
||||
or output data and any credentials needed to access the location.
|
||||
"""
|
||||
|
||||
support_status = support.SupportStatus(version='5.0.0')
|
||||
|
||||
PROPERTIES = (
|
||||
NAME, TYPE, URL, DESCRIPTION, CREDENTIALS
|
||||
|
||||
) = (
|
||||
'name', 'type', 'url', 'description', 'credentials'
|
||||
)
|
||||
|
||||
_CREDENTIAL_KEYS = (
|
||||
USER, PASSWORD
|
||||
) = (
|
||||
'user', 'password'
|
||||
)
|
||||
|
||||
_DATA_SOURCE_TYPES = (
|
||||
SWIFT, HDFS, MAPRFS
|
||||
) = (
|
||||
'swift', 'hdfs', 'maprfs'
|
||||
)
|
||||
|
||||
properties_schema = {
|
||||
NAME: properties.Schema(
|
||||
properties.Schema.STRING,
|
||||
_("Name of the data source."),
|
||||
update_allowed=True
|
||||
),
|
||||
TYPE: properties.Schema(
|
||||
properties.Schema.STRING,
|
||||
_('Type of the data source.'),
|
||||
constraints=[
|
||||
constraints.AllowedValues(_DATA_SOURCE_TYPES),
|
||||
],
|
||||
required=True,
|
||||
update_allowed=True
|
||||
),
|
||||
URL: properties.Schema(
|
||||
properties.Schema.STRING,
|
||||
_('URL for the data source.'),
|
||||
required=True,
|
||||
update_allowed=True
|
||||
),
|
||||
DESCRIPTION: properties.Schema(
|
||||
properties.Schema.STRING,
|
||||
_('Description of the data source.'),
|
||||
default='',
|
||||
update_allowed=True
|
||||
),
|
||||
CREDENTIALS: properties.Schema(
|
||||
properties.Schema.MAP,
|
||||
_('Credentials used for swift. Not required if sahara is '
|
||||
'configured to use proxy users and delegated trusts for '
|
||||
'access.'),
|
||||
schema={
|
||||
USER: properties.Schema(
|
||||
properties.Schema.STRING,
|
||||
_('Username for accessing the data source URL.'),
|
||||
required=True
|
||||
),
|
||||
PASSWORD: properties.Schema(
|
||||
properties.Schema.STRING,
|
||||
_("Password for accessing the data source URL."),
|
||||
required=True
|
||||
)
|
||||
},
|
||||
update_allowed=True
|
||||
)
|
||||
}
|
||||
|
||||
default_client_name = 'sahara'
|
||||
|
||||
entity = 'data_sources'
|
||||
|
||||
def _data_source_name(self):
|
||||
return self.properties[self.NAME] or self.physical_resource_name()
|
||||
|
||||
def handle_create(self):
|
||||
credentials = self.properties[self.CREDENTIALS] or {}
|
||||
args = {
|
||||
'name': self._data_source_name(),
|
||||
'description': self.properties[self.DESCRIPTION],
|
||||
'data_source_type': self.properties[self.TYPE],
|
||||
'url': self.properties[self.URL],
|
||||
'credential_user': credentials.get(self.USER),
|
||||
'credential_pass': credentials.get(self.PASSWORD)
|
||||
}
|
||||
|
||||
data_source = self.client().data_sources.create(**args)
|
||||
self.resource_id_set(data_source.id)
|
||||
|
||||
def handle_update(self, json_snippet, tmpl_diff, prop_diff):
|
||||
if prop_diff:
|
||||
self.properties = json_snippet.properties(
|
||||
self.properties_schema,
|
||||
self.context)
|
||||
data = dict(self.properties)
|
||||
if not data.get(self.NAME):
|
||||
data[self.NAME] = self.physical_resource_name()
|
||||
self.client().data_sources.update(self.resource_id, data)
|
||||
|
||||
|
||||
def resource_mapping():
|
||||
return {
|
||||
'OS::Sahara::DataSource': DataSource
|
||||
}
|
131
heat/tests/test_sahara_data_source.py
Normal file
131
heat/tests/test_sahara_data_source.py
Normal file
@ -0,0 +1,131 @@
|
||||
#
|
||||
# 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 mock
|
||||
import six
|
||||
|
||||
from heat.common import exception
|
||||
from heat.common import template_format
|
||||
from heat.engine.clients.os import sahara
|
||||
from heat.engine.resources.openstack.sahara import data_source
|
||||
from heat.engine import scheduler
|
||||
from heat.tests import common
|
||||
from heat.tests import utils
|
||||
|
||||
|
||||
data_source_template = """
|
||||
heat_template_version: 2015-10-15
|
||||
resources:
|
||||
data-source:
|
||||
type: OS::Sahara::DataSource
|
||||
properties:
|
||||
name: my-ds
|
||||
type: swift
|
||||
url: swift://container.sahara/text
|
||||
credentials:
|
||||
user: admin
|
||||
password: swordfish
|
||||
"""
|
||||
|
||||
|
||||
class SaharaDataSourceTest(common.HeatTestCase):
|
||||
def setUp(self):
|
||||
super(SaharaDataSourceTest, self).setUp()
|
||||
t = template_format.parse(data_source_template)
|
||||
self.stack = utils.parse_stack(t)
|
||||
resource_defns = self.stack.t.resource_definitions(self.stack)
|
||||
self.rsrc_defn = resource_defns['data-source']
|
||||
self.client = mock.Mock()
|
||||
self.patchobject(data_source.DataSource, 'client',
|
||||
return_value=self.client)
|
||||
|
||||
def _create_resource(self, name, snippet, stack):
|
||||
ds = data_source.DataSource(name, snippet, stack)
|
||||
value = mock.MagicMock(id='12345')
|
||||
self.client.data_sources.create.return_value = value
|
||||
scheduler.TaskRunner(ds.create)()
|
||||
return ds
|
||||
|
||||
def test_create(self):
|
||||
ds = self._create_resource('data-source', self.rsrc_defn, self.stack)
|
||||
args = self.client.data_sources.create.call_args[1]
|
||||
expected_args = {
|
||||
'name': 'my-ds',
|
||||
'description': '',
|
||||
'data_source_type': 'swift',
|
||||
'url': 'swift://container.sahara/text',
|
||||
'credential_user': 'admin',
|
||||
'credential_pass': 'swordfish'
|
||||
}
|
||||
self.assertEqual(expected_args, args)
|
||||
self.assertEqual('12345', ds.resource_id)
|
||||
expected_state = (ds.CREATE, ds.COMPLETE)
|
||||
self.assertEqual(expected_state, ds.state)
|
||||
|
||||
def test_resource_mapping(self):
|
||||
mapping = data_source.resource_mapping()
|
||||
self.assertEqual(1, len(mapping))
|
||||
self.assertEqual(data_source.DataSource,
|
||||
mapping['OS::Sahara::DataSource'])
|
||||
|
||||
def test_delete(self):
|
||||
ds = self._create_resource('data-source', self.rsrc_defn, self.stack)
|
||||
scheduler.TaskRunner(ds.delete)()
|
||||
self.assertEqual((ds.DELETE, ds.COMPLETE), ds.state)
|
||||
self.client.data_sources.delete.assert_called_once_with(
|
||||
ds.resource_id)
|
||||
|
||||
def test_update(self):
|
||||
ds = self._create_resource('data-source', self.rsrc_defn,
|
||||
self.stack)
|
||||
self.rsrc_defn['Properties']['type'] = 'hdfs'
|
||||
self.rsrc_defn['Properties']['url'] = 'my/path'
|
||||
scheduler.TaskRunner(ds.update, self.rsrc_defn)()
|
||||
data = {
|
||||
'name': 'my-ds',
|
||||
'description': '',
|
||||
'type': 'hdfs',
|
||||
'url': 'my/path',
|
||||
'credentials': {
|
||||
'user': 'admin',
|
||||
'password': 'swordfish'
|
||||
}
|
||||
}
|
||||
self.client.data_sources.update.assert_called_once_with(
|
||||
'12345', data)
|
||||
self.assertEqual((ds.UPDATE, ds.COMPLETE), ds.state)
|
||||
|
||||
def test_delete_not_found(self):
|
||||
ds = self._create_resource('data-source', self.rsrc_defn, self.stack)
|
||||
self.client.data_sources.delete.side_effect = (
|
||||
sahara.sahara_base.APIException(error_code=404))
|
||||
scheduler.TaskRunner(ds.delete)()
|
||||
self.assertEqual((ds.DELETE, ds.COMPLETE), ds.state)
|
||||
self.client.data_sources.delete.assert_called_once_with(
|
||||
ds.resource_id)
|
||||
|
||||
def test_show_attribute(self):
|
||||
ds = self._create_resource('data-source', self.rsrc_defn, self.stack)
|
||||
value = mock.MagicMock()
|
||||
value.to_dict.return_value = {'ds': 'info'}
|
||||
self.client.data_sources.get.return_value = value
|
||||
self.assertEqual({'ds': 'info'}, ds.FnGetAtt('show'))
|
||||
|
||||
def test_validate_password_without_user(self):
|
||||
self.rsrc_defn['Properties']['credentials'].pop('user')
|
||||
ds = data_source.DataSource('data-source', self.rsrc_defn, self.stack)
|
||||
ex = self.assertRaises(exception.StackValidationFailed, ds.validate)
|
||||
error_msg = ('Property error: resources.data-source.properties.'
|
||||
'credentials: Property user not assigned')
|
||||
self.assertEqual(error_msg, six.text_type(ex))
|
Loading…
x
Reference in New Issue
Block a user