Allow calling template validate and template add with a string

Vitrage template add and template validate can now be called with either
a path or a string that holds the template yaml.

Change-Id: Ieaa372e92d201b46124163b164cc868ae35c86b2
Story: 2004055
Task: 27061
This commit is contained in:
Ifat Afek 2019-03-05 12:21:14 +00:00
parent bde2d05710
commit ecd027535d
5 changed files with 174 additions and 21 deletions

View File

@ -0,0 +1,4 @@
---
features:
- Added an option to add templates to Vitrage by a string that holds the
template yaml, and not only by a file path.

View File

@ -0,0 +1,16 @@
metadata:
version: 3
name: template1
description: simple template
type: standard
entities:
alarm:
name: cpu problem
host:
type: nova.host
scenarios:
- condition: alarm [ on ] host
actions:
- set_state:
state: ERROR
target: host

View File

@ -0,0 +1,78 @@
# Copyright 2019 - Nokia
#
# 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
from oslotest import base
from vitrageclient import exceptions as exc
from vitrageclient.tests.utils import get_resources_dir
from vitrageclient.v1.template import Template
TEMPLATE_STRING = """
metadata:
version: 3
name: template1
description: simple template
type: standard
entities:
alarm:
name: cpu problem
host:
type: nova.host
scenarios:
- condition: alarm [ on ] host
actions:
- set_state:
state: ERROR
target: host
"""
class TestTemplate(base.BaseTestCase):
def test_validate_by_path(self):
template_path = get_resources_dir() + '/template1.yaml'
template = Template(mock.Mock())
template.validate(path=template_path)
def test_validate_by_nonexisting_path(self):
template = Template(mock.Mock())
self.assertRaises(IOError, template.validate,
path='non_existing_template_path.yaml')
def test_validate_by_template(self):
template = Template(mock.Mock())
template.validate(template_str=TEMPLATE_STRING)
def test_validate_by_nothing(self):
template = Template(mock.Mock())
self.assertRaises(exc.CommandError, template.validate)
def test_add_by_path(self):
template_path = get_resources_dir() + '/template1.yaml'
template = Template(mock.Mock())
template.add(path=template_path)
def test_add_by_nonexisting_path(self):
template = Template(mock.Mock())
self.assertRaises(IOError, template.add,
path='non_existing_template_path.yaml')
def test_add_by_template(self):
template = Template(mock.Mock())
template.add(template_str=TEMPLATE_STRING)
def test_add_by_nothing(self):
template = Template(mock.Mock())
self.assertRaises(exc.CommandError, template.add)

View File

@ -0,0 +1,19 @@
# Copyright 2019 - Nokia
#
# 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 os import path
def get_resources_dir():
return path.join(path.dirname(__file__), 'resources')

View File

@ -35,10 +35,22 @@ class Template(object):
url = self.url + uuid
return self.api.get(url).json()
def add(self, path, template_type=None, params=None):
"""Add a new template"""
def add(self, path=None, template_str=None,
template_type=None, params=None):
"""Add a new template
files_content = self._load_yaml_files(path)
:param path: (optional) The template file path or templates dir path
:param template_str: (optional) A string representation of the template
yaml
Either path or template_str must exist (but not both)
:param template_type: (optional) The template type, in case it is not
written inside the template metadata section
:param params: (optional) Actual values for the template parameters
:return:
"""
files_content = \
self._load_template(path=path, template_str=template_str)
api_params = dict(templates=files_content,
template_type=template_type,
params=params)
@ -49,7 +61,8 @@ class Template(object):
params = dict(uuid=uuid)
return self.api.delete(self.url, json=params).json()
def validate(self, path, template_type=None, params=None):
def validate(self, path=None, template_str=None,
template_type=None, params=None):
"""Template validation
Make sure that the template file is correct in terms of syntax
@ -58,18 +71,25 @@ class Template(object):
template, or directory path for validation of several templates (the
directory must contain only templates)
:param path: the template file path or templates dir path
:param template_type: type of templates ('standard','definition',...)
:param params: (optional) actual values for the template parameters
"""
:param path: (optional) The template file path or templates dir path
:param template_str: (optional) A string representation of the template
yaml
Either path or template_str must exist (but not both)
files_content = self._load_yaml_files(path)
:param template_type: (optional) The template type, in case it is not
written inside the template metadata section
:param params: (optional) Actual values for the template parameters
:return:
"""
files_content = \
self._load_template(path=path, template_str=template_str)
api_params = dict(templates=files_content,
template_type=template_type,
params=params)
return self.api.post(self.url, json=api_params).json()
def _load_yaml_files(self, path):
@classmethod
def _load_yaml_files(cls, path):
if os.path.isdir(path):
files_content = []
@ -77,20 +97,36 @@ class Template(object):
file_path = '%s/%s' % (path, file_name)
if os.path.isfile(file_path):
template = self._load_yaml_file(file_path)
template = cls._load_yaml_file(file_path)
files_content.append((file_path, template))
else:
files_content = [(path, self._load_yaml_file(path))]
files_content = [(path, cls._load_yaml_file(path))]
return files_content
@staticmethod
def _load_yaml_file(path):
@classmethod
def _load_yaml_file(cls, path):
with open(path, 'r') as stream:
try:
return yaml_utils.load(stream)
except ValueError as e:
message = 'Could not load template file: %s. Reason: %s' \
% (path, e.message)
raise exc.CommandError(message)
return cls._load_yaml(stream)
@classmethod
def _load_yaml(cls, yaml_content):
try:
return yaml_utils.load(yaml_content)
except ValueError as e:
message = 'Could not load template: %s. Reason: %s' \
% (yaml_content, e.message)
raise exc.CommandError(message)
@classmethod
def _load_template(cls, path, template_str):
if path:
files_content = cls._load_yaml_files(path)
elif template_str:
files_content = [(None, cls._load_yaml(template_str))]
else:
raise exc.CommandError(
'Add template API must be called with either \'path\' or '
'\'template_str\'')
return files_content