Exemplo n.º 1
0
def gitlog():
    ecr = ECR()

    staging_deployment = Deployment('staging')
    staging_tag = staging_deployment.current_tag
    if staging_tag is None:
        raise HokusaiError("Could not find a tag 'staging'.  Aborting.")
    if staging_tag == 'staging':
        staging_tag = ecr.find_git_sha1_image_tag('staging')
        if staging_tag is None:
            print_red(
                "Could not find a git SHA1 tag for 'staging'.  Aborting.")
            return -1

    production_deployment = Deployment('production')
    production_tag = production_deployment.current_tag
    if production_tag is None:
        raise HokusaiError("Could not find a tag 'production'.  Aborting.")
    if production_tag == 'production':
        production_tag = ecr.find_git_sha1_image_tag('production')
        if production_tag is None:
            print_red(
                "Could not find a git SHA1 tag for 'production'.  Aborting.")
            return -1

    print_green("Comparing %s to %s" % (production_tag, staging_tag))
    shout("git log --right-only %s..%s" % (production_tag, staging_tag),
          print_output=True)
Exemplo n.º 2
0
def gitdiff():
    ecr = ECR()

    staging_deployment = Deployment('staging')
    staging_tag = staging_deployment.current_tag
    if staging_tag is None:
        raise HokusaiError("Could not find a tag for staging.  Aborting.")
    staging_tag = ecr.find_git_sha1_image_tag(staging_tag)
    if staging_tag is None:
        raise HokusaiError(
            "Could not find a git SHA1 tag for tag %s.  Aborting." %
            staging_tag)

    production_deployment = Deployment('production')
    production_tag = production_deployment.current_tag
    if production_tag is None:
        raise HokusaiError("Could not find a tag for production.  Aborting.")
    production_tag = ecr.find_git_sha1_image_tag(production_tag)
    if production_tag is None:
        raise HokusaiError("Could not find a git SHA1 for tag %s.  Aborting." %
                           production_tag)

    print_green("Comparing %s to %s" % (production_tag, staging_tag))
    for remote in shout('git remote').splitlines():
        shout("git fetch %s" % remote)
    shout("git diff %s %s" % (production_tag, staging_tag), print_output=True)
Exemplo n.º 3
0
def gitlog():
    ecr = ECR()

    staging_deployment = Deployment('staging')
    staging_tag = staging_deployment.current_tag
    if staging_tag is None:
        raise HokusaiError("Could not find a tag for staging.  Aborting.")
    staging_tag = ecr.find_git_sha1_image_tag(staging_tag)
    if staging_tag is None:
        raise HokusaiError(
            "Could not find a git SHA1 tag for tag %s.  Aborting." %
            staging_tag)

    production_deployment = Deployment('production')
    production_tag = production_deployment.current_tag
    if production_tag is None:
        raise HokusaiError("Could not find a tag for production.  Aborting.")
    production_tag = ecr.find_git_sha1_image_tag(production_tag)
    if production_tag is None:
        raise HokusaiError("Could not find a git SHA1 for tag %s.  Aborting." %
                           production_tag)

    print_green("Comparing %s to %s" % (production_tag, staging_tag))
    shout("git log --right-only %s..%s" % (production_tag, staging_tag),
          print_output=True)
Exemplo n.º 4
0
def gitcompare(org_name, git_compare_link):
  ecr = ECR()

  staging_tag = ecr.find_git_sha1_image_tag('staging')
  if staging_tag is None:
    raise HokusaiError("Could not find a tag for staging.  Aborting.")

  production_tag = ecr.find_git_sha1_image_tag('production')
  if production_tag is None:
    raise HokusaiError("Could not find a git SHA1 tag for production.  Aborting.")

  print_green(git_compare_link % (org_name, config.project_name, production_tag, staging_tag))
Exemplo n.º 5
0
def promote(migration, constraint, git_remote, timeout):
    ecr = ECR()

    deploy_from = Deployment('staging')
    tag = deploy_from.current_tag
    if tag is None:
        raise HokusaiError("Could not find a tag for staging.  Aborting.")
    tag = ecr.find_git_sha1_image_tag(tag)
    if tag is None:
        print_red("Could not find a git SHA1 for tag %s.  Aborting." % tag)
        return 1

    if migration is not None:
        print_green("Running migration '%s' on production..." % migration,
                    newline_after=True)
        return_code = CommandRunner('production').run(tag,
                                                      migration,
                                                      constraint=constraint,
                                                      tty=False)
        if return_code:
            raise HokusaiError("Migration failed with return code %s" %
                               return_code,
                               return_code=return_code)

    deploy_to = Deployment('production').update(tag, constraint, git_remote,
                                                timeout)
    print_green("Promoted staging to production at %s" % tag)
Exemplo n.º 6
0
def gitlog():
    ecr = ECR()

    staging_tag = ecr.find_git_sha1_image_tag('staging')
    if staging_tag is None:
        raise HokusaiError("Could not find a tag for staging.  Aborting.")

    production_tag = ecr.find_git_sha1_image_tag('production')
    if production_tag is None:
        raise HokusaiError(
            "Could not find a git SHA1 tag for production.  Aborting.")

    print_green("Comparing %s to %s" % (production_tag, staging_tag))
    for remote in shout('git remote').splitlines():
        shout("git fetch %s" % remote)
    shout("git log --right-only %s..%s" % (production_tag, staging_tag),
          print_output=True)
Exemplo n.º 7
0
def gitcompare(org_name, git_compare_link):
    ecr = ECR()

    staging_deployment = Deployment('staging')
    staging_tag = staging_deployment.current_tag
    if staging_tag is None:
        raise HokusaiError("Could not find a tag for staging.  Aborting.")
    staging_tag = ecr.find_git_sha1_image_tag(staging_tag)
    if staging_tag is None:
        raise HokusaiError(
            "Could not find a git SHA1 tag for tag %s.  Aborting." %
            staging_tag)

    production_deployment = Deployment('production')
    production_tag = production_deployment.current_tag
    if production_tag is None:
        raise HokusaiError("Could not find a tag for production.  Aborting.")
    production_tag = ecr.find_git_sha1_image_tag(production_tag)
    if production_tag is None:
        raise HokusaiError("Could not find a git SHA1 for tag %s.  Aborting." %
                           production_tag)

    print_green(git_compare_link %
                (org_name, config.project_name, production_tag, staging_tag))
Exemplo n.º 8
0
class Deployment(object):
    def __init__(self, context, deployment_name=None, namespace=None):
        self.context = context
        self.namespace = namespace
        self.kctl = Kubectl(self.context, namespace=namespace)
        self.ecr = ECR()
        if deployment_name:
            self.cache = [
                self.kctl.get_object("deployment %s" % deployment_name)
            ]
        else:
            self.cache = self.kctl.get_objects(
                'deployment',
                selector="app=%s,layer=application" % config.project_name)

    def update(self,
               tag,
               constraint,
               git_remote,
               timeout,
               resolve_tag_sha1=True):
        if not self.ecr.project_repo_exists():
            raise HokusaiError("Project repo does not exist.  Aborting.")

        if resolve_tag_sha1:
            tag = self.ecr.find_git_sha1_image_tag(tag)
            if tag is None:
                raise HokusaiError(
                    "Could not find a git SHA1 for tag %s.  Aborting." % tag)

        if self.namespace is None:
            print_green("Deploying %s to %s..." % (tag, self.context),
                        newline_after=True)
        else:
            print_green("Deploying %s to %s/%s..." %
                        (tag, self.context, self.namespace),
                        newline_after=True)

        if config.pre_deploy is not None:
            print_green("Running pre-deploy hook '%s'..." % config.pre_deploy,
                        newline_after=True)
            return_code = CommandRunner(self.context,
                                        namespace=self.namespace).run(
                                            tag,
                                            config.pre_deploy,
                                            constraint=constraint,
                                            tty=False)
            if return_code:
                raise HokusaiError(
                    "Pre-deploy hook failed with return code %s" % return_code,
                    return_code=return_code)

        deployment_timestamp = datetime.datetime.utcnow().strftime("%s%f")
        for deployment in self.cache:
            containers = [(container['name'], container['image'])
                          for container in deployment['spec']['template']
                          ['spec']['containers']]
            deployment_targets = [{
                "name":
                name,
                "image":
                "%s:%s" % (self.ecr.project_repo, tag)
            } for name, image in containers if self.ecr.project_repo in image]
            patch = {
                "spec": {
                    "template": {
                        "metadata": {
                            "labels": {
                                "deploymentTimestamp": deployment_timestamp
                            }
                        },
                        "spec": {
                            "containers": deployment_targets
                        }
                    },
                    "progressDeadlineSeconds": timeout
                }
            }

            print_green("Patching deployment %s..." %
                        deployment['metadata']['name'],
                        newline_after=True)
            shout(
                self.kctl.command(
                    "patch deployment %s -p '%s'" %
                    (deployment['metadata']['name'], json.dumps(patch))))

        print_green("Waiting for deployment rollouts to complete...")

        rollout_commands = [
            self.kctl.command("rollout status deployment/%s" %
                              deployment['metadata']['name'])
            for deployment in self.cache
        ]
        return_codes = shout_concurrent(rollout_commands, print_output=True)
        if any(return_codes):
            print_red(
                "One or more deployment rollouts timed out!  Rolling back...",
                newline_before=True,
                newline_after=True)
            rollback_commands = [
                self.kctl.command("rollout undo deployment/%s" %
                                  deployment['metadata']['name'])
                for deployment in self.cache
            ]
            shout_concurrent(rollback_commands, print_output=True)
            raise HokusaiError("Deployment failed!")

        post_deploy_success = True

        if config.post_deploy is not None:
            print_green("Running post-deploy hook '%s'..." %
                        config.post_deploy,
                        newline_after=True)
            return_code = CommandRunner(self.context,
                                        namespace=self.namespace).run(
                                            tag,
                                            config.post_deploy,
                                            constraint=constraint,
                                            tty=False)
            if return_code:
                print_yellow(
                    "WARNING: Running the post-deploy hook failed with return code %s"
                    % return_code,
                    newline_before=True,
                    newline_after=True)
                print_yellow(
                    "The tag %s has been rolled out.  However, you should run the post-deploy hook '%s' manually, or re-run this deployment."
                    % (tag, config.post_deploy),
                    newline_after=True)
                post_deploy_success = False

        if self.namespace is None:
            deployment_tag = "%s--%s" % (
                self.context,
                datetime.datetime.utcnow().strftime("%Y-%m-%d--%H-%M-%S"))
            print_green("Updating ECR deployment tags in %s..." %
                        self.ecr.project_repo,
                        newline_after=True)
            try:
                self.ecr.retag(tag, self.context)
                print_green("Updated ECR tag %s -> %s" % (tag, self.context))

                self.ecr.retag(tag, deployment_tag)
                print_green("Updated ECR tag %s -> %s" % (tag, deployment_tag),
                            newline_after=True)
            except (ValueError, ClientError) as e:
                print_yellow(
                    "WARNING: Updating ECR deployment tags failed due to the error: '%s'"
                    % str(e),
                    newline_before=True,
                    newline_after=True)
                print_yellow(
                    "The tag %s has been rolled out.  However, you should create the ECR tags '%s' and '%s' manually, or re-run this deployment."
                    % (tag, deployment_tag, self.context),
                    newline_after=True)
                post_deploy_success = False

            remote = git_remote or config.git_remote
            if remote is not None:
                print_green("Pushing Git deployment tags to %s..." % remote,
                            newline_after=True)
                try:
                    shout("git fetch %s" % remote)
                    shout("git tag -f %s %s" % (self.context, tag),
                          print_output=True)
                    shout("git tag -f %s %s" % (deployment_tag, tag),
                          print_output=True)
                    shout("git push -f --no-verify %s refs/tags/%s" %
                          (remote, self.context),
                          print_output=True)
                    print_green("Updated Git tag %s -> %s" %
                                (tag, self.context))
                    shout("git push -f --no-verify %s refs/tags/%s" %
                          (remote, deployment_tag),
                          print_output=True)
                    print_green("Updated Git tag %s -> %s" %
                                (tag, deployment_tag),
                                newline_after=True)
                except CalledProcessError as e:
                    print_yellow(
                        "WARNING: Creating Git deployment tags failed due to the error: '%s'"
                        % str(e),
                        newline_before=True,
                        newline_after=True)
                    print_yellow(
                        "The tag %s has been rolled out.  However, you should create the Git tags '%s' and '%s' manually, or re-run this deployment."
                        % (tag, deployment_tag, self.context),
                        newline_after=True)
                    post_deploy_success = False

        if post_deploy_success:
            print_green("Deployment succeeded!")
        else:
            raise HokusaiError("One or more post-deploy steps failed!")

    def refresh(self):
        deployment_timestamp = datetime.datetime.utcnow().strftime("%s%f")
        for deployment in self.cache:
            patch = {
                "spec": {
                    "template": {
                        "metadata": {
                            "labels": {
                                "deploymentTimestamp": deployment_timestamp
                            }
                        }
                    }
                }
            }
            print_green("Refreshing %s..." % deployment['metadata']['name'],
                        newline_after=True)
            shout(
                self.kctl.command(
                    "patch deployment %s -p '%s'" %
                    (deployment['metadata']['name'], json.dumps(patch))))

        print_green("Waiting for refresh to complete...")

        rollout_commands = [
            self.kctl.command("rollout status deployment/%s" %
                              deployment['metadata']['name'])
            for deployment in self.cache
        ]
        return_codes = shout_concurrent(rollout_commands, print_output=True)
        if any(return_codes):
            raise HokusaiError("Refresh failed!")

    @property
    def names(self):
        return [deployment['metadata']['name'] for deployment in self.cache]

    @property
    def current_tag(self):
        images = []

        for deployment in self.cache:
            containers = deployment['spec']['template']['spec']['containers']
            container_images = [
                container['image'] for container in containers
                if self.ecr.project_repo in container['image']
            ]

            if not container_images:
                raise HokusaiError(
                    "Deployment has no valid target containers.  Aborting.")
            if not all(x == container_images[0] for x in container_images):
                raise HokusaiError(
                    "Deployment's containers do not reference the same image tag.  Aborting."
                )

            images.append(container_images[0])

        if not all(y == images[0] for y in images):
            raise HokusaiError(
                "Deployments do not reference the same image tag. Aborting.")

        return images[0].rsplit(':', 1)[1]
Exemplo n.º 9
0
class Deployment(object):
    def __init__(self, context, deployment_name=None, namespace=None):
        self.context = context
        self.namespace = namespace
        self.kctl = Kubectl(self.context, namespace=namespace)
        self.ecr = ECR()
        if deployment_name:
            self.cache = [
                self.kctl.get_object("deployment %s" % deployment_name)
            ]
        else:
            self.cache = self.kctl.get_objects(
                'deployment',
                selector="app=%s,layer=application" % config.project_name)

    def update(self, tag, constraint, git_remote, resolve_tag_sha1=True):
        if not self.ecr.project_repo_exists():
            raise HokusaiError("Project repo does not exist.  Aborting.")

        if resolve_tag_sha1:
            tag = self.ecr.find_git_sha1_image_tag(tag)
            if tag is None:
                raise HokusaiError(
                    "Could not find a git SHA1 for tag %s.  Aborting." % tag)

        if self.namespace is None:
            print_green("Deploying %s to %s..." % (tag, self.context))
        else:
            print_green("Deploying %s to %s/%s..." %
                        (tag, self.context, self.namespace))

        if self.namespace is None:
            self.ecr.retag(tag, self.context)
            print_green("Updated tag %s -> %s" % (tag, self.context))

            deployment_tag = "%s--%s" % (
                self.context,
                datetime.datetime.utcnow().strftime("%Y-%m-%d--%H-%M-%S"))
            self.ecr.retag(tag, deployment_tag)
            print_green("Updated tag %s -> %s" % (tag, deployment_tag))

            if git_remote is not None:
                print_green("Pushing deployment tags to %s..." % git_remote)
                shout("git tag -f %s" % self.context, print_output=True)
                shout("git tag %s" % deployment_tag, print_output=True)
                shout("git push --force %s --tags" % git_remote,
                      print_output=True)

        if config.pre_deploy is not None:
            print_green("Running pre-deploy hook '%s'..." % config.pre_deploy)
            return_code = CommandRunner(self.context,
                                        namespace=self.namespace).run(
                                            tag,
                                            config.pre_deploy,
                                            constraint=constraint)
            if return_code:
                raise HokusaiError(
                    "Pre-deploy hook failed with return code %s" % return_code,
                    return_code=return_code)

        deployment_timestamp = datetime.datetime.utcnow().strftime("%s%f")
        for deployment in self.cache:
            containers = deployment['spec']['template']['spec']['containers']
            container_names = [container['name'] for container in containers]
            deployment_targets = [{
                "name":
                name,
                "image":
                "%s:%s" % (self.ecr.project_repo, tag)
            } for name in container_names]
            patch = {
                "spec": {
                    "template": {
                        "metadata": {
                            "labels": {
                                "deploymentTimestamp": deployment_timestamp
                            }
                        },
                        "spec": {
                            "containers": deployment_targets
                        }
                    }
                }
            }
            print_green("Patching deployment %s..." %
                        deployment['metadata']['name'])
            shout(
                self.kctl.command(
                    "patch deployment %s -p '%s'" %
                    (deployment['metadata']['name'], json.dumps(patch))))

        print_green("Waiting for rollout to complete...")

        rollout_commands = [
            self.kctl.command("rollout status deployment/%s" %
                              deployment['metadata']['name'])
            for deployment in self.cache
        ]
        return_code = shout_concurrent(rollout_commands)
        if return_code:
            raise HokusaiError("Deployment failed!", return_code=return_code)

        if config.post_deploy is not None:
            print_green("Running post-deploy hook '%s'..." %
                        config.post_deploy)
            return_code = CommandRunner(self.context,
                                        namespace=self.namespace).run(
                                            tag,
                                            config.post_deploy,
                                            constraint=constraint)
            if return_code:
                raise HokusaiError(
                    "Post-deploy hook failed with return code %s" %
                    return_code,
                    return_code=return_code)

    def refresh(self):
        deployment_timestamp = datetime.datetime.utcnow().strftime("%s%f")
        for deployment in self.cache:
            patch = {
                "spec": {
                    "template": {
                        "metadata": {
                            "labels": {
                                "deploymentTimestamp": deployment_timestamp
                            }
                        }
                    }
                }
            }
            print_green("Refreshing %s..." % deployment['metadata']['name'])
            shout(
                self.kctl.command(
                    "patch deployment %s -p '%s'" %
                    (deployment['metadata']['name'], json.dumps(patch))))

        print_green("Waiting for refresh to complete...")

        rollout_commands = [
            self.kctl.command("rollout status deployment/%s" %
                              deployment['metadata']['name'])
            for deployment in self.cache
        ]
        return_code = shout_concurrent(rollout_commands)
        if return_code:
            raise HokusaiError("Refresh failed!", return_code=return_code)

    @property
    def names(self):
        return [deployment['metadata']['name'] for deployment in self.cache]

    @property
    def current_tag(self):
        images = []

        for deployment in self.cache:
            containers = deployment['spec']['template']['spec']['containers']
            container_names = [container['name'] for container in containers]
            container_images = [container['image'] for container in containers]

            if not all(x == container_images[0] for x in container_images):
                raise HokusaiError(
                    "Deployment's containers do not reference the same image tag.  Aborting."
                )

            images.append(containers[0]['image'])

        if not all(y == images[0] for y in images):
            raise HokusaiError(
                "Deployments do not reference the same image tag. Aborting.")

        return images[0].rsplit(':', 1)[1]
Exemplo n.º 10
0
class TestECR(HokusaiIntegrationTestCase):
    def setUp(self):
        self.ecr = ECR()

    @httpretty.activate
    def test_registry(self):
        httpretty.register_uri(
            httpretty.POST,
            "https://sts.amazonaws.com/",
            body=open(
                os.path.join(os.getcwd(), 'test', 'fixtures',
                             'sts-get-caller-identity-response.xml')).read(),
            content_type="application/xml")
        httpretty.register_uri(
            httpretty.POST,
            "https://api.ecr.us-east-1.amazonaws.com/",
            body=open(
                os.path.join(os.getcwd(), 'test', 'fixtures',
                             'ecr-repositories-response.json')).read(),
            content_type="application/x-amz-json-1.1")
        repositories = [
            str(repo['repositoryName']) for repo in self.ecr.registry
        ]
        self.assertTrue('hello' in repositories)
        self.assertTrue('bar' in repositories)
        self.assertTrue('baz' in repositories)

    @httpretty.activate
    def test_project_repo_exists(self):
        httpretty.register_uri(
            httpretty.POST,
            "https://sts.amazonaws.com/",
            body=open(
                os.path.join(os.getcwd(), 'test', 'fixtures',
                             'sts-get-caller-identity-response.xml')).read(),
            content_type="application/xml")
        httpretty.register_uri(
            httpretty.POST,
            "https://api.ecr.us-east-1.amazonaws.com/",
            body=open(
                os.path.join(os.getcwd(), 'test', 'fixtures',
                             'ecr-repositories-response.json')).read(),
            content_type="application/x-amz-json-1.1")
        self.assertTrue(self.ecr.project_repo_exists())

    @httpretty.activate
    def test_get_project_repo(self):
        httpretty.register_uri(
            httpretty.POST,
            "https://sts.amazonaws.com/",
            body=open(
                os.path.join(os.getcwd(), 'test', 'fixtures',
                             'sts-get-caller-identity-response.xml')).read(),
            content_type="application/xml")
        httpretty.register_uri(
            httpretty.POST,
            "https://api.ecr.us-east-1.amazonaws.com/",
            body=open(
                os.path.join(os.getcwd(), 'test', 'fixtures',
                             'ecr-repositories-response.json')).read(),
            content_type="application/x-amz-json-1.1")
        self.assertEqual(self.ecr.project_repo,
                         '123456789012.dkr.ecr.us-east-1.amazonaws.com/hello')

    @httpretty.activate
    def test_create_project_repo(self):
        httpretty.register_uri(
            httpretty.POST,
            "https://sts.amazonaws.com/",
            body=open(
                os.path.join(os.getcwd(), 'test', 'fixtures',
                             'sts-get-caller-identity-response.xml')).read(),
            content_type="application/xml")
        httpretty.register_uri(
            httpretty.POST,
            "https://api.ecr.us-east-1.amazonaws.com/",
            body=open(
                os.path.join(os.getcwd(), 'test', 'fixtures',
                             'ecr-create-repository-response.json')).read(),
            content_type="application/x-amz-json-1.1")
        httpretty.register_uri(
            httpretty.POST,
            "https://api.ecr.us-east-1.amazonaws.com/",
            body=open(
                os.path.join(os.getcwd(), 'test', 'fixtures',
                             'ecr-empty-repositories-response.json')).read(),
            content_type="application/x-amz-json-1.1")
        self.assertTrue(self.ecr.create_project_repo())

    @httpretty.activate
    def test_get_login(self):
        httpretty.register_uri(
            httpretty.POST,
            "https://sts.amazonaws.com/",
            body=open(
                os.path.join(os.getcwd(), 'test', 'fixtures',
                             'sts-get-caller-identity-response.xml')).read(),
            content_type="application/xml")
        httpretty.register_uri(
            httpretty.POST,
            "https://api.ecr.us-east-1.amazonaws.com/",
            body=open(
                os.path.join(os.getcwd(), 'test', 'fixtures',
                             'ecr-authorization-response.json')).read(),
            content_type="application/x-amz-json-1.1")
        self.assertEqual(
            self.ecr.get_login(),
            'docker login -u AWS -p 76W8YEUFHDSAE98DFDHSFSDFIUHSDAJKGKSADFGKDF https://123456789012.dkr.ecr.us-east-1.amazonaws.com'
        )

    @httpretty.activate
    def test_images(self):
        httpretty.register_uri(
            httpretty.POST,
            "https://sts.amazonaws.com/",
            body=open(
                os.path.join(os.getcwd(), 'test', 'fixtures',
                             'sts-get-caller-identity-response.xml')).read(),
            content_type="application/xml")
        httpretty.register_uri(
            httpretty.POST,
            "https://api.ecr.us-east-1.amazonaws.com/",
            body=open(
                os.path.join(os.getcwd(), 'test', 'fixtures',
                             'ecr-images-response.json')).read(),
            content_type="application/x-amz-json-1.1")
        self.assertEqual(
            self.ecr.images[0]['imageTags'],
            ['a2605e5b93ec4beecde122c53a3fdea18807459c', 'latest'])
        self.assertEqual(
            self.ecr.images[0]['imageDigest'],
            'sha256:8sh968hsn205e8bff53ba8ed1006c7f41dacd17db164efdn6d346204f997shdn'
        )
        self.assertEqual(self.ecr.images[0]['registryId'], '123456789012')
        self.assertEqual(self.ecr.images[0]['repositoryName'], 'hello')

    @httpretty.activate
    def test_tag_exists(self):
        httpretty.register_uri(
            httpretty.POST,
            "https://sts.amazonaws.com/",
            body=open(
                os.path.join(os.getcwd(), 'test', 'fixtures',
                             'sts-get-caller-identity-response.xml')).read(),
            content_type="application/xml")
        httpretty.register_uri(
            httpretty.POST,
            "https://api.ecr.us-east-1.amazonaws.com/",
            body=open(
                os.path.join(os.getcwd(), 'test', 'fixtures',
                             'ecr-images-response.json')).read(),
            content_type="application/x-amz-json-1.1")
        self.assertTrue(
            self.ecr.tag_exists('a2605e5b93ec4beecde122c53a3fdea18807459c'))
        self.assertTrue(self.ecr.tag_exists('latest'))

    @httpretty.activate
    def test_tags(self):
        httpretty.register_uri(
            httpretty.POST,
            "https://sts.amazonaws.com/",
            body=open(
                os.path.join(os.getcwd(), 'test', 'fixtures',
                             'sts-get-caller-identity-response.xml')).read(),
            content_type="application/xml")
        httpretty.register_uri(
            httpretty.POST,
            "https://api.ecr.us-east-1.amazonaws.com/",
            body=open(
                os.path.join(os.getcwd(), 'test', 'fixtures',
                             'ecr-images-response.json')).read(),
            content_type="application/x-amz-json-1.1")
        self.assertIn('a2605e5b93ec4beecde122c53a3fdea18807459c',
                      self.ecr.tags())
        self.assertIn('latest', self.ecr.tags())

    @httpretty.activate
    def test_find_git_sha1_image_tag(self):
        httpretty.register_uri(
            httpretty.POST,
            "https://sts.amazonaws.com/",
            body=open(
                os.path.join(os.getcwd(), 'test', 'fixtures',
                             'sts-get-caller-identity-response.xml')).read(),
            content_type="application/xml")
        httpretty.register_uri(
            httpretty.POST,
            "https://api.ecr.us-east-1.amazonaws.com/",
            body=open(
                os.path.join(os.getcwd(), 'test', 'fixtures',
                             'ecr-images-response.json')).read(),
            content_type="application/x-amz-json-1.1")
        self.assertEqual(self.ecr.find_git_sha1_image_tag('latest'),
                         'a2605e5b93ec4beecde122c53a3fdea18807459c')

    @httpretty.activate
    def test_image_digest_for_tag(self):
        httpretty.register_uri(
            httpretty.POST,
            "https://sts.amazonaws.com/",
            body=open(
                os.path.join(os.getcwd(), 'test', 'fixtures',
                             'sts-get-caller-identity-response.xml')).read(),
            content_type="application/xml")
        httpretty.register_uri(
            httpretty.POST,
            "https://api.ecr.us-east-1.amazonaws.com/",
            body=open(
                os.path.join(os.getcwd(), 'test', 'fixtures',
                             'ecr-images-response.json')).read(),
            content_type="application/x-amz-json-1.1")
        self.assertEqual(
            self.ecr.image_digest_for_tag(
                'a2605e5b93ec4beecde122c53a3fdea18807459c'),
            'sha256:8sh968hsn205e8bff53ba8ed1006c7f41dacd17db164efdn6d346204f997shdn'
        )
        self.assertEqual(
            self.ecr.image_digest_for_tag('latest'),
            'sha256:8sh968hsn205e8bff53ba8ed1006c7f41dacd17db164efdn6d346204f997shdn'
        )