I am working on a project where I need to work with http apis and call them using Python
language. Below is what I need to do:
- Take few input parameters like -
environmentName
,instanceName
,configName
. - Call get API on a service. Get the JSON data and compare the
configName
it already has vs what you want to update from the command line. - If config is same then don't do anything and return back with a message.
- But if config is different then post new JSON data with new
configName
passed from command line in it to the service using http api. In this there are two things:- We will make new JSON with new
configName
in it along with one more key which isaction
and value of that will bedownload
. After successfully posting this new JSON then we will call another api (verifyApi
) to verify whether all machines have downloaded successfully that config or not. If they downloaded successfully then we will move to the next step otherwise we will fail and return. - If all machines downloaded successfully, then we will change
action
key toverify
in the same JSON and then we will post it again. After successfully posting this new JSON, we will call sameverifyApi
to make sure all machines have verified successfully.
- We will make new JSON with new
Once everything is successful return, otherwise fail it. Below is my code which does the job:
import requests
import json
import sys
import base64
# define all constants
actions=['download', 'verify']
endpoint="http://consul.{}.demo.com/"
config_path="v1/kv/app-name/{}/config"
status_path="v1/kv/app-name/{}/status/{}"
catalog_path="v1/catalog/service/app-name?ns=default&tag={}"
raw="?raw"
def update( url, json ):
"""
This will make a PUT api call to update with new json config.
"""
try:
r = requests.put(url, data=json, headers={'Content-type': 'application/json'})
r.raise_for_status()
return True
except requests.exceptions.HTTPError as errh:
print ("Http Error:",errh)
except requests.exceptions.ConnectionError as errc:
print ("Error Connecting:",errc)
except requests.exceptions.Timeout as errt:
print ("Timeout Error:",errt)
except requests.exceptions.RequestException as err:
print ("OOps: Something Else",err)
return False
def check( environment, instance, config, action ):
"""
This will get list of all ipAddresses for that instance in that environment.
And then check whether each machine from that list have downloaded and verified successfully.
Basically for each 'action' type I need to verify things.
If successful at the end then print out the message.
"""
flag = True
catalog_url = endpoint.format(environment) + catalog_path.format(instance)
response = requests.get(catalog_url)
url = endpoint.format(environment) + status_path.format(instance) + raw
json_array = response.json()
count = 0
for x in json_array:
ip = x['Address']
count++
r = requests.get(url.format(ip))
data = r.json()
if action == 'download' and "isDownloaded" in data and data['isDownloaded'] and "currentCfg" in data and data['currentCfg'] == config:
continue
elif action == 'verify' and "activeCfg" in data and data['activeCfg'] == config:
continue
else:
flag = False #set to False if above two if statements fail
print("failed to " +action+ " on " +ip)
if flag and action == 'download':
print("downloaded successfully on all "+count+" machines")
elif flag and action == 'verify':
print("verified successfully on all "+count+" machines")
return flag
def main():
# capture inputs from command line
environment = sys.argv[1]
instance = sys.argv[2]
new_config = sys.argv[3]
# make url for get api to verify whether configs are same or not
# as mentioned in point 1.
url=endpoint.format(environment) + config_path.format(instance)
response = requests.get(url + raw)
data = json.loads(response.content)
remote_config = data['remoteConfig']
# compare remote_config in the json with config passed from command prompt
if remote_config == new_config:
print("cannot push same config")
return
# config is different
data['remoteConfig'] = new_config
# now for each action, update json and then verify whether that action completed successfully.
for action in actions:
data['action'] = action
if update(url, json.dumps(data)):
if check(environment, instance, new_config, action):
continue
else:
print(action+ " action failed")
return
else:
print("failed to update")
return
if __name__ == "__main__":
try:
sys.exit(main())
except KeyboardInterrupt:
print("\nCaught ctrl+c, exiting")
Problem Statement
I have my above code which works fine so opting for code review to see if there is any better way to do the above things efficiently. I am also sure we can rewrite the above code in a much cleaner manner compared to the way I have since I am relatively new to Python
and may have made a lot of mistakes in designing it. Given this code will be running in production wanted to see what can be done to improve it.
The idea is something like this when I run it from the command line.
If everything is successful then it should look like this:
python test.py dev master-instace test-config-123.tgz
downloaded successfully on all 10 machines
verified successfully on all 10 machines
config pushed successfully!!
In case of download
action failure:
python test.py dev master-instace test-config-123.tgz
failed to download on 1.2.3.4
failed to download on 4.2.3.4
download action failed
In the case of verify
action failure:
python test.py dev master-instace test-config-123.tgz
downloaded successfully on all 10 machines
failed to verify on 1.2.3.4
failed to verify on 4.2.3.4
verify action failed
or if there is any better way to make the output cleaner - I am open to the suggestion as well.
verify
and the actionverify
related? I feel not, but in either cases it makes for a confusing piece of code! \$\endgroup\$