def _rabbitmq_version_post_3_7(self, fail_on_error=False):
        """Use the JSON formatter to get a machine readable output of the version.

        At this point we do not know which RabbitMQ server version we are dealing with and which
        version of `rabbitmqctl` we are using, so we will try to use the JSON formatter and see
        what happens. In some versions of
        """
        def int_list_to_str(ints):
            return ''.join([chr(i) for i in ints])

        rc, output, err = self._exec(['status', '--formatter', 'json'], check_rc=False)
        if rc != 0:
            return self._fail(msg="Could not parse the version of the RabbitMQ server, "
                                  "because `rabbitmqctl status` returned no output.",
                              stop_execution=fail_on_error)
        try:
            status_json = json.loads(output)
            if 'rabbitmq_version' in status_json:
                return Version.StrictVersion(status_json['rabbitmq_version'])
            for application in status_json.get('running_applications', list()):
                if application[0] == 'rabbit':
                    if isinstance(application[1][0], int):
                        return Version.StrictVersion(int_list_to_str(application[2]))
                    else:
                        return Version.StrictVersion(application[1])
            return self._fail(msg="Could not find RabbitMQ version of `rabbitmqctl status` command.",
                              stop_execution=fail_on_error)
        except ValueError as e:
            return self._fail(msg="Could not parse output of `rabbitmqctl status` as JSON: {exc}.".format(exc=repr(e)),
                              stop_execution=fail_on_error)
 def _get_topic_permissions(self):
     """Get topic permissions of the user from RabbitMQ."""
     if self._version < Version.StrictVersion('3.7.0'):
         return dict()
     if self._version >= Version.StrictVersion('3.7.6'):
         permissions = json.loads(self._exec(['list_user_topic_permissions', self.username, '--formatter', 'json']))
     else:
         output = self._exec(['list_user_topic_permissions', self.username]).strip().split('\n')
         perms_out = [perm.split('\t') for perm in output if perm.strip()]
         permissions = list()
         for vhost, exchange, write, read in perms_out:
             permissions.append(dict(vhost=vhost, exchange=exchange, write=write, read=read))
     return as_topic_permission_dict(permissions)
    def get(self):
        """Retrieves the list of registered users from the node.

        If the user is already present, the node will also be queried for the user's permissions and topic
        permissions.
        If the version of the node is >= 3.7.6 the JSON formatter will be used, otherwise the plaintext will be
        parsed.
        """
        if self._version >= Version.StrictVersion('3.7.6'):
            users = dict([(user_entry['user'], user_entry['tags'])
                          for user_entry in json.loads(self._exec(['list_users', '--formatter', 'json']))])
        else:
            users = self._exec(['list_users'])

            def process_tags(tags):
                if not tags:
                    return list()
                return tags.replace('[', '').replace(']', '').replace(' ', '').strip('\t').split(',')

            users_and_tags = [user_entry.split('\t') for user_entry in users.strip().split('\n')]

            users = dict()
            for user_parts in users_and_tags:
                users[user_parts[0]] = process_tags(user_parts[1]) if len(user_parts) > 1 else []

        self.existing_tags = users.get(self.username, list())
        self.existing_permissions = self._get_permissions() if self.username in users else dict()
        self.existing_topic_permissions = self._get_topic_permissions() if self.username in users else dict()
        return self.username in users
    def _get_permissions(self):
        """Get permissions of the user from RabbitMQ."""
        if self._version >= Version.StrictVersion('3.7.6'):
            permissions = json.loads(self._exec(['list_user_permissions', self.username, '--formatter', 'json']))
        else:
            output = self._exec(['list_user_permissions', self.username]).strip().split('\n')
            perms_out = [perm.split('\t') for perm in output if perm.strip()]
            # Filter out headers from the output of the command in case they are still present
            perms_out = [perm for perm in perms_out if perm != ["vhost", "configure", "write", "read"]]

            permissions = list()
            for vhost, configure, write, read in perms_out:
                permissions.append(dict(vhost=vhost, configure=configure, write=write, read=read))

        if self.bulk_permissions:
            return as_permission_dict(permissions)
        else:
            return only(first(self.permissions.keys()), as_permission_dict(permissions))
    def _rabbitmq_version_pre_3_7(self, fail_on_error=False):
        """Get the version of the RabbitMQ Server.

        Before version 3.7.6 the `rabbitmqctl` utility did not support the
        `--formatter` flag, so the output has to be parsed using regular expressions.
        """
        version_reg_ex = r"{rabbit,\"RabbitMQ\",\"([0-9]+\.[0-9]+\.[0-9]+)\"}"
        rc, output, err = self._exec(['status'], check_rc=False)
        if rc != 0:
            if fail_on_error:
                self.module.fail_json(msg="Could not parse the version of the RabbitMQ server, because"
                                          " `rabbitmqctl status` returned no output.")
            else:
                return None
        reg_ex_res = re.search(version_reg_ex, output, re.IGNORECASE)
        if not reg_ex_res:
            return self._fail(msg="Could not parse the version of the RabbitMQ server from the output of "
                                  "`rabbitmqctl status` command: {output}.".format(output=output),
                              stop_execution=fail_on_error)
        try:
            return Version.StrictVersion(reg_ex_res.group(1))
        except ValueError as e:
            return self._fail(msg="Could not parse the version of the RabbitMQ server: {exc}.".format(exc=repr(e)),
                              stop_execution=fail_on_error)