Source code for infrahouse_toolkit.cli.ih_s3.cmd_upload_logs
"""
.. topic:: ``ih-s3 upload-logs``
A ``ih-s3 upload-logs`` subcommand.
See ``ih-s3 upload-logs`` for more details.
"""
import sys
from logging import getLogger
from subprocess import PIPE, Popen
from urllib.parse import urlparse
import click
from botocore.exceptions import ClientError
from infrahouse_core.aws.asg import ASG
from infrahouse_core.aws.asg_instance import ASGInstance
from infrahouse_toolkit.lock.exceptions import LockAcquireError
from infrahouse_toolkit.lock.system import SystemLock
LOG = getLogger()
[docs]def normalize_directory_name(source: str) -> str:
"""
Remove slashes and dots from ends for the path and replace slashes with dashes.
:param source: original path name.
:return: modified path name.
"""
return source.lstrip("/.").replace("/", "-")
@click.command(name="upload-logs")
@click.option(
"--only-if-terminating",
help="Proceed only if the instance is in a 'Terminating:Wait' lifecycle state.",
default=None,
is_flag=True,
show_default=True,
)
@click.option(
"--wait-until-complete",
help="Wait this many seconds until the logs are uploaded.",
default=3600,
type=click.INT,
show_default=True,
)
@click.option(
"--complete-lifecycle-action",
help="Specify a lifecycle hook name to complete it.",
default=None,
show_default=True,
)
@click.argument("local_directory")
@click.argument("s3_path")
@click.pass_context
def cmd_upload_logs(ctx, **kwargs):
"""
Archive the local directory and upload it to S3.
For example, a command
\b
ih-s3 upload-logs /var/log s3://foo-bucket/path/to/
will create an S3 object s3://foo-bucket/path/to/var-log.tar.gz
"""
s3_client = ctx.obj["s3_client"]
url_parts = urlparse(kwargs["s3_path"])
local_instance = ASGInstance()
only_if_terminating = kwargs["only_if_terminating"]
if only_if_terminating is None or (only_if_terminating and local_instance.lifecycle_state == "Terminating:Wait"):
try:
with SystemLock("/var/tmp/cmd_upload_logs.lock", blocking=False):
try:
cmd = ["tar", "zcf", "-", kwargs["local_directory"]]
with Popen(cmd, stdout=PIPE) as proc:
s3_client.upload_fileobj(
proc.stdout,
url_parts.netloc,
f"{url_parts.path.strip('/')}/{normalize_directory_name(kwargs['local_directory'])}.tar.gz",
)
except ClientError as err:
LOG.exception(err)
sys.exit(1)
if kwargs["complete_lifecycle_action"]:
ASG(asg_name=local_instance.asg_name).complete_lifecycle_action(kwargs["complete_lifecycle_action"])
except LockAcquireError as err:
LOG.warning(err)