ripe-api.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. #!/usr/bin/env python3
  2. import requests
  3. import json
  4. import yaml
  5. import sys
  6. import argparse
  7. import tempfile
  8. import os
  9. import hashlib
  10. from subprocess import call
  11. config = os.path.join(os.path.dirname(os.path.realpath(__file__)),"config.yml")
  12. # Read configuration
  13. with open(config, 'r') as ymlfile:
  14. cfg = yaml.load(ymlfile, Loader=yaml.FullLoader)
  15. # Functions
  16. def call_api(method, url, object_data=None):
  17. headers = { 'Content-Type': 'application/json',
  18. 'Accept': 'application/json' }
  19. response = requests.request(method, url, json=object_data, headers=headers,
  20. params=cfg['params'])
  21. if not response.text:
  22. print("No response received (error %i)" % response.status_code)
  23. sys.exit(1)
  24. json_response=json.loads(response.text)
  25. if "errormessages" in json_response:
  26. for err in json_response['errormessages']['errormessage']:
  27. if 'args' in err:
  28. print(err['text'].replace('\n', ' ').replace('\r', '') \
  29. % tuple([d['value'] for d in err['args']]))
  30. else:
  31. print(err['text'])
  32. return json_response
  33. # Print formatted output from JSON
  34. def print_output(json, object_file):
  35. if "objects" in json:
  36. for attr in json['objects']['object'][0]['attributes']['attribute']:
  37. object_file.write("%-20s %s\n" % (attr['name']+':',
  38. attr['value']))
  39. if object_file:
  40. object_file.close()
  41. def read_input(object_file):
  42. attr = []
  43. for line in object_file.readlines():
  44. if not line: continue
  45. attr.append({'name':line.split(':', 1)[0].strip(),
  46. 'value':line.split(':', 1)[1].strip() })
  47. object_data = {
  48. "objects": {
  49. "object": [
  50. {
  51. "attributes": {
  52. "attribute": attr
  53. }
  54. }
  55. ]
  56. }
  57. }
  58. return object_data
  59. # Get record
  60. def get(args):
  61. print("Getting %s object %s" % (args.type, args.key))
  62. url = '/'.join((cfg['base_url'],args.type,args.key))
  63. json_response=call_api("GET", url)
  64. print_output(json_response, args.file)
  65. return
  66. # Delete record
  67. def delete(args):
  68. print("Deleting %s object %s" % (args.type, args.key))
  69. url = '/'.join((cfg['base_url'],args.type,args.key))
  70. json_response=call_api("DELETE", url)
  71. return
  72. # Create record
  73. def create(args):
  74. print("Creating %s object" % (args.type))
  75. url = '/'.join((cfg['base_url'],args.type))
  76. object_data = read_input(args.file)
  77. json_response=call_api("POST", url, object_data)
  78. print_output(json_response, sys.stdout)
  79. return
  80. # Update record
  81. def update(args):
  82. print("Updating %s object %s" % (args.type, args.key))
  83. url = '/'.join((cfg['base_url'],args.type,args.key))
  84. object_data = read_input(args.file)
  85. json_response=call_api("PUT", url, object_data)
  86. print_output(json_response, sys.stdout)
  87. return
  88. # Edit record
  89. def edit(args):
  90. tmp_fd, tmp_name = tempfile.mkstemp()
  91. get(parser.parse_args(["get", args.type, args.key, tmp_name]))
  92. EDITOR = os.environ.get('EDITOR','vim')
  93. # Memory inefficient, but who cares?
  94. hash1 = hashlib.md5(open(tmp_name).read().encode('utf-8')).hexdigest()
  95. call([EDITOR, tmp_name])
  96. hash2 = hashlib.md5(open(tmp_name).read().encode('utf-8')).hexdigest()
  97. if hash1 != hash2:
  98. update(parser.parse_args(["update", args.type, args.key, tmp_name]))
  99. else:
  100. print("Object unchanged, not updating")
  101. os.unlink(tmp_name)
  102. return
  103. if __name__ == '__main__':
  104. # Arguments parsing
  105. # USAGE : ./ripe-api.py delete <TYPE> <KEY>
  106. # ./ripe-api.py create <TYPE> <FILE>
  107. # ./ripe-api.py update <TYPE> <KEY> <FILE>
  108. # ./ripe-api.py get <TYPE> <KEY> <FILE>
  109. # ./ripe-api.py edit <TYPE> <KEY>
  110. parser = argparse.ArgumentParser(description='RIPE API client')
  111. subparsers = parser.add_subparsers(help='Action to perform',dest='action',required=True)
  112. parser_get = subparsers.add_parser('get', help='Get an object')
  113. parser_get.add_argument('type', type=str, help='Object type')
  114. parser_get.add_argument('key', type=str, help='Object identifier')
  115. parser_get.add_argument('file', type=argparse.FileType('w'), help='Output file')
  116. parser_delete = subparsers.add_parser('delete', help='Delete an object')
  117. parser_delete.add_argument('type', type=str, help='Object type')
  118. parser_delete.add_argument('key', type=str, help='Object identifier')
  119. parser_post = subparsers.add_parser('create', help='Create an object')
  120. parser_post.add_argument('type', type=str, help='Object type')
  121. parser_post.add_argument('file', type=argparse.FileType('r'), help='Input file')
  122. parser_put = subparsers.add_parser('update', help='Update an object')
  123. parser_put.add_argument('type', type=str, help='Object type')
  124. parser_put.add_argument('key', type=str, help='Object identifier')
  125. parser_put.add_argument('file', type=argparse.FileType('r'), help='Input file')
  126. parser_edit = subparsers.add_parser('edit', help='Edit an object')
  127. parser_edit.add_argument('type', type=str, help='Object type')
  128. parser_edit.add_argument('key', type=str, help='Object identifier')
  129. args = parser.parse_args()
  130. globals()[args.action](args)