gitfs.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670
  1. # -*- coding: utf-8 -*-
  2. '''
  3. Base classes for gitfs/git_pillar integration tests
  4. '''
  5. # Import python libs
  6. from __future__ import absolute_import, print_function, unicode_literals
  7. import copy
  8. import errno
  9. import logging
  10. import os
  11. import psutil
  12. import shutil
  13. import signal
  14. import tempfile
  15. import textwrap
  16. import time
  17. # Import Salt libs
  18. import salt.utils.files
  19. import salt.utils.path
  20. import salt.utils.yaml
  21. from salt.fileserver import gitfs
  22. from salt.pillar import git_pillar
  23. from salt.ext.six.moves import range # pylint: disable=redefined-builtin
  24. # Import Salt Testing libs
  25. from tests.support.case import ModuleCase
  26. from tests.support.mixins import LoaderModuleMockMixin, SaltReturnAssertsMixin
  27. from tests.support.paths import TMP
  28. from tests.support.helpers import (
  29. get_unused_localhost_port,
  30. requires_system_grains,
  31. )
  32. from tests.support.mock import patch
  33. log = logging.getLogger(__name__)
  34. USERNAME = 'gitpillaruser'
  35. PASSWORD = 'saltrules'
  36. _OPTS = {
  37. '__role': 'minion',
  38. 'environment': None,
  39. 'pillarenv': None,
  40. 'hash_type': 'sha256',
  41. 'file_roots': {},
  42. 'state_top': 'top.sls',
  43. 'state_top_saltenv': None,
  44. 'renderer': 'yaml_jinja',
  45. 'renderer_whitelist': [],
  46. 'renderer_blacklist': [],
  47. 'pillar_merge_lists': False,
  48. 'git_pillar_base': 'master',
  49. 'git_pillar_branch': 'master',
  50. 'git_pillar_env': '',
  51. 'git_pillar_root': '',
  52. 'git_pillar_ssl_verify': True,
  53. 'git_pillar_global_lock': True,
  54. 'git_pillar_user': '',
  55. 'git_pillar_password': '',
  56. 'git_pillar_insecure_auth': False,
  57. 'git_pillar_privkey': '',
  58. 'git_pillar_pubkey': '',
  59. 'git_pillar_passphrase': '',
  60. 'git_pillar_refspecs': [
  61. '+refs/heads/*:refs/remotes/origin/*',
  62. '+refs/tags/*:refs/tags/*',
  63. ],
  64. 'git_pillar_includes': True,
  65. }
  66. PROC_TIMEOUT = 10
  67. NOTSET = object()
  68. class ProcessManager(object):
  69. '''
  70. Functions used both to set up self-contained SSH/HTTP servers for testing
  71. '''
  72. wait = 10
  73. def find_proc(self, name=None, search=None):
  74. def _search(proc):
  75. return any([search in x for x in proc.cmdline()])
  76. if name is None and search is None:
  77. raise ValueError('one of name or search is required')
  78. for proc in psutil.process_iter():
  79. if name is not None:
  80. if search is None:
  81. if name in proc.name():
  82. return proc
  83. elif name in proc.name() and _search(proc):
  84. return proc
  85. else:
  86. if _search(proc):
  87. return proc
  88. return None
  89. def wait_proc(self, name=None, search=None, timeout=PROC_TIMEOUT):
  90. for idx in range(1, self.wait + 1):
  91. proc = self.find_proc(name=name, search=search)
  92. if proc is not None:
  93. return proc
  94. else:
  95. if idx != self.wait:
  96. log.debug(
  97. 'Waiting for %s process (%d of %d)',
  98. name, idx, self.wait
  99. )
  100. time.sleep(1)
  101. else:
  102. log.debug(
  103. 'Failed fo find %s process after %d seconds',
  104. name, self.wait
  105. )
  106. raise Exception(
  107. 'Unable to find {0} process running from temp config file {1} '
  108. 'using psutil'.format(name, search)
  109. )
  110. class SSHDMixin(ModuleCase, ProcessManager, SaltReturnAssertsMixin):
  111. '''
  112. Functions to stand up an SSHD server to serve up git repos for tests.
  113. '''
  114. sshd_proc = None
  115. @classmethod
  116. def prep_server(cls):
  117. cls.sshd_config_dir = tempfile.mkdtemp(dir=TMP)
  118. cls.sshd_config = os.path.join(cls.sshd_config_dir, 'sshd_config')
  119. cls.sshd_port = get_unused_localhost_port()
  120. cls.url = 'ssh://{username}@127.0.0.1:{port}/~/repo.git'.format(
  121. username=cls.username,
  122. port=cls.sshd_port)
  123. cls.url_extra_repo = 'ssh://{username}@127.0.0.1:{port}/~/extra_repo.git'.format(
  124. username=cls.username,
  125. port=cls.sshd_port)
  126. home = '/root/.ssh'
  127. cls.ext_opts = {
  128. 'url': cls.url,
  129. 'url_extra_repo': cls.url_extra_repo,
  130. 'privkey_nopass': os.path.join(home, cls.id_rsa_nopass),
  131. 'pubkey_nopass': os.path.join(home, cls.id_rsa_nopass + '.pub'),
  132. 'privkey_withpass': os.path.join(home, cls.id_rsa_withpass),
  133. 'pubkey_withpass': os.path.join(home, cls.id_rsa_withpass + '.pub'),
  134. 'passphrase': cls.passphrase}
  135. def spawn_server(self):
  136. ret = self.run_function(
  137. 'state.apply',
  138. mods='git_pillar.ssh',
  139. pillar={'git_pillar': {'git_ssh': self.git_ssh,
  140. 'id_rsa_nopass': self.id_rsa_nopass,
  141. 'id_rsa_withpass': self.id_rsa_withpass,
  142. 'sshd_bin': self.sshd_bin,
  143. 'sshd_port': self.sshd_port,
  144. 'sshd_config_dir': self.sshd_config_dir,
  145. 'master_user': self.master_opts['user'],
  146. 'user': self.username}}
  147. )
  148. try:
  149. self.sshd_proc = self.wait_proc(name='sshd',
  150. search=self.sshd_config)
  151. finally:
  152. # Do the assert after we check for the PID so that we can track
  153. # it regardless of whether or not something else in the SLS
  154. # failed (but the SSH server still started).
  155. self.assertSaltTrueReturn(ret)
  156. class WebserverMixin(ModuleCase, ProcessManager, SaltReturnAssertsMixin):
  157. '''
  158. Functions to stand up an nginx + uWSGI + git-http-backend webserver to
  159. serve up git repos for tests.
  160. '''
  161. nginx_proc = uwsgi_proc = None
  162. @classmethod
  163. def prep_server(cls):
  164. '''
  165. Set up all the webserver paths. Designed to be run once in a
  166. setUpClass function.
  167. '''
  168. cls.root_dir = tempfile.mkdtemp(dir=TMP)
  169. cls.config_dir = os.path.join(cls.root_dir, 'config')
  170. cls.nginx_conf = os.path.join(cls.config_dir, 'nginx.conf')
  171. cls.uwsgi_conf = os.path.join(cls.config_dir, 'uwsgi.yml')
  172. cls.git_dir = os.path.join(cls.root_dir, 'git')
  173. cls.repo_dir = os.path.join(cls.git_dir, 'repos')
  174. cls.venv_dir = os.path.join(cls.root_dir, 'venv')
  175. cls.uwsgi_bin = os.path.join(cls.venv_dir, 'bin', 'uwsgi')
  176. cls.nginx_port = cls.uwsgi_port = get_unused_localhost_port()
  177. while cls.uwsgi_port == cls.nginx_port:
  178. # Ensure we don't hit a corner case in which two sucessive calls to
  179. # get_unused_localhost_port() return identical port numbers.
  180. cls.uwsgi_port = get_unused_localhost_port()
  181. cls.url = 'http://127.0.0.1:{port}/repo.git'.format(port=cls.nginx_port)
  182. cls.url_extra_repo = 'http://127.0.0.1:{port}/extra_repo.git'.format(port=cls.nginx_port)
  183. cls.ext_opts = {'url': cls.url, 'url_extra_repo': cls.url_extra_repo}
  184. # Add auth params if present (if so this will trigger the spawned
  185. # server to turn on HTTP basic auth).
  186. for credential_param in ('user', 'password'):
  187. if hasattr(cls, credential_param):
  188. cls.ext_opts[credential_param] = getattr(cls, credential_param)
  189. @requires_system_grains
  190. def spawn_server(self, grains):
  191. auth_enabled = hasattr(self, 'username') and hasattr(self, 'password')
  192. pillar = {'git_pillar': {'config_dir': self.config_dir,
  193. 'git_dir': self.git_dir,
  194. 'venv_dir': self.venv_dir,
  195. 'root_dir': self.root_dir,
  196. 'nginx_port': self.nginx_port,
  197. 'uwsgi_port': self.uwsgi_port,
  198. 'auth_enabled': auth_enabled}}
  199. # Different libexec dir for git backend on Debian-based systems
  200. git_core = '/usr/libexec/git-core' \
  201. if grains['os_family'] in ('RedHat') \
  202. else '/usr/lib/git-core'
  203. pillar['git_pillar']['git-http-backend'] = os.path.join(
  204. git_core,
  205. 'git-http-backend')
  206. ret = self.run_function(
  207. 'state.apply',
  208. mods='git_pillar.http',
  209. pillar=pillar)
  210. if not os.path.exists(pillar['git_pillar']['git-http-backend']):
  211. self.fail(
  212. '{0} not found. Either git is not installed, or the test '
  213. 'class needs to be updated.'.format(
  214. pillar['git_pillar']['git-http-backend']
  215. )
  216. )
  217. try:
  218. self.nginx_proc = self.wait_proc(name='nginx',
  219. search=self.nginx_conf)
  220. self.uwsgi_proc = self.wait_proc(name='uwsgi',
  221. search=self.uwsgi_conf)
  222. finally:
  223. # Do the assert after we check for the PID so that we can track
  224. # it regardless of whether or not something else in the SLS
  225. # failed (but the webserver still started).
  226. self.assertSaltTrueReturn(ret)
  227. class GitTestBase(ModuleCase):
  228. '''
  229. Base class for all gitfs/git_pillar tests. Must be subclassed and paired
  230. with either SSHDMixin or WebserverMixin to provide the server.
  231. '''
  232. case = port = bare_repo = base_extra_repo = admin_repo = admin_extra_repo = None
  233. maxDiff = None
  234. git_opts = '-c user.name="Foo Bar" -c user.email=foo@bar.com'
  235. ext_opts = {}
  236. # We need to temporarily skip pygit2 tests on EL7 until the EPEL packager
  237. # updates pygit2 to bring it up-to-date with libgit2.
  238. @requires_system_grains
  239. def is_el7(self, grains):
  240. return grains['os_family'] == 'RedHat' and grains['osmajorrelease'] == 7
  241. # Cent OS 6 has too old a version of git to handle the make_repo code, as
  242. # it lacks the -c option for git itself.
  243. @requires_system_grains
  244. def is_pre_el7(self, grains):
  245. return grains['os_family'] == 'RedHat' and grains['osmajorrelease'] < 7
  246. @classmethod
  247. def setUpClass(cls):
  248. cls.prep_server()
  249. def setUp(self):
  250. # Make the test class available to the tearDownClass so we can clean up
  251. # after ourselves. This (and the gated block below) prevent us from
  252. # needing to spend the extra time creating an ssh server and user and
  253. # then tear them down separately for each test.
  254. self.update_class(self)
  255. if self.is_pre_el7(): # pylint: disable=E1120
  256. self.skipTest(
  257. 'RHEL < 7 has too old a version of git to run these tests')
  258. @classmethod
  259. def update_class(cls, case):
  260. '''
  261. Make the test class available to the tearDownClass. Note that this
  262. cannot be defined in a parent class and inherited, as this will cause
  263. the parent class to be modified.
  264. '''
  265. if getattr(cls, 'case') is None:
  266. setattr(cls, 'case', case)
  267. def make_repo(self, root_dir, user='root'):
  268. raise NotImplementedError()
  269. class GitFSTestBase(GitTestBase, LoaderModuleMockMixin):
  270. '''
  271. Base class for all gitfs tests
  272. '''
  273. @requires_system_grains
  274. def setup_loader_modules(self, grains): # pylint: disable=W0221
  275. return {
  276. gitfs: {
  277. '__opts__': copy.copy(_OPTS),
  278. '__grains__': grains,
  279. }
  280. }
  281. def make_repo(self, root_dir, user='root'):
  282. raise NotImplementedError()
  283. class GitPillarTestBase(GitTestBase, LoaderModuleMockMixin):
  284. '''
  285. Base class for all git_pillar tests
  286. '''
  287. @requires_system_grains
  288. def setup_loader_modules(self, grains): # pylint: disable=W0221
  289. return {
  290. git_pillar: {
  291. '__opts__': copy.copy(_OPTS),
  292. '__grains__': grains,
  293. }
  294. }
  295. def get_pillar(self, ext_pillar_conf):
  296. '''
  297. Run git_pillar with the specified configuration
  298. '''
  299. cachedir = tempfile.mkdtemp(dir=TMP)
  300. self.addCleanup(shutil.rmtree, cachedir, ignore_errors=True)
  301. ext_pillar_opts = {'optimization_order': [0, 1, 2]}
  302. ext_pillar_opts.update(
  303. salt.utils.yaml.safe_load(
  304. ext_pillar_conf.format(
  305. cachedir=cachedir,
  306. extmods=os.path.join(cachedir, 'extmods'),
  307. **self.ext_opts
  308. )
  309. )
  310. )
  311. with patch.dict(git_pillar.__opts__, ext_pillar_opts):
  312. return git_pillar.ext_pillar(
  313. 'minion',
  314. {},
  315. *ext_pillar_opts['ext_pillar'][0]['git']
  316. )
  317. def make_repo(self, root_dir, user='root'):
  318. self.bare_repo = os.path.join(root_dir, 'repo.git')
  319. self.admin_repo = os.path.join(root_dir, 'admin')
  320. for dirname in (self.bare_repo, self.admin_repo):
  321. shutil.rmtree(dirname, ignore_errors=True)
  322. # Create bare repo
  323. self.run_function(
  324. 'git.init',
  325. [self.bare_repo],
  326. user=user,
  327. bare=True)
  328. # Clone bare repo
  329. self.run_function(
  330. 'git.clone',
  331. [self.admin_repo],
  332. url=self.bare_repo,
  333. user=user)
  334. def _push(branch, message):
  335. self.run_function(
  336. 'git.add',
  337. [self.admin_repo, '.'],
  338. user=user)
  339. self.run_function(
  340. 'git.commit',
  341. [self.admin_repo, message],
  342. user=user,
  343. git_opts=self.git_opts,
  344. )
  345. self.run_function(
  346. 'git.push',
  347. [self.admin_repo],
  348. remote='origin',
  349. ref=branch,
  350. user=user,
  351. )
  352. with salt.utils.files.fopen(
  353. os.path.join(self.admin_repo, 'top.sls'), 'w') as fp_:
  354. fp_.write(textwrap.dedent('''\
  355. base:
  356. '*':
  357. - foo
  358. '''))
  359. with salt.utils.files.fopen(
  360. os.path.join(self.admin_repo, 'foo.sls'), 'w') as fp_:
  361. fp_.write(textwrap.dedent('''\
  362. branch: master
  363. mylist:
  364. - master
  365. mydict:
  366. master: True
  367. nested_list:
  368. - master
  369. nested_dict:
  370. master: True
  371. '''))
  372. # Add another file to be referenced using git_pillar_includes
  373. with salt.utils.files.fopen(
  374. os.path.join(self.admin_repo, 'bar.sls'), 'w') as fp_:
  375. fp_.write('included_pillar: True\n')
  376. # Add another file in subdir
  377. os.mkdir(os.path.join(self.admin_repo, 'subdir'))
  378. with salt.utils.files.fopen(
  379. os.path.join(self.admin_repo, 'subdir', 'bar.sls'), 'w') as fp_:
  380. fp_.write('from_subdir: True\n')
  381. _push('master', 'initial commit')
  382. # Do the same with different values for "dev" branch
  383. self.run_function(
  384. 'git.checkout',
  385. [self.admin_repo],
  386. user=user,
  387. opts='-b dev')
  388. # The bar.sls shouldn't be in any branch but master
  389. self.run_function(
  390. 'git.rm',
  391. [self.admin_repo, 'bar.sls'],
  392. user=user)
  393. with salt.utils.files.fopen(
  394. os.path.join(self.admin_repo, 'top.sls'), 'w') as fp_:
  395. fp_.write(textwrap.dedent('''\
  396. dev:
  397. '*':
  398. - foo
  399. '''))
  400. with salt.utils.files.fopen(
  401. os.path.join(self.admin_repo, 'foo.sls'), 'w') as fp_:
  402. fp_.write(textwrap.dedent('''\
  403. branch: dev
  404. mylist:
  405. - dev
  406. mydict:
  407. dev: True
  408. nested_list:
  409. - dev
  410. nested_dict:
  411. dev: True
  412. '''))
  413. _push('dev', 'add dev branch')
  414. # Create just a top file in a separate repo, to be mapped to the base
  415. # env and referenced using git_pillar_includes
  416. self.run_function(
  417. 'git.checkout',
  418. [self.admin_repo],
  419. user=user,
  420. opts='-b top_only')
  421. # The top.sls should be the only file in this branch
  422. self.run_function(
  423. 'git.rm',
  424. [self.admin_repo, 'foo.sls', os.path.join('subdir', 'bar.sls')],
  425. user=user)
  426. with salt.utils.files.fopen(
  427. os.path.join(self.admin_repo, 'top.sls'), 'w') as fp_:
  428. fp_.write(textwrap.dedent('''\
  429. base:
  430. '*':
  431. - bar
  432. '''))
  433. _push('top_only', 'add top_only branch')
  434. # Create just another top file in a separate repo, to be mapped to the base
  435. # env and including mounted.bar
  436. self.run_function(
  437. 'git.checkout',
  438. [self.admin_repo],
  439. user=user,
  440. opts='-b top_mounted')
  441. # The top.sls should be the only file in this branch
  442. with salt.utils.files.fopen(
  443. os.path.join(self.admin_repo, 'top.sls'), 'w') as fp_:
  444. fp_.write(textwrap.dedent('''\
  445. base:
  446. '*':
  447. - mounted.bar
  448. '''))
  449. _push('top_mounted', 'add top_mounted branch')
  450. def make_extra_repo(self, root_dir, user='root'):
  451. self.bare_extra_repo = os.path.join(root_dir, 'extra_repo.git')
  452. self.admin_extra_repo = os.path.join(root_dir, 'admin_extra')
  453. for dirname in (self.bare_extra_repo, self.admin_extra_repo):
  454. shutil.rmtree(dirname, ignore_errors=True)
  455. # Create bare extra repo
  456. self.run_function(
  457. 'git.init',
  458. [self.bare_extra_repo],
  459. user=user,
  460. bare=True)
  461. # Clone bare repo
  462. self.run_function(
  463. 'git.clone',
  464. [self.admin_extra_repo],
  465. url=self.bare_extra_repo,
  466. user=user)
  467. def _push(branch, message):
  468. self.run_function(
  469. 'git.add',
  470. [self.admin_extra_repo, '.'],
  471. user=user)
  472. self.run_function(
  473. 'git.commit',
  474. [self.admin_extra_repo, message],
  475. user=user,
  476. git_opts=self.git_opts,
  477. )
  478. self.run_function(
  479. 'git.push',
  480. [self.admin_extra_repo],
  481. remote='origin',
  482. ref=branch,
  483. user=user,
  484. )
  485. with salt.utils.files.fopen(
  486. os.path.join(self.admin_extra_repo, 'top.sls'), 'w') as fp_:
  487. fp_.write(textwrap.dedent('''\
  488. "{{saltenv}}":
  489. '*':
  490. - motd
  491. - nowhere.foo
  492. '''))
  493. with salt.utils.files.fopen(
  494. os.path.join(self.admin_extra_repo, 'motd.sls'), 'w') as fp_:
  495. fp_.write(textwrap.dedent('''\
  496. motd: The force will be with you. Always.
  497. '''))
  498. _push('master', 'initial commit')
  499. class GitPillarSSHTestBase(GitPillarTestBase, SSHDMixin):
  500. '''
  501. Base class for GitPython and Pygit2 SSH tests
  502. '''
  503. id_rsa_nopass = id_rsa_withpass = None
  504. git_ssh = '/tmp/git_ssh'
  505. @classmethod
  506. def tearDownClass(cls):
  507. if cls.case is None:
  508. return
  509. if cls.case.sshd_proc is not None:
  510. cls.case.sshd_proc.send_signal(signal.SIGTERM)
  511. cls.case.run_state('user.absent', name=cls.username, purge=True)
  512. for dirname in (cls.sshd_config_dir, cls.case.admin_repo,
  513. cls.case.bare_repo):
  514. if dirname is not None:
  515. shutil.rmtree(dirname, ignore_errors=True)
  516. ssh_dir = os.path.expanduser('~/.ssh')
  517. for filename in (cls.id_rsa_nopass,
  518. cls.id_rsa_nopass + '.pub',
  519. cls.id_rsa_withpass,
  520. cls.id_rsa_withpass + '.pub',
  521. cls.git_ssh):
  522. try:
  523. os.remove(os.path.join(ssh_dir, filename))
  524. except OSError as exc:
  525. if exc.errno != errno.ENOENT:
  526. raise
  527. def setUp(self):
  528. '''
  529. Create the SSH server and user, and create the git repo
  530. '''
  531. super(GitPillarSSHTestBase, self).setUp()
  532. self.sshd_proc = self.find_proc(name='sshd',
  533. search=self.sshd_config)
  534. self.sshd_bin = salt.utils.path.which('sshd')
  535. if self.sshd_proc is None:
  536. self.spawn_server()
  537. known_hosts_ret = self.run_function(
  538. 'ssh.set_known_host',
  539. user=self.master_opts['user'],
  540. hostname='127.0.0.1',
  541. port=self.sshd_port,
  542. enc='ssh-rsa',
  543. fingerprint='fd:6f:7f:5d:06:6b:f2:06:0d:26:93:9e:5a:b5:19:46',
  544. hash_known_hosts=False,
  545. fingerprint_hash_type='md5',
  546. )
  547. if 'error' in known_hosts_ret:
  548. raise Exception(
  549. 'Failed to add key to {0} user\'s known_hosts '
  550. 'file: {1}'.format(
  551. self.master_opts['user'],
  552. known_hosts_ret['error']
  553. )
  554. )
  555. root_dir = os.path.expanduser('~{0}'.format(self.username))
  556. if root_dir.startswith('~'):
  557. self.fail(
  558. 'Unable to resolve homedir for user \'{0}\''.format(
  559. self.username
  560. )
  561. )
  562. self.make_repo(root_dir, user=self.username)
  563. self.make_extra_repo(root_dir, user=self.username)
  564. def get_pillar(self, ext_pillar_conf):
  565. '''
  566. Wrap the parent class' get_pillar() func in logic that temporarily
  567. changes the GIT_SSH to use our custom script, ensuring that the
  568. passphraselsess key is used to auth without needing to modify the root
  569. user's ssh config file.
  570. '''
  571. orig_git_ssh = os.environ.pop('GIT_SSH', NOTSET)
  572. os.environ['GIT_SSH'] = self.git_ssh
  573. try:
  574. return super(GitPillarSSHTestBase, self).get_pillar(ext_pillar_conf)
  575. finally:
  576. os.environ.pop('GIT_SSH', None)
  577. if orig_git_ssh is not NOTSET:
  578. os.environ['GIT_SSH'] = orig_git_ssh
  579. class GitPillarHTTPTestBase(GitPillarTestBase, WebserverMixin):
  580. '''
  581. Base class for GitPython and Pygit2 HTTP tests
  582. '''
  583. @classmethod
  584. def tearDownClass(cls):
  585. for proc in (cls.case.nginx_proc, cls.case.uwsgi_proc):
  586. if proc is not None:
  587. try:
  588. proc.send_signal(signal.SIGQUIT)
  589. except psutil.NoSuchProcess:
  590. pass
  591. shutil.rmtree(cls.root_dir, ignore_errors=True)
  592. def setUp(self):
  593. '''
  594. Create and start the webserver, and create the git repo
  595. '''
  596. super(GitPillarHTTPTestBase, self).setUp()
  597. self.nginx_proc = self.find_proc(name='nginx',
  598. search=self.nginx_conf)
  599. self.uwsgi_proc = self.find_proc(name='uwsgi',
  600. search=self.uwsgi_conf)
  601. if self.nginx_proc is None and self.uwsgi_proc is None:
  602. self.spawn_server() # pylint: disable=E1120
  603. self.make_repo(self.repo_dir)
  604. self.make_extra_repo(self.repo_dir)