File: config.py

package info (click to toggle)
kytos-utils 2019.2-3
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 396 kB
  • sloc: python: 1,310; sh: 15; makefile: 3
file content (158 lines) | stat: -rw-r--r-- 5,960 bytes parent folder | download | duplicates (2)
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
"""Kytos utils configuration."""
# This file is part of kytos-utils.
#
# Copyright (c) 2016 Kytos Team
#
# Authors:
#    Beraldo Leal <beraldo AT ncc DOT unesp DOT br>

import json
import logging
import os
import re
import urllib.request
from collections import namedtuple
from configparser import ConfigParser

LOG = logging.getLogger(__name__)


class KytosConfig():
    """Kytos Configs.

    Read the config file for kytos utils and/or request data for the user in
    order to get the correct paths and links.
    """

    def __init__(self, config_file='~/.kytosrc'):
        """Init method.

        Receive the config_file as argument.
        """
        self.config_file = os.path.expanduser(config_file)
        self.debug = False
        if self.debug:
            LOG.setLevel(logging.DEBUG)

        # allow_no_value=True is used to keep the comments on the config file.
        self.config = ConfigParser(allow_no_value=True)

        # Parse the config file. If no config file was found, then create some
        # default sections on the config variable.
        self.config.read(self.config_file)
        self.check_sections(self.config)

        self.set_env_or_defaults()

        if not os.path.exists(self.config_file):
            LOG.warning("Config file %s not found.", self.config_file)
            LOG.warning("Creating a new empty config file.")
            with open(self.config_file, 'w') as output_file:
                os.chmod(self.config_file, 0o0600)
                self.config.write(output_file)

    def log_configs(self):
        """Log the read configs if debug is enabled."""
        for sec in self.config.sections():
            LOG.debug('   %s: %s', sec, self.config.options(sec))

    def set_env_or_defaults(self):
        """Read some environment variables and set them on the config.

        If no environment variable is found and the config section/key is
        empty, then set some default values.
        """
        option = namedtuple('Option', ['section', 'name', 'env_var',
                                       'default_value'])

        options = [option('auth', 'user', 'NAPPS_USER', None),
                   option('auth', 'token', 'NAPPS_TOKEN', None),
                   option('napps', 'api', 'NAPPS_API_URI',
                          'https://napps.kytos.io/api/'),
                   option('napps', 'repo', 'NAPPS_REPO_URI',
                          'https://napps.kytos.io/repo'),
                   option('kytos', 'api', 'KYTOS_API',
                          'http://localhost:8181/')]

        for option in options:
            if not self.config.has_option(option.section, option.name):
                env_value = os.environ.get(option.env_var,
                                           option.default_value)
                if env_value:
                    self.config.set(option.section, option.name, env_value)

        self.config.set('global', 'debug', str(self.debug))

    @staticmethod
    def check_sections(config):
        """Create a empty config file."""
        default_sections = ['global', 'auth', 'napps', 'kytos']
        for section in default_sections:
            if not config.has_section(section):
                config.add_section(section)

    def save_token(self, user, token):
        """Save the token on the config file."""
        self.config.set('auth', 'user', user)
        self.config.set('auth', 'token', token)
        # allow_no_value=True is used to keep the comments on the config file.
        new_config = ConfigParser(allow_no_value=True)

        # Parse the config file. If no config file was found, then create some
        # default sections on the config variable.
        new_config.read(self.config_file)
        self.check_sections(new_config)

        new_config.set('auth', 'user', user)
        new_config.set('auth', 'token', token)
        filename = os.path.expanduser(self.config_file)
        with open(filename, 'w') as out_file:
            os.chmod(filename, 0o0600)
            new_config.write(out_file)

    def clear_token(self):
        """Clear Token information on config file."""
        # allow_no_value=True is used to keep the comments on the config file.
        new_config = ConfigParser(allow_no_value=True)

        # Parse the config file. If no config file was found, then create some
        # default sections on the config variable.
        new_config.read(self.config_file)
        self.check_sections(new_config)

        new_config.remove_option('auth', 'user')
        new_config.remove_option('auth', 'token')
        filename = os.path.expanduser(self.config_file)
        with open(filename, 'w') as out_file:
            os.chmod(filename, 0o0600)
            new_config.write(out_file)

    @classmethod
    def get_metadata(cls):
        """Return kytos-utils metadata."""
        meta_path = ("%s/metadata.py" % os.path.dirname(__file__))
        meta_file = open(meta_path).read()
        metadata = dict(re.findall(r"(__[a-z]+__)\s*=\s*'([^']+)'", meta_file))
        return metadata

    @classmethod
    def get_remote_metadata(cls):
        """Return kytos metadata."""
        kytos_api = KytosConfig().config.get('kytos', 'api')
        meta_uri = kytos_api + 'api/kytos/core/metadata/'
        meta_file = urllib.request.urlopen(meta_uri).read()
        metadata = json.loads(meta_file)
        return metadata

    @classmethod
    def check_versions(cls):
        """Check if kytos and kytos-utils metadata are compatible."""
        kytos_metadata = cls.get_remote_metadata()
        kutils_metadata = cls.get_metadata()
        kytos_version = kytos_metadata.get('__version__')
        kutils_version = kutils_metadata.get('__version__')

        if kytos_version != kutils_version:
            logger = logging.getLogger()
            logger.warning('kytos (%s) and kytos utils (%s) versions '
                           'are not equal.', kytos_version, kutils_version)