Skip to content

Commit

Permalink
Change docker2sqlelf to be in Python (#21)
Browse files Browse the repository at this point in the history
Rewrite docker2sqlelf to be written in Python rather than bash for
reusability.
  • Loading branch information
fzakaria authored Apr 6, 2024
1 parent e9b2d6c commit 26a1445
Showing 1 changed file with 88 additions and 78 deletions.
166 changes: 88 additions & 78 deletions tools/docker2sqlelf
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)

0 comments on commit 26a1445

Please sign in to comment.