Exemplo n.º 1
0
def deploy(kctx: kitipy.Context, version: str):
    """Deploy a given version to ECS."""
    client = kitipy.libs.aws.ecs.new_client()
    stack = kctx.config["stacks"][kctx.stack.name]
    cluster_name = kctx.stage["ecs_cluster_name"]
    service_name = versioned_service_name(stack)

    service_def = stack["ecs_service_definition"](kctx)
    task_def = stack["ecs_task_definition"](kctx)
    task_def["containerDefinitions"] = stack["ecs_container_transformer"](
        kctx, version)

    task_def_tags = task_def.get("tags", [])
    task_def_tags.append({'key': 'kitipy.image_tag', 'value': version})
    task_def["tags"] = task_def_tags

    try:
        deployment_id = kitipy.libs.aws.ecs.upsert_service(
            client, cluster_name, service_name, task_def, service_def)
    except kitipy.libs.aws.ecs.ServiceDefinitionChangedError as err:
        kctx.fail(
            "Could not deploy the API: ECS service definition has " +
            "changed - {0}. You have to increment the version ".format(err) +
            "number in the ./tasks.py file before re-running this command.\n")

    for event in kitipy.libs.aws.ecs.watch_deployment(client, cluster_name,
                                                      service_name,
                                                      deployment_id):
        createdAt = event["createdAt"].isoformat()
        message = event["message"]
        kctx.info("[{createdAt}] {message}".format(createdAt=createdAt,
                                                   message=message))
Exemplo n.º 2
0
def ensure_tag_exists(kctx: kitipy.Context, tag: str):
    """Check if the given Git tag exists on both local copy and remote origin.
    This is mostly useful to ensure no invalid tag is going to be deployed.
    
    Args:
        kctx (kitipy.Context): Kitipy context.
        tag (str): Git tag to verify.
    
    Raises:
        ValueError: If the given Git tag does not exist either on local or
            remote origin.
    """
    res = kctx.local(
        'git ls-remote --exit-code --tags origin refs/tags/%s >/dev/null 2>&1'
        % (tag),
        check=False)
    if res.returncode != 0:
        kctx.fail("The given tag is not available on Git remote origin.")

    res = kctx.local(
        'git ls-remote --exit-code --tags ./. refs/tags/%s >/dev/null 2>&1' %
        (tag),
        check=False)
    if res.returncode != 0:
        kctx.fail(
            "The given tag is not available in your local Git repo. Please fetch remote tags before running this task again."
        )
Exemplo n.º 3
0
def edit(kctx: kitipy.Context, secret_name):
    """Edit secrets stored by AWS Secrets Manager."""
    stack = kctx.config['stacks'][kctx.stack.name]
    secret_arn = stack['secret_arn_resolver'](kctx=kctx,
                                              secret_name=secret_name)
    client = sm.new_client()
    secret = sm.describe_secret_with_current_value(client, secret_arn)

    if secret == None:
        kctx.fail("Secret \"%s\" not found." % (secret_name))

    value = click.edit(text=secret['SecretString'])

    if value == None:
        kctx.info("Secret value was not changed. Aborting.")
        raise click.exceptions.Abort()

    trim_question = ("Your secret value ends with a new line. This is " +
                     "generally abnormal. Would you want to trim it " +
                     "automatically?")
    if value.endswith("\n") and click.confirm(trim_question, default=True):
        value = value.rstrip("\n")

    kctx.echo(("NOTE: Secret values end with %s. This is here to help you " +
               "see invisible characters (e.g. whitespace, line breaks, " +
               "etc...).\n") % (secret_delimiter))

    kctx.echo("ID: %s" % (secret["ARN"]))
    kctx.echo("Name: %s" % (secret["Name"]))
    kctx.echo("Previous value: %s" %
              (format_secret_value(secret["SecretString"], True)))
    kctx.echo("New value: %s" % (format_secret_value(value, True)))
    click.confirm("\nDo you confirm this change?", abort=True)

    sm.put_secret_value(client, secret["ARN"], value)
Exemplo n.º 4
0
def ensure_tag_is_recent(kctx: kitipy.Context, tag: str, last: int = 5):
    """Check if the given Git tag is recent enough (by default, one of the
    last five).

    Args:
        kctx (kitipy.Context): Kitipy Context.
        tag (str): Tag to look for.
    """
    res = kctx.local(
        "git for-each-ref --format='%%(refname:strip=2)' --sort=committerdate 'refs/tags/*' 2>/dev/null | tail -n%d | grep %s >/dev/null 2>&1"
        % (last, tag),
        check=False,
    )
    if res.returncode != 0:
        kctx.fail(
            'This tag seems too old: at least %d new tags have been released since %s.'
            % (last, tag))
Exemplo n.º 5
0
def format(kctx: kitipy.Context, show_diff, fix):
    """Run yapf to detect style divergences and fix them."""
    if not show_diff and not fix:
        kctx.fail(
            "You can't use both --no-diff and --no-fix at the same time.")

    confirm_msg = 'Do you want to reformat your code using yapf?'

    dry_run = lambda: kctx.local('yapf --diff -r kitipy/ tests/ tasks*.py',
                                 check=False)
    apply = lambda: kctx.local('yapf -vv -p -i -r kitipy/ tests/ tasks*.py')

    kitipy.confirm_and_apply(dry_run,
                             confirm_msg,
                             apply,
                             show_dry_run=show_diff,
                             ask_confirm=fix is None,
                             should_apply=fix if fix is not None else True)
Exemplo n.º 6
0
def run(kctx: kitipy.Context, container: str, command: List[str],
        version: Optional[str]):
    """Run a given command in a oneoff task."""
    client = kitipy.libs.aws.ecs.new_client()
    stack = kctx.config["stacks"][kctx.stack.name]
    cluster_name = kctx.stage["ecs_cluster_name"]
    service_name = versioned_service_name(stack)
    task_def = stack["ecs_task_definition"](kctx)

    if version is None:
        regular_task_def = kitipy.libs.aws.ecs.get_task_definition(
            client, task_def["family"])
        version = next((tag["value"] for tag in regular_task_def["tags"]
                        if tag["key"] == "kitipy.image_tag"), None)

    if version is None:
        kctx.fail(
            "No --version flag was provided and no deployments have been found."
        )

    task_name = "{0}-{1}".format(service_name, "-".join(command))

    containers = stack["ecs_container_transformer"](kctx, version)
    containers = stack["ecs_oneoff_container_transformer"](kctx, containers,
                                                           container)

    run_args = stack["ecs_service_definition"](kctx)
    run_args = {
        k: v
        for k, v in run_args.items()
        if k not in ["desiredCount", "loadBalancers"]
    }

    task_def["family"] = task_def["family"] + "-oneoff"
    task_def["containerDefinitions"] = list(containers)

    task_arn = kitipy.libs.aws.ecs.run_oneoff_task(client, cluster_name,
                                                   task_name, task_def,
                                                   container, command,
                                                   run_args)

    task = kitipy.libs.aws.ecs.wait_until_task_stops(client, cluster_name,
                                                     task_arn)
    show_task(kctx, task)
Exemplo n.º 7
0
def validate_tag(kctx: kitipy.Context, image_ref: str):
    """Check if the given image reference exists on a remote Docker registry.
    
    Args:
        kctx (kitipy.Context): The current kitipy Context.
        image_ref (str):
            A full image reference composed of: the repository to check, the
            base image name and the image tag.

    Raises:
        click.Exception: When the given image tag doesn't exist.
    """
    if len(image_ref) == 0:
        kctx.fail(
            "No image tag provided. You can provide it through --tag flag or IMAGE_TAG env var."
        )

    images = (service['image'] for service in kctx.stack.config['services'])
    for image in images:
        result = actions.buildx_imagetools_inspect(image_ref, _check=False)
        if result.returncode != 0:
            kctx.fail('Image %s not found on remote registry.' % (image_ref))
Exemplo n.º 8
0
def docker_tasks(kctx: kitipy.Context):
    if not isinstance(kctx.stack, stack.BaseStack):
        kctx.fail("No valid Docker stack available in kipity Context.")