Uber infrastructure interview: How do you package and test Python DevOps automation so it behaves consistently in laptops, CI, cron, and containers?
Quick Answer
Package automation as a real Python project with pinned dependencies, console_scripts entry points, unit tests around pure logic, integration tests behind explicit flags, and containerized execution for CI. Avoid unversioned scripts copied between hosts, implicit global Python packages, and credentials hidden in developer machines.
Detailed Answer
A Python automation repo is like a toolbox shared by many mechanics. If every mechanic has a different wrench size and nobody knows which tool was used on the last repair, the organization eventually creates inconsistent and risky operations. Packaging is what turns a script into a repeatable operational tool.
The baseline is a project file such as pyproject.toml, a src layout, pinned runtime dependencies, and a lock or constraints strategy. The script should expose a console_scripts entry point so users run inventory-scan instead of python random/path/script.py. Configuration should come from environment variables, config files, or cloud identity, not from edits inside the script. Logging should be structured enough for CI and cron logs.
Testing should match the risk. Pure logic such as filtering stale resources, rendering reports, or classifying errors should have fast unit tests with no cloud access. API boundaries should be wrapped behind clients that can be faked. Integration tests that touch AWS, Kubernetes, or Git providers should require explicit environment variables and run against sandbox accounts or ephemeral namespaces. This prevents every pull request from mutating real infrastructure.
For execution, containers remove host drift. A slim Python image with the package installed, non-root user, and pinned dependency set gives CI, cron, and Kubernetes CronJobs the same runtime. The container should not bake in secrets. Credentials should come from workload identity, IAM role, Kubernetes ServiceAccount, or secret mounts controlled by the platform.
The gotcha is dependency drift. A script can work for months and then break because a transitive dependency released a new major version or a base image moved. Senior candidates mention reproducible builds, dependency scanning, scheduled upgrade PRs, and recording tool version in every audit log.
Code Example
# pyproject.toml
[project] # Define installable Python package metadata.
name = "platform-automation" # Give the automation a stable package name.
version = "0.3.0" # Version the operational tool for audit records.
dependencies = ["boto3==1.34.120", "kubernetes==29.0.0", "pydantic==2.7.4"] # Pin runtime dependencies.
[project.scripts] # Define command line entry points.
inventory-scan = "platform_automation.inventory:main" # Run as inventory-scan.
[tool.pytest.ini_options] # Keep tests discoverable in CI.
testpaths = ["tests"] # Store tests under tests directory.
# Dockerfile
FROM python:3.12-slim # Use a specific Python runtime image.
WORKDIR /app # Set a predictable working directory.
COPY pyproject.toml ./ # Copy package metadata first for layer caching.
COPY src ./src # Copy source code into the image.
RUN pip install --no-cache-dir . # Install package and console scripts.
USER 10001 # Run automation as a non-root user.
ENTRYPOINT ["inventory-scan"] # Make the container run the tool by default.
# tests/test_policy.py
from platform_automation.policy import should_delete_volume # Import pure policy logic.
def test_keeps_recent_volume(): # Verify safe default behavior.
assert should_delete_volume({"age_days": 5, "attached": False}) is False # Recent resources are kept.
def test_deletes_old_unattached_volume(): # Verify intended cleanup policy.
assert should_delete_volume({"age_days": 45, "attached": False}) is True # Old unattached resources are removable.Interview Tip
A junior engineer typically says they would put the script in Git and run pip install, but for a senior role, the interviewer is actually looking for reproducibility. Mention pyproject.toml, pinned dependencies, console entry points, unit tests, explicit integration tests, containerized execution, non-root runtime, and secrets through identity rather than files on a laptop. This is the difference between a helpful script and production automation.