Skip to content

Commit

Permalink
finally clean up the one large cli4 routine. it needed to be split a …
Browse files Browse the repository at this point in the history
…long time ago
  • Loading branch information
mahtin committed Feb 24, 2018
1 parent 1a6593c commit c73a674
Showing 1 changed file with 172 additions and 155 deletions.
327 changes: 172 additions & 155 deletions cli4/cli4.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,163 +14,14 @@

import CloudFlare

def dump_commands(cf):
def dump_commands():
"""dump a tree of all the known API commands"""
cf = CloudFlare.CloudFlare()
w = cf.api_list()
sys.stdout.write('\n'.join(w) + '\n')

def cli4(args):
"""Cloudflare API via command line"""

verbose = False
output = 'json'
raw = False
dump = False
method = 'GET'

usage = ('usage: cli4 '
+ '[-V|--version] [-h|--help] [-v|--verbose] [-q|--quiet] [-j|--json] [-y|--yaml] '
+ '[-r|--raw] '
+ '[-d|--dump] '
+ '[--get|--patch|--post|--put|--delete] '
+ '[item=value|item=@filename|@filename ...] '
+ '/command...')

try:
opts, args = getopt.getopt(args,
'VhvqjyrdGPOUD',
[
'version',
'help', 'verbose', 'quiet', 'json', 'yaml',
'raw',
'dump',
'get', 'patch', 'post', 'put', 'delete'
])
except getopt.GetoptError:
exit(usage)
for opt, arg in opts:
if opt in ('-V', '--version'):
exit('Cloudflare library version: %s' % (CloudFlare.__version__))
if opt in ('-h', '--help'):
exit(usage)
elif opt in ('-v', '--verbose'):
verbose = True
elif opt in ('-q', '--quiet'):
output = None
elif opt in ('-j', '--json'):
output = 'json'
elif opt in ('-y', '--yaml'):
if yaml is None:
exit('cli4: install yaml support')
output = 'yaml'
elif opt in ('-r', '--raw'):
raw = True
elif opt in ('-d', '--dump'):
dump = True
elif opt in ('-G', '--get'):
method = 'GET'
elif opt in ('-P', '--patch'):
method = 'PATCH'
elif opt in ('-O', '--post'):
method = 'POST'
elif opt in ('-U', '--put'):
method = 'PUT'
elif opt in ('-D', '--delete'):
method = 'DELETE'

if dump:
cf = CloudFlare.CloudFlare()
dump_commands(cf)
exit(0)

digits_only = re.compile('^-?[0-9]+$')
floats_only = re.compile('^-?[0-9.]+$')

# next grab the params. These are in the form of tag=value or =value or @filename
params = None
content = None
files = None
while len(args) > 0 and ('=' in args[0] or args[0][0] == '@'):
arg = args.pop(0)
if arg[0] == '@':
if method != 'PUT':
exit('cli4: %s - raw file upload only with PUT' % (filename))
filename = arg[1:]
try:
if filename == '-':
content = sys.stdin.read()
else:
with open(filename, 'r') as f:
content = f.read()
except IOError:
exit('cli4: %s - file open failure' % (filename))
continue
tag_string, value_string = arg.split('=', 1)
if value_string.lower() == 'true':
value = True
elif value_string.lower() == 'false':
value = False
elif value_string == '' or value_string.lower() == 'none':
value = None
elif value_string[0] is '=' and value_string[1:] == '':
exit('cli4: %s== - no number value passed' % (tag_string))
elif value_string[0] is '=' and digits_only.match(value_string[1:]):
value = int(value_string[1:])
elif value_string[0] is '=' and floats_only.match(value_string[1:]):
value = float(value_string[1:])
elif value_string[0] is '=':
exit('cli4: %s== - invalid number value passed' % (tag_string))
elif value_string[0] in '[{' and value_string[-1] in '}]':
# a json structure - used in pagerules
try:
#value = json.loads(value) - changed to yaml code to remove unicode string issues
if yaml is None:
exit('cli4: install yaml support')
value = yaml.safe_load(value_string)
except ValueError:
exit('cli4: %s="%s" - can\'t parse json value' % (tag_string, value_string))
elif value_string[0] is '@':
filename = value_string[1:]
# a file to be uploaded - used in dns_records/import - only via POST
if method != 'POST':
exit('cli4: %s=%s - file upload only with POST' % (tag_string, filename))
files = {}
try:
if filename == '-':
files[tag_string] = sys.stdin
else:
files[tag_string] = open(filename, 'rb')
except IOError:
exit('cli4: %s=%s - file open failure' % (tag_string, filename))
# no need for param code below
continue
else:
value = value_string

if tag_string == '':
# There's no tag; it's just an unnamed list
if params is None:
params = []
try:
params.append(value)
except AttributeError:
exit('cli4: %s=%s - param error. Can\'t mix unnamed and named list' %
(tag_string, value_string))
else:
if params is None:
params = {}
tag = tag_string
try:
params[tag] = value
except TypeError:
exit('cli4: %s=%s - param error. Can\'t mix unnamed and named list' %
(tag_string, value_string))

# what's left is the command itself
if len(args) != 1:
exit(usage)

command = args[0]
def run_command(cf, method, command, params=None, content=None, files=None):
"""run the command line"""
# remove leading and trailing /'s
if command[0] == '/':
command = command[1:]
Expand All @@ -190,8 +41,6 @@ def cli4(args):
hex_only = re.compile('^[0-9a-fA-F]+$')
waf_rules = re.compile('^[0-9]+[A-Z]*$')

cf = CloudFlare.CloudFlare(debug=verbose, raw=raw)

m = cf
for element in parts:
if element[0] == ':':
Expand Down Expand Up @@ -302,10 +151,16 @@ def cli4(args):
for x in e:
sys.stderr.write('cli4: /%s - %d %s\n' % (command, x, x))
exit('cli4: /%s - %d %s' % (command, e, e))
except CloudFlare.exceptions.CloudFlareInternalError as e:
exit('cli4: InternalError: /%s - %d %s' % (command, e, e))
except Exception as e:
exit('cli4: /%s - %s - api error' % (command, e))

results.append(r)
return results

def write_results(results, output):
"""dump the results"""

if len(results) == 1:
results = results[0]
Expand Down Expand Up @@ -335,3 +190,165 @@ def cli4(args):
if not results.endswith('\n'):
sys.stdout.write('\n')

def do_it(args):
"""Cloudflare API via command line"""

verbose = False
output = 'json'
raw = False
dump = False
method = 'GET'

usage = ('usage: cli4 '
+ '[-V|--version] [-h|--help] [-v|--verbose] [-q|--quiet] [-j|--json] [-y|--yaml] '
+ '[-r|--raw] '
+ '[-d|--dump] '
+ '[--get|--patch|--post|--put|--delete] '
+ '[item=value|item=@filename|@filename ...] '
+ '/command...')

try:
opts, args = getopt.getopt(args,
'VhvqjyrdGPOUD',
[
'version',
'help', 'verbose', 'quiet', 'json', 'yaml',
'raw',
'dump',
'get', 'patch', 'post', 'put', 'delete'
])
except getopt.GetoptError:
exit(usage)
for opt, arg in opts:
if opt in ('-V', '--version'):
exit('Cloudflare library version: %s' % (CloudFlare.__version__))
if opt in ('-h', '--help'):
exit(usage)
elif opt in ('-v', '--verbose'):
verbose = True
elif opt in ('-q', '--quiet'):
output = None
elif opt in ('-j', '--json'):
output = 'json'
elif opt in ('-y', '--yaml'):
if yaml is None:
exit('cli4: install yaml support')
output = 'yaml'
elif opt in ('-r', '--raw'):
raw = True
elif opt in ('-d', '--dump'):
dump = True
elif opt in ('-G', '--get'):
method = 'GET'
elif opt in ('-P', '--patch'):
method = 'PATCH'
elif opt in ('-O', '--post'):
method = 'POST'
elif opt in ('-U', '--put'):
method = 'PUT'
elif opt in ('-D', '--delete'):
method = 'DELETE'

if dump:
dump_commands()
exit(0)

digits_only = re.compile('^-?[0-9]+$')
floats_only = re.compile('^-?[0-9.]+$')

# next grab the params. These are in the form of tag=value or =value or @filename
params = None
content = None
files = None
while len(args) > 0 and ('=' in args[0] or args[0][0] == '@'):
arg = args.pop(0)
if arg[0] == '@':
# a file to be uploaded - used in workers/script - only via PUT
filename = arg[1:]
if method != 'PUT':
exit('cli4: %s - raw file upload only with PUT' % (filename))
try:
if filename == '-':
content = sys.stdin.read()
else:
with open(filename, 'r') as f:
content = f.read()
except IOError:
exit('cli4: %s - file open failure' % (filename))
continue
tag_string, value_string = arg.split('=', 1)
if value_string.lower() == 'true':
value = True
elif value_string.lower() == 'false':
value = False
elif value_string == '' or value_string.lower() == 'none':
value = None
elif value_string[0] is '=' and value_string[1:] == '':
exit('cli4: %s== - no number value passed' % (tag_string))
elif value_string[0] is '=' and digits_only.match(value_string[1:]):
value = int(value_string[1:])
elif value_string[0] is '=' and floats_only.match(value_string[1:]):
value = float(value_string[1:])
elif value_string[0] is '=':
exit('cli4: %s== - invalid number value passed' % (tag_string))
elif value_string[0] in '[{' and value_string[-1] in '}]':
# a json structure - used in pagerules
try:
#value = json.loads(value) - changed to yaml code to remove unicode string issues
if yaml is None:
exit('cli4: install yaml support')
value = yaml.safe_load(value_string)
except ValueError:
exit('cli4: %s="%s" - can\'t parse json value' % (tag_string, value_string))
elif value_string[0] is '@':
# a file to be uploaded - used in dns_records/import - only via POST
filename = value_string[1:]
if method != 'POST':
exit('cli4: %s=%s - file upload only with POST' % (tag_string, filename))
files = {}
try:
if filename == '-':
files[tag_string] = sys.stdin
else:
files[tag_string] = open(filename, 'rb')
except IOError:
exit('cli4: %s=%s - file open failure' % (tag_string, filename))
# no need for param code below
continue
else:
value = value_string

if tag_string == '':
# There's no tag; it's just an unnamed list
if params is None:
params = []
try:
params.append(value)
except AttributeError:
exit('cli4: %s=%s - param error. Can\'t mix unnamed and named list' %
(tag_string, value_string))
else:
if params is None:
params = {}
tag = tag_string
try:
params[tag] = value
except TypeError:
exit('cli4: %s=%s - param error. Can\'t mix unnamed and named list' %
(tag_string, value_string))

# what's left is the command itself
if len(args) != 1:
exit(usage)
command = args[0]

cf = CloudFlare.CloudFlare(debug=verbose, raw=raw)
results = run_command(cf, method, command, params, content, files)
write_results(results, output)

def cli4(args):
"""Cloudflare API via command line"""

do_it(args)
exit(0)

0 comments on commit c73a674

Please sign in to comment.