puppet module unit test coverage
Also refactored puppet module Co-Authored-By: Dmitry Guryanov <dguryanov@mirantis.com> Change-Id: I36ff6d0cd5fe67e9a14c7c8a5940606cc0594e6d Partial-Bug: #1365391
This commit is contained in:
parent
b14b7a69a8
commit
23b5bb288b
@ -13,44 +13,58 @@
|
||||
# under the License.
|
||||
|
||||
import logging
|
||||
import six
|
||||
|
||||
from fuelmenu.common.utils import execute
|
||||
from fuelmenu.common import utils
|
||||
from fuelmenu import consts
|
||||
|
||||
|
||||
def _to_string(value):
|
||||
if isinstance(value, bool):
|
||||
return '{0},'.format(str(value).lower())
|
||||
return '"{0}",'.format(value)
|
||||
|
||||
|
||||
def puppetApply(classes):
|
||||
#name should be a string
|
||||
#params should be a dict or list of dicts
|
||||
'''Runs puppet apply -e "classname {'name': params}".'''
|
||||
"""Runs puppet apply
|
||||
|
||||
:param classes: list of {'type': 'name': 'params':}. name must be a string
|
||||
:type classes: dict or list of dicts
|
||||
"""
|
||||
log = logging
|
||||
log.info("Puppet start")
|
||||
|
||||
command = ["puppet", "apply", "-d", "-v", "--logdest",
|
||||
"/var/log/puppet/fuelmenu-puppet.log"]
|
||||
input = []
|
||||
# TODO(mattymo): Convert puppet resource types to consts
|
||||
for cls in classes:
|
||||
if cls['type'] == "literal":
|
||||
input.append(cls["name"])
|
||||
continue
|
||||
elif cls['type'] == "resource":
|
||||
input.extend([cls["class"], "{", '"%s":' % cls["name"]])
|
||||
elif cls['type'] == "class":
|
||||
input.extend(["class", "{", '"%s":' % cls["class"]])
|
||||
else:
|
||||
log.error("Invalid type %s" % cls['type'])
|
||||
return False
|
||||
#Build params
|
||||
for key, value in cls["params"].iteritems():
|
||||
if type(value) == bool:
|
||||
input.extend([key, "=>", '%s,' % str(value).lower()])
|
||||
else:
|
||||
input.extend([key, "=>", '"%s",' % value])
|
||||
input.append('}')
|
||||
|
||||
log.debug(' '.join(command))
|
||||
log.debug(' '.join(input))
|
||||
code, out, err = execute(command, stdin=' '.join(input))
|
||||
if code != 0:
|
||||
log.error("Exit code: {0}. Error: {1} Stdout: {1}".format(
|
||||
code, err, out))
|
||||
puppet_type_handlers = {
|
||||
consts.PUPPET_TYPE_LITERAL: lambda item: [item['name']],
|
||||
consts.PUPPET_TYPE_RESOURCE: lambda item: [
|
||||
item["class"], "{", '"{0}":'.format(item["name"])],
|
||||
consts.PUPPET_TYPE_CLASS: lambda item: [
|
||||
"class", "{", '"{0}":'.format(item["class"])]
|
||||
}
|
||||
|
||||
cmd_input = list()
|
||||
for cls in classes:
|
||||
if cls['type'] not in puppet_type_handlers:
|
||||
log.error("Invalid type %s", cls['type'])
|
||||
return False
|
||||
|
||||
cmd_input.extend(puppet_type_handlers[cls['type']](cls))
|
||||
if cls['type'] == consts.PUPPET_TYPE_LITERAL:
|
||||
continue
|
||||
|
||||
#Build params
|
||||
for key, value in six.iteritems(cls["params"]):
|
||||
cmd_input.extend([key, "=>", _to_string(value)])
|
||||
cmd_input.append('}')
|
||||
|
||||
stdin = ' '.join(cmd_input)
|
||||
log.debug(' '.join(command))
|
||||
log.debug(stdin)
|
||||
code, out, err = utils.execute(command, stdin=stdin)
|
||||
if code != 0:
|
||||
log.error("Exit code: %d. Error: %s Stdout: %s",
|
||||
code, err, out)
|
||||
return False
|
||||
|
@ -23,3 +23,7 @@ RELEASE_FILE = "/etc/fuel_release"
|
||||
|
||||
PRE_DEPLOYMENT_MODE = "pre"
|
||||
POST_DEPLOYMENT_MODE = "post"
|
||||
|
||||
PUPPET_TYPE_LITERAL = "literal"
|
||||
PUPPET_TYPE_RESOURCE = "resource"
|
||||
PUPPET_TYPE_CLASS = "class"
|
||||
|
82
fuelmenu/tests/test_common_puppet.py
Normal file
82
fuelmenu/tests/test_common_puppet.py
Normal file
@ -0,0 +1,82 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2016 Mirantis, Inc.
|
||||
#
|
||||
# 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 unittest
|
||||
|
||||
from fuelmenu.common import puppet
|
||||
|
||||
|
||||
@mock.patch('fuelmenu.common.puppet.logging')
|
||||
@mock.patch('fuelmenu.common.puppet.utils.execute',
|
||||
return_value=(0, 'Success', 0))
|
||||
class TestPuppetApply(unittest.TestCase):
|
||||
def setUp(self):
|
||||
super(TestPuppetApply, self).setUp()
|
||||
self.command = ["puppet", "apply", "-d", "-v", "--logdest",
|
||||
"/var/log/puppet/fuelmenu-puppet.log"]
|
||||
self.input = (
|
||||
'literal_1 class_1 { "resource_1": resource_k1 => "Resource_v1", }'
|
||||
' class { "class_1": class_k3 => true, }'
|
||||
)
|
||||
self.classes = [
|
||||
{
|
||||
'type': 'literal',
|
||||
'name': 'literal_1',
|
||||
'params': {
|
||||
'literal_k1': 'Literal_v1',
|
||||
}
|
||||
},
|
||||
{
|
||||
'type': 'resource',
|
||||
'name': 'resource_1',
|
||||
'class': 'class_1',
|
||||
'params': {
|
||||
'resource_k1': 'Resource_v1',
|
||||
}
|
||||
},
|
||||
{
|
||||
'type': 'class',
|
||||
'class': 'class_1',
|
||||
'params': {
|
||||
'class_k3': True
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
def test_puppet_apply(self, m_execute, m_log):
|
||||
self.assertEqual(puppet.puppetApply(self.classes), None)
|
||||
m_execute.assert_called_once_with(self.command, stdin=self.input)
|
||||
m_log.info.assert_called_once_with('Puppet start')
|
||||
self.assertFalse(m_log.error.called)
|
||||
|
||||
def test_incorrect_type(self, m_execute, m_log):
|
||||
self.classes.append({
|
||||
'type': 'incorrect',
|
||||
'name': 'incorrect name',
|
||||
'class': 'class_2',
|
||||
'params': {}
|
||||
})
|
||||
self.assertEqual(puppet.puppetApply(self.classes), False)
|
||||
self.assertFalse(m_execute.called)
|
||||
m_log.error.assert_called_once_with('Invalid type %s', 'incorrect')
|
||||
|
||||
def test_execute_failure(self, m_execute, m_log):
|
||||
res = (1, 'Fail', 5)
|
||||
m_execute.return_value = res
|
||||
self.assertEqual(puppet.puppetApply(self.classes), False)
|
||||
m_log.error.assert_called_once_with(
|
||||
'Exit code: %d. Error: %s Stdout: %s', res[0], res[2], res[1])
|
Loading…
Reference in New Issue
Block a user