~nskaggs/juju-ci-tools/add-essential-operations

« back to all changes in this revision

Viewing changes to jujupy.py

Merge trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
672
672
        if retcode != 0:
673
673
            raise subprocess.CalledProcessError(retcode, full_args)
674
674
 
675
 
    def get_juju_output(self, command, args, used_feature_flags,
676
 
                        juju_home, model=None, timeout=None, user_name=None):
 
675
    def get_juju_output(self, command, args, used_feature_flags, juju_home,
 
676
                        model=None, timeout=None, user_name=None,
 
677
                        merge_stderr=False):
677
678
        args = self.full_args(command, args, model, timeout)
678
679
        env = self.shell_environ(used_feature_flags, juju_home)
679
680
        log.debug(args)
682
683
        with scoped_environ(env):
683
684
            proc = subprocess.Popen(
684
685
                args, stdout=subprocess.PIPE, stdin=subprocess.PIPE,
685
 
                stderr=subprocess.PIPE)
 
686
                stderr=subprocess.STDOUT if merge_stderr else subprocess.PIPE)
686
687
            sub_output, sub_error = proc.communicate()
687
688
            log.debug(sub_output)
688
689
            if proc.returncode != 0:
690
691
                e = subprocess.CalledProcessError(
691
692
                    proc.returncode, args, sub_output)
692
693
                e.stderr = sub_error
693
 
                if (
 
694
                if sub_error and (
694
695
                    'Unable to connect to environment' in sub_error or
695
696
                        'MissingOrIncorrectVersionHeader' in sub_error or
696
697
                        '307: Temporary Redirect' in sub_error):
836
837
 
837
838
    agent_metadata_url = 'agent-metadata-url'
838
839
 
 
840
    model_permissions = frozenset(['read', 'write', 'admin'])
 
841
 
 
842
    controller_permissions = frozenset(['login', 'addmodel', 'superuser'])
 
843
 
839
844
    @classmethod
840
845
    def preferred_container(cls):
841
846
        for container_type in [LXD_MACHINE, LXC_MACHINE]:
1153
1158
        """
1154
1159
        model = self._cmd_model(kwargs.get('include_e', True),
1155
1160
                                kwargs.get('controller', False))
1156
 
        timeout = kwargs.get('timeout')
 
1161
        pass_kwargs = dict(
 
1162
            (k, kwargs[k]) for k in kwargs if k in ['timeout', 'merge_stderr'])
1157
1163
        return self._backend.get_juju_output(
1158
1164
            command, args, self.used_feature_flags, self.env.juju_home,
1159
 
            model, timeout, user_name=self.env.user_name)
 
1165
            model, user_name=self.env.user_name, **pass_kwargs)
1160
1166
 
1161
1167
    def show_status(self):
1162
1168
        """Print the status to output."""
1505
1511
 
1506
1512
    def get_model_uuid(self):
1507
1513
        name = self.env.environment
1508
 
        output_yaml = self.get_juju_output('show-model', '--format', 'yaml')
 
1514
        model = self._cmd_model(True, False)
 
1515
        output_yaml = self.get_juju_output(
 
1516
            'show-model', '--format', 'yaml', model, include_e=False)
1509
1517
        output = yaml.safe_load(output_yaml)
1510
1518
        return output[name]['model-uuid']
1511
1519
 
1835
1843
        output = self.get_juju_output('add-user', *args, include_e=False)
1836
1844
        return self._get_register_command(output)
1837
1845
 
 
1846
    # Future ACL feature.
 
1847
    # def add_user(self, username, models=None, permissions='login'):
 
1848
    #     """Adds provided user and return register command arguments.
 
1849
 
 
1850
    #     :return: Registration token provided by the add-user command.
 
1851
    #     """
 
1852
    #     output = self.get_juju_output('add-user', include_e=False)
 
1853
    #     self.grant(username, permissions, models)
 
1854
    #     return self._get_register_command(output)
 
1855
 
1838
1856
    def revoke(self, username, models=None, permissions='read'):
1839
1857
        if models is None:
1840
1858
            models = self.env.environment
1841
1859
 
1842
 
        args = (username, models, '--acl', permissions)
 
1860
        args = (username, permissions, models)
1843
1861
 
1844
1862
        self.controller_juju('revoke', args)
1845
1863
 
1883
1901
        controller_name = '{}_controller'.format(username)
1884
1902
 
1885
1903
        model = self.env.environment
1886
 
        token = self.add_user(username, models=model + ',controller',
 
1904
        token = self.add_user(username, models=model,
1887
1905
                              permissions=user.permissions)
1888
1906
        user_client = self.create_cloned_environment(juju_home,
1889
1907
                                                     controller_name,
1905
1923
        except pexpect.TIMEOUT:
1906
1924
            raise Exception(
1907
1925
                'Registering user failed: pexpect session timed out')
 
1926
        user_client.env.user_name = username
1908
1927
        return user_client
1909
1928
 
 
1929
    def remove_user(self, username):
 
1930
        self.juju('remove-user', (username, '-y'), include_e=False)
 
1931
 
1910
1932
    def create_cloned_environment(
1911
1933
            self, cloned_juju_home, controller_name, user_name=None):
1912
1934
        """Create a cloned environment.
1926
1948
        return user_client
1927
1949
 
1928
1950
    def grant(self, user_name, permission, model=None):
 
1951
        """Grant the user with model or controller permission."""
 
1952
        if permission in self.controller_permissions:
 
1953
            self.juju('grant', (user_name, permission),
 
1954
                      include_e=False)
 
1955
        elif permission in self.model_permissions:
 
1956
            if model is None:
 
1957
                model = self.model_name
 
1958
            self.juju('grant', (user_name, permission, model),
 
1959
                      include_e=False)
 
1960
        else:
 
1961
            raise
 
1962
 
 
1963
    def list_clouds(self, format='json'):
 
1964
        """List all the available clouds."""
 
1965
        return self.get_juju_output('list-clouds', '--format',
 
1966
                                    format, include_e=False)
 
1967
 
 
1968
    def show_controller(self, format='json'):
 
1969
        """Show controller's status."""
 
1970
        return self.get_juju_output('show-controller', '--format',
 
1971
                                    format, include_e=False)
 
1972
 
 
1973
    def ssh_keys(self, full=False):
 
1974
        """Give the ssh keys registered for the current model."""
 
1975
        args = []
 
1976
        if full:
 
1977
            args.append('--full')
 
1978
        return self.get_juju_output('ssh-keys', *args)
 
1979
 
 
1980
    def add_ssh_key(self, *keys):
 
1981
        """Add one or more ssh keys to the current model."""
 
1982
        return self.get_juju_output('add-ssh-key', *keys, merge_stderr=True)
 
1983
 
 
1984
    def remove_ssh_key(self, *keys):
 
1985
        """Remove one or more ssh keys from the current model."""
 
1986
        return self.get_juju_output('remove-ssh-key', *keys, merge_stderr=True)
 
1987
 
 
1988
    def import_ssh_key(self, *keys):
 
1989
        """Import ssh keys from one or more identities to the current model."""
 
1990
        return self.get_juju_output('import-ssh-key', *keys, merge_stderr=True)
 
1991
 
 
1992
 
 
1993
class EnvJujuClient2B9(EnvJujuClient):
 
1994
 
 
1995
    def update_user_name(self):
 
1996
        return
 
1997
 
 
1998
    def create_cloned_environment(
 
1999
            self, cloned_juju_home, controller_name, user_name=None):
 
2000
        """Create a cloned environment.
 
2001
 
 
2002
        `user_name` is unused in this version of beta.
 
2003
        """
 
2004
        user_client = self.clone(env=self.env.clone())
 
2005
        user_client.env.juju_home = cloned_juju_home
 
2006
        # New user names the controller.
 
2007
        user_client.env.controller = Controller(controller_name)
 
2008
        return user_client
 
2009
 
 
2010
    def get_model_uuid(self):
 
2011
        name = self.env.environment
 
2012
        output_yaml = self.get_juju_output('show-model', '--format', 'yaml')
 
2013
        output = yaml.safe_load(output_yaml)
 
2014
        return output[name]['model-uuid']
 
2015
 
 
2016
    def grant(self, user_name, permission, model=None):
1929
2017
        """Grant the user with a model."""
1930
2018
        if model is None:
1931
2019
            model = self.model_name
1932
2020
        self.juju('grant', (user_name, model, '--acl', permission),
1933
2021
                  include_e=False)
1934
2022
 
1935
 
 
1936
 
class EnvJujuClient2B9(EnvJujuClient):
1937
 
    def update_user_name(self):
1938
 
        return
1939
 
 
1940
 
    def create_cloned_environment(
1941
 
            self, cloned_juju_home, controller_name, user_name=None):
1942
 
        """Create a cloned environment.
1943
 
 
1944
 
        `user_name` is unused in this version of beta.
1945
 
 
1946
 
        """
1947
 
        user_client = self.clone(env=self.env.clone())
1948
 
        user_client.env.juju_home = cloned_juju_home
1949
 
        # New user names the controller.
1950
 
        user_client.env.controller = Controller(controller_name)
1951
 
        return user_client
 
2023
    def revoke(self, username, models=None, permissions='read'):
 
2024
        if models is None:
 
2025
            models = self.env.environment
 
2026
 
 
2027
        args = (username, models, '--acl', permissions)
 
2028
 
 
2029
        self.controller_juju('revoke', args)
1952
2030
 
1953
2031
 
1954
2032
class EnvJujuClient2B8(EnvJujuClient2B9):
2151
2229
        """List the models registered with the current controller."""
2152
2230
        log.info('The model is environment {}'.format(self.env.environment))
2153
2231
 
 
2232
    def list_clouds(self, format='json'):
 
2233
        """List all the available clouds."""
 
2234
        return {}
 
2235
 
 
2236
    def show_controller(self, format='json'):
 
2237
        """Show controller's status."""
 
2238
        return {}
 
2239
 
2154
2240
    def get_models(self):
2155
2241
        """return a models dict with a 'models': [] key-value pair."""
2156
2242
        return {}
2407
2493
                  (name, provider,
2408
2494
                   'size={}'.format(size)))
2409
2495
 
 
2496
    def ssh_keys(self, full=False):
 
2497
        """Give the ssh keys registered for the current model."""
 
2498
        args = []
 
2499
        if full:
 
2500
            args.append('--full')
 
2501
        return self.get_juju_output('authorized-keys', 'list', *args)
 
2502
 
 
2503
    def add_ssh_key(self, *keys):
 
2504
        """Add one or more ssh keys to the current model."""
 
2505
        return self.get_juju_output('authorized-keys', 'add', *keys,
 
2506
                                    merge_stderr=True)
 
2507
 
 
2508
    def remove_ssh_key(self, *keys):
 
2509
        """Remove one or more ssh keys from the current model."""
 
2510
        return self.get_juju_output('authorized-keys', 'delete', *keys,
 
2511
                                    merge_stderr=True)
 
2512
 
 
2513
    def import_ssh_key(self, *keys):
 
2514
        """Import ssh keys from one or more identities to the current model."""
 
2515
        return self.get_juju_output('authorized-keys', 'import', *keys,
 
2516
                                    merge_stderr=True)
 
2517
 
2410
2518
 
2411
2519
class EnvJujuClient22(EnvJujuClient1X):
2412
2520