|
19 | 19 | RUN yum clean all |
20 | 20 | 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 |
21 | 21 |
|
| 22 | +# Commands to Create/Activate python Virtual Environment on launch |
22 | 23 | RUN echo 'virtualenv -p python3 ./zappa-venv >/dev/null' >> /root/.bashrc |
23 | 24 | RUN echo 'source ./zappa-venv/bin/activate >/dev/null' >> /root/.bashrc |
24 | 25 |
|
25 | 26 | CMD ["bash"]""" |
26 | 27 |
|
27 | | -def get_creds_from_env(): |
28 | | - # Get credentials from environment variables |
29 | | - key = os.environ.get('AWS_ACCESS_KEY_ID') |
30 | | - secret = os.environ.get('AWS_SECRET_ACCESS_KEY') |
31 | | - region = os.environ.get('AWS_DEFAULT_REGION') |
32 | | - |
33 | | - if None == key or None == secret or None == region: |
34 | | - return False |
35 | | - else: |
36 | | - return key, secret, region |
37 | | - |
38 | | -def get_creds_from_credentials_file(): |
39 | | - # Get credentials from ~/.aws/credentials |
40 | | - aws_credentials_path = os.path.expanduser('~/.aws/credentials') |
41 | | - if os.path.isfile(aws_credentials_path): |
42 | | - config = configparser.ConfigParser() |
43 | | - config.read(aws_credentials_path) |
44 | | - |
45 | | - # If there are no credentials in the file, return False |
46 | | - if len(config.sections()) == 0: |
47 | | - return False |
48 | | - |
49 | | - # If there is only one profile, use it |
50 | | - elif len(config.sections()) == 1: |
51 | | - profile = config.sections()[0] |
52 | | - |
53 | | - # Otherwise, prompt the user |
54 | | - else: |
55 | | - profile = click.prompt(f"Please enter the profile you would like to use: ",type=click.Choice(config.sections())) |
56 | | - |
57 | | - key = config[profile].get('aws_access_key_id') |
58 | | - secret = config[profile].get('aws_secret_access_key') |
59 | | - region = config[profile].get('region') |
60 | | - return False if None in (key, secret, region) else profile |
61 | | - |
62 | 28 | @click.command() |
63 | 29 | def zappadock(): |
64 | | - # Set Zappadock Docker File |
| 30 | + """This is a tool for running Zappa commands in a Lambda-like environment. |
| 31 | + |
| 32 | + Make sure the Docker daemon is installed and running before using this tool. |
| 33 | +
|
| 34 | + Your AWS credentials must be setup to use this tool. |
| 35 | + See https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html#environment-variables for more information. |
| 36 | + """ |
| 37 | + |
| 38 | + # Set Zappadock Docker Filename |
65 | 39 | docker_file = '.zappadock-Dockerfile' |
66 | 40 |
|
67 | | - # Create Dockerfile |
| 41 | + # Create Dockerfile if it doesn't exist |
68 | 42 | if not os.path.isfile(docker_file): |
| 43 | + |
69 | 44 | click.echo(f"Creating Dockerfile.") |
70 | 45 | with open(docker_file, 'w') as f: |
| 46 | + |
| 47 | + # Find the current running Python version |
71 | 48 | python_version = '.'.join(platform.python_version().split('.')[:2]) |
72 | 49 |
|
| 50 | + # Check if the current Python version is supported |
73 | 51 | if python_version not in ['3.6', '3.7', '3.8','3.9']: |
74 | 52 | click.echo(f"Python version {python_version} is not supported. Please use 3.6, 3.7, 3.8, or 3.9.") |
75 | 53 | exit() |
76 | 54 |
|
| 55 | + # Check the current architecture |
77 | 56 | if (platform.machine().lower() in ['aarch64', 'arm64', 'armv7l', 'armv8l'] |
78 | 57 | and python_version in ['3.6', '3.7']): |
79 | 58 | click.echo("AWS Lambda does not support Python 3.6 or 3.7 on ARM64 on devices.") |
80 | 59 | exit() |
81 | 60 |
|
| 61 | + # Get the base image |
82 | 62 | if python_version in ['3.8','3.9']: |
83 | 63 | image = f"mlupin/docker-lambda:python{python_version}-build" |
84 | 64 | else: |
85 | 65 | image = f"lambci/lambda:build-python{python_version}" |
86 | 66 |
|
| 67 | + # Write the Dockerfile |
87 | 68 | f.write(DOCKERFILE.format(base_image=image)) |
88 | 69 |
|
89 | | - # Check if Zappa has already been run |
90 | | - if os.path.isfile('zappa_settings.json'): |
| 70 | + docker_run_command = ["docker run -ti --rm"] |
91 | 71 |
|
92 | | - # Check from settings if Zappadock should use environment variables or credentials file |
93 | | - with open('zappa_settings.json') as f: |
94 | | - # Try to get 'profile_name' from settings |
95 | | - try: |
96 | | - _ = list(json.load(f).values())[0]['profile_name'] |
97 | | - creds_type = 'file' |
98 | | - |
99 | | - # File exists but no profile name is set |
100 | | - except KeyError: |
101 | | - creds_type = 'env' |
102 | | - |
103 | | - # File exists but there are no settings or invalid JSON |
104 | | - except (IndexError , json.decoder.JSONDecodeError): |
105 | | - creds_type = 'any' |
106 | | - else: |
107 | | - creds_type = 'any' |
108 | | - |
109 | | - # Get credentials from environment variables |
110 | | - if creds_type == 'env': |
111 | | - env_creds = get_creds_from_env() |
112 | | - if env_creds: |
113 | | - 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]} ' |
114 | | - else: |
115 | | - click.echo("Please set the AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_DEFAULT_REGION environment variables.") |
116 | | - exit() |
| 72 | + # Add mount command to .aws folder if it exists |
| 73 | + if os.path.isdir(os.path.expanduser('~/.aws')): |
| 74 | + docker_run_command.append(f'-v ~/.aws/:/root/.aws') |
117 | 75 |
|
118 | | - # Get credentials from ~/.aws/credentials |
119 | | - elif creds_type == 'file': |
120 | | - profile_name = get_creds_from_credentials_file() |
121 | | - if profile_name: |
122 | | - run_docker_settings = f' -e AWS_PROFILE={profile_name} -v ~/.aws/:/root/.aws ' |
123 | | - else: |
124 | | - click.echo("Your Zappa settings are configured to use credentials from ~/.aws/credentials.\nNone of the profiles in ~/.aws/credentials were found.") |
125 | | - exit() |
126 | | - |
127 | | - # Get credentials from any source |
128 | | - elif creds_type == 'any': |
129 | | - env_creds = get_creds_from_env() |
130 | | - if env_creds: |
131 | | - 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]} ' |
132 | | - else: |
133 | | - profile_name = get_creds_from_credentials_file() |
134 | | - if profile_name: |
135 | | - run_docker_settings = f' -e AWS_PROFILE={profile_name} -v ~/.aws/:/root/.aws ' |
136 | | - else: |
137 | | - 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.") |
138 | | - exit() |
139 | 76 |
|
| 77 | + # Add AWS Environment Variables to Docker Command if they exist |
| 78 | + for i in ['AWS_ACCESS_KEY_ID', 'AWS_SECRET_ACCESS_KEY', 'AWS_DEFAULT_REGION','AWS_PROFILE']: |
| 79 | + if i in os.environ: |
| 80 | + docker_run_command.append(f'-e {i}={os.environ[i]}') |
140 | 81 |
|
141 | | - # Create Docker client |
142 | 82 | try: |
| 83 | + # Create Docker client |
143 | 84 | click.echo("Creating Docker client.") |
144 | 85 | client = docker.from_env() |
145 | | - except docker.errors.DockerException: |
146 | | - click.echo(f"{traceback.format_exc()}\n\nDocker failed to load.\nMake sure its installed and running before continuing.") |
| 86 | + |
| 87 | + except docker.errors.DockerException as e: |
| 88 | + |
| 89 | + if 'Permission denied' in str(e): |
| 90 | + # If the user doesn't have permission to run docker, let them know |
| 91 | + 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.") |
| 92 | + else: |
| 93 | + # Docker isn't installed / running |
| 94 | + click.echo(f"{traceback.format_exc()}\n\nDocker failed to load.\nMake sure its installed and running before continuing.") |
147 | 95 | click.echo("Exiting...") |
148 | 96 | exit() |
149 | 97 |
|
150 | | - # Check if Dockerfile is already built |
| 98 | + # Build Docker Image |
151 | 99 | with open(docker_file, 'rb') as f: |
152 | 100 | try: |
153 | 101 | click.echo("Building Docker Image. This may take some time...") |
154 | 102 | docker_image = client.images.build(fileobj=f) |
155 | | - except docker.errors.DockerException: |
| 103 | + except docker.errors.DockerException as e: |
156 | 104 | click.echo(f"{traceback.format_exc()}\n\nDocker failed to build.\nCheck the Dockerfile for any mistakes.") |
157 | 105 | click.echo("Exiting...") |
158 | 106 | exit() |
159 | 107 |
|
160 | 108 | # Create command to start ZappaDock |
161 | | - cmnd1 ="docker run -ti --rm" |
162 | | - cmnd2 = run_docker_settings |
163 | | - cmnd3 = f'-v "{os.getcwd()}:/var/task" {docker_image[0].id}' |
| 109 | + docker_run_command.append(f'-v "{os.getcwd()}:/var/task" {docker_image[0].id}') |
164 | 110 |
|
165 | | - # Run command |
| 111 | + # Run Docker Command |
166 | 112 | click.echo("Starting ZappaDock...") |
167 | | - os.system(f"{cmnd1} {cmnd2} {cmnd3}") |
| 113 | + os.system(' '.join(docker_run_command)) |
0 commit comments