From 734a814553a1769c4c12474e1cf8005c663a47ff Mon Sep 17 00:00:00 2001
From: Martin Levy <martin@cloudflare.com>
Date: Wed, 15 Jan 2020 15:16:55 -0800
Subject: [PATCH] changed converters to have more meaningful error handlers

---
 cli4/cli4.py       | 52 +++++++++++++++++++++++----------------
 cli4/converters.py | 61 ++++++++++++++++++++++++++++++----------------
 2 files changed, 71 insertions(+), 42 deletions(-)

diff --git a/cli4/cli4.py b/cli4/cli4.py
index 09b5b4e..9c16848 100644
--- a/cli4/cli4.py
+++ b/cli4/cli4.py
@@ -56,23 +56,29 @@ def run_command(cf, method, command, params=None, content=None, files=None):
                 elif element[0] == ':':
                     # raw string - used for workers script_name - use ::script_name
                     identifier1 = element[1:]
-                elif cmd[0] == 'certificates':
-                    # identifier1 = convert_certificates_to_identifier(cf, element)
-                    identifier1 = converters.convert_zones_to_identifier(cf, element)
-                elif cmd[0] == 'zones':
-                    identifier1 = converters.convert_zones_to_identifier(cf, element)
-                elif cmd[0] == 'organizations':
-                    identifier1 = converters.convert_organizations_to_identifier(cf, element)
-                elif (cmd[0] == 'user') and (cmd[1] == 'organizations'):
-                    identifier1 = converters.convert_organizations_to_identifier(cf, element)
-                elif (cmd[0] == 'user') and (cmd[1] == 'invites'):
-                    identifier1 = converters.convert_invites_to_identifier(cf, element)
-                elif (cmd[0] == 'user') and (cmd[1] == 'virtual_dns'):
-                    identifier1 = converters.convert_virtual_dns_to_identifier(cf, element)
-                elif (cmd[0] == 'user') and (cmd[1] == 'load_balancers') and (cmd[2] == 'pools'):
-                    identifier1 = converters.convert_load_balancers_pool_to_identifier(cf, element)
                 else:
-                    exit("/%s/%s :NOT CODED YET 1" % ('/'.join(cmd), element))
+                    try:
+                        if cmd[0] == 'certificates':
+                            # identifier1 = convert_certificates_to_identifier(cf, element)
+                            identifier1 = converters.convert_zones_to_identifier(cf, element)
+                        elif cmd[0] == 'zones':
+                            identifier1 = converters.convert_zones_to_identifier(cf, element)
+                        elif cmd[0] == 'accounts':
+                            identifier1 = converters.convert_accounts_to_identifier(cf, element)
+                        elif cmd[0] == 'organizations':
+                            identifier1 = converters.convert_organizations_to_identifier(cf, element)
+                        elif (cmd[0] == 'user') and (cmd[1] == 'organizations'):
+                            identifier1 = converters.convert_organizations_to_identifier(cf, element)
+                        elif (cmd[0] == 'user') and (cmd[1] == 'invites'):
+                            identifier1 = converters.convert_invites_to_identifier(cf, element)
+                        elif (cmd[0] == 'user') and (cmd[1] == 'virtual_dns'):
+                            identifier1 = converters.convert_virtual_dns_to_identifier(cf, element)
+                        elif (cmd[0] == 'user') and (cmd[1] == 'load_balancers') and (cmd[2] == 'pools'):
+                            identifier1 = converters.convert_load_balancers_pool_to_identifier(cf, element)
+                        else:
+                            raise Exception("/%s/%s :NOT CODED YET" % ('/'.join(cmd), element))
+                    except Exception as e:
+                        exit('cli4: /%s - %s' % (command, e))
                 cmd.append(':' + identifier1)
             elif identifier2 is None:
                 if len(element) in [32, 40, 48] and hex_only.match(element):
@@ -81,12 +87,16 @@ def run_command(cf, method, command, params=None, content=None, files=None):
                 elif element[0] == ':':
                     # raw string - used for workers script_names
                     identifier2 = element[1:]
-                elif (cmd[0] and cmd[0] == 'zones') and (cmd[2] and cmd[2] == 'dns_records'):
-                    identifier2 = converters.convert_dns_record_to_identifier(cf,
-                                                                              identifier1,
-                                                                              element)
                 else:
-                    exit("/%s/%s :NOT CODED YET 2" % ('/'.join(cmd), element))
+                    try:
+                        if (cmd[0] and cmd[0] == 'zones') and (cmd[2] and cmd[2] == 'dns_records'):
+                            identifier2 = converters.convert_dns_record_to_identifier(cf,
+                                                                                      identifier1,
+                                                                                      element)
+                        else:
+                            raise Exception("/%s/%s :NOT CODED YET" % ('/'.join(cmd), element))
+                    except Exception as e:
+                        exit('cli4: /%s - %s' % (command, e))
                 # identifier2 may be an array - this needs to be dealt with later
                 if isinstance(identifier2, list):
                     cmd.append(':' + '[' + ','.join(identifier2) + ']')
diff --git a/cli4/converters.py b/cli4/converters.py
index 3b58ad3..78b81a1 100644
--- a/cli4/converters.py
+++ b/cli4/converters.py
@@ -3,20 +3,39 @@
 
 import CloudFlare
 
+class converterError(Exception):
+    """ errors for converters"""
+    pass
+
 def convert_zones_to_identifier(cf, zone_name):
     """zone names to numbers"""
     params = {'name':zone_name, 'per_page':1}
     try:
         zones = cf.zones.get(params=params)
     except CloudFlare.exceptions.CloudFlareAPIError as e:
-        exit('cli4: %s - %d %s' % (zone_name, e, e))
+        raise converterError(int(e), '%s - %d %s' % (zone_name, e, e))
     except Exception as e:
-        exit('cli4: %s - %s' % (zone_name, e))
+        raise converterError(0, '%s - %s' % (zone_name, e))
 
     if len(zones) == 1:
         return zones[0]['id']
 
-    exit('cli4: %s - zone not found' % (zone_name))
+    raise converterError('%s: not found' % (zone_name))
+
+def convert_accounts_to_identifier(cf, account_name):
+    """account names to numbers"""
+    params = {'name':account_name, 'per_page':1}
+    try:
+        accounts = cf.accounts.get(params=params)
+    except CloudFlare.exceptions.CloudFlareAPIError as e:
+        raise converterError(int(e), '%s - %d %s' % (account_name, e, e))
+    except Exception as e:
+        raise converterError(0, '%s - %s' % (account_name, e))
+
+    if len(accounts) == 1:
+        return accounts[0]['id']
+
+    raise converterError('%s: not found' % (account_name))
 
 def convert_dns_record_to_identifier(cf, zone_id, dns_name):
     """dns record names to numbers"""
@@ -25,9 +44,9 @@ def convert_dns_record_to_identifier(cf, zone_id, dns_name):
     try:
         dns_records = cf.zones.dns_records.get(zone_id, params=params)
     except CloudFlare.exceptions.CloudFlareAPIError as e:
-        exit('cli4: %s - %d %s' % (dns_name, e, e))
+        raise converterError(int(e), '%s - %d %s' % (dns_name, e, e))
     except Exception as e:
-        exit('cli4: %s - %s' % (dns_name, e))
+        raise converterError(0, '%s - %s' % (dns_name, e))
 
     r = []
     for dns_record in dns_records:
@@ -36,80 +55,80 @@ def convert_dns_record_to_identifier(cf, zone_id, dns_name):
     if len(r) > 0:
         return r
 
-    exit('cli4: %s - dns name not found' % (dns_name))
+    raise converterError('%s: not found' % (dns_name))
 
 def convert_certificates_to_identifier(cf, certificate_name):
     """certificate names to numbers"""
     try:
         certificates = cf.certificates.get()
     except CloudFlare.exceptions.CloudFlareAPIError as e:
-        exit('cli4: %s - %d %s' % (certificate_name, e, e))
+        raise converterError(int(e), '%s - %d %s' % (certificate_name, e, e))
     except Exception as e:
-        exit('cli4: %s - %s' % (certificate_name, e))
+        raise converterError(0, '%s - %s' % (certificate_name, e))
 
     for certificate in certificates:
         if certificate_name in certificate['hostnames']:
             return certificate['id']
 
-    exit('cli4: %s - no zone certificates found' % (certificate_name))
+    raise converterError('%s: not found' % (certificate_name))
 
 def convert_organizations_to_identifier(cf, organization_name):
     """organizations names to numbers"""
     try:
         organizations = cf.user.organizations.get()
     except CloudFlare.exceptions.CloudFlareAPIError as e:
-        exit('cli4: %s - %d %s' % (organization_name, e, e))
+        raise converterError(int(e), '%s - %d %s' % (organization_name, e, e))
     except Exception as e:
-        exit('cli4: %s - %s' % (organization_name, e))
+        raise converterError(0, '%s - %s' % (organization_name, e))
 
     for organization in organizations:
         if organization_name == organization['name']:
             return organization['id']
 
-    exit('cli4: %s - no organizations found' % (organization_name))
+    raise converterError('%s not found' % (organization_name))
 
 def convert_invites_to_identifier(cf, invite_name):
     """invite names to numbers"""
     try:
         invites = cf.user.invites.get()
     except CloudFlare.exceptions.CloudFlareAPIError as e:
-        exit('cli4: %s - %d %s' % (invite_name, e, e))
+        raise converterError(int(e), '%s - %d %s' % (invite_name, e, e))
     except Exception as e:
-        exit('cli4: %s - %s' % (invite_name, e))
+        raise converterError(0, '%s - %s' % (invite_name, e))
 
     for invite in invites:
         if invite_name == invite['organization_name']:
             return invite['id']
 
-    exit('cli4: %s - no invites found' % (invite_name))
+    raise converterError('%s: not found' % (invite_name))
 
 def convert_virtual_dns_to_identifier(cf, virtual_dns_name):
     """virtual dns names to numbers"""
     try:
         virtual_dnss = cf.user.virtual_dns.get()
     except CloudFlare.exceptions.CloudFlareAPIError as e:
-        exit('cli4: %s - %d %s\n' % (virtual_dns_name, e, e))
+        raise converterError(int(e), '%s - %d %s' % (virtual_dns_name, e, e))
     except Exception as e:
-        exit('cli4: %s - %s\n' % (virtual_dns_name, e))
+        raise converterError(0, '%s - %s' % (virtual_dns_name, e))
 
     for virtual_dns in virtual_dnss:
         if virtual_dns_name == virtual_dns['name']:
             return virtual_dns['id']
 
-    exit('cli4: %s - no virtual_dns found' % (virtual_dns_name))
+    raise converterError('%s: not found' % (virtual_dns_name))
 
 def convert_load_balancers_pool_to_identifier(cf, pool_name):
     """load balancer pool names to numbers"""
     try:
         pools = cf.user.load_balancers.pools.get()
     except CloudFlare.exceptions.CloudFlareAPIError as e:
-        exit('cli4: %s - %d %s' % (pool_name, e, e))
+        raise converterError(int(e), '%s - %d %s' % (pool_name, e, e))
     except Exception as e:
-        exit('cli4: %s - %s' % (pool_name, e))
+        raise converterError(0, '%s - %s' % (pool_name, e))
 
     for p in pools:
         if pool_name == p['description']:
             return p['id']
 
-    exit('cli4: %s - no pools found' % (pool_name))
+    raise converterError('%s: not found' % (pool_name))