-
-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Change docker2sqlelf to be in Python (#21)
Rewrite docker2sqlelf to be written in Python rather than bash for reusability.
- Loading branch information
Showing
1 changed file
with
88 additions
and
78 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,78 +1,88 @@ | ||
#!/usr/bin/env bash | ||
|
||
set -e -o pipefail | ||
|
||
# Default behavior is to clean up the temporary directory | ||
KEEP_TEMP_DIR=false | ||
|
||
# Parse command-line arguments | ||
while [[ "$#" -gt 0 ]]; do | ||
case $1 in | ||
-k|--keep) KEEP_TEMP_DIR=true ;; | ||
*) IMAGE_NAME="$1" ;; | ||
esac | ||
shift | ||
done | ||
|
||
# Ensure an image name was provided | ||
if [ -z "$IMAGE_NAME" ]; then | ||
echo "Usage: $0 [-k|--keep] <docker-image-name>" | ||
exit 1 | ||
fi | ||
|
||
# Create a temporary directory for the container's filesystem | ||
TEMP_DIR=$(mktemp -d) | ||
echo "Created temporary directory at $TEMP_DIR" | ||
|
||
# Function to cleanup on exit, if not keeping the temporary directory | ||
cleanup() { | ||
if [ "$KEEP_TEMP_DIR" = false ]; then | ||
echo "Cleaning up..." | ||
# Remove temporary directory | ||
rm -rf "$TEMP_DIR" | ||
echo "Removed temporary directory $TEMP_DIR" | ||
else | ||
echo "Keeping temporary directory $TEMP_DIR" | ||
fi | ||
} | ||
|
||
# Create a temporary directory for the container's filesystem | ||
TEMP_DIR=$(mktemp -d) | ||
echo "Created temporary directory at $TEMP_DIR"s | ||
|
||
# Trap EXIT to cleanup | ||
trap cleanup EXIT | ||
|
||
# Create docker container from the image | ||
CONTAINER_ID=$(docker create "$IMAGE_NAME") | ||
echo "Created container with ID $CONTAINER_ID" | ||
|
||
# Export the container's filesystem and untar it to the temporary directory | ||
docker export "$CONTAINER_ID" | tar -C "$TEMP_DIR" -xf - | ||
echo "Exported and extracted container's filesystem to $TEMP_DIR" | ||
|
||
# Remove the docker container | ||
docker rm "$CONTAINER_ID" | ||
echo "Removed container $CONTAINER_ID" | ||
|
||
# Replace colons with hyphens | ||
MODIFIED_IMAGE_NAME="${IMAGE_NAME//:/-}" | ||
|
||
# Uncomment the below lines if this script is failing on a distribution | ||
# it will run sqlelf on each file one at a time, and it will tell you | ||
# which file it is failing on | ||
# echo "Running sqlelf on the contents of $TEMP_DIR one file at a time." | ||
# KEEP_TEMP_DIR=true | ||
# find "$TEMP_DIR" -type f -print0 | while IFS= read -r -d $'\0' file; do | ||
# if ! file "$file" | grep -q 'ELF'; then | ||
# continue | ||
# fi | ||
# echo "Processing $file with sqlelf" | ||
# sqlelf "$file" --sql "SELECT 1;" | ||
# done | ||
|
||
# Run sqlelf tool on the contents of the temporary directory | ||
echo "Running sqlelf on the contents of $TEMP_DIR" | ||
sqlelf "$TEMP_DIR" --sql ".backup ${MODIFIED_IMAGE_NAME}.sqlite" | ||
|
||
echo "Script completed successfully." | ||
#!/usr/bin/env python3 | ||
|
||
import argparse | ||
import atexit | ||
import os | ||
import shutil | ||
import tempfile | ||
from functools import reduce | ||
|
||
import docker | ||
|
||
from sqlelf import elf, sql | ||
|
||
|
||
def docker2sqelf(image_name: str, keep_temp_dir: bool = False) -> str: | ||
client = docker.from_env() | ||
|
||
temp_dir = tempfile.mkdtemp() | ||
print(f"Created temporary directory at {temp_dir}") | ||
|
||
def cleanup(): | ||
if not keep_temp_dir: | ||
print("Cleaning up...") | ||
shutil.rmtree(temp_dir) | ||
print(f"Removed temporary directory {temp_dir}") | ||
else: | ||
print(f"Keeping temporary directory {temp_dir}") | ||
|
||
atexit.register(cleanup) | ||
|
||
container = client.containers.create(image_name) | ||
print(f"Created container with ID {container.id}") | ||
|
||
export_path = f"{temp_dir}/container.tar" | ||
with open(export_path, "wb") as out_f: | ||
bits = container.export() | ||
for chunk in bits: | ||
out_f.write(chunk) | ||
print(f"Exported container's filesystem to {export_path}") | ||
|
||
shutil.unpack_archive(export_path, temp_dir) | ||
print(f"Extracted container's filesystem to {temp_dir}") | ||
|
||
container.remove() | ||
print(f"Removed container {container.id}") | ||
|
||
modified_image_name = image_name.replace(":", "-") | ||
|
||
filenames: list[str] = reduce( | ||
lambda a, b: a + b, | ||
map( | ||
lambda dir: ( | ||
[ | ||
os.path.join(root, file) | ||
for root, _, files in os.walk(dir) | ||
for file in files | ||
] | ||
if os.path.isdir(dir) | ||
else [dir] | ||
), | ||
[temp_dir], | ||
), | ||
) | ||
|
||
filenames = [f for f in filenames if os.path.isfile(f)] | ||
|
||
print("Creating sqlelf database") | ||
engine = sql.make_sql_engine(filenames, elf.CacheFlag.ALL()) | ||
|
||
print("Dumping the sqlite database") | ||
database_filename = f"{modified_image_name}.sqlite" | ||
engine.dump(database_filename) | ||
|
||
print(f"Created database {database_filename}") | ||
return database_filename | ||
|
||
|
||
if __name__ == "__main__": | ||
parser = argparse.ArgumentParser( | ||
description="Convert docker image to sqlelf database." | ||
) | ||
parser.add_argument("image_name", help="Docker image name") | ||
parser.add_argument( | ||
"-k", "--keep", help="Keep temporary directory", action="store_true" | ||
) | ||
args = parser.parse_args() | ||
|
||
docker2sqelf(args.image_name, args.keep) |