~fcorrea/charms/trusty/landscape-client/trunk

« back to all changes in this revision

Viewing changes to hooks/common.py

Add a basic test for the container-relation-joined relation.

The purpose of this branch isn't to add full test coverage for the
container-relation-joined relation. It's to make it possible to add
tests for this hooks (and other hooks as well, of course). I added a
simple test to show that it's indeed possible to test it.

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
from landscape.sysvconfig import SysVConfig
12
12
 
13
13
 
14
 
_config = Configuration()
15
 
 
16
 
 
17
14
def log(message):
18
15
    """Log a message via Juju."""
19
16
    return check_output(["juju-log", message])
20
17
 
21
18
 
22
 
def get_client_config():
23
 
    """
24
 
    Return a L{Configuration} object with the current client configuration.
25
 
    """
26
 
    _config.reload()
27
 
    return _config
28
 
 
29
 
 
30
 
def _run_juju_tool(command, params=None):
31
 
    """Run specified Juju tool and parse json output."""
32
 
 
33
 
    cmd = [command, "--format", "json"]
34
 
    if params:
35
 
        cmd.extend(params)
36
 
    output = check_output(cmd)
37
 
    return json.loads(output) if output else {}
38
 
 
39
 
 
40
 
def get_relation_config():
41
 
    """Get relation configuration from Juju."""
42
 
    return _run_juju_tool("relation-get")
43
 
 
44
 
 
45
 
def get_service_config():
46
 
    """Get service configuration from Juju."""
47
 
    return _run_juju_tool("config-get")
48
 
 
49
 
 
50
 
def update_client_config(service_config):
51
 
    """Update the client config.
52
 
 
53
 
    @param service_config: A dict containing the config items to be
54
 
        updated. Dashes in the key values will be converted to
55
 
        underscore, to match the Landscape configuration.
56
 
 
57
 
    An attempt to register the client will be made, if the client wasn't
58
 
    configured before.
59
 
    """
60
 
    client_config = get_client_config()
61
 
    for key, value in service_config.items():
62
 
        if key != "origin":
63
 
            setattr(client_config, key.replace("-", "_"), value)
64
 
        if key == "registration-key":
65
 
            # Use registration_password additionally for
66
 
            # backwards compatibility with landscape-client in precise.
67
 
            setattr(client_config, "registration_password", value)
68
 
    client_config.write()
69
 
    return try_to_register()
70
 
 
71
 
 
72
 
class ErrorHandler:
 
19
class JujuBroker(object):
 
20
    """Class responsible for communicating with Juju.
 
21
 
 
22
    This class should be used to set and get information from Juju, so
 
23
    that it can be overridden in unit tests, where a complete Juju
 
24
    environment isn't available.
 
25
    """
 
26
 
 
27
    def __init__(self):
 
28
        self.environment = os.environ.copy()
 
29
 
 
30
    def get_relation_config(self):
 
31
        """Get relation configuration from Juju."""
 
32
        return self._run_juju_tool("relation-get")
 
33
 
 
34
    def get_service_config(self):
 
35
        """Get service configuration from Juju."""
 
36
        return self._run_juju_tool("config-get")
 
37
 
 
38
    def _run_juju_tool(self, command):
 
39
        """Run specified Juju tool and parse json output."""
 
40
        output = check_output([command, "--format", "json"])
 
41
        return json.loads(output) if output else {}
 
42
 
 
43
 
 
44
class LandscapeBroker(object):
 
45
    """Class responsible for communicating with the Landscape client.
 
46
 
 
47
    This class should be used to interact with Landscape client, so
 
48
    that it can be overridden in unit tests, where we can't let
 
49
    Landscape access system-specific behaviours.
 
50
    """
 
51
 
 
52
    def __init__(self):
 
53
        self.config = Configuration()
 
54
 
 
55
    def update_client_config(self, service_config):
 
56
        """Update the client config.
 
57
 
 
58
        @param service_config: A dict containing the config items to be
 
59
            updated. Dashes in the key values will be converted to
 
60
            underscore, to match the Landscape configuration.
 
61
 
 
62
        An attempt to register the client will be made, if the client wasn't
 
63
        configured before.
 
64
        """
 
65
        self.config.reload()
 
66
        for key, value in service_config.items():
 
67
            if key != "origin":
 
68
                setattr(self.config, key.replace("-", "_"), value)
 
69
            if key == "registration-key":
 
70
                # Use registration_password additionally for
 
71
                # backwards compatibility with landscape-client in precise.
 
72
                setattr(self.config, "registration_password", value)
 
73
        self.config.write()
 
74
        return self.try_to_register()
 
75
 
 
76
    def clear_registration(self):
 
77
        """
 
78
        Do steps necessary to clear the client registration, so that next time
 
79
        it will re-register
 
80
        """
 
81
        stop_client_and_disable_init_script()
 
82
 
 
83
 
 
84
    def try_to_register(self):
 
85
        """Try to register the client if needed.
 
86
 
 
87
        If the client has already been configured, no registration attempt
 
88
        will be made. The same is true if a computer title hasn't been set,
 
89
        since that means that the juju-info-relation-joined hasn't been run,
 
90
        which means that it's expected that the configuration will be broken
 
91
        at that point.
 
92
 
 
93
        The following keys need to be set for an attempt to be made:
 
94
         - account_name, computer_title
 
95
 
 
96
        If an error is encountered, the client will be disabled and the hook
 
97
        calling this function will exit with an error code.
 
98
        """
 
99
        error_handler = ErrorHandler()
 
100
 
 
101
        sysvconfig = SysVConfig()
 
102
        configured = sysvconfig.is_configured_to_run()
 
103
        config = LandscapeSetupConfiguration()
 
104
        config.load([])
 
105
        config.silent = True
 
106
        if configured:
 
107
            print "Client already registered, skipping"
 
108
            return 0
 
109
        if not config.get("account_name") or not config.get("computer_title"):
 
110
            print "Need account-name and computer-title to proceed, skipping"
 
111
            return 0
 
112
        try:
 
113
            setup(config)
 
114
        except ConfigurationError as error:
 
115
            print >> sys.stderr, "Configuration error: %s" % (str(error),)
 
116
            error_handler.flag_error(1)
 
117
        else:
 
118
            register(config, on_error=error_handler.flag_error)
 
119
        return error_handler.exit_code
 
120
 
 
121
 
 
122
class ErrorHandler(object):
73
123
 
74
124
    exit_code = 0
75
125
 
87
137
        self.exit_code = exit_code
88
138
 
89
139
 
90
 
def clear_registration():
91
 
    """
92
 
    Do steps necessary to clear the client registration, so that next time
93
 
    it will re-register
94
 
    """
95
 
    stop_client_and_disable_init_script()
96
 
 
97
 
 
98
 
def try_to_register():
99
 
    """Try to register the client if needed.
100
 
 
101
 
    If the client has already been configured, not registration attempt
102
 
    will be made. The same is true if a computer title hasn't been set,
103
 
    since that means that the juju-info-relation-joined hasn't been run,
104
 
    which means that it's expected that the configuration will be broken
105
 
    at that point.
106
 
 
107
 
    The following keys need to be set for an attempt to be made:
108
 
     - account_name, computer_title
109
 
 
110
 
    If an error is encountered, the client will be disabled and the hook
111
 
    calling this function will exit with an error code.
112
 
    """
113
 
    error_handler = ErrorHandler()
114
 
 
115
 
    sysvconfig = SysVConfig()
116
 
    configured = sysvconfig.is_configured_to_run()
117
 
    config = LandscapeSetupConfiguration()
118
 
    config.load([])
119
 
    config.silent = True
120
 
    if configured:
121
 
        print "Client already registered, skipping"
122
 
        return 0
123
 
    if not config.get("account_name") or not config.get("computer_title"):
124
 
        print "Need account-name and computer-title to proceed, skipping"
125
 
        return 0
126
 
    try:
127
 
        setup(config)
128
 
    except ConfigurationError as error:
129
 
        print >> sys.stderr, "Configuration error: %s" % (str(error),)
130
 
        error_handler.flag_error(1)
131
 
    else:
132
 
        register(config, on_error=error_handler.flag_error)
133
 
    return error_handler.exit_code
134
 
 
135
 
 
136
140
def chown(filename):
137
141
    """Change file owner and group to landscape."""
138
142
    user = getpwnam("landscape")