test_rpmbuild_pkgbuild.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. # -*- coding: utf-8 -*-
  2. """
  3. Test the ssh module
  4. """
  5. from __future__ import absolute_import, print_function, unicode_literals
  6. import logging
  7. import os
  8. import re
  9. import shutil
  10. import subprocess
  11. import salt.utils.files
  12. import salt.utils.platform
  13. from tests.support.case import ModuleCase
  14. from tests.support.helpers import (
  15. destructiveTest,
  16. requires_salt_modules,
  17. requires_system_grains,
  18. skip_if_binaries_missing,
  19. skip_if_not_root,
  20. slowTest,
  21. )
  22. from tests.support.runtests import RUNTIME_VARS
  23. GPG_TEST_PRIV_KEY = """-----BEGIN PGP PRIVATE KEY BLOCK-----
  24. Version: GnuPG v2.0.22 (GNU/Linux)
  25. lQO+BF7qopoBCACVyX0rjtcbh1CMu0Od/luO14VvgEZ+u+MJaioiEN6NMU0SscBn
  26. A4/+BSu/f6DPc9MgJBM6AI0O4a7OM00kwZHODT3TykLEJKbL+taObkHcS9j5b5iA
  27. ife+56W8KLEZpYk6uhk9LXMKilc7R01qXgLrDgqx9kGIe/5bC/AtCEW656zOWRPn
  28. 1p55oWW2toM7pVkdsOG1UZ43uZq1+iTSuxe+FcH0NU0yPBISFa+x5kuKP+xBa8Ou
  29. n206+NGtnQQJjlbPtce/QrJU3mQP8xgBZBdU7NevxYTyQrkJXwUPqCXevqCU4KKX
  30. c+I+nAJsrvnbdcnBWe5bUvVnpKMOLguxeKtzABEBAAH+AwMCzrLgDoSW+UfkFdnF
  31. lSk/IWSYZJSZniMDuKgMk23lNRFShjg7zFwfvdcO1dNDQsz7FaGpxg3OasmKCPRp
  32. 0UBJEoQd7FwSM3GaG8+TSHcHc6AjwJgGKvJkVd2N++XyMxlqZe8xxjjtWw0FhUwI
  33. hHjh8eG5jPGipe2HX8R4r1Q367T+yHYsGNjjMwSWOY0oL1BCL0PxBzPcfcKeJ2kd
  34. jzbHlVfUlwvwfYZePrOjhEw+WC0cdASw4rEFFhKtrGByGm8L/BdZFitc6RIjQHgh
  35. T4wsfjOKqW4ZwL0QPIZdUkNJr/453fqKwgoikba710LyU7yuYxXtT7B05PbiempG
  36. r/zznl1ftlj+50FwciUX70MdEenSEDRibefhhYYucMLPJ9jtTEwHqysF8JqBcoHp
  37. EZ9FqtnChlzWjsO44BX1Nuk9bNyq5WCQLWapFksvH6Vz06JPDVtVr02eFogQgTKn
  38. bSQWoxFh/0eq/Kwit2AGfZLL8VmGNc6MFELiejzSlDbd1BZcohZrC0Wr8KsxBgbO
  39. h+6nchnV5r7hNjAR3/DgeBU9URqgXCmqEt0woantl0K4VP41Mu6EzZ+7DX1fP0K7
  40. 4iLVdH/az3j9RLVWp4rfBFsTeXbJ7fvWwRDOi7OrLzzyfHhzQVKNFKhhZtIKdk7m
  41. JN7rxcSWpCscZ3a9G5VoZsJ8sSNDbNMoG2diNFRLoD65qcoPTqXhDtTpt6En0cbW
  42. ed6gW+V6cgCa33Cju2t7RGzdv0ELPdV6W4YcF4xBzjmkSoqT7RSfZx17Pj2QkAiz
  43. dmI775GvkfXM63U24zhaJ+xJfbQuTBqMgby7R1f1gIcKNdTZkP8kp8vMR+LaZD05
  44. +DxP0I+o+poPpVXLhI/+N8lSEMxv1AoTfGXvPzE1nq7VeQDC0RSS1xFzh5FM9G8R
  45. i7RhU2FsdFN0YWNrIFBhY2thZ2luZyBUZWFtIChUaGlzIGtleSBpcyBmb3IgdGVz
  46. dGluZyBwYWNrYWdlIHNpZ25pbmcgb25seSkgPHBhY2thZ2luZ0BzYWx0c3RhY2su
  47. Y29tPokBOQQTAQIAIwUCXuqimgIbAwcLCQgHAwIBBhUIAgkKCwQWAgMBAh4BAheA
  48. AAoJEB9x5CcVTJJB0LUH/AvT1+EOSErOCzqOlwFIodLExH90PiXR6GbDzZPiaqmh
  49. hEY6xaf5vt8IlMZAhZcv9Gv6E+pXW0oFVGyTdaJEvfnF0VOE+xYuOM0XPTpxn1Ua
  50. GnTu52KZylxQBBkcxP44acKENQ1hCROnXu7nb0q83g1vdvKjwa2O1hKXVX209tTx
  51. Gkw75z8rHU6l7UpPwQ779AQfiMjAVGH+H09JtuUHXyBcJnC9AHmUqJeNaWEbv8UJ
  52. CnM8Qqz9IOCilREPeuCPGJ5yl9wvG8ZDjFJ26RMvMRfOozVzqUR3cYv0Ww0h9myb
  53. XkC6OJLOzH3WEayM3pOmUJgQXhWXL3inoKEG1qqnHIGdA74EXuqimgEIAOEvqyJC
  54. ++bXzHFB5QLkIo3YDel9IOKJ6F/z9619IJiWziHUqVk+9wdDPyHjnIq+1AXb0vLU
  55. dmIVmn5Sf5YvHin5tWn9iyID4vz4xy9mEKZe4vn+O6LVhf8u/aB32dQ1ObRQb0ja
  56. CtPoyxiQr+3Se/9W2hww+RLopzRy5pmcoooMbgYiE9ZsSaRtr5gk3/tHptdo1++D
  57. kFCW9gYj2edf85POoFthYMbj2chvmZMbPu1k1d3+Xqa5qdrfVRVFkQbJuXRUnU0J
  58. UQTq4B0RACiD8eJlu4jWidrrLWVukY5MCg+aPltCfH8MACN8M6XShGtM6W5xK0AX
  59. zLK/gw/NuvNl3qcAEQEAAf4DAwLOsuAOhJb5R+Rh8MHQD5JxUcA4R3s1mwfLf8GH
  60. OTi6S1ovLl7yqV6swkHG11y6WVEujHVKSLqySBleh6AgPcQRzkkg2HjHq29qG+cy
  61. aeDnt0xpb/RKSbiJrGLnUSbSDUB+GLJrIiFyUD6wckNx7gGX8XBczkDeatujUDoA
  62. 8Pk6M4QqRx7BolEM5ArYPT+qaSFl9O9Gxhg2urlo05QaWXvNYO3efUxg3wJAPt9h
  63. Xp7Z+EwSC+Q6kX7uXU+mLkBI1PcHYwC/1U5QbWDW7J4LCq09w1WLzMqNsV7UcpWm
  64. lsGrEd79KKHMvYCalUWPGzZPb3xWO3MN3wh9R/RcsvavFWxMolzSv70MNBh/xsrs
  65. FjxYXzt87dJ77GqOO3cPFZ3MbQ2iGdYYDtJSR4zv4zCj5h8nxW72K/LuFv386KzE
  66. T/OijfgCfdldV0bhNFwCKgXIJsjQdUx2aIlJyqod3fDlHMD27SZjeLzAj78q4p6b
  67. XvoMEpzTmMEc1tXRY4OlemhsTG1eP2hSqx1DZa52fQnYJTvk5WXmsNipF33oCX5d
  68. L1bG0haGR1Ph0bn/CU9RZdaAORxOQEnyUMAHgSDjdH4Z9Bu8BRcDhLEysyrRi3kX
  69. rSIeLFWAoNdJOtfF8z021bpyXv1rOjWEx5V9PNDJH6C2Y2kK5GQlzQCKx9lM5eTb
  70. EabJBcON8VJD0lXyG7U4YW/4u8WBE7wuSZ9tBBTk52h23/+wHr4glvXeYwQty5z4
  71. OGBRgm0LXt86PM+yw/1xqvA8g0UDN4NmfNev1YkoEOLN9VZthWQtt2qUCeCbSo+u
  72. LmtZgzIrU+9zaRc+byDnGIUwK/7GMdKTJHUjQUeWCocBbNXkeuG5HetBI2OgmhRp
  73. UEdjivoLeuhCSj7FFPpO81TXOKUEgIXFWKLXLGWkKKsCiQEfBBgBAgAJBQJe6qKa
  74. AhsMAAoJEB9x5CcVTJJBJdEIAIKlQ2csFOorfl9vXWXdMhMI8bQ87uFtpA/OuPOL
  75. KpMLcraQBhun/1BeLPdKCL0Mee/SXcATw43JBgi0/khOYqNEDEGSERQkkyNlkopf
  76. J50fxxJ0/PJTYHjJnvDL3z9L44o2acx2hjzr93S7hzQdEkAr8/EpMHushoCoVJyl
  77. +qdllBtzEyaQNQnHfydSS6I7WJ5C9FO+e+onDH2bgZWZXAgQyaUzXmjRvzhmh8Lp
  78. CNZBzPGVvoYfvGJRReq5b9OAy62wxxCkGV9lik+KzQDhaZggr3R+4NciZvW9nK5S
  79. bid1WZeSiPYUHRqQQnC4XDJ9+9+p9HzlEZZsfCeiRf5ALsk=
  80. =mNsA
  81. -----END PGP PRIVATE KEY BLOCK-----
  82. """
  83. GPG_TEST_PUB_KEY = """-----BEGIN PGP PUBLIC KEY BLOCK-----
  84. Version: GnuPG v2.0.22 (GNU/Linux)
  85. mQENBF7qopoBCACVyX0rjtcbh1CMu0Od/luO14VvgEZ+u+MJaioiEN6NMU0SscBn
  86. A4/+BSu/f6DPc9MgJBM6AI0O4a7OM00kwZHODT3TykLEJKbL+taObkHcS9j5b5iA
  87. ife+56W8KLEZpYk6uhk9LXMKilc7R01qXgLrDgqx9kGIe/5bC/AtCEW656zOWRPn
  88. 1p55oWW2toM7pVkdsOG1UZ43uZq1+iTSuxe+FcH0NU0yPBISFa+x5kuKP+xBa8Ou
  89. n206+NGtnQQJjlbPtce/QrJU3mQP8xgBZBdU7NevxYTyQrkJXwUPqCXevqCU4KKX
  90. c+I+nAJsrvnbdcnBWe5bUvVnpKMOLguxeKtzABEBAAG0YVNhbHRTdGFjayBQYWNr
  91. YWdpbmcgVGVhbSAoVGhpcyBrZXkgaXMgZm9yIHRlc3RpbmcgcGFja2FnZSBzaWdu
  92. aW5nIG9ubHkpIDxwYWNrYWdpbmdAc2FsdHN0YWNrLmNvbT6JATkEEwECACMFAl7q
  93. opoCGwMHCwkIBwMCAQYVCAIJCgsEFgIDAQIeAQIXgAAKCRAfceQnFUySQdC1B/wL
  94. 09fhDkhKzgs6jpcBSKHSxMR/dD4l0ehmw82T4mqpoYRGOsWn+b7fCJTGQIWXL/Rr
  95. +hPqV1tKBVRsk3WiRL35xdFThPsWLjjNFz06cZ9VGhp07udimcpcUAQZHMT+OGnC
  96. hDUNYQkTp17u529KvN4Nb3byo8GtjtYSl1V9tPbU8RpMO+c/Kx1Ope1KT8EO+/QE
  97. H4jIwFRh/h9PSbblB18gXCZwvQB5lKiXjWlhG7/FCQpzPEKs/SDgopURD3rgjxie
  98. cpfcLxvGQ4xSdukTLzEXzqM1c6lEd3GL9FsNIfZsm15AujiSzsx91hGsjN6TplCY
  99. EF4Vly94p6ChBtaqpxyBuQENBF7qopoBCADhL6siQvvm18xxQeUC5CKN2A3pfSDi
  100. iehf8/etfSCYls4h1KlZPvcHQz8h45yKvtQF29Ly1HZiFZp+Un+WLx4p+bVp/Ysi
  101. A+L8+McvZhCmXuL5/jui1YX/Lv2gd9nUNTm0UG9I2grT6MsYkK/t0nv/VtocMPkS
  102. 6Kc0cuaZnKKKDG4GIhPWbEmkba+YJN/7R6bXaNfvg5BQlvYGI9nnX/OTzqBbYWDG
  103. 49nIb5mTGz7tZNXd/l6muana31UVRZEGybl0VJ1NCVEE6uAdEQAog/HiZbuI1ona
  104. 6y1lbpGOTAoPmj5bQnx/DAAjfDOl0oRrTOlucStAF8yyv4MPzbrzZd6nABEBAAGJ
  105. AR8EGAECAAkFAl7qopoCGwwACgkQH3HkJxVMkkEl0QgAgqVDZywU6it+X29dZd0y
  106. EwjxtDzu4W2kD86484sqkwtytpAGG6f/UF4s90oIvQx579JdwBPDjckGCLT+SE5i
  107. o0QMQZIRFCSTI2WSil8nnR/HEnT88lNgeMme8MvfP0vjijZpzHaGPOv3dLuHNB0S
  108. QCvz8Skwe6yGgKhUnKX6p2WUG3MTJpA1Ccd/J1JLojtYnkL0U7576icMfZuBlZlc
  109. CBDJpTNeaNG/OGaHwukI1kHM8ZW+hh+8YlFF6rlv04DLrbDHEKQZX2WKT4rNAOFp
  110. mCCvdH7g1yJm9b2crlJuJ3VZl5KI9hQdGpBCcLhcMn3736n0fOURlmx8J6JF/kAu
  111. yQ==
  112. =6abY
  113. -----END PGP PUBLIC KEY BLOCK-----
  114. """
  115. GPG_TEST_KEY_PASSPHRASE = "saltstacktestingpackages"
  116. GPG_TEST_KEY_ID = "154C9241"
  117. GPG_AGENT_CONF = """default-cache-ttl 600
  118. default-cache-ttl-ssh 600
  119. max-cache-ttl 600
  120. max-cache-ttl-ssh 600
  121. allow-preset-passphrase
  122. daemon
  123. debug-all
  124. ## debug-pinentry
  125. log-file /root/gpg-agent.log
  126. verbose
  127. # PIN entry program
  128. pinentry-program /usr/bin/pinentry-gtk
  129. pinentry-timeout 30
  130. allow-loopback-pinentry
  131. """
  132. TEST_SYSTEM_USER = "root"
  133. TEST_SYSTEM_GROUP = "root"
  134. log = logging.getLogger(__name__)
  135. def _testrpm_signed(abs_path_named_rpm):
  136. try:
  137. rpm_chk_sign = subprocess.Popen(
  138. ["rpm", "--checksig", "-v", abs_path_named_rpm],
  139. shell=False,
  140. close_fds=True,
  141. stdout=subprocess.PIPE,
  142. stderr=subprocess.PIPE,
  143. ).communicate()[0]
  144. except OSError:
  145. return False
  146. if not rpm_chk_sign:
  147. log.debug("problem checking signatures on rpm")
  148. return False
  149. test_string = GPG_TEST_KEY_ID.lower() + ": OK"
  150. CHECK_KEYID_OK = re.compile(test_string, re.M)
  151. retrc = CHECK_KEYID_OK.search(rpm_chk_sign.decode())
  152. log.debug(
  153. "signed checking, found test_string '{0}' in rpm_chk_sign '{1}', return code '{2}'".format(
  154. test_string, rpm_chk_sign, retrc
  155. )
  156. )
  157. if retrc:
  158. return True
  159. return False
  160. @skip_if_binaries_missing(["gpg", "rpm", "createrepo"], check_all=True)
  161. class RPMSignModuleTest(ModuleCase):
  162. """
  163. Test the RPM Signing module
  164. """
  165. @classmethod
  166. def setUpClass(cls):
  167. cls.subsalt_dir = os.path.join(RUNTIME_VARS.TMP, "subsalt")
  168. cls.gpghome = os.path.join(cls.subsalt_dir, ".gnupg")
  169. cls.repodir = os.path.join(cls.subsalt_dir, "repodir")
  170. @requires_salt_modules("gpg")
  171. def setUp(self):
  172. """
  173. Set up the rpm signing module tests
  174. """
  175. super(RPMSignModuleTest, self).setUp()
  176. if not os.path.isdir(self.subsalt_dir):
  177. os.makedirs(self.subsalt_dir)
  178. if not os.path.isdir(self.gpghome):
  179. os.makedirs(self.gpghome)
  180. os.chmod(self.gpghome, 0o600)
  181. if not os.path.isdir(self.repodir):
  182. os.makedirs(self.repodir)
  183. self.repo_named_rpm = "hello-2.10-1.el7.x86_64.rpm"
  184. shutil.copy(os.path.join(RUNTIME_VARS.FILES, self.repo_named_rpm), self.repodir)
  185. gpg_conf_path = os.path.join(self.gpghome, "gpg.conf")
  186. self.gpg_conf = "use-agent"
  187. with salt.utils.files.fopen(gpg_conf_path, "wb") as fd:
  188. fd.write(self.gpg_conf.encode())
  189. gpg_agent_conf_path = os.path.join(self.gpghome, "gpg-agent.conf")
  190. self.gpg_agent_conf = GPG_AGENT_CONF
  191. with salt.utils.files.fopen(gpg_agent_conf_path, "wb") as fd:
  192. fd.write(self.gpg_agent_conf.encode())
  193. gpg_pkg_key_pem_path = os.path.join(self.gpghome, "gpg_pkg_key.pem")
  194. self.gpg_pkg_key_pem = GPG_TEST_PRIV_KEY
  195. with salt.utils.files.fopen(gpg_pkg_key_pem_path, "wb") as fd:
  196. fd.write(self.gpg_pkg_key_pem.encode())
  197. gpg_pkg_key_pub_path = os.path.join(self.gpghome, "gpg_pkg_key.pub")
  198. self.gpg_pkg_key_pub = GPG_TEST_PUB_KEY
  199. with salt.utils.files.fopen(gpg_pkg_key_pub_path, "wb") as fd:
  200. fd.write(self.gpg_pkg_key_pub.encode())
  201. self.gpg_passphrase = GPG_TEST_KEY_PASSPHRASE
  202. self.gpg_keyid = GPG_TEST_KEY_ID
  203. def tearDown(self):
  204. """
  205. Tear down the rpm signing module tests
  206. """
  207. if os.path.isdir(self.repodir):
  208. shutil.rmtree(self.repodir)
  209. if os.path.isdir(self.gpghome):
  210. shutil.rmtree(self.gpghome)
  211. if os.path.isdir(self.subsalt_dir):
  212. shutil.rmtree(self.subsalt_dir)
  213. super(RPMSignModuleTest, self).tearDown()
  214. del self.gpg_passphrase
  215. del self.gpg_keyid
  216. del self.gpg_pkg_key_pub
  217. del self.gpg_pkg_key_pem
  218. del self.gpg_agent_conf
  219. del self.gpg_conf
  220. @slowTest
  221. @skip_if_not_root
  222. @skip_if_binaries_missing(
  223. ["gpgconf", "gpg-agent", "/usr/libexec/gpg-preset-passphrase"], check_all=True
  224. )
  225. @requires_system_grains
  226. @destructiveTest
  227. @requires_salt_modules("pkgbuild.make_repo")
  228. def test_make_repo_with_gpg_agent(self, grains):
  229. """
  230. test make repo, signing rpm
  231. """
  232. if not (grains["os_family"] == "RedHat" and grains["osmajorrelease"] >= 8):
  233. self.skipTest(
  234. "TODO: test not configured for {0} and major release {1}".format(
  235. grains["os_family"], grains["osmajorrelease"]
  236. )
  237. )
  238. pillar = self.run_function("pillar.data")
  239. self.assertEqual(pillar["gpg_passphrase"], "saltstacktestingpackages")
  240. self.assertEqual(pillar["gpg_pkg_pub_keyname"], "gpg_pkg_key.pub")
  241. # launch gpg-agent
  242. self.run_function(
  243. "cmd.run", ["gpgconf --kill gpg-agent"], template="jinja", python_shell=True
  244. )
  245. gpg_agent_cmd = "gpg-agent --homedir {0} --allow-preset-passphrase --max-cache-ttl 600 --daemon".format(
  246. self.gpghome
  247. )
  248. gpg_tty_info_path = os.path.join(self.gpghome, "gpg_tty_info")
  249. self.run_function(
  250. "cmd.run",
  251. ["{0}".format(gpg_agent_cmd)],
  252. template="jinja",
  253. python_shell=True,
  254. )
  255. self.run_function(
  256. "cmd.run",
  257. [
  258. "{0}".format(gpg_agent_cmd),
  259. "GPG_TTY=$(tty) ; export GPG_TTY ; echo $GPG_TTY=$(tty) > {0}".format(
  260. gpg_tty_info_path
  261. ),
  262. ],
  263. template="jinja",
  264. python_shell=True,
  265. )
  266. # sign rpm and create repo
  267. ret = self.run_function(
  268. "pkgbuild.make_repo",
  269. repodir=self.repodir,
  270. keyid=self.gpg_keyid,
  271. env=None,
  272. use_passphrase=True,
  273. gnupghome=self.gpghome,
  274. runas="root",
  275. timeout=15.0,
  276. )
  277. self.assertNotEqual(ret, {})
  278. test_rpm_path = os.path.join(self.repodir, self.repo_named_rpm)
  279. self.assertTrue(_testrpm_signed(test_rpm_path))
  280. test_repodata_path = os.path.join(self.repodir, "repodata")
  281. self.assertTrue(os.path.isdir(test_repodata_path))
  282. test_repomd_xml_path = os.path.join(test_repodata_path, "repomd.xml")
  283. self.assertTrue(os.path.isfile(test_repomd_xml_path))
  284. self.run_function(
  285. "cmd.run", ["gpgconf --kill gpg-agent"], template="jinja", python_shell=True
  286. )
  287. @slowTest
  288. @skip_if_not_root
  289. @requires_system_grains
  290. @destructiveTest
  291. @requires_salt_modules("pkgbuild.make_repo")
  292. def test_make_repo_no_gpg_agent(self, grains):
  293. """
  294. test make repo, signing rpm
  295. """
  296. if not (grains["os_family"] == "RedHat" or grains["os_family"] == "Amazon"):
  297. self.skipTest(
  298. "TODO: test not configured for {0}".format(grains["os_family"])
  299. )
  300. if grains["os_family"] == "RedHat" and grains["osmajorrelease"] >= 8:
  301. self.skipTest(
  302. "TODO: test not configured for {0} and major release {1}".format(
  303. grains["os_family"], grains["osmajorrelease"]
  304. )
  305. )
  306. if grains["os_family"] == "Amazon" and grains["osmajorrelease"] != 2:
  307. self.skipTest(
  308. "TODO: test not configured for {0} and major release {1}".format(
  309. grains["os_family"], grains["osmajorrelease"]
  310. )
  311. )
  312. pillar = self.run_function("pillar.data")
  313. self.assertEqual(pillar["gpg_passphrase"], "saltstacktestingpackages")
  314. self.assertEqual(pillar["gpg_pkg_pub_keyname"], "gpg_pkg_key.pub")
  315. # sign rpm and create repo
  316. ret = self.run_function(
  317. "pkgbuild.make_repo",
  318. repodir=self.repodir,
  319. keyid=self.gpg_keyid,
  320. env=None,
  321. use_passphrase=True,
  322. gnupghome=self.gpghome,
  323. runas="root",
  324. timeout=15.0,
  325. )
  326. self.assertNotEqual(ret, {})
  327. test_rpm_path = os.path.join(self.repodir, self.repo_named_rpm)
  328. self.assertTrue(_testrpm_signed(test_rpm_path))
  329. test_repodata_path = os.path.join(self.repodir, "repodata")
  330. self.assertTrue(os.path.isdir(test_repodata_path))
  331. test_repomd_xml_path = os.path.join(test_repodata_path, "repomd.xml")
  332. self.assertTrue(os.path.isfile(test_repomd_xml_path))