123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- # coding: utf-8
- # Import Python libs
- from __future__ import absolute_import
- import os
- import shutil
- import tempfile
- import pytest
- # Import Salt Testing libs
- from tests.support.unit import TestCase
- from tests.support.mock import patch, MagicMock
- from tests.support.mixins import AdaptedConfigurationTestCaseMixin
- import salt.config
- import salt.utils.files
- import salt.spm
- _F1 = {
- 'definition': {
- 'name': 'formula1',
- 'version': '1.2',
- 'release': '2',
- 'summary': 'test',
- 'description': 'testing, nothing to see here',
- }
- }
- _F1['contents'] = (
- ('FORMULA', ('name: {name}\n'
- 'version: {version}\n'
- 'release: {release}\n'
- 'summary: {summary}\n'
- 'description: {description}').format(**_F1['definition'])),
- ('modules/mod1.py', '# mod1.py'),
- ('modules/mod2.py', '# mod2.py'),
- ('states/state1.sls', '# state1.sls'),
- ('states/state2.sls', '# state2.sls'),
- )
- @pytest.mark.destructive_test
- class SPMTestUserInterface(salt.spm.SPMUserInterface):
- '''
- Unit test user interface to SPMClient
- '''
- def __init__(self):
- self._status = []
- self._confirm = []
- self._error = []
- def status(self, msg):
- self._status.append(msg)
- def confirm(self, action):
- self._confirm.append(action)
- def error(self, msg):
- self._error.append(msg)
- class SPMTest(TestCase, AdaptedConfigurationTestCaseMixin):
- def setUp(self):
- self._tmp_spm = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, self._tmp_spm, ignore_errors=True)
- minion_config = self.get_temp_config('minion', **{
- 'spm_logfile': os.path.join(self._tmp_spm, 'log'),
- 'spm_repos_config': os.path.join(self._tmp_spm, 'etc', 'spm.repos'),
- 'spm_cache_dir': os.path.join(self._tmp_spm, 'cache'),
- 'spm_build_dir': os.path.join(self._tmp_spm, 'build'),
- 'spm_build_exclude': ['.git'],
- 'spm_db_provider': 'sqlite3',
- 'spm_files_provider': 'local',
- 'spm_db': os.path.join(self._tmp_spm, 'packages.db'),
- 'extension_modules': os.path.join(self._tmp_spm, 'modules'),
- 'file_roots': {'base': [self._tmp_spm, ]},
- 'formula_path': os.path.join(self._tmp_spm, 'spm'),
- 'pillar_path': os.path.join(self._tmp_spm, 'pillar'),
- 'reactor_path': os.path.join(self._tmp_spm, 'reactor'),
- 'assume_yes': True,
- 'force': False,
- 'verbose': False,
- 'cache': 'localfs',
- 'cachedir': os.path.join(self._tmp_spm, 'cache'),
- 'spm_repo_dups': 'ignore',
- 'spm_share_dir': os.path.join(self._tmp_spm, 'share'),
- })
- self.ui = SPMTestUserInterface()
- self.client = salt.spm.SPMClient(self.ui, minion_config)
- self.minion_config = minion_config
- for attr in ('client', 'ui', '_tmp_spm', 'minion_config'):
- self.addCleanup(delattr, self, attr)
- def _create_formula_files(self, formula):
- fdir = os.path.join(self._tmp_spm, formula['definition']['name'])
- shutil.rmtree(fdir, ignore_errors=True)
- os.mkdir(fdir)
- for path, contents in formula['contents']:
- path = os.path.join(fdir, path)
- dirname, _ = os.path.split(path)
- if not os.path.exists(dirname):
- os.makedirs(dirname)
- with salt.utils.files.fopen(path, 'w') as f:
- f.write(contents)
- return fdir
- def test_build_install(self):
- # Build package
- fdir = self._create_formula_files(_F1)
- with patch('salt.client.Caller', MagicMock(return_value=self.minion_opts)):
- with patch('salt.client.get_local_client', MagicMock(return_value=self.minion_opts['conf_file'])):
- self.client.run(['build', fdir])
- pkgpath = self.ui._status[-1].split()[-1]
- assert os.path.exists(pkgpath)
- # Install package
- with patch('salt.client.Caller', MagicMock(return_value=self.minion_opts)):
- with patch('salt.client.get_local_client', MagicMock(return_value=self.minion_opts['conf_file'])):
- self.client.run(['local', 'install', pkgpath])
- # Check filesystem
- for path, contents in _F1['contents']:
- path = os.path.join(self.minion_config['file_roots']['base'][0], _F1['definition']['name'], path)
- assert os.path.exists(path)
- with salt.utils.files.fopen(path, 'r') as rfh:
- assert rfh.read() == contents
- # Check database
- with patch('salt.client.Caller', MagicMock(return_value=self.minion_opts)):
- with patch('salt.client.get_local_client', MagicMock(return_value=self.minion_opts['conf_file'])):
- self.client.run(['info', _F1['definition']['name']])
- lines = self.ui._status[-1].split('\n')
- for key, line in (
- ('name', 'Name: {0}'),
- ('version', 'Version: {0}'),
- ('release', 'Release: {0}'),
- ('summary', 'Summary: {0}')):
- assert line.format(_F1['definition'][key]) in lines
- # Reinstall with force=False, should fail
- self.ui._error = []
- with patch('salt.client.Caller', MagicMock(return_value=self.minion_opts)):
- with patch('salt.client.get_local_client', MagicMock(return_value=self.minion_opts['conf_file'])):
- self.client.run(['local', 'install', pkgpath])
- assert len(self.ui._error) > 0
- # Reinstall with force=True, should succeed
- with patch.dict(self.minion_config, {'force': True}):
- self.ui._error = []
- with patch('salt.client.Caller', MagicMock(return_value=self.minion_opts)):
- with patch('salt.client.get_local_client', MagicMock(return_value=self.minion_opts['conf_file'])):
- self.client.run(['local', 'install', pkgpath])
- assert len(self.ui._error) == 0
- def test_failure_paths(self):
- fail_args = (
- ['bogus', 'command'],
- ['create_repo'],
- ['build'],
- ['build', '/nonexistent/path'],
- ['info'],
- ['info', 'not_installed'],
- ['files'],
- ['files', 'not_installed'],
- ['install'],
- ['install', 'nonexistent.spm'],
- ['remove'],
- ['remove', 'not_installed'],
- ['local', 'bogus', 'command'],
- ['local', 'info'],
- ['local', 'info', '/nonexistent/path/junk.spm'],
- ['local', 'files'],
- ['local', 'files', '/nonexistent/path/junk.spm'],
- ['local', 'install'],
- ['local', 'install', '/nonexistent/path/junk.spm'],
- ['local', 'list'],
- ['local', 'list', '/nonexistent/path/junk.spm'],
- # XXX install failure due to missing deps
- # XXX install failure due to missing field
- )
- for args in fail_args:
- self.ui._error = []
- with patch('salt.client.Caller', MagicMock(return_value=self.minion_opts)):
- with patch('salt.client.get_local_client', MagicMock(return_value=self.minion_opts['conf_file'])):
- self.client.run(args)
- assert len(self.ui._error) > 0
|