File: read_configs.py

package info (click to toggle)
python-cloudflare 2.20.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,048 kB
  • sloc: python: 6,932; makefile: 138; sh: 76
file content (117 lines) | stat: -rw-r--r-- 5,621 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
""" reading the config file for Cloudflare API"""

import os
import re
try:
    # py3
    import configparser
except ImportError:
    # py2
    import ConfigParser as configparser # type: ignore

class ReadConfigError(Exception):
    """ errors for read_configs"""

def read_configs(profile=None):
    """ reading the config file for Cloudflare API"""

    # We return all these values
    config = {'email': None, 'key': None, 'token': None, 'certtoken': None, 'extras': None, 'base_url': None, 'openapi_url': None, 'profile': None}

    # envioronment variables override config files - so setup first
    config['email'] = os.getenv('CLOUDFLARE_EMAIL') if os.getenv('CLOUDFLARE_EMAIL') is not None else os.getenv('CF_API_EMAIL')
    config['key'] = os.getenv('CLOUDFLARE_API_KEY') if os.getenv('CLOUDFLARE_API_KEY') is not None else os.getenv('CF_API_KEY')
    config['token'] = os.getenv('CLOUDFLARE_API_TOKEN') if os.getenv('CLOUDFLARE_API_TOKEN') is not None else os.getenv('CF_API_TOKEN')
    config['certtoken'] = os.getenv('CLOUDFLARE_API_CERTKEY') if os.getenv('CLOUDFLARE_API_CERTKEY') is not None else os.getenv('CF_API_CERTKEY')
    config['extras'] = os.getenv('CLOUDFLARE_API_EXTRAS') if os.getenv('CLOUDFLARE_API_EXTRAS') is not None else os.getenv('CF_API_EXTRAS')
    config['base_url'] = os.getenv('CLOUDFLARE_API_URL') if os.getenv('CLOUDFLARE_API_URL') is not None else os.getenv('CF_API_URL')
    config['openapi_url'] = os.getenv('CLOUDFLARE_OPENAPI_URL') if os.getenv('CLOUDFLARE_OPENAPI_URL') is not None else os.getenv('CF_OPENAPI_URL')

    config['global_request_timeout'] = os.getenv('CLOUDFLARE_GLOBAL_REQUEST_TIMEOUT')
    config['max_request_retries'] = os.getenv('CLOUDFLARE_MAX_REQUEST_RETRIES')
    config['http_headers'] = os.getenv('CLOUDFLARE_HTTP_HEADERS')

    # grab values from config files
    cp = configparser.ConfigParser()
    try:
        cp.read([
            '.cloudflare.cfg',
            os.path.expanduser('~/.cloudflare.cfg'),
            os.path.expanduser('~/.cloudflare/cloudflare.cfg')
        ])
    except OSError:
        raise ReadConfigError("%s: configuration file error" % ('.cloudflare.cfg')) from None

    if len(cp.sections()) == 0 and profile is not None and len(profile) > 0:
        # no config file and yet a config name provided - not acceptable!
        raise ReadConfigError("%s: configuration section provided however config file missing" % (profile)) from None

    # Is it CloudFlare or Cloudflare? (A legacy issue)
    if profile is None:
        if cp.has_section('CloudFlare'):
            profile = 'CloudFlare'
        if cp.has_section('Cloudflare'):
            profile = 'Cloudflare'

    # still not found - then set to to CloudFlare for legacy reasons
    if profile is None:
        profile = "CloudFlare"

    config['profile'] = profile

    if len(profile) > 0 and len(cp.sections()) > 0:
        # we have a configuration file - lets use it

        if not cp.has_section(profile):
            raise ReadConfigError("%s: configuration section missing - configuration file only has these sections: %s" % (profile, ','.join(cp.sections()))) from None

        for option in ['email', 'key', 'token', 'certtoken', 'extras', 'base_url', 'openapi_url', 'global_request_timeout', 'max_request_retries', 'http_headers']:
            try:
                config_value = cp.get(profile, option)
                if option == 'extras':
                    # we join all values together as one space seperated strings
                    config[option] = re.sub(r"\s+", ' ', config_value)
                elif option == 'http_headers':
                    # we keep lines as is for now
                    config[option] = config_value
                else:
                    config[option] = re.sub(r"\s+", '', config_value)
                if config[option] is None or config[option] == '':
                    config.pop(option)
            except (configparser.NoOptionError, configparser.NoSectionError):
                pass

            # do we have an override for specific calls? (i.e. token.post or email.get etc)
            for method in ['get', 'patch', 'post', 'put', 'delete']:
                option_for_method = option + '.' + method
                try:
                    config_value = cp.get(profile, option_for_method)
                    config[option_for_method] = re.sub(r"\s+", '', config_value)
                    if config[option] is None or config[option] == '':
                        config.pop(option_for_method)
                except (configparser.NoOptionError, configparser.NoSectionError):
                    pass

    # do any final cleanup - only needed for extras and http_headers (which are multiline)
    if 'extras' in config and config['extras'] is not None:
        config['extras'] = config['extras'].strip().split(' ')
    if 'http_headers' in config and config['http_headers'] is not None:
        config['http_headers'] = [h for h in config['http_headers'].split('\n') if len(h) > 0]
        for h in config['http_headers']:
            try:
                t, v = h.split(':', 1)
            except ValueError:
                # clearly a bad header syntax
                raise ReadConfigError('%s: header syntax error' % (h)) from None
            if len(t.strip()) == 0:
                raise ReadConfigError('%s: header syntax error' % (h)) from None

    # remove blank entries
    for x in sorted(config.keys()):
        if config[x] is None or config[x] == '':
            try:
                config.pop(x)
            except KeyError:
                pass

    return config