IF YOU WOULD LIKE TO GET AN ACCOUNT, please write an email to s dot adaszewski at gmail dot com. User accounts are meant only to report issues and/or generate pull requests. This is a purpose-specific Git hosting for ADARED projects. Thank you for your understanding!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

232 lines
9.3KB

  1. import pytest
  2. from focker.image import validate_spec, \
  3. build_squeeze, \
  4. build, \
  5. command_image_build, \
  6. command_image_tag, \
  7. command_image_untag, \
  8. command_image_list, \
  9. command_image_prune, \
  10. command_image_remove
  11. import subprocess
  12. from tempfile import TemporaryDirectory
  13. import focker.image
  14. import os
  15. from focker.zfs import zfs_find, \
  16. zfs_mountpoint, \
  17. zfs_exists_snapshot_sha256, \
  18. zfs_parse_output, \
  19. zfs_exists
  20. from focker.misc import focker_unlock
  21. import yaml
  22. def test_validate_spec_01():
  23. spec = { 'base': 'base', 'steps': 'steps' }
  24. validate_spec(spec)
  25. def test_validate_spec_02():
  26. spec = { 'steps': 'steps' }
  27. with pytest.raises(ValueError):
  28. validate_spec(spec)
  29. def test_validate_spec_03():
  30. spec = { 'base': 'base' }
  31. with pytest.raises(ValueError):
  32. validate_spec(spec)
  33. def test_validate_spec_04():
  34. spec = {}
  35. with pytest.raises(ValueError):
  36. validate_spec(spec)
  37. def test_build_squeeze(monkeypatch):
  38. focker_unlock()
  39. subprocess.check_output(['focker', 'image', 'remove', '--force', '-R', 'test-build-squeeze-base'])
  40. subprocess.check_output(['focker', 'bootstrap', '--empty', '-t', 'test-build-squeeze-base'])
  41. spec = dict(base='test-build-squeeze-base', steps=[
  42. dict(copy=['/etc/localtime', '/etc/localtime']),
  43. dict(copy=['/etc/hosts', '/etc/hosts'])
  44. ])
  45. _, base_sha256 = zfs_find('test-build-squeeze-base', focker_type='image')
  46. def fail(sha256, *args, **kwargs):
  47. if sha256 != base_sha256:
  48. raise RuntimeError('No pre-existing layers expected apart from base')
  49. monkeypatch.setattr(focker.image, 'zfs_snapshot_by_sha256', fail)
  50. with TemporaryDirectory() as d:
  51. args = lambda: 0
  52. args.focker_dir = d
  53. name, _ = build_squeeze(spec, args)
  54. focker_unlock()
  55. mountpoint = zfs_mountpoint(name.split('@')[0])
  56. print('name:', name, 'mountpoint:', mountpoint)
  57. assert os.path.exists(os.path.join(mountpoint, 'etc/localtime'))
  58. assert os.path.exists(os.path.join(mountpoint, 'etc/hosts'))
  59. subprocess.check_output(['focker', 'image', 'remove', '-R', 'test-build-squeeze-base'])
  60. assert not os.path.exists(mountpoint)
  61. def test_build(monkeypatch):
  62. focker_unlock()
  63. subprocess.check_output(['focker', 'image', 'remove', '--force', '-R', 'test-build-squeeze-base'])
  64. subprocess.check_output(['focker', 'bootstrap', '--empty', '-t', 'test-build-squeeze-base'])
  65. spec = dict(base='test-build-squeeze-base', steps=[
  66. dict(copy=['/etc/localtime', '/etc/localtime']),
  67. dict(copy=['/etc/hosts', '/etc/hosts'])
  68. ])
  69. _, base_sha256 = zfs_find('test-build-squeeze-base', focker_type='image')
  70. counter = 0
  71. def count_calls(*args, **kwargs):
  72. nonlocal counter
  73. counter += 1
  74. return zfs_exists_snapshot_sha256(*args, **kwargs)
  75. monkeypatch.setattr(focker.image, 'zfs_exists_snapshot_sha256', count_calls)
  76. with TemporaryDirectory() as d:
  77. args = lambda: 0
  78. args.focker_dir = d
  79. name, _ = build(spec, args)
  80. assert counter == 2
  81. focker_unlock()
  82. mountpoint = zfs_mountpoint(name.split('@')[0])
  83. print('name:', name, 'mountpoint:', mountpoint)
  84. assert os.path.exists(os.path.join(mountpoint, 'etc/localtime'))
  85. assert os.path.exists(os.path.join(mountpoint, 'etc/hosts'))
  86. subprocess.check_output(['focker', 'image', 'remove', '-R', 'test-build-squeeze-base'])
  87. assert not os.path.exists(mountpoint)
  88. def test_command_image_build():
  89. focker_unlock()
  90. subprocess.check_output(['focker', 'image', 'remove', '--force', '-R', 'test-command-image-build-base'])
  91. subprocess.check_output(['focker', 'bootstrap', '--empty', '-t', 'test-command-image-build-base'])
  92. with TemporaryDirectory() as d:
  93. args = lambda: 0
  94. with open(os.path.join(d, 'Fockerfile'), 'w') as f:
  95. yaml.dump(dict(base='test-command-image-build-base', steps=[
  96. dict(copy=['/etc/localtime', '/etc/localtime']),
  97. dict(copy=['/etc/hosts', '/etc/hosts'])
  98. ]), f)
  99. args.focker_dir = d
  100. args.squeeze = False
  101. args.tags = [ 'test-command-image-build' ]
  102. command_image_build(args)
  103. focker_unlock()
  104. name, _ = zfs_find('test-command-image-build', focker_type='image')
  105. mountpoint = zfs_mountpoint(name)
  106. assert os.path.exists(os.path.join(mountpoint, 'etc/localtime'))
  107. assert os.path.exists(os.path.join(mountpoint, 'etc/hosts'))
  108. subprocess.check_output(['focker', 'image', 'remove', '-R', 'test-command-image-build-base'])
  109. assert not os.path.exists(mountpoint)
  110. def test_command_image_tag():
  111. focker_unlock()
  112. subprocess.check_output(['focker', 'image', 'remove', '--force', '-R', 'test-command-image-tag'])
  113. subprocess.check_output(['focker', 'bootstrap', '--empty', '-t', 'test-command-image-tag'])
  114. name_1, sha256_1 = zfs_find('test-command-image-tag', focker_type='image')
  115. args = lambda: 0
  116. args.reference = sha256_1
  117. args.tags = ['test-a', 'test-b', 'test-c']
  118. command_image_tag(args)
  119. for t in args.tags:
  120. name_2, sha256_2 = zfs_find(t, focker_type='image')
  121. assert name_2 == name_1
  122. assert sha256_2 == sha256_1
  123. subprocess.check_output(['focker', 'image', 'remove', '-R', 'test-command-image-tag'])
  124. for t in args.tags:
  125. with pytest.raises(ValueError):
  126. zfs_find(t, focker_type='image')
  127. with pytest.raises(ValueError):
  128. zfs_find('test-command-image-tag', focker_type='image')
  129. def test_command_image_untag():
  130. focker_unlock()
  131. subprocess.check_output(['focker', 'image', 'remove', '--force', '-R', 'test-command-image-untag'])
  132. subprocess.check_output(['focker', 'bootstrap', '--empty', '-t', 'test-command-image-untag', 'test-command-image-untag-1', 'test-command-image-untag-2'])
  133. name, sha256 = zfs_find('test-command-image-untag', focker_type='image')
  134. args = lambda: 0
  135. args.tags = ['test-command-image-untag-1', 'test-command-image-untag-2']
  136. command_image_untag(args)
  137. tags = zfs_parse_output(['zfs', 'get', '-H', 'focker:tags', name])
  138. tags = tags[0][2].split(',')
  139. assert tags == ['test-command-image-untag']
  140. with pytest.raises(ValueError):
  141. zfs_find('test-command-image-untag-1', focker_type='image')
  142. with pytest.raises(ValueError):
  143. zfs_find('test-command-image-untag-2', focker_type='image')
  144. subprocess.check_output(['focker', 'image', 'remove', 'test-command-image-untag'])
  145. def test_command_image_list(monkeypatch):
  146. focker_unlock()
  147. subprocess.check_output(['focker', 'image', 'remove', '--force', '-R', 'test-command-image-list'])
  148. subprocess.check_output(['focker', 'bootstrap', '--empty', '-t', 'test-command-image-list', 'test-command-image-list-1', 'test-command-image-list-2'])
  149. name, sha256 = zfs_find('test-command-image-list', focker_type='image')
  150. args = lambda: 0
  151. args.tagged_only = True
  152. args.full_sha256 = True
  153. lst = None
  154. headers = None
  155. def fake_tabulate(*args, **kwargs):
  156. nonlocal lst
  157. nonlocal headers
  158. lst = args[0]
  159. headers = kwargs['headers']
  160. monkeypatch.setattr(focker.image, 'tabulate', fake_tabulate)
  161. command_image_list(args)
  162. assert lst is not None
  163. assert headers == ['Tags', 'Size', 'SHA256', 'Base']
  164. assert len(lst) >= 3
  165. match = list(filter(lambda a: sorted(a[0].split(' ')) == ['test-command-image-list', 'test-command-image-list-1', 'test-command-image-list-2'], lst))
  166. assert len(match) == 1
  167. match = match[0]
  168. assert match[2] == sha256
  169. assert match[3] == '-'
  170. subprocess.check_output(['focker', 'image', 'remove', 'test-command-image-list'])
  171. def test_command_image_prune():
  172. focker_unlock()
  173. subprocess.check_output(['focker', 'image', 'remove', '--force', '-R', 'test-command-image-prune'])
  174. subprocess.check_output(['focker', 'bootstrap', '--empty', '-t', 'test-command-image-prune'])
  175. name, sha256 = zfs_find('test-command-image-prune', focker_type='image')
  176. mountpoint = zfs_mountpoint(name)
  177. subprocess.check_output(['focker', 'image', 'untag', 'test-command-image-prune'])
  178. args = lambda: 0
  179. command_image_prune(args)
  180. with pytest.raises(ValueError):
  181. zfs_find('test-command-image-prune', focker_type='image')
  182. with pytest.raises(ValueError):
  183. zfs_find(sha256, focker_type='image')
  184. assert not os.path.exists(mountpoint)
  185. def test_command_image_remove():
  186. focker_unlock()
  187. subprocess.check_output(['focker', 'image', 'remove', '--force', '-R', 'test-command-image-remove'])
  188. subprocess.check_output(['focker', 'bootstrap', '--empty', '-t', 'test-command-image-remove'])
  189. name, sha256 = zfs_find('test-command-image-remove', focker_type='image')
  190. mountpoint = zfs_mountpoint(name)
  191. args = lambda: 0
  192. args.reference = 'test-command-image-remove'
  193. args.force = False
  194. args.remove_dependents = False
  195. command_image_remove(args)
  196. with pytest.raises(ValueError):
  197. zfs_find('test-command-image-remove', focker_type='image')
  198. with pytest.raises(ValueError):
  199. zfs_find(sha256, focker_type='image')
  200. assert not os.path.exists(mountpoint)
  201. assert not zfs_exists(name)