Support of ignoreErrors for commands

cfn-init will now fail immediately if a command with the key
ignoreErrors='false' or without that key fails (eg it returns an exit
code other than 0). This is similar to what the AWS cfn-init script is
doing.

Change-Id: I41bfa36154fa8b16541a6abb489495739b772376
Closes-Bug: #1269476
This commit is contained in:
Simon Pasquier 2014-01-16 11:16:13 +01:00
parent a61e221950
commit 3a0993210d
2 changed files with 62 additions and 19 deletions

View File

@ -829,6 +829,10 @@ def metadata_server_port(
return None
class CommandsHandlerRunError(Exception):
pass
class CommandsHandler(object):
def __init__(self, commands):
@ -887,14 +891,12 @@ class CommandsHandler(object):
if command_status == 0:
LOG.info("%s has been successfully executed" % command_label)
else:
if "ignoreErrors" in properties:
if properties["ignoreErrors"] == "false":
LOG.error("%s has failed. Not ignoring" % command_label)
else:
LOG.info("%s has failed. Explicit ignoring"
% command_label)
if "ignoreErrors" in properties and \
to_boolean(properties["ignoreErrors"]):
LOG.info("%s has failed (status=%d). Explicit ignoring"
% (command_label, command_status))
else:
LOG.error("%s has failed." % command_label)
raise CommandsHandlerRunError("%s has failed." % command_label)
class GroupsHandler(object):

View File

@ -800,18 +800,6 @@ class TestMetadataRetrieve(testtools.TestCase):
finally:
m.UnsetStubs()
def test_cfn_init(self):
with tempfile.NamedTemporaryFile(mode='w+') as foo_file:
md_data = {"AWS::CloudFormation::Init": {"config": {"files": {
foo_file.name: {"content": "bar"}}}}}
md = cfn_helper.Metadata('teststack', None)
self.assertTrue(
md.retrieve(meta_str=md_data, last_path=self.last_file))
md.cfn_init()
self.assertThat(foo_file.name, ttm.FileContains('bar'))
def test_nova_meta_with_cache(self):
meta_in = {"uuid": "f9431d18-d971-434d-9044-5b38f5b4646f",
"availability_zone": "nova",
@ -960,6 +948,59 @@ class TestMetadataRetrieve(testtools.TestCase):
self.m.VerifyAll()
class TestCfnInit(MockPopenTestCase):
def setUp(self):
super(TestCfnInit, self).setUp()
self.tdir = self.useFixture(fixtures.TempDir())
self.last_file = os.path.join(self.tdir.path, 'last_metadata')
def test_cfn_init(self):
with tempfile.NamedTemporaryFile(mode='w+') as foo_file:
md_data = {"AWS::CloudFormation::Init": {"config": {"files": {
foo_file.name: {"content": "bar"}}}}}
md = cfn_helper.Metadata('teststack', None)
self.assertTrue(
md.retrieve(meta_str=md_data, last_path=self.last_file))
md.cfn_init()
self.assertThat(foo_file.name, ttm.FileContains('bar'))
def test_cfn_init_with_ignore_errors_false(self):
self.mock_cmd_run(['su', 'root', '-c', '/bin/command1']).AndReturn(
FakePOpen('Doing something', 'error', -1))
self.m.ReplayAll()
md_data = {"AWS::CloudFormation::Init": {"config": {"commands": {
"00_foo": {"command": "/bin/command1",
"ignoreErrors": "false"}}}}}
md = cfn_helper.Metadata('teststack', None)
self.assertTrue(
md.retrieve(meta_str=md_data, last_path=self.last_file))
self.assertRaises(cfn_helper.CommandsHandlerRunError, md.cfn_init)
def test_cfn_init_with_ignore_errors_true(self):
self.mock_cmd_run(['su', 'root', '-c', '/bin/command1']).AndReturn(
FakePOpen('Doing something', 'error', -1))
self.mock_cmd_run(['su', 'root', '-c', '/bin/command2']).AndReturn(
FakePOpen('All good'))
self.m.ReplayAll()
md_data = {"AWS::CloudFormation::Init": {"config": {"commands": {
"00_foo": {"command": "/bin/command1",
"ignoreErrors": "true"},
"01_bar": {"command": "/bin/command2",
"ignoreErrors": "false"}
}}}}
md = cfn_helper.Metadata('teststack', None)
self.assertTrue(
md.retrieve(meta_str=md_data, last_path=self.last_file))
md.cfn_init()
class TestSourcesHandler(MockPopenTestCase):
def test_apply_sources_empty(self):
sh = cfn_helper.SourcesHandler({})