· 6 years ago · Jan 03, 2020, 06:28 PM
1from kubernetes import client, config
2from subprocess import Popen,PIPE
3import subprocess
4from threading import Timer
5import argparse
6import logging
7import sys
8import os, signal
9import time
10import base64
11from time import sleep
12'''
13This script is using kubernetes API, required to install module kubernetes by:
14pip3 install kubernetes
15
16to run script please use command:
17python3 portforward --namespace <namespace> --environment <fromlist> --portin <listentoport> --seconds <forwardingtime>
18
19'''
20
21logger = logging.getLogger()
22logger.setLevel(logging.INFO)
23
24ch = logging.StreamHandler(sys.stdout)
25ch.setLevel(logging.INFO)
26formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
27ch.setFormatter(formatter)
28logger.addHandler(ch)
29
30#Func provides binded variables
31def get_input():
32 parser = argparse.ArgumentParser()
33 parser.add_argument('--env',help='environment of kube config')
34 parser.add_argument('--namespace', help='client product namespace')
35 parser.add_argument('--database', help='namespace pod/database name')
36 parser.add_argument('--seconds', help='seconds')
37
38 return parser.parse_args()
39
40#Func with dictionary for each environment each kube config file
41def getKubecfg(arg):
42 conf_dict = {
43 'kmd/cam-kmd-prod':'/var/lib/rundeck/.kube/kmd/cam-kmd-prod.yml',
44 'kmd/cam-kmd-stage':'/var/lib/rundeck/.kube/kmd/cam-kmd-stage.yml',
45 'kmd/consume-kmd-dev':'/var/lib/rundeck/.kube/kmd/consume-kmd-dev.yml',
46 'kmd/consume-kmd-prod':'/var/lib/rundeck/.kube/kmd/consume-kmd-prod.yml',
47 'kmd/consume-kmd-stage':'/var/lib/rundeck/.kube/kmd/consume-kmd-stage.yml',
48 'eu-prod-logging':'/var/lib/rundeck/.kube/logging-eu-prod.yml',
49 'eu-prod-monitoring':'/var/lib/rundeck/.kube/monitoring-eu-prod.yml',
50 'eu-qa-logging':'/var/lib/rundeck/.kube/logging-eu-qa.yml',
51 'eu-qa-monitoring':'/var/lib/rundeck/.kube/monitoring-eu-qa.yml',
52 'mcmp-dmo':'/var/lib/rundeck/.kube/mcmp/mcmp-demo-cic.yml',
53 'minidash':'/var/lib/rundeck/.kube/internal/dash-dev.yml',
54 'kmd/planning-kmd-prod':'/var/lib/rundeck/.kube/kmd/planning-kmd-prod.yml',
55 'kmd/planning-kmd-stage':'/var/lib/rundeck/.kube/kmd/planning-kmd-stage.yml',
56 'ubis-dev':'/var/lib/rundeck/.kube/ubis-dev.yml',
57 'ubis-prod':'/var/lib/rundeck/.kube/ubis-prod.yml',
58 'ubis-stage':'/var/lib/rundeck/.kube/ubis-stage.yml',
59 'ubis-test':'/var/lib/rundeck/.kube/ubis-test.yml'
60 #to add new environment just provide key:value pair - name of environment and path to kube config
61 }
62 print("Working with environment {}".format(conf_dict.get(arg)))
63 kube_cfg = conf_dict.get(arg)
64 return kube_cfg
65
66def getContainerDetails(db,ns):
67
68 print("Getting pod name by label")
69 get_pod = v1.list_namespaced_pod(ns)
70 for i in get_pod.items:
71 if i.metadata.labels.get("name") == db:
72 print("Pod name is {}".format(i.metadata.name))
73 break;
74 get_port = v1.read_namespaced_pod(i.metadata.name, ns)
75 for j in get_port.spec.containers:
76 for k in j.ports:
77 print("Pod {} container port is {}".format(i.metadata.name,k.container_port))
78
79 #returned value are Pod name and container of database port
80 return i.metadata.name, k.container_port
81
82def getnamespacePod(namespace):
83 print("Namespace pod of namespace provided")
84 response = v1.list_namespaced_pod(namespace)
85 for i in response.items:
86 print("%s\t%s" % (i.status.pod_ip, i.metadata.name))
87
88#Func to run command kubectl port-forward based on the arguments provided to running script and output of pod
89def portForward(pod,namespace,port_in,port_pod,seconds):
90 print("Run port forwarding for pod {} with open port {} that listen on port {}".format(pod,port_pod,port_in))
91 kube_command = ('kubectl port-forward {} -n {} {}:{} &'.format(pod, namespace, port_in, port_pod, seconds))
92 time.sleep(5)
93 run = subprocess.Popen(kube_command,shell=True)#stderr=subprocess.PIPE)
94 print(run)
95 time.sleep(10)
96 print(subprocess.Popen(["curl","localhost:{}".format(port_in)]))
97 seconds = int(seconds)
98 time.sleep(5)
99 for line in os.popen("ps aux | grep port-forward "+" | grep {}:{}".format(port_in,port_pod)):
100 fields = line.split()
101 pid = fields[1]
102 print(fields,pid)
103 os.kill(int(pid), signal.SIGKILL)
104 print(kube_command)
105
106def extractSecrets(db,namespace):
107 response = v1.list_namespaced_secret(namespace)
108 print("\n")
109 print("Looking for secrets...")
110 print("\n")
111 time.sleep(3)
112 for i in response.items:
113 if db in i.metadata.name:
114 print("Secret match with database name")
115 logger.info("Printing extracted secret for database")
116 secrets = v1.read_namespaced_secret(i.metadata.name, namespace)
117 print("Extracting for secret name {}".format(i.metadata.name))
118 count = list(secrets.data.items())
119 for i in range(len(count)):
120 print("Extracted value of key {} : {}".format(list(secrets.data.keys())[i],base64.b64decode(list(secrets.data.values())[i]).decode("utf-8")))
121 else:
122 continue
123
124def sleepFunct(seconds):
125 sleep_time = int(seconds)
126 print("Waiting {} to close script".format(sleep_time))
127# sleep(sleep_time)
128 for i in range(sleep_time):
129 if i % 10 == 0:
130 print(i)
131 time.sleep(1)
132
133 print("Script completed")
134
135if __name__ == '__main__':
136
137 args = get_input()
138 ns = args.namespace
139 env = args.env
140 db = args.database
141 seconds = args.seconds
142
143 #Assign v1 variable to work with CoreV1API
144
145 kubecfg = getKubecfg(env)
146 print("Trying load from provided path")
147 config.load_kube_config(kubecfg)
148
149 v1 = client.CoreV1Api()
150
151 logger.info("Getting pod name and container port based on selected database attached to namespace")
152 pod, port_pod = getContainerDetails(db,ns)
153
154 logger.info("Assigning target port to selected database")
155
156 if db == "mongodb":
157 port_in = 50100
158 print("Assigned mongodb to target port 50100")
159 elif db == "couchdb":
160 port_in = 50200
161 print("Assigned couchdb to target port 50200")
162 elif db == "mariadb":
163 port_in = 50300
164 print("Assigned mariadb to target port 50300")
165
166 logger.info("Enabling port forward")
167 portForward(pod,ns,port_in,port_pod,seconds)
168 extractSecrets(db,ns)
169 sleepFunct(seconds)