1414
1515import CloudFlare
1616
17- def dump_commands (cf ):
17+ def dump_commands ():
1818 """dump a tree of all the known API commands"""
19+ cf = CloudFlare .CloudFlare ()
1920 w = cf .api_list ()
2021 sys .stdout .write ('\n ' .join (w ) + '\n ' )
2122
22- def cli4 (args ):
23- """Cloudflare API via command line"""
24-
25- verbose = False
26- output = 'json'
27- raw = False
28- dump = False
29- method = 'GET'
30-
31- usage = ('usage: cli4 '
32- + '[-V|--version] [-h|--help] [-v|--verbose] [-q|--quiet] [-j|--json] [-y|--yaml] '
33- + '[-r|--raw] '
34- + '[-d|--dump] '
35- + '[--get|--patch|--post|--put|--delete] '
36- + '[item=value|item=@filename|@filename ...] '
37- + '/command...' )
38-
39- try :
40- opts , args = getopt .getopt (args ,
41- 'VhvqjyrdGPOUD' ,
42- [
43- 'version' ,
44- 'help' , 'verbose' , 'quiet' , 'json' , 'yaml' ,
45- 'raw' ,
46- 'dump' ,
47- 'get' , 'patch' , 'post' , 'put' , 'delete'
48- ])
49- except getopt .GetoptError :
50- exit (usage )
51- for opt , arg in opts :
52- if opt in ('-V' , '--version' ):
53- exit ('Cloudflare library version: %s' % (CloudFlare .__version__ ))
54- if opt in ('-h' , '--help' ):
55- exit (usage )
56- elif opt in ('-v' , '--verbose' ):
57- verbose = True
58- elif opt in ('-q' , '--quiet' ):
59- output = None
60- elif opt in ('-j' , '--json' ):
61- output = 'json'
62- elif opt in ('-y' , '--yaml' ):
63- if yaml is None :
64- exit ('cli4: install yaml support' )
65- output = 'yaml'
66- elif opt in ('-r' , '--raw' ):
67- raw = True
68- elif opt in ('-d' , '--dump' ):
69- dump = True
70- elif opt in ('-G' , '--get' ):
71- method = 'GET'
72- elif opt in ('-P' , '--patch' ):
73- method = 'PATCH'
74- elif opt in ('-O' , '--post' ):
75- method = 'POST'
76- elif opt in ('-U' , '--put' ):
77- method = 'PUT'
78- elif opt in ('-D' , '--delete' ):
79- method = 'DELETE'
80-
81- if dump :
82- cf = CloudFlare .CloudFlare ()
83- dump_commands (cf )
84- exit (0 )
85-
86- digits_only = re .compile ('^-?[0-9]+$' )
87- floats_only = re .compile ('^-?[0-9.]+$' )
88-
89- # next grab the params. These are in the form of tag=value or =value or @filename
90- params = None
91- content = None
92- files = None
93- while len (args ) > 0 and ('=' in args [0 ] or args [0 ][0 ] == '@' ):
94- arg = args .pop (0 )
95- if arg [0 ] == '@' :
96- if method != 'PUT' :
97- exit ('cli4: %s - raw file upload only with PUT' % (filename ))
98- filename = arg [1 :]
99- try :
100- if filename == '-' :
101- content = sys .stdin .read ()
102- else :
103- with open (filename , 'r' ) as f :
104- content = f .read ()
105- except IOError :
106- exit ('cli4: %s - file open failure' % (filename ))
107- continue
108- tag_string , value_string = arg .split ('=' , 1 )
109- if value_string .lower () == 'true' :
110- value = True
111- elif value_string .lower () == 'false' :
112- value = False
113- elif value_string == '' or value_string .lower () == 'none' :
114- value = None
115- elif value_string [0 ] is '=' and value_string [1 :] == '' :
116- exit ('cli4: %s== - no number value passed' % (tag_string ))
117- elif value_string [0 ] is '=' and digits_only .match (value_string [1 :]):
118- value = int (value_string [1 :])
119- elif value_string [0 ] is '=' and floats_only .match (value_string [1 :]):
120- value = float (value_string [1 :])
121- elif value_string [0 ] is '=' :
122- exit ('cli4: %s== - invalid number value passed' % (tag_string ))
123- elif value_string [0 ] in '[{' and value_string [- 1 ] in '}]' :
124- # a json structure - used in pagerules
125- try :
126- #value = json.loads(value) - changed to yaml code to remove unicode string issues
127- if yaml is None :
128- exit ('cli4: install yaml support' )
129- value = yaml .safe_load (value_string )
130- except ValueError :
131- exit ('cli4: %s="%s" - can\' t parse json value' % (tag_string , value_string ))
132- elif value_string [0 ] is '@' :
133- filename = value_string [1 :]
134- # a file to be uploaded - used in dns_records/import - only via POST
135- if method != 'POST' :
136- exit ('cli4: %s=%s - file upload only with POST' % (tag_string , filename ))
137- files = {}
138- try :
139- if filename == '-' :
140- files [tag_string ] = sys .stdin
141- else :
142- files [tag_string ] = open (filename , 'rb' )
143- except IOError :
144- exit ('cli4: %s=%s - file open failure' % (tag_string , filename ))
145- # no need for param code below
146- continue
147- else :
148- value = value_string
149-
150- if tag_string == '' :
151- # There's no tag; it's just an unnamed list
152- if params is None :
153- params = []
154- try :
155- params .append (value )
156- except AttributeError :
157- exit ('cli4: %s=%s - param error. Can\' t mix unnamed and named list' %
158- (tag_string , value_string ))
159- else :
160- if params is None :
161- params = {}
162- tag = tag_string
163- try :
164- params [tag ] = value
165- except TypeError :
166- exit ('cli4: %s=%s - param error. Can\' t mix unnamed and named list' %
167- (tag_string , value_string ))
168-
169- # what's left is the command itself
170- if len (args ) != 1 :
171- exit (usage )
172-
173- command = args [0 ]
23+ def run_command (cf , method , command , params = None , content = None , files = None ):
24+ """run the command line"""
17425 # remove leading and trailing /'s
17526 if command [0 ] == '/' :
17627 command = command [1 :]
@@ -190,8 +41,6 @@ def cli4(args):
19041 hex_only = re .compile ('^[0-9a-fA-F]+$' )
19142 waf_rules = re .compile ('^[0-9]+[A-Z]*$' )
19243
193- cf = CloudFlare .CloudFlare (debug = verbose , raw = raw )
194-
19544 m = cf
19645 for element in parts :
19746 if element [0 ] == ':' :
@@ -302,10 +151,16 @@ def cli4(args):
302151 for x in e :
303152 sys .stderr .write ('cli4: /%s - %d %s\n ' % (command , x , x ))
304153 exit ('cli4: /%s - %d %s' % (command , e , e ))
154+ except CloudFlare .exceptions .CloudFlareInternalError as e :
155+ exit ('cli4: InternalError: /%s - %d %s' % (command , e , e ))
305156 except Exception as e :
306157 exit ('cli4: /%s - %s - api error' % (command , e ))
307158
308159 results .append (r )
160+ return results
161+
162+ def write_results (results , output ):
163+ """dump the results"""
309164
310165 if len (results ) == 1 :
311166 results = results [0 ]
@@ -335,3 +190,165 @@ def cli4(args):
335190 if not results .endswith ('\n ' ):
336191 sys .stdout .write ('\n ' )
337192
193+ def do_it (args ):
194+ """Cloudflare API via command line"""
195+
196+ verbose = False
197+ output = 'json'
198+ raw = False
199+ dump = False
200+ method = 'GET'
201+
202+ usage = ('usage: cli4 '
203+ + '[-V|--version] [-h|--help] [-v|--verbose] [-q|--quiet] [-j|--json] [-y|--yaml] '
204+ + '[-r|--raw] '
205+ + '[-d|--dump] '
206+ + '[--get|--patch|--post|--put|--delete] '
207+ + '[item=value|item=@filename|@filename ...] '
208+ + '/command...' )
209+
210+ try :
211+ opts , args = getopt .getopt (args ,
212+ 'VhvqjyrdGPOUD' ,
213+ [
214+ 'version' ,
215+ 'help' , 'verbose' , 'quiet' , 'json' , 'yaml' ,
216+ 'raw' ,
217+ 'dump' ,
218+ 'get' , 'patch' , 'post' , 'put' , 'delete'
219+ ])
220+ except getopt .GetoptError :
221+ exit (usage )
222+ for opt , arg in opts :
223+ if opt in ('-V' , '--version' ):
224+ exit ('Cloudflare library version: %s' % (CloudFlare .__version__ ))
225+ if opt in ('-h' , '--help' ):
226+ exit (usage )
227+ elif opt in ('-v' , '--verbose' ):
228+ verbose = True
229+ elif opt in ('-q' , '--quiet' ):
230+ output = None
231+ elif opt in ('-j' , '--json' ):
232+ output = 'json'
233+ elif opt in ('-y' , '--yaml' ):
234+ if yaml is None :
235+ exit ('cli4: install yaml support' )
236+ output = 'yaml'
237+ elif opt in ('-r' , '--raw' ):
238+ raw = True
239+ elif opt in ('-d' , '--dump' ):
240+ dump = True
241+ elif opt in ('-G' , '--get' ):
242+ method = 'GET'
243+ elif opt in ('-P' , '--patch' ):
244+ method = 'PATCH'
245+ elif opt in ('-O' , '--post' ):
246+ method = 'POST'
247+ elif opt in ('-U' , '--put' ):
248+ method = 'PUT'
249+ elif opt in ('-D' , '--delete' ):
250+ method = 'DELETE'
251+
252+ if dump :
253+ dump_commands ()
254+ exit (0 )
255+
256+ digits_only = re .compile ('^-?[0-9]+$' )
257+ floats_only = re .compile ('^-?[0-9.]+$' )
258+
259+ # next grab the params. These are in the form of tag=value or =value or @filename
260+ params = None
261+ content = None
262+ files = None
263+ while len (args ) > 0 and ('=' in args [0 ] or args [0 ][0 ] == '@' ):
264+ arg = args .pop (0 )
265+ if arg [0 ] == '@' :
266+ # a file to be uploaded - used in workers/script - only via PUT
267+ filename = arg [1 :]
268+ if method != 'PUT' :
269+ exit ('cli4: %s - raw file upload only with PUT' % (filename ))
270+ try :
271+ if filename == '-' :
272+ content = sys .stdin .read ()
273+ else :
274+ with open (filename , 'r' ) as f :
275+ content = f .read ()
276+ except IOError :
277+ exit ('cli4: %s - file open failure' % (filename ))
278+ continue
279+ tag_string , value_string = arg .split ('=' , 1 )
280+ if value_string .lower () == 'true' :
281+ value = True
282+ elif value_string .lower () == 'false' :
283+ value = False
284+ elif value_string == '' or value_string .lower () == 'none' :
285+ value = None
286+ elif value_string [0 ] is '=' and value_string [1 :] == '' :
287+ exit ('cli4: %s== - no number value passed' % (tag_string ))
288+ elif value_string [0 ] is '=' and digits_only .match (value_string [1 :]):
289+ value = int (value_string [1 :])
290+ elif value_string [0 ] is '=' and floats_only .match (value_string [1 :]):
291+ value = float (value_string [1 :])
292+ elif value_string [0 ] is '=' :
293+ exit ('cli4: %s== - invalid number value passed' % (tag_string ))
294+ elif value_string [0 ] in '[{' and value_string [- 1 ] in '}]' :
295+ # a json structure - used in pagerules
296+ try :
297+ #value = json.loads(value) - changed to yaml code to remove unicode string issues
298+ if yaml is None :
299+ exit ('cli4: install yaml support' )
300+ value = yaml .safe_load (value_string )
301+ except ValueError :
302+ exit ('cli4: %s="%s" - can\' t parse json value' % (tag_string , value_string ))
303+ elif value_string [0 ] is '@' :
304+ # a file to be uploaded - used in dns_records/import - only via POST
305+ filename = value_string [1 :]
306+ if method != 'POST' :
307+ exit ('cli4: %s=%s - file upload only with POST' % (tag_string , filename ))
308+ files = {}
309+ try :
310+ if filename == '-' :
311+ files [tag_string ] = sys .stdin
312+ else :
313+ files [tag_string ] = open (filename , 'rb' )
314+ except IOError :
315+ exit ('cli4: %s=%s - file open failure' % (tag_string , filename ))
316+ # no need for param code below
317+ continue
318+ else :
319+ value = value_string
320+
321+ if tag_string == '' :
322+ # There's no tag; it's just an unnamed list
323+ if params is None :
324+ params = []
325+ try :
326+ params .append (value )
327+ except AttributeError :
328+ exit ('cli4: %s=%s - param error. Can\' t mix unnamed and named list' %
329+ (tag_string , value_string ))
330+ else :
331+ if params is None :
332+ params = {}
333+ tag = tag_string
334+ try :
335+ params [tag ] = value
336+ except TypeError :
337+ exit ('cli4: %s=%s - param error. Can\' t mix unnamed and named list' %
338+ (tag_string , value_string ))
339+
340+ # what's left is the command itself
341+ if len (args ) != 1 :
342+ exit (usage )
343+ command = args [0 ]
344+
345+ cf = CloudFlare .CloudFlare (debug = verbose , raw = raw )
346+ results = run_command (cf , method , command , params , content , files )
347+ write_results (results , output )
348+
349+ def cli4 (args ):
350+ """Cloudflare API via command line"""
351+
352+ do_it (args )
353+ exit (0 )
354+
0 commit comments