| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 | from __future__ import absolute_importfrom __future__ import print_functionfrom __future__ import unicode_literalsimport base64import jsonimport osimport dockerfrom enum import Enumfrom .const import NAMEfrom .const import REPO_ROOTfrom .utils import ScriptErrorfrom .utils import yesnofrom script.release.release.const import COMPOSE_TESTS_IMAGE_BASE_NAMEclass Platform(Enum):    ALPINE = 'alpine'    DEBIAN = 'debian'    def __str__(self):        return self.value# Checks if this version respects the GA version format ('x.y.z') and not an RCdef is_tag_latest(version):    ga_version = all(n.isdigit() for n in version.split('.')) and version.count('.') == 2    return ga_version and yesno('Should this release be tagged as \"latest\"? [Y/n]: ', default=True)class ImageManager(object):    def __init__(self, version, latest=False):        self.docker_client = docker.APIClient(**docker.utils.kwargs_from_env())        self.version = version        self.latest = latest        if 'HUB_CREDENTIALS' in os.environ:            print('HUB_CREDENTIALS found in environment, issuing login')            credentials = json.loads(base64.urlsafe_b64decode(os.environ['HUB_CREDENTIALS']))            self.docker_client.login(                username=credentials['Username'], password=credentials['Password']            )    def _tag(self, image, existing_tag, new_tag):        existing_repo_tag = '{image}:{tag}'.format(image=image, tag=existing_tag)        new_repo_tag = '{image}:{tag}'.format(image=image, tag=new_tag)        self.docker_client.tag(existing_repo_tag, new_repo_tag)    def get_full_version(self, platform=None):        return self.version + '-' + platform.__str__() if platform else self.version    def get_runtime_image_tag(self, tag):        return '{image_base_image}:{tag}'.format(            image_base_image=NAME,            tag=self.get_full_version(tag)        )    def build_runtime_image(self, repository, platform):        git_sha = repository.write_git_sha()        compose_image_base_name = NAME        print('Building {image} image ({platform} based)'.format(            image=compose_image_base_name,            platform=platform        ))        full_version = self.get_full_version(platform)        build_tag = self.get_runtime_image_tag(platform)        logstream = self.docker_client.build(            REPO_ROOT,            tag=build_tag,            buildargs={                'BUILD_PLATFORM': platform.value,                'GIT_COMMIT': git_sha,            },            decode=True        )        for chunk in logstream:            if 'error' in chunk:                raise ScriptError('Build error: {}'.format(chunk['error']))            if 'stream' in chunk:                print(chunk['stream'], end='')        if platform == Platform.ALPINE:            self._tag(compose_image_base_name, full_version, self.version)        if self.latest:            self._tag(compose_image_base_name, full_version, platform)            if platform == Platform.ALPINE:                self._tag(compose_image_base_name, full_version, 'latest')    def get_ucp_test_image_tag(self, tag=None):        return '{image}:{tag}'.format(            image=COMPOSE_TESTS_IMAGE_BASE_NAME,            tag=tag or self.version        )    # Used for producing a test image for UCP    def build_ucp_test_image(self, repository):        print('Building test image (debian based for UCP e2e)')        git_sha = repository.write_git_sha()        ucp_test_image_tag = self.get_ucp_test_image_tag()        logstream = self.docker_client.build(            REPO_ROOT,            tag=ucp_test_image_tag,            target='build',            buildargs={                'BUILD_PLATFORM': Platform.DEBIAN.value,                'GIT_COMMIT': git_sha,            },            decode=True        )        for chunk in logstream:            if 'error' in chunk:                raise ScriptError('Build error: {}'.format(chunk['error']))            if 'stream' in chunk:                print(chunk['stream'], end='')        self._tag(COMPOSE_TESTS_IMAGE_BASE_NAME, self.version, 'latest')    def build_images(self, repository):        self.build_runtime_image(repository, Platform.ALPINE)        self.build_runtime_image(repository, Platform.DEBIAN)        self.build_ucp_test_image(repository)    def check_images(self):        for name in self.get_images_to_push():            try:                self.docker_client.inspect_image(name)            except docker.errors.ImageNotFound:                print('Expected image {} was not found'.format(name))                return False        return True    def get_images_to_push(self):        tags_to_push = {            "{}:{}".format(NAME, self.version),            self.get_runtime_image_tag(Platform.ALPINE),            self.get_runtime_image_tag(Platform.DEBIAN),            self.get_ucp_test_image_tag(),            self.get_ucp_test_image_tag('latest'),        }        if is_tag_latest(self.version):            tags_to_push.add("{}:latest".format(NAME))        return tags_to_push    def push_images(self):        tags_to_push = self.get_images_to_push()        print('Build tags to push {}'.format(tags_to_push))        for name in tags_to_push:            print('Pushing {} to Docker Hub'.format(name))            logstream = self.docker_client.push(name, stream=True, decode=True)            for chunk in logstream:                if 'status' in chunk:                    print(chunk['status'])                if 'error' in chunk:                    raise ScriptError(                        'Error pushing {name}: {err}'.format(name=name, err=chunk['error'])                    )
 |