diff options
Diffstat (limited to 'tests/software_config')
23 files changed, 0 insertions, 2903 deletions
diff --git a/tests/software_config/__init__.py b/tests/software_config/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/tests/software_config/__init__.py +++ /dev/null diff --git a/tests/software_config/common.py b/tests/software_config/common.py deleted file mode 100644 index c1a2dce..0000000 --- a/tests/software_config/common.py +++ /dev/null @@ -1,38 +0,0 @@ -# -# 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 json -import os -import subprocess - -import testtools - - -class RunScriptTest(testtools.TestCase): - - def relative_path(self, from_path, *to_paths): - return os.path.join( - os.path.dirname(os.path.realpath(from_path)), *to_paths) - - def run_cmd(self, args, env, input_str=None): - subproc = subprocess.Popen(args, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - env=env) - stdout, stderr = subproc.communicate(input=input_str) - return subproc.returncode, stdout, stderr - - def json_from_file(self, path): - with open(path) as f: - return json.load(f) diff --git a/tests/software_config/config-tool-fake.py b/tests/software_config/config-tool-fake.py deleted file mode 100755 index efa0883..0000000 --- a/tests/software_config/config-tool-fake.py +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env python -# -# 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. -''' -A fake config tool for unit testing the software-config hooks. - -JSON containing the current environment variables and command line arguments -are written to the file specified by the path in environment variable -TEST_STATE_PATH. - -Environment variable TEST_RESPONSE defines JSON specifying what files to write -out, and what to print to stdout and stderr. -''' - -import json -import os -import sys - - -def main(argv=sys.argv): - - state_path = os.environ.get('TEST_STATE_PATH') - - # handle multiple invocations by writing to numbered state path files - suffix = 0 - while os.path.isfile(state_path): - suffix += 1 - state_path = '%s_%s' % (os.environ.get('TEST_STATE_PATH'), suffix) - - with open(state_path, 'w') as f: - json.dump({'env': dict(os.environ), 'args': argv}, f) - - if 'TEST_RESPONSE' not in os.environ: - return - - response = json.loads(os.environ.get('TEST_RESPONSE')) - for k, v in response.get('files', {}).iteritems(): - open(k, 'w') - with open(k, 'w') as f: - f.write(v) - - sys.stdout.write(response.get('stdout', '')) - sys.stderr.write(response.get('stderr', '')) - return response.get('returncode', 0) - - -if __name__ == '__main__': - sys.exit(main(sys.argv)) diff --git a/tests/software_config/heat_config_notify.py b/tests/software_config/heat_config_notify.py deleted file mode 120000 index 3dcf1f9..0000000 --- a/tests/software_config/heat_config_notify.py +++ /dev/null @@ -1 +0,0 @@ -../../hot/software-config/elements/heat-config/bin/heat-config-notify
\ No newline at end of file diff --git a/tests/software_config/hook-fake.py b/tests/software_config/hook-fake.py deleted file mode 100755 index 1f3e074..0000000 --- a/tests/software_config/hook-fake.py +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/env python -# -# 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. -''' -A fake heat-config hook for unit testing the 55-heat-config -os-refresh-config script. -''' - -import json -import os -import sys - - -def main(argv=sys.argv): - c = json.load(sys.stdin) - - inputs = {} - for input in c['inputs']: - inputs[input['name']] = input.get('value', '') - - response = {} - - # populate outputs from inputs of the same name - for output in c.get('outputs') or []: - output_name = output['name'] - response[output_name] = inputs.get(output_name, '') - - # populate deploy outputs from the inputs of the same name - response.update({ - 'deploy_stdout': inputs.get('deploy_stdout', 'stdout'), - 'deploy_stderr': inputs.get('deploy_stderr', 'stderr'), - 'deploy_status_code': inputs.get('deploy_status_code', '0'), - }) - - # write out stdin and stdout json for test asserts - stdin_path = os.path.join( - os.path.dirname(os.path.realpath(__file__)), '%s.stdin' % c['group']) - stdout_path = os.path.join( - os.path.dirname(os.path.realpath(__file__)), '%s.stdout' % c['group']) - - with open(stdin_path, 'w') as f: - json.dump(c, f) - f.flush() - with open(stdout_path, 'w') as f: - json.dump(response, f) - f.flush() - json.dump(response, sys.stdout) - -if __name__ == '__main__': - sys.exit(main(sys.argv)) diff --git a/tests/software_config/hook_kubelet.py b/tests/software_config/hook_kubelet.py deleted file mode 120000 index cb59984..0000000 --- a/tests/software_config/hook_kubelet.py +++ /dev/null @@ -1 +0,0 @@ -../../hot/software-config/elements/heat-config-kubelet/install.d/hook-kubelet.py
\ No newline at end of file diff --git a/tests/software_config/test_heat_config.py b/tests/software_config/test_heat_config.py deleted file mode 100644 index 9fb3f1b..0000000 --- a/tests/software_config/test_heat_config.py +++ /dev/null @@ -1,272 +0,0 @@ -# -# 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 copy -import json -import os -import shutil -import tempfile - -import fixtures -from testtools import matchers - -from tests.software_config import common - - -class HeatConfigTest(common.RunScriptTest): - - fake_hooks = ['cfn-init', 'chef', 'puppet', 'salt', 'script', - 'apply-config', 'hiera', 'json-file'] - - data = [ - { - 'id': '1111', - 'group': 'chef', - 'inputs': [{ - 'name': 'deploy_signal_id', - 'value': 'mock://192.0.2.2/foo' - }], - 'config': 'one' - }, { - 'id': '2222', - 'group': 'cfn-init', - 'inputs': [], - 'config': 'two' - }, { - 'id': '3333', - 'group': 'salt', - 'inputs': [{'name': 'foo', 'value': 'bar'}], - 'outputs': [{'name': 'foo'}], - 'config': 'three' - }, { - 'id': '4444', - 'group': 'puppet', - 'inputs': [], - 'config': 'four' - }, { - 'id': '5555', - 'group': 'script', - 'inputs': [{ - 'name': 'deploy_status_code', 'value': '-1' - }, { - 'name': 'deploy_stderr', 'value': 'A bad thing happened' - }, { - 'name': 'deploy_signal_id', - 'value': 'mock://192.0.2.3/foo' - }], - 'config': 'five' - }, { - 'id': '6666', - 'group': 'apply-config', - 'inputs': [{'name': 'foo', 'value': 'bar'}], - 'config': 'six' - }, { - 'id': '7777', - 'group': 'hiera', - 'inputs': [], - 'config': 'seven' - }, { - 'id': '8888', - 'group': 'json-file', - 'inputs': [], - 'config': 'eight' - }, { - 'id': '9999', - 'group': 'no-such-hook', - 'inputs': [], - 'config': 'nine' - }] - - outputs = { - 'chef': { - 'deploy_status_code': '0', - 'deploy_stderr': 'stderr', - 'deploy_stdout': 'stdout' - }, - 'cfn-init': { - 'deploy_status_code': '0', - 'deploy_stderr': 'stderr', - 'deploy_stdout': 'stdout' - }, - 'salt': { - 'deploy_status_code': '0', - 'deploy_stderr': 'stderr', - 'deploy_stdout': 'stdout', - 'foo': 'bar' - }, - 'puppet': { - 'deploy_status_code': '0', - 'deploy_stderr': 'stderr', - 'deploy_stdout': 'stdout' - }, - 'script': { - 'deploy_status_code': '-1', - 'deploy_stderr': 'A bad thing happened', - 'deploy_stdout': 'stdout' - }, - 'hiera': { - 'deploy_status_code': '0', - 'deploy_stderr': 'stderr', - 'deploy_stdout': 'stdout' - }, - 'json-file': { - 'deploy_status_code': '0', - 'deploy_stderr': 'stderr', - 'deploy_stdout': 'stdout' - }, - 'apply-config': { - 'deploy_status_code': '0', - 'deploy_stderr': 'stderr', - 'deploy_stdout': 'stdout' - } - } - - def setUp(self): - super(HeatConfigTest, self).setUp() - - self.fake_hook_path = self.relative_path(__file__, 'hook-fake.py') - - self.heat_config_path = self.relative_path( - __file__, - '../..', - 'hot/software-config/elements', - 'heat-config/os-refresh-config/configure.d/55-heat-config') - - self.hooks_dir = self.useFixture(fixtures.TempDir()) - self.deployed_dir = self.useFixture(fixtures.TempDir()) - - with open(self.fake_hook_path) as f: - fake_hook = f.read() - - for hook in self.fake_hooks: - hook_name = self.hooks_dir.join(hook) - with open(hook_name, 'w') as f: - os.utime(hook_name, None) - f.write(fake_hook) - f.flush() - os.chmod(hook_name, 0o755) - self.env = os.environ.copy() - - def write_config_file(self, data): - config_file = tempfile.NamedTemporaryFile() - config_file.write(json.dumps(data)) - config_file.flush() - return config_file - - def run_heat_config(self, data): - with self.write_config_file(data) as config_file: - - self.env.update({ - 'HEAT_CONFIG_HOOKS': self.hooks_dir.join(), - 'HEAT_CONFIG_DEPLOYED': self.deployed_dir.join(), - 'HEAT_SHELL_CONFIG': config_file.name - }) - returncode, stdout, stderr = self.run_cmd( - [self.heat_config_path], self.env) - - self.assertEqual(0, returncode, stderr) - - def test_hooks_exist(self): - self.assertThat( - self.hooks_dir.join('no-such-hook'), - matchers.Not(matchers.FileExists())) - - for hook in self.fake_hooks: - hook_path = self.hooks_dir.join(hook) - self.assertThat(hook_path, matchers.FileExists()) - - def test_run_heat_config(self): - - self.run_heat_config(self.data) - - for config in self.data: - hook = config['group'] - stdin_path = self.hooks_dir.join('%s.stdin' % hook) - stdout_path = self.hooks_dir.join('%s.stdout' % hook) - deployed_file = self.deployed_dir.join('%s.json' % config['id']) - - if hook == 'no-such-hook': - self.assertThat( - stdin_path, matchers.Not(matchers.FileExists())) - self.assertThat( - stdout_path, matchers.Not(matchers.FileExists())) - continue - - self.assertThat(stdin_path, matchers.FileExists()) - self.assertThat(stdout_path, matchers.FileExists()) - - # parsed stdin should match the config item - self.assertEqual(config, - self.json_from_file(stdin_path)) - - # parsed stdin should match the written deployed file - self.assertEqual(config, - self.json_from_file(deployed_file)) - - self.assertEqual(self.outputs[hook], - self.json_from_file(stdout_path)) - - # clean up files in preparation for second run - os.remove(stdin_path) - os.remove(stdout_path) - - # run again with no changes, assert no new files - self.run_heat_config(self.data) - for config in self.data: - hook = config['group'] - stdin_path = self.hooks_dir.join('%s.stdin' % hook) - stdout_path = self.hooks_dir.join('%s.stdout' % hook) - - self.assertThat( - stdin_path, matchers.Not(matchers.FileExists())) - self.assertThat( - stdout_path, matchers.Not(matchers.FileExists())) - - # run again changing the puppet config - data = copy.deepcopy(self.data) - for config in data: - if config['id'] == '4444': - config['id'] = '44444444' - self.run_heat_config(data) - for config in self.data: - hook = config['group'] - stdin_path = self.hooks_dir.join('%s.stdin' % hook) - stdout_path = self.hooks_dir.join('%s.stdout' % hook) - - if hook == 'puppet': - self.assertThat(stdin_path, matchers.FileExists()) - self.assertThat(stdout_path, matchers.FileExists()) - else: - self.assertThat( - stdin_path, matchers.Not(matchers.FileExists())) - self.assertThat( - stdout_path, matchers.Not(matchers.FileExists())) - - # run again with a different deployed_dir - old_deployed_dir = self.deployed_dir - self.env['HEAT_CONFIG_DEPLOYED_OLD'] = old_deployed_dir.join() - self.deployed_dir = self.useFixture(fixtures.TempDir()) - # make sure the new deployed_dir doesn't exist to trigger the migration - shutil.rmtree(self.deployed_dir.join()) - - self.run_heat_config(data) - for config in self.data: - hook = config['group'] - if hook == 'no-such-hook': - continue - deployed_file = self.deployed_dir.join('%s.json' % config['id']) - old_deployed_file = old_deployed_dir.join('%s.json' % config['id']) - self.assertEqual(config, - self.json_from_file(deployed_file)) - self.assertThat( - old_deployed_file, matchers.Not(matchers.FileExists())) diff --git a/tests/software_config/test_heat_config_docker_compose.py b/tests/software_config/test_heat_config_docker_compose.py deleted file mode 100644 index 358ed6f..0000000 --- a/tests/software_config/test_heat_config_docker_compose.py +++ /dev/null @@ -1,117 +0,0 @@ -# -# 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 json -import os -import tempfile - -import fixtures -import yaml - -from tests.software_config import common - - -class HeatConfigDockerComposeORCTest(common.RunScriptTest): - - fake_hooks = ['docker-compose'] - - data = [ - { - "name": "abcdef001", - "group": "docker-compose", - "inputs": {}, - "config": { - "web": { - "image": "nginx", - "links": [ - "db" - ], - "ports": [ - "8000:8000" - ] - }, - "db": { - "image": "redis" - } - } - }, - { - "name": "abcdef002", - "group": "docker-compose", - "inputs": {}, - "config": { - "web": { - "image": "httpd", - "links": [ - "db" - ], - "ports": [ - "80:8001" - ] - }, - "db": { - "image": "postgress" - } - } - } - ] - - def setUp(self): - super(HeatConfigDockerComposeORCTest, self).setUp() - - self.fake_hook_path = self.relative_path(__file__, 'hook-fake.py') - self.heat_config_docker_compose_path = self.relative_path( - __file__, - '../..', - 'hot/software-config/elements', - 'heat-config-docker-compose/os-refresh-config/configure.d/' - '50-heat-config-docker-compose') - - self.docker_compose_dir = self.useFixture(fixtures.TempDir()) - - with open(self.fake_hook_path) as f: - fake_hook = f.read() - - for hook in self.fake_hooks: - hook_name = self.docker_compose_dir.join(hook) - with open(hook_name, 'w') as f: - os.utime(hook_name, None) - f.write(fake_hook) - f.flush() - os.chmod(hook_name, 0o755) - - def write_config_file(self, data): - config_file = tempfile.NamedTemporaryFile() - config_file.write(json.dumps(data)) - config_file.flush() - return config_file - - def test_run_heat_config(self): - with self.write_config_file(self.data) as config_file: - env = os.environ.copy() - env.update({ - 'HEAT_DOCKER_COMPOSE_WORKING': self.docker_compose_dir.join(), - 'HEAT_SHELL_CONFIG': config_file.name - }) - - returncode, stdout, stderr = self.run_cmd( - [self.heat_config_docker_compose_path], env) - - self.assertEqual(0, returncode, stderr) - - compose_yml = self.docker_compose_dir.join( - 'abcdef001/docker-compose.yml') - with open(compose_yml) as f: - self.assertEqual(yaml.safe_dump( - self.data[0].get('config'), - default_flow_style=False), f.read()) diff --git a/tests/software_config/test_heat_config_kubelet.py b/tests/software_config/test_heat_config_kubelet.py deleted file mode 100644 index 03d2eed..0000000 --- a/tests/software_config/test_heat_config_kubelet.py +++ /dev/null @@ -1,147 +0,0 @@ -# -# 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 json -import os -import tempfile - -import fixtures -from testtools import matchers - -from tests.software_config import common - - -class HeatConfigKubeletORCTest(common.RunScriptTest): - - fake_hooks = ['kubelet'] - - data = [{ - "id": "abcdef001", - "group": "kubelet", - "name": "mysql", - "config": { - "version": "v1beta2", - "volumes": [{ - "name": "mariadb-data" - }], - "containers": [{ - "image": "mariadb_image", - "volumeMounts": [{ - "mountPath": "/var/lib/mysql", - "name": "mariadb-data" - }], - "name": "mariadb", - "env": [{ - "name": "DB_ROOT_PASSWORD", - "value": "mariadb_password" - }], - "ports": [{ - "containerPort": 3306 - }] - }]} - }, { - "id": "abcdef002", - "group": "kubelet", - "name": "rabbitmq", - "config": { - "version": "v1beta2", - "containers": [{ - "image": "rabbitmq_image", - "name": "rabbitmq", - "ports": [{ - "containerPort": 5672 - }] - }] - } - }, { - "id": "abcdef003", - "group": "kubelet", - "name": "heat_api_engine", - "config": { - "version": "v1beta2", - "containers": [{ - "image": "heat_engine_image", - "name": "heat-engine", - "env": [{ - "name": "DB_ROOT_PASSWORD", - "value": "mariadb_password" - }, { - "name": "HEAT_DB_PASSWORD", - "value": "heatdb_password" - }, { - "name": "HEAT_KEYSTONE_PASSWORD", - "value": "password" - }] - }, { - "image": "heat_api_image", - "name": "heat-api", - "ports": [{ - "containerPort": 8004 - }] - }] - } - }] - - def setUp(self): - super(HeatConfigKubeletORCTest, self).setUp() - - self.fake_hook_path = self.relative_path(__file__, 'hook-fake.py') - - self.heat_config_kubelet_path = self.relative_path( - __file__, - '../..', - 'hot/software-config/elements', - 'heat-config-kubelet/os-refresh-config/configure.d/' - '50-heat-config-kubelet') - - self.manifests_dir = self.useFixture(fixtures.TempDir()) - - with open(self.fake_hook_path) as f: - fake_hook = f.read() - - for hook in self.fake_hooks: - hook_name = self.manifests_dir.join(hook) - with open(hook_name, 'w') as f: - os.utime(hook_name, None) - f.write(fake_hook) - f.flush() - os.chmod(hook_name, 0o755) - - def write_config_file(self, data): - config_file = tempfile.NamedTemporaryFile() - config_file.write(json.dumps(data)) - config_file.flush() - return config_file - - def test_run_heat_config(self): - - with self.write_config_file(self.data) as config_file: - - env = os.environ.copy() - env.update({ - 'HEAT_KUBELET_MANIFESTS': self.manifests_dir.join(), - 'HEAT_SHELL_CONFIG': config_file.name - }) - returncode, stdout, stderr = self.run_cmd( - [self.heat_config_kubelet_path], env) - - self.assertEqual(0, returncode, stderr) - - for config in self.data: - manifest_name = '%s.json' % config['id'] - manifest_path = self.manifests_dir.join(manifest_name) - self.assertThat(manifest_path, matchers.FileExists()) - - # manifest file should match manifest config - self.assertEqual(config['config'], - self.json_from_file(manifest_path)) diff --git a/tests/software_config/test_heat_config_notify.py b/tests/software_config/test_heat_config_notify.py deleted file mode 100644 index c3d5d20..0000000 --- a/tests/software_config/test_heat_config_notify.py +++ /dev/null @@ -1,209 +0,0 @@ -# -# 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 cStringIO -import json -import tempfile - -import fixtures -import mock - -from tests.software_config import common -from tests.software_config import heat_config_notify as hcn - - -class HeatConfigNotifyTest(common.RunScriptTest): - - data_signal_id = { - 'id': '5555', - 'group': 'script', - 'inputs': [{ - 'name': 'deploy_signal_id', - 'value': 'mock://192.0.2.3/foo' - }], - 'config': 'five' - } - - data_signal_id_put = { - 'id': '5555', - 'group': 'script', - 'inputs': [{ - 'name': 'deploy_signal_id', - 'value': 'mock://192.0.2.3/foo' - }, { - 'name': 'deploy_signal_verb', - 'value': 'PUT' - }], - 'config': 'five' - } - - data_heat_signal = { - 'id': '5555', - 'group': 'script', - 'inputs': [{ - 'name': 'deploy_auth_url', - 'value': 'mock://192.0.2.3/auth' - }, { - 'name': 'deploy_user_id', - 'value': 'aaaa' - }, { - 'name': 'deploy_password', - 'value': 'password' - }, { - 'name': 'deploy_project_id', - 'value': 'bbbb' - }, { - 'name': 'deploy_stack_id', - 'value': 'cccc' - }, { - 'name': 'deploy_resource_name', - 'value': 'the_resource' - }], - 'config': 'five' - } - - def setUp(self): - super(HeatConfigNotifyTest, self).setUp() - self.deployed_dir = self.useFixture(fixtures.TempDir()) - hcn.init_logging = mock.MagicMock() - - def write_config_file(self, data): - config_file = tempfile.NamedTemporaryFile() - config_file.write(json.dumps(data)) - config_file.flush() - return config_file - - def test_notify_missing_file(self): - - signal_data = json.dumps({'foo': 'bar'}) - stdin = cStringIO.StringIO(signal_data) - - with self.write_config_file(self.data_signal_id) as config_file: - config_file_name = config_file.name - - self.assertEqual( - 1, hcn.main(['heat-config-notify', config_file_name], stdin)) - - def test_notify_missing_file_arg(self): - - signal_data = json.dumps({'foo': 'bar'}) - stdin = cStringIO.StringIO(signal_data) - - self.assertEqual( - 1, hcn.main(['heat-config-notify'], stdin)) - - def test_notify_signal_id(self): - requests = mock.MagicMock() - hcn.requests = requests - - requests.post.return_value = '[200]' - - signal_data = json.dumps({'foo': 'bar'}) - stdin = cStringIO.StringIO(signal_data) - - with self.write_config_file(self.data_signal_id) as config_file: - self.assertEqual( - 0, hcn.main(['heat-config-notify', config_file.name], stdin)) - - requests.post.assert_called_once_with( - 'mock://192.0.2.3/foo', - data=signal_data, - headers={'content-type': 'application/json'}) - - def test_notify_signal_id_put(self): - requests = mock.MagicMock() - hcn.requests = requests - - requests.post.return_value = '[200]' - - signal_data = json.dumps({'foo': 'bar'}) - stdin = cStringIO.StringIO(signal_data) - - with self.write_config_file(self.data_signal_id_put) as config_file: - self.assertEqual( - 0, hcn.main(['heat-config-notify', config_file.name], stdin)) - - requests.put.assert_called_once_with( - 'mock://192.0.2.3/foo', - data=signal_data, - headers={'content-type': 'application/json'}) - - def test_notify_signal_id_empty_data(self): - requests = mock.MagicMock() - hcn.requests = requests - - requests.post.return_value = '[200]' - - stdin = cStringIO.StringIO() - - with self.write_config_file(self.data_signal_id) as config_file: - self.assertEqual( - 0, hcn.main(['heat-config-notify', config_file.name], stdin)) - - requests.post.assert_called_once_with( - 'mock://192.0.2.3/foo', - data='{}', - headers={'content-type': 'application/json'}) - - def test_notify_signal_id_invalid_json_data(self): - requests = mock.MagicMock() - hcn.requests = requests - - requests.post.return_value = '[200]' - - stdin = cStringIO.StringIO('{{{"hi') - - with self.write_config_file(self.data_signal_id) as config_file: - self.assertEqual( - 0, hcn.main(['heat-config-notify', config_file.name], stdin)) - - requests.post.assert_called_once_with( - 'mock://192.0.2.3/foo', - data='{}', - headers={'content-type': 'application/json'}) - - def test_notify_heat_signal(self): - ksclient = mock.MagicMock() - hcn.ksclient = ksclient - ks = mock.MagicMock() - ksclient.Client.return_value = ks - - heatclient = mock.MagicMock() - hcn.heatclient = heatclient - heat = mock.MagicMock() - heatclient.Client.return_value = heat - - signal_data = json.dumps({'foo': 'bar'}) - stdin = cStringIO.StringIO(signal_data) - - ks.service_catalog.url_for.return_value = 'mock://192.0.2.3/heat' - heat.resources.signal.return_value = 'all good' - - with self.write_config_file(self.data_heat_signal) as config_file: - self.assertEqual( - 0, hcn.main(['heat-config-notify', config_file.name], stdin)) - - ksclient.Client.assert_called_once_with( - auth_url='mock://192.0.2.3/auth', - user_id='aaaa', - password='password', - project_id='bbbb') - ks.service_catalog.url_for.assert_called_once_with( - service_type='orchestration', endpoint_type='publicURL') - - heatclient.Client.assert_called_once_with( - '1', 'mock://192.0.2.3/heat', token=ks.auth_token) - heat.resources.signal.assert_called_once_with( - 'cccc', - 'the_resource', - data={'foo': 'bar'}) diff --git a/tests/software_config/test_hook_ansible.py b/tests/software_config/test_hook_ansible.py deleted file mode 100644 index 6849472..0000000 --- a/tests/software_config/test_hook_ansible.py +++ /dev/null @@ -1,225 +0,0 @@ -# Copyright 2015 NEC Corporation. All rights reserved. -# -# 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 json -import os - -import fixtures - -from tests.software_config import common - - -class HookAnsibleTest(common.RunScriptTest): - - data = { - 'id': '1234', - 'name': 'fake_resource_name', - 'group': 'ansible', - 'options': {}, - 'inputs': [ - {'name': 'foo', 'value': 'bar'}, - {'name': 'another', 'value': 'input'} - ], - 'config': 'the ansible playbook' - } - - data_tags = { - 'id': '1234', - 'name': 'fake_resource_name_tags', - 'group': 'ansible', - 'options': {'tags': 'abc,def'}, - 'inputs': [ - {'name': 'foo', 'value': 'bar'}, - {'name': 'another', 'value': 'input'} - ], - 'config': 'the ansible playbook' - } - - data_modulepath = data.copy() - data_modulepath.update({ - 'options': {'modulepath': '/opt/ansible:/usr/share/ansible'}, - }) - - data_tags_modulepath = data.copy() - data_tags_modulepath.update({ - 'options': {'modulepath': '/opt/ansible:/usr/share/ansible', - 'tags': 'abc,def'}, - }) - - def setUp(self): - super(HookAnsibleTest, self).setUp() - self.hook_path = self.relative_path( - __file__, - '../..', - 'hot/software-config/elements', - 'heat-config-ansible/install.d/hook-ansible.py') - - self.fake_tool_path = self.relative_path( - __file__, - 'config-tool-fake.py') - - self.working_dir = self.useFixture(fixtures.TempDir()) - self.outputs_dir = self.useFixture(fixtures.TempDir()) - self.test_state_path = self.outputs_dir.join('test_state.json') - self.test_inventory = "localhost test_var=123," - - self.env = os.environ.copy() - self.env.update({ - 'HEAT_ANSIBLE_WORKING': self.working_dir.join(), - 'HEAT_ANSIBLE_OUTPUTS': self.outputs_dir.join(), - 'HEAT_ANSIBLE_CMD': self.fake_tool_path, - 'TEST_STATE_PATH': self.test_state_path - }) - - def test_hook(self): - self._hook_run() - - def test_hook_tags(self): - self._hook_run(data=self.data_tags, options=['--tags', 'abc,def']) - - def test_hook_modulepath(self): - self._hook_run(data=self.data_modulepath, - options=['--module-path', - '/opt/ansible:/usr/share/ansible']) - - def test_hook_tags_modulepath(self): - self._hook_run(data=self.data_tags_modulepath, - options=['--module-path', - '/opt/ansible:/usr/share/ansible', - '--tags', 'abc,def']) - - def _hook_run(self, data=None, options=None): - - self.env.update({ - 'TEST_RESPONSE': json.dumps({ - 'stdout': 'ansible success', - 'stderr': 'thing happened', - }), - }) - returncode, stdout, stderr = self.run_cmd( - [self.hook_path], self.env, json.dumps(data or self.data)) - - self.assertEqual(0, returncode, stderr) - self.assertEqual({ - 'deploy_stdout': 'ansible success', - 'deploy_stderr': 'thing happened', - 'deploy_status_code': 0, - }, json.loads(stdout)) - - state = self.json_from_file(self.test_state_path) - ansible_playbook = self.working_dir.join('1234_playbook.yaml') - vars_filename = self.working_dir.join('1234_variables.json') - - expected_args = [ - self.fake_tool_path, - '-i', - 'localhost,'] - if options: - expected_args += options - expected_args += [ - ansible_playbook, - '--extra-vars'] - expected_args.append('@%s' % vars_filename) - self.assertEqual(expected_args, state['args']) - - # Write 'variables' to file - variables = self.json_from_file(vars_filename) - self.assertEqual('bar', variables['foo']) - self.assertEqual('input', variables['another']) - self.assertEqual(self.outputs_dir.join('1234'), - variables['heat_outputs_path']) - - # Write the executable 'config' to file - with open(ansible_playbook) as f: - self.assertEqual('the ansible playbook', f.read()) - - def test_hook_inventory(self): - - self.env.update({ - 'HEAT_ANSIBLE_INVENTORY': self.test_inventory, - 'TEST_RESPONSE': json.dumps({ - 'stdout': 'ansible success', - 'stderr': 'thing happened', - }), - }) - returncode, stdout, stderr = self.run_cmd( - [self.hook_path], self.env, json.dumps(self.data)) - - self.assertEqual(0, returncode, stderr) - self.assertEqual({ - 'deploy_stdout': 'ansible success', - 'deploy_stderr': 'thing happened', - 'deploy_status_code': 0, - }, json.loads(stdout)) - - state = self.json_from_file(self.test_state_path) - ansible_playbook = self.working_dir.join('1234_playbook.yaml') - vars_filename = self.working_dir.join('1234_variables.json') - - self.assertEqual( - [ - self.fake_tool_path, - '-i', - self.test_inventory, - ansible_playbook, - '--extra-vars', - '@%s' % vars_filename - ], - state['args']) - - def test_hook_ansible_failed(self): - - self.env.update({ - 'TEST_RESPONSE': json.dumps({ - 'stdout': 'ansible failed', - 'stderr': 'bad thing happened', - 'returncode': 4 - }), - }) - returncode, stdout, stderr = self.run_cmd( - [self.hook_path], self.env, json.dumps(self.data)) - - self.assertEqual(0, returncode, stderr) - self.assertEqual({ - 'deploy_stdout': 'ansible failed', - 'deploy_stderr': 'bad thing happened', - 'deploy_status_code': 4, - }, json.loads(stdout)) - - state = self.json_from_file(self.test_state_path) - ansible_playbook = self.working_dir.join('1234_playbook.yaml') - vars_filename = self.working_dir.join('1234_variables.json') - - self.assertEqual( - [ - self.fake_tool_path, - '-i', - 'localhost,', - ansible_playbook, - '--extra-vars', - '@%s' % vars_filename - ], - state['args']) - - # Write 'variables' to file - variables = self.json_from_file(vars_filename) - self.assertEqual('bar', variables['foo']) - self.assertEqual('input', variables['another']) - self.assertEqual(self.outputs_dir.join('1234'), - variables['heat_outputs_path']) - - # Write the executable 'config' to file - with open(ansible_playbook) as f: - self.assertEqual('the ansible playbook', f.read()) diff --git a/tests/software_config/test_hook_apply_config.py b/tests/software_config/test_hook_apply_config.py deleted file mode 100644 index 5aa27d7..0000000 --- a/tests/software_config/test_hook_apply_config.py +++ /dev/null @@ -1,81 +0,0 @@ -# -# 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 fixtures -import json -import logging -import os -import tempfile -import yaml - -from tests.software_config import common - -log = logging.getLogger('test_hook_apply_config') - - -class HookApplyConfigTest(common.RunScriptTest): - - data = { - 'id': 'test_apply_config', - 'name': 'fake_resource_name', - 'group': 'apply-config', - 'config': {'foo': 'bar'} - } - - def setUp(self): - super(HookApplyConfigTest, self).setUp() - self.hook_path = self.relative_path( - __file__, - '../..', - 'hot/software-config/elements', - 'heat-config-apply-config/install.d/hook-apply-config.py') - - self.metadata_dir = self.useFixture(fixtures.TempDir()) - self.templates_dir = self.useFixture(fixtures.TempDir()) - tmp_dir = tempfile.NamedTemporaryFile(mode='w', delete=False).name - os.unlink(tmp_dir) - self.tmp_file = os.path.basename(tmp_dir) - self.out_dir = self.templates_dir.join('tmp') - - self.metadata = self.metadata_dir.join(self.tmp_file) - - self.env = os.environ.copy() - self.env.update({ - 'OS_CONFIG_FILES': self.metadata, - 'OS_CONFIG_APPLIER_TEMPLATES': self.templates_dir.join(), - }) - - # our fake metadata file - with open(self.metadata, "w+") as md: - md.write(json.dumps({'foo': 'bar'})) - - # This is our fake template root we use to verify os-apply-config - # works as expected - os.mkdir(self.out_dir) - with open(os.path.join(self.out_dir, self.tmp_file), "w+") as template: - template.write("foo={{foo}}") - - def test_hook(self): - - returncode, stdout, stderr = self.run_cmd( - [self.hook_path], self.env, json.dumps(self.data)) - - self.assertEqual(0, returncode, stderr) - ret = yaml.safe_load(stdout) - self.assertIsNotNone(ret['deploy_stderr']) - self.assertEqual('', ret['deploy_stdout']) - self.assertEqual(0, ret['deploy_status_code']) - f = os.path.join('/tmp', self.tmp_file) - with open(f) as out_file: - self.assertEqual('foo=bar', out_file.read()) - os.unlink(f) diff --git a/tests/software_config/test_hook_atomic.py b/tests/software_config/test_hook_atomic.py deleted file mode 100644 index 95b068c..0000000 --- a/tests/software_config/test_hook_atomic.py +++ /dev/null @@ -1,115 +0,0 @@ -# -# 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 json -import os - -import fixtures - -from tests.software_config import common - - -class HookAtomicTest(common.RunScriptTest): - data = { - "id": "abcdef001", - "group": "atomic", - "inputs": [], - "config": { - "command": "install", - "image": "imain/atomic-install-rabbitmq" - } - } - - def setUp(self): - super(HookAtomicTest, self).setUp() - self.hook_path = self.relative_path( - __file__, - '../..', - 'hot/software-config/heat-container-agent', - 'scripts/hooks/atomic') - - self.fake_tool_path = self.relative_path( - __file__, - 'config-tool-fake.py') - - self.working_dir = self.useFixture(fixtures.TempDir()) - self.outputs_dir = self.useFixture(fixtures.TempDir()) - self.test_state_path = self.outputs_dir.join('test_state.json') - - self.env = os.environ.copy() - self.env.update({ - 'HEAT_ATOMIC_WORKING': self.working_dir.join(), - 'HEAT_ATOMIC_CMD': self.fake_tool_path, - 'TEST_STATE_PATH': self.test_state_path, - }) - - def test_hook(self): - - self.env.update({ - 'TEST_RESPONSE': json.dumps({ - 'stdout': 'Downloading xxx', - 'stderr': '' - }) - }) - returncode, stdout, stderr = self.run_cmd( - [self.hook_path], self.env, json.dumps(self.data)) - - self.assertEqual(0, returncode, stderr) - - self.assertEqual({ - 'deploy_stdout': 'Downloading xxx', - 'deploy_stderr': '', - 'deploy_status_code': 0 - }, json.loads(stdout)) - - state = self.json_from_file(self.test_state_path) - self.assertEqual( - [ - self.fake_tool_path, - 'install', - 'imain/atomic-install-rabbitmq', - '-n abcdef001', - '' - ], - state['args']) - - def test_hook_failed(self): - - self.env.update({ - 'TEST_RESPONSE': json.dumps({ - 'stdout': '', - 'stderr': 'Container exists...', - 'returncode': 1 - }) - }) - returncode, stdout, stderr = self.run_cmd( - [self.hook_path], self.env, json.dumps(self.data)) - - self.assertEqual(0, returncode, stderr) - - self.assertEqual({ - 'deploy_stdout': '', - 'deploy_stderr': 'Container exists...', - 'deploy_status_code': 1 - }, json.loads(stdout)) - - state = self.json_from_file(self.test_state_path) - self.assertEqual( - [ - self.fake_tool_path, - 'install', - 'imain/atomic-install-rabbitmq', - '-n abcdef001', - '' - ], - state['args']) diff --git a/tests/software_config/test_hook_cfn_init.py b/tests/software_config/test_hook_cfn_init.py deleted file mode 100644 index 8bb9275..0000000 --- a/tests/software_config/test_hook_cfn_init.py +++ /dev/null @@ -1,112 +0,0 @@ -# -# 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 json -import os - -import fixtures - -from tests.software_config import common - - -class HookCfnInitTest(common.RunScriptTest): - - data = { - 'group': 'cfn-init', - 'inputs': [], - 'config': {'foo': 'bar'} - } - - def setUp(self): - super(HookCfnInitTest, self).setUp() - self.hook_path = self.relative_path( - __file__, - '../..', - 'hot/software-config/elements', - 'heat-config-cfn-init/install.d/hook-cfn-init.py') - - self.fake_tool_path = self.relative_path( - __file__, - 'config-tool-fake.py') - - self.metadata_dir = self.useFixture(fixtures.TempDir()) - # use the temp dir to store the fake config tool state too - self.test_state_path = self.metadata_dir.join('test_state.json') - self.env = os.environ.copy() - self.env.update({ - 'HEAT_CFN_INIT_LAST_METADATA_DIR': self.metadata_dir.join(), - 'HEAT_CFN_INIT_CMD': self.fake_tool_path, - 'TEST_STATE_PATH': self.test_state_path, - }) - - def test_hook(self): - - self.env.update({ - 'TEST_RESPONSE': json.dumps({ - 'stdout': 'cfn-init success', - 'stderr': 'thing happened' - }), - }) - returncode, stdout, stderr = self.run_cmd( - [self.hook_path], self.env, json.dumps(self.data)) - - self.assertEqual(0, returncode, stderr) - self.assertEqual({ - 'deploy_stdout': 'cfn-init success', - 'deploy_stderr': 'thing happened', - 'deploy_status_code': 0 - }, json.loads(stdout)) - - # assert last_metadata was written with cfn-init metadata - self.assertEqual( - {'AWS::CloudFormation::Init': {'foo': 'bar'}}, - self.json_from_file(self.metadata_dir.join('last_metadata'))) - - # assert cfn-init was called with no args - self.assertEqual( - [self.fake_tool_path], - self.json_from_file(self.test_state_path)['args']) - - def test_hook_cfn_init_failed(self): - - self.env.update({ - 'TEST_RESPONSE': json.dumps({ - 'stderr': 'bad thing happened', - 'returncode': 1 - }), - }) - returncode, stdout, stderr = self.run_cmd( - [self.hook_path], self.env, json.dumps(self.data)) - - self.assertEqual(0, returncode, stderr) - self.assertEqual({ - 'deploy_stdout': '', - 'deploy_stderr': 'bad thing happened', - 'deploy_status_code': 1 - }, json.loads(stdout)) - - self.assertEqual( - {'AWS::CloudFormation::Init': {'foo': 'bar'}}, - self.json_from_file(self.metadata_dir.join('last_metadata'))) - - # assert cfn-init was called with no args - self.assertEqual( - [self.fake_tool_path], - self.json_from_file(self.test_state_path)['args']) - - def test_hook_invalid_json(self): - - returncode, stdout, stderr = self.run_cmd( - [self.hook_path], self.env, "{::::") - - self.assertEqual(1, returncode, stderr) diff --git a/tests/software_config/test_hook_chef.py b/tests/software_config/test_hook_chef.py deleted file mode 100644 index 8322037..0000000 --- a/tests/software_config/test_hook_chef.py +++ /dev/null @@ -1,207 +0,0 @@ -# -# 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 copy -import imp -import json -import logging -import mock -import StringIO -import sys - -from tests.software_config import common - -log = logging.getLogger('test_hook_chef') - - -@mock.patch("os.chdir") -@mock.patch("os.makedirs") -@mock.patch('subprocess.Popen') -class HookChefTest(common.RunScriptTest): - - data = { - 'id': 'fake_stack', - 'name': 'fake_resource_name', - 'group': 'chef', - 'inputs': [ - {'name': 'fooval', 'value': {'bar': 'baz'}}, - {'name': 'barval', 'value': {'foo': 'biff'}}, - {'name': "deploy_server_id", 'value': 'foo'}, - {'name': "deploy_action", 'value': 'foo'}, - {'name': "deploy_stack_id", 'value': 'foo'}, - {'name': "deploy_resource_name", 'value': 'foo'}, - {'name': "deploy_signal_transport", 'value': 'foo'}, - {'name': "deploy_signal_id", 'value': 'foo'}, - {'name': "deploy_signal_verb", 'value': 'foo'} - ], - 'options': {}, - 'outputs': [ - {'name': 'first_output'}, - {'name': 'second_output'} - ], - 'config': None - } - - def setUp(self): - super(HookChefTest, self).setUp() - self.hook_path = self.relative_path( - __file__, - '../..', - 'hot/software-config/elements', - 'heat-config-chef/install.d/hook-chef.py') - sys.stdin = StringIO.StringIO() - sys.stdout = StringIO.StringIO() - - def tearDown(self): - super(HookChefTest, self).tearDown() - sys.stdin = sys.__stdin__ - sys.stdout = sys.__stdout__ - - def get_module(self): - try: - imp.acquire_lock() - return imp.load_source("hook_chef", self.hook_path) - finally: - imp.release_lock() - - def test_hook(self, mock_popen, mock_mkdirs, mock_chdir): - data = copy.deepcopy(self.data) - data['config'] = '["recipe[apache]"]' - hook_chef = self.get_module() - sys.stdin.write(json.dumps(data)) - sys.stdin.seek(0) - mock_subproc = mock.Mock() - mock_popen.return_value = mock_subproc - mock_subproc.communicate.return_value = ("out", "err") - mock_subproc.returncode = 0 - with mock.patch("os.fdopen", mock.mock_open()) as mfdopen: - with mock.patch("os.open", mock.mock_open()): - hook_chef.main(json.dumps(data)) - exp_node = { - 'barval': {'foo': 'biff'}, - 'fooval': {u'bar': u'baz'}, - 'run_list': [u'recipe[apache]'] - } - exp_node = json.dumps(exp_node, indent=4) - exp_cfg = ("log_level :debug\n" - "log_location STDOUT\n" - "local_mode true\n" - "chef_zero.enabled true\n" - "cookbook_path '/var/lib/heat-config/" - "heat-config-chef/kitchen/cookbooks'\n" - "role_path '/var/lib/heat-config/" - "heat-config-chef/kitchen/roles'\n" - "environment_path '/var/lib/heat-config/" - "heat-config-chef/kitchen/environments'\n" - "node_path '/var/lib/heat-config/" - "heat-config-chef/node'") - mfdopen.return_value.write.assert_any_call(exp_cfg) - mfdopen.return_value.write.assert_any_call(exp_node) - calls = [ - mock.call(['hostname', '-f'], env=mock.ANY, stderr=mock.ANY, - stdout=mock.ANY), - mock.call([ - 'chef-client', '-z', '--config', - '/var/lib/heat-config/heat-config-chef/client.rb', '-j', - '/var/lib/heat-config/heat-config-chef/node/out.json'], - env=mock.ANY, stderr=mock.ANY, stdout=mock.ANY) - ] - mock_popen.assert_has_calls(calls, any_order=True) - self.assertEqual({"deploy_status_code": 0, - "deploy_stdout": "out", - "deploy_stderr": "err"}, - json.loads(sys.stdout.getvalue())) - - def test_hook_with_kitchen(self, mock_popen, mock_mkdirs, mock_chdir): - data = copy.deepcopy(self.data) - data['config'] = '["recipe[apache]"]' - data['options'] = { - "kitchen": "https://github.com/fake.git", - "kitchen_path": "/opt/heat/chef/kitchen" - } - sys.stdin.write(json.dumps(data)) - hook_chef = self.get_module() - sys.stdin.seek(0) - mock_subproc = mock.Mock() - mock_popen.return_value = mock_subproc - mock_subproc.communicate.return_value = ("out", "err") - mock_subproc.returncode = 0 - with mock.patch("os.fdopen", mock.mock_open()) as mfdopen: - with mock.patch("os.open", mock.mock_open()): - hook_chef.main(json.dumps(data)) - exp_cfg = ("log_level :debug\n" - "log_location STDOUT\n" - "local_mode true\n" - "chef_zero.enabled true\n" - "cookbook_path '/opt/heat/chef/kitchen/" - "cookbooks'\n" - "role_path '/opt/heat/chef/kitchen/roles'\n" - "environment_path '/opt/heat/chef/kitchen/" - "environments'\n" - "node_path '/var/lib/heat-config/heat-config-chef" - "/node'") - mfdopen.return_value.write.assert_any_call(exp_cfg) - calls = [ - mock.call(['git', 'clone', "https://github.com/fake.git", - "/opt/heat/chef/kitchen"], env=mock.ANY, - stderr=mock.ANY, stdout=mock.ANY), - mock.call(['hostname', '-f'], env=mock.ANY, stderr=mock.ANY, - stdout=mock.ANY), - mock.call([ - 'chef-client', '-z', '--config', - '/var/lib/heat-config/heat-config-chef/client.rb', '-j', - '/var/lib/heat-config/heat-config-chef/node/out.json'], - env=mock.ANY, stderr=mock.ANY, stdout=mock.ANY) - ] - mock_popen.assert_has_calls(calls, any_order=True) - self.assertEqual({"deploy_status_code": 0, - "deploy_stdout": "out", - "deploy_stderr": "err"}, - json.loads(sys.stdout.getvalue())) - - def test_hook_environment(self, mock_popen, mock_mkdirs, mock_chdir): - data = copy.deepcopy(self.data) - data['config'] = '["recipe[apache]"]' - data['inputs'].append({'name': 'environment', - 'value': 'production'}) - hook_chef = self.get_module() - sys.stdin.write(json.dumps(data)) - sys.stdin.seek(0) - mock_subproc = mock.Mock() - mock_popen.return_value = mock_subproc - mock_subproc.communicate.return_value = ("out", "err") - mock_subproc.returncode = 0 - with mock.patch("os.fdopen", mock.mock_open()) as mfdopen: - with mock.patch("os.open", mock.mock_open()): - hook_chef.main(json.dumps(data)) - exp_node = { - 'barval': {'foo': 'biff'}, - 'fooval': {u'bar': u'baz'}, - 'run_list': [u'recipe[apache]'] - } - exp_node = json.dumps(exp_node, indent=4) - exp_cfg = ("log_level :debug\n" - "log_location STDOUT\n" - "local_mode true\n" - "chef_zero.enabled true\n" - "cookbook_path '/var/lib/heat-config/" - "heat-config-chef/kitchen/cookbooks'\n" - "role_path '/var/lib/heat-config/" - "heat-config-chef/kitchen/roles'\n" - "environment_path '/var/lib/heat-config/" - "heat-config-chef/kitchen/environments'\n" - "environment 'production'\n" - "node_path '/var/lib/heat-config/" - "heat-config-chef/node'") - mfdopen.return_value.write.assert_any_call(exp_cfg) - mfdopen.return_value.write.assert_any_call(exp_node) diff --git a/tests/software_config/test_hook_docker_cmd.py b/tests/software_config/test_hook_docker_cmd.py deleted file mode 100644 index 354c831..0000000 --- a/tests/software_config/test_hook_docker_cmd.py +++ /dev/null @@ -1,267 +0,0 @@ -# -# 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 copy -import json -import os -import tempfile - -import fixtures -from testtools import matchers - -from tests.software_config import common - - -class HookDockerCmdTest(common.RunScriptTest): - data = { - "name": "abcdef001", - "group": "docker-cmd", - "config": { - "web": { - "name": "x", - "image": "xxx" - }, - "db": { - "name": "y", - "image": "xxx", - "net": "host", - "restart": "always", - "privileged": True, - "user": "root", - "volumes": [ - "/run:/run", - "db:/var/lib/db" - ], - "environment": [ - "KOLLA_CONFIG_STRATEGY=COPY_ALWAYS", - "FOO=BAR" - ] - - } - } - } - - def setUp(self): - super(HookDockerCmdTest, self).setUp() - self.hook_path = self.relative_path( - __file__, - '../..', - 'hot/software-config/elements', - 'heat-config-docker-cmd/install.d/hook-docker-cmd.py') - - self.cleanup_path = self.relative_path( - __file__, - '../..', - 'hot/software-config/elements/heat-config-docker-cmd/', - 'os-refresh-config/configure.d/50-heat-config-docker-cmd') - - self.fake_tool_path = self.relative_path( - __file__, - 'config-tool-fake.py') - - self.working_dir = self.useFixture(fixtures.TempDir()) - self.outputs_dir = self.useFixture(fixtures.TempDir()) - self.test_state_path = self.outputs_dir.join('test_state.json') - - self.env = os.environ.copy() - self.env.update({ - 'HEAT_DOCKER_CMD_WORKING': self.working_dir.join(), - 'HEAT_DOCKER_CMD': self.fake_tool_path, - 'TEST_STATE_PATH': self.test_state_path, - }) - - def test_hook(self): - - self.env.update({ - 'TEST_RESPONSE': json.dumps({ - 'stdout': '', - 'stderr': 'Creating abcdef001_db_1...' - }) - }) - returncode, stdout, stderr = self.run_cmd( - [self.hook_path], self.env, json.dumps(self.data)) - - self.assertEqual(0, returncode, stderr) - - self.assertEqual({ - 'deploy_stdout': '', - 'deploy_stderr': 'Creating abcdef001_db_1...\n' - 'Creating abcdef001_db_1...', - 'deploy_status_code': 0 - }, json.loads(stdout)) - - state_0 = self.json_from_file(self.test_state_path) - state_1 = self.json_from_file('%s_1' % self.test_state_path) - self.assertEqual([ - self.fake_tool_path, - 'run', - '--detach=true', - '--name', - 'abcdef001__db', - '--env=KOLLA_CONFIG_STRATEGY=COPY_ALWAYS', - '--env=FOO=BAR', - '--net=host', - '--privileged=true', - '--restart=always', - '--user=root', - '--volume=/run:/run', - '--volume=db:/var/lib/db', - 'xxx' - ], state_0['args']) - self.assertEqual([ - self.fake_tool_path, - 'run', - '--detach=true', - '--name', - 'abcdef001__web', - 'xxx' - ], state_1['args']) - - def test_hook_failed(self): - - self.env.update({ - 'TEST_RESPONSE': json.dumps({ - 'stdout': '', - 'stderr': 'Error: image library/xxx:latest not found', - 'returncode': 1 - }) - }) - returncode, stdout, stderr = self.run_cmd( - [self.hook_path], self.env, json.dumps(self.data)) - - self.assertEqual({ - 'deploy_stdout': '', - 'deploy_stderr': 'Error: image library/xxx:latest not found\n' - 'Error: image library/xxx:latest not found', - 'deploy_status_code': 1 - }, json.loads(stdout)) - - state_0 = self.json_from_file(self.test_state_path) - state_1 = self.json_from_file('%s_1' % self.test_state_path) - self.assertEqual([ - self.fake_tool_path, - 'run', - '--detach=true', - '--name', - 'abcdef001__db', - '--env=KOLLA_CONFIG_STRATEGY=COPY_ALWAYS', - '--env=FOO=BAR', - '--net=host', - '--privileged=true', - '--restart=always', - '--user=root', - '--volume=/run:/run', - '--volume=db:/var/lib/db', - 'xxx' - ], state_0['args']) - self.assertEqual([ - self.fake_tool_path, - 'run', - '--detach=true', - '--name', - 'abcdef001__web', - 'xxx' - ], state_1['args']) - - def test_cleanup_deleted(self): - with tempfile.NamedTemporaryFile(delete=False) as f: - f.write(json.dumps([self.data])) - f.flush() - self.env['HEAT_SHELL_CONFIG'] = f.name - - returncode, stdout, stderr = self.run_cmd( - [self.cleanup_path], self.env) - - # on the first run, abcdef001.json is written out, no docker calls made - configs_path = os.path.join(self.env['HEAT_DOCKER_CMD_WORKING'], - 'abcdef001.json') - self.assertThat(configs_path, matchers.FileExists()) - self.assertThat(self.test_state_path, - matchers.Not(matchers.FileExists())) - - # run again with empty config data - with tempfile.NamedTemporaryFile(delete=False) as f: - f.write(json.dumps([])) - f.flush() - self.env['HEAT_SHELL_CONFIG'] = f.name - - returncode, stdout, stderr = self.run_cmd( - [self.cleanup_path], self.env) - - # on the second run, abcdef001.json is deleted, docker rm is run on - # both containers - configs_path = os.path.join(self.env['HEAT_DOCKER_CMD_WORKING'], - 'abcdef001.json') - self.assertThat(configs_path, - matchers.Not(matchers.FileExists())) - state_0 = self.json_from_file(self.test_state_path) - state_1 = self.json_from_file('%s_1' % self.test_state_path) - self.assertEqual([ - self.fake_tool_path, - 'rm', - '-f', - 'abcdef001__db', - ], state_0['args']) - self.assertEqual([ - self.fake_tool_path, - 'rm', - '-f', - 'abcdef001__web', - ], state_1['args']) - - def test_cleanup_changed(self): - with tempfile.NamedTemporaryFile(delete=False) as f: - f.write(json.dumps([self.data])) - f.flush() - self.env['HEAT_SHELL_CONFIG'] = f.name - - returncode, stdout, stderr = self.run_cmd( - [self.cleanup_path], self.env) - - # on the first run, abcdef001.json is written out, no docker calls made - configs_path = os.path.join(self.env['HEAT_DOCKER_CMD_WORKING'], - 'abcdef001.json') - self.assertThat(configs_path, matchers.FileExists()) - self.assertThat(self.test_state_path, - matchers.Not(matchers.FileExists())) - - # run again with changed config data - new_data = copy.deepcopy(self.data) - new_data['config']['web']['image'] = 'yyy' - with tempfile.NamedTemporaryFile(delete=False) as f: - f.write(json.dumps([new_data])) - f.flush() - self.env['HEAT_SHELL_CONFIG'] = f.name - - returncode, stdout, stderr = self.run_cmd( - [self.cleanup_path], self.env) - - # on the second run, abcdef001.json is written with the new data, - # docker rm is run on both containers - configs_path = os.path.join(self.env['HEAT_DOCKER_CMD_WORKING'], - 'abcdef001.json') - self.assertThat(configs_path, matchers.FileExists()) - state_0 = self.json_from_file(self.test_state_path) - state_1 = self.json_from_file('%s_1' % self.test_state_path) - self.assertEqual([ - self.fake_tool_path, - 'rm', - '-f', - 'abcdef001__db', - ], state_0['args']) - self.assertEqual([ - self.fake_tool_path, - 'rm', - '-f', - 'abcdef001__web', - ], state_1['args']) diff --git a/tests/software_config/test_hook_docker_compose.py b/tests/software_config/test_hook_docker_compose.py deleted file mode 100644 index f9cc904..0000000 --- a/tests/software_config/test_hook_docker_compose.py +++ /dev/null @@ -1,177 +0,0 @@ -# -# 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 json -import os - -import fixtures - -from tests.software_config import common - - -class HookDockerComposeTest(common.RunScriptTest): - data = { - "name": "abcdef001", - "group": "docker-compose", - "inputs": [ - { - "name": "env_files", - "value": u'[ { "file_name": "./common.env", ' - u'"content": "xxxxx" }, ' - u'{ "file_name": "./test.env", ' - u'"content": "yyyy" }, ' - u'{ "file_name": "./test1.env", ' - u'"content": "zzz" } ]' - } - ], - "config": { - "web": { - "name": "x", - "env_file": [ - "./common.env", - "./test.env" - ] - }, - "db": { - "name": "y", - "env_file": "./test1.env" - } - } - } - - data_without_input = { - "name": "abcdef001", - "group": "docker-compose", - "inputs": [], - "config": { - "web": { - "name": "x", - "env_file": [ - "./common.env", - "./test.env" - ] - }, - "db": { - "name": "y", - "env_file": "./test1.env" - } - } - } - - def setUp(self): - super(HookDockerComposeTest, self).setUp() - self.hook_path = self.relative_path( - __file__, - '../..', - 'hot/software-config/elements', - 'heat-config-docker-compose/install.d/hook-docker-compose.py') - - self.fake_tool_path = self.relative_path( - __file__, - 'config-tool-fake.py') - - self.working_dir = self.useFixture(fixtures.TempDir()) - self.outputs_dir = self.useFixture(fixtures.TempDir()) - self.test_state_path = self.outputs_dir.join('test_state.json') - - self.env = os.environ.copy() - self.env.update({ - 'HEAT_DOCKER_COMPOSE_WORKING': self.working_dir.join(), - 'HEAT_DOCKER_COMPOSE_CMD': self.fake_tool_path, - 'TEST_STATE_PATH': self.test_state_path, - }) - - def test_hook(self): - - self.env.update({ - 'TEST_RESPONSE': json.dumps({ - 'stdout': '', - 'stderr': 'Creating abcdef001_db_1...' - }) - }) - returncode, stdout, stderr = self.run_cmd( - [self.hook_path], self.env, json.dumps(self.data)) - - self.assertEqual(0, returncode, stderr) - - self.assertEqual({ - 'deploy_stdout': '', - 'deploy_stderr': 'Creating abcdef001_db_1...', - 'deploy_status_code': 0 - }, json.loads(stdout)) - - state = self.json_from_file(self.test_state_path) - self.assertEqual( - [ - self.fake_tool_path, - 'up', - '-d', - '--no-build', - ], - state['args']) - - def test_hook_without_inputs(self): - - self.env.update({ - 'TEST_RESPONSE': json.dumps({ - 'stdout': '', - 'stderr': 'env_file_not found...', - 'returncode': 1 - }) - }) - returncode, stdout, stderr = self.run_cmd( - [self.hook_path], self.env, json.dumps(self.data_without_input)) - - self.assertEqual({ - 'deploy_stdout': '', - 'deploy_stderr': 'env_file_not found...', - 'deploy_status_code': 1 - }, json.loads(stdout)) - - state = self.json_from_file(self.test_state_path) - self.assertEqual( - [ - self.fake_tool_path, - 'up', - '-d', - '--no-build', - ], - state['args']) - - def test_hook_failed(self): - - self.env.update({ - 'TEST_RESPONSE': json.dumps({ - 'stdout': '', - 'stderr': 'Error: image library/xxx:latest not found', - 'returncode': 1 - }) - }) - returncode, stdout, stderr = self.run_cmd( - [self.hook_path], self.env, json.dumps(self.data)) - - self.assertEqual({ - 'deploy_stdout': '', - 'deploy_stderr': 'Error: image library/xxx:latest not found', - 'deploy_status_code': 1 - }, json.loads(stdout)) - - state = self.json_from_file(self.test_state_path) - self.assertEqual( - [ - self.fake_tool_path, - 'up', - '-d', - '--no-build', - ], - state['args']) diff --git a/tests/software_config/test_hook_hiera.py b/tests/software_config/test_hook_hiera.py deleted file mode 100644 index 8e6e6c4..0000000 --- a/tests/software_config/test_hook_hiera.py +++ /dev/null @@ -1,85 +0,0 @@ -# -# 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 fixtures -import json -import logging -import os -import tempfile -import yaml - -from tests.software_config import common - -log = logging.getLogger('test_hook_hiera_config') - -HIERA_CONFIG_BASE = """ ---- -:backends: - - json -:json: - :datadir: %(datadir)s -:hierarchy: - - %(datafile)s -""" - - -class HookHieraTest(common.RunScriptTest): - - data = { - 'id': 'test_hiera', - 'name': 'fake_resource_name', - 'group': 'hiera', - 'config': { - 'hierarchy': ['compute'], - 'datafiles': { - 'compute': {'foo': 'bar'} - } - } - } - - def setUp(self): - super(HookHieraTest, self).setUp() - self.hook_path = self.relative_path( - __file__, - '../..', - 'hot/software-config/elements', - 'heat-config-hiera/install.d/hook-hiera.py') - - self.hieradata_dir = self.useFixture(fixtures.TempDir()).join() - self.conf = tempfile.NamedTemporaryFile(mode='w', delete=False).name - os.unlink(self.conf) - - self.env = os.environ.copy() - self.env.update({ - 'HEAT_HIERA_CONFIG': self.conf, - 'HEAT_PUPPET_HIERA_DATADIR': self.hieradata_dir, - }) - - def test_hook(self): - - returncode, stdout, stderr = self.run_cmd( - [self.hook_path], self.env, json.dumps(self.data)) - - self.assertEqual(0, returncode, stderr) - ret = yaml.safe_load(stdout) - self.assertIsNotNone(ret['deploy_stderr']) - self.assertEqual('', ret['deploy_stdout']) - self.assertEqual(0, ret['deploy_status_code']) - - conf_data = HIERA_CONFIG_BASE % {'datadir': self.hieradata_dir, - 'datafile': 'compute'} - with open(self.conf) as conf_file: - self.assertEqual(conf_data, conf_file.read()) - - with open(os.path.join(self.hieradata_dir, 'compute.json')) as data: - self.assertEqual("{\n \"foo\": \"bar\"\n}", data.read()) diff --git a/tests/software_config/test_hook_json_file.py b/tests/software_config/test_hook_json_file.py deleted file mode 100644 index 73a7d2f..0000000 --- a/tests/software_config/test_hook_json_file.py +++ /dev/null @@ -1,62 +0,0 @@ -# -# 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 json -import logging -import os -import tempfile -import yaml - -from tests.software_config import common - -log = logging.getLogger('test_hook_json_file') - - -class HookKollaConfigTest(common.RunScriptTest): - - def setUp(self): - super(HookKollaConfigTest, self).setUp() - self.hook_path = self.relative_path( - __file__, - '../..', - 'hot/software-config/elements', - 'heat-config-json-file/install.d/hook-json-file.py') - - self.conf = tempfile.NamedTemporaryFile(mode='w', delete=False).name - os.unlink(self.conf) - - self.env = os.environ.copy() - self.data = { - 'id': 'test_json_file', - 'name': 'fake_resource_name', - 'group': 'json-file', - 'config': { - self.conf: { - 'command': 'foo' - } - } - } - - def test_hook(self): - - returncode, stdout, stderr = self.run_cmd( - [self.hook_path], self.env, json.dumps(self.data)) - - self.assertEqual(0, returncode, stderr) - ret = yaml.safe_load(stdout) - self.assertIsNotNone(ret['deploy_stderr']) - self.assertEqual('', ret['deploy_stdout']) - self.assertEqual(0, ret['deploy_status_code']) - - with open(os.path.join(self.conf)) as data: - self.assertEqual("{\n \"command\": \"foo\"\n}", data.read()) diff --git a/tests/software_config/test_hook_kubelet.py b/tests/software_config/test_hook_kubelet.py deleted file mode 100644 index de4c235..0000000 --- a/tests/software_config/test_hook_kubelet.py +++ /dev/null @@ -1,114 +0,0 @@ -# -# 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 re -import testtools - -from tests.software_config import hook_kubelet - - -class HookKubeletTest(testtools.TestCase): - - config = { - "id": "a50ae8dd-b0c4-407f-8732-3571b3a0f28b", - "group": "kubelet", - "inputs": [], - "name": "20_apache_deployment", - "outputs": [], - "options": {}, - "config": { - "version": "v1beta2", - "volumes": [{ - "name": "mariadb-data" - }], - "containers": [{ - "image": "kollaglue/fedora-rdo-rabbitmq", - "name": "rabbitmq", - "ports": [{ - "containerPort": 5672, - "hostPort": 5672}] - }, { - "image": "kollaglue/fedora-rdo-heat-engine", - "name": "heat-engine", - "env": [{ - "name": "AUTH_ENCRYPTION_KEY", - "value": "Vegu95l2jwkucD9RSYAoFpRbUlh0PGF7"}] - }, { - "image": "kollaglue/fedora-rdo-heat-engine", - "name": "heat-engine2", - "env": [{ - "name": "AUTH_ENCRYPTION_KEY", - "value": "Vegu95l2jwkucD9RSYAoFpRbUlh0PGF7"}] - }] - } - } - - def setUp(self): - super(HookKubeletTest, self).setUp() - docker = mock.MagicMock() - self.docker_client = mock.MagicMock() - docker.Client.return_value = self.docker_client - self.docker_client.version.return_value = { - 'ApiVersion': '1.3.0' - } - hook_kubelet.docker = docker - - def test_id_to_pod_name_part(self): - self.assertEqual( - 'fc9070b3ba4e4f2', - hook_kubelet.id_to_pod_name_part( - 'fc9070b3-ba4e-4f22-b732-5ffdcdb40b74')) - - def test_container_pattern(self): - pattern = hook_kubelet.container_pattern( - 'fc9070b3-ba4e-4f22-b732-5ffdcdb40b74', 'mariadb') - self.assertEqual( - '^/k8s_mariadb\\.[0-9a-z]{8}_fc9070b3ba4e4f2', pattern) - - pat = re.compile(pattern) - - self.assertIsNotNone(pat.match( - '/k8s_mariadb.dac8ccce_fc9070b3ba4e4f2' - 'uv6pejpu5nqbmrqoungurhtob5gvt.default.' - 'file_2c8cf9fc94674e8buv6pejpu5nqbmrqoungurhtob5gvt_dcd1e1d9')) - self.assertIsNotNone(pat.match( - '/k8s_mariadb.dac8ccce_fc9070b3ba4e4f2a')) - - self.assertIsNone(pat.match( - 'k8s_mariadb.dac8ccce_fc9070b3ba4e4f2a')) - self.assertIsNone(pat.match( - '/k8s_mysqldb.dac8ccce_fc9070b3ba4e4f2a')) - self.assertIsNone(pat.match( - '/k8s_mariadb.dac8ccc_fc9070b3ba4e4f2a')) - self.assertIsNone(pat.match( - '/k8s_mariadb.dac8ccce_gc9070b3ba4e4f22a')) - - def test_required_images(self): - self.assertEqual( - set([ - 'kollaglue/fedora-rdo-heat-engine', - 'kollaglue/fedora-rdo-rabbitmq']), - hook_kubelet.required_images(self.config)) - - self.assertEqual( - set(), hook_kubelet.required_images({'config': {}})) - - def test_required_container_patterns(self): - patterns = hook_kubelet.required_container_patterns(self.config) - self.assertEqual({ - 'heat-engine': '^/k8s_heat-engine\\.[0-9a-z]{8}_a50ae8ddb0c4407', - 'heat-engine2': '^/k8s_heat-engine2\\.[0-9a-z]{8}_a50ae8ddb0c4407', - 'rabbitmq': '^/k8s_rabbitmq\\.[0-9a-z]{8}_a50ae8ddb0c4407' - }, patterns) diff --git a/tests/software_config/test_hook_puppet.py b/tests/software_config/test_hook_puppet.py deleted file mode 100644 index cd01c94..0000000 --- a/tests/software_config/test_hook_puppet.py +++ /dev/null @@ -1,287 +0,0 @@ -# -# 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 copy -import json -import os - -import fixtures - -from tests.software_config import common - - -class HookPuppetTest(common.RunScriptTest): - - data = { - 'id': '1234', - 'creation_time': '2015-07-16T11:40:20', - 'name': 'fake_resource_name', - 'group': 'puppet', - 'options': { - 'enable_hiera': True, - 'enable_facter': True, - 'enable_debug': True, - 'enable_verbose': True, - }, - 'inputs': [ - {'name': 'foo', 'value': 'bar'}, - {'name': 'another', 'value': 'input'} - ], - 'outputs': [ - {'name': 'first_output'}, - {'name': 'second_output'} - ], - 'config': 'the puppet script' - } - - def setUp(self): - super(HookPuppetTest, self).setUp() - self.hook_path = self.relative_path( - __file__, - '../..', - 'hot/software-config/elements', - 'heat-config-puppet/install.d/hook-puppet.py') - - self.fake_tool_path = self.relative_path( - __file__, - 'config-tool-fake.py') - - self.working_dir = self.useFixture(fixtures.TempDir()) - self.outputs_dir = self.useFixture(fixtures.TempDir()) - self.log_dir = self.useFixture(fixtures.TempDir()) - self.hiera_datadir = self.useFixture(fixtures.TempDir()) - self.test_state_path = self.outputs_dir.join('test_state.json') - - self.env = os.environ.copy() - self.env.update({ - 'HEAT_PUPPET_WORKING': self.working_dir.join(), - 'HEAT_PUPPET_OUTPUTS': self.outputs_dir.join(), - 'HEAT_PUPPET_LOGDIR': self.log_dir.join(), - 'HEAT_PUPPET_HIERA_DATADIR': self.hiera_datadir.join(), - 'HEAT_PUPPET_CMD': self.fake_tool_path, - 'TEST_STATE_PATH': self.test_state_path, - }) - - def test_hook(self): - - self.env.update({ - 'TEST_RESPONSE': json.dumps({ - 'stdout': 'puppet success', - 'stderr': 'thing happened', - 'files': { - self.outputs_dir.join('1234.first_output'): 'output 1', - self.outputs_dir.join('1234.second_output'): 'output 2', - } - }), - }) - returncode, stdout, stderr = self.run_cmd( - [self.hook_path], self.env, json.dumps(self.data)) - - self.assertEqual(0, returncode, stderr) - self.assertEqual({ - 'deploy_stdout': 'puppet success', - 'deploy_stderr': 'thing happened', - 'deploy_status_code': 0, - 'first_output': 'output 1', - 'second_output': 'output 2', - }, json.loads(stdout)) - - state = self.json_from_file(self.test_state_path) - puppet_script = self.working_dir.join('1234.pp') - self.assertEqual( - [ - self.fake_tool_path, - 'apply', - '--detailed-exitcodes', - '--logdest', - 'console', - '--debug', - '--logdest', - '/var/log/puppet/heat-debug.log', - '--verbose', - '--logdest', - '/var/log/puppet/heat-verbose.log', - puppet_script - ], - state['args']) - - self.assertEqual('bar', state['env']['FACTER_foo']) - self.assertEqual('input', state['env']['FACTER_another']) - self.assertEqual(self.outputs_dir.join('1234'), - state['env']['FACTER_heat_outputs_path']) - with open(puppet_script) as f: - self.assertEqual('the puppet script', f.read()) - - def test_hook_no_debug(self): - self.data['options']['enable_debug'] = False - self.env.update({ - 'TEST_RESPONSE': json.dumps({ - 'stdout': 'success', - 'stderr': '', - }), - }) - returncode, stdout, stderr = self.run_cmd( - [self.hook_path], self.env, json.dumps(self.data)) - - state = self.json_from_file(self.test_state_path) - puppet_script = self.working_dir.join('1234.pp') - self.assertEqual( - [ - self.fake_tool_path, - 'apply', - '--detailed-exitcodes', - '--logdest', - 'console', - '--verbose', - '--logdest', - '/var/log/puppet/heat-verbose.log', - puppet_script - ], - state['args']) - self.data['options']['enable_debug'] = True - - def test_hook_no_verbose(self): - self.data['options']['enable_verbose'] = False - self.env.update({ - 'TEST_RESPONSE': json.dumps({ - 'stdout': 'success', - 'stderr': '', - }), - }) - returncode, stdout, stderr = self.run_cmd( - [self.hook_path], self.env, json.dumps(self.data)) - - state = self.json_from_file(self.test_state_path) - puppet_script = self.working_dir.join('1234.pp') - self.assertEqual( - [ - self.fake_tool_path, - 'apply', - '--detailed-exitcodes', - '--logdest', - 'console', - '--debug', - '--logdest', - '/var/log/puppet/heat-debug.log', - puppet_script - ], - state['args']) - self.data['options']['enable_verbose'] = True - - def test_hook_puppet_failed(self): - - self.env.update({ - 'TEST_RESPONSE': json.dumps({ - 'stdout': 'puppet failed', - 'stderr': 'bad thing happened', - 'returncode': 4 - }), - }) - returncode, stdout, stderr = self.run_cmd( - [self.hook_path], self.env, json.dumps(self.data)) - - self.assertEqual(0, returncode, stderr) - self.assertEqual({ - 'deploy_stdout': 'puppet failed', - 'deploy_stderr': 'bad thing happened', - 'deploy_status_code': 4, - }, json.loads(stdout)) - - state = self.json_from_file(self.test_state_path) - puppet_script = self.working_dir.join('1234.pp') - self.assertEqual( - [ - self.fake_tool_path, - 'apply', - '--detailed-exitcodes', - '--logdest', - 'console', - '--debug', - '--logdest', - '/var/log/puppet/heat-debug.log', - '--verbose', - '--logdest', - '/var/log/puppet/heat-verbose.log', - puppet_script - ], - state['args']) - - self.assertEqual('bar', state['env']['FACTER_foo']) - self.assertEqual('input', state['env']['FACTER_another']) - self.assertEqual(self.outputs_dir.join('1234'), - state['env']['FACTER_heat_outputs_path']) - with open(puppet_script) as f: - self.assertEqual('the puppet script', f.read()) - - def test_hook_hiera(self): - - self.env.update({ - 'TEST_RESPONSE': json.dumps({ - 'stdout': 'puppet success', - 'stderr': 'thing happened', - 'files': { - self.outputs_dir.join('1234.first_output'): 'output 1', - self.outputs_dir.join('1234.second_output'): 'output 2', - } - }), - }) - modulepath = self.working_dir.join() - data = copy.deepcopy(self.data) - data['options']['modulepath'] = modulepath - data['options']['tags'] = 'package,file' - returncode, stdout, stderr = self.run_cmd( - [self.hook_path], self.env, json.dumps(data)) - - self.assertEqual(0, returncode, stderr) - self.assertEqual({ - 'deploy_stdout': 'puppet success', - 'deploy_stderr': 'thing happened', - 'deploy_status_code': 0, - 'first_output': 'output 1', - 'second_output': 'output 2', - }, json.loads(stdout)) - - state = self.json_from_file(self.test_state_path) - puppet_script = self.working_dir.join('1234.pp') - hiera_datafile = self.hiera_datadir.join('heat_config_%s.json' - % self.data['name']) - self.assertEqual( - [ - self.fake_tool_path, - 'apply', - '--detailed-exitcodes', - '--logdest', - 'console', - '--modulepath', - modulepath, - '--tags', - 'package,file', - '--debug', - '--logdest', - '/var/log/puppet/heat-debug.log', - '--verbose', - '--logdest', - '/var/log/puppet/heat-verbose.log', - puppet_script - ], - state['args']) - - self.assertEqual(self.outputs_dir.join('1234'), - state['env']['FACTER_heat_outputs_path']) - with open(puppet_script) as f: - self.assertEqual('the puppet script', f.read()) - with open(hiera_datafile) as f: - self.assertEqual({ - 'foo': 'bar', - 'another': 'input', - }, json.loads(f.read())) diff --git a/tests/software_config/test_hook_salt.py b/tests/software_config/test_hook_salt.py deleted file mode 100644 index 372a624..0000000 --- a/tests/software_config/test_hook_salt.py +++ /dev/null @@ -1,135 +0,0 @@ -# -# 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 fixtures -import json -import logging -import os -import yaml - -from tests.software_config import common - -log = logging.getLogger('test_hook_salt') - -slsok = """ -testit: - environ.setenv: - - name: does_not_matter - - value: - foo: {{ opts['fooval'] }} - bar: {{ opts['barval'] }} -""" - -slsfail = """ -failure: - test.echo: - - text: I don't work -""" - -slsnotallowed = """ -install_service: - pkg.installed: - - name: {{ opts['fooval'] }} -""" - - -class HookSaltTest(common.RunScriptTest): - - data = { - 'id': 'fake_stack', - 'name': 'fake_resource_name', - 'group': 'salt', - 'inputs': [ - {'name': 'fooval', 'value': 'bar'}, - {'name': 'barval', 'value': 'foo'} - ], - 'outputs': [ - {'name': 'first_output'}, - {'name': 'second_output'} - ], - 'config': None - } - - def setUp(self): - super(HookSaltTest, self).setUp() - self.hook_path = self.relative_path( - __file__, - '../..', - 'hot/software-config/elements', - 'heat-config-salt/install.d/hook-salt.py') - - self.working_dir = self.useFixture(fixtures.TempDir()) - self.minion_config_dir = self.useFixture(fixtures.TempDir()) - self.minion_cach_dir = self.useFixture(fixtures.TempDir()) - - self.minion_conf = self.minion_config_dir.join("minion") - - self.env = os.environ.copy() - self.env.update({ - 'HEAT_SALT_WORKING': self.working_dir.join(), - 'SALT_MINION_CONFIG': self.minion_conf - }) - - with open(self.minion_conf, "w+") as conf_file: - conf_file.write("cachedir: %s\n" % self.minion_cach_dir.join()) - conf_file.write("log_level: DEBUG\n") - - def test_hook(self): - - self.data['config'] = slsok - - returncode, stdout, stderr = self.run_cmd( - [self.hook_path], self.env, json.dumps(self.data)) - - self.assertEqual(0, returncode, stderr) - ret = yaml.safe_load(stdout) - self.assertEqual(0, ret['deploy_status_code']) - self.assertIsNone(ret['deploy_stderr']) - self.assertIsNotNone(ret['deploy_stdout']) - resp = yaml.safe_load(ret['deploy_stdout']) - self.assertTrue(resp.values()[0]['result']) - self.assertEqual({'bar': 'foo', 'foo': 'bar'}, - resp.values()[0]['changes']) - - def test_hook_salt_failed(self): - - self.data['config'] = slsfail - - returncode, stdout, stderr = self.run_cmd( - [self.hook_path], self.env, json.dumps(self.data)) - - self.assertEqual(0, returncode) - self.assertIsNotNone(stderr) - self.assertIsNotNone(stdout) - jsonout = json.loads(stdout) - self.assertIsNone(jsonout.get("deploy_stdout"), - jsonout.get("deploy_stdout")) - self.assertEqual(2, jsonout.get("deploy_status_code")) - self.assertIsNotNone(jsonout.get("deploy_stderr")) - self.assertIn("was not found in SLS", jsonout.get("deploy_stderr")) - - def test_hook_salt_retcode(self): - - self.data['config'] = slsnotallowed - - returncode, stdout, stderr = self.run_cmd( - [self.hook_path], self.env, json.dumps(self.data)) - - self.assertEqual(0, returncode, stderr) - self.assertIsNotNone(stdout) - self.assertIsNotNone(stderr) - ret = json.loads(stdout) - self.assertIsNone(ret['deploy_stdout']) - self.assertIsNotNone(ret['deploy_stderr']) - resp = yaml.safe_load(ret['deploy_stderr']).values()[0] - self.assertFalse(resp['result']) diff --git a/tests/software_config/test_hook_script.py b/tests/software_config/test_hook_script.py deleted file mode 100644 index 2e0d5e8..0000000 --- a/tests/software_config/test_hook_script.py +++ /dev/null @@ -1,133 +0,0 @@ -# -# 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 json -import os - -import fixtures - -from tests.software_config import common - - -class HookScriptTest(common.RunScriptTest): - - def setUp(self): - super(HookScriptTest, self).setUp() - self.hook_path = self.relative_path( - __file__, - '../..', - 'hot/software-config/elements', - 'heat-config-script/install.d/hook-script.py') - - self.fake_tool_path = self.relative_path( - __file__, - 'config-tool-fake.py') - - with open(self.fake_tool_path) as f: - self.fake_tool_contents = f.read() - - self.data = { - 'id': '1234', - 'group': 'script', - 'inputs': [ - {'name': 'foo', 'value': 'bar'}, - {'name': 'another', 'value': 'input'}, - {'name': 'a_dict', 'value': '{"key": "value"}'}, - {'name': 'a_list', 'value': '["v1", 12]'}, - ], - 'outputs': [ - {'name': 'first_output'}, - {'name': 'second_output'} - ], - 'config': self.fake_tool_contents - } - - self.working_dir = self.useFixture(fixtures.TempDir()) - self.outputs_dir = self.useFixture(fixtures.TempDir()) - self.test_state_path = self.outputs_dir.join('test_state.json') - - self.env = os.environ.copy() - self.env.update({ - 'HEAT_SCRIPT_WORKING': self.working_dir.join(), - 'HEAT_SCRIPT_OUTPUTS': self.outputs_dir.join(), - 'TEST_STATE_PATH': self.test_state_path, - }) - - def test_hook(self): - - self.env.update({ - 'TEST_RESPONSE': json.dumps({ - 'stdout': 'script success', - 'stderr': 'thing happened', - 'files': { - self.outputs_dir.join('1234.first_output'): 'output 1', - self.outputs_dir.join('1234.second_output'): 'output 2', - } - }), - }) - returncode, stdout, stderr = self.run_cmd( - [self.hook_path], self.env, json.dumps(self.data)) - - self.assertEqual(0, returncode, stderr) - self.assertEqual({ - 'deploy_stdout': 'script success', - 'deploy_stderr': 'thing happened', - 'deploy_status_code': 0, - 'first_output': 'output 1', - 'second_output': 'output 2', - }, json.loads(stdout)) - - state = self.json_from_file(self.test_state_path) - script = self.working_dir.join('1234') - with open(script) as f: - self.assertEqual(self.fake_tool_contents, f.read()) - - self.assertEqual([script], state['args']) - self.assertEqual('bar', state['env']['foo']) - self.assertEqual('input', state['env']['another']) - self.assertEqual('{"key": "value"}', state['env']['a_dict']) - self.assertEqual('["v1", 12]', state['env']['a_list']) - self.assertEqual(self.outputs_dir.join('1234'), - state['env']['heat_outputs_path']) - - def test_hook_failed(self): - - self.env.update({ - 'TEST_RESPONSE': json.dumps({ - 'stdout': 'script failed', - 'stderr': 'bad thing happened', - 'returncode': 1 - }), - }) - returncode, stdout, stderr = self.run_cmd( - [self.hook_path], self.env, json.dumps(self.data)) - - self.assertEqual(0, returncode, stderr) - self.assertEqual({ - 'deploy_stdout': 'script failed', - 'deploy_stderr': 'bad thing happened', - 'deploy_status_code': 1, - }, json.loads(stdout)) - - state = self.json_from_file(self.test_state_path) - script = self.working_dir.join('1234') - with open(script) as f: - self.assertEqual(self.fake_tool_contents, f.read()) - - self.assertEqual([script], state['args']) - self.assertEqual('bar', state['env']['foo']) - self.assertEqual('input', state['env']['another']) - self.assertEqual('{"key": "value"}', state['env']['a_dict']) - self.assertEqual('["v1", 12]', state['env']['a_list']) - self.assertEqual(self.outputs_dir.join('1234'), - state['env']['heat_outputs_path']) |