Skip to content

Commit

Permalink
Merge pull request #2 from dickermoshe/forward_all_creds
Browse files Browse the repository at this point in the history
Zappadock loads creds fom envvar and ~/.aws
  • Loading branch information
dickermoshe authored Mar 10, 2022
2 parents 213dbb5 + 63c31f2 commit 7e63dd3
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 98 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ This ZappaDock streamlines the workflow.
#### What Does ZappaDock Do ?
ZappaDock does 3 things.
1. Run a docker container with your code mounted.
2. Recognize your AWS credentials and load them into the container.
2. Load your AWS Credentials from the `~/.aws` folder and environmental variables into the container.
3. Create and activate a virtual environment inside the container.

So now you can test and deploy your code confident that it will work once deployed.
Expand All @@ -28,7 +28,7 @@ $ pip install zappadock

## Usage
1. Make sure Docker is installed by running `docker info` command from a terminal.
2. Set your AWS credentials in environmental variables or in the `~/.aws/credentials` file. See the [Amazon Docs](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html#environment-variables) for more information.
2. Set your AWS credentials in environmental variables or in the `~/.aws` folder. See the [Amazon Docs](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html#environment-variables) for more information.
3. Run `zappadock` in the directory you wish to run your Zappa commands.
Your directory will be loaded in a docker container, and a virtual environment will be created and activated.

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

setup(
name="zappadock",
version='0.1.5',
version='0.1.6',
author="Moshe Dicker",
author_email='[email protected]',
description="A tool for running Zappa commands in a Lambda-like' environment.",
Expand Down
136 changes: 41 additions & 95 deletions zappadock/zappadock.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,149 +19,95 @@
RUN yum clean all
RUN yum install -y which clang cmake python-devel python3-devel amazon-linux-extras gcc openssl-devel bzip2-devel libffi-devel wget tar gzip make
# Commands to Create/Activate python Virtual Environment on launch
RUN echo 'virtualenv -p python3 ./zappa-venv >/dev/null' >> /root/.bashrc
RUN echo 'source ./zappa-venv/bin/activate >/dev/null' >> /root/.bashrc
CMD ["bash"]"""

def get_creds_from_env():
# Get credentials from environment variables
key = os.environ.get('AWS_ACCESS_KEY_ID')
secret = os.environ.get('AWS_SECRET_ACCESS_KEY')
region = os.environ.get('AWS_DEFAULT_REGION')

if None == key or None == secret or None == region:
return False
else:
return key, secret, region

def get_creds_from_credentials_file():
# Get credentials from ~/.aws/credentials
aws_credentials_path = os.path.expanduser('~/.aws/credentials')
if os.path.isfile(aws_credentials_path):
config = configparser.ConfigParser()
config.read(aws_credentials_path)

# If there are no credentials in the file, return False
if len(config.sections()) == 0:
return False

# If there is only one profile, use it
elif len(config.sections()) == 1:
profile = config.sections()[0]

# Otherwise, prompt the user
else:
profile = click.prompt(f"Please enter the profile you would like to use: ",type=click.Choice(config.sections()))

key = config[profile].get('aws_access_key_id')
secret = config[profile].get('aws_secret_access_key')
region = config[profile].get('region')
return False if None in (key, secret, region) else profile

@click.command()
def zappadock():
# Set Zappadock Docker File
"""This is a tool for running Zappa commands in a Lambda-like environment.
Make sure the Docker daemon is installed and running before using this tool.
Your AWS credentials must be setup to use this tool.
See https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html#environment-variables for more information.
"""

# Set Zappadock Docker Filename
docker_file = '.zappadock-Dockerfile'

# Create Dockerfile
# Create Dockerfile if it doesn't exist
if not os.path.isfile(docker_file):

click.echo(f"Creating Dockerfile.")
with open(docker_file, 'w') as f:

# Find the current running Python version
python_version = '.'.join(platform.python_version().split('.')[:2])

# Check if the current Python version is supported
if python_version not in ['3.6', '3.7', '3.8','3.9']:
click.echo(f"Python version {python_version} is not supported. Please use 3.6, 3.7, 3.8, or 3.9.")
exit()

# Check the current architecture
if (platform.machine().lower() in ['aarch64', 'arm64', 'armv7l', 'armv8l']
and python_version in ['3.6', '3.7']):
click.echo("AWS Lambda does not support Python 3.6 or 3.7 on ARM64 on devices.")
exit()

# Get the base image
if python_version in ['3.8','3.9']:
image = f"mlupin/docker-lambda:python{python_version}-build"
else:
image = f"lambci/lambda:build-python{python_version}"

# Write the Dockerfile
f.write(DOCKERFILE.format(base_image=image))

# Check if Zappa has already been run
if os.path.isfile('zappa_settings.json'):
docker_run_command = ["docker run -ti --rm"]

# Check from settings if Zappadock should use environment variables or credentials file
with open('zappa_settings.json') as f:
# Try to get 'profile_name' from settings
try:
_ = list(json.load(f).values())[0]['profile_name']
creds_type = 'file'

# File exists but no profile name is set
except KeyError:
creds_type = 'env'

# File exists but there are no settings or invalid JSON
except (IndexError , json.decoder.JSONDecodeError):
creds_type = 'any'
else:
creds_type = 'any'

# Get credentials from environment variables
if creds_type == 'env':
env_creds = get_creds_from_env()
if env_creds:
run_docker_settings = f' -e AWS_ACCESS_KEY_ID={env_creds[0]} -e AWS_SECRET_ACCESS_KEY={env_creds[1]} -e AWS_DEFAULT_REGION={env_creds[2]} '
else:
click.echo("Please set the AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_DEFAULT_REGION environment variables.")
exit()
# Add mount command to .aws folder if it exists
if os.path.isdir(os.path.expanduser('~/.aws')):
docker_run_command.append(f'-v ~/.aws/:/root/.aws')

# Get credentials from ~/.aws/credentials
elif creds_type == 'file':
profile_name = get_creds_from_credentials_file()
if profile_name:
run_docker_settings = f' -e AWS_PROFILE={profile_name} -v ~/.aws/:/root/.aws '
else:
click.echo("Your Zappa settings are configured to use credentials from ~/.aws/credentials.\nNone of the profiles in ~/.aws/credentials were found.")
exit()

# Get credentials from any source
elif creds_type == 'any':
env_creds = get_creds_from_env()
if env_creds:
run_docker_settings = f' -e AWS_ACCESS_KEY_ID={env_creds[0]} -e AWS_SECRET_ACCESS_KEY={env_creds[1]} -e AWS_DEFAULT_REGION={env_creds[2]} '
else:
profile_name = get_creds_from_credentials_file()
if profile_name:
run_docker_settings = f' -e AWS_PROFILE={profile_name} -v ~/.aws/:/root/.aws '
else:
click.echo("Credentials not found.\nYou can set them in ~/.aws/credentials or by setting environment variables.\nSee https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html#environment-variables for more info.")
exit()

# Add AWS Environment Variables to Docker Command if they exist
for i in ['AWS_ACCESS_KEY_ID', 'AWS_SECRET_ACCESS_KEY', 'AWS_DEFAULT_REGION','AWS_PROFILE']:
if i in os.environ:
docker_run_command.append(f'-e {i}={os.environ[i]}')

# Create Docker client
try:
# Create Docker client
click.echo("Creating Docker client.")
client = docker.from_env()
except docker.errors.DockerException:
click.echo(f"{traceback.format_exc()}\n\nDocker failed to load.\nMake sure its installed and running before continuing.")

except docker.errors.DockerException as e:

if 'Permission denied' in str(e):
# If the user doesn't have permission to run docker, let them know
click.echo("Your user is not in the docker group.\nSee https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user for more information.")
else:
# Docker isn't installed / running
click.echo(f"{traceback.format_exc()}\n\nDocker failed to load.\nMake sure its installed and running before continuing.")
click.echo("Exiting...")
exit()

# Check if Dockerfile is already built
# Build Docker Image
with open(docker_file, 'rb') as f:
try:
click.echo("Building Docker Image. This may take some time...")
docker_image = client.images.build(fileobj=f)
except docker.errors.DockerException:
except docker.errors.DockerException as e:
click.echo(f"{traceback.format_exc()}\n\nDocker failed to build.\nCheck the Dockerfile for any mistakes.")
click.echo("Exiting...")
exit()

# Create command to start ZappaDock
cmnd1 ="docker run -ti --rm"
cmnd2 = run_docker_settings
cmnd3 = f'-v "{os.getcwd()}:/var/task" {docker_image[0].id}'
docker_run_command.append(f'-v "{os.getcwd()}:/var/task" {docker_image[0].id}')

# Run command
# Run Docker Command
click.echo("Starting ZappaDock...")
os.system(f"{cmnd1} {cmnd2} {cmnd3}")
os.system(' '.join(docker_run_command))

0 comments on commit 7e63dd3

Please sign in to comment.