-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpackage.py
More file actions
256 lines (202 loc) · 7.93 KB
/
package.py
File metadata and controls
256 lines (202 loc) · 7.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
#!/usr/bin/env python3
"""
AWS Lambda Deployment Package Builder
This script automates the creation of a .zip deployment package for AWS Lambda
following the AWS documentation guidelines. It creates a deployment package
with all dependencies installed at the root level as required by Lambda.
Usage:
python package.py
The script will:
1. Create a 'package' directory for dependencies
2. Install all dependencies from requirements.txt into the package directory
3. Create a .zip file with dependencies at the root
4. Add lambda_function.py to the root of the .zip file
5. Clean up temporary files
Output: lambda_deployment_package.zip
"""
import os
import sys
import shutil
import subprocess
import zipfile
from pathlib import Path
def run_command(command: list, cwd: str | None = None) -> bool:
"""
Run a shell command and return success status.
Args:
command: List of command parts
cwd: Working directory for the command
Returns:
True if command succeeded, False otherwise
"""
try:
print(f"Running: {' '.join(command)}")
result = subprocess.run(
command, cwd=cwd, check=True, capture_output=True, text=True
)
if result.stdout:
print(result.stdout)
return True
except subprocess.CalledProcessError as e:
print(f"Error running command: {e}")
if e.stderr:
print(f"Error output: {e.stderr}")
return False
def create_deployment_package():
"""Create AWS Lambda deployment package following AWS guidelines."""
# Get the current directory (lambda directory)
lambda_dir = Path.cwd()
package_dir = lambda_dir / "package"
zip_filename = "lambda_deployment_package.zip"
zip_path = lambda_dir / zip_filename
print("=== AWS Lambda Deployment Package Builder ===")
print(f"Working directory: {lambda_dir}")
# Step 1: Clean up any existing package directory and zip file
print("\n1. Cleaning up existing files...")
if package_dir.exists():
print(f"Removing existing package directory: {package_dir}")
shutil.rmtree(package_dir)
if zip_path.exists():
print(f"Removing existing zip file: {zip_path}")
zip_path.unlink()
# Step 2: Create package directory
print("\n2. Creating package directory...")
package_dir.mkdir(exist_ok=True)
print(f"Created directory: {package_dir}")
# Step 3: Install dependencies
print("\n3. Installing dependencies from requirements.txt...")
if not (lambda_dir / "requirements.txt").exists():
print("Error: requirements.txt not found!")
return False
# Install dependencies to package directory
install_success = run_command(
[
sys.executable,
"-m",
"pip",
"install",
"--platform",
"manylinux2014_x86_64",
"--implementation",
"cp",
"--python-version",
"3.13",
"--only-binary=:all:",
"--target",
str(package_dir),
"-r",
"requirements.txt",
"--upgrade",
]
)
if not install_success:
print("Failed to install dependencies!")
return False
print("Dependencies installed successfully!")
# Step 4: Create zip file with dependencies at root
print("\n4. Creating zip file with dependencies...")
try:
with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as zipf:
# Add all files from package directory to root of zip
for root, dirs, files in os.walk(package_dir):
for file in files:
file_path = Path(root) / file
# Calculate relative path from package directory
relative_path = file_path.relative_to(package_dir)
# Add to zip at root level
zipf.write(file_path, str(relative_path))
print(f"Created zip file: {zip_path}")
except Exception as e:
print(f"Error creating zip file: {e}")
return False
# Step 5: Add lambda_function.py to root of zip
print("\n5. Adding lambda_function.py to zip file...")
lambda_function_path = lambda_dir / "lambda_function.py"
if not lambda_function_path.exists():
print("Error: lambda_function.py not found!")
return False
try:
with zipfile.ZipFile(zip_path, "a", zipfile.ZIP_DEFLATED) as zipf:
zipf.write(lambda_function_path, "lambda_function.py")
print("Added lambda_function.py to zip file!")
except Exception as e:
print(f"Error adding lambda_function.py: {e}")
return False
# Step 6: Add additoinal modules to zip if it exists
print("\n6. Adding additional modules...")
database_dir = lambda_dir / "database"
if database_dir.exists():
try:
with zipfile.ZipFile(zip_path, "a", zipfile.ZIP_DEFLATED) as zipf:
for root, dirs, files in os.walk(database_dir):
for file in files:
if file.endswith(".py"):
file_path = Path(root) / file
relative_path = file_path.relative_to(lambda_dir)
zipf.write(file_path, str(relative_path))
print("Added database module to zip file!")
except Exception as e:
print(f"Error adding database module: {e}")
return False
else:
print("No database directory found, skipping...")
api_client_path = lambda_dir / "api_client.py"
if not api_client_path.exists():
print("Error: api_client.py not found!")
return False
try:
with zipfile.ZipFile(zip_path, "a", zipfile.ZIP_DEFLATED) as zipf:
zipf.write(api_client_path, "api_client.py")
print("Added api_client.py to zip file!")
except Exception as e:
print(f"Error adding api_client.py: {e}")
return False
# Step 7: Clean up package directory
print("\n7. Cleaning up temporary files...")
if package_dir.exists():
shutil.rmtree(package_dir)
print("Removed temporary package directory")
# Step 8: Verify zip file structure
print("\n8. Verifying zip file structure...")
try:
with zipfile.ZipFile(zip_path, "r") as zipf:
file_list = zipf.namelist()
# Check for lambda_function.py at root
if "lambda_function.py" not in file_list:
print("Warning: lambda_function.py not found at root of zip!")
return False
# Show first few files for verification
print("Zip file contents (first 10 files):")
for i, filename in enumerate(file_list[:10]):
print(f" {filename}")
if len(file_list) > 10:
print(f" ... and {len(file_list) - 10} more files")
print(f"\nTotal files in zip: {len(file_list)}")
except Exception as e:
print(f"Error verifying zip file: {e}")
return False
print(f"\n✅ SUCCESS! Deployment package created: {zip_filename}")
print(f"📦 File size: {zip_path.stat().st_size / 1024 / 1024:.2f} MB")
print("\nYou can now upload this zip file to AWS Lambda!")
return True
def main():
"""Main entry point."""
# Check if we're in the lambda directory
if not Path("lambda_function.py").exists():
print(
"Error: This script must be run from the lambda directory containing lambda_function.py"
)
print("Current directory:", Path.cwd())
sys.exit(1)
# Check if requirements.txt exists
if not Path("requirements.txt").exists():
print("Error: requirements.txt not found in current directory")
sys.exit(1)
# Create the deployment package
success = create_deployment_package()
if not success:
print("\n❌ Failed to create deployment package!")
sys.exit(1)
sys.exit(0)
if __name__ == "__main__":
main()