This file is indexed.

/usr/share/pyshared/juju/control/utils.py is in juju-0.7 0.7-0ubuntu2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
import os
from itertools import tee

from twisted.internet.defer import inlineCallbacks, returnValue

from juju.environment.errors import EnvironmentsConfigError
from juju.state.errors import ServiceUnitStateMachineNotAssigned
from juju.state.environment import EnvironmentStateManager
from juju.state.machine import MachineStateManager
from juju.state.service import ServiceStateManager


def get_environment(options):
    env_name = options.environment or os.environ.get("JUJU_ENV")
    environment = options.environments.get(env_name)
    if environment is None and options.environment:
        raise EnvironmentsConfigError(
            "Invalid environment %r" % options.environment)
    elif environment is None:
        environment = options.environments.get_default()
    return environment


def sync_environment_state(client, config, name):
    """Push the local environment config to zookeeper.

    This needs to be done:

      * On any command which can cause the provisioning agent to take action
        against the provider (ie create/destroy a machine), because the PA
        needs to use credentials stored in the environment config to do so.
      * On any command which uses constraints-related code (even if indirectly)
        because Constraints objects are provider-specific, and need to be
        created with the help of a MachineProvider; and the only way state code
        can get a MachineProvider is by getting one from ZK (we certainly don't
        want to thread the relevant provider from juju.control and/or the PA
        itself all the way through the state code). So, we sync, to ensure
        that state code can use an EnvironmentStateManager to get a provider.
    """
    esm = EnvironmentStateManager(client)
    return esm.set_config_state(config, name)


@inlineCallbacks
def get_ip_address_for_machine(client, provider, machine_id):
    """Returns public DNS name and machine state for the machine id.

    :param client: a connected zookeeper client.
    :param provider: the `MachineProvider` in charge of the juju.
    :param machine_id: machine ID of the desired machine to connect to.
    :return: tuple of the DNS name and a `MachineState`.
    """
    manager = MachineStateManager(client)
    machine_state = yield manager.get_machine_state(machine_id)
    instance_id = yield machine_state.get_instance_id()
    provider_machine = yield provider.get_machine(instance_id)
    returnValue((provider_machine.dns_name, machine_state))


@inlineCallbacks
def get_ip_address_for_unit(client, provider, unit_name):
    """Returns public DNS name and unit state for the service unit.

    :param client: a connected zookeeper client.
    :param provider: the `MachineProvider` in charge of the juju.
    :param unit_name: service unit running on a machine to connect to.
    :return: tuple of the DNS name and a `MachineState`.
    :raises: :class:`juju.state.errors.ServiceUnitStateMachineNotAssigned`
    """
    manager = ServiceStateManager(client)
    service_unit = yield manager.get_unit_state(unit_name)
    machine_id = yield service_unit.get_assigned_machine_id()
    if machine_id is None:
        raise ServiceUnitStateMachineNotAssigned(unit_name)
    returnValue(
        ((yield service_unit.get_public_address()), service_unit))


def expand_path(p):
    return os.path.abspath(os.path.expanduser(p))


def expand_constraints(s):
    if s:
        return s.split(" ")
    return []


class ParseError(Exception):
    """Used to support returning custom parse errors in passthrough parsing.

    Enables similar support to what is seen in argparse, without using its
    internals.
    """


def parse_passthrough_args(args, flags_taking_arg=()):
    """Scans left to right, partitioning flags and positional args.

    :param args: Unparsed args from argparse
    :param flags_taking_arg: One character flags that combine
       with arguments.
    :return: tuple of flags and positional args
    :raises: :class:`juju.control.utils.ParseError`

    TODO May need to support long options for other passthrough commands.
    """
    args = iter(args)
    flags_taking_arg = set(flags_taking_arg)
    flags = []
    positional = []
    while True:
        args, peek_args = tee(args)
        try:
            peeked = peek_args.next()
        except StopIteration:
            break
        if peeked.startswith("-"):
            flags.append(args.next())
            # Only need to consume the next arg if the flag both takes
            # an arg (say -L) and then it has an extra arg following
            # (8080:localhost:80), rather than being combined, such as
            # -L8080:localhost:80
            if len(peeked) == 2 and peeked[1] in flags_taking_arg:
                try:
                    flags.append(args.next())
                except StopIteration:
                    raise ParseError(
                        "argument -%s: expected one argument" % peeked[1])
        else:
            # At this point no more flags for the command itself (more
            # can follow after the first positional arg, as seen in
            # working with ssh, for example), so consume the rest and
            # stop parsing options
            positional = list(args)
            break
    return flags, positional