
Scripting for better devops: a Python kata
I like automating things, so I try cutting edges where possible. One of the tiny annoying troubles bugging me was figuring the right live database to connect to, or the right cluster to select with kubectl, while knowing only a country name. Surely, if someone has just 2-3 countries, or even regional deployment, this does not turn into a problem at all. But if the deployment has 30, 40, 70 countries?
So, I've decided to make a script that takes a country name or code as an input, and makes a connection to the right database or cluster.
At first, I wanted to write the script in NodeJS, but not every engineer has NodeJS runtime installed. This implies serious distribution difficulties, especially if the script becomes a part of a project repository. Bash scripting was also off the table, because I find this language quite cumbersome and hardly suitable for complex scripts.
I've decided to give Python a try. After all, Python is a language of many fields: system scripting, plugin development, cloud native development.
The script
So, behold! My first script written in Python... using with help of ChatGPT obviously.
#!/usr/bin/env python3# -*- coding: utf-8 -*-import argparseimport subprocessPROJECT_NAME = "my-project"regions = {"eu": "europe-west1","us": "us-east1",}clusters = {"eu": "gke_my-project-live_europe-west1_01","us": "gke_my-project-live_us-east1_01",}countries = [# Asia{"name": "USA", "code": "us", "region": "us", "db_instance": "live-us"},{"name": "Germany", "code": "de", "region": "eu", "db_instance": "live-de"},]def main():args = parse_arguments()country = find_country(args.country)if country == None:print("No such country: {}".format(args.country))exit(1)if args.action == "database":if args.rw:print("Caution: read-write mode enabled!")connect_database(country, args.rw)elif args.action == "cluster":select_cluster(country)exit(0)def select_cluster(country):kubectl_cmd = get_absolute_path("kubectl")execute("{} config use-context {}".format(kubectl_cmd, clusters[country["region"]]))def connect_database(country, rw):if rw:db_instance = country["db_instance"]else:db_instance = country.get("db_instance_replica", "{}-replica".format(country["db_instance"]))db_region = country.get("db_region", country["region"])cloud_sql_proxy_cmd = get_absolute_path("cloud_sql_proxy")execute("{} -instances={}:{}:{}=tcp:54321".format(cloud_sql_proxy_cmd, PROJECT_NAME, regions[db_region], db_instance))def execute(command):print("Executing: {}".format(command))try:subprocess.run(command, shell=False)except KeyboardInterrupt:print("Ctrl+C pressed. Exiting gracefully.")def get_absolute_path(cmd):output = subprocess.run("which {}".format(cmd), capture_output=True, shell=True)return output.stdout.decode()[:-1]def find_country(country):country_uppercased = country.upper()for country_element in countries:if (country_element["name"].upper() == country_uppercased or country_element["code"].upper() == country_uppercased):return country_elementreturn Nonedef parse_arguments():parser = argparse.ArgumentParser(description="A helper tool for faster devops")parser.add_argument("country", type=str, help="The country name or code")parser.add_argument("action", choices=["database", "cluster"], help="What to do")parser.add_argument("--rw", action="store_true", help="If set to TRUE, the connection will be writable")return parser.parse_args()if __name__ == "__main__":main()
Well, this script has proven its usefulness to me, and hopefully it will do so too to whoever stumbles upon this tiny post :)

Sergei Gannochenko
React, Node, Go, Docker, AWS, Jamstack.
15+ years in dev.