How to Automate Kubernetes Pod API Configuration
Many complex applications (like Jellyseerr, Prowlarr, or Sonarr) do not support declarative configuration via environment variables or YAML config files. They expect a human to open their Web UI, click through a setup wizard, and enter API keys.
When deploying these applications in Kubernetes via Infrastructure-as-Code (IaC), this creates a manual chokepoint. We can bypass this by writing Python scripts that simulate the browser's REST API calls.
Step-by-Step Guide
1. Extract Secrets Dynamically
Because API keys for these apps are often generated randomly on their first boot, you cannot hardcode them in Kubernetes Secrets. Instead, use your Python script to execute a command inside the running pod to read the dynamically generated config file.
import subprocess
import xml.etree.ElementTree as ET
def get_api_key(namespace, app):
"""Executes a command inside the pod to read the config.xml and extract the ApiKey"""
cmd = f"kubectl exec -n {namespace} deploy/{app} -- cat /config/config.xml"
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
root = ET.fromstring(result.stdout)
return root.find('ApiKey').text
2. Identify the Target Endpoints
Use Chrome DevTools (Network tab) while manually clicking through the app's Web UI. Identify the exact API endpoints the UI is hitting when you click "Save" or "Connect".
For example, connecting Jellyseerr to Jellyfin might require a POST to http://jellyseerr:5055/api/v1/auth/jellyfin.
3. Build the Payload
Reconstruct the JSON payload that the browser sent. Ensure you pass the dynamically extracted API keys.
payload = {
"hostname": "http://jellyfin:8096",
"apiKey": jellyfin_api_key,
"adminUsername": "admin"
}
4. Send the Request and Handle Errors
Use the requests library to send the configuration.
Crucial: Ensure your script handles cases where the app is already configured (Idempotency). For instance, Jellyseerr will throw an HTTP 500 Error if you attempt to submit a hostname after it has already been set up.
import requests
def configure_jellyseerr(jellyseerr_url, payload):
try:
response = requests.post(f"{jellyseerr_url}/api/v1/auth/jellyfin", json=payload)
# 400 and 500 errors often mean the app is already configured.
# You should explicitly check the response JSON or status code.
if response.status_code == 500 and "already configured" in response.text:
print("Jellyseerr is already configured.")
else:
response.raise_for_status()
print("Successfully configured Jellyseerr!")
except requests.exceptions.RequestException as e:
print(f"Failed to configure: {e}")
5. Execute Post-Deployment
Run your Python script immediately after your kubectl apply commands, ensuring you add a polling mechanism or kubectl wait to ensure the pods are completely Ready before the script attempts to interact with their REST APIs.