images.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. from __future__ import absolute_import
  2. from __future__ import print_function
  3. from __future__ import unicode_literals
  4. import base64
  5. import json
  6. import os
  7. import docker
  8. from enum import Enum
  9. from .const import NAME
  10. from .const import REPO_ROOT
  11. from .utils import ScriptError
  12. class Platform(Enum):
  13. ALPINE = 'alpine'
  14. DEBIAN = 'debian'
  15. def __str__(self):
  16. return self.value
  17. class ImageManager(object):
  18. def __init__(self, version, latest=False):
  19. self.built_tags = []
  20. self.docker_client = docker.APIClient(**docker.utils.kwargs_from_env())
  21. self.version = version
  22. self.latest = latest
  23. if 'HUB_CREDENTIALS' in os.environ:
  24. print('HUB_CREDENTIALS found in environment, issuing login')
  25. credentials = json.loads(base64.urlsafe_b64decode(os.environ['HUB_CREDENTIALS']))
  26. self.docker_client.login(
  27. username=credentials['Username'], password=credentials['Password']
  28. )
  29. def _tag(self, image, existing_tag, new_tag):
  30. existing_repo_tag = '{image}:{tag}'.format(image=image, tag=existing_tag)
  31. new_repo_tag = '{image}:{tag}'.format(image=image, tag=new_tag)
  32. self.docker_client.tag(existing_repo_tag, new_repo_tag)
  33. self.built_tags.append(new_repo_tag)
  34. def build_runtime_image(self, repository, platform):
  35. git_sha = repository.write_git_sha()
  36. compose_image_base_name = NAME
  37. print('Building {image} image ({platform} based)'.format(
  38. image=compose_image_base_name,
  39. platform=platform
  40. ))
  41. full_version = '{version}-{platform}'.format(version=self.version, platform=platform)
  42. build_tag = '{image_base_image}:{full_version}'.format(
  43. image_base_image=compose_image_base_name,
  44. full_version=full_version
  45. )
  46. logstream = self.docker_client.build(
  47. REPO_ROOT,
  48. tag=build_tag,
  49. buildargs={
  50. 'BUILD_PLATFORM': platform.value,
  51. 'GIT_COMMIT': git_sha,
  52. },
  53. decode=True
  54. )
  55. for chunk in logstream:
  56. if 'error' in chunk:
  57. raise ScriptError('Build error: {}'.format(chunk['error']))
  58. if 'stream' in chunk:
  59. print(chunk['stream'], end='')
  60. self.built_tags.append(build_tag)
  61. if platform == Platform.ALPINE:
  62. self._tag(compose_image_base_name, full_version, self.version)
  63. if self.latest:
  64. self._tag(compose_image_base_name, full_version, platform)
  65. if platform == Platform.ALPINE:
  66. self._tag(compose_image_base_name, full_version, 'latest')
  67. # Used for producing a test image for UCP
  68. def build_ucp_test_image(self, repository):
  69. print('Building test image (debian based for UCP e2e)')
  70. git_sha = repository.write_git_sha()
  71. compose_tests_image_base_name = NAME + '-tests'
  72. ucp_test_image_tag = '{image}:{tag}'.format(
  73. image=compose_tests_image_base_name,
  74. tag=self.version
  75. )
  76. logstream = self.docker_client.build(
  77. REPO_ROOT,
  78. tag=ucp_test_image_tag,
  79. target='build',
  80. buildargs={
  81. 'BUILD_PLATFORM': Platform.DEBIAN.value,
  82. 'GIT_COMMIT': git_sha,
  83. },
  84. decode=True
  85. )
  86. for chunk in logstream:
  87. if 'error' in chunk:
  88. raise ScriptError('Build error: {}'.format(chunk['error']))
  89. if 'stream' in chunk:
  90. print(chunk['stream'], end='')
  91. self.built_tags.append(ucp_test_image_tag)
  92. self._tag(compose_tests_image_base_name, self.version, 'latest')
  93. def build_images(self, repository):
  94. self.build_runtime_image(repository, Platform.ALPINE)
  95. self.build_runtime_image(repository, Platform.DEBIAN)
  96. self.build_ucp_test_image(repository)
  97. def check_images(self):
  98. for name in self.built_tags:
  99. try:
  100. self.docker_client.inspect_image(name)
  101. except docker.errors.ImageNotFound:
  102. print('Expected image {} was not found'.format(name))
  103. return False
  104. return True
  105. def push_images(self):
  106. for name in self.built_tags:
  107. print('Pushing {} to Docker Hub'.format(name))
  108. logstream = self.docker_client.push(name, stream=True, decode=True)
  109. for chunk in logstream:
  110. if 'status' in chunk:
  111. print(chunk['status'])
  112. if 'error' in chunk:
  113. raise ScriptError(
  114. 'Error pushing {name}: {err}'.format(name=name, err=chunk['error'])
  115. )